Rails 4: cómo usar $(documento).ready () con turbo-enlaces


Me encontré con un problema en mi aplicación Rails 4 al intentar organizar archivos JS "a la manera de rails". Anteriormente estaban dispersos en diferentes puntos de vista. Los organicé en archivos separados y los compilé con la canalización de activos. Sin embargo, acabo de enterarme de que el evento "listo" de jQuery no se activa en los clics posteriores cuando se activa el turbo-enlace. La primera vez que carga una página funciona. Pero cuando haces clic en un enlace, cualquier cosa dentro de ready( function($) { no se ejecutará (porque la página no en realidad cargar de nuevo). Buena explicación: aquí.

Así que mi pregunta es: ¿Cuál es la forma correcta de garantizar que los eventos de jQuery funcionen correctamente mientras los turbo-enlaces están activados? ¿Envuelve los scripts en un oyente específico de Rails? O tal vez rails tiene 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 varios archivos a través del manifiesto(s) como la aplicación.js.

Author: Community, 2013-09-12

19 answers

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 activarán los enlaces turbo.

Edit ...adición de la versión de Javascript (por solicitud):

var ready;
ready = function() {

  ...your javascript goes here...

};

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

Edit 2 ...Para Rails 5 (Turbolinks 5) page:load se convierte en turbolinks:load e incluso se disparará con la carga inicial. Así que podemos hacer lo siguiente:

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

  ...your javascript goes here...

});
 538
Author: Meltemi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-29 00:50:51

Acabo de enterarme de otra opción para resolver este problema. Si carga la gema jquery-turbolinks enlazará los eventos Rails Turbolinks a los eventos document.ready para que pueda escribir su jQuery de la manera habitual. Simplemente agregue jquery.turbolinks justo después de jquery en el archivo de manifiesto js (por defecto: application.js).

 233
Author: emersonthis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-24 00:25:38

Recientemente encontré la forma más limpia y fácil de entender de lidiar con ella:

$(document).on 'ready page:load', ->
  # Actions to do

O

$(document).on('ready page:load', function () {
  // Actions to do
});

EDITAR
Si tiene eventos delegados vinculados a document, asegúrese de adjuntarlos fuera de la función ready, de lo contrario obtendrán rebote en cada evento page:load (causando que las mismas funciones se ejecuten varias veces). Por ejemplo, si tienes llamadas como esta:

$(document).on 'ready page:load', ->
  ...
  $(document).on 'click', '.button', ->
    ...
  ...

Sacarlos de la función ready, como esto:

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

$(document).on 'click', '.button', ->
  ...

Los eventos delegados vinculados al document no necesitan estar vinculados al evento ready.

 196
Author: Dezl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-14 07:11:15

Encontró esto en la documentación de Rails 4, similar a la solución de DemoZluk pero ligeramente más corta:

$(document).on 'page:change', ->
  # Actions to do

O

$(document).on('page:change', function () {
  // Actions to do
});

Si tienes scripts externos que llaman a $(document).ready() o si no te molesta reescribir todo tu JavaScript existente, entonces esta gema te permite seguir usando $(document).ready() con TurboLinks: https://github.com/kossnocorp/jquery.turbolinks

 90
Author: migu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 01:23:29

De acuerdo con las nuevas guías rails , 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 escuche el evento $(document).ready y solo se disparará un evento. Sin sorpresas, no hay necesidad de usar el jquery .turbolinks gema.

Esto funciona con rails 4.2 y superiores, no solo con rails 5.

 73
Author: vedant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-19 11:59:21

NOTA: Consulte la respuesta de @SDP para obtener una solución integrada y limpia

Lo fijé de la siguiente manera:

Asegúrese de incluir la aplicación.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 .

Define una función global que maneja 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 enlazar cosas como:

// in coffee script:
onLoad ->
  $('a.clickable').click => 
    alert('link clicked!');

// equivalent in javascript:
onLoad(function() {
  $('a.clickable').click(function() {
    alert('link clicked');
});
 10
Author: sled,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-03 22:48:38

Nada de lo anterior funciona para mí, resolví esto al no usar el document(documento) de jQuery.listo, pero usa addEventListener en su lugar.

document.addEventListener("turbolinks:load", function() {
  // do something
});
 8
Author: RockL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-13 12:05:45

O bien utilizar el

$(document).on "page:load", attachRatingHandler

O usar jQuery .on function to achieve the same effect

$(document).on 'click', 'span.star', attachRatingHandler

Vea aquí para más detalles: http://srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html

 3
Author: derekyau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-12 17:50:47

En lugar de usar una variable para guardar la función "ready" y vincularla a los eventos, es posible que desee activar el evento ready cada vez que page:load se active.

$(document).on('page:load', function() {
  $(document).trigger('ready');
});
 2
Author: wachunei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-25 18:45:25

Esto es lo que he hecho para asegurarme de 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") por sí mismo se comporta inesperadamente especially especialmente si estás en desarrollo.

 2
Author: Gray Kemmey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-19 08:09:54

Encontré el siguiente artículo 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)
 2
Author: Adrian Mann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-21 14:54:02

Pensé que dejaría esto aquí para aquellos que actualizan a Turbolinks 5 : la forma más fácil de arreglar su código es ir desde:

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

 2
Author: tirdadc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-01 03:13:13

Tienes Que usar:

document.addEventListener("turbolinks:load", function() {
  // your code here
})

De turbolinks doc.

 2
Author: Gian Franco Fioriello,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-18 00:13:21
$(document).on 'ready turbolinks:load', ->
  console.log '(document).turbolinks:load'
 2
Author: Sukeerthi Adiga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-28 10:20:11
$(document).ready(ready)  

$(document).on('turbolinks:load', ready)
 1
Author: Konstantinos Mou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-14 06:47:48
 <%= link_to 'Edit', edit_article_path(article), 'data-no-turbolink' => true %>

Tal vez puedas usar así para usar "listo", al igual que cerrar tu turbolink.

 0
Author: Alan Wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-04 08:05:34

Primero, instale la gema jquery-turbolinks. Y luego, no se olvide de mover los 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 que el contenido de la etiqueta. Esta solución funcionó para mí.

 0
Author: Aboozar Rajabi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-21 09:58:11

Probado tantas solución 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);
 0
Author: Simon Meyborg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-01 10:04:14

Normalmente hago lo siguiente para mis proyectos de rails 4:

En application.js

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

Luego en el resto de la .archivos js, en lugar de usar $(function (){}) llamo onInit(function(){})

 0
Author: muZk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 18:49:46