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

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

ただいまの
回答率

88.80%

Javascript(アコーディオン作成)でfor文を使ったコードの簡略化について。

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 596
退会済みユーザー

退会済みユーザー

JavascriptでJQueryを使わず、アコーディオンを作っています。
そこで、一旦コードは完成しているのですが、これをもっと簡略化することになりました。for文とquerySelectorAllを使うとのことなのですが、どちらも使ってみると、clickイベントがうまく反映されません。
どうすればうまくまとめられますか?
一旦完成されているコードは下記のようになっています。
dtをクリックしたらddを表示、または非表示、HTMLを読み込んだ際は非表示から始めたいです。
初めて質問するので、わかりにくかったらすみません…。

var a=document.getElementById("art_content");
a.style.display="none";
document.getElementById("art").onclick=function(e){
var str = document.getElementById("art_content");
if(str.style.display == "none"){
  str.style.display="block";
}else{
  str.style.display="none";
}
}
​
var b=document.getElementById("science_content");
b.style.display="none";
document.getElementById("science").onclick=function(){
var str = document.getElementById(“science_content");
if(str.style.display == "none"){
  str.style.display = "block";
}else{
  str.style.display = "none";
  }
}
​
var c=document.getElementById(“math_content");
c.style.display="none";
document.getElementById("math").onclick=function(){
var str = document.getElementById("math_content");
if(str.style.display == "none"){
  str.style.display = "block";
}else{
  str.style.display = "none";
  }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2019/02/15 13:47

    再現確認に必要なのでHTML、CSSもあわせてご提示ください。

    キャンセル

  • m.ts10806

    2019/02/15 13:49

    ちなみに「うまくいかない」だけでは何が起きているか伝わりませんし、そのコードを提示しないことには「丸投げ作業依頼」に等しい内容となってしまいます。
    内容ご調整ください。

    キャンセル

回答 4

+3

イベントはルートで監視します
クラスに"accordion"があれば複数動作します

<!DOCTYPE html>
<title>?</title>
<meta charset="utf-8">
<style>
dl.accordion dt { cursor: pointer; }
dl.accordion dd { display: none; }
dl.accordion dt.active+dd { display: block; }
</style>

<body>
<dl class="accordion">
<dt>a<dd>abcdefg
<dt>1<dd>1234567
<dt>ABC<dd>ABCDEFGHIJK
</dl>

<script>

function disp (dt) {
  let p = dt.parentNode;
  if (p.classList.contains ('accordion'))
    dt.classList.toggle ('active');
}


function handler (event) {
  let e = event.target;
  if ('DT' === e.tagName)
    disp (e);
} 

document.addEventListener ('click', handler, false);

</script>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/15 15:37 編集

    そういえば、 $(document).on(eventName, target, function); の考えってこれだったね

    キャンセル

  • 2019/02/15 16:26

    jQuery ? そんなの知らな~い。素でできるようなことを・・・

    キャンセル

+2

こんなことかな?[動くサンプル]

javascript

var dts = document.getElementsByTagName('dt');
for (var dt of dts) {
    console.log(dt);
    dt.addEventListener("click", function(e) {
        e.target.classList.toggle("active");
    });
}

css 

dt {
    cursor: pointer;
}

dd {
    display: none;
}

dt.active+dd {
    display: block;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/15 14:22

    サンプルと同様の動きであってます!
    ただ、asahina1979さんのコードをjavascriptに入れてもクリックした時の表示、非表示の動作が切り替わりません...。

    キャンセル

  • 2019/02/15 14:26

    cssを前提にしておられるので。

    キャンセル

  • 2019/02/15 14:27 編集

    それか、HTMLの構成が間違えてるのね

    HTML の構造としては

    dl
    ├dt
    ├dd

    が正常で

    dl
    ├dt
    │├dd

    は不正です。

    After dt or dd elements inside dl elements.

    https://html.spec.whatwg.org/multipage/grouping-content.html#the-dd-element

    キャンセル

checkベストアンサー

+1

①idにart_contentscience_contentmath_contentを持つ要素を、querySelectorAllで取得
②取得した要素の大きさ分繰り返し文(for)で回す
③それぞれの要素に対して、質問文のコードの共通部分を適用させる

ざっくり以下のようなイメージ

var list = document.querySelectorAll(/*三つのID要素を取得するためのセレクタ*/);

for(var i=0;i<list.length;i++){
//共通処理
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/15 14:41

    (papinianus 様の回答ではなく…!?)
    (他の回答者様と比べてほぼコード書いてないしこんなのがBAでいいのだろうか…。)

    キャンセル

  • 2019/02/15 14:45

    papinianusさんのコードでも正常に動作したのですが、如何せん私には複雑で...
    パッとわかりやすかったmadoka9393さんのコードを選ばせていただきました。
    もっと詳しくわかる方でしたら、papinianusさんのコードの方がいいのかもしれないのですが。。

    キャンセル

  • 2019/02/15 14:52

    こちらとしては無理やり「querySelectorAll」と「for」を使う例として出しただけなので…。
    とりあえずうまいこといっているのでしたらまぁよかったです。

    キャンセル

+1

<html>
<body>
<dl>
<dt id='art'>a</dt>
<dd id='art_content'>ac</dd>
<dt id='science'>s</dt>
<dd id='science_content'>sc</dd>
<dt id='math'>m</dt>
<dd id='math_content'>mc</dd>
</dl>
<script language='javascript'>
['art','math','science'].forEach(id => {
  document.querySelector(`#${id}_content`), elm => elm.style.display="none");
  document.querySelector(`#${id}`).addEventListener('click', elm => {
    const child = document.querySelector(`#${id}_content`)
    child.style.display = child.style.display === 'none' ? 'block' : 'none'
  });
});
</script>
</body>
</html>

欲しいであろうもの

<html>
<body>
<dl>
<dt id='art'>a</dt>
<dd id='art_content'>ac</dd>
<dt id='science'>s</dt>
<dd id='science_content'>sc</dd>
<dt id='math'>m</dt>
<dd id='math_content'>mc</dd>
</dl>
<script language='javascript'>
const dds = document.querySelectorAll('dd');
for(let i = 0; i < dds.length; i++) {
  dds[i].style.display = 'none';
}
const dts = document.querySelectorAll('dt');
for(let i = 0; i < dts.length; i++) {
  const id = dts[i].id;
  dts[i].addEventListener('click', elm => {
    const child = document.querySelector(`#${id}_content`)
    child.style.display = child.style.display === 'none' ? 'block' : 'none'
  });
}
</script>
</body>
</html>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/15 14:25

    asahina1979様
    すみませんでした。直しました。

    yoshino543様
    forはまだ使えると思いますが、idベースで動いている以上、querySelectorAllは出番なくないですか?idなんで、Allって言ったところで1個しか取れないわけで、1個しか取れないと分かってるなら、querySelectorにしたほうが要素そのものが取れるので。

    キャンセル

  • 2019/02/15 14:48

    私もあまり使い道がわからず、悩んでいました、
    メンターからの指示でしたのでわざと使おうとしてたのですが、そうですよね、聞いてみます。

    キャンセル

  • 2019/02/15 14:51

    たぶん、こういうことが言いたいんだろうという忖度コードを追記してます。

    キャンセル

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

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る