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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

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

Q&A

1回答

1061閲覧

複数のスライドで、ページのインデックス番号が繋がってしまう。

punchan36

総合スコア105

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

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

0グッド

0クリップ

投稿2021/05/19 03:14

編集2021/06/03 05:21

前提・実現したいこと

モーダルにて表示されるスライド機能を作成致しました。
スライドの大まかな機能としては以下の通りです。

  • 「←前へ」「次へ→」のボタンがあり、クリックすると表示されるページが切り替わる。
  • 1, 2, 3のページ番号もあり、クリックすると該当のページに表示が切り替わる。
  • スライドが最初か最後のページである場合、「←前へ」「次へ→」ボタンの表示がそれぞれ消える。

スライドが一つしかない場合は下記のコードで問題なく実装出来ていたのですが、スライドを2つ以上に増やすと最後の項目が上手く機能しなくなりました。

slide.html.erb

rails

1<ul> 2 <li><div data-target="slide01">スライド1</div> 3 <div id="slide01" class="modal-wrapper"> 4 <div class="modal"> 5 <div class="close-modal"> 6 <i class="fa fa-2x fa-times"></i> 7 </div> 8 <div class="slide-wrapper"> 9 <div class="slide-title">スライド1</div> 10 <div class="change-btn-wrapper"> 11 <div class="change-btn prev-btn">← 前へ</div> 12 <div class="change-btn next-btn">次へ →</div> 13 </div> 14 <ul class="slides"> 15 <li class="slide active">あ</li> 16 <li class="slide">い</li> 17 <li class="slide">う</li> 18 </ul> 19 <div class="index-btn-wrapper"> 20 <div class="index-btn">1</div> 21 <div class="index-btn">2</div> 22 <div class="index-btn">3</div> 23 </div> 24 </div> 25 </div> 26 </div> 27 </li> 28 29 <li><div data-target="slide01">スライド2</div> 30 <div id="slide01" class="modal-wrapper"> 31 <div class="modal"> 32 <div class="close-modal"> 33 <i class="fa fa-2x fa-times"></i> 34 </div> 35 <div class="slide-wrapper"> 36 <div class="slide-title">スライド2</div> 37 <div class="change-btn-wrapper"> 38 <div class="change-btn prev-btn">← 前へ</div> 39 <div class="change-btn next-btn">次へ →</div> 40 </div> 41 <ul class="slides"> 42 <li class="slide active">か</li> 43 <li class="slide">き</li> 44 <li class="slide">く</li> 45 </ul> 46 <div class="index-btn-wrapper"> 47 <div class="index-btn">1</div> 48 <div class="index-btn">2</div> 49 <div class="index-btn">3</div> 50 </div> 51 </div> 52 </div> 53 </div> 54 </li> 55</ul>

slide.js

js

1$(document).on('turbolinks:load', function() { 2 $(function() { 3 function toggleChangeBtn(){ 4 var slideIndex = $('.slide').index($('.active')); 5 $('.change-btn').show(); 6 if (slideIndex == 0) { 7 $('.prev-btn').hide(); 8 } else if (slideIndex == $('.slide').length -1) { 9 $('.next-btn').hide(); 10 } 11 12 $('.index-btn').click(function() { 13 $('.active').removeClass('active'); 14 var clickedIndex = $('.index-btn').index($(this)); 15 $('.slide').eq(clickedIndex).addClass('active'); 16 toggleChangeBtn(); 17 }); 18 19 $('.change-btn').click(function() { 20 var $displaySlide = $('.active'); 21 $displaySlide.removeClass('active'); 22 if ($(this).hasClass('next-btn')) { 23 $displaySlide.next().addClass('active'); 24 } 25 else { 26 $displaySlide.prev().addClass('active'); 27 } 28 toggleChangeBtn(); 29 }); 30 }) 31});

発生している問題

以下の記述により、インデックス番号を取得する事でスライドが最初か最後のページである場合を判断し、「←前へ」「次へ→」ボタンの表示をそれぞれ消しています。

slide.js

js

1var slideIndex = $('.slide').index($('.active')); 2$('.change-btn').show(); 3if (slideIndex == 0) { 4 $('.prev-btn').hide(); 5} else if (slideIndex == $('.slide').length -1) { 6 $('.next-btn').hide(); 7}

しかしタイトルにもありますが、スライドを複数にした事でページのインデックス番号が繋がってしまったようなのです。結果としてスライド内でページを遷移しても、思い通りに「←前へ」「次へ→」ボタンの表示が消えてくれません。

以下のコードでインデックス番号を確かめましたが、実際に繋がってしまっていました。

slide.html.erb

rails

1<li class="slide" id="ki">き</li>

slide.js

js

1$(function() { 2 var number = $('#ki'); 3 var i = $('.slide').index(number); 4 alert(i) 5}); 6 7=> 4

スライド1:「あ、い、う」の3ページ。スライド2:「か、き、く」の3ページ。
「き」のインデックス番号として1(0, 1の2番目)を期待していましたが、4(0, 1, 2, 3, 4の5番目)とアラートが出てしまいました。

試したこと

インデックス番号をそれぞれのスライドで切り分ける方法がどうしても分かりませんでしたので、代わりに以下の方法を試みました。

  1. ビュー側にて最初及び最後のページに firstPagelastPageなるクラスを各スライドに付与する。
  2. 表示されているのが最初のページの場合「前へ」ボタンを、最後のページの場合「次へ」ボタンをそれぞれ非表示にする。

slide.js

js

1var currentPage = $('.active'); 2if (currentPage.hasClass('firstPage')) { 3 $('.prev-btn').hide(); 4} else if (currentPage.hasClass('lastPage')) { 5 $('.next-btn').hide(); 6}

しかし後半で「ページ番号をクリックした際に .active クラスが付いていたスライドから .active を取り除く」と言った処理もある為、他のスライドの .active クラスも一緒に取り除かれてしまい、クリックした際に何も表示されなくなってしまいます。

slide.js

js

1$('.index-btn').click(function() { 2 $('.active').removeClass('active'); 3 var clickedIndex = $('.index-btn').index($(this)); 4 $('.slide').eq(clickedIndex).addClass('active'); 5 toggleChangeBtn(); 6});

インデックス番号をそれぞれのスライドで切り分ける方法があれば一番スマートかなと思うのですが、何か良い方法はありませんでしょうか。ご助言を頂けますと有難いです。

補足情報(FW/ツールのバージョンなど)

ruby 2.6.4p104
RubyGems 3.0.3
Rails 5.2.3
jquery 1.12.4

追記

ご回答を元にしたコードを追記致します。
ページの中身は独立して(他のスライドに依存する事なく)表示されるようになったものの、「←前へ 次へ→」ボタンのみまだ他のスライドでの動作と連動して表示されてしまいます。

slide.html.erb

rails

1<ul> 2 <li><div data-target="slide01" class="click-modal">スライド1</div> 3 <div id="slide01" class="modal-wrapper"> 4 <div class="modal"> 5 <div class="close-modal"> 6 <i class="fa fa-2x fa-times"></i> 7 </div> 8 <div class="slide-wrapper"> 9 <div class="slide-title">スライド1</div> 10 <div class="change-btn-wrapper"> 11 <div class="change-btn prev-btn">← 前へ</div> 12 <div class="change-btn next-btn">次へ →</div> 13 </div> 14 <ul class="slides"> 15 <li class="slide firstSlide active">あ</li> 16 <li class="slide">い</li> 17 <li class="slide lastSlide">う</li> 18 </ul> 19 <div class="index-btn-wrapper"> 20 <div class="index-btn">1</div> 21 <div class="index-btn">2</div> 22 <div class="index-btn">3</div> 23 </div> 24 </div> 25 </div> 26 </div> 27 </li> 28 29 <li><div data-target="slide02" class="click-modal">スライド2</div> 30 <div id="slide02" class="modal-wrapper"> 31 <div class="modal"> 32 <div class="close-modal"> 33 <i class="fa fa-2x fa-times"></i> 34 </div> 35 <div class="slide-wrapper"> 36 <div class="slide-title">スライド2</div> 37 <div class="change-btn-wrapper"> 38 <div class="change-btn prev-btn">← 前へ</div> 39 <div class="change-btn next-btn">次へ →</div> 40 </div> 41 <ul class="slides"> 42 <li class="slide firstSlide active">か</li> 43 <li class="slide">き</li> 44 <li class="slide lastSlide">く</li> 45 </ul> 46 <div class="index-btn-wrapper"> 47 <div class="index-btn">1</div> 48 <div class="index-btn">2</div> 49 <div class="index-btn">3</div> 50 </div> 51 </div> 52 </div> 53 </div> 54 </li> 55</ul>

slide.js

js

1$(document).on('turbolinks:load', function() { 2 $(function() { 3 function toggleChangeBtn(dir){ 4 var dir = $(this).parents('.slide-wrapper'); //対象のクラスを絞りたいが、絞れていない? 5 var currentSlide = dir.find('.active'); // 表示されているスライドをcurrentSlideと名付ける。 6 $('.change-btn').show(); // 「前へ」と「次へ」は常に表示する。 7 if (currentSlide.hasClass('firstSlide')) { 8 dir.find('.prev-btn').hide(); // 表示されているスライドが最初のページの場合「前へ」は非表示。 9 } else if (currentSlide.hasClass('lastSlide')) { 10 dir.find('.next-btn').hide(); // 表示されているスライドが最後のページの場合「次へ」は非表示。 11 } 12 } 13 14 $('.index-btn').click(function() { 15 var dir = $(this).parents('.slide-wrapper'); //対象のクラスを絞る。 16 dir.find('.active').removeClass('active'); // 表示されていたスライドから.activeを取り除く。 17 var clickedIndex = $('.index-btn').index($(this)); 18 $('.slide').eq(clickedIndex).addClass('active'); // クリックされたページ番号と同じインデックス番号を持つスライドに.activeを付与する。 19 toggleChangeBtn(dir); 20 }); 21 22 $('.change-btn').click(function() { 23 var dir = $(this).parents('.slide-wrapper'); //対象のクラスを絞る。 24 var $displaySlide = dir.find('.active'); // 表示されているスライドをdisplaySlideと名付ける。 25 $displaySlide.removeClass('active'); // .activeが付いていたスライドから.activeを取り除く。 26 if ($(this).hasClass('next-btn')) { 27 $displaySlide.next().addClass('active'); // .next-btnクラスがついていたら、その次のスライドにactiveを付与する。 28 } 29 else { 30 $displaySlide.prev().addClass('active'); // .prev-btnクラスがついていたら、その前のスライドにactiveを付与する。 31 } 32 toggleChangeBtn(dir); 33 }); 34 }) 35});

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

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

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

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

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

guest

回答1

0

$(this)を使って対象となるセレクタだけを制御すればいいのではないかと思います。
このイベント制御だと同じクラスの全セレクタが対象となってしまってますよ。

このようにparentsメソッドを使って対象のセレクタの範囲を絞るといいでしょう。

js

1 $('.change-btn').on("click",function() { 2 var dir = $(this).parents('.slide-wrapper'); //対象のクラスを絞る 3 //省略 4 toggleChangeBtn(dir); //対象のセレクタを関数の引数とする 5 //省略

これでテストしてうまくいってます。

投稿2021/05/31 00:37

編集2021/06/01 09:07
FKM

総合スコア3647

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

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

punchan36

2021/06/01 07:09

有難うございます!ご回答を元に試行錯誤しております。 元のコードではなく「試したこと」に記載致しましたコードを $(this) を使いながら改良しているのですが、まずそちらの理解で合っておりますでしょうか。 var currentSlide = $('.active'); この定義のせいで、'.active'クラスが付いている他のスライドのページにまで変更を加えてしまっているのは理解出来ます。 これを「今表示されているスライド」と言う定義にしたいのですが、そこがよく分かりません…。
punchan36

2021/06/02 08:29

有難うございます! まだ上手く動いてくれません。状況を追記致しましたので、可能でありましたらご助言頂けますと有難いです。
FKM

2021/06/02 09:09 編集

dirはその選択したセレクタなので、それの下にある子要素は全部dirで縛っていく必要があります。 なので変数dirは関数にも引数として持ち運んでください。その関数内にあるslideクラスやactiveクラス、それにprev-bthクラス、next-btnクラスもそのdirセレクタの子孫要素である必要があります。 単体だとうまくいったのに、複数だとうまくいかなくなったということは、つまり、選択した親要素配下の子孫要素だけをうまく絞れていないということです。
punchan36

2021/06/02 09:49 編集

有難うございます!ご指摘を頂いてから間違いに気が付きました。 二つの関数に引数を指定する事で動かす対象を「表示したスライドのみ」に絞り込んだつもりなのですが、まだ動きが以前と変わりません…。理解したつもりでしたが、どこかおかしかったでしょうか。。 飲み込みが悪く、何度も申し訳ありません。 ビューファイルは特にいじっておらず、修正したjsコードのみ追記内で編集致しました。
FKM

2021/06/02 10:17

toggleChangeBtn(dir){…}としないと、dirセレクタを持っていけませんよ。
punchan36

2021/06/03 01:54

有難うございます。 まだ試行錯誤しております…。 今回改めて引数を使った事で、toggleChangeBtnの処理が指定したクラスの範囲内で行われていると思います(追記内のslide.jsを再度編集致しました)。 ただ結果が変わらないのは、ページ番号や次へボタンを押したときの「.activeクラスを取り除く」と言った処理が依然として他のセレクタも含んでしまっているからなのでしょうか…。
FKM

2021/06/03 01:57

.activeの部分も全部dirの下にあるはずなので、dir.find('.active')…と記述しないといけません。とにかく、slide-wrapperの子孫にあるものは全部dirに紐付けられる要素です。よその親の子孫をもらってはいけません。
punchan36

2021/06/03 03:34

有難うございます! これでページの中身は独立して(他のスライドに依存する事なく)表示されるようになりました! ただ一点だけ、「←前へ 次へ→」ボタンのみまだ他のスライドでの動作と連動して表示されてしまいます。 toggleChangeBtn関数内の動作も「表示したスライドのみ」に絞り込んで行いたいのですが、恐らくこの関数がクリックイベントではない為 $(this) を認識してくれていないのかなと思いました…。 何か良い記述の仕方はありませんでしょうか…?(現在のコードを追記内にて記述致しました。)
FKM

2021/06/03 04:08

2つのボタンもdirの子孫です。
punchan36

2021/06/03 05:21

「前へ」と「次へ」に関する記述を以下の様に書き換えましたがダメです…。こう言う事ではないのでしょうか…? if (currentSlide.hasClass('firstSlide')) { dir.find('.prev-btn').hide(); } else if (currentSlide.hasClass('lastSlide')) { dir.find('.next-btn').hide(); }
FKM

2021/06/03 05:25

ifの判定文を一番初期の状態に戻して下さい。
punchan36

2021/06/03 05:52

最初に書いたif文とはこちらでしょうか…これで同様に動かなかったのですが。。 var currentSlide = dir.find('.active'); if (currentSlide.hasClass('firstSlide')) { $('.prev-btn').hide(); } else if (currentSlide.hasClass('lastSlide')) { $('.next-btn').hide(); } こちらの事ではないですよね。意図が読み取れず申し訳ありません。 var slideIndex = dir.find('.slide').index($('.active')); if (slideIndex == 0) { dir.find('.prev-btn').hide(); } else if (slideIndex == $('.slide').length -1) { dir.find('.next-btn').hide(); }
FKM

2021/06/03 06:04 編集

下の方で間違いないですが、今まで自分がアドバイス送ったことをよく注意して振り返れば、そのif判定文も問題があることはわかるはずです。 dirは何のために指定したのか、それは複数あるslide-wrapperクラスから一つだけ絞り込むためです。なので、そのslide-wrapperクラスの子孫にあるクラスは全部絞り込む必要があります。
punchan36

2021/06/03 06:50

以下の様に slide-wrapper 以下の全てのクラスを dir で絞り込んだつもりですが、まだ動きません…。 おかしな箇所がありますでしょうか。ここまで一歩一歩になってしまい本当に申し訳ありません。 var dir = $(this).parents('.slide-wrapper'); var slideIndex = dir.find('.slide').dir.index('.active'); if (slideIndex == 0) { dir.find('.prev-btn').hide(); } else if (slideIndex == dir.find('.slide').length -1) { dir.find('.next-btn').hide(); }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問