コラム・コーディングの鉄則(1) - DOMで処理が最優先されるのはID名である。
HTML/css/JavaScriptコーディングの鉄則、その1。
「DOMで最優先されるのはID名である」
このことを覚えておくとコーディングにおいて何かと役に立つ。
たとえばaタグ全部をgetElementsByTagNameメソッドで取ってきて、
ontouchstartとontouchend(iPhone/Androidコーディングではonclick系のイベントハンドラの代わりに ontouch系を用いる)で背景画像のポシジョンをtop⇔bottomで切り替えるため次のようなスクリプトを書いたとしよう。
◆サンプルスクリプト(1)
function smartPhoneBGImgRollover() { var a = document.getElementsByTagName("a"); for(var i=0; i < a.length; i++) { a[i].style.backgroundPosition="left top"; a[i].ontouchstart = function() { this.style.backgroundPosition="left bottom"}; a[i].ontouchend = function() { this.style.backgroundPosition="left top"}; } }
すべての背景画像つきのaタグがロールオーバー用の背景画像なら良いが、背景画像が単なる「→」だったり、一箇所だけbackground- positionがright top(bottom)だったりといったケースが出てこないとも限らない。そういった場合、上記の鉄則、「DOMで最優先されるのはID名である」を覚えていれば、その例外処理をさせたい要素に任意のid名を振り、document.getElementByIdメソッドで例外処理を記述しようという思考が生まれる。
◆サンプルスクリプト(2)
function smartPhoneBGColorRollover() { var b = document.getElementById("NaviType2"); this.style.backgroundColor="transparent"; this.style.backgroundPosition="right center"; b.ontouchstart = function() { this.style.backgroundColor="#CCCCCC"}; b.ontouchend = function() { this.style.backgroundColor="transparent";}; }
サンプルスクリプト(1)で全てのaタグにロールオーバーの処理がされるが、サンプルスクリプト(2)のように例外的な処理をさせたいaタグにid 名(この例ではNaviType2)を振り、例外処理を追加することができる。
◆HTMLの例
<p><a href="#" id="NaviType2">リンク</a></p>
これは「DOMではID名が最優先される」という原則があるゆえ、 document.getElementsByTagName()メソッドよりdocument.getElementById()メソッドが優先されるという特性を利用したハックである。
cssコーディングにおいても、DOMというのはまずID名を探しに行くので、class名やtag名よりもID名をセレクタにしたほうがより優先的に処理される。スタイル指定が込み入りすぎてきた場合などに「一瞬要素がピクンと下がって(上がって)から正しい位置に固定される」といった現象が発生した、といったケースには、該当箇所のスタイル付けをclass名でスタイル付けしているものとID名でスタイル付けされているものとに分け、処理の優先順位を再検討する、といった方法で改善が見込める場合がある。
スクリプト全体は次の通り。上記コードに加え、最後にwindow.addEventListenerでロールオーバーの関数をリセットしている。
iPhone/Androidなどのwebkit系のコーディングにおいて、普通のcssの:hoverの挙動ではhoverで色が変わったまま元に戻らず残るなどの不具合が生じた場合、このコードは試す価値がある。
function smartPhoneBGImgRollover() { var a = document.getElementsByTagName("a"); for(var i=0; i < a.length; i++) { a[i].style.backgroundPosition="left top"; a[i].ontouchstart = function() { this.style.backgroundPosition="left bottom"}; a[i].ontouchend = function() { this.style.backgroundPosition="left top"}; } } function smartPhoneBGColorRollover() { var b = document.getElementById("NaviType2"); this.style.backgroundColor="transparent"; this.style.backgroundPosition="right center"; b.ontouchstart = function() { this.style.backgroundColor="#CCCCCC"}; b.ontouchend = function() { this.style.backgroundColor="transparent";}; } if(window.addEventListener) { window.addEventListener("load", smartPhoneBGImgRollover, false); window.addEventListener("load", smartPhoneBGColorRollover, false); } else if(window.attachEvent) { window.attachEvent("onload", smartPhoneBGImgRollover); window.attachEvent("onload", smartPhoneBGColorRollover()); }