2008年2月21日木曜日

addEventListener(), attachEvent() を使ってaddLoadEvent()

addLoadEvent() は少し古い技術なので、DOM操作で使われるaddEventListener()、attachEvent() を利用して書き換えてみました。

function addLoadEvent(func) {
 if(typeof window.addEventListener == 'function'){ // addEventListenerが使えるなら
  window.addEventListener('load', func, false);
  return true;
 } else if(typeof window.attachEvent == 'object'){ // attachEventが使えるなら(IE用)
  window.attachEvent('onload', func);
  return true;
 }

 var oldonload = window.onload; // どちらも使えないなら
 if (typeof window.onload != 'function') {
  window.onload = func;
 } else {
  window.onload = function() {
   oldonload();
   func();
  }
 }
}

addEventListener() と attachEvent()

addEventListener() と attachEvent() は、DOMで扱われるノードに対するイベント(マウスクリックとか)をトリガーとして、メソッドを追加します。
addEventListener() はW3Cで定義された標準メソッドで、attachEvent() はIEの独自拡張です。IEは addEventListener() を利用することができません。
attachEvent() は追加されたメソッドの処理順がめちゃくちゃなんですが、window.onload よりは使い勝手がよいので採用しました。

window.onloadだけで作られたaddLoadEvent()との違い

まず、次のJavaScriptコードを実行してみてください。

<script type='text/javascript'>
function addLoadEvent(func) {
 var oldonload = window.onload;
 if (typeof window.onload != 'function') {
  window.onload = func;
 } else {
  window.onload = function() {
   oldonload();
   func();
  }
 }
}

function hello(){
 alert('Hello, World!');
}

function yes(){
 alert('Yes, my master.');
}

addLoadEvent(hello);
window.onload = yes;
</script>

上記コードを実行すると、yes() が実行され、hello()が実行されない結果に終わります。
addEventListener() で window.onload 追加したメソッドが window.onload = yes; によって上書きされてしまっているのです。

上書きされないようにするためには addLoadEvent() を addEventListener() を利用したコードに書き換えます。

<script type='text/javascript'>
function addLoadEvent(func) {
 if(typeof window.addEventListener == 'function'){
  window.addEventListener('load', func, false);
  return true;
 } else if(typeof window.attachEvent == 'object'){
  window.attachEvent('onload', func);
  return true;
 }

 var oldonload = window.onload;
 if (typeof window.onload != 'function') {
  window.onload = func;
 } else {
  window.onload = function() {
   oldonload();
   func();
  }
 }
}

function hello(){
 alert('Hello, World!');
}

function yes(){
 alert('Yes, my master.');
}

addLoadEvent(hello);
window.onload = yes;
</script>

これで hello(), yes() 両方の関数が有効になりました。
addEventListener() は window.onload に関数を格納しているわけではないので、window.onload = yes; が実行されて機能が上書きされる心配はありません。

どんな状況で addLoadEvent() が役に立つのか

  • 他人が書いたコードに機能を追加するとき
  • Proxomitron, Greasemonkey 等で既存サイトに機能を追加するとき

# 逆から見れば、一からJavaScriptコードを書くときには、addLoadEvent() を使わず addEventListener() を使った方がわかりやすいかもしれません。

ラベル: ,

2008年2月20日水曜日

JavaScriptでinclude

JavaScriptはVer.2.0から include が実装されるそうですが、それまでは長いコードを一つのJSファイルにまとめると管理が大変です。かといって、複数ファイルにコードを分割して、script要素を複数宣言するのも手間がかかります。
そこで、includeの代用となる関数を作りました。

// 外部JavaScriptをインクルード
function include_javascript(jspath){
 jspath = jspath.toString();

 var scriptElm = document.createElement('script');
 scriptElm.type = 'text/javascript';
 scriptElm.charset = 'utf-8';
 scriptElm.src = jspath;
 var head = document.getElementsByTagName('head')[0];
 head.appendChild(scriptElm);
}

// 外部JavaScript群をインクルード
function include_javascripts(jspaths){

 for(var key in jspaths){
  include_javascript(jspaths[key]);
 }
}

関数の使い方

1つの外部JavaScriptをincludeするには、以下のように書きます。

include_javascript('./js/hogehoge.js');

複数の外部JavaScriptをincludeするには、以下のように書きます。

var js_path = [
 './js/hogehoge1.js',
 './js/hogehoge2.js'
];
include_javascripts(js_path);

注意点

引数のJavaScriptパスはHTML文書からの相対パスか絶対パスを指定してください。(関数を呼び出したJavaScriptファイルからの相対パスではありません)

仕組み

include_javascript() は引数で指定された外部JavaScriptファイルを呼び出すscript要素を生成します。
include_javascripts() は引数で渡された配列の要素数だけ include_javascript() を繰り返します。

ラベル: ,