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

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

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

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

Q&A

解決済

3回答

1478閲覧

HTML文書をJavaScriptで開閉させたい

AGadget

総合スコア60

JavaScript

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

0グッド

0クリップ

投稿2019/02/03 15:31

日記をHTMLで書いています。
HTMLとCSSを勉強して見やすくすることができたのですが、内容が多くなってきたために各日付ごとに開閉させたいと考えています。
完成像としてはスマートフォン版Wikipediaのように開閉できる感じを考えています。
そこで色々と試してみて思った通りに動くようになったのですが、もう少し綺麗(?)に書きたいなと考えております。

以下にHTMLとJavaScriptのコードを挿入します。

当初は、このような感じでした。

HTML

1<body> 2 <h2 id="s0_head">2019/01/01</h2> 3 <p id="s0_body">いろはにほへと</p> 4 <h2 id="s1_head">2019/01/02</h2> 5 <p id="s1_body">ちりぬるを</p> 6</body>

JavaScript

1const s0_head = document.getElementById("s0_head"); 2const s0_body = document.getElementById("s0_body"); 3const s1_head = document.getElementById("s1_head"); 4const s1_body = document.getElementById("s1_body"); 5let s0 = 0; 6let s1 = 0; 7s0_head.addEventListener("click", ()=>{ 8 if(s0 == 0){ 9 s0_body.style.display = "flex"; 10 s0 = 1; 11 }else{ 12 s0_body.style.display = "none"; 13 s0 = 0; 14 } 15}); 16s1_head.addEventListener("click", ()=>{ 17 if(s1 == 0){ 18 s1_body.style.display = "flex"; 19 s1 = 1; 20 }else{ 21 s1_body.style.display = "none"; 22 s1 = 0; 23 } 24});

JavaScriptに配列というものがあると知って以下のようにしました。
これが今の状態となります。

HTML

1<body> 2 <h2 class="s_head">2019/01/01</h2> 3 <p class="s_body">いろはにほへと</p> 4 <h2 class="s_head">2019/01/02</h2> 5 <p class="s_body">ちりぬるを</p> 6</body>

JavaScript

1const s_head = document.getElementsByClassName("s_head"); 2const s_body = document.getElementsByClassName("s_body"); 3let s = [0, 0]; 4s_head[0].addEventListener("click", ()=>{ 5 if(s[0] == 0){ 6 s_body[0].style.display = "flex"; 7 s[0] = 1; 8 }else{ 9 s_body[0].style.display = "none"; 10 s[0] = 0; 11 } 12}); 13s_head[1].addEventListener("click", ()=>{ 14 if(s[1] == 0){ 15 s_body[1].style.display = "flex"; 16 s[1] = 1; 17 }else{ 18 s_body[1].style.display = "none"; 19 s[1] = 0; 20 } 21});

この状態から繰り返している処理をまとめたいのですが失敗が続いています。
正規表現を使って、**s_head[/*/].addEventListener()...**のようにしてみたり、for文を使って、**for(i = 0; i < s_head.length; i++){s_head[i].addEventListener()...}**としてみたり、forEach文というものを試してみたりしたのですが、いずれもエラーが出て動かない状態です。

色々と調べてみたのですが配列を使ってメニューを作るといった旨の記事が見当たらないので、もしかして、そもそもこういった作り方は根本的に間違っているのではないかと考えています。

最後になりますが質問は2点です。

  1. 配列を使ってメニューをまとめたいのですが、どのようにすればよいでしょうか?
  2. そもそも配列を使ってメニューを作るのは不適切なのでしょうか?

長文となりましたが、ご回答お待ちしております。
よろしくお願いします。

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

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

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

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

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

kszk311

2019/02/03 15:38

jQueryの方が比較的簡単にできるかと思いますが、jQueryは使わず、素のJavascriptでの実装ということで良いですか?
AGadget

2019/02/04 12:42

はい、そうですね。 jQueryが、とても便利だという話は聞いていたのですが、とりあえずは素のJavaScriptでやっていこうと思っています。
guest

回答3

0

ベストアンサー

こんにちは。

いろいろな修正が考えられそうですので、あくまで一案ということで回答します。以下の修正案ではHTMLも修正対象としています。

html

1<div class="diary"> 2 <h2 class="s_head">2019/01/01</h2> 3 <p class="s_body">いろはにほへと</p> 4</div> 5 6<div class="diary"> 7 <h2 class="s_head">2019/01/02</h2> 8 <p class="s_body">ちりぬるを</p> 9</div>

javascript

1document.querySelectorAll('.diary').forEach( 2 diary => { 3 const h = diary.querySelector('.s_head'), 4 b = diary.querySelector('.s_body'); 5 6 h.addEventListener('click', () => { 7 b.style.display = b.style.display === 'flex' ? 'none' : 'flex'; 8 }); 9 } 10);

修正の考え方としては、

  • HTMLのほうで、<h2><p>を一組にして <div>で囲ってこれのクラスを diaryとします。

  

  • JS では、diaryクラスのすべての <div>を取得して、その中にある <h2><p>について期待する動作を設定します。

 

ご質問にあった、

  1. 配列を使ってメニューをまとめたいのですが、どのようにすればよいでしょうか?
  1. そもそも配列を使ってメニューを作るのは不適切なのでしょうか?

についてですが、上記のコードのように、配列を別途追加しなくても要件を満たすコードは書けます。ご質問のコードにある配列sは、各本文が開いているか、閉じているかを示すフラグの配列ですが、フラグを追加するたびに、ロジックを追いにくくなりバグを生みやすくなると思ったほうがよいかと思います。

以上参考になれば幸いです。

追記

HTMLのほうは修正せずに、JSのみ修正する案です。

javascript

1document.querySelectorAll('.s_head').forEach( 2 h => { 3 h.addEventListener('click', 4 () => { 5 const b = h.nextElementSibling; 6 b.style.display = b.style.display === 'flex' ? 'none' : 'flex'; 7 } 8 ); 9 } 10);

投稿2019/02/03 18:33

編集2019/02/04 01:19
jun68ykt

総合スコア9058

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

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

AGadget

2019/02/04 13:08

回答ありがとうございます。 全体を包んで中の要素に色々するという発想がありませんでした。 これからは様々な角度から試行錯誤していきたいと思います。
jun68ykt

2019/02/04 13:40

どういたしまして。 ひとまず前に進めていけそうな感じですね、よかったです????
guest

0

JavaScriptのみだと以下のようになるかと思います。
考え方を最後に載せています。

html

1<h2 class="accordion">2019/01/01</h2> 2<p class="content" style="display:none">いろはにほへと</p> 3 4<h2 class="accordion">2019/01/02</h2> 5<p class="content" style="display:none">ちりぬるを</p>

JavaScript

1const accordion = document.querySelectorAll('.accordion'); 2 3for(let i=0; i < accordion.length; i++){ 4 accordion[i].addEventListener('click',function(event){ 5 let content = this.nextElementSibling; 6 if(content.style.display === 'none'){ 7 content.style.display = 'block'; 8 }else{ 9 content.style.display = 'none'; 10 } 11 }); 12}

考え方
・一つ一つの要素にidを与えているときりがないので、class(accordionとする)を代わりに与える
・class="accordion"をもつ要素をリストとしてとってくる。->querySelectorAll
・それぞれのaccordionをもつ要素に対してクリックしたときの動作を追加。-> for, addEventListener
・クリックしたときに実際に動作が生じる要素(content)を選択->nextElementSibling
・その要素がdisplay="none"ならblockに。blockならnoneに。

実際の動作:
https://codepen.io/unotalk/pen/aXwdNV

jQueryを使えばもっと簡単に作れるのでそちらも書いておきます。

jQuery

1$('.accordion').each(function(){ 2 $(this).on('click',function(){ 3 $(this).next().toggle('slow'); 4 }); 5} 6);

実際の動作
https://codepen.io/unotalk/pen/exRJQy

投稿2019/02/03 17:52

編集2019/02/03 18:06
unotalk

総合スコア124

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

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

AGadget

2019/02/04 13:07

回答ありがとうございます。 今までgetElement系での取得しか知りませんでしたので、querySelectorAllを始めとして色々と勉強になりました。
guest

0

直接の回答ではないですが、

内容が多くなってきたために各日付ごとに開閉させたいと考えています。

開閉はいいのですが、HTMLの量が減るわけではありません。
日記をHTML直に書くのではなくDBに登録する仕組みにされてはどうでしょうか。
そのほうがAjaxを利用するなどしてもっと軽快に動くWeb日記ができると思います。
一覧→詳細とページを進むようにすれば、それこそ1日記何万、何百万と字数がない限り折りたたむ必要もないですし。

投稿2019/02/04 00:51

m.ts10806

総合スコア80842

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

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

AGadget

2019/02/04 13:11

回答ありがとうございます。 ちょうどPCスクールでDBの勉強をしておりますので、ある程度技術力が付いたらDBに移行しようと思います。 非同期遷移にも興味がありますので、いつか挑戦してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問