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

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

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

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

Q&A

解決済

1回答

597閲覧

javascriptでアコーディオンを実装したい

kitty

総合スコア15

JavaScript

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

0グッド

1クリップ

投稿2019/05/01 05:05

編集2019/05/01 06:36

お世話になります。javascript初心者です。
現在、jqueryで書いた物を、勉強のためjavascriptで書いているところです。

やりたいこと

・javascriptでアコーディオンを実装したい
・その際、アコーディオンは複数あるので、idではなく該当classをクリックしたら、
その隣の要素を出現させたい。
・最終的には要素の出し方はslidedown/upさせたいが、
そもそもトリガーをクリックしてもalert処理さえ実装できていないので、
まずはalertを出したい。

参考サイト

https://memocarilog.info/jquery/7300
→こちらのサイトの通りidで作成すると、「cloneNode」のエラーはでず、きちんと動きます。
ただし今回のようにclassで処理をすると「cloneNode」のエラーが発生してしまい
それ以降の処理が動きません。

###HTML

html

1 <ul class="c-header-gnavi__list"> 2 <li class="c-header-gnavi__item js-accordion-box"> 3 <span class="c-header-gnavi__link js-accordion-trigger"><span class="c-header-gnavi__link-inner">アコーディオントリガー</span></span> 4 <ul class="sp js-accordion-items"> 5 <li class="c-mega-navi__item"><a href="">アコーディオン子要素1</a></li> 6 <li class="c-mega-navi__item"><a href="">アコーディオン子要素2</a></li> 7 <li class="c-mega-navi__item"><a href="">アコーディオン子要素3</a></li> 8 </ul> 9 </li> 10 <li class="c-header-gnavi__item"> 11 <span class="c-header-gnavi__link js-accordion-trigger"><span class="c-header-gnavi__link-inner">アコーディオントリガー2</span></span> 12 <ul class="sp js-accordion-items"> 13 <li class="c-mega-navi__item"><a href="">アコーディオン子要素素1</a></li> 14 <li class="c-mega-navi__item"><a href="">アコーディオン子要素2</a></li> 15 <li class="c-mega-navi__item"><a href="">アコーディオン子要素3</a></li> 16 </ul> 17 </li> 18 </ul>

javascript(エラーがでる)

※一旦スライドダウン・アップの処理は置いておいて、まずは('.js-accordion-trigger')をクリックしたらアラートが出るようにしたいです。(ただし、最終的にはクリックしたら、スライドダウン+アップ処理をする前提で記述したいです)

javascript

1window.onload = function() { 2 const accrodionTrigger = document.getElementsByClassName('js-accordion-trigger'); 3 const accrodionItems = document.getElementsByClassName('js-accordion-items'); 4 5 for (let i = 0;i < accrodionTrigger.length;i++) { 6 const accrodionItemsCopy = accrodionTrigger.nextElementSibling.cloneNode(true); 7 accrodionItems.parentNode.appendChild(accrodionItemsCopy); 8 const accrodionItemsCopyH = accrodionItemsCopy.offsetHeight; 9 accrodionTrigger[i].addEventListener('click',() => { 10 alert(accrodionItemsCopyH); 11 }); 12 } 13}

試したこと

①cloneNodeのタイミングや、書き方を変えてみました。
例えば、

const accrodionItemsCopy = this.nextElementSibling.cloneNode(true);
const accrodionItemsCopy = accrodionTrigger.cloneNode(true);

②for文の外に書いてみる。

エラー内容

Cannot read property 'cloneNode' of undefined at window.onload

引き続き調べを進めますが、
何かヒントなどいただければ嬉しいです。

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

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

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

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

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

naomi3

2019/05/01 06:07

this.nextElementSibling.cloneNode(true); 「TypeError: this.nextElementSibling is undefined」とエラーが出ます。 「this」が正しくないのでは?
kitty

2019/05/01 06:44

ご確認いただきありがとうございました。 修正してアラートが出るようになりました。 また機会がありましたらよろしくお願いいたします。
guest

回答1

0

ベストアンサー

const accrodionItemsCopy = this.nextElementSibling.cloneNode(true);
ここでおもむろに this.nextElementSibling が登場していますが、こういう登場の仕方をしたときの thiswindow を指します。this はどういう登場の仕方をするかによって取り回しが違います。これを話し始めると長くなるので詳細は必要に応じてググっていただこうと思います。

つまり、こうなります。

js

1this.nextElementSibling 2// -> window.nextElementSibling

で、残念ながら windownextElementSibling などというプロパティは無いので、 こうなります。

js

1this.nextElementSibling 2// -> window.nextElementSibling 3// -> undefined

undefinedcloneNode() などというメソッド(or プロパティ) はないですよ、というのがそのエラーの内容です。

forループの中で accrodionItemsCopy を宣言している行を、こう書き換えたら動きませんでしょうか。

js

1const accrodionItemsCopy = accrodionTrigger[i].nextElementSibling.cloneNode(true); 2// もしくは 3const accrodionItemsCopy = accrodionItems[i].cloneNode(true);

ここまでが回答です。


ここから先は余談というか、読まなくても別にいいのですが……
アコーディオンを実現するためにいちいちノードをコピーするのは、まあ大した負荷ではないのですが、スマートではないと思います。当時は確かにJavaScriptで要素の高さを調べて、高さを徐々に0にしたり本来の高さにしたりしてニュルっと動くアニメーションを作るしかなかったのですが、最近では長々とコードを書かなくてもCSSだけ(あるいはアニメーションはCSSで定義、アニメーションさせるためのクラスを付けたり外したりするのをJavaScriptでやったり)でアコーディオンを実装できたりしますので、モダンな書き方というか、最近の流行りを探ってみるとよいかなと思います。

投稿2019/05/01 06:29

thyda.eiqau

総合スコア2982

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

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

kitty

2019/05/01 06:53

ご確認いただきありがとうございました。 アラートが出るようになりました。 おっしゃる通りだと思います・・ スキルアップのため、とりあえずjavascriptを一から勉強し直そうと思い、 今までjqueryで処理してきたアクションを全てjavascriptで書いてみようと今回に至っているのですが全くスマートではないなと感じました。 色々やりながら使い分けをしていきたいと思います。 なので懲りずにまた質問をアップするかもしれません。 恐れ入りますがまた何か機会がございましたらよろしくお願いいたします(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問