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

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

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

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

jQuery

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

Q&A

解決済

1回答

3626閲覧

アコーディオンを開いたタイミングでslickを実行したい

aKusano

総合スコア3763

JavaScript

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

jQuery

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

0グッド

0クリップ

投稿2019/02/03 14:40

編集2019/02/04 00:29

以前質問して解決したこちらの質問のサイトを
リニューアルすることになり、以前とほぼ同様の機能を実装しようとしたのですが、
以前とは微妙に違うエラーが発生してアコーディオン内のslickが実行されない問題が発生してしまいました。

結論から言うとアコーディオンを開いたタイミングでslickが初期化されていないため、
存在しないslickオブジェクトに対してslickSetOptionメソッドを実行しようとするためにエラーとなっている状況と思われます。

なのでアコーディオンを開いたタイミングでslickを初期化する処理を加えれば良いのではないかと思うのですが、
実行したいものが単純なslickスライダーではないため、どうするのが良いのか分かりません。

前提・実現したいこと

・カルーセル表示にはslick.jsを使用している(ver. 1.3.15)
・SPレイアウト(640px以下)ではアコーディオンパネルの中でカレンダーをカルーセル表示で見せる
・PCではアコーディオンなし/カルーセル表示なし
・ブラウザをリサイズしても上記表示を正常に切り替える
・カレンダー表示はアコーディオンの中で見せる場合と、そうでない場合の両方のパターンがある
・アコーディオンではない状態のカレンダー表示は、既存のinitCalendar()関数で正しく表示できている

発生している問題・エラーメッセージ

SPレイアウト時にアコーディオンを開くと、エラーが出てslick.jsの初期化が正しく行われない
イメージ説明

該当のソースコード

HTML

1<div class="js-accordion"> 2 <h3 class="jy-routeCaption js-acrTitle">アコーディオン開閉見出し<span class="js-acrLabel">開く</span></h3> 3 <div class="js-acrBody"> 4 <div class="jy-calendar" data-month="12,1"> 5 <div class="cal"> 6 <table>省略 12月カレンダー</table> 7 </div><!-- /.cal --> 8 <div class="cal"> 9 <table>省略 1月カレンダー</table> 10 </div><!-- /.cal --> 11 </div><!-- /jy-calendar --> 12 </div><!-- /.js-acrBody --> 13</div><!-- /.js-accordion -->

JavaScript

1//ready 2$(function(){ 3 initCalendar(); //カレンダー初期化(※slick初期化含む) 4}); 5 6//load 7$(window).on('load', function(){ 8 accordionPanel01(); //アコーディオン開閉(※slick表示リフレッシュ含む) 9}); 10 11//resize 12var timer = false; 13$(window).resize(function() { 14 if (timer !== false) { 15 clearTimeout(timer); 16 } 17 timer = setTimeout(function() { 18 resetAccordionPane01(); //アコーディオン表示リセット 19 initCalendar(); //カレンダー初期化(※slick初期化含む) 20 }, 200); 21}); 22 23/* カレンダー初期化処理 24-------------------------------------------------- */ 25function initCalendar(){ 26 var $cal = $(".jy-calendar"); 27 var d = new Date(); //日時情報を取得 28 var month = String(d.getMonth()+1); //当月を取得して文字列に変換 29 var w = $(window).width(); 30 var size = 640; 31 32 $cal.each(function(){ 33 var len = $(this).find(".cal").length; 34 35 //アイテムが2つ以上だったら 36 if(len > 1){ 37 var calMonthText = $(this).data("month"); //掲載月データを取得 38 var calArray = String(calMonthText).split(","); //掲載月データを配列に変換 39 var num = $.inArray(month, calArray); //当月が何番目にあるかを取得 40 if(num < 0){ 41 num = 0; //当月が無かったら最初の月 42 } 43 //640px以下だったら(SPレイアウト時) 44 if (w <= size) { 45 if(!$(this).hasClass('slick-initialized')) { 46 $(this).slick({ //slickの初期化 47 initialSlide: num, 48 variableWidth: true, 49 centerMode: true 50 }); 51 $(this).find(".cal").matchHeight({ 52 remove: true 53 }); 54 } 55    //641px以上だったら(PCレイアウト時) 56 } else { 57 if($(this).hasClass('slick-initialized')) { 58 $(this).unslick(); //slickの解除 59 $(this).find(".cal").matchHeight(); 60 } 61 } 62 //アイテムが1つだったら 63 }else{ 64 $(this).find(".cal").addClass("center"); 65 return false; 66 } 67 }); 68} 69 70/* アコーディオン開閉処理 71-------------------------------------------------- */ 72function accordionPanel01() { 73 $(".js-acrTitle").on("click", function(){ 74 var w = $(window).width(); 75 var size = 640; 76 77 //640px以下だったら 78 if(w <= size){ 79 var $eventTarget = $(this); //.js-acrTitle 80 81 //アコーディオン開いている時の処理 82 if($(this).hasClass("op")){ 83 $(this).removeClass("op"); 84 $(this).find(".js-acrLabel").text("開く"); 85 $(this).next().stop().slideUp(400, function () { 86 // 87 }); 88 //アコーディオン閉じている時の処理 89 }else{ 90 $(this).addClass("op"); 91 $(this).find(".js-acrLabel").text("閉じる"); 92 $(this).next().stop().slideDown(400, function () { 93 //アコーディオンの中にカレンダーがあったら 94 if($eventTarget.next().has(".jy-calendar")){ 95 $eventTarget.next().find(".jy-calendar").slickSetOption(null, null, true);//slickの表示をリフレッシュ★エラーの原因箇所 96 } 97 } 98 }); 99 } 100 }else{ 101 return false; 102 } 103 }); 104} 105 106/* リサイズされた場合のアコーディオン表示処理 107-------------------------------------------------- */ 108function resetAccordionPane01() { 109 var w = $(window).width(); 110 var size = 640; 111 112 $(".js-accordion").each(function(){ 113 if (w <= size) { //SPの時 114 var display = $(this).find(".js-acrBody").css("display"); 115 if(display == "block"){//アコーディオンが開いていたら 116 $(this).find(".js-acrTitle").addClass("op"); //開閉アイコンの状態を設定 117 } 118 } else { //PCの時 119 //強制的にパネルを開く 120 $(this).find(".js-acrBody").show(); 121 $(this).find(".js-acrTitle").removeClass("op"); 122 } 123 }); 124}

試したこと

↓こちらはエラーこそ出ませんが、initCalendar()が実行されませんでした。

javaScript

1//アコーディオンの中にカレンダーがあったら 2if($eventTarget.next().has(".jy-calendar")){ 3 initCalendar(); //slickのリフレッシュの代わりにカレンダー表示の関数を入れてみる 4}

↓こちらはアコーディオンを開いた時にslickが実行されますが、
initCalendar()でやっている諸々の仕様(該当月を初期スライドにする、PCレイアウト時にはslickを解除するなど)の適用ができていないのでこれだけでは駄目です。

javaScript

1//アコーディオンの中にカレンダーがあったら 2if($eventTarget.next().has(".jy-calendar")){ 3 $(".jy-calendar").slick(); //ダイレクトにslickを実行してみる 4}

アドバイスいただきたいこと

・ すでに存在するinitCalendar()の関数を、アコーディオンを開くタイミングで実行する方法はありますか?
・ アコーディオンの中でカレンダーを表示する場合は既存のinitCalendar()とは別の処理(関数?)を用意しなければならないのでしょうか?
・何か他にエラーを起こすような問題が存在しているでしょうか?

解決の糸口が見つからない状態なので、何かアドバイスをいただけますと助かります。
よろしくお願い申し上げます。

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

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

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

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

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

m.ts10806

2019/02/03 14:46

.find(".jy-calendar")[0] のようにしてもだめですか?
aKusano

2019/02/03 14:52

エラーの内容が変わりました。 TypeError: $eventTarget.next().find(".jy-calendar")[0].slickSetOption is not a function.
s8_chu

2019/02/03 23:25 編集

質問者さんの実現したいことがあまり理解できなかったので、とりあえず出てきたエラーを解消してみましたが、この状態では質問者さんの実現したいことは行えていますか? https://codepen.io/anon/pen/xMrgXE また、 slick のバージョンを教えていただけませんか?
aKusano

2019/02/04 00:00

ありがとうございます。 slickのバージョンはちょっと古くて1.3.15になります。 codepen確認させていただきましたが、近いですがちょっと違います。 SPレイアウトになった時、アコーディオンは閉じた状態からスタートしたいです。
m.ts10806

2019/02/04 00:01

バージョン情報は再現確認には最も必要なものなので質問本文に追記してください
退会済みユーザー

退会済みユーザー

2019/02/04 00:07

initCalendar 内のthisは本当にイベント対象のthisなのかだな。
aKusano

2019/02/04 00:30

バージョン情報を本文内に追記いたしました。ご指摘ありがとうございます。
guest

回答1

0

ベストアンサー

こちらはアコーディオンを開いた時にslickが実行されますが、

initCalendar()でやっている諸々の仕様(該当月を初期スライドにする、PCレイアウト時にはslickを解除するなど)の適用ができていないのでこれだけでは駄目です。

「諸々の仕様」が提示されているものだけなのであれば、numが算出済みだったらよいのでは?
ウィンドウサイズに関係なく、.jy-calendarのdata属性に算出したnumを保存するようにして、「ダイレクトにslickを実行してみる」の箇所で使えばよいのでは。

投稿2019/02/03 15:11

kei344

総合スコア69398

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

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

aKusano

2019/02/03 15:14

なるほど。ちょっとやってみます!
aKusano

2019/02/04 01:40

当月判定だけでなく、カレンダーの数が1つか2つ以上かで表示を変える必要もあり、numだけどうこうしたのではやはり難しそうだったので、とりあえず「ダイレクトにslickを実行してみる」のところにinitCalendar()の中身のコード(※対象となる要素のセレクタだけは変更)をぶちこんでみたところ、SP表示の時のカレンダー表示はうまくいきました。が、今度はPCレイアウトに変更したときにslickを解除するのがうまく行かず。。。 なかなか一筋縄ではいかないようです…。
kei344

2019/02/04 01:44

initCalendar()で$(this).unslick();してますか? initCalendar()で$(this).slick();してませんよね。
aKusano

2019/02/04 01:51

initCalendar()の方では$(this).unslick();してます。アコーディオンに入ってないカレンダーの方はうまく表示切り替えできてます。 同じコードをそのままアコーディオンのスクリプトの中に入れた場合、$(this).unslick();しているところが効かないみたいです。 …あ、アコーディオンの方はそもそも「640px以下」の時にしか実行されないif文の中にあるので、641px以上の時のunslick()が動くわけないですね…。
aKusano

2019/02/04 01:53

今のままのinitCalendar()では、やはりアコーディオンの中でそのまま流用することはできなさそうということが見えてきました。。。アコーディオンの中でも動くようにするには根本的にロジック組み替えるか、アコーディオンの中用の動作コードを別途作らないと駄目ですかね…。
aKusano

2019/02/05 01:03

initCalendar()の組み換えはちょっと大変そうなのでアコーディオンの中にベタにカレンダーの処理を埋め込んでしまってひとまず動かすことにしました…。もっとうまいやり方が絶対あるような気がしますがたとえクソコードでも動かすのが先決なので…(汗) コメントのやりとりの中でひとまず動作につながるヒントに気づけたのでベストアンサーとさせていただきます。いつもありがとうございます。
aKusano

2019/02/06 15:24

すみません、その後改めてコードを確認したところ、initCalender()の中に原因があることが判明しました。 //アイテムが1つだったら }else{ $(this).find(".cal").addClass("center"); return false; ←★これ } 不要なreturn falseが入っていたため途中で処理が終了し、slickの初期化が正しく行われなかったというのが真相だった模様です。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問