Rails 4: как использовать $(document).ready() с турбо-ссылками

Я столкнулся с проблемой в своем Rails 4 при попытке организовать JS файлы "путь рельсов". Раньше они были разбросаны по разным взглядам. Я организовал их в отдельные файлы и скомпилировал их с помощью конвейера активов. Тем не менее, я только что узнал, что событие jQuery "ready" не срабатывает при последующих нажатиях, когда включено турбосвязывание. При первой загрузке страницы она работает. Но когда вы нажимаете ссылку, что-либо внутри ready( function($) { не будет выполнено (потому что страница на самом деле не загружается снова). Хорошее объяснение: здесь.

Итак, мой вопрос: какой правильный способ обеспечить правильное функционирование jQuery-событий во время включения турбо-ссылок? Вы завершаете скрипты в Rails-специфическом слушателе? Или, может быть, у рельсов есть какая-то магия, которая делает это ненужным? Документы немного расплывчаты в отношении того, как это должно работать, особенно в отношении загрузки нескольких файлов через манифест (ы), например application.js.

Ответ 1

Я только что узнал о другом варианте решения этой проблемы. Если вы загрузите драгоценный камень jquery-turbolinks, он привяжет события Rails Turbolinks к событиям document.ready, чтобы вы могли написать свой jQuery обычным способом. Вы просто добавляете jquery.turbolinks сразу после jquery в файл манифеста js (по умолчанию: application.js).

Ответ 2

Вот что я делаю... CoffeeScript:

ready = ->

  ...your coffeescript goes here...

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

Последняя строка прослушивает загрузку страницы, что вызывает турбо-ссылки.

Изменить... добавление версии Javascript (для каждого запроса):

var ready;
ready = function() {

  ...your javascript goes here...

};

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

Изменить 2... Для Rails 5 (Turbolinks 5) page:load становится turbolinks:load и будет даже запущен при начальной загрузке. Поэтому мы можем просто сделать следующее:

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

  ...your javascript goes here...

});

Ответ 3

Недавно я нашел самый чистый и понятный способ борьбы с ним:

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

ИЛИ

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

ИЗМЕНИТЬ
Если у вас делегированные события связаны с document, убедитесь, что вы прикрепляете их вне функции ready, иначе они будут отскакивать каждый page:load событие (заставляя одни и те же функции запускаться несколько раз). Например, если у вас есть такие вызовы, как:

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

Выньте их из функции ready, например:

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

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

Делегированные события, связанные с document, не должны быть связаны с событием ready.

Ответ 4

Обнаружено это в документации Rails 4, аналогично решению DemoZluk, но немного короче:

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

ИЛИ

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

Если у вас есть внешние скрипты, вызывающие $(document).ready(), или если вас не беспокоит переписывание всего вашего существующего JavaScript, то этот камень позволяет вам использовать $(document).ready() с TurboLinks: https://github.com/kossnocorp/jquery.turbolinks

Ответ 5

В соответствии с новыми направляющими rails правильный способ заключается в следующем:

$(document).on('turbolinks:load', function() {
   console.log('(document).turbolinks:load')
});

или, в coffeescript:

$(document).on "turbolinks:load", ->
alert "page has loaded!"

Не слушайте событие $(document).ready, и только одно событие будет запущено. Никаких сюрпризов, нет необходимости использовать драгоценный камень jquery.turbolinks.

Это работает с рельсами 4.2 и выше, а не только с рельсами 5.

Ответ 6

ПРИМЕЧАНИЕ. См. ответ @SDP для чистого встроенного решения

Я зафиксировал его следующим образом:

убедитесь, что вы включили application.js, прежде чем другие зависимые от приложения js файлы будут включены, изменив порядок включения следующим образом:

// in application.js - make sure `require_self` comes before `require_tree .`
//= require_self
//= require_tree .

Определите глобальную функцию, которая обрабатывает привязку в application.js

// application.js
window.onLoad = function(callback) {
  // binds ready event and turbolink page:load event
  $(document).ready(callback);
  $(document).on('page:load',callback);
};

Теперь вы можете связать такие вещи, как:

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

// equivalent in javascript:
onLoad(function() {
  $('a.clickable').click(function() {
    alert('link clicked');
});

Ответ 7

Ничего из этого не работает для меня, я решил это, не используя jQuery $(document).ready, но вместо этого используйте addEventListener.

document.addEventListener("turbolinks:load", function() {
  // do something
});

Ответ 8

$(document).on 'ready turbolinks:load', ->
  console.log '(document).turbolinks:load'

Ответ 10

Либо используйте

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

или использовать функцию jQuery.on для достижения того же эффекта

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

см. здесь для более подробной информации: http://srbiv.github.io/2013/04/06/rails-4-my-first-run-in-with-turbolinks.html

Ответ 11

Вместо использования переменной для сохранения "готовой" функции и привязки ее к событиям вы можете запускать событие ready при срабатывании page:load.

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

Ответ 12

Вот то, что я сделал для обеспечения того, что вещи не выполняются дважды:

$(document).on("page:change", function() {
     // ... init things, just do not bind events ...
     $(document).off("page:change");
});

Я нахожу использование жемчужины jquery-turbolinks или комбинирование $(document).ready и $(document).on("page:load") или используя $(document).on("page:change") самостоятельно ведет себя неожиданно - особенно если вы находитесь в разработке.

Ответ 14

Я решил, что оставлю это здесь для тех, кто обновляется до Turbolinks 5: самый простой способ исправить ваш код - перейти от:

var ready;
ready = function() {
  // Your JS here
}
$(document).ready(ready);
$(document).on('page:load', ready)

в

var ready;
ready = function() {
  // Your JS here
}
$(document).on('turbolinks:load', ready);

Ссылка: https://github.com/turbolinks/turbolinks/issues/9#issuecomment-184717346

Ответ 15

$(document).ready(ready)  

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

Ответ 16

Я обычно делаю следующие для моих рельсов 4 проекта:

В application.js

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

Затем в остальных.js файлах вместо использования $(function(){}) я вызываю onInit(function(){})

Ответ 17

 <%= link_to 'Edit', edit_article_path(article), 'data-no-turbolink' => true %>

Может быть, вы можете использовать это, чтобы использовать "готово", это точно так же, как закрыть турболинк.

Ответ 18

Сначала установите jquery-turbolinks gem. И затем, не забудьте переместить ваши включенные файлы Javascript из конца тела вашего application.html.erb в его <head>.

Как описанный здесь, если вы поместили ссылку javascript приложения в нижний колонтитул для оптимизации скорости, вам нужно будет переместить ее в чтобы он загружался до содержимого в теге. Это решение сработало для меня.

Ответ 19

Протестировано так много решений, наконец, дошло до этого. Этот код не обязательно дважды вызывается.

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

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

Ответ 20

Я обнаружил, что мои функции удвоились при использовании функции для ready и turbolinks:load, поэтому я использовал

var ready = function() {
  // you code goes here
}

if (Turbolinks.supported == false) {
  $(document).on('ready', ready);
};
if (Turbolinks.supported == true) {
  $(document).on('turbolinks:load', ready);
};

Таким образом, ваши функции не удваиваются, если поддерживаются turbolinks!