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

[JS] childnodes on the fly ID geven en functie onmouseover

Pagina: 1
Acties:

  • ? ?
  • Registratie: Mei 2007
  • Niet online
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//in een functie tijdens het laden van de pagina
for (i=0;i<navRoot.childNodes.length;i++)
{
        node = navRoot.childNodes[i];
        if (node.nodeName == "IMG")
        {
                var d = 'pic' + i;
                node.setAttribute('id', d);
                node.onmouseover = function(){zoomIn(d);}
                node.onmouseout = function(){zoomOut(d);}
        }
}

//img vergroten
function zoomIn(p)
{
        if(document.getElementById(p).height < HEIGHT_BIG)
        {
                document.getElementById(p).height++;
                setTimeout("zoomIn('" + p + "')", 10);
        }
}


Situatie: een DIV met IMG elementen in zonder een ID.
Tijdens de load, wordt een IDs ("pic1" bv) toegekend aan de IMG elementen. Er wordt ook een mouseover event toegevoegd en daarin wordt het ID meegegeven.

Echter, bij een mouseover op bv. de eerste IMG met ID "pic0" is het argument p van zoomIn() steeds het laatst toegekende ID: "pic3" bv. als er 4 IMG elementen zijn...

Kan ik een argument meegeven bij het toevoegen van een onmouseover event? Blijkbaar wel, maar waarom wordt dan het laatste ID altijd meegegeven? Of zit er ergens een foutje in..

[ Voor 7% gewijzigd door ? ? op 02-04-2008 15:53 ]


  • user109731
  • Registratie: Maart 2004
  • Niet online
Blijkbaar wel, maar waarom wordt dan het laatste ID altijd meegegeven?
Omdat er afaik geen kopie van d maar een referentie naar d word gebruikt. Zo kun je een kopie van d maken zodat het wel goed gaat:

JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
function createFunction(value) {
    return function() { zoomIn(value); }
}
for (i=0;i<navRoot.childNodes.length;i++)
{
        node = navRoot.childNodes[i];
        if (node.nodeName == "IMG") 
        {
            var d = 'pic' + i;
            node.setAttribute('id', d);
            node.onmouseover = createFunction(d);
        }
}

[ Voor 22% gewijzigd door user109731 op 02-04-2008 16:21 ]


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Waarom zou je op zo'n omslachtige manier met ID's willen werken als de eventhandler toch al in de scope van het element zelf wordt uitgevoerd (hint: 'this')?

Intentionally left blank


  • ? ?
  • Registratie: Mei 2007
  • Niet online
dank je JanDM !

@crisp: een this referentie kun je niet meegeven met een setTimeout (?), lukte mij toch niet

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 20:17
Daar heb je geen ids voor nodig Je kunt in je zoomIn functie gewoon uit de event properties uitlezen over welk plaatje is gehovered. Zoiets:
JavaScript:
1
2
3
4
5
6
7
8
9
function zoomIn(e) {
  if (!e) var e = window.event;
  img = (e.srcElement) ? e.srcElement : e.target;

  var numSteps = HEIGHT_BIG - img.height;
  for(var i = 1; i<=numSteps; i++) {
    window.setTimeOut(function() { img.height = img.height+1;}, i*10; });
  }
}

[ Voor 1% gewijzigd door T-MOB op 02-04-2008 16:36 . Reden: highlighting! (en gepruts ;) ]

Regeren is vooruitschuiven


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Een reeks timeouts is niet echt verstandig, er is geen garantie dat ze in volgorde worden uitgevoerd.

Scope in de timeout is op te lossen mbv een anonymous functie en call/apply

Intentionally left blank


Verwijderd

era.zer schreef op woensdag 02 april 2008 @ 15:47:
Kan ik een argument meegeven bij het toevoegen van een onmouseover event? Blijkbaar wel, maar waarom wordt dan het laatste ID altijd meegegeven? Of zit er ergens een foutje in..
Je definieert in een for-loop een (anonieme) functie. In JavaScript krijgen functies pas variable-scope tijdens "execution time", als de functie wordt uitgevoerd. In dit geval is het een event-handler en is de originele for-loop al lang en breed afgelopen als de functie wordt uitgevoerd. De variabele d heeft dan (nog steeds) de waarde die het kreeg tijdens de laatste iteratie van de loop.

Dit is wel op te lossen maar je kunt beter de adviezen opvolgen van mijn voorgangers in deze thread. :)

  • ? ?
  • Registratie: Mei 2007
  • Niet online
Het loopt in de soep en ik denk dat het niet direct op te lossen is, zoveel theorie van javascript ken ik niet, maar als plaatje 1 een hover doet en dan out, vervolgens over plaatje 1 een hover:
dan gaat de settimeout misschien nog af voor plaatje1, omdat die gescheduled was.

Het werkt dus als je niet te vlug van de ene image naar de andere gaat, maar da's niet de bedoeling..

Je kan een global var current_img gaan bijhouden en assignen in zoomIn(), maar als de zoomIn() van plaatje 1 nog eens afgaat, zoals hierboven zit je nog met de vorige enz.

Ik ga één functie maken met een timeout die om de x tijd gewoon kijkt welk img-element laatst gehovered werd, en dan de images gaat verkleinen/vergroten. Denk dat zoiets een goeie oplossing is?

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Ik heb wel een opzetje voor je, kijk eens of je dit begrijpt:
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
<!doctype html>
<html>
<head>
<script type="text/javascript">

var HEIGHT_BIG = 30;
var HEIGHT_SMALL = 15;

function zoomIn()
{
    this.zoomState = 1;
    zoom.call(this, 1);
}

function zoomOut()
{
    this.zoomState = -1;
    zoom.call(this, -1);
}

function zoom(i)
{
    if (this.zoomState == i)
    {
        this.height += this.zoomState;
        if (    (this.zoomState > 0 && this.height < HEIGHT_BIG) ||
            (this.zoomState < 0 && this.height > HEIGHT_SMALL)
        )
        {
            var self = this;
            setTimeout(function() { zoom.call(self, i); }, 10);
        }
    }
}

window.onload = function()
{
    var images = document.getElementsByTagName('img'), i = 0, img;
    while ((img = images[i++]))
    {
        img.onmouseover = zoomIn;
        img.onmouseout = zoomOut;
    }
}

</script>
<body>
<img src="http://gathering.tweakers.net/global/smileys/smile.gif">
<img src="http://gathering.tweakers.net/global/smileys/smile.gif">
<img src="http://gathering.tweakers.net/global/smileys/smile.gif">

:)

Intentionally left blank


  • ? ?
  • Registratie: Mei 2007
  • Niet online
Is dat nette code! d:)b

Dat snap ik, maar zelf was ik daar niet op gekomen. Mijn "this" idee klopte ook niet, this in zoomIn bv. is het image object (en niet zoals ik zat te denken gewoon die functie -idioot), ik zou eens een boekje moeten lezen..

als je de timeout bij het uitzoomen 10x groter maakt krijg je een mooi effectje!

[ Voor 15% gewijzigd door ? ? op 03-04-2008 09:34 ]


  • torp
  • Registratie: Januari 2001
  • Laatst online: 14-11 13:07
Ik heb hier een tijd naar gekeken en ik snap het helemaal behalve deze regel:
HTML:
1
2
3
<script type="text/javascript">
    var images = document.getElementsByTagName('img'), i = 0, img;
</script>

Wat gebeurt hier? Hoe werken die komma's?

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 20:17
Daar worden variabelen geinitialiseerd, alleen op een regel. Het is equivalent aan:
JavaScript:
1
2
3
 var images = document.getElementsByTagName('img');
 var i = 0;
 var img;

Dat declareren is belangrijk omdat er anders eerst in de omliggende scope wordt gekeken naar een variabele met die naam. Is die aanwezig dan wordt die gebruikt.
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
var a = 'global';
var b = 'global';

function test() {
  var a;
  a = 'local';
  b = 'local';
}

test();
alert('a:' + a); //->global
alert('b:' + b); //->local

Regeren is vooruitschuiven


  • torp
  • Registratie: Januari 2001
  • Laatst online: 14-11 13:07
Daar worden variabelen geinitialiseerd, alleen op een regel.
Oh, zo simpel... wat dom dat ik dat niet zag, net als in PHP...

[ Voor 24% gewijzigd door torp op 04-04-2008 02:00 ]

Pagina: 1