Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[JS] Mouse onclick event properties doorgeven

Pagina: 1
Acties:

  • OkkE
  • Registratie: Oktober 2000
  • Laatst online: 10-11 15:46

OkkE

CSS influencer :+

Topicstarter
Hey Tweakers,

De titel zal wat vaag zijn, maar ik weet niet precies hoe ik dit het beste kan omschrijven.

Ik heb de volgende functies:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
function addBlockToggle(classname) {
    var blocks = getElementsByClassName(classname);
    for (var i=0; i<blocks.length; i++) {
        var elmId = blocks[i].id;
        // passing blocks[i].id direct results in: ERR blocks[i] has no properties
        addEventHandler(blocks[i], 'click', function(e){toggleBlock(elmId)});
    }
}

function toggleBlock(id) {
    // testing...
    alert('toggle: '+id);
}


Het probleem hier bij is dat als ik op een element klik altijd het ID van het laatste element ge-alert wordt, ipv het ID van het block waar ik op klik.
Ik ging er van uit dat elmId als een string gebruikt werd, op de zelfde manier als wanneer je dit inline doet. Maar het lijkt toch een referentie te zijn, of iets?

Dit dacht ik op te lossen door het zo te doen:
JavaScript:
1
addEventHandler(blocks[i], 'click', toggleBlock);


en dan de alert zo:
JavaScript:
1
2
3
4
function toggleBlock(id) {
    var id = this.id;
    alert('toggle: '+id);
}

Maar dat werkt niet in Explorer.
Ooit had ik een zelfde probleem, maar dan met een onMouseOver, daar heb ik het toen opgelost door de volgende functie:
JavaScript:
1
2
3
4
5
6
7
8
function toggleBlock(e) {
    var id = this.id;
    if (!id) {
        elm = e.relatedTarget || e.toElement;
        id = elm.id;
    }
    alert('toggle: '+id);
}

Maar dit schijnt weer niet te werken voor onClick events, want dan bestaat er geen e.toElement of e.relatedTarget. Ze alerten iig "null".

Kan iemand me uitleggen waar het mis gaat, en hoe ik dit op zou kunnen lossen? Of ben ik toch genoodzaakt d.m.v. een extra mouseover/mouseout event het huidige ID te bewaren in bijv. een hidden input?

“The best way to get the right answer on the Internet is not to ask a question, it's to post the wrong answer.”
QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers.


Verwijderd

OkkE schreef op maandag 17 maart 2008 @ 13:32:
Het probleem hier bij is dat als ik op een element klik altijd het ID van het laatste element ge-alert wordt, ipv het ID van het block waar ik op klik.
Ik ging er van uit dat elmId als een string gebruikt werd, op de zelfde manier als wanneer je dit inline doet. Maar het lijkt toch een referentie te zijn, of iets?
Dit is een scoping issue. Je definieert een anonymous function en je gebruikt daarin een variabele elmId die daarbuiten (in de for-loop) is gedefinieerd. Probleem is dat deze variabele pas wordt gescoped als de functie wordt uitgevoerd (dus niet bij de definitie). Tegen die tijd is de for-loop allang afgelopen en heeft deze variabele dus altijd de laatste waarde gekregen.

Zie http://www.mennovanslooten.nl/blog/post/62 voor iets meer info hierover.

Een oplossing is een functie uitvoeren in de for-loop om zo de variabele bijtijds te scopen:

JavaScript:
1
2
3
4
5
6
7
8
9
10
function addBlockToggle(classname) {
    var blocks = getElementsByClassName(classname);
    for (var i=0; i<blocks.length; i++) {
        var elmId = blocks[i].id;
        function(elementId) {
            addEventHandler(blocks[i], 'click', function(e){toggleBlock(elementId)});
        }(elmId);
    }
}    
    

Maar dat is hier niet de beste oplossing, denk ik. Een block zou zichzelf prima moeten kunnen togglen zonder deze vage shit. Kijk anders eens bij quirksmode voor e.target en e.srcElement.

  • OkkE
  • Registratie: Oktober 2000
  • Laatst online: 10-11 15:46

OkkE

CSS influencer :+

Topicstarter
Bedankt voor je antwoord.

Ik was er ondertussen inderdaad achter dat het om een scoop-probleem ging, alleen hoe ik het moest oplossen was me nog even onduidelijk.

Het stukje code dat je poste werkt niet gelijk knippen/plakken, maar wanneer ik het zoals op je blog doe, werkt het wel. Zo dus:
JavaScript:
1
2
3
4
5
blocks[i].onclick = function(value) {
    return function() {
        toggleBlock(value);
    }
}(elmId);


De oplossing met e.target en e.srcElement, zoals op Quirksmode, werkt wel wanneer je op de DIV zelf klikt, alleen staan er ook links in die DIV, en dan werkt het niet - die geven niet het ID van de parent terug.

Het hele idee is eigenlijk als volgt:

code:
1
2
3
4
5
6
7
<div>
    <h2><a href="/page.htm">Some title</a></h2>
    <p>Random text</p>
    <div>
        <p>Extra information, links etc.</p>
    </div>
</div>

Wanneer op de DIV (of H2, of A) geklikt wordt, is het de bedoeling dat de binnenste DIV zichtbaar wordt. Mijn idee was om dat te doen door de buitenste DIV een class "closed" mee te geven, en deze via een onClick te vervangen in de class "open".

“The best way to get the right answer on the Internet is not to ask a question, it's to post the wrong answer.”
QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers.


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

this.id zou nogthans gewoon moeten werken, maar ik gok zo dat addEventHandler() bij jou een wrapper is die voor IE attachEvent gebruikt, en de juiste scope is net een van de grootste manco's aan IE's brakke event-model...

Meer info in bijvoorbeeld dit recente topic: [JS] AddEvent, wat is de perfecte cross-browser oplossing?

Intentionally left blank


  • OkkE
  • Registratie: Oktober 2000
  • Laatst online: 10-11 15:46

OkkE

CSS influencer :+

Topicstarter
De addEventHandler is inderdaad een wrapper die in IE de attachEvent gebruikt, het is het script van PPK. Maar bedankt voor de link, interressant topic over die AddEvent, zal 'm zeker nog eens doorlezen.

“The best way to get the right answer on the Internet is not to ask a question, it's to post the wrong answer.”
QA Engineer walks into a bar. Orders a beer. Orders 0 beers. Orders 999999999 beers. Orders a lizard. Orders -1 beers.