[JS]probleem met setTimeout en clearTimeout

Pagina: 1
Acties:
  • 147 views sinds 30-01-2008
  • Reageer

  • Dr_Frickin_Evil
  • Registratie: Mei 2000
  • Laatst online: 26-05 16:31
Ik heb een menuutje:
code:
1
2
3
4
5
6
7
8
9
10
11
12
        <ul>
            <li onmouseover="hideLayers();">Home</li>
            <li onmouseover="hideLayers();">News &amp; Tours</li>
            <li onmouseover="hideLayers();showLayer('no1');cleartimer('timeout1')"
            onmouseout="timeout('no1','timeout1');">Guestbook</li>
                <ul id="no1" onmouseover="cleartimer('timeout1');"
            onmouseout="timeout('no1','timeout1')">
                    <li>Lezen</li>
                    <li>Reactie plaatsen</li>
                </ul>
            </li>
        </ul>


de javascript code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
var timer = new Array();
var submenu = new Array();

function cleartimer(which) {
    if (timer[which]) 
        {
        clearTimeout(timer[which]);
        timer[which] = null;
        }
    }

function timeout(layername,which) {
    timer[which] = window.setTimeout('hideLayer(\''+layername+'\')', 1000);
    }

function hideLayers() {
    for (i = 0; i <= submenu.length-1; i++) {
        layer = document.getElementById(submenu[i]);
        layer.style.display = 'none';
        }
    }

function hideLayer(layer) {
document.getElementById(layer).style.display = 'none'
    }

function showLayer(layer) {
    submenu[submenu.length] = layer;
    layer = document.getElementById(layer);
    layer.style.display = 'block';
    }

(overigens moet ik nog ff naar die showLayer-functie kijken, hij moet eerst controleren of die layernaam niet al in het array staat, zoja dan moet ie hem natuurlijk niet toevoegen, maar dat is het probleem nu niet)

Het menu werkt in mozilla prima. In IE werkt het niet goed. Ik heb het idee alsof IE het event dat je de muis van de <ul> naar de <li> van het submenu ook als een onmouseout beschouwd. Het probleem is namelijk, dat hij het menuutje toch afsluit , maw de cleartimer wordt niet (goed) aangeroepen. Wat kan het probleem zijn? De javascript code is in principe gewoon goed, die gebruik ik op een andere pagina ook.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

ook hier weer: eventbubbling. Bouw een check in welk element het event getriggered heeft.

Intentionally left blank


  • Dr_Frickin_Evil
  • Registratie: Mei 2000
  • Laatst online: 26-05 16:31
Hmm wat bedoel je precies? Ik moet javascript laten weergeven door welk element de functies zijn aangeroepen? Kun je een voorbeeldje geven?

Hier kan ik me echt mateloos aan ergereren he, meer als de helft van de tijd ben je bezig met het debuggen van fouten, die vaak niet eens echt aan jezelf liggen...

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 10-05 18:53

Bosmonster

*zucht*

Dr_Frickin_Evil schreef op 03 april 2004 @ 00:17:
Hmm wat bedoel je precies? Ik moet javascript laten weergeven door welk element de functies zijn aangeroepen? Kun je een voorbeeldje geven?

Hier kan ik me echt mateloos aan ergereren he, meer als de helft van de tijd ben je bezig met het debuggen van fouten, die vaak niet eens echt aan jezelf liggen...
Waar zouden bugs in jouw code anders aan liggen dan aan jezelf :?

Het lijkt me vrij logisch dat als je twee geneste elementen hebt met mouseovers/etc dat die events elkaar gaan overlappen. Dit is eventbubbling. Je zult dus beter moeten kijken naar welk element het event opgeroepen heeft en eventueel het event cancellen voor bovenliggende elementen.

  • Dr_Frickin_Evil
  • Registratie: Mei 2000
  • Laatst online: 26-05 16:31
Bosmonster schreef op 03 april 2004 @ 00:31:
[...]


Waar zouden bugs in jouw code anders aan liggen dan aan jezelf :?

Het lijkt me vrij logisch dat als je twee geneste elementen hebt met mouseovers/etc dat die events elkaar gaan overlappen. Dit is eventbubbling. Je zult dus beter moeten kijken naar welk element het event opgeroepen heeft en eventueel het event cancellen voor bovenliggende elementen.
Aangezien het in Mozilla prima werkt, en in Internet Explorer niet, gaat het dus om een interpretatieverschil tussen die 2. Noem het voorbarig, maar dan ga ik er vanuit dat Mozilla het bij het rechte eind heeft, en dat het dus een bug van IE is. Ik vind het zelf sowieso raar, dat als ik een onmouse event op een ul-element plaats, dat ie dan ook reageert als ik van dat element naar een li-element ga. Als ik een background color op de ul plaats, dan is ie toch ook gekleurd over z'n hele oppervlak, dus ook over z'n li's?

Maargoed, het eventbubbling zal ik eens naar zoeken, ik snap nog niet helemaal wat dat inhoudt.

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 22-03 18:12
[mierenneuk]
Dr_Frickin_Evil schreef op 02 april 2004 @ 20:53:
code:
1
    for (i = 0; i <= submenu.length-1; i++) {
=>
code:
1
    for (i = 0; i < submenu.length; i++) {


[/mierenneuk]

:P

Noushka's Magnificent Dream | Unity


  • Dr_Frickin_Evil
  • Registratie: Mei 2000
  • Laatst online: 26-05 16:31
Crisp, dit lees ik in een andere thread:
crisp schreef op 25 oktober 2003 @ 22:10:
dat heeft te maken met eventBubbling; een mouseout op een hoger gelegen element bubbled door naar ondergelegen elementen. In dit geval ga je in je menu over een li-element, dat triggered een mouseout op de li, die doorbubbled naar je ondergelegen element en daar ook de onmouseout triggered. Wat je kan doen is checken of het target element (of srcElement in IE) van je event wel je menu zelf is, of je list-item in dat menu :)
In mijn geval zal ik dus moeten controleren of het event is getriggered door ofwel een li in een ul met class mainmenu, ofwel door een ul met class submenu? Zal eens kijken, das natuurlijk niet zo moeilijk te controleren.

  • Dr_Frickin_Evil
  • Registratie: Mei 2000
  • Laatst online: 26-05 16:31
Het werkt, heb nu dit:

code:
1
2
3
4
5
6
7
8
function timeout(layername,which,evt) {
    evt = (evt) ? evt : ((window.event) ? event : null);
    if (evt.stopPropagation)
        evt.stopPropagation();// DOM Level 2
    else 
        evt.cancelBubble = true;// IE
    timer[which] = window.setTimeout('hideLayer(\''+layername+'\')', 1000);
    }

[ Voor 66% gewijzigd door Dr_Frickin_Evil op 03-04-2004 19:10 ]


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Ik heb hier vandaag ook eens mijn gedachten over laten gaan, en geprobeerd om vanuit een cleane multiple list met zo min mogelijk code een mooi uitklap menu te maken. Dit is wat ik bedacht heb:

we beginnen met een list zonder poespas:

HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<ul id="menu">
    <li>
        <a href="#">item 1</a>
        <ul>
            <li>
                <a href="#">item 1.1</a>
                <ul>
                    <li><a href="#">item 1.1.1</a></li>
                    <li><a href="#">item 1.1.2</a></li>
                    <li><a href="#">item 1.1.3</a></li>
                </ul>
            </li>
            <li>
                <a href="#">item 1.2</a>
                <ul>
                    <li><a href="#">item 1.2.1</a></li>
                    <li><a href="#">item 1.2.2</a></li>
                    <li><a href="#">item 1.2.3</a></li>
                </ul>
            </li>
            <li>
                <a href="#">item 1.3</a>
                <ul>
                    <li><a href="#">item 1.3.1</a></li>
                    <li><a href="#">item 1.3.2</a></li>
                    <li><a href="#">item 1.3.3</a></li>
                </ul>
            </li>
        </ul>
    </li>
    <li>
        <a href="#">item 2</a>
        <ul>
            <li>
                <a href="#">item 2.1</a>
                <ul>
                    <li><a href="#">item 2.1.1</a></li>
                    <li><a href="#">item 2.1.2</a></li>
                    <li><a href="#">item 2.1.3</a></li>
                </ul>
            </li>
            <li>
                <a href="#">item 2.2</a>
                <ul>
                    <li><a href="#">item 2.2.1</a></li>
                    <li><a href="#">item 2.2.2</a></li>
                    <li><a href="#">item 2.2.3</a></li>
                </ul>
            </li>
            <li>
                <a href="#">item 2.3</a>
                <ul>
                    <li><a href="#">item 2.3.1</a></li>
                    <li><a href="#">item 2.3.2</a></li>
                    <li><a href="#">item 2.3.3</a></li>
                </ul>
            </li>
        </ul>
    </li>
</ul>


even mooi stylen. Frappant is dat eigenlijk alleen Opera dit 100% goed doet, zo zie je maar dat de meeste browsers toch nog behoorlijk buggy zijn als het aankomt op CSS2 support:

Cascading Stylesheet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
ul#menu, ul#menu ul {
    margin: 0px;
    padding: 0px;
    border: 1px solid black;
    border-bottom-width: 0px;
    width: 120px;
    background-color: #808080;
    line-height: 0px;
}
ul#menu li {
    position: relative;
    list-style-type: none;
}
ul#menu li a {
    display: block;
    padding: 0px 4px;
    color: white;
    font-family: arial, tahoma, helvetica, sans-serif;
    font-size: 13px;
    font-weight: bold;
    text-decoration: none;
    border-bottom: 1px solid black;
    height: 20px;
    line-height: 20px;
}
ul#menu li a:hover {
    background-color: #0000ff;
}
ul#menu li ul {
    position: absolute;
    display: none;
    top: 2px;
    left: 100px;
}


nu moeten we nog wat events gaan toekennen; dat doe ik middels de volgende code:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
window.onload = init_menu;

function init_menu() {

    var menu = document.getElementById('menu');
    var li = menu.getElementsByTagName('LI'), i = li.length;
    while (i--) li.item(i).onmouseover = showMenu;
    menu.onmouseout = timeout;
    menu.onmouseover = cleartimer;

}

var timer = null;
function timeout() {

    timer = setTimeout('hideMenus(document.getElementById(\'menu\'), null)', 1000);

}

function cleartimer() {

    if (timer != null) clearTimeout(timer);
    timer = null;

}

function showMenu() {

    hideMenus(this.parentNode, this);

    var el = this.firstChild;
    while (el != null && (el.nodeType != 1 || el.tagName != 'UL')) el = el.nextSibling;

    if (el != null) el.style.display = 'block';

}

function hideMenus(level, skipli) {

    var stack = [level], i = 1, li, j, el;
    while (i--) {
        li = stack[i].childNodes, j = li.length;
        while (j--) {
            el = li.item(j);
            if (el != null && el != skipli && (el.tagName == 'UL' || el.tagName == 'LI')) {
                stack[i++] = el;
                if (el.tagName == 'UL') el.style.display = 'none';
            }
        }
    }

}


Je ziet dat eigenlijk alleen op de mouseout van de 1e ul een timer noodzakelijk is, voor de rest kunnen we alles regelen middels mouseovers op de li's :)

online voorbeeld

[ Voor 6% gewijzigd door crisp op 04-04-2004 12:30 ]

Intentionally left blank


  • Dr_Frickin_Evil
  • Registratie: Mei 2000
  • Laatst online: 26-05 16:31
Mooi menuutje. Werkt goed.

Ik heb nu echt een probleempje met de height/line-height van de anchors. Ik wil ze dicht op elkaar plaatsen, maar IE wil niet onder een height van zo'n 15px :? Hij lijkt ook een margin aan te houden die toch echt op 0px staat. Ik snap er weer niet veel van.

Het staat hier online: http://131.155.241.103/lttnew

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Ik merkte het zelf al op, IE (en Mozilla ook in mindere mate) is nog verre van perfect als het gaat om het stylen van lists. Het zetten van een height op de li zelf geeft zelfs nog vreemdere effecten. Het blijft dus een beetje puzzelen ben ik bang...

Intentionally left blank


  • Dr_Frickin_Evil
  • Registratie: Mei 2000
  • Laatst online: 26-05 16:31
Het is wel echt frusterend. In dit geval is het niet bijzonder storend, maar ik wil het gewoon mooi hetzelfde hebben. Ff verder prutsen danmaar.... :(
Pagina: 1