Webページ宣言イベントハンドラー

Backbase AJAXフレームワークと緊密に連携して、ハンドラーが使用される場所で定義されている場合、宣言型イベントハンドラーを使用する便利さを感じました。

ボタンのイベントクリックハンドラーの例を次に示します。

< button >

< tb:handler event ='click' >

alert(' click ')

</ tb:handler >

</ button >




* This source code was highlighted with Source Code Highlighter .




実装の基礎を簡単に説明してください。 ハンドラーを宣言するには、名前空間で非標準のタグを使用します(xhtmlでの正しい操作のため)。 ページの読み込み時に、すべての要素を見つけて、実際のイベントハンドラーを作成します。 使いやすさに加えて、このアプローチにより、ハンドラーの機能を拡張し、IEでイベントを処理したり、 キーボードイベントを共通の分母に導くなど、さまざまなブラウザーで作業を統合することができます。



最初のバージョンは、主な実装のアイデアを示しています。

if (!window.ev){

// ,

window.ev = {};

//

ev.namespaceURI = 'http://tedbeer.net' ;

// ,

ev.browser = {ie : false , standard : false };

ev.browser.standard = Boolean( document .addEventListener);

ev.browser.ie = '\v' == 'v' ; //for other browsers it's a vertical tab - \u000B



//

ev.init = function ( event ){

var arr = [];

if (ev.browser.ie) {

arr = document .getElementsByTagName( 'handler' );

for ( var i = 0; i < arr.length; i++) {

if (arr[i].tagUrn == ev.namespaceURI) {

arr[i].parentNode[ 'on' + arr[i].getAttribute( 'event' )] =

new Function( 'event' , arr[i].innerText);

arr[i].innerText = '' ; //clean up to avoid displaying

}

}

} else {

arr = document .getElementsByTagNameNS(ev.namespaceURI, 'handler' ); //xhtml

if (!arr.length) //html

arr = document .getElementsByTagName( 'tb:handler' );

for ( var i = 0; i < arr.length; i++) {

arr[i].parentNode.addEventListener( arr[i].getAttribute( 'event' ),

new Function( 'event' , arr[i].textContent), false );

arr[i].textContent = '' ; //clean up to avoid displaying

}

}

};



if (ev.browser.standard)

window.addEventListener( 'load' , ev.init, false );

else

window.onload = ev.init;

}




* This source code was highlighted with Source Code Highlighter .






テストページ:

< style type ="text/css" >

.test-div {

width: 200px;

height: 200px;

background-color: #6699FF;

}

</ style >

< script type ="text/javascript" src ="ev.js" ></ script >

< div class ="test-div" >

< tb:handler event ='click' >

alert('click');

</ tb:handler >

</ div >



* This source code was highlighted with Source Code Highlighter .






オンラインテスト コードev.js



コードは何をしているのかを簡単に理解できるほど十分に透過的ですが、意図的に誤解を招くような妨害が含まれています。

有能な開発者はより多くのショールを見つけるでしょう、私はこれを私の宿題として残します:-)コメントに何か書くことがあるように。 次のコードでは、これらの妨害を修正し、次の機能を追加します。 コードは少し複雑になっています。

if (!window.ev){

// ,

window.ev = {};

//

ev.namespaceURI = 'http://tedbeer.net' ;

// ,

ev.browser = {ie : false , standard : false };

ev.browser.standard = Boolean( document .addEventListener);

ev.browser.ie = '\v' == 'v' ; //for other browsers it's a vertical tab - \u000B



//

ev.setEventHandler = function (oNode, oEventNode){

if ( this .browser.ie) {

var vHandler = function (){

var self = arguments.callee;

var ev = window. event ;

ev.target = ev.srcElement;

ev.currentTarget = self.node.parentNode;

var sMatch = self.node.getAttribute( 'match' );

if (sMatch === null || Sizzle.matches(sMatch, [ev.target]).length > 0)

return self.handler(ev);

}

vHandler.node = oEventNode;

var sBody = oEventNode.innerText;

if (!sBody.length) { // CDATA (xhtml)

for ( var i = 0; i < oEventNode.childNodes.length; i++)

if (oEventNode.childNodes[i].nodeType) { //4 or 8 - CDATA or comment

sBody = oEventNode.childNodes[i].nodeValue;

break ; //

}

} else //

oEventNode.innerText = '' ;

//

try {

vHandler.handler = new Function( 'event' , sBody);

} catch (e) { //

alert(e.message + ':\n' + sBody)

}

oNode.attachEvent( 'on' + oEventNode.getAttribute( 'event' ), vHandler);

} else {

var vHandler = function ( event ){

var self = arguments.callee;

var sMatch = self.node.getAttribute( 'match' );

if (sMatch === null || Sizzle.matches(sMatch, [ event .target]).length > 0)

return self.handler( event );

}

vHandler.node = oEventNode;

var sBody = oEventNode.textContent;

if (!sBody.length) { // CDATA (xhtml)

for ( var i = 0; i < oEventNode.childNodes.length; i++) {

if (oEventNode.childNodes[i].nodeType) { //4 or 8 - CDATA or comment

sBody = oEventNode.childNodes[i].nodeValue;

break ; //

}

}

} else //

oEventNode.textContent = '' ;

//

try {

vHandler.handler = new Function( 'event' , sBody);

} catch (e) { //

alert(e.message + ':\n' + sBody)

}

oNode.addEventListener( oEventNode.getAttribute( 'event' ), vHandler, false );

}

};



ev.init = function ( event ){

var arr = [];

if ( document .getElementsByTagNameNS) { //xhtml

arr = document .getElementsByTagNameNS(ev.namespaceURI, 'handler' )

}

if (!arr.length) {

if (ev.browser.ie) { //ie

arr = []; //convert a nodelist to array

var arr2 = document .getElementsByTagName( 'handler' );

for ( var i = 0; i < arr2.length; i++) {

if (arr2[i].tagUrn == ev.namespaceURI) { //accept our namespace only

arr.push(arr2[i]);

}

}

} else //html

arr = document .getElementsByTagName( 'tb:handler' );

}

for ( var i = 0; i < arr.length; i++) {

ev.setEventHandler(arr[i].parentNode, arr[i]);

}

};

if (ev.browser.standard) {

window.addEventListener( 'load' , ev.init, false );

} else

window.attachEvent( 'onload' , ev.init);

}




* This source code was highlighted with Source Code Highlighter .




テストページ:
.test-div {

width: 200px;

height: 200px;

background-color: #6699FF;

border-bottom: 1px dotted #666666;

}

.inner-div {

width: 100px;

height: 100px;

background-color: #66CCCC;

}

.test-div2 {

width: 200px;

height: 200px;

background-color: #6699FF;

}

.inner-div2 {

width: 100px;

height: 100px;

background-color: #66CCCC;

}

</ style >

< script type ="text/javascript" src ="sizzle.js" ></ script >

<script type= "text/javascript" src= "ev2.js" > </ script >

</ head >

< body >

Click on boxes to see what event handlers are called.

< div class ="test-div" >

< tb:handler event ='click' match ='.inner-div' ><!--

alert('A: ' + event.target.className)

// comment

alert('<A2>')

--></ tb:handler >

< tb:handler event ='click' match ='.test-div' ><!--

alert('B: ' + event.target.className)

// comment

alert('<B2>
')

--></ tb:handler >

< div class ="inner-div" > XXX </ div >

</ div >

< div class ="test-div2" >

< tb:handler event ='click' match ='.inner-div2' >

alert('C: ' + event.target.className)

</ tb:handler >

< div class ="inner-div2" > YYY </ div >

</ div >








*このソースコードは、 ソースコードハイライターで強調表示されました。


オンラインhtmlテスト xhtmlテスト コードev2.js

このコードはコメント内にあり、ブラウザーの解析を回避し、スペースと改行を保持します。 xhtmlの場合 、コードをCDATAセクションに配置します。

CSSセレクターが機能するためのシズルライブラリの使用に注意してください。 同様に、独自のイベントハンドラー機能拡張を追加できます。



結論

上記のコードはほんの小さなデモンストレーションです。 本格的なプロジェクトに適したフレームワークを探していて、宣言型言語を気にしない場合は、 BackbaseAmpleSDKをご覧になることをお勧めします。 実際、1人が両方のフレームワークに取り組みました。 後者( AmpleSDK )については、まもなくayaxinに関する発表があるはずです。 著者はまだ古い契約に関する彼の権利に驚いており、ソースコードを開くことができません。 しかし、この期間が過ぎるとすぐに、彼はフレームワークをオープンソースにすることを約束しました。 フレームワークは他の多くのモジュール(svg、smil、xinclude、schema ...)を実装します。これらはすべてクロスブラウザー(IEを含む)であり、最も重要なことは、自家製APIではなく標準APIを使用します。 したがって、使用を開始するのは簡単です-単に標準に目を通すだけです。



脅威 このコードは、プロジェクトに制限なく使用できます。 どこからもコピーされません。 私は基本的に、これを回避するために利用可能なフレームワークの実装を見ていませんでした。

UPD 熟したAmpleSDKの発表はここにあります: ajaxian.com/archives/ample-sdk-browser-in-a-browser



All Articles