Rails 4:ターボリンクで$(document).ready()を使用する方法


422

「Rails way」でJSファイルを整理しようとしたときに、Rails 4アプリで問題が発生しました。以前は、さまざまなビューに散らばっていました。それらを別々のファイルに編成し、アセットパイプラインでコンパイルしました。ただし、ターボリンクがオンになっていると、jQueryの「準備完了」イベントが後続のクリックで起動しないことを知りました。初めてページをロードしたときに機能します。ただし、リンクをクリックすると、の内部はready( function($) {実行されません(ページが実際に再度読み込まれないため)。良い説明:ここ

だから私の質問は:ターボリンクがオンのときにjQueryイベントが正しく機能することを保証する正しい方法は何ですか?スクリプトをRails固有のリスナーでラップしますか?それとも、レールには不必要な魔法があるのでしょうか?特にapplication.jsのようなマニフェストを介して複数のファイルをロードすることに関して、ドキュメントはこれがどのように機能するかについて少し曖昧です。

回答:


554

これが私がすることです... 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:loadturbolinks:load初期ロード時に発生します。したがって、次のようにすることができます。

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

  ...your javascript goes here...

});

3
そのコーヒーのスクリプトですか?まだ習っていません。あなたの例に相当するjsまたはjQueryはありますか?
emersonthis 2013

6
わかったと思います:両方とトリガーが発生するvar ready = function() { ... } $(document).ready(ready) $(document).on('page:load', ready)ことについて懸念はありますか? .ready'page:load'
emersonthis 2013

4
:@Emerson非常に便利なウェブサイトは、明示的な名前で、そこにあるjs2coffee.org
MrYoshiji

16
レディ関数が2度呼び出されないことが確認できました。ハードリフレッシュの場合は、イベントのみreadyが発生します。ターボリンクロードの場合、イベントのみpage:loadが発生します。readypage:loadを同じページで解雇することはできません。
クリスチャン

7
FYIまた、複数のイベントのためにこれを適用することができますpage:loadし、ready最初のargumetのためのスペースで区切られた文字列を含むことによって。$(document).on('page:load ready', ready);2番目の引数は単に関数でありready、この答えの例に従って、たまたま名前が付けられます。
ahnbizcad 2014

235

この問題を解決するための別のオプションを知りました。あなたがロードした場合宝石をそれがへのレールTurbolinksイベントをバインドしますあなたは、通常の方法であなたのjQueryを書くことができるようなイベント。あなただけの追加直後(デフォルト:JSマニフェストファイル内)。jquery-turbolinksdocument.readyjquery.turbolinksjqueryapplication.js


2
素晴らしいです、ありがとう!まさに私が必要とするもの。レールウェイ。コンベンション。
ジェレミーベッカー

6
ドキュメントに従って//= require jquery.turbolinks、マニフェスト(例:application.js)に追加する必要があります。
外典作成者

1
@wildmonkey 2つの答えは相互に排他的です。0.o
ahnbizcad

1
このgemを追加する場合は、railsサーバーを再起動する必要があります
Toby 1 Kenobi

21
Rails 4のデフォルトがTurbolinks 5になり、jquery.turbolinksでサポートされなくなりました!github.com/kossnocorp/jquery.turbolinks/issues/56
sebastian

201

最近、私はそれを処理する最もクリーンで理解しやすい方法を見つけました:

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

または

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

EDIT
あなたがしている場合は委任イベントにバインドされたが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


9
これは、別のready()関数を作成するという一般に認められている答えよりもはるかに単純です。ボーナスは、ready関数の外部で委任されたイベントをバインドすることの説明に賛成票を投じます。
クリスチャン

1
この方法の欠点は、$(document).on( "ready", handler ), deprecated as of jQuery 1.8. jquery / readyです
mfazekas 14

@Dezi @mfazekasこのソリューションは、jQueryの以前のバージョンを使用していて、jquery-turbolinks gemがない場合に機能しますか?またはready、gemを使用してBYを無効にした部分はありますか?
ahnbizcad 2014

それを行う最も簡単で簡単な方法。それは複数のファイルで配布されたjsコードをサポートし、それらが含まれている順序で気にする必要はありません。変数の割り当てよりもはるかにクリーンです。
Evgenia Manolova 2015年


91

これはRails 4のドキュメントで見つかりました。DemoZlukのソリューションに似ていますが、少し短いです:

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

または

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

を呼び出す外部スクリプトがある$(document).ready()場合、または既存のすべてのJavaScriptを書き換えるの$(document).ready()が面倒な場合は、このgemを使用してTurboLinksで引き続き使用できます:https : //github.com/kossnocorp/jquery.turbolinks


79

新しいレールガイドによると、正しい方法は次のとおりです。

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

または、coffeescript:

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

イベント$(document).readyをリッスンしないでください。イベントが1つだけ発生します。驚きはありません、jquery.turbolinks gem を使用する必要はありません。

これは、レール5だけでなく、レール4.2以降でも機能します。


これでうまくいきました。ここで解決策を試してみました:stackoverflow.com/questions/17881384/…が、何らかの理由で機能しませんでした。今度はturbolinks:loadにロードします
krinker

1
"turbolinks:load"イベントがRails 4.2で機能することを誰かが確認できますか?turbolinks:イベントの接頭辞をで導入された TurbolinksとTurbolinks使用していますRailsの4.2 IIRCに使用されていないクラシックを。Rails 5以前のアプリで機能しない"page:change"場合"turbolinks:load"は、試してみてください。guides.rubyonrails.org/v4.2.7/…を
Eliot Sykes

1
@EliotSykesガイドは更新されていません。Rails 4.2は、turbolinks-classicではなくgithub.com/turbolinks/turbolinksを使用するようになりました。いずれにしても、これはGemfileで指定した内容によって異なります。あなたがすぐに同じことを確認することを願っています:)
ヴェダント

3
@ vedant1811に感謝します。執筆時点で、新しいRails 4.2.7アプリがTurbolinks 5(turbolinks-classicではない)を使用していることを確認しています。開発者はこれを読んでいます-使用されているturbolinksバージョンについてGemfile.lockを確認してください。5.0未満の場合は、page:changeターボリンクを使用またはアップグレードします。:またturbolinksは古いイベント名にイベントを変換するところ、これは、いくつかに関連する可能性があるたgithub.com/turbolinks/turbolinks/blob/v5.0.0/src/turbolinks/...
エリオット・サイクスを

1
alert "page has loaded!"コールバック関数によって実際に実行されるようにインデントする必要はありますか?
mbigras

10

注:クリーンで組み込みのソリューションについては、@ SDPの回答を参照してください

私はそれを次のように修正しました:

次のようにインクルードの順序を変更して、他のアプリ依存のjsファイルがインクルードされる前に、application.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');
});

2
これは、すべてのcoffeescriptファイルではなく、1か所で追加する必要があるため、最もクリーンなようです。よくやった!
2013年

@sledこれは、SDPのgemとこのコードを使用する方法を使用するということですか?それとも宝石を使わない答えですか?
ahnbizcad 2014

この答えを忘れて、SDPのソリューションを使用してください。
2014

@sled SDPのソリューションと、通話を1か所だけに置くという概念を組み合わせることができますか?
ahnbizcad 2014

1
@gwho:SDPの回答が示すように、ターボリンクはreadyイベントにフックします。これは、「標準」の初期化方法を使用できることを意味します$(document).ready(function() { /* do your init here */});。完全なページが読み込まれたときに(->ターボリンクなしで)initコードを呼び出し、ターボリンクを介してページを読み込んだときに、initコードを再度実行する必要があります。ターボリンクが使用されている場合にのみコードを実行する場合:$(document).on('page:load', function() { /* init only for turbolinks */});
スレッド

8

上記のどれも私にはうまくいきません、jQueryの$(document).readyを使用せずにこれを解決しましたが、代わりにaddEventListenerを使用しました。

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

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

これは、Turbolinks> = 5のすべてのブラウザーで機能する唯一のソリューションであり、最初のページの読み込み時と、リンク(ターボリンクを使用)をクリックしたときにトリガーされます。これは、Chromeがturbolinks:load最初のページのロード時にトリガーする一方で、Safariがトリガーせず、それを修正する(ハッカーがトリガーturbolinks:loadするapplication.js)方法が明らかにChromeを破壊するためです(これにより2回起動します)。これが正解です。間違いなく2つのイベントreadyと行くturbolinks:load
ルカサルーダ



2

変数を使用して「準備完了」関数を保存し、イベントにバインドする代わりに、トリガーするreadyたびにイベントをトリガーすることができpage:loadます。

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

2

これが2度実行されないようにするために私が行ったことです。

$(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")、あなたが開発している場合は特に-予期せぬ振る舞い自体が。


意外と振る舞うとはどういう意味ですか?
sunnyrjuneja 2015

$(document).off上記の匿名の "page:change"関数のビットを含まない単純なアラートがある場合、そのページに到達するとアラートが表示されます。しかし、少なくともWEBrickを実行している開発では、別のページへのリンクをクリックしたときにも警告されます。さらに悪いことに、元のページに戻るリンクをクリックすると2回アラートが表示されます。
グレイケミー

2

私は次の記事を見つけました。これは私にとって非常に効果的であり、次の使用法について詳しく説明しています。

var load_this_javascript = function() { 
  // do some things 
}
$(document).ready(load_this_javascript)
$(window).bind('page:change', load_this_javascript)

2

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


2
$(document).ready(ready)  

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

2
このコードスニペットは問題を解決する可能性がありますが、説明を含めると、投稿の質を高めるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。
andreas

4
実際、この答えは正しくありません。このturbolinks:loadイベントは、最初のページの読み込み時だけでなく、リンクをたどった後にも発生します。標準readyイベントとイベントの両方にイベントをアタッチすると、turbolinks:load最初にページにアクセスしたときに2回発生します。
アレクサンダーバード2016年

この答えは間違っています。@alexanderbirdが言ったように、それはreadyその後のページの読み込みで2回起動する原因になります。変更または削除してください。
チェスター2017

@alexanderbirdあなたのコメントは私にとって問題の1つを解決しました
Anwar

1

テストされた非常に多くのソリューションがついにこれに至りました。これだけ多くのコードが2回呼び出されることはありません。

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

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


1

私は通常、rails 4プロジェクトに対して次のことを行います。

application.js

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

次に、残りの.jsファイルで、$(function (){})次の呼び出しを使用する代わりにonInit(function(){})


0

まず、jquery-turbolinksgemをインストールします。そして、あなたの体の端からご含まJavaScriptファイルを移動することを忘れないでくださいapplication.html.erbそのに<head>

ここで説明しますが、速度最適化の理由からフッター内のアプリケーションのjavascriptのリンクを入れている場合、あなたはそれがタグ内のコンテンツの前にロードされるようにタグにそれを移動する必要があります。この解決策は私にとってうまくいきました。


0

私はのための機能を使用する場合、私の機能が倍増したreadyturbolinks: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);
};

そうすることで、ターボリンクがサポートされている場合に関数が2倍になりません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.