docodemore
docodemore

Reputation: 1074

jQuery scripts on ajax content WITHOUT using $(document).on

I am using an infinite scroll plugin which uses ajax.

When the 'next page' is loaded via ajax, all other ajax related scripts that are on the next page do not work. I have been told that I have to use 'delegated events'(ie change $(id).click() to $(document).on) - problem is that means editing multiple plugins and changing dozens of function calls.

Is there any way I can avoid changing everything to $(document).on and do something cool with the infinite scroll?????

I'd much rather modify the infinite scroll plugin rather than modifying other ajax related plugins to make them fit.

Upvotes: 0

Views: 126

Answers (4)

Neil Girardi
Neil Girardi

Reputation: 4933

Event delegation is the correct solution. The issue is that the HTML elements on the "next page" were not part of the DOM when the page loaded. Therefore, if you did something like:

$(function() {
    $('#some-element-on-the-next-page').click(function() {
        foo();
    }); 
});

Your handler did not bind.

I wouldn't attach the events to $(document). I would attach them to the closest parent which is available when the DOM loads. For example, the body tag or the fixed width wrapper which is the first child of the body (assuming your layout uses this type of structure.)

Make sure that the element that you attach to is not emptied with .empty() or repopulated with .html() as that will break the binding. Attaching the delegated handlers lower down on the DOM tree will give you better performance since the events will not have to bubble all the way up to the document node to fire your methods.

You shouldn't need to rewrite all of your functions and plugins, just the bindings to the events that fire them.
I typically use the module pattern and de-couple my method definitions from the click handlers. All of my methods are defined in the outer closure. I'll have a "document ready" section where I bind user events like clicks.

For example:

var myModule = (function() {

    var public = {};

    public.foo = function() {
        // do something cool here
    };


    // document ready
    $(function () {

        $('#site-container').on('click', '.js-foo', function() {
            public.foo();
         });

    });


    return public;   

})(); 

If you need to change the bindings in the future you will only need to change the call inside the document ready section.

Upvotes: 0

Sinetheta
Sinetheta

Reputation: 9449

Unfortunately you have very few options here, and switching to delegated events is by far the best of them.

The problem is that your old code was assigning behaviour to "particular elements" when what it should really have been doing is creating page-wide responses to "certain types of actions".

I see 3 possibilities, and only one of them is guaranteed to work.

  1. Run any scripts that are needed on new pages each time a new page is loaded. The downside here being that unless you are careful about also "tearing down" between content loads you will have behaviours repeating or colliding with each other (eg: double popups, broken animations).
  2. Encapsulate the dynamic areas in <iframe>s. Depending on your architecture this may or may not be possible, and certainly won't be easy to integrate with some kind of infinite scrolling plugin which already expects a certain page structure.
  3. Bite the bullet and fix the crappy code.

Upvotes: 4

Starx
Starx

Reputation: 79031

Loading scripts inside your ajax loaded content is a bad way to start with anyway. What you need is event delegation to attach itself to any dynamically added elements.

$("body").on("click", ".yourclass", function() {
    //This function will run for every element with `yourclass` class you load via ajax
});

Upvotes: 1

Collin Grady
Collin Grady

Reputation: 2243

If you must keep using .click() then you must have a function you can call on the new content to re-hook the events every time you add more content to the page.

e: though it is worth noting that a change from .click to .on can often be handled by a properly structured find/replace

Upvotes: 0

Related Questions