OSDN Git Service

Version 0.6.12.
[pettanr/clientJs.git] / 0.6.x / js / dom / 11_XDomEvent.js
1 /**
2  * use X.Callback
3  */
4
5 if( window.addEventListener ){
6         X.Dom.Event = function( e ){
7                 this._event        = e;
8                 this.type          = e.type;
9                 this.target        = e.target; // xnode
10                 this.currentTarget = e.currentTarget; // xnode
11                 this.relatedTarget = e.relatedTarget; // xnode
12                 this.eventPhase    = e.eventPhase;
13                 
14                 this.clientX       = e.clientX;
15                 this.clientY       = e.clientY;
16                 //this.screenX       = e.screenX;
17                 //this.screenY       = e.screenY;
18                 this.pageX         = e.pageX;
19                 this.pageY         = e.pageY;
20                 this.offsetX       = e.offsetX || e.layerX;
21                 this.offsetY       = e.offsetY || e.layerY;
22                 
23                 this.keyCode       = e.keyCode;
24                 this.altKey        = e.altKey;
25                 this.ctrlKey       = e.ctrlKey;
26                 this.shiftKey      = e.shiftKey;
27                 
28                 // http://www.programming-magic.com/20090127231544/
29                 this.which         = e.which || ( e.button + 1 ); // 左:1, 中:2, 右:3
30                 
31                 // https://developer.mozilla.org/ja/docs/DOM/DOM_event_reference/mousewheel
32                 if( e.wheelDeltaY !== undefined ){
33                         this.wheelDeltaX = e.wheelDeltaX / 12;
34                         this.wheelDeltaY = e.wheelDeltaY / 12;
35                 } else
36                 if( e.wheelDelta !== undefined ){
37                         this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;
38                 } else {
39                         this.wheelDeltaX = this.wheelDeltaY = - e.detail * 3;
40                 };
41                 
42                 if( e.constructor === window.TouchEvent ){
43                         // TouchEvent
44                         this.touches        = e.touches;
45                         this.changedTouches = e.changedTouches;
46                         this.targetTouches  = e.targetTouches;
47                         //this.altKey         = e.altKey;
48                         //this.ctrlKey        = e.ctrlKey;
49                         this.metaKey        = e.metaKey;
50                         //this.shiftKey       = e.shiftKey;
51                         //this.type           = e.type;
52                         //this.target         = e.target;
53                 } else
54                 if( e.constructor === window.PointerEvent ){
55                         // PointerEvent;
56                         this.currentPoint  = e.currentPoint;
57                         this.width         = e.width;
58                         this.height        = e.height;
59                         this.timeStamp     = e.timeStamp;
60                         this.hwTimestamp   = e.hwTimestamp;
61                         this.intermediatePoints = e.intermediatePoints;
62                         this.isPrimary     = e.isPrimary;
63                         this.pointerId     = e.pointerId;
64                         this.pointerType   = e.pointerType;
65                         this.pressure      = e.pressure;
66                         this.tiltX         = e.tiltX;
67                         this.tiltY         = e.tiltY;
68                 };
69         };
70 } else {
71         X.Dom.Event = function( e, element ){
72                 var btn;
73                 
74                 this._event        = e;
75                 this.type          = e.type;
76                 this.target        = e.srcElement; // xnode
77                 this.currentTarget = element; // xnode
78                 this.relatedTarget = e.formElement ? e.formElement : e.toElement; // xnode
79                 this.eventPhase    = e.srcElement === element ? 2: 3;
80                 
81                 this.clientX       = e.clientX;
82                 this.clientY       = e.clientY;
83                 //this.screenX       = e.screenX;
84                 //this.screenY       = e.screenY;
85                 this.pageX         = e.clientX + document.body.scrollLeft;
86                 this.pageY         = e.clientY + document.body.scrollTop;
87                 
88                 if( X.UA.IE && 5 <= X.UA.IE ){
89                         this.offsetX       = e.offsetX;
90                         this.offsetY       = e.offsetY;                 
91                 };
92                 
93                 this.keyCode       = e.keyCode;
94                 this.altKey        = e.altKey;
95                 this.ctrlKey       = e.ctrlKey;
96                 this.shiftKey      = e.shiftKey;
97                 
98                 // http://www.programming-magic.com/20090127231544/
99                 switch( this.type ){
100                         case 'click'    :
101                         case 'dblclick' :
102                                 this.which = 1;
103                                 break;
104                         case 'contextmenu' :
105                                 this.which = 3;
106                                 break;
107                         default :
108                                 btn = e.button;
109                                 this.which =
110                                         btn & 1 ? 1 :
111                                         btn & 4 ? 2 :
112                                         btn & 2 ? 3 : 0; // 左:1(click:0), 中:4, 右:2
113                 };
114                 this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;
115         };
116 };
117
118 X.Dom.Event.DOM_PREINIT  = 0;
119 X.Dom.Event.DOM_INIT     = 1;
120 X.Dom.Event.XDOM_READY   = 2;
121 X.Dom.Event.VIEW_RESIZED = 3;
122 X.Dom.Event._LAST_EVENT  = 3;
123
124 X.Dom.Event._Helper =
125         document.addEventListener ?
126                 (function( elm, type ){
127                         elm.addEventListener( type, this, false );
128                 }) :
129         document.attachEvent ?
130                 (function( elm, type ){
131                         elm.attachEvent( 'on' + type, ( this.callback = X.Callback.create( this ) ) );
132                 }) :
133                 (function( elm, type ){
134                         this.callback = elm[ 'on' + type ] = X.Callback.create( this );
135                 });
136
137 X.Dom.Event._Helper.prototype.removeEvent =
138         document.removeEventListener ?
139                 (function( migrate ){
140                         this.type && this.elm.removeEventListener( this.type, this, false );
141                         if( migrate ) return;
142                         delete this.elm;
143                         delete this.type;
144                         delete this.list;
145                 }) :
146         document.detachEvent ?
147                 (function( migrate ){
148                         this.type && this.elm.detachEvent( 'on' + this.type, this.callback );
149                         X.Callback._correct( this.callback );
150                         if( migrate ) return;
151                         delete this.elm;
152                         delete this.type;
153                         delete this.list;
154                         delete this.callback;
155                 }) :
156                 (function( migrate ){
157                         this.elm[ 'on' + this.type ] = X.emptyFunction;
158                         this.elm[ 'on' + this.type ] = '';
159                         X.Callback._correct( this.callback );
160                         if( migrate ) return;
161                         delete this.elm;
162                         delete this.type;
163                         delete this.list;
164                         delete this.callback;
165                 });
166
167 /*
168  * eventDispatch 中の Event.remove への対処.
169  * 現在 dispatch 中の function より以前の function が抜かれた場合の対策
170  */
171 X.Dom.Event._Helper.prototype.handleEvent =
172         document.removeEventListener ?
173                 (function( e ){
174                         var list   = this.list,
175                                 e      = new X.Dom.Event( e ),
176                                 i      = 0,
177                                 ret    = 0,
178                                 p, f, r;
179                         list.removed = 0;
180                         for( ; i < list.length; ){
181                                 list.pointer = i - list.removed;
182                                 f = list[ list.pointer ];
183                                 r = f( e );
184                                 ret |= ( r || 0 );
185                                 if( r & X.Callback.UN_LISTEN ){
186                                         list.splice( list.pointer, 1 );
187                                         X.Callback._correct( f );
188                                         if( list.length === 0 ){
189                                                 this.removeEvent();
190                                                 break;
191                                         };
192                                 } else {
193                                         ++i;
194                                 };
195                                 if( r & X.Callback.STOP_NOW ) break;
196                         };
197                         delete list.pointer;
198                         delete list.removed;
199                         if( ret & X.Callback.STOP_PROPAGATION ){
200                                 event.cancelBubble = true;
201                         };
202                         if( ret & X.Callback.PREVENT_DEFAULT ){
203                                 return event.returnValue = false;
204                         };
205                 }) :
206                 (function(){
207                         var list   = this.list,
208                                 e      = new X.Dom.Event( event, this.elm ),
209                                 i      = 0,
210                                 ret    = 0,
211                                 p, f, r;
212                         list.removed = 0;
213                         for( ; i < list.length; ){
214                                 list.pointer = i - list.removed;
215                                 f = list[ list.pointer ];
216                                 r = f( e );
217                                 ret |= ( r || 0 );
218                                 if( r & X.Callback.UN_LISTEN ){
219                                         list.splice( list.pointer, 1 );
220                                         X.Callback._correct( f );
221                                         if( list.length === 0 ){
222                                                 this.removeEvent();
223                                                 break;
224                                         };
225                                 } else {
226                                         ++i;
227                                 };
228                                 if( r & X.Callback.STOP_NOW ) break;
229                         };
230                         delete list.pointer;
231                         delete list.removed;
232                         if( ret & X.Callback.STOP_PROPAGATION ){
233                                 e.stopPropagation();
234                         };
235                         if( ret & X.Callback.PREVENT_DEFAULT ){
236                                 e.preventDefault();
237                                 return false;
238                         };
239                 });
240
241 X.Dom.Event._chashe  = [ {}, {}, null, {} ]; // window, document, documentElement, body
242 X.Dom.Event._chashe2 = [];
243
244 X.Dom.Event.add = function( element, type, arg2, arg3, arg4 /* [ listener || ( context + function ) || function ][ arguments ] */ ){
245         var XEvent = X.Dom.Event,
246                 hash   = XEvent._getHash( element, true ),
247                 helper = hash[ type ],
248                 callback, list;
249         if( typeof arg2 === 'function' ){
250                 callback = X.Callback.create( element, arg2, arg3 );
251         } else {
252                 callback = X.Callback.create( arg2, arg3, arg4 );
253         };
254         if( helper ){
255                 list = helper.list;
256                 list.indexOf( callback ) === -1 && ( list[ list.length ] = callback );
257         } else {
258                 helper = hash[ type ] = new XEvent._Helper( element, type );
259                 helper.elm  = element;
260                 helper.type = type;
261                 helper.list = [ callback ];
262         };
263 };
264
265 X.Dom.Event._getHash = function( element, create ){
266         var uid, ret;
267         if( element === window ){
268                 return this._chashe[ 0 ];
269         } else
270         if( element === document ){
271                 return this._chashe[ 1 ];
272         } else
273         if( element === document.body ){
274                 return this._chashe[ 3 ];
275         } else
276         if( element === document.documentElement ){
277                 return this._chashe[ 2 ] || ( create && ( this._chashe[ 2 ] = {} ) );
278         };
279         
280         if( X.UA.IE && X.UA.IE < 5 ){
281                 if( uid = 2 + parseFloat( element.getAttribute( 'UID' ) ) ){
282                         if( ret = this._chashe[ uid ] ) return ret;
283                         if( create ) return ( this._chashe[ uid ] = {} );
284                 };
285                 // wrong!
286                 if( uid = parseFloat( element.getAttribute( '_UID' ) ) ){
287                         return this._chashe2[ uid ];
288                 };
289                 if( create ){
290                         uid = this._chashe2.length;
291                         element.setAttrivute( '_UID', '' + uid );
292                         return this._chashe2[ uid ] = {};
293                 };
294                 //
295         } else {
296                 if( uid = 2 + element.UID ){
297                         if( ret = this._chashe[ uid ] ) return ret;
298                         if( create ) return ( this._chashe[ uid ] = {} );
299                 };
300                 // wrong!
301                 if( uid = element._UID ){
302                         return this._chashe2[ uid ];
303                 };
304                 if( create ){
305                         element._UID = uid = this._chashe2.length;
306                         return this._chashe2[ uid ] = {};
307                 };
308                 //
309         };
310 };
311
312 X.Dom.Event.remove = function( /* element, type, arg2, arg3, arg4 */ ){
313         var element = arguments[ 0 ],
314                 type    = arguments[ 1 ],
315                 arg2, arg3, arg4,
316                 hash    = X.Dom.Event._getHash( element ),
317                 helper, callback, list, i;
318         if( !hash ) return;
319         
320         switch( arguments.length ){
321                 case 0 :
322                         return;
323                 case 1 :
324                         for( type in hash ){
325                                 X.Dom.Event.remove( element, type );
326                         };
327                         X.Dom.Event._chashe.splice( X.Dom.Event._chashe.indexOf( hash ), 1 );
328                         break;
329                 case 2 :
330                         if( helper = hash[ type ] ){
331                                 list = helper.list;
332                                 i    = list.length;
333                                 for( ; i; ){
334                                         callback = list[ --i ];
335                                         X.Callback._correct( callback );
336                                 };
337                                 list.length = 0;
338                                 helper.removeEvent();
339                                 delete hash[ type ];
340                };
341                break;
342             default :
343                         arg2     = arguments[ 2 ];
344                         arg3     = arguments[ 3 ];
345                         arg4     = arguments[ 4 ];
346                         callback = typeof arg2 === 'function' ? X.Callback.create( element, arg2, arg3 ) : X.Callback.create( arg2, arg3, arg4 );
347                         list = helper.list;
348                         i    = list.indexOf( callback );
349                         if( i !== -1 ){
350                                 list.splice( i, 1 );
351                                 if( list.pointer && i <= list.pointer ){
352                                         ++list.removed;
353                                 };
354                                 X.Callback._correct( callback );
355                                 if( list.length === 0 ){
356                                         helper.removeEvent();
357                                         delete hash[ type ];
358                                 };
359                         };
360         };
361 };
362
363 // イベントの退避、dom が画面から抜かれる場合に実施しておく
364 X.Dom.Event.migrate = function( element ){
365         var XEvent = X.Dom.Event,
366                 hash   = XEvent._getHash( element ),
367                 type;
368         if( !hash ) return;
369         for( type in hash ){
370                 hash[ type ].removeEvent( true );
371         };
372 };
373
374 // 退避したイベントの復帰
375 X.Dom.Event.restore = function( element ){
376         var XEvent = X.Dom.Event,
377                 hash   = XEvent._getHash( element ),
378                 helper = XEvent._Helper,
379                 type;
380         if( !hash ) return;
381         for( type in hash ){
382                 helper.call( hash[ type ], element, type );
383         };
384 };
385
386
387
388 /* -----------------------------------------------
389  * Document Ready
390  *  Dean Edwards/Matthias Miller/John Resig
391  */
392 /* for ie9+/Mozilla/Opera9 */
393 if( document.addEventListener ){
394         X.Dom.Event.add( document, 'DOMContentLoaded', X.Dom._init );
395 } else
396 if( 5 <= X.UA.IE && X.inHead ){
397         // if this script in Head
398         document.write( "<script id=__ie_onload defer src=javascript:void(0)><\/script>" );
399         X.Dom._script = document.getElementById( "__ie_onload" );
400         X.Dom._script.onreadystatechange = function(){
401                 this.readyState === 'complete' && X.Dom._init();
402         };
403 } else
404 if( X.UA.WebKit ){ // sniff
405         X.Timer.add( 10, function(){
406                 if( !X.Dom._init ) return X.Callback.UN_LISTEN;
407                 if( 'loaded|complete'.indexOf( document.readyState ) !== -1 ) return X.Dom._init();
408         });
409 };
410
411 /* for other browsers */
412 X.Dom.Event.add( window, 'load', X.Dom._init );
413
414 //
415 X.Dom.listenOnce( X.Dom.Event.XDOM_READY, function(e){ console.log( 'X.Dom XDomReady ' + X.Dom.ready ) } );
416
417 X.Dom.listenOnce( X.Dom.Event.VIEW_RESIZED, function(e){ console.log( 'X.Dom VIEW_RESIZED ' + e.w + 'x' + e.h ) } );