views:

150

answers:

3

I did some googling and figured I'm probably experiencing so called "event bubbling" that I've never heard of but are not surprised by it's existance. I want it to fire only once and I'm wondering how to fix this.

Basically, I have this small code snippet:

$('.bggallery_images').click(function () {      
    alert('test');      
});

This is supposed to fire once from a php snippet that basically adds an image of each image from a specific folder. It then outputs an echo string where each image has the class of "bggallery_images".

PHP snippet looks like this:

                    <?php
                    $dirname = "img";
                    $images = scandir($dirname);
                    $ignore = Array(".", "..");
                    foreach($images as $file)
                        {
                        if(!in_array($file, $ignore))
                            {                                                           
                                echo "<img class=\"bggallery_images\" src=\"$dirname/$file\" />";                                                               
                            };
                        }  
                    ?>  

This all generates the html markup that looks like this for each image:

<img src="img/WhitePattern6.gif" class="bggallery_images">

What is happening here?

Here's the rendered output from FireBug:

<div id="gallery_lightbox" style="height: 215px; z-index: 4; display: block;">
                    <div id="close"></div>
                        <h2><cufon class="cufon cufon-canvas" alt="Velg " style="width: 39px; height: 20px;"><canvas width="49" height="23" style="width: 49px; height: 23px; top: -4px; left: 0px;"></canvas><cufontext>Velg </cufontext></cufon><cufon class="cufon cufon-canvas" alt="bakgrunnsbilde" style="width: 123px; height: 20px;"><canvas width="129" height="23" style="width: 129px; height: 23px; top: -4px; left: 0px;"></canvas><cufontext>bakgrunnsbilde</cufontext></cufon></h2>
                        <div class="bggallery_images">testererererer</div>
                        <img src="img/Bakgrunner/4462-v4.jpg" class="bggallery_images"><img src="img/Bakgrunner/5922.gif" class="bggallery_images"><img src="img/Bakgrunner/BluePattern.gif" class="bggallery_images"><img src="img/Bakgrunner/Brown1.gif" class="bggallery_images"><img src="img/Bakgrunner/Brown2Pattern.jpg" class="bggallery_images"><img src="img/Bakgrunner/BrownPattern.jpg" class="bggallery_images"><img src="img/Bakgrunner/Brownn.gif" class="bggallery_images"><img src="img/Bakgrunner/GrayPattern.gif" class="bggallery_images"><img src="img/Bakgrunner/GreenPattern3.gif" class="bggallery_images"><img src="img/Bakgrunner/OrangePattern.gif" class="bggallery_images"><img src="img/Bakgrunner/PurplePattern.gif" class="bggallery_images"><img src="img/Bakgrunner/PurplePattern2.gif" class="bggallery_images"><img src="img/Bakgrunner/RedPattern3.gif" class="bggallery_images"><img src="img/Bakgrunner/RedPattern4.gif" class="bggallery_images"><img src="img/Bakgrunner/RedPattern5.gif" class="bggallery_images"><img src="img/Bakgrunner/Tiled_Wallpaper__Green_Texture_by_knitetgantt.png" class="bggallery_images"><img src="img/Bakgrunner/WhitePattern4.gif" class="bggallery_images"><img src="img/Bakgrunner/WhitePattern5.gif" class="bggallery_images"><img src="img/Bakgrunner/WhitePattern6.gif" class="bggallery_images"><img src="img/Bakgrunner/WhitePattern7.gif" class="bggallery_images"><img src="img/Bakgrunner/WhitePurple.jpg" class="bggallery_images"><img src="img/Bakgrunner/YellowPattern.gif" class="bggallery_images"><img src="img/Bakgrunner/vintage-wallpaper.jpg" class="bggallery_images">  
                     </div>

Edit: Here's the js.js file basically. I didn't include the kwicks slidemenu script though.

/* ********************************************** */
/* DOCUMENT READY */
/* ********************************************** */

$(document).ready(function () {
    bg_gallery();

});

/* ********************************************** */
/* Background gallery changer */
/* ********************************************** */

function bg_gallery() {

        // Sett nytt bakgrunnsbilde i CSSen 
        var originalBG = $('#wrapper').css('background-image');             

        $('.bggallery_images').click(function () {  
            var newBG = "url('" + $(this).attr('src');
            var fullpath = $(this).attr('src');
            var filename = fullpath.replace('img/Bakgrunner/', '');

            $('#wrapper').css('background-image', newBG);
            alert('test');

            // Lagre til SQL
            /*alert('Test');
            $.ajax({
                url: 'save_to_db.php', // The url to your function to handle saving to the db
                data: filename,
                dataType:'Text',
                type: 'POST',  // Could also use GET if you prefer
                success: function(data) {
                    // Just for testing purposes.
                    //alert('Background changed to: ' + data);
                }           

            });*/

    });     
        // Få frem galleriet

    $('.bggallery_current_image').click(function () {

        $('html, body').animate({scrollTop:0}, 'slow');
        $('#gallery_lightbox').css('height','215px'); // Sett høyde på lightbox-dings
        $('#gallery_lightbox').css('z-index','4'); // Sørg for at boksen er i øverste lag

        $('body').append('<div id="bggallery_overlay"></div>');
        $('#bggallery_overlay').css('height', $(document).height ());
        $('#bggallery_overlay').css('width', $(document).width ());     

        $('#bggallery_overlay').fadeIn('fast',function(){$('#gallery_lightbox').fadeIn('slow');});

    });

     $('#close').click(function () {
         $('#bggallery_overlay').fadeOut('fast',function(){$("#bggallery_overlay").remove();}); //callback, vent
         $('#gallery_lightbox').fadeOut('slow');


    });
};


/* ********************************************** */
/* Content loader (swoosh ut-swosh inn) */
/* ********************************************** */

/* Load kun fra dynload-klasser, må wrappe en div f. eks rundt slike a href linker */

$('.dynload').die('click').live('click', function () {
    $('#ajaxloader').fadeIn('fast');
    $('#ajaxloaderfridge').fadeIn('fast');
    var href = this.href + ' #content';
    var height_initially = $('#container').height();
    $('#content').slideUp('fast', function () {

        $('#content').fadeOut('fast');
        var height_current = $('#container').height();

        $(this).load(href, '', function (data) {
            createSlidemenus();
            bg_gallery();
            $('#ajaxloader').fadeOut('fast');
            $('#ajaxloaderfridge').fadeOut('fast');

            $("#content").animate({
                height: 'show',
                opacity: 'show'
            }, 'normal');

            $('#content').show('fast');

            Cufon.replace('h1, h2, h3, h4, .menuwrapper', {
                fontFamily: 'advent'
            });
        });
    });
    return false;
});

$(createSlidemenus);

function createSlidemenus() {
    $('#kontrollpanel .slidepanels').kwicks({
        min: 42,
        spacing: 3,
        isVertical: true,
        sticky: true,
        event: 'click'
    });
}
A: 

Hey Kenny,

Check out the following link to clarify event bubbling: http://www.quirksmode.org/js/events_order.html

You can prevent bubbling by just returning "false" from the event handler:

$('.bggallery_images').click(function () {      
    alert('test');
    return false;
});

Edit: This code works without producing two alerts so it must be something external to this.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd"&gt;
<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"&gt;&lt;/script&gt;
</head>
<body>
    <div id="gallery_lightbox" style="height: 215px; z-index: 4; display: block;">
        <div id="close"></div>
        <h2>
            <cufon class="cufon cufon-canvas" alt="Velg " style="width: 39px; height: 20px;">
                <canvas width="49" height="23" style="width: 49px; height: 23px; top: -4px; left: 0px;"></canvas>
                <cufontext>Velg</cufontext>
            </cufon>
            <cufon class="cufon cufon-canvas" alt="bakgrunnsbilde" style="width: 123px; height: 20px;">
                <canvas width="129" height="23" style="width: 129px; height: 23px; top: -4px; left: 0px;"></canvas>
                <cufontext>bakgrunnsbilde</cufontext>
            </cufon>
        </h2>
        <div class="bggallery_images">testererererer</div>
        <img src="http://google.com/images/srpr/nav_logo13.png" class="bggallery_images"/>
        <img src="http://google.com/images/srpr/nav_logo13.png" class="bggallery_images"/>
    </div>

    <script type="text/javascript">
        $('.bggallery_images').click(function () {      
            alert('test');
        });
    </script>
</body>
</html>
Steven Paligo
I already tried this and it does not fix the problem. What does that imply?
Kenny Bones
It might not be a bubbling problem then. Do you have that same alert on any element that contains and an image?
Steven Paligo
If I understand you correctly, do I have another alert connected to a class or id that these images are contained in? No I do not. Tried searching the js file for that word (alert) and there's just one result.
Kenny Bones
Hm, well that's frustrating. :)Try this: $('.bggallery_images').click(function (e) { alert('test'); if (!e) var e = window.event; e.cancelBubble = true; if (e.stopPropagation) e.stopPropagation(); });By the way, which browser are you using?
Steven Paligo
I'm using FireFox. It also happens in IE. Tried your snippet and the alertbox appear twice.. I just love how things like this happen :)
Kenny Bones
Can you post the HTML/JavaScript from the rendered page somewhere? I'd like to play around with it if I can.
Steven Paligo
Like the output from FireBug? I can do that I suppose. Just to add some info, I created a div with the same class as the ones the images use and it alert came twice as well. Looks like its got nothing to do with img tags thenEdit: Updated the code and I know it looks like crap.. Also, I don't think the image tags are unclosed. Because notice the div in there with the same class and some dummy text inside? It happens there as well.
Kenny Bones
Check out the edit above. That code works without producing two alerts. I'd compare it to what you have and see what's functionally different.
Steven Paligo
Yeah, see my updated post for my js file. I think the problem is in that one. Tried removing the click handler from the function I was using it in "function gb_gallery()" and moved it to document ready instead. And the problem doesn't exist there.
Kenny Bones
A: 

I've created a test page from the html and js instruction you posted and can't reproduce your error- the alert only fires once. I'm using this for a jquery reference:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"&gt;&lt;/script&gt;

and this at the end to start things up

<script>

    $('.bggallery_images').click(function() {
        alert('test');
    });

</script>

you're doing something you're not telling us about or firebug is lying to you. it's possible the html that firebug is showing you (as it's interpreted) is different than the physical source of the page. can you post a complete example of your output which demonstrates the problem?

lincolnk
I noticed something just now. If I remove this js snippet from the original function it was in and put it in document ready, it only fires once. I've updated the first post to include the entire js.js file I use.
Kenny Bones
A: 

You might want to have a look at the jquery .bind() method.

The following is taken from the jquery docs page

Example: Cancel a default action and prevent it from bubbling up by returning false:

$("form").bind("submit", function() { return false; })

Example: Stop an event from bubbling without preventing the default action by 
using the .stopPropagation() method.

$("form").bind("submit", function(event) {
  event.stopPropagation();
});
andreas