Rails 4: how to use $(document).ready() with turbo

2018-12-31 01:36发布

I ran into an issue in my Rails 4 app while trying to organize JS files "the rails way". They were previously scattered across different views. I organized them into separate files and compile them with the assets pipeline. However, I just learned that jQuery's "ready" event doesn't fire on subsequent clicks when turbo-linking is turned on. The first time you load a page it works. But when you click a link, anything inside the ready( function($) { won't get executed (because the page doesn't actually load again). Good explanation: here.

So my question is: What is the right way to ensure that jQuery events work properly while turbo-links are on? Do you wrap the scripts in a Rails-specific listener? Or maybe rails has some magic that makes it unnecessary? The docs are a bit vague on how this should work, especially with respect to loading multiple files via the manifest(s) like application.js.

19条回答
几人难应
2楼-- · 2018-12-31 01:50

Instead of using a variable to save the "ready" function and bind it to the events, you might want to trigger the ready event whenever page:load triggers.

$(document).on('page:load', function() {
  $(document).trigger('ready');
});
查看更多
有味是清欢
3楼-- · 2018-12-31 01:52

Tested so many solution finally came to this. This many your code is definitely not called twice.

      var has_loaded=false;
      var ready = function() {
        if(!has_loaded){
          has_loaded=true;
           
          // YOURJS here
        }
      }

      $(document).ready(ready);
      $(document).bind('page:change', ready);

查看更多
萌妹纸的霸气范
4楼-- · 2018-12-31 01:52

I usually do the following for my rails 4 projects:

In application.js

function onInit(callback){
    $(document).ready(callback);
    $(document).on('page:load', callback);
}

Then in the rest of the .js files, instead of using $(function (){}) I call onInit(function(){})

查看更多
情到深处是孤独
5楼-- · 2018-12-31 01:53

I found the following article which worked great for me and details the use of the following:

var load_this_javascript = function() { 
  // do some things 
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)
查看更多
无色无味的生活
6楼-- · 2018-12-31 01:55
$(document).on 'ready turbolinks:load', ->
  console.log '(document).turbolinks:load'
查看更多
闭嘴吧你
7楼-- · 2018-12-31 01:56

Here's what I do... CoffeeScript:

ready = ->

  ...your coffeescript goes here...

$(document).ready(ready)
$(document).on('page:load', ready)

last line listens for page load which is what turbo links will trigger.

Edit...adding Javascript version (per request):

var ready;
ready = function() {

  ...your javascript goes here...

};

$(document).ready(ready);
$(document).on('page:load', ready);

Edit 2...For Rails 5 (Turbolinks 5) page:load becomes turbolinks:load and will be even fired on initial load. So we can just do the following:

$(document).on('turbolinks:load', function() {

  ...your javascript goes here...

});
查看更多
登录 后发表回答