javascript - track - Rails 4: cómo usar $(document).ready() con turbo-enlaces
turbolinks callbacks (19)
Acabo de enterarme de otra opción para resolver este problema. Si carga la gema jquery-turbolinks
, vinculará los eventos Rails Turbolinks con los eventos document.ready
para que pueda escribir su jQuery de la forma habitual. Simplemente agregue jquery.turbolinks
justo después de jquery
en el archivo de manifiesto js (de forma predeterminada: application.js
).
Me encontré con un problema en mi aplicación Rails 4 al intentar organizar los archivos JS "a la manera de los rieles". Anteriormente estaban dispersos en diferentes puntos de vista. Los organicé en archivos separados y los compilé con el canal de activos. Sin embargo, acabo de enterarme de que el evento "listo" de jQuery no se dispara con los clics posteriores cuando se activa el turbo-vinculación. La primera vez que carga una página funciona. Pero cuando hace clic en un enlace, cualquier cosa que ready( function($) {
dentro de la ready( function($) {
no se ejecutará (porque la página no vuelve a cargar). Buena explicación: here .
Entonces, mi pregunta es: ¿Cuál es la forma correcta de garantizar que los eventos de jQuery funcionen correctamente mientras están activados los turbo-enlaces? ¿Envuelves los scripts en un oyente específico de Rails? ¿O tal vez los rieles tienen algo de magia que lo hace innecesario? Los documentos son un poco vagos sobre cómo debería funcionar esto, especialmente con respecto a la carga de múltiples archivos a través de los manifiestos como application.js.
En lugar de usar una variable para guardar la función "listo" y vincularla a los eventos, es posible que desee activar el evento ready
cada vez que la page:load
activadores.
$(document).on(''page:load'', function() {
$(document).trigger(''ready'');
});
Encontré el siguiente article que funcionó muy bien para mí y detalla el uso de lo siguiente:
var load_this_javascript = function() {
// do some things
}
$(document).ready(load_this_javascript)
$(window).bind(''page:change'', load_this_javascript)
Encontré esto en la documentación de Rails 4 , similar a la solución de DemoZluk pero un poco más corta:
$(document).on ''page:change'', ->
# Actions to do
O
$(document).on(''page:change'', function () {
// Actions to do
});
Si tiene scripts externos que llaman a $(document).ready()
o si no se le puede molestar en volver a escribir todo su JavaScript existente, esta gema le permite seguir usando $(document).ready()
con TurboLinks: https: //github.com/kossnocorp/jquery.turbolinks
Esto es lo que hago ... CoffeeScript:
ready = ->
...your coffeescript goes here...
$(document).ready(ready)
$(document).on(''page:load'', ready)
la última línea escucha la carga de la página, que es lo que los enlaces turbo activarán.
Editar ... agregando la versión de Javascript (por solicitud):
var ready;
ready = function() {
...your javascript goes here...
};
$(document).ready(ready);
$(document).on(''page:load'', ready);
Edición 2 ... Para la página de Rails 5 (Turbolinks 5) page:load
convierte en turbolinks:load
y se activará incluso en la carga inicial. Así que podemos hacer lo siguiente:
$(document).on(''turbolinks:load'', function() {
...your javascript goes here...
});
Esto es lo que he hecho para garantizar que las cosas no se ejecuten dos veces:
$(document).on("page:change", function() {
// ... init things, just do not bind events ...
$(document).off("page:change");
});
Encuentro que usar la gema jquery-turbolinks
o combinar $(document).ready
y $(document).on("page:load")
o usar $(document).on("page:change")
se comporta de forma inesperada. -Especialmente si estás en desarrollo.
Nada de lo anterior funciona para mí, resolví esto al no usar $ (document) .ready de jQuery, pero en su lugar usé addEventListener.
document.addEventListener("turbolinks:load", function() {
// do something
});
Normalmente hago lo siguiente para mis proyectos de rieles 4:
En application.js
function onInit(callback){
$(document).ready(callback);
$(document).on(''page:load'', callback);
}
Luego, en el resto de los archivos .js, en lugar de usar $(function (){})
llamo a onInit(function(){})
O bien usar el
$(document).on "page:load", attachRatingHandler
o usa la función .on de jQuery para lograr el mismo efecto
$(document).on ''click'', ''span.star'', attachRatingHandler
Consulte aquí para obtener más detalles: http://srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html
Pensé en dejar esto aquí para aquellos que se actualicen a github.com/turbolinks/turbolinks : la forma más fácil de corregir su código es a partir de:
var ready;
ready = function() {
// Your JS here
}
$(document).ready(ready);
$(document).on(''page:load'', ready)
a:
var ready;
ready = function() {
// Your JS here
}
$(document).on(''turbolinks:load'', ready);
Referencia: https://github.com/turbolinks/turbolinks/issues/9#issuecomment-184717346
Primero, instale la gema jquery-turbolinks
. Y luego, no olvide mover sus archivos Javascript incluidos desde el final del cuerpo de su application.html.erb
a su <head>
.
Como se describe aquí , si ha puesto el enlace javascript de la aplicación en el pie de página por razones de optimización de velocidad, deberá moverlo a la etiqueta para que se cargue antes del contenido de la etiqueta. Esta solución funcionó para mí.
Probado tantas soluciones finalmente llegó a esto. Este número de su código definitivamente no se llama dos veces.
var has_loaded=false;
var ready = function() {
if(!has_loaded){
has_loaded=true;
// YOURJS here
}
}
$(document).ready(ready);
$(document).bind(''page:change'', ready);
Recientemente encontré la forma más limpia y fácil de entender de lidiar con esto:
$(document).on ''ready page:load'', ->
# Actions to do
O
$(document).on(''ready page:load'', function () {
// Actions to do
});
EDITAR
Si ha delegado eventos vinculados al document
, asegúrese de adjuntarlos fuera de la función de ready
, de lo contrario obtendrán rebotes en cada page:load
evento de page:load
(que hace que las mismas funciones se ejecuten varias veces). Por ejemplo, si tiene alguna llamada como esta:
$(document).on ''ready page:load'', ->
...
$(document).on ''click'', ''.button'', ->
...
...
Sácalos de la función ready
, así:
$(document).on ''ready page:load'', ->
...
...
$(document).on ''click'', ''.button'', ->
...
Los eventos delegados vinculados al document
no necesitan estar vinculados en el evento ready
.
Según las nuevas guías de rieles , la forma correcta es hacer lo siguiente:
$(document).on(''turbolinks:load'', function() {
console.log(''(document).turbolinks:load'')
});
o, en coffeescript:
$(document).on "turbolinks:load", ->
alert "page has loaded!"
No escuches el evento $(document).ready
y solo se activará un evento. Sin sorpresas, no es necesario utilizar la gema jquery.turbolinks .
Esto funciona con rieles 4.2 y superiores, no solo rieles 5.
Tienes que usar:
document.addEventListener("turbolinks:load", function() {
// your code here
})
NOTA: Consulte la respuesta de @ SDP para obtener una solución limpia e integrada
Lo arreglé como sigue:
asegúrese de incluir application.js antes de que los otros archivos js dependientes de la aplicación se incluyan cambiando el orden de inclusión de la siguiente manera:
// in application.js - make sure `require_self` comes before `require_tree .`
//= require_self
//= require_tree .
Defina una función global que maneje el enlace en application.js
// application.js
window.onLoad = function(callback) {
// binds ready event and turbolink page:load event
$(document).ready(callback);
$(document).on(''page:load'',callback);
};
Ahora puedes atar cosas como:
// in coffee script:
onLoad ->
$(''a.clickable'').click =>
alert(''link clicked!'');
// equivalent in javascript:
onLoad(function() {
$(''a.clickable'').click(function() {
alert(''link clicked'');
});
<%= link_to ''Edit'', edit_article_path(article), ''data-no-turbolink'' => true %>
tal vez usted pueda usar así para usar "listo", como cerrar su turbolink.
$(document).on ''ready turbolinks:load'', ->
console.log ''(document).turbolinks:load''
$(document).ready(ready)
$(document).on(''turbolinks:load'', ready)