[jQuery] Event wordt twee keer gefired?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • mcdronkz
  • Registratie: Oktober 2003
  • Laatst online: 16-04 12:44
Raar probleem.

Ik heb een soort van Lightbox gemaakt, waarmee ik een reeks afbeeldingen kan laten zien.

Als ik m'n imageviewer voor de eerste keer open is er niks aan de hand. Ik kan gewoon het volgende of vorige plaatje kiezen, het "click"-event wordt dan maar één keer gefired.

Als ik de imageviewer laat sluiten met HideImageViewer() en vervolgens weer open gebeurt er ineens iets raars. Als ik op "volgende" of "vorige" druk wordt het "click"-event twee keer gefired!

Je zou zeggen dat er iets mis gaat bij HideImageViewer(), maar het is mij een raadsel. Ik heb al veel dingen getest om steeds maar uit te sluiten, ik heb gedebugged, op de vreemdste plaatsen een alert() gezet, maar ik ben de draad nu echt kwijt.

Dit zijn de functies:

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
function HideImageViewer()
{
    $(document).ready(function()
    {
        $("#imageviewer .image img").attr("src", null);
        $("#imageviewer .title img").attr("src", null);
        $("#imageviewer").css("display", "none");
    });
}

function ShowImageSequence(sequence)
{
    $(document).ready(function(){
        /*
        Lees het XML bestand in
        */
        $.get("/" + sequence + ".xml", function(xml){ 
            /*
            Loop door het XML bestand heen.
            */
            $i = 1;
            var images = new Array();
            $(xml).find("image").each(function(){       
                images[$i] = Array($(this).find("URL").text(), $(this).find("title").text());
                $i++;
            });

            $("#imageviewer").css("display", "block"); 
            $("#imageviewer .navigation").css("display", "block"); 
            
            /*
            Zorg dat bij het laden de eerste afbeelding getoond wordt.
            */
            $currentImage = 1;
            $imageCount = $(xml).find("image").length;
            
            $("#imageviewer .image img").attr("src", images[$currentImage][0]);
            $("#imageviewer .title img").attr("src", "textimage.html?text=" + images[$currentImage][1]);
                                    
            $("#imageviewer .previous").click(function()
            {
                /*
                Er drukt iemand op "vorige".
                */
                if(($currentImage - 1) > 0)
                {
                    $currentImage--;
                }
                
                $("#imageviewer .image img").attr("src", images[$currentImage][0]);
                $("#imageviewer .title img").attr("src", "textimage.html?text=" + images[$currentImage][1]);
            });
            
            $("#imageviewer .next").click(function()
            {
                /*
                Er drukt iemand op "volgende".
                */
                if(($currentImage + 1) <= $imageCount)
                { 
                    $currentImage++;
                }
                                
                $("#imageviewer .image img").attr("src", images[$currentImage][0]);
                $("#imageviewer .title img").attr("src", "textimage.html?text=" + images[$currentImage][1]);
            });
        });
    });
}


Allemaal heel basic zoals je ziet.

Hier de relevante HTML code:

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
            <div id="imageviewer">
                <img src="images/imageviewer_border.png" class="border" />

                <div class="image">         
                    <img src="images/blank.png" />
                </div>
                
                <div class="title">
                    <img src="images/blank.png" />
                </div>
                
                <div class="overlay">
                    &nbsp;
                </div>
                
                <div class="navigation">
                    <div class="close">
                        <img src="/images/close.png" onClick="HideImageViewer();" />
                    </div>

                    <div class="previous">
                        <img src="/images/previous.png" />
                    </div>
                    
                    <div class="next">
                        <img src="/images/next.png" />
                    </div>
                </div>
            </div>


Het kan vast allemaal veel mooier/correct (alt attributes bijvoorbeeld) maar dat lijkt me niet de oorzaak van mijn probleem.

Het event wordt dus echt twee keer gefired.

Zie ik iets enorm over het hoofd, wie kan me vertellen wat hier mis gaat?

Acties:
  • 0 Henk 'm!

  • Erik Jan
  • Registratie: Juni 1999
  • Niet online

Erik Jan

Langzaam en zeker

Als ik jou was zou ik morgen verder gaan want je voegt steeds al je code toe aan het onReady event van je document.

This can no longer be ignored.


Acties:
  • 0 Henk 'm!

  • mcdronkz
  • Registratie: Oktober 2003
  • Laatst online: 16-04 12:44
Erik Jan schreef op vrijdag 31 juli 2009 @ 02:47:
Als ik jou was zou ik morgen verder gaan want je voegt steeds al je code toe aan het onReady event van je document.
Oké, maar wat voor effect zou dat moeten hebben op de werking dan?

Zonder het onReady event functioneert 'ie namelijk precies net zo goed, of net zo waardeloos zoals je in dit geval beter kunt zeggen.

[ Voor 18% gewijzigd door mcdronkz op 31-07-2009 03:35 ]


Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 18-09 16:28

Bosmonster

*zucht*

Logisch toch? Iedere keer als je je lightbox opent voeg je opnieuw die click event toe...

Daarnaast is het wel jammer dat je het via doe XML oplost, wat natuurlijk verre van unobtrusive is.

edit:

Die documentready zie ik nu pas.. die slaat natuurlijk helemaal nergens op zoals je die nu geimplementeerd hebt...

Als laatste:
Duik eens in de plugins en hoe je deze moet bouwen. De beste manier om dit in jQuery op te lossen is door er een plugin van te maken.

[ Voor 82% gewijzigd door Bosmonster op 31-07-2009 09:53 ]


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Erik Jan schreef op vrijdag 31 juli 2009 @ 02:47:
Als ik jou was zou ik morgen verder gaan want je voegt steeds al je code toe aan het onReady event van je document.
Da's niet het enige wat aan die code gaar is:

JavaScript:
1
2
$currentImage = 1;
$imageCount = $(xml).find("image").length; 


Die variabelen zijn niet gedefinieerd met behulp van het var keyword. Een assignment aan een ongedefinieerde variable betekent in JavaScript dat die variable impliciet gedeclareerd wordt. Impliciete declaratie vindt echter altijd plaats op het niveau van de global scope!

Dit scriptje gaat dus gigantisch op z'n bek zodra je het 2 of meer keer per pagina instantieert, want beide instanties zullen van dezelfde (globale) variable gebruik maken.


[EDIT]
Goed, ik was in een goede bui en ik had eventjes een paar minuten over.

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Anonieme namespace om component te black-boxen.
(function($){

$.fn.extend({
    imageViewer: function(sequence){
        var self = this;
        
        // Viewer reeds geinstantieerd op deze node...
        if ($(self).data("imageviewer") === "imageviewer") return;
        
        $(self).data("imageviewer", "imageviewer");
        
        $.get("/" + sequence + ".xml", function(xml){ 
            /*
            Loop door het XML bestand heen.
            */
            var images = [];
            $(xml).find("image").each(function(){          
                images.push_back({
                    url: $(this).find("URL").text(),
                    title: $(this).find("title").text()
                });             
            });

            $(self).css("display", "block"); 
            $(".navigation", self).css("display", "block"); 
            

            /*
            Zorg dat bij het laden de eerste afbeelding getoond wordt.
            */
            var currentImage = 0;           
            
            function loadImage()
            {
                $(".image img", self).attr("src", images[currentImage].url);
                $(".title img", self).attr("src",
                    "textimage.html?text=" + images[currentImage].title
                );
            }

            /*
            Er drukt iemand op "vorige".
            */
            $(".previous", self).bind("click.imageviewer", function(){          
                currentImage = Math.max(--currentImage, 0);                     
                loadImage();
            });
            

            /*
            Er drukt iemand op "volgende".
            */
            $(".next", self).bind("click.imageviewer", function(){
                currentImage = Math.min(++currentImage, images.length-1);                               
                loadImage();
            });
            
            /*
            Er druk iemand op "sluiten"
            */
            $(".close", self).bind("click.imageviewer", function(){
                $(self).unbind(".imageviewer");
                $(".image img", self).removeAttr("src");
                $(".title img", self).removeAttr("src");
                $(self).css("display", "none");
                
                $(self).removeData("imageviewer");
            });
        });
    }
});

})(jQuery);

$(document).ready(function(){
    $("#imageviewer").imageviewer("mijnSequence");
});



Let wel: dit is ongetest! Ik heb het gewoon even snel in een notepadje gedumpd.
Hiermee zou mcdronkz alleen in elk geval een heel eind moeten komen, denk ik zo.

[ Voor 56% gewijzigd door R4gnax op 31-07-2009 16:55 ]


Acties:
  • 0 Henk 'm!

  • mcdronkz
  • Registratie: Oktober 2003
  • Laatst online: 16-04 12:44
Wow, dat is de eerste keer dat ik meemaak dat iemand hier in een dusdanig goede bui is dat 't hele script herschreven wordt :D. Super, dankjewel!

De rest ook bedankt.

't Zijn, zoals je wellicht zult begrijpen, m'n eerste stappen in jQuery. Omdat er een werkend eindproduct moest komen binnen korte tijd had ik weing tijd om er dieper in te springen. Ik vind het echter een ontzettend interessant idee dat ik binnen korte tijd dit soort JavaScript dingen kan schrijven die met XML, JSON, events enzovoorts werken, 't zal er dus wel eens van komen dat ik een jQuery boek zal aanschaffen :).

Nogmaals bedankt, ik ga me eens verdiepen in het script dat hierboven gepost is.
Pagina: 1