質問: isotope(http://isotope.metafizzy.co/)を使用し、イラストのレスポンシブサイトを作っている初心者です。自分なりに勉強したり、ご教示頂いたりしてある程度まで出来たのですが、『画面が480px以下のとき、複数あるメニュー(isotopeの並べ替えの項目)をドロップダウンにしたい』所で行き詰まっております。 現状を下記にアップしてみました。 http://omatome.sitemix.jp/ ファイルは下記にアップしました。 http://9.gigafile.nu/hc596de80177ef188377febf86056d69d-0410 【やりたいこと】 (1)480pix以下に対応させたいjavascriptは【pix480.js】に書いたのですが、このスクリプトを480px以下の時だけ実施したい。 (2)480px以下でメニューがドロップダウンリストになった時、クリックでリストを開く>項目を選ぶ>リストが自動で閉じる>選択された項目だけが表示されるようにしたい。![イメージ説明](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/0b8c7b655eecd64bcc19445c7bf4374a.png) この動作が【pix480.js】のみの変更で叶いますでしょうか?いろいろ、文法やイベントなど勉強してみたのですが、理解できませんでした。できましたら、ズバリ教えて頂ければ助かります。よろしくおねがいします。 追記/もし他の部分にでもおかしいところがあれば、アドバイス頂ければ勉強になります。よろしくおねがいします。
回答: ざっくりとですが、こんな感じはいかがでしょうか? ``` $(function() { var windowW =$(window).width();//画面の横幅を取得 if(windowW<481){//画面の横幅が480px以下なら var open = false;//ドロップダウンリストが開いているか判定する変数 $(".button:not(.is-checked)").hide(); $(".button-group").click(function() { if(open){ //ドロップダウンリストが開いていたら閉じる $(this).children(".button:not(.is-checked)").hide(0,function(){$(this).css( "zIndex", "" );open = false;}); }else{ // "ul.button-group"をクリックするとその中の"li"が見えるようになって、zIndex+1 $(this).children(".button").show(0,function(){$(this).css( "zIndex", 1 );open = true;}); /*show/hideの数値はdurationなのでお好みの数値を*/ } }) } }); ``` * `$(window).load(function(){..});`の中に`$(function(){...});`が入れ子になっていましたが、入れ子にする意味が無いので、一つに。 * body最後だったので`$(function(){...})`でいいかな...と。(もし全て読み込み後のほうが良ければ$(window).loadでもいいですが、場合によっては結構遅いので...) * 単純に表示/非表示を切り替えるだけなら`.toggle()`系のメソッドで書いていいと思います。 4/3追記:画面リサイズでも動くように 自分だとこのようにするかな...というコードを記載させていただきます。 ``` (function($){ var dropDown = false;//liがモバイル(ドロップダウンリスト)状態か判定する用の変数 function listOpen(){ dropDown = false; //ドロップダウン状態をOFF $(".button:not(.is-checked)").show(); $(".button").off(".drop"); //ドロップダウン時に付加したクリックイベントをキャンセル } function dropDownLi(){ dropDown = true; //ドロップダウン状態をON $(".button:not(.is-checked)").hide(); $(".button").on( "click.drop" , function() { //isotopeのクリックイベントと衝突しないように名前空間を使って var parent = $(this).parent() if( parent.hasClass("open") ){ //開いていれば $(this).siblings().slideUp( 200 , function(){ parent.removeClass("open") }); }else{ //閉じていれば $(this).siblings().slideDown( 200 , function(){ parent.addClass("open") }); } }); } $(function() { var windowW = $(window).width();//画面の横幅を取得 if( windowW < 481 ){//画面の横幅が480px以下なら dropDownLi() } $(window).resize(function(){ //window幅が変化した際にドロップダウン状態か判定し、イベントを分岐 windowW = $(window).width(); if(windowW < 481){ if(dropDown) return; //ドロップダウン状態なら以後の処理を行わない dropDownLi() }else{ if(!dropDown) return; //ドロップダウン状態でなければ以後の処理を行わない listOpen() } }) }); })(jQuery); ``` グローバルをあまり汚したくなかったので、クロージャにしました。 windowのresizeイベントに対して、**画面幅によってイベントを分岐させる**という処理を入れると作成できます。 resizeイベントは画面幅が変わる度に何度も呼び出されるため、記述によってはイベントがどんどん重複してしまいます。 そのため、今の状態を判別するフラグのようなものを併用して、 状態が変わるとすぐにフラグを切り替え、それ以後同じイベントが呼ばれないようにしています。 また、よくよく考えれば変数の真偽判定だけだと、複数ドロップダウンリストを開いている時の挙動が意図した通りにならないので、親要素へのクラス有無判定に変更しました。 * ドロップダウン状態⇔通常 を何度も切り替える事も想定して、それぞれのイベントを関数にまとめました。 * 親要素であるulにクリックイベントだったのが何だか気持ちが悪かったので、li要素に対してのイベントへ変更。 * isotope側にもliに対するクリックイベントがあるので、衝突を避けるため、clickイベントに名前空間を利用しました。 * isotopeがせっかくアニメーションで動くのにドロップダウンリストの動きが無いのはちょっとアンバランスかな、と思ったので、show/hideをslideToggleにしてみました。