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