jQueryで複数の.toggleボタンを使いたい場合の問題とその解決方法

このQ&Aのポイント
  • jQueryの.toggleを使用してアニメーションを交互に切り替えるためには、ボタン1とボタン2の動作を個別に設定する必要があります。
  • .hoge1ボタンをクリックした場合、アニメーションが実行されたかどうかを確認し、実行されていない場合はテキストエリアを表示します。
  • .hoge2ボタンをクリックした場合、アニメーションが実行されたかどうかを確認し、実行されていない場合はテキストエリアを表示し、特定のテキストを追加してフォーカスします。
回答を見る
  • ベストアンサー

jQueryにて、.toggle()でアニメート

.toggle( function(){ } , function(){ } ); こういう形で無名関数の中には.animateを入れてアニメーションを交互するようにしています。 (もうすぐこの形が使えなくなるそうですが…) やりたいことはもう少し複雑で、まず.toggleするボタンを2つ以上にしたいと思っています。 それぞれのボタンは元々、 ボタン1:設定した"hoge1"を押すとあるテキストエリアが存在するボックスが大きくなったり小さくなったりする。hoge1ボタンもそれに合わせてwidthが大きくなったり小さくなったりする。 ボタン2:"hoge2"を押すとテキストエリアに対して.val("特定のテキスト").focus();するようにして"特定のテキスト"を追加してその後フォーカスするようなボタン。 これらは別々にちゃんと動いていまして、そこまでは出来てるんですが ボタン2の"hoge2"に、押したら 『ボックスが開いた上でテキスト追加のフォーカス』 という動作を追加したいと思い $(".hoge1, .hoge2").toggle(function(){ $(".textareabox").animate({width:"300px", height:"toggle", opacity:"toggle"}); $(".hoge1").animate({width:"300px"}); },function(){ $(".hoge1").animate({width:"150px"}); $(".textareabox").animate({width:"150px", height:"toggle", opacity:"toggle"}); }); こういう風にボタンを2つともセレクトすると、どちらか一方のみを使うのであれば動くんですが 当たり前のことに"hoge1"を一度だけ押してから"hoge2"を押すと .hoge1のwidthは戻らずに、.textareaboxのみ引っ込んで(toggleして)、そこからずれていきます。 ややこしいのですが、場合分けすると (".hoge1")をクリックしたら 未アニメート時:出す 既アニメート時:ひっこめる ("hoge2")をクリックしたら 未アニメート時:出して.val().focus() 既アニメート時:出したままで.val().focus() こういうことにしたいです。.val.focusは別でscript書いてます。 :not(:animated)とかいうのをググって見つけたんですがいまいちわかりません。 初心者なので前提からしてどこか間違ってるかもしれませんが どなたかお知恵拝借願います。。。

質問者が選んだベストアンサー

  • ベストアンサー
  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.3

A No1、2です。 ".textareabox"の動作のheight:"toggle", opacity:"toggle"は、要素の状態に応じてtoggleされますので、イベントの処理をtoggleで行う必要はないでしょう。 一方で、hoge1は自分自身が動作対象でありながら他にもトリガーが存在するために単純にtoggleでは処理しにくいことになっています。 結局のところ、textareaboxもhoge1もwidthはhoge1の状態に応じて処理内容を決め、height、opacityはtextareaboxに対してのtoggleで処理すればよいことになりませんか。 >つまりこの場合flagを2つ作れば良いということですかね? 2つでもよいですが、hoge1の状態が判定できさえすれば良いように思えます。 例示のようにflagなどの状態変数を作成する方法が汎用的と思いますが、変数を使わずに直接要素を調べて判断する方法もあるでしょう。 $(".hoge1, .hoge2").click(function(){ var f = $(".hoge1").css("width") == "150px"; $(".hoge1").animate({width:f?300:150}); $(".textareabox").animate({width:f?250:150, height:"toggle", opacity:"toggle"}); }); 書きっぱなしなので、動作確認していません。  .css("width")の戻り値が単位付きだったかどうか記憶していませんが、こんな考え方でもご希望の処理ができると思います。 あと、更に言うならば、回答の例やご提示の処理も含めて、アニメーション中に次のイベントが発生した場合の対処を記述しておいたほうが、より良い記述となることでしょう。

man_ahoaho
質問者

お礼

ありがとうございます! 回答2と1を何度も見直し私も同じ結論に達しまして、hoge1の状態をflagに入れてうまく動作させることが出来ました! hoge2のときは出したままにさせる、というのはtoggleだとflagだけでは何度か押すとtoggleしてしまうため、show()を使うことで回避しました。 ご教授ありがとうございました。

その他の回答 (2)

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.2

A No1です。 >ボタン2を押したとき、もしボックスが開いていたら >開いたままにする、ができないような気がするのですが >どうでしょうか? 「開く」とか「出す」というのがどのような動作を意味しているのかよくわからないのですが、要は、状態に応じて処理内容を変えたいのだと想像しました。 A No1にも書きましたが、toggleだと要素ごとにオン/オフの状態を記憶してしまうために、実際に見えている状態に連動した値にならないだけでなく、ひとつの状態に対して複数の変数を作っていることになります。 これを回避するために、実際の状態と整合した状態の記憶用の変数を自前で設定してあげれば、その値(=状態)によって処理内容を決定することができます。 A No1の変数 flagがこれに該当します。 複数の同様の処理が可能なようにクロージャー的な記述になっていますが、わかりやすくするなら、グローバルな状態変数を作成しておくと考えればよろしいでしょう。

man_ahoaho
質問者

補足

すいません、説明不足でした。 $(".hoge1, .hoge2").toggle(function(){ $(".textareabox").animate({width:"250px", height:"toggle", opacity:"toggle"}); $(".hoge1").animate({width:"300px"}); },function(){ $(".hoge1").animate({width:"150px"}); $(".textareabox").animate({width:"150px", height:"toggle", opacity:"toggle"}); }); ちょっと1度目に書いたコードと2行目のwidthが違うのですが、1度目が間違いでこうでした。 このコードでやっているのは、animate()のheightとopacityをtoggleという値によって出てきたり消えたりを繰り返しています。".textareabox"にはCSSシートでdisplay:none;を初期設定としています。 そして、height:"toggle", opacity:"toggle"とやると縦に大きくなりながら透明なボックスが無透明になる様子がアニメートされます。 つまり、テキストエリアボックスは消えたり出てきたりします。widthはまぁhoge1に合わせて大きくしてるだけです。 それと同時に、ボタン自身は横幅が大きくなったり小さくなったりします。 つまり、一回hoge1を押すと1.ボタンの横幅が大きくなる、2.テキストエリアボックスが現れる、という2つのアニメーションを同時にやっていることとなります。 なので、単純にそう動作するボタンを2つ作るんであればclassを同じにするだけでいけそうなんですが つまりこの場合flagを2つ作れば良いということですかね? 変数を作るとのこと、参考になります。ちょっと試してみます。

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.1

.hoge1、.hoge2のどれをクリックしても、交互に状態を変えたいという意味でしょうか? 「toggle」は各要素ごとに状態を記憶するようになっているようですので、ご提示の記述方法ですとご質問のような動作になると思います。 グループの要素のどれをクリックしても、まとめて同じスイッチのオン/オフをするようにしたいのであれば自前で定義してあげるとか… var groupToggle = function(e, w1, w2){  var flag = false;  return function(){   if(flag = !flag) e.animate({width:w1});   else e.animate({width:w2});  } } var gt1 = groupToggle($(".hoge1"), 300, 150); $(".hoge1, .hoge2").click(function(){ gt1(); }); みたいな感じ。 あるいは、ご提示の記述に近い形にするなら、代表して状態を記憶するためのダミーの要素を作成しておいて、その状態にあわせて処理を実行するようにしてあげるとか。 $("#fuga").toggle(function(){  $(".hoge1").animate({width:"300px"}); },function(){  $(".hoge1").animate({width:"150px"}); }); $(".hoge1, .hoge2").click(function(){ $("#fuga").click(); }); みたいなのでもいけると思います。

man_ahoaho
質問者

補足

ありがとうございます。 それだと、ボタン2を押したとき、もしボックスが開いていたら開いたままにする、ができないような気がするのですがどうでしょうか?

関連するQ&A

  • jqueryでtoggleを無制限に繰り返したい

    下記のhtmlテキストのjquery記載部分について質問させていただきます。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>toggle繰り返し</title> </head> <body> <p>toggle繰り返し</p> <div id="box" style="width:150px;height:150px;background:blue;"> </div> <script src="http://code.jquery.com/jquery-1.10.1.min.js"> </script> <script> $(function() { $('#box').toggle(1000); $('#box').toggle(1000); $('#box').toggle(1000); $('#box').toggle(1000); $('#box').fadeOut(1000, function() { }); }); </script> </body> </html> 上記のhtmlの上から14行目~17行目に記載してあるにあるscript部分に、 $('#box').toggle(1000); を4回記載しているため、 4回、繰り返しフェードアウトが実行されています。 DreamWeaverCS6で作成し、ブラウザIE10、firefox24.0で動作確認しています。 ここで質問ですが、この回数を無制限に、つまり永久に繰り返すようにするには、どのようにすればよいのでしょうか?具体的なコードを記載していただけると助かります。 詳しい方がいましたら、よろしくお願いします。

  • 【jQuery】サムネイル

    3つのサムネイル画像(.thumb)があります。 クリックした.thumbはopacityを1に、その他は0.5に切り替わる する方法を教えてください。 始めは1番目.thumbのopacityは1でお願いします。 ■html <div id="ph-wrap"> <div id="photo"> <p><img src="./img/photo1.png" width="480" height="320" alt="" /></p> <p><img src="./img/photo2.png" width="480" height="320" alt="" /></p> <p><img src="./img/photo3.png" width="480" height="320" alt="" /></p> </div> <div id="thumb-wrap"> <p class="thumb"><img src="./img/photo1.png" width="120" height="80" alt="" /></p> <p class="thumb"><img src="./img/photo2.png" width="120" height="80" alt="" /></p> <p class="thumb"><img src="./img/photo3.png" width="120" height="80" alt="" /></p> </div> </div> ■CSS(一部抜粋) #thumb-wrap{ float:left; margin:0 0 0 10px; padding:0; width:120px; } #thumb-wrap img{ width:120px; height:80px; cursor:pointer; opacity:0.5; -moz-opacity:0.5; /* Firefox */ filter: alpha(opacity=50); /* IE */ } .opc{ opacity:1.0; -moz-opacity:1; /* Firefox */ filter: alpha(opacity=100); /* IE */ } ■jQuery $(function () { var photoImg = "#photo img" var thumbWrapImg = "#thumb-wrap img" $("#photo p:gt(0)").hide(); $(thumbWrapImg).eq(0).css({"opacity":1}); $(thumbWrapImg).click(function () { $(this).animate({"opacity":1},100); $(photoImg).attr("src",$(this).attr("src")); }); });

  • opacityについて

    $(function(){ $("#s1").animate({ $(this).css("opacity","0") },3000); }); html <div id="s1"><img src="1" width="300px" height="300px"></div> 質問:消えると思ったのですが、3秒後に画像が消えませんでした。 できないのでしょうか? 画像を時間で消える方法があればご教授ください

  • jQuery hover時に遅延させる方法

    よろしくお願い致します。 jQueryを使用して以下のようなコードを書いております。 $('#hoge').hover( function(){ $(this).animate({'marginTop':'100px'},500,'easeOutQuart'); }, function(){ $(this).animate({'marginTop':'0px'},500,'easeOutQuart'); } ); 上記のコードで問題なく動作するのですが、要素(#hoge)からマウスを離したときにだけ遅延処理をさせたいと思い、以下のようなコードを書いてみたのですが動作しません。 $('#hoge').hover( function(){ $(this).animate({'marginTop':'100px'},500,'easeOutQuart'); }, function(){ setTimeout(function(){ $(this).animate({'marginTop':'0px'},500,'easeOutQuart'); },1000); } ); この場合、どのようなコードを記述すれば良いのでしょうか?

  • jQueryでスマホ向けページのロールオーバー

    スマートフォン向けページで、記事をタップすると その記事にグレーのオーバーレイがかかり、 指が外れるとオーバーレイが消える効果をつけたいと思います。 CSSだけでは難しそうでしたので、jQueryで空のdivを作成する 方法を考えました。 背景を透過した空のdivを生成するところまではできたのですが、 それを外すことがどうしてもできません。 Javascriptの基本的な文法がわかっていないせいだと思います…。 下記がうまく行かなかったソースです。 removeの記述に問題があるのだと思いますが ご教授の程よろしくお願い致します。 また、この程度JSを使わなくてもCSSだけでできるようでしたら その方法でもかまいませんので教えていただければと思います。 ■JS <script> $(function($){ $( "#hoge a" ) .bind( 'touchstart', function(){ $( this ).prepend( "<div></div>" ); }).bind( 'touchend', function(){ $( this ).unbind(); }).bind( 'touchend', function(){ $( "<div></div>" ).remove( ); }) }); </script> ■HTML <section id="hoge"> <a href="#"> <article> <figure><img src="image.png" width="100" height="120"></figure> <p>テキストテキスト</p> </article> </a> </section> ■CSS #hoge article { position: relative; } #hoge article figure { z-index: 1; } #hoge a div { background-color: #000; opacity: 0.3; width: 100px; height: 150px; position: absolute; top: 0; left: 0; z-index: 2; }

  • jquery:animate中にイベントを付与

    #box{width:100%;height:100%;position:relative;} #idou{width:3000px;height:100%;position:absolute;} #ugoku{position:absolute;top:-300px;right:-1500px;} a{display:block;width:100px;height:100px;right:0;top:100px;} <div id="box"><div id="idou"><img id="ugoku" src="*.gif" width="300" height="300"><a href="">左に移動</a></div></div> ・jQuery(1.7.1) ・mousewheel.jsを使用、var scrollInt=100;$('html').mousewheel(function(event,mov){$("html,body").css("left","-="+(scrollInt*mov)+"px");});で通常は横移動するソース。 ・$("a").click(function(){$("#idou").animate({left:0},"slow");});でリンクをクリックすると左に戻す。この時の#ugokuが問題。 ・移動の角度は50度で設定、#idouのleftが-1000~-1500pxの間というような特定の間に#ugokuの画像を画面の右上から左下にanimateで流したい。 最後の項目をやろうとして完全に行き詰ってしまって困っています。 どちらかというと数学の問題かもしれません。 animate動作中に、#idouのleftが~pxになったときを拾うようなイベントは存在するのでしょうか?その他良いやり方やURLあれば教えて頂けると幸いです。 よろしくご教授ください。

  • 画像スライダーをやってますが

    <script type="text/javascript"> <!-- $(function(){ var sty=$("#s1"); sty.each(function(){ var mo1=$(this); var mo2=mo1.find("ul"); var mo3=mo1.find("li"); var mo4=mo1.find("li:first"); mo3.css({display:"block",opacity:"0",zIndex:"1"}); mo4.css({zIndex:"2"}).stop().animate({opacity:"1"},3500); setInterval(function(){ mo2.find('li:first-child').animate({opacity:'0'},1500).next('li').css({zIndex:'100'}).animate({opacity:'1'},1500).end().appendTo(mo2).css({zIndex:'99'}); },5000); }); }); --> </script> </head> <body> <div id="s1"> <ul> <li><img src="rtp/7.jpg" width="300px" height="300px"></li> <li><img src="rtp/9.jpg" width="300px" height="300px"></li> <li><img src="rtp/10.jpg" width="300px" height="300px"></li> </ul> </div> </body> </html> 見よう見まねで成功はしましたが、見真似なのでどういう構造なのか勉強しているところです。 今日は前半をなんとかやったんですが mo3.css({display:"block",opacity:"0",zIndex:"1"}); の部分のdisplay:"block"はなぜやっているのかが解りませんでした。 最初の設定は画像を消すところだと思うのですが、だとするとなぜblockなのかが解りません。

  • javascriptで吹き出し

    下記のサイトにある吹き出しをメニューボタンのように複数の画像に反映させたいのですが、どのようにすればよいでしょうか? http://www.dvq.co.nz/web-design/create-a-jquery-popup-bubble-effect/ javaスクリプトコード $(document).ready(function(){ $(".info-popup a").hover(function(){ $(this).next("em").stop(true, true).animate({opacity: "show", top: "40"}, "slow"); }, function() { $(this).next("em").animate({opacity: "hide", top: "70"}, "fast"); }); }); cssファイル .info-popup { margin: 0px auto; padding: 0; width: 162px; position: relative; } div.info-popup em { background: url(../image/menu_info_c.gif) no-repeat; width: 162px; height: 42px; position: absolute; top: 0px; left: 0px; text-align: center; text-indent: -9999px; z-index: 2; display: none; } #info-icon { width: 162px; height: 42px; background: url(../image/menu_info.gif) no-repeat 0 0; text-indent: -9999px; margin: 0 auto; display: block; } htmlファイル <div class="info-popup"> <a href="information.html" id="info-icon">information</a> <em>information</em> </div> 詳しい方、是非、アドバイスをお願い致します。

  • 【jQuery】for文ではイベント登録できない?

    複数のボタンがあり、それぞれがクリックされると、 対応したdiv要素がanimateを行う、というギミックを作成しております。 配列に複数のボタンのid名と、各div要素のid名を格納しておき、 for文でclickイベントを登録しようとしましたが、うまく動作しませんでした。 【例1】 jQuery(function($){  var buttonArray = ["#button0", "#button1", "#button2"];  var divArray = ["#box0", "#box1", "#box2"];  for(i=0; i<buttonArray.length; i++){   $(buttonArray[i]).click(function(){    $(divArray[i]).animate({width: "0px"}, "slow", "swing");   });  } }); --------------------------------------------------- 以下のように書くと、正常に動作しました。 【例2】 jQuery(function($){  var buttonArray = ["#button0", "#button1", "#button2"];  var divArray = ["#box0", "#box1", "#box2"];  $(buttonArray[0]).click(function(){   $(divArray[0]).animate({width: "0px"}, "slow", "swing");  });  $(buttonArray[1]).click(function(){   $(divArray[1]).animate({width: "0px"}, "slow", "swing");  });  $(buttonArray[2]).click(function(){   $(divArray[2]).animate({width: "0px"}, "slow", "swing");  }); }); --------------------------------------------------- そこで質問なのですが、 ・for文ではイベントの登録は行えないのか? ・今回のようなケースの場合、どのように書くのが適切か? 上記2点に関して、ご回答、ご意見を頂けますと幸いです。 どうぞよろしくお願い申し上げます。

  • jqueryでdata-の画像サイズの取得方法

    通常の場合、 <img src="hoge.png" /> $("img").on("load",function(){ var w = $(this).width(); var h = $(this).height(); $(this).css({"width":w +"px", "height":h +"px"}); }); でサイズは取得できますが、 <img src="hoge.png" data-src="hoge2.png" /> の場合でhoge2.pngの画像サイズを取得する方法を探しています。 分かる方がいらしたら教えてください。 よろしくお願いします。