コラム・コーディングの鉄則(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());
}