OSDN Git Service

Version 0.6.17, X.Dom.Query work a little.
[pettanr/clientJs.git] / 0.6.x / js / dom / 12_XDomEvent.js
1 /**
2  * use X.Callback
3  * 
4  * http://d.hatena.ne.jp/uupaa/20100430/1272561922
5  * 
6  */
7
8 if( window.addEventListener ){
9         X.Dom.Event = function( e ){
10                 //this._event        = e;
11                 this.type          = e.type;
12                 
13                 //http://www.quirksmode.org/js/events_properties.html
14                 this.target        = e.target.nodeType === 3 ? e.target.parentNode : e.target;// defeat Safari bug // xnode
15                 
16                 this.currentTarget = e.currentTarget; // xnode
17                 this.relatedTarget = e.relatedTarget; // xnode
18                 this.eventPhase    = e.eventPhase;
19                 
20                 this.clientX       = e.clientX;
21                 this.clientY       = e.clientY;
22                 //this.screenX       = e.screenX;
23                 //this.screenY       = e.screenY;
24                 this.pageX         = e.pageX;
25                 this.pageY         = e.pageY;
26                 this.offsetX       = e.offsetX || e.layerX;
27                 this.offsetY       = e.offsetY || e.layerY;
28                 
29                 this.keyCode       = e.keyCode;
30                 this.altKey        = e.altKey;
31                 this.ctrlKey       = e.ctrlKey;
32                 this.shiftKey      = e.shiftKey;
33                 
34                 // http://www.programming-magic.com/20090127231544/
35                 this.which         = e.which || ( e.button + 1 ); // 左:1, 中:2, 右:3
36                 
37                 // https://developer.mozilla.org/ja/docs/DOM/DOM_event_reference/mousewheel
38                 if( e.wheelDeltaY !== undefined ){
39                         this.wheelDeltaX = e.wheelDeltaX / 12;
40                         this.wheelDeltaY = e.wheelDeltaY / 12;
41                 } else
42                 if( e.wheelDelta !== undefined ){
43                         this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;
44                 } else
45                 if( e.detail !== undefined ){
46                         this.wheelDeltaX = this.wheelDeltaY = - e.detail * 3;
47                 } else {
48                         this.wheelDeltaX = this.wheelDeltaY = 0;
49                 };
50                 
51                 if( e.constructor === window.TouchEvent ){
52                         // TouchEvent
53                         this.touches        = e.touches;
54                         this.changedTouches = e.changedTouches;
55                         this.targetTouches  = e.targetTouches;
56                         //this.altKey         = e.altKey;
57                         //this.ctrlKey        = e.ctrlKey;
58                         this.metaKey        = e.metaKey;
59                         //this.shiftKey       = e.shiftKey;
60                         //this.type           = e.type;
61                         //this.target         = e.target;
62                 } else
63                 if( e.constructor === window.PointerEvent ){
64                         // PointerEvent;
65                         this.currentPoint  = e.currentPoint;
66                         this.width         = e.width;
67                         this.height        = e.height;
68                         this.timeStamp     = e.timeStamp;
69                         this.hwTimestamp   = e.hwTimestamp;
70                         this.intermediatePoints = e.intermediatePoints;
71                         this.isPrimary     = e.isPrimary;
72                         this.pointerId     = e.pointerId;
73                         this.pointerType   = e.pointerType;
74                         this.pressure      = e.pressure;
75                         this.tiltX         = e.tiltX;
76                         this.tiltY         = e.tiltY;
77                 };
78         };
79 } else {
80         X.Dom.Event = function( e, element ){
81                 var btn;
82                 
83                 //this._event        = e;
84                 this.type          = e.type;
85                 this.target        = e.srcElement; // xnode
86                 this.currentTarget = element; // xnode
87                 this.relatedTarget = e.formElement ? e.formElement : e.toElement; // xnode
88                 this.eventPhase    = e.srcElement === element ? 2: 3;
89                 
90                 this.clientX       = e.clientX;
91                 this.clientY       = e.clientY;
92                 //this.screenX       = e.screenX;
93                 //this.screenY       = e.screenY;
94                 
95                 if( X.Dom._root ){ // uuu...
96                         this.pageX         = e.clientX + X.Dom._root.scrollLeft;
97                         this.pageY         = e.clientY + X.Dom._root.scrollTop;                 
98                 };
99                 
100                 if( X.UA.IE && 5 <= X.UA.IE ){
101                         this.offsetX       = e.offsetX; // イベントターゲット左上からの座標
102                         this.offsetY       = e.offsetY;                 
103                 } else {
104                         //this.offsetX       = e.x - e.srcElement.offsetLeft; // e.x はイベント発生要素の親要素を基準にした座標。
105                         //this.offsetY       = e.y - e.srcElement.offsetTop;    
106                 };
107                 
108                 this.keyCode       = e.keyCode;
109                 this.altKey        = e.altKey;
110                 this.ctrlKey       = e.ctrlKey;
111                 this.shiftKey      = e.shiftKey;
112                 
113                 // http://www.programming-magic.com/20090127231544/
114                 switch( this.type ){
115                         case 'click'    :
116                         case 'dblclick' :
117                                 this.which = 1;
118                                 break;
119                         case 'contextmenu' :
120                                 this.which = 3;
121                                 break;
122                         default :
123                                 btn = e.button;
124                                 this.which =
125                                         btn & 1 ? 1 :
126                                         btn & 4 ? 2 :
127                                         btn & 2 ? 3 : 0; // 左:1(click:0), 中:4, 右:2
128                 };
129                 this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;
130         };
131 };
132
133 X.Dom.Event.DOM_PRE_INIT        = 0;
134 X.Dom.Event.DOM_INIT            = 1;
135 X.Dom.Event.XDOM_READY          = 2;
136 X.Dom.Event.VIEW_ACTIVATE       = 3;
137 X.Dom.Event.VIEW_DEACTIVATE     = 4;
138 X.Dom.Event.VIEW_RESIZED        = 5;
139 // on_screen_keyboard_show
140 // on_screen_keyboard_hide
141 // before_commit_update
142 X.Dom.Event.COMMIT_UPDATE       = 6;
143 // hash_change
144 // before_unload
145 // X.Dom.Event.LOAD_BEFORE_STOP    = 7;
146 X.Dom.Event.LOAD_ASSET_COMPLETE = 7;
147 X.Dom.Event.LOAD_ASSET_ERROR    = 8;
148
149 X.Dom.Event.ANIME_BEFORE_START  = 9;
150 X.Dom.Event.ANIME_START         = 10;
151 X.Dom.Event.ANIME               = 11;
152 X.Dom.Event.ANIME_END           = 12;
153 X.Dom.Event.ANIME_BEFORE_STOP   = 13; // xnode.stop() のみ、指定時間による停止では呼ばれない
154 X.Dom.Event.ANIME_STOP          = 14;
155 X.Dom.Event._LAST_EVENT         = 14; // ここに書いてあるイベントの最後の値 X.Dom.Event.ANIME_STOP と同じ値
156
157
158 X.Dom.Node.prototype.listen = function( type, arg2, arg3, arg4 /* [ listener || ( context + function ) || function ][ arguments ] */ ){
159         var elm;
160         
161         if( this._xnodeType === 0 || this._xnodeType === 3 || !arg2 ) return this;
162         
163         ( !this._listeners || !this._listeners[ type ] ) && this._addEvent( type );
164         
165         return typeof arg2 === 'function' ?
166                 X.EventDispatcher.prototype.listen.call( this, type, this, arg2, arg3 ) :
167                 X.EventDispatcher.prototype.listen.apply( this, arguments );
168 };
169
170 X.Dom.Node.prototype._addEvent =
171         document.removeEventListener ?
172                 (function( type ){
173                         this._rawNode && this._rawNode.addEventListener( type, this, false );
174                 }) :
175         document.detachEvent ?
176                 (function( type ){
177                         if( !this._rawNode ) return;
178                         this._handleEvent = this._handleEvent || X.Callback.create( this );
179                         this._rawNode.attachEvent( 'on' + type, this._handleEvent );
180                 }) :
181                 (function( type ){
182                         var elm = this._ie4getRawNode();
183                         if( !elm ) return;
184                         this._handleEvent = elm[ 'on' + type ] = this._handleEvent || X.Callback.create( this );
185                 });
186
187
188 X.Dom.Node.prototype.unlisten = function( type /* , arg2, arg3, arg4 */ ){
189         var list = this._listeners,
190                 l    = !this._dispatching && list && type !== undefined && list[ type ] && list[ type ].length;
191         
192         X.EventDispatcher.prototype.unlisten.apply( this, arguments );
193         
194         l && !list[ type ] && this._removeEvent( type );
195         
196         return this;
197 };
198
199 X.Dom.Node.prototype._removeEvent =
200         document.removeEventListener ?
201                 (function( type ){
202                         var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
203                         if( !elm ) return;
204                         elm.removeEventListener( type, this, false );
205                 }) :
206         document.detachEvent ?
207                 (function( type ){
208                         var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
209                         if( !elm ) return;
210                         elm.detachEvent( 'on' + type, this._handleEvent );
211                         if( !this._listeners ){
212                                 X.Callback._correct( this._handleEvent );
213                                 delete this._handleEvent;
214                         };
215                 }) :
216                 (function( type ){
217                         var elm = this._ie4getRawNode ? this._ie4getRawNode() : this._rawNode;
218                         if( !elm ) return;
219                         elm[ 'on' + type ] = X.emptyFunction;
220                         elm[ 'on' + type ] = '';
221                         if( !this._listeners ){
222                                 X.Callback._correct( this._handleEvent );
223                                 delete this._handleEvent;
224                         };
225                 });
226
227
228 X.Dom.Node.prototype.handleEvent =
229         document.removeEventListener ?
230                 (function( e ){
231                         var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( e ) );
232
233                         if( ret & X.Callback.STOP_PROPAGATION ){
234                                 e.stopPropagation();
235                         };
236                         if( ret & X.Callback.PREVENT_DEFAULT ){
237                                 e.preventDefault();
238                                 return false;
239                         };
240                 }) :
241                 (function(){
242                         var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( event, this._rawNode ) );
243
244                         if( ret & X.Callback.STOP_PROPAGATION ){
245                                 event.cancelBubble = true;
246                         };
247                         if( ret & X.Callback.PREVENT_DEFAULT ){
248                                 return event.returnValue = false;
249                         };
250                 });
251
252
253 // イベントの退避、dom が画面から抜かれる場合に実施しておく
254 X.Dom.Node.prototype._migrateEvent = function(){
255         var hash = this._listeners,
256                 type;
257         if( !hash ) return;
258         for( type in hash ){
259                 this._removeEvent( type );
260         };
261 };
262
263 // 退避したイベントの復帰
264 X.Dom.Node.prototype._restoreEvent = function(){
265         var hash = this._listeners,
266                 type;
267         if( !hash ) return;
268         for( type in hash ){
269                 this._addEvent( type );
270         };
271 };
272
273
274
275 /* -----------------------------------------------
276  * Document Ready
277  *  Dean Edwards/Matthias Miller/John Resig
278  */
279 /* for ie9+/Mozilla/Opera9 */
280 if( document.addEventListener ){
281         X.Dom.Node._document.listenOnce( 'DOMContentLoaded', X.Dom._init );
282 } else
283 if( 5 <= X.UA.IE && X.inHead ){
284         // if this script in Head
285         document.write( "<script id=__ie_onload defer src=javascript:void(0)><\/script>" );
286         X.Dom._script = document.getElementById( "__ie_onload" );
287         X.Dom._script.onreadystatechange = function(){
288                 this.readyState === 'complete' && X.Dom._init();
289         };
290 } else
291 if( X.UA.WebKit ){ // sniff
292         X.Timer.add( 10, function(){
293                 if( !X.Dom._init ) return X.Callback.UN_LISTEN;
294                 if( 'loaded|complete'.indexOf( document.readyState ) !== -1 ) return X.Dom._init();
295         });
296 };
297
298 /* for other browsers */
299 X.Dom.Node._window.listenOnce( 'load', X.Dom._init );
300
301 //
302 X.Dom.listenOnce( X.Dom.Event.XDOM_READY, function(e){ console.log( 'X.Dom XDomReady ' + X.Dom.readyState ) } );
303
304 X.Dom.listenOnce( X.Dom.Event.VIEW_RESIZED, function(e){ console.log( 'X.Dom VIEW_RESIZED ' + e.w + 'x' + e.h ) } );
305
306
307 /* --------------------------------------
308  *  load
309  */
310 X.Dom.listenOnce( X.Dom.Event.DOM_INIT, function(){
311         
312         Node._html = document.documentElement ? new Node( document.documentElement ) : null;
313         //alert( document.all.tags('html')[ 0 ].tagName );
314         var r    = Node.root = new Node( document.body ),
315                 body = r._rawNode,
316                 createTree, n = 0, s;
317         r.appendTo = r.appendToRoot = r.before = r.after = r.clone = r.remove = r.destroy = r.prevNode = r.nextNode = new Function( 'return this' );
318         
319         if( body.childNodes ){
320                 /*
321                  * body.innerHTML(可能なら outerHTML を使って属性を控える)
322                  */
323                 createTree = function( xnode, elm, skipCleanup ){
324                         var     children = elm.childNodes,
325                                 i = 0,
326                                 l = children.length,
327                                 child, _xnode, text;
328                         for( ; i < children.length; ){
329                                 child = children[ i ];
330                                 switch( child.nodeType ){
331                                         case 1 :
332                                                 if( !xnode._xnodes ) xnode._xnodes = [];
333                                                 xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
334                                                 // attr の取得
335                                                 _xnode.parent = xnode;
336                                                 child.childNodes.length && createTree( _xnode, child, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( child.tagName ) );//.toLowerCase() ) );
337                                                 break;
338                                         case 3 :
339                                                 if( skipCleanup || ( ( text = child.data ) && ( text = X.Dom.cleanupWhiteSpace( text ) ) !== ' ' ) ){
340                                                         if( !skipCleanup ) child.data = text;
341                                                         if( !xnode._xnodes ) xnode._xnodes = [];
342                                                         xnode._xnodes[ xnode._xnodes.length ] = _xnode = new Node( child );
343                                                         _xnode.parent = xnode;
344                                                         break;                                                  
345                                                 };
346                                         default :
347                                                 elm.removeChild( child );
348                                                 ++n;
349                                                 continue;                                                               
350                                 };
351                                 ++i;
352                         };
353                 };
354                 createTree( r, body );
355         } else
356         if( body.children ){
357                 createTree = function( xnode, children, skipCleanup ){
358                         var i = 0,
359                                 l = children.length,
360                                 j = 0,
361                                 child, _xnode, f, tag, text;
362
363                         xnode._ie4dirtyChildren = true;
364                         for( ; i < l; ++i ){
365                                 child = children[ i ];
366                                 if( child.tagName === '!' ) continue;
367                                 f = false;
368                                 while( j < xnode._xnodes.length ){
369                                         _xnode = xnode._xnodes[ j ];
370                                         _xnode.parent    = xnode;
371                                         _xnode._ie4dirty = true;
372                                         if( _xnode._xnodeType === 1 ){
373                                                 tag = child.tagName; //.toLowerCase();
374                                                 if( _xnode._tag !== tag ){
375                                                         alert( _xnode._tag + ' !== ' + child.tagName + ' * ' + child.outerHTML );
376                                                 } else {
377                                                         _xnode._rawNode = child;
378                                                         //!( _xnode._id = child.getAttribute( 'id' ) ) && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
379                                                         !_xnode._id && child.setAttribute( 'id', ( _xnode._ie4uid = 'ie4uid' + _xnode._uid ) );
380                                                         child.setAttribute( 'UID', '' + _xnode._uid );
381                                                         child.children.length && createTree( _xnode, child.children, skipCleanup || 0 <= X.Dom.skipCleanupTagNames.indexOf( tag ) );
382                                                         f = true;
383                                                         ++j;
384                                                         break;
385                                                 };
386                                         } else
387                                         if( _xnode._xnodeType === 3 ){
388                                                 if( !skipCleanup && ( !( text = _xnode._text ) || ( text = X.Dom.cleanupWhiteSpace( text ) ) === ' ' ) ){
389                                                         _xnode.remove();
390                                                         ++n;
391                                                         continue;
392                                                 };
393                                                 if( !skipCleanup ) _xnode._text = text;
394                                         };
395                                         ++j;
396                                 };
397                                 if( !f ) alert( '**** ' + child.outerHTML );
398                         };
399                 };
400                 
401                 r._xnodes = [];
402                 Node.skipCreate = true;
403                 /*
404                  * http://support.microsoft.com/kb/812417/ja
405                  * PRB: outerHTML の HTML 要素のプロパティは、既定の属性は表示されません。
406                  * 
407                  * body.innerHTML でなく、 body.outerHTML
408                  */
409                 r._xnodes.push.apply( r._xnodes, X.Dom.parse( body.innerHTML, true ) );
410                 delete Node.skipCreate;
411                 createTree( r, body.children );
412                 //alert(n +  ' ' + body.innerHTML);
413                 r._ie4reserveUpdate();
414                 //alert(n +  ' ' + body.innerHTML);
415                 r._ie4startUpdate();
416                 alert(n +  ' ' + body.innerHTML);
417         } else {
418                 
419         };
420         
421         //r.width  = new Function( 'return X.Dom.getSize()[ 0 ]' );
422         //r.height = new Function( 'return X.Dom.getSize()[ 1 ]' );
423         
424         Node._systemNode = r.create( 'div' ).className( 'hidden-sysyem-node' );
425         r._xnodes.splice( r._xnodes.indexOf( Node._systemNode ), 1 ); // hide from api user
426 } );
427
428