l'essentiel est invisible pour les yeux

Tuesday, January 08, 2008

[Javascript] Prototype.jsのEventオブジェクトを拡張する

prototype.js 1.6では、Element#observeで登録したイベントハンドラに渡されるEventオブジェクトが、Event.extendを呼び出したPrototype.js独自のEventオブジェクトで拡張されていますが、Eventオブジェクトに任意のメソッドを追加する方法です。

例えば、親ノードの座標からの相対座標を取得する、Event#relativeX, Event#relativeYをEventオブジェクトに追加する際は次のようになる。コードは単純だが、Event.addMethodsの引数に渡されるオブジェクトで定義されている要素が、eventを参照可能にするため、Event.extend内で再びメソッドを定義し直して、eventをスコープに加える必要がある。クロージャーを用いるメソッドの再定義は、関数のスコープを自由に変更できるので便利である。

※ Firefox 2.x, Safari 3で動作確認。IE未確認。


// Add arbitrary methods as instance methods of Event object
Event.addMethods = function(aMethods) {
var _extend = Event.extend;

Event.extend = function(event) {
var methods = Object.keys(aMethods).inject({}, function(m, name) {
Event.Methods[name] = aMethods[name];
m[name] = Event.Methods[name].methodize();
return m;
});
_extend(event);
Object.extend(Prototype.Browser.IE ? event : Event.prototype, methods);
return event;
};
};

// example
Event.addMethods({
relativeX: function(event) {
var origin = event.element().cumulativeOffset();
return event.pointerX() - origin[0];
},
relativeY: function(event) {
var origin = event.element().cumulativeOffset();
return event.pointerY() - origin[1];
}
});




イベントリスナ

Element.extend(node).observe('mousemove', function(event) {
console.log('pointerX: %d, pointerY: %d, relativeX: %d, relativeY: %d',
event.pointerX(), event.pointerY(), event.relativeX(), event.relativeY());
});