質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

2回答

4636閲覧

【Rails/jQuery】turbolinks をオフにしないままで、.hover を発火させたり.offset().top を取得したい

jusco

総合スコア80

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

2クリップ

投稿2015/08/07 17:26

編集2015/08/10 04:51

RailsでTubolinksをオンにしてjQueryを使用する場合、通常通りの記述ではreadyが動かないということがわかったため、その対策を記入しました。
それによってTubolinksをオフにせずともいくつかのjsファイルはうまく動作したのですが、以下の2機能についてはreadyがうまく発火していないようで、ページを再読み込みしないと動作しません。

今回実装したい機能は以下の2点です。
1.「#fixMenu」の固定
2.「.MenuBody」の表示切り替え

まず1.について。

javascript

1var ready; 2ready = function() { 3 4$(document).ready(function() { 5 var nav = $('#fixMenu'), 6 offset = nav.offset(); 7 8 $(window).scroll(function () { 9 if($(window).scrollTop() > offset.top - 20) { 10 nav.addClass('fixed'); 11 } else { 12 nav.removeClass('fixed'); 13 } 14 }); 15}); 16 17 }; 18$(document).ready(ready); 19$(document).on('page:load', ready);

上記の記述でreadyの対策はできているかと思うのですが、ページ遷移後にはうまく動作せず、「Uncaught TypeError: Cannot read property 'top' of undefined」とエラーが出てしまいます。

また、2について、

javascript

1var ready; 2ready = function() { 3 $(function() { 4 $('.toggleMenu').click(function() { 5 if ($('.MenuBody').css('display') == 'block') { 6 $('.MenuBody').fadeOut('800'); 7 }else{ 8 $('.MenuBody').slideDown('1000','swing'); 9 10 } 11 }); 12 $('.toggleMenu,.MenuBody').hover(function(){ 13 over_flag = true; 14 }, function(){ 15 over_flag = false; 16 }); 17 $('body').click(function() { 18 if (over_flag == false) { 19 $('.MenuBody').fadeOut('800'); 20 21 } 22 }); 23 }); 24}; 25$(document).ready(ready); 26$(document).on('page:load', ready);

こちらも同様に、ページ遷移後はうまく動作せず、再読み込みすればうまく動作します。
ページ遷移後は、「.MenuBody」は上から降りてはくるのですが、降りてくると同時にフェードアウトして消えてしまいます。
おそらく「.hover」の発火がうまくいってないのではないかと思いますが、「Uncaught ReferenceError: over_flag is not defined」というエラーが出ています。

jquery.turbolinksを使用しても同様の結果でした。
どのようにすればこれらのjQueryを正常動作させることができるでしょうか。

ご回答よろしくお願いいたします。


  1. について、hello-world様から頂いた以下の回答で動作しました。

Javascript

1 2(function(){ 3 var offset; 4 5 $(window).scroll(function () { 6 var nav = $('#fixMenu'); 7 if(offset && $(window).scrollTop() > offset.top - 20) { 8 nav.addClass('fixed'); 9 } else { 10 nav.removeClass('fixed'); 11 } 12 }); 13 14 $(document).on('ready page:load', function(){ 15 offset = $('#fixMenu').offset(); 16 }) 17})();

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

lang

1var ready; 2ready = function() { 3 var nav = $('#fixMenu'), 4 offset = nav.offset(); 5 6 $(window).scroll(function () { 7 if($(window).scrollTop() > offset.top - 20) { 8 nav.addClass('fixed'); 9 } else { 10 nav.removeClass('fixed'); 11 } 12 }); 13}; 14$(document).ready(ready); 15$(document).on('page:load', ready);

です。readyon(page:load)に渡す関数の中でさらにreadyに渡してもうまくいきません


改善案

lang

1$(window).scroll(function () { 2 var nav = $('#fixMenu'), 3 offset = nav.offset(); 4 if($(window).scrollTop() > offset.top - 20) { 5 nav.addClass('fixed'); 6 } else { 7 nav.removeClass('fixed'); 8 } 9});

案2

lang

1(function(){ 2 var offset; 3 4 $(window).scroll(function () { 5 if(offset && $(window).scrollTop() > offset.top - 20) { 6 nav.addClass('fixed'); 7 } else { 8 nav.removeClass('fixed'); 9 } 10 }); 11 12 $(document).on('ready page:load', function(){ 13 offset = $('#fixMenu').offset(); 14 }) 15})();

2.「.MenuBody」の表示切り替え

  1. イベントの登録がおかしかったのを修正しました。$(document).on('ready page:load', function(){
  2. アニメーションの途中で消えるということだったので、アニメーションが完了してからcanFadeクラスを追加するようにした
  3. over_flag変数が正しく宣言されていなかったので、代わりにisHoverクラスとして要素に持たせた

lang

1$(document).on('ready page:load', function(){ 2 $('.toggleMenu').click(function() { 3 if ($('.MenuBody').css('display') != 'block') { 4 $('.MenuBody').slideDown('1000','swing', function() { 5 $('.MenuBody').addClass('canFade'); 6 }); 7 } else if($('.MenuBody').hasClass('canFade')) { 8 $('.MenuBody').fadeOut('800'); 9 } 10 }); 11 $('.toggleMenu,.MenuBody').hover(function(){ 12 $('.MenuBody').addClass('isHover'); 13 }, function(){ 14 $('.MenuBody').removeClass('isHover'); 15 }); 16 $('body').click(function() { 17 if ($('.MenuBody').hasClass('isHover') == false && $('.MenuBody').hasClass('canFade')) { 18 $('.MenuBody').fadeOut('800'); 19 } 20 }); 21}); 22

投稿2015/08/07 23:36

編集2015/08/10 06:51
hello-world

総合スコア1342

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jusco

2015/08/08 05:56

ご回答有難うございます! readyを減らして、教えていただいたとおりに記述してみましたがうまく動作しませんでした(T_T)
hello-world

2015/08/08 13:30

> 上記の記述でreadyの対策はできているかと思うのですが、ページ遷移後にはうまく動作せず、「Uncaught TypeError: Cannot read property 'top' of undefined」とエラーが出てしまいます。 まだこのエラーがでているのなら、offset が undefinedだというエラーなので var nav = $('#fixMenu'), offset = nav.offset(); のすぐ下で console.log(nav, offset); などして、値を確認するのはどうでしょうか。
jusco

2015/08/10 01:03

ご回答有難うございます。 console.log(nav, offset); を記入したところ、 [div#fixMenu, context: document, selector: "#fixMenu"] Object {top: 270, left: 842} このように値が取得できてはいるようなのですが、ページ遷移後にリロードを行わない場合、 Uncaught TypeError: Cannot read property 'top' of undefined(anonymous function) といったエラーメッセージが出てしまいます。 ページをリロードすることでこのエラーは消え、通常通りにjqueryが作動します…。
hello-world

2015/08/10 01:31

追記しました。 scrollイベントは、readyを待たずすぐに登録しても問題ないので、この方法でどうでしょう
jusco

2015/08/10 01:50

ご回答ありがとうございます。 早速試してみたところ、ページ遷移後でもすぐに動作辞退は確認できました! しかし、スクロールすると、固定部分が点滅したような表示になり、非常にカクカク動いているように見えてしまっています。 時には消えてしまうこともあります・・・。
hello-world

2015/08/10 02:16

カタカタするということは、position: fixed がうまく動いていないということですよね? `fixed` クラスでは`position: fixed`が指定されているのでしょうか? 何かのせいで、`fixed`クラスがついたり消えたりということはありませんか? if($(window).scrollTop() > offset.top - 20) {   nav.addClass('fixed');   console.log("add") } else {   nav.removeClass('fixed');   console.log("remove") } こんな感じのコードでログ中に removeが混じったりということはありませんか?
jusco

2015/08/10 03:08

おっしゃる通りで、fixedクラスにはそのような指定をしています。 確認したところ、スクロールすると、removeとaddがなんども繰り返しでログとして出ています。 元々の記述では、画面遷移後は動作しないものの、リロードすればadd,removeが交互に動作するということはなく、うまく動作していました。 しかし、リロードを待たずに登録する方法では、画面遷移後は動作するものの、add,removeが交互に動作してしまっています。
hello-world

2015/08/10 04:07

追記しました。これならどうでしょう
jusco

2015/08/10 04:49 編集

(function(){ var offset; $(window).scroll(function () { var nav = $('#fixMenu'); if(offset && $(window).scrollTop() > offset.top - 20) { nav.addClass('fixed'); } else { nav.removeClass('fixed'); } }); $(document).on('ready page:load', function(){ offset = $('#fixMenu').offset(); }) })(); ご回答いただいたものを元に、5行目に「var nav = $('#fixMenu');」を追記することでうまく動作しました!ありがとうございましたm(__)m もしよろしければ、2.についてもなにか分かりましたら教えて頂けると幸いです…m(__)m
hello-world

2015/08/10 06:51

質問2について追記しました。こんな感じでどうでしょうか。
jusco

2015/08/10 07:50

ご回答いただいた内容で完全に動作の確認が取れました!! 最後までご丁寧にお付き合い頂きまして、誠にありがとうございました…!!m(__)m
guest

0

Turbolinksを有効にしていると、windowオブジェクトはページ遷移しても変化しませんので、ページ遷移のたびに$(window).scrollイベントをセットしていると、どんどん溜まってきてしまいます。前のページにあった#fixMenuを指したままのjQueryオブジェクトもクロージャ内に残って、うまく動作しません。

ということで、

  1. 最初に一度だけ$(window).scrollへイベントをセットして、その中では$('body').trigger('window_scrolled');のようにカスタムイベントを中継するだけにする
  2. readyとページ遷移の両方で駆動する関数の中で、$('body').on('window_scrolled')とカスタムイベントを拾う

という流れがいいのではないかと思います。

投稿2015/08/08 00:26

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jusco

2015/08/08 05:57

ご回答有難うございます! 指針を示して頂いてありがとうございます。 流れはわかったのですが、実際にそれをどのように記述するのかがわかりません・・・。 お手すきの際に、具体的なコードを教えて頂けないでしょうか。 よろしくお願い致しますm(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問