🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

jQuery

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

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

3回答

785閲覧

jQueryの記述をシンプルにしたい

futon

総合スコア10

JavaScript

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

jQuery

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

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2019/12/20 02:58

初心者です。
以下のようにリストをアコーディオンにしています。
mainもsubもbuttonを押すとappearが出現し、cssのopenというクラスを付与します。
openが付与されると、cssのcontentでbuttonの文章が変わります。

質問ですが、jQueryで全く同じ内容の文章を2回書くのはスマートではないので、もっとよい書き方を教えていただきたいと思い投稿させていただきました。
よろしくお願いいたします。

【html】 <div class="contents_ttl"> タイトル </div> <div id="main" class="contents_box"> <ul> <li> <div class="txt">aaaaa</div> </li> <li> <div class="txt">bbbbb</div> </li> <li> <div class="txt">ccccc</div> </li> <li> <div class="txt">ddddd</div> </li> <li class="appear1"> <ul> <li> <div class="contents_ttl"> タイトル </div> </li> <li> <div class="txt">eeeee</div> </li> <li> <div class="txt">fffff</div> </li> <li> <div class="txt">ggggg</div> </li> <li> <div class="txt">hhhhh</div> </li> </ul> </li> <li class="readmore button1"> <a href="#"><span></span></a> </li> </ul> </div> <div class="contents_ttl"> タイトル </div> <div id="sub" class="contents_box"> <ul> <li> <div class="txt">aaaaa</div> </li> <li> <div class="txt">bbbbb</div> </li> <li> <div class="txt">ccccc</div> </li> <li> <div class="txt">ddddd</div> </li> <li class="appear2"> <ul> <li> <div class="contents_ttl"> タイトル </div> </li> <li> <div class="txt">eeeee</div> </li> <li> <div class="txt">fffff</div> </li> <li> <div class="txt">ggggg</div> </li> <li> <div class="txt">hhhhh</div> </li> </ul> </li> <li class="readmore button2"> <a href="#"><span></span></a> </li> </ul> </div>
【jQuery】 $(function(){ $('.appear1').hide(); $('.button1').click(function(){ $('.appear1').slideToggle(); $(this).toggleClass('open1'); return false; }); }); $(function(){ $('.appear2').hide(); $('.button2').click(function(){ $('.appear2').slideToggle(); $(this).toggleClass('open2'); return false; }); });
【css】 .contents_box ul li.readmore a span::after { content: "続きを読む"; } .contents_box ul li.open2 a span::after { content: "閉じる"; }

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

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

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

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

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

futon

2020/01/24 06:20

質問者です。 返答が遅くなってしまい申し訳ありません! $(function(){ ... }の使い方、勘違いしているかもしれません…。 ただ、リンク先も拝見しましたが、初心者のためどのように間違っているのかがわかりません…。 もしよろしければご指摘いただけると大変ありがたいです。
guest

回答3

0

ボタンとそれをクリックすることで展開される li 要素が隣接しているため、 siblings メソッドprev メソッドなどを使用してボタンと li 要素を関連付けることが出来ます。これを利用すると、以下のように一度の記述で複数のトグルメニューに対応出来ます (動作確認用リンク)。

HTML

1<div class="contents_ttl"> 2 タイトル 3</div> 4<div id="main" class="contents_box"> 5 <ul> 6 <li> 7 <div class="txt">aaaaa</div> 8 </li> 9 <li> 10 <div class="txt">bbbbb</div> 11 </li> 12 <li> 13 <div class="txt">ccccc</div> 14 </li> 15 <li> 16 <div class="txt">ddddd</div> 17 </li> 18 <li class="appear"> 19 <ul> 20 <li> 21 <div class="contents_ttl"> 22 タイトル 23 </div> 24 </li> 25 <li> 26 <div class="txt">eeeee</div> 27 </li> 28 <li> 29 <div class="txt">fffff</div> 30 </li> 31 <li> 32 <div class="txt">ggggg</div> 33 </li> 34 <li> 35 <div class="txt">hhhhh</div> 36 </li> 37 </ul> 38 </li> 39 <li class="readmore button"> 40 <a href="#"><span></span></a> 41 </li> 42 </ul> 43</div> 44 45<div class="contents_ttl"> 46 タイトル 47</div> 48<div id="sub" class="contents_box"> 49 <ul> 50 <li> 51 <div class="txt">aaaaa</div> 52 </li> 53 <li> 54 <div class="txt">bbbbb</div> 55 </li> 56 <li> 57 <div class="txt">ccccc</div> 58 </li> 59 <li> 60 <div class="txt">ddddd</div> 61 </li> 62 <li class="appear"> 63 <ul> 64 <li> 65 <div class="contents_ttl"> 66 タイトル 67 </div> 68 </li> 69 <li> 70 <div class="txt">eeeee</div> 71 </li> 72 <li> 73 <div class="txt">fffff</div> 74 </li> 75 <li> 76 <div class="txt">ggggg</div> 77 </li> 78 <li> 79 <div class="txt">hhhhh</div> 80 </li> 81 </ul> 82 </li> 83 <li class="readmore button"> 84 <a href="#"><span></span></a> 85 </li> 86 </ul> 87</div>

CSS

1.contents_box ul li.readmore a span::after { 2 content: "続きを読む"; 3} 4 5.contents_box ul li.open a span::after { 6 content: "閉じる"; 7}

jQuery

1$(function() { 2 $('.appear').hide(); 3 $('.button').click(function() { 4 $(this).prev('.appear').slideToggle(); 5 $(this).toggleClass('open'); 6 return false; 7 }); 8});

投稿2019/12/20 04:05

編集2019/12/20 04:08
s8_chu

総合スコア14731

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

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

futon

2020/01/24 05:37

質問者です。 お礼が遅くなってしまいまして申し訳ありませんでした! prevを使った書き方、とてもシンプルで私の知りたかった答えです! 動作確認まで作成してくださり、ありがとうございました!
guest

0

ベストアンサー

今回の質問内容に「愚直に対応する」ならば
[1, 2]という配列を作ったりfor文で回せば良い。

js

1// 配列を使う場合 2[1, 2].forEach(function(i){ 3 $('.appear' + i).hide(); 4 $('.button' + i).click(function(){ 5 $('.appear' + i).slideToggle(); 6 $(this).toggleClass('open' + i); 7 return false; 8 }); 9}); 10 11// for文で解決する場合 12// let iという宣言にしなかったらclickイベントが発火した時に常にi=2になり動作がおかしくなるんだっけか? 13// 恐らくIEでは懸念の現象が発生するかもしれない 14for (let i = 1; i <= 2; i++) { 15 $('.appear' + i).hide(); 16 $('.button' + i).click(function(){ 17 $('.appear' + i).slideToggle(); 18 $(this).toggleClass('open' + i); 19 return false; 20 }); 21}

ただし、「アコーディオンメニュー」をUXで考える場合、
閉じた本と栞みたいな関係にしたいはず……

となれば2個で収まるはずがないので、
上記の対応では不足している・微妙という結論になってしまうだろう。

そういう意味で「jQueryの記述をシンプルにしたい」として
今回の質問を出したのは素晴らしいタイミングだと思う。


結論から言えば「HTMLの作りが悪いので、汎用的になるように作り直しましょう」となる。
どうやって?
カギとなるのはクラス

クラスとは、級、階級、等級、格、類、分類、種類、学級、科目、授業などの意味を持つ英単語。 (IT用語辞典 e-Wordsより)

jQueryは「特定のクラスを持つ要素をコンポーネント」として作り変える。
今回は「アコーディオンメニュー」を実装したいと言っているので、
包む用のdivを一つ足してアコーディオンメニュー空間を作ってみよう。

html

1<div class="contents_ttl"> 2 タイトル 3</div> 4<div id="main" class="contents_box accordion_menu"> 5 <ul> 6 <li> 7 <div class="txt">aaaaa</div> 8 </li> 9 <li> 10 <div class="txt">bbbbb</div> 11 </li> 12 <li> 13 <div class="txt">ccccc</div> 14 </li> 15 <li> 16 <div class="txt">ddddd</div> 17 </li> 18 <li class="appear"> 19 <ul> 20 <li> 21 <div class="contents_ttl"> 22 タイトル 23 </div> 24 </li> 25 <li> 26 <div class="txt">eeeee</div> 27 </li> 28 <li> 29 <div class="txt">fffff</div> 30 </li> 31 <li> 32 <div class="txt">ggggg</div> 33 </li> 34 <li> 35 <div class="txt">hhhhh</div> 36 </li> 37 </ul> 38 </li> 39 <li class="readmore button"> 40 <a href="#"><span></span></a> 41 </li> 42 </ul> 43</div>

一つの要素は半角スペースで区切ることで複数のクラスを名乗っても良い。
それを利用してcontents_box accordion_menuという2クラスにした。

このアコーディオンメニューというクラスはCSSでは何も意味を持たないが、
JavaScript(jQuery)を使って素晴らしいアコーディオンメニューに生まれ変わる。

jQueryには.each()という機能が存在し、
まるでfor文のように各々に要素に対して処理を施すことができる。
また、特定の要素を覚えておく事で、そこから子孫要素を探すfindメソッドを使う事で簡単にコンポーネント化が実現出来るだろう。

js

1// ボタンを連打された時に変な挙動になる気がしたので、 2// 先受けになるがフラグを用意しておいた 3$('.accordion_menu').each(function(){ 4 var $elm = $(this); 5 var isOpened = false; 6 $elm.find('.appear').hide(); 7 $elm.find('.button').click(function(){ 8 isOpened = !isOpened; 9 if (isOpened) { 10 $elm.find('.appear').slideDown(); 11 $(this).addClass('open'); 12 } else { 13 $elm.find('.appear').slideUp(); 14 $(this).removeClass('open'); 15 } 16 return false; 17 }); 18});

動作は未検証だが、これでアコーディオンメニューというコンポーネントの作成は完了。
後はHTML上で.accordion_menuクラスを付与してやり、
.buttonクラスをポチポチすれば.appearクラスの表示・非表示が切り替わるようになる。
アコーディオンが増えてもHTMLの改修のみで完了するようになる。

jQuery(JS)とHTMLとCSSは決してひとつでは成り立たない。
不味いHTMLの設計をJSとCSSのみで吸収するとコードが歪になり、
継ぎ接ぎの布を充てがうようなコードを納品することになってしまう。

良いHTMLならばeachやfor文でスパッと一撃で解決出来るコードになる。
これを目指して相互に少しずつ改良していくようにしよう。
どちらの設計力も身につけば、一撃で素晴らしいHTMLやJSコードを作って納品出来るようになる。

投稿2019/12/20 13:04

編集2019/12/20 13:16
miyabi-sun

総合スコア21203

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

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

Plan-B.0306

2019/12/21 08:38

昨日、高評価を押した者ですが、一部の隙もないほどの完璧な回答で脱帽しました。 私は質問者さんではありませんが勉強になりました。 ありがとうございます。
futon

2020/01/24 06:36 編集

質問者です。 お礼が遅くなってしまいまして申し訳ありませんでした! 教えていただいた3パターンともに私が知りたかった答えでしたが、とくに「アコーディオンメニューというコンポーネントを作る」という考え方、とても勉強になりました。 あるものに対して無理やり動作を付けるのではなく、設計からきちんと考えなくてはならないですね。 配列とfor文については理解出来ましたが、最後に教えていただいたのは読み解いて理解を深めたいと思います。 ありがとうございました!
guest

0

共通のクラスをつけて、クリックイベントはその共通クラスに対して付ければ良いかと。
んで、設定した値で、分岐させればいいです。

html

1<li class="readmore buttonRead" data-buttonid="1"> 2 <a href="#"><span></span></a> 3</li> 4 5<li class="readmore buttonRead" data-buttonid="2"> 6 <a href="#"><span></span></a> 7</li>

javascript

1$(function(){ 2 3$('.buttonRead').hide().click(function(){ 4 const buttonId = this.dataset.buttonid; 5 $('.appear' + buttonId).slideToggle(); 6 $(this).toggleClass('open' + buttonId); 7 return false; 8}); 9 10});

投稿2019/12/20 04:12

編集2019/12/20 04:16
miyabi_takatsuk

総合スコア9555

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

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

futon

2020/01/24 06:36 編集

質問者です。 お礼が遅くなってしまいまして申し訳ありませんでした! カスタムデータ属性を使うということでしょうか。 このままコピペでは動作しませんでしたが、私が理解出来ていないせいだと思いますので、読み解いて理解を深めたいと思います。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問