WaSP の左上の画像のロールオーバーは
<img id="logo" src="/img/logo.gif" height="100" width="103" alt="Web Standards Project logo" />
生 HTML はこんなかんじで onmouseover/onmouseout 属性を記述せず、 JavaScript で
function initRollOvers() { var logo; if (document.getElementById) { logo = document.getElementById('logo'); } else { return false; } /*if (document.all) {*/ logo.onmouseover = swapI; logo.onmouseout = swapI; /*} else { logo.addEventListener('mouseover',swapI,false); logo.addEventListener('mouseout',swapI,false); }*/ return true; } function swapI(e) { e = (e) ? e : event; thisI = (e.srcElement) ? e.srcElement : e.target; if((thisI.status != 'a') && (thisI.status != 'p')) { thisI.src = '/img/' + thisI.id + '_a.gif'; thisI.status='a'; } else if(thisI.status != 'p') { thisI.src='/img/'+thisI.id+'.gif'; thisI.status=''; } }
こんな風にして id 属性に logo という画像を持つ img 要素の onmouseover と onmouseout をページ表示時に動的に変更することで実現していました。
似たような手法は Nikon のサイトや Yamaha のサイトでも 利用されています(両方同じ業者さんみたい)。
もう一つ、今度は別のところで、これと似た手法を見ました。
del.icio.us では delete リンクをクリックしたときに ちょっとした工夫をしているのですが、 このちょっとした工夫は下記のように実現されています。
delete リンクの HTML ソースはこんなかんじ。
<a href="/yohei?delete=9d7b7c953b1e47a7d82e791848f43899" class="rm" rel="nofollow">delete</a>
onclick 属性がなく Javascript の影も形もありません。
どうなっているかというと、ヘッダでロードしている Javascript で
function rmPostAddEvent() { var all = getElementsByClass(document.getElementById('posts'),'rm','a') for(var i = 0, o; o = all[i]; i++) o.onclick = function(){ return rmPost(this) } } function rmPost(o) { o.style.display = 'none' var s = document.createElement('span'); s.o = o s.innerHTML = '<span class="important">delete this post?</span> <a href="'+o.href+'">yes</a> / <a href="'+o.href.replace(/(\?|&)delete=[^&]*&?/,'$1')+'" onclick="this.parentNode.o.style.display=\'inline\';this.parentNode.parentNode.removeChild(this.parentNode);return false">no</a>' o.parentNode.insertBefore(s, o) return false }
とやって、yes/no を追加しています。
ロールオーバーの例と del.icio.us の例で共通するのは、 静的なコンテンツ部分(HTML)と動的な UI の振る舞い制御部分(JavaScript)を 完全に別ファイルに分けているところです。 もちろんこうするためには class 属性や id 属性の値にコンベンションが必要となるのですが、 このようにアクションとコンテンツを分離することで、以下のようなメリットがありそうです。
- コンテンツ生成プログラムの効率化
- onmouseover などイベント系の属性を記述しないですむので、HTML 生成プログラムが効率化しそうです
- メンテナンス性の向上
- 上の項目につながりますが、問題があるのがデータなのか、スクリプトなのかの区別がつきやすそうです
- HTML サイズの縮小
- 要素毎に属性を記述しないですむので、ネットワーク転送量が減少します
さらに、class や id の値のコンベンションという意味で、microformats との相性もよさそうです。
さらに面白いと思ったのは、 この動的・静的がサーバから見たときと、クライアントから見たときにちょうど対称的になっているところです。 サーバから見ると、生成するデータ(ブックマーク一覧)こそが動的であり、 そこに yes/no リンクという振る舞いを与える JavaScript プログラムは静的です(del.icio.us の URL にも static とある)。 逆にクライアント(ブラウザ)から見ると、 HTML に入っているブックマーク一覧というデータは静的ですが、 JavaScript によってそれらを動的に変更しています。
こういうのってかなり抽象化できていて、正にデザインパターンと呼べそうな気がするのですが、 何か名前があるんでしょうか(NDO メソッド)。ちょっと探してみたけれど、見つけられませんでした。 勝手に behavior injection(振る舞いの注入) とか action injection (アクションの注入) と想像して検索してみたのだけれど。
> こういうのってかなり抽象化できていて、正にデザインパターンと呼べそうな気がするのですが
返信削除考え方的にはアスペクト指向、実装的にはobserverパターンなのではないでしょうか。
gorou さん、コメントありがとうございます。
返信削除なるほど考え方は確かにアスペクト指向っぽいですね。参考になります