Migrating jQuery for use in a Turbolinks Application
Updating to a rails version with Turbolinks can potentially cause issues with existing jQuery code. The primary issue is with jQuery that is invoked in the ready() function.
Take this jQuery as an example.
$(document).ready(function(){
$("[data-toggle='autocomplete']").each(function(){
$(this).prop("autocomplete", "off");
});
});
In the context of a Turbolinks application this will only be triggered on an initial page load or refresh (i.e. not after any subsequent Turbolink controlled link clicks). One way to get around this is to wrap the code to be executed in a function and call it from an eventListener bound to the page:load event in addition to the ready() function.
function toggleAutoComplete(){
$("[data-toggle='autocomplete']").each(function(){
$(this).prop("autocomplete", "off");
});
}
$(document).ready(function(){ toggleAutoComplete() });
document.addEventListener('page:load', function(){ toggleAutoComplete() });
EDIT: @glaszig points out that you can use
jQuery(document).on("ready page:change", function() { toggleAutoComplete() })
to make this a bit more concise and keep your jQuery as an anonymous function if you so choose. Also page:change will cause the jQuery to get executed a few milliseconds before page:load.
This will call the toggleAutoComplete() function when the page is initially loaded ( via ready() ) and when the page:load (or page:change if you use it) event is triggered at the end of the Turbolinks Events Sequence.
There are a lot of things you can do to write your jQuery to make it Turblolinks compatible now (most of them are javascript best-practices anyhow). There are a lot of good resources out there on how to do that in the Turbolinks context, however an easy one to keep in mind is using (EDIT: delegated) on() events instead of explicit event functions (e.g. click, change, submit, etc) when possible. This ensures that the functions are attached to these DOM objects regardless if the object was in existence when the function was initially called.
Written by Jessie Keck
Related protips
8 Responses

The .on() part is actually not true anymore, read the docs: Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on().
That said, you could bind events to document and then as the first parameter send in the selector. This is NOT a best practice but will do it's job.

That's not exactly right either, $.fn.on was added to bring together event binding (elements that exist on document ready) and delegation (elements which may exist in the future).