シンプルなユニバーサルjavascriptスイッチ

サイトを開発する場合、多くの場合、その状態を切り替える必要があります。通常、ツールチップ、入力フィールド、ページの別の部分を非表示または表示するために、擬似リンクが使用されます。



JavaScriptコードとそのスタイルを毎回作成できますが、時間が経つにつれて、コードの成長につながります。



ただし、問題はよりエレガントに解決できます。 以下で検討する解決策は単純であり、タイプセッターがスタイルに必要な変更を個別に行うことができるため、JavaScriptプログラマーのその後の関与を必要としません。



動作原理



このソリューションは、開発者Pavel Dovbush別名dppによって提案されました。HTMLコードでは、 jstJavaScript toggle )クラスはスイッチング要素に登録され、 jswJavaScript wrapper )は変更が発生する親要素に登録されます。



提案されたスクリプトは、 jstクラスの要素のクリックを追跡し、ラッピング要素の特定のクラスをjswクラスに切り替えます。 デフォルトでは、これはjseクラス( JavaScript enable )ですが、 rel属性で別の名前を指定できます。 要素の他のクラスは影響を受けません。



以下は、アイデアを示すために意図的に簡略化されたコードですが、Internet Explorerバージョン8以前をサポートするために使用されるフレームワークに追加または転送するのは簡単です。



//  . document.addEventListener('click', clickEvent, false); function clickEvent(e) { /*     .jst,    toggle(). */ if (e.target && /(^|\s)jst(\s|$)/.test(e.target.className)) { toggle(e.target); //     (,   ). e.preventDefault(); } } function toggle(el) { var cls = el.rel || 'jse', //       . rcls = new RegExp('(^|\\s)' + cls + '(?=\\s|$)'); //   . do { el = el.parentNode; if (!el) return; //    -  . } while(!/(^|\s)jsw(\s|$)/.test(el.className)); //  . if (rcls.test(el.className)) { el.className = el.className.replace(rcls, ''); } else { el.className += ' ' + cls; } }
      
      





クリックイベントハンドラーは、「 イベントバブリング 」を使用して、 ドキュメントノードですぐに「ハング」します。 この手法により、ドキュメント内の任意の場所でクリックを追跡でき、完全なダウンロードを必要とせず(スクリプトの実行時にドキュメントが既に存在します)、このコードを含むJavaScriptが実行された直後に動作を開始します。 同時に、「ハング」イベントハンドラーに対する一連の低速なDOM要求を取り除くことにより、ページの初期化速度が向上しますが、これは従来のアプローチでは避けられませんでした。



上記のコードのrel属性はドットで直接指定されていますが、このオプションはリンクでのみ機能します。 エレメントの属性を取得するには、 getAttribute()メソッドを使用します。 セマンティクスの観点からは、HTML5のdata- *属性を使用する方がより適切です。この考慮事項はこの記事の範囲外です。



標準の切り替えオプションの場合、標準スタイルを定義するのが妥当です。 Badooでは、jsh、jsb、jseh、jsebなどのクラスがこれに使用されます。



 .js .jsb, .js .jse .jseb { display: block } .js .jsi, .js .jse .jsei { display: inline } .jsb, .jsi, .js .jsh, .js .jse .jseh { display: none }
      
      





jsクラスは、実行時にすぐにスクリプトによって追加され、JavaScriptが有効か無効かに応じてスタイルを分離します。



 document.documentElement.className += ' js'
      
      





jsiクラスとjsbクラスは、JavaScriptの実行時にそれぞれインライン要素とブロック要素を表示できるようにしますが、 jshは逆に非表示にします。 jseiクラスjsebクラス およびjsehクラスは、 jseクラスが存在する場合のjs クラスと同じように機能します。



これらのクラスを使用すると、ブラウザでJavaScriptがオフになっている場合に「グレースフルデグラデーション」(英語のグレースフルデグラデーション )を確保しながら、ページの動作を柔軟に制御できます。



使用例


Badoo Webサイトでは、自分に関する基本情報のブロックに本名と姓を示す必要はありません。 このため、設計者はこれらのフィールドを擬似リンクの下に隠すことにしました。





テキストをクリックすると、フィールドが表示され、擬似リンク自体が消えます(画像内のフォームの幅が縮小されます)。





これは、たとえば次のHTMLコードを使用して実現できます。



 <div class="jsw"> <span class="change jst jsi jseh">    </span> <div class="jsh jseb"> <label for="firstname"></label> <input type="text" id="firstname"> </div> <div class="jsh jseb"> <label for="lastname"></label> <input type="text" id="lastname"> </div> </div>
      
      





擬似リンクの変更クラスは外観を設定し、JavaScriptが有効になるとjsiが表示し、切り替え後にjsehは非表示にします。 jshクラスを使用すると、JavaScriptを有効にするとフィールドが非表示になり、 jsebは切り替え後にそれらを表示します。



これにより、非表示の擬似リンクの動作が保証されます。 それでも、ブラウザでスクリプトをオフにすると、オプションのフィールドが表示されるため、フォーム全体が利用可能になります。



例からわかるように、スイッチは往復操作のみに使用する必要はありません。 また、オプションのフィールドの表示など、一方的なアクションの場合にも使用できます。



サイトでのその他の使用例:





長期使用



ただし、単純な切り替えだけでは必ずしも十分ではありません。3つ以上の状態を切り替えるか、提案されたオプション(ラジオボタンを使用)からのユーザーの選択に応じて、フォーム内の何かを変更する必要があります。



関数は、この使用のために簡単に変更できます。 これを行うには、 jswクラスを持つ親要素でrelまたはvalue属性からの値で上書きされる要素をクリックすることにより、 jssクラスが定義されます。 jswを除く要素上の他のクラスは上書きされるため、このオプションはすでに慎重に使用する必要があります。



 function clickEvent(e) { if (!e.target) return; //     .jst,  //   toggle(). if (/(^|\s)jst(\s|$)/.test(e.target.className)) { toggle(e.target); //     (  ). e.preventDefault(); e.stopPropagation(); } //    .jss,   toggle() //   . if (/(^|\s)jss(\s|$)/.test(e.target.className)) { toggle(e.target, true); //      //    . if (e.target.tagName != 'INPUT') { e.preventDefault(); e.stopPropagation(); } } } function toggle(el, set) { var cls = el.rel || (el.nodeName == 'INPUT' ? 'jse_' + el.value : 'jse'); //   . do { el = el.parentNode; if (!el) return; //    -  . } while(!/(^|\s)jsw(\s|$)/.test(el.className)); if (set) { //   (.jss). el.className = 'jsw ' + cls; } else { //       . var rcls = new RegExp('(^|\\s)' + cls + '(?=\\s|$)'); //   (.jst). if (rcls.test(el.className)) { el.className = el.className.replace(rcls, ''); } else { el.className += ' ' + cls; } } }
      
      





使用例


Badooユーザーはお互いにプレゼントを贈ることができ、1つを選択するのに役立ついくつかの重複するセットがあります。 たとえば、チェリーはすべてのセットに存在し、サッカーボールは友好的で完全なものにのみ存在します。







やや単純化されたHTMLは次のようになります。



 <div id="gifts_wrapper" class="jsw all"> <p class="description"> <a href="#" class="jss" rel="all"> </a> <a href="#" class="jss" rel="popular"></a> <a href="#" class="jss" rel="romantic"></a> <a href="#" class="jss" rel="friendship"></a> </p> <div class="gifts_items"> <div class="giftframe romantic popular"> <img src="…" title=""> </div> <div class="giftframe friendship popular"> <img src="…" title=""> </div> <div class="giftframe friendship"> <img src="…" title=" "> </div> <div class="giftframe romantic friendship"> <img src="…" title=" "> </div> <div class="giftframe romantic"> <img src="…" title=""> </div> <div class="giftframe romantic friendship popular"> <img src="…" title=""> </div> </div> </div>
      
      





各ギフトは<div class = "giftframe">要素で表され、内部にギフトの写真があり、要素の追加のクラスは特定のグループへの所属を決定します。



この機能を使用すると、これらのセットの切り替えを制御するために必要なスタイルは次のとおりです。



 .gift_items .giftframe { display:none; } .all .gift_items .giftframe, .popular .gift_items .popular, .romantic .gift_items .romantic, .friendship .gift_items .friendship { display:inline-block; }
      
      





この機能をラジオボタンで使用する例としては、チケットの予約という形式があります(残念ながら、同じように明確な例は見つかりませんでした)。 片道チケットまたは往復チケットの予約に応じて、返却日フィールドが表示されるか、表示されません。







サンプルHTMLコード:



 <div class="jsw"> <label> <input type="radio" name="direction" class="jss" value="oneway">    </label> <label> <input type="radio" name="direction" class="jss" value="twoway"> - </label> <label> : <input type="date" name="fly_date"> </label> <label class="back_date"> : <input type="date" name="back_date"> </label> </div>
      
      





指定されたコードを使用すると、CSSで1行のみで戻り日付フィールドを非表示にできます。



 .jse_oneway .back_date { display:none }
      
      





おわりに



毎回車輪を再発明する代わりに、発生する問題のクラスを一般化し、80%のケースでそれらを満足させる普遍的な解決策を見つけることができます。



この記事で検討する機能を使用すると、JavaScriptコードをオーバーロードせず、JavaScriptプログラマーのリソースを流用することなく、レイアウトデザイナーのみの力を使用して、ページ上の要素を切り替える多くの典型的なタスクを解決できます。 その結果、CSSコードの量も減少します。



それにもかかわらず、この関数の使用が不可能な場合があります:たとえば、表示されたフィールドへの自動フォーカス(新しいブラウザのオートフォーカス属性がこの問題を解決しますが)またはAJAXリクエストを使用してページの一部を動的に読み込みます。



また、多数の切り替え可能なアイテム、たとえば膨大な数のさまざまなタブを使用すると、CSSコードが不当に肥大化する可能性があります。そのため、他のソリューションを検討するのが理にかなっています。



この機能の利点は、シンプルさと汎用性です。 JavaScriptを実行するすべてのブラウザーで動作し、アイドルスクリプトの場合に「エレガントな劣化」のすべての機能を備え、隠し<input type = "radio">を使用する方法とは異なり、余分な要素や「ハック」を必要としません。 CSS3セレクター:チェック



更新:労働者の要求に応じて、いくつかの例をここに示します



Leo Solntsev Aingis 、Badooウェブ開発者



All Articles