Where to put the page-initialize javascript when using pjax?
Asked Answered
P

3

18

Most of the times, I put some javascript code in $(document).ready to do some initialization stuffs on the page, like event binding, etc.

But now I would like to use pjax https://github.com/defunkt/jquery-pjax for some of my pages.

With pjax, because there's only part of the page gets refreshed, $(document).ready will not get called again.

I could manually trigger the initializing script on event pjax:end, but I also want to know if there's a better solution for that.

Thanks.

Plaided answered 14/3, 2012 at 4:51 Comment(0)
S
0

I think your best bet is probably just to do what you said and hook your page specific init code up to the "pjax:end" event. That way it'll essentially be doing the same job that it did before and run against whatever html has been loaded in to the DOM.

Stealth answered 19/3, 2012 at 13:26 Comment(0)
G
57

You can easily link all your existing code to both the document.ready and pjax:success events, like so:

Before:

$(document).ready(function() {
    // page load stuff
});

After:

$(document).on('ready pjax:success', function() {
    // will fire on initial page load, and subsequent PJAX page loads
});
Geography answered 16/5, 2012 at 7:10 Comment(3)
What can I do if the initialization code is different for each page?Chalmers
@Adrian Macneil - What can I do if the initialization code is different for each page?Qatar
@Vonfry I use location page window.location.pathnameQatar
H
4

I have came up with this neat solution. You first start by creating a namespace for your binders in the global scope:

// Binder for PJAX init functions

$.fn.bindPJAX = {}; // Create namespace

function bindPJAX(functionName) {
  // Check function existence, then call it
  return $().bindPJAX[functionName] && $().bindPJAX[functionName]();
}

Then bind a callback to PJAX clicks:

$(document).ready(function(){
  if ($.support.pjax) {
    $('a[data-pjax]').on('click', function(event) {

      var container = '#main';
      var emptyRoute = 'feed'; // The function that will be called on domain's root

      // Store current href without domain
      var link = event.currentTarget.href.replace(/^.*\/\/[^\/]+\//, '');
      var target = link === "" ? emptyRoute : link;

      // Bind href-specific asynchronous initialization
      $(document).on('ready pjax:success', container, function() {
        bindPJAX(target); // Call initializers
        $(document).off('ready pjax:success', container); // Unbind initialization
      });

      // PJAX-load the new content
      $.pjax.click(event, {container: $(container)});

    })
  }
});

When this is set up, you can proceed to extend the $.fn.bindPJAX object to add functions that will match your route name. For example, this, in the global scope, will be called when accessing http://www.yourdomain.com/admin via PJAX:

$.extend($.fn.bindPJAX, {
  admin: function(){
    // Initialization script for /admin route
  }
});

You should also consider a viable DRY fallback when PJAX fails or isn't supported, like launching the correct init function on first pageload by checking window.location in javascript, or maybe hardcoding it in your application's views.

Humanist answered 18/2, 2013 at 8:29 Comment(0)
S
0

I think your best bet is probably just to do what you said and hook your page specific init code up to the "pjax:end" event. That way it'll essentially be doing the same job that it did before and run against whatever html has been loaded in to the DOM.

Stealth answered 19/3, 2012 at 13:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.