Question

Lets say I have the following code

// JS

$(function(){
        $('[data-mc=logout]').click(function(){
                if (!confirm(myconfig.msg['asklogout'])) {
                    return false;
                }
        });

        $('[data-mc=ajax]').click(function(){
                var target=$(this).data('target'); //retrieve data-target of the clicked tag
                return false;
        });
});

which target some HTML elements

//  HTML

<a class='menulink' data-mc='logout' data-target='main-content-div' href='page/'>Logout</a>
<a class='menulink' data-mc='ajax' data-target='main-content-div' href='page/'>Start page</a>
  1. Am I right when I say that this code needs to be called on every full page load?

  2. a: If so, what if one of the elements doesn't exists on the chosen page?
    b: To avoid errors an "if exist" check is necessary, right?
    c: jQuery will do that prior adding the handler?

  3. What if some content gets requested using Ajax and inserted into the DOM. Then this code needs to be called again, right?

  4. Is this best practice or should the code be split and called per page load, where only existing element's event handlers gets attached?

Was it helpful?

Solution

  1. Always, JavaScript and jQuery never does a thing if you don't run it after a full page load.

  2. With jQuery, if no such element(s) exist, nothing happens.

  3. Dynamically added content will not have the handlers that have been applied by previous jQuery calls. I'm not sure exactly what will happen if you run the code again, but you might end up with elements that have multiple handlers attached where you only meant to attach one.

  4. If you are dynamically changing the set of objects that need event handlers you are probably better off putting the event handlers on a static parent element, the document for instance. You can use the jQuery on method to attach an event handler to the document, and pass it a filter string that will cause your handler only to fire when the event happens on an element that match the filter, and with the matched element as this value. The jQuery manual calls this delegated events:

    $(parentElement).on(eventName, filterString, function(){});
    

    The only possible downside to delegated events are that event handling may be a bit slower, but I can't think of a realistic example where this is a practical issue.

OTHER TIPS

If you want to bind events to dynamically loaded elements, you can utilize Event Bubbling. JQuery will help you with that! You'll need to bind the event with the on function(instead of click etc.) and use late selectors(not actual name - it's just me calling them that). For example:

HTML:

<div id="add-stuff-here"></div>

JavaScript:

$(function(){
        var addStuffHere=$('#add-stuff-here');
        addStuffHere.on('click','button[doit]',function(){
            var newButtonIndex = addStuffHere.children().length+1;
            var newButton = $('<button/>');
            newButton.text(newButtonIndex);
            if(1 == newButtonIndex%2){
                newButton.attr('doit', 'doit');
            }
            addStuffHere.append(newButton);
        });
        addStuffHere.append($('<button doit="doit">1</button>'));
});

I bound the click event to the div, and gave it the late selector button[doit]. Now this event will apply to all children of the div that match the selector(the odd-numbered buttons - the even ones don't get doit). Clicking on these buttons will create new buttons, and if they are odd they'll also get the event because it is bound to the parent.

Behind the scenes the events bubble up to the containing elements, so the event launches on the button and bubbles up to the div where it's handled. Here JQuery works it's magic - When you have a late selector, JQuery identify the source of the event, and if it matches the late selector you'll JQuery will treat it like the child element's event. If you don't have a late selector JQuery will treat it like the container's event.

Another approach, which I used before learning of event bubbling, is to attach the events to the dynamically created elements. Doing this manually it cumbersome, so I've build some helper functions: registerJQueryFunction and applyJQueryTo. applyJQueryTo will invoke all the functions registered with registerJQueryFunction on an element(s), and those function will set the events.

This works even better if you have built a framework(even a wrapper framework) for the dynamic loading, as you can simply integrate applyJQueryTo into it and never worry about it.

Licensed under: CC-BY-SA with attribution
scroll top