4 * http://d.hatena.ne.jp/uupaa/20100430/1272561922
8 if( window.addEventListener ){
9 X.Dom.Event = function( e ){
12 this.target = e.target; // xnode
13 this.currentTarget = e.currentTarget; // xnode
14 this.relatedTarget = e.relatedTarget; // xnode
15 this.eventPhase = e.eventPhase;
17 this.clientX = e.clientX;
18 this.clientY = e.clientY;
19 //this.screenX = e.screenX;
20 //this.screenY = e.screenY;
23 this.offsetX = e.offsetX || e.layerX;
24 this.offsetY = e.offsetY || e.layerY;
26 this.keyCode = e.keyCode;
27 this.altKey = e.altKey;
28 this.ctrlKey = e.ctrlKey;
29 this.shiftKey = e.shiftKey;
31 // http://www.programming-magic.com/20090127231544/
32 this.which = e.which || ( e.button + 1 ); // 左:1, 中:2, 右:3
34 // https://developer.mozilla.org/ja/docs/DOM/DOM_event_reference/mousewheel
35 if( e.wheelDeltaY !== undefined ){
36 this.wheelDeltaX = e.wheelDeltaX / 12;
37 this.wheelDeltaY = e.wheelDeltaY / 12;
39 if( e.wheelDelta !== undefined ){
40 this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;
42 if( e.detail !== undefined ){
43 this.wheelDeltaX = this.wheelDeltaY = - e.detail * 3;
45 this.wheelDeltaX = this.wheelDeltaY = 0;
48 if( e.constructor === window.TouchEvent ){
50 this.touches = e.touches;
51 this.changedTouches = e.changedTouches;
52 this.targetTouches = e.targetTouches;
53 //this.altKey = e.altKey;
54 //this.ctrlKey = e.ctrlKey;
55 this.metaKey = e.metaKey;
56 //this.shiftKey = e.shiftKey;
58 //this.target = e.target;
60 if( e.constructor === window.PointerEvent ){
62 this.currentPoint = e.currentPoint;
64 this.height = e.height;
65 this.timeStamp = e.timeStamp;
66 this.hwTimestamp = e.hwTimestamp;
67 this.intermediatePoints = e.intermediatePoints;
68 this.isPrimary = e.isPrimary;
69 this.pointerId = e.pointerId;
70 this.pointerType = e.pointerType;
71 this.pressure = e.pressure;
77 X.Dom.Event = function( e, element ){
82 this.target = e.srcElement; // xnode
83 this.currentTarget = element; // xnode
84 this.relatedTarget = e.formElement ? e.formElement : e.toElement; // xnode
85 this.eventPhase = e.srcElement === element ? 2: 3;
87 this.clientX = e.clientX;
88 this.clientY = e.clientY;
89 //this.screenX = e.screenX;
90 //this.screenY = e.screenY;
92 if( X.Dom._root ){ // uuu...
93 this.pageX = e.clientX + X.Dom._root.scrollLeft;
94 this.pageY = e.clientY + X.Dom._root.scrollTop;
97 if( X.UA.IE && 5 <= X.UA.IE ){
98 this.offsetX = e.offsetX;
99 this.offsetY = e.offsetY;
102 this.keyCode = e.keyCode;
103 this.altKey = e.altKey;
104 this.ctrlKey = e.ctrlKey;
105 this.shiftKey = e.shiftKey;
107 // http://www.programming-magic.com/20090127231544/
121 btn & 2 ? 3 : 0; // 左:1(click:0), 中:4, 右:2
123 this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;
127 X.Dom.Event.DOM_PRE_INIT = 0;
128 X.Dom.Event.DOM_INIT = 1;
129 X.Dom.Event.XDOM_READY = 2;
130 X.Dom.Event.VIEW_ACTIVATE = 3;
131 X.Dom.Event.VIEW_DEACTIVATE = 4;
132 X.Dom.Event.VIEW_RESIZED = 5;
133 // before_commit_update
134 X.Dom.Event.COMMIT_UPDATE = 6;
137 // X.Dom.Event.LOAD_BEFORE_STOP = 7;
138 X.Dom.Event.LOAD_ASSET_COMPLETE = 7;
139 X.Dom.Event.LOAD_ASSET_ERROR = 8;
141 X.Dom.Event.ANIME_BEFORE_START = 9;
142 X.Dom.Event.ANIME_START = 10;
143 X.Dom.Event.ANIME = 11;
144 X.Dom.Event.ANIME_END = 12;
145 X.Dom.Event.ANIME_BEFORE_STOP = 13; // xnode.stop() のみ、指定時間による停止では呼ばれない
146 X.Dom.Event.ANIME_STOP = 14;
147 X.Dom.Event._LAST_EVENT = 14; // ここに書いてあるイベントの最後の値 X.Dom.Event.ANIME_STOP と同じ値
150 X.Dom.Node.prototype.listen = function( type, arg2, arg3, arg4 /* [ listener || ( context + function ) || function ][ arguments ] */ ){
153 if( this._xnodeType === 0 || this._xnodeType === 3 || !arg2 ) return this;
155 ( !this._listeners || !this._listeners[ type ] ) && this._addEvent( type );
157 return typeof arg2 === 'function' ?
158 X.EventDispatcher.prototype.listen.call( this, type, this, arg2, arg3 ) :
159 X.EventDispatcher.prototype.listen.apply( this, arguments );
162 X.Dom.Node.prototype._addEvent =
163 document.removeEventListener ?
165 this._rawNode && this._rawNode.addEventListener( type, this, false );
167 document.detachEvent ?
169 if( !this._rawNode ) return;
170 this._handleEvent = this._handleEvent || X.Callback.create( this );
171 this._rawNode.attachEvent( 'on' + type, this._handleEvent );
174 var elm = this._ie4getRawNode();
176 this._handleEvent = elm[ 'on' + type ] = this._handleEvent || X.Callback.create( this );
180 X.Dom.Node.prototype.unlisten = function( type /* , arg2, arg3, arg4 */ ){
181 var list = this._listeners,
182 l = list && type && list[ type ] && list[ type ].length;
184 X.EventDispatcher.prototype.unlisten.apply( this, arguments );
186 if( type !== undefined && !this._dispatching && l && !list[ type ] ){
187 this._removeEvent( type );
193 X.Dom.Node.prototype._removeEvent =
194 document.removeEventListener ?
196 var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
198 elm.removeEventListener( type, this, false );
200 document.detachEvent ?
202 var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
204 elm.detachEvent( 'on' + type, this._handleEvent );
205 if( !this._listeners ){
206 X.Callback._correct( this._handleEvent );
207 delete this._handleEvent;
211 var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
213 elm[ 'on' + type ] = X.emptyFunction;
214 elm[ 'on' + type ] = '';
215 if( !this._listeners ){
216 X.Callback._correct( this._handleEvent );
217 delete this._handleEvent;
222 X.Dom.Node.prototype.handleEvent =
223 document.removeEventListener ?
225 var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( e ) );
227 if( ret & X.Callback.STOP_PROPAGATION ){
230 if( ret & X.Callback.PREVENT_DEFAULT ){
236 var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( event, this._rawNode ) );
238 if( ret & X.Callback.STOP_PROPAGATION ){
239 event.cancelBubble = true;
241 if( ret & X.Callback.PREVENT_DEFAULT ){
242 return event.returnValue = false;
247 // イベントの退避、dom が画面から抜かれる場合に実施しておく
248 X.Dom.Node.prototype._migrateEvent = function(){
249 var hash = this._listeners,
253 this._removeEvent( type );
258 X.Dom.Node.prototype._restoreEvent = function(){
259 var hash = this._listeners,
263 this._addEvent( type );
269 /* -----------------------------------------------
271 * Dean Edwards/Matthias Miller/John Resig
273 /* for ie9+/Mozilla/Opera9 */
274 if( document.addEventListener ){
275 X.Dom.Node._document.listenOnce( 'DOMContentLoaded', X.Dom._init );
277 if( 5 <= X.UA.IE && X.inHead ){
278 // if this script in Head
279 document.write( "<script id=__ie_onload defer src=javascript:void(0)><\/script>" );
280 X.Dom._script = document.getElementById( "__ie_onload" );
281 X.Dom._script.onreadystatechange = function(){
282 this.readyState === 'complete' && X.Dom._init();
285 if( X.UA.WebKit ){ // sniff
286 X.Timer.add( 10, function(){
287 if( !X.Dom._init ) return X.Callback.UN_LISTEN;
288 if( 'loaded|complete'.indexOf( document.readyState ) !== -1 ) return X.Dom._init();
292 /* for other browsers */
293 X.Dom.Node._window.listenOnce( 'load', X.Dom._init );
296 X.Dom.listenOnce( X.Dom.Event.XDOM_READY, function(e){ console.log( 'X.Dom XDomReady ' + X.Dom.ready ) } );
298 X.Dom.listenOnce( X.Dom.Event.VIEW_RESIZED, function(e){ console.log( 'X.Dom VIEW_RESIZED ' + e.w + 'x' + e.h ) } );
301 /* --------------------------------------
304 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
306 Node._html = document.documentElement ? new Node( document.documentElement ) : null;
308 var r = Node.root = new Node( document.body ),
310 createTree, n = 0, s;
311 r.appendTo = r.appendToRoot = r.before = r.after = r.clone = r.remove = r.destroy = r.prevNode = r.nextNode = new Function( 'return this' );
313 if( body.childNodes ){
314 createTree = function( xnode, elm, skipCleanup ){
315 var children = elm.childNodes,
319 for( ; i < children.length; ){
320 child = children[ i ];
321 switch( child.nodeType ){
323 if( !xnode._xnodes ) xnode._xnodes = [];
324 xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
325 _xnode.parent = xnode;
326 child.childNodes.length && createTree( _xnode, child, skipCleanup || 0 <= X.skipCleanupTagNames.indexOf( child.tagName.toLowerCase() ) );
329 if( skipCleanup || ( ( text = child.data ) && ( text = X.cleanupWhiteSpace( text ) ) !== ' ' ) ){
330 if( !skipCleanup ) child.data = text;
331 if( !xnode._xnodes ) xnode._xnodes = [];
332 xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
333 _xnode.parent = xnode;
337 elm.removeChild( child );
344 createTree( r, body );
347 createTree = function( xnode, children, skipCleanup ){
351 child, _xnode, f, tag, text;
353 xnode._ie4dirtyChildren = true;
355 child = children[ i ];
356 if( child.tagName === '!' ) continue;
358 while( j < xnode._xnodes.length ){
359 _xnode = xnode._xnodes[ j ];
360 _xnode.parent = xnode;
361 _xnode._ie4dirty = true;
362 if( _xnode._xnodeType === 1 ){
363 tag = child.tagName.toLowerCase();
364 if( _xnode._tag !== tag ){
365 alert( _xnode._tag + ' !== ' + child.tagName + ' * ' + child.outerHTML );
367 _xnode._rawNode = child;
368 !( _xnode._id = child.getAttribute( 'id' ) ) && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
369 child.setAttribute( 'UID', '' + _xnode._uid );
370 child.children.length && createTree( _xnode, child.children, skipCleanup || 0 <= X.skipCleanupTagNames.indexOf( tag ) );
376 if( _xnode._xnodeType === 3 ){
377 if( !skipCleanup && ( !( text = _xnode._text ) || ( text = X.cleanupWhiteSpace( text ) ) === ' ' ) ){
382 if( !skipCleanup ) _xnode._text = text;
386 if( !f ) alert( '**** ' + child.outerHTML );
391 Node.skipCreate = true;
392 r._xnodes.push.apply( r._xnodes, X.Dom.parse( body.innerHTML, true ) );
393 delete Node.skipCreate;
394 createTree( r, body.children );
395 r._ie4reserveUpdate();
396 //alert(n + ' ' + body.innerHTML);
398 //alert(n + ' ' + body.innerHTML);
403 //r.width = new Function( 'return X.Dom.getSize()[ 0 ]' );
404 //r.height = new Function( 'return X.Dom.getSize()[ 1 ]' );
406 Node._systemNode = r.create( 'div' ).className( 'hidden-sysyem-node' );
407 r._xnodes.splice( r._xnodes.indexOf( Node._systemNode ), 1 ); // hide from api user