OSDN Git Service

Version 0.3.34, fix X.Dom.Builder, fix X.Timer, detect ScrollBar size.
[pettanr/clientJs.git] / 0.6.x / js / dom / 12_XDomEvent.js
1 /**\r
2  * use X.Callback\r
3  * \r
4  * http://d.hatena.ne.jp/uupaa/20100430/1272561922\r
5  * \r
6  */\r
7 \r
8 if( window.addEventListener ){\r
9         X.Dom.Event = function( e, xnode ){\r
10                 //this._event        = e;\r
11                 this.type          = e.type;\r
12                 \r
13                 //http://www.quirksmode.org/js/events_properties.html\r
14                 this.target        = Node._getXNode( e.target.nodeType === 3 ? e.target.parentNode : e.target );// defeat Safari bug // xnode\r
15                 \r
16                 this.currentTarget = xnode; // xnode\r
17                 this.relatedTarget = Node._getXNode( e.relatedTarget ); // xnode\r
18                 this.eventPhase    = e.eventPhase;\r
19                 \r
20                 this.clientX       = e.clientX;\r
21                 this.clientY       = e.clientY;\r
22                 //this.screenX       = e.screenX;\r
23                 //this.screenY       = e.screenY;\r
24                 this.pageX         = e.pageX;\r
25                 this.pageY         = e.pageY;\r
26                 this.offsetX       = e.offsetX || e.layerX;\r
27                 this.offsetY       = e.offsetY || e.layerY;\r
28                 \r
29                 this.keyCode       = e.keyCode;\r
30                 this.altKey        = e.altKey;\r
31                 this.ctrlKey       = e.ctrlKey;\r
32                 this.shiftKey      = e.shiftKey;\r
33                 \r
34                 // http://www.programming-magic.com/20090127231544/\r
35                 this.which         = e.which || ( e.button + 1 ); // 左:1, 中:2, 右:3\r
36                 \r
37                 // https://developer.mozilla.org/ja/docs/DOM/DOM_event_reference/mousewheel\r
38                 if( e.wheelDeltaY !== undefined ){\r
39                         this.wheelDeltaX = e.wheelDeltaX / 12;\r
40                         this.wheelDeltaY = e.wheelDeltaY / 12;\r
41                 } else\r
42                 if( e.wheelDelta !== undefined ){\r
43                         this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;\r
44                 } else\r
45                 if( e.detail !== undefined ){\r
46                         this.wheelDeltaX = this.wheelDeltaY = - e.detail * 3;\r
47                 } else {\r
48                         this.wheelDeltaX = this.wheelDeltaY = 0;\r
49                 };\r
50                 \r
51                 if( e.constructor === window.TouchEvent ){\r
52                         // TouchEvent\r
53                         this.touches        = e.touches;\r
54                         this.changedTouches = e.changedTouches;\r
55                         this.targetTouches  = e.targetTouches;\r
56                         this.metaKey        = e.metaKey;\r
57                         this.force          = e.force || e.webkitForce || 0;\r
58                 } else\r
59                 if( e.constructor === window.PointerEvent ){\r
60                         // PointerEvent;\r
61                         this.currentPoint  = e.currentPoint;\r
62                         this.width         = e.width;\r
63                         this.height        = e.height;\r
64                         this.timeStamp     = e.timeStamp;\r
65                         this.hwTimestamp   = e.hwTimestamp;\r
66                         this.intermediatePoints = e.intermediatePoints;\r
67                         this.isPrimary     = e.isPrimary;\r
68                         this.pointerId     = e.pointerId;\r
69                         this.pointerType   = e.pointerType;\r
70                         this.pressure      = e.pressure;\r
71                         this.tiltX         = e.tiltX;\r
72                         this.tiltY         = e.tiltY;\r
73                 };\r
74         };\r
75 } else {\r
76         X.Dom.Event = function( e, xnode, element ){\r
77                 var btn;\r
78                 \r
79                 //this._event        = e;\r
80                 this.type          = e.type;\r
81                 this.target        = Node._getXNode( e.srcElement ); // xnode\r
82                 if( this.target && this.target._xnodeType === 3 ) this.target = this.target.parent; // ie4 の fake Textnode がヒットしていないか?\r
83                 this.currentTarget = xnode; // xnode\r
84                 this.relatedTarget = Node._getXNode( e.formElement ? e.formElement : e.toElement ); // xnode\r
85                 this.eventPhase    = e.srcElement === element ? 2: 3;\r
86                 \r
87                 this.clientX       = e.clientX;\r
88                 this.clientY       = e.clientY;\r
89                 //this.screenX       = e.screenX;\r
90                 //this.screenY       = e.screenY;\r
91                 \r
92                 if( X.Dom._root ){ // uuu...\r
93                         \r
94                         this.pageX         = e.clientX + X.Dom._root.scrollLeft;\r
95                         this.pageY         = e.clientY + X.Dom._root.scrollTop;\r
96                         \r
97                         // DOMAssistant 2.8.1\r
98                         //event.pageX = DOMAssistant.def(e.pageX)? e.pageX : (event.clientX + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0));\r
99                         //event.pageY = DOMAssistant.def(e.pageY)? e.pageY : (event.clientY + (de.scrollTop || b.scrollTop) - (de.clientTop || 0));                                                     \r
100                 };\r
101                 \r
102 \r
103                 \r
104                 if( X.UA.IE && 5 <= X.UA.IE ){\r
105                         this.offsetX       = e.offsetX; // イベントターゲット左上からの座標\r
106                         this.offsetY       = e.offsetY;                 \r
107                 }// else\r
108                 //if( e.srcElement ){\r
109                 //      this.offsetX       = e.x - e.srcElement.offsetLeft; // e.x はイベント発生要素の親要素を基準にした座標。\r
110                 //      this.offsetY       = e.y - e.srcElement.offsetTop;      \r
111                 //};\r
112                 \r
113                 this.keyCode       = e.keyCode;\r
114                 this.altKey        = e.altKey;\r
115                 this.ctrlKey       = e.ctrlKey;\r
116                 this.shiftKey      = e.shiftKey;\r
117                 \r
118                 // http://www.programming-magic.com/20090127231544/\r
119                 switch( this.type ){\r
120                         case 'click'    :\r
121                         case 'dblclick' :\r
122                                 this.which = 1;\r
123                                 break;\r
124                         case 'contextmenu' :\r
125                                 this.which = 3;\r
126                                 break;\r
127                         default :\r
128                                 btn = e.button;\r
129                                 this.which =\r
130                                         btn & 1 ? 1 :\r
131                                         btn & 4 ? 2 :\r
132                                         btn & 2 ? 3 : 0; // 左:1(click:0), 中:4, 右:2\r
133                 };\r
134                 this.wheelDeltaX = this.wheelDeltaY = e.wheelDelta / 12;\r
135         };\r
136 };\r
137 \r
138 X.Dom.Event.DOM_PRE_INIT        = ++X.Event._LAST_EVENT;\r
139 X.Dom.Event.DOM_BUILDER_COMPLETE= ++X.Event._LAST_EVENT;\r
140 X.Dom.Event.DOM_INIT            = ++X.Event._LAST_EVENT;\r
141 X.Dom.Event.XDOM_READY          = ++X.Event._LAST_EVENT;\r
142 X.Dom.Event.VIEW_ACTIVATE       = ++X.Event._LAST_EVENT;\r
143 X.Dom.Event.VIEW_DEACTIVATE     = ++X.Event._LAST_EVENT;\r
144 X.Dom.Event.VIEW_RESIZED        = ++X.Event._LAST_EVENT;\r
145 X.Dom.Event.BASE_FONT_RESIZED   = ++X.Event._LAST_EVENT;\r
146 // same_page_jump\r
147 // on_screen_keyboard_show\r
148 // on_screen_keyboard_hide\r
149 X.Dom.Event.BEFORE_UPDATE       = ++X.Event._LAST_EVENT;\r
150 X.Dom.Event.AFTER_UPDATE        = ++X.Event._LAST_EVENT;\r
151 // hash_change\r
152 X.Dom.Event.BEFORE_UNLOAD       = ++X.Event._LAST_EVENT;\r
153 X.Dom.Event.UNLOAD              = ++X.Event._LAST_EVENT;\r
154 X.Dom.Event.LOAD_BEFORE_STOP    = ++X.Event._LAST_EVENT;\r
155 X.Dom.Event.LOAD_ASSET_STOP     = ++X.Event._LAST_EVENT;\r
156 X.Dom.Event.LOAD_ASSET_COMPLETE = ++X.Event._LAST_EVENT;\r
157 X.Dom.Event.LOAD_ASSET_ERROR    = ++X.Event._LAST_EVENT;\r
158 \r
159 X.Dom.Event.ANIME_BEFORE_START  = ++X.Event._LAST_EVENT;\r
160 X.Dom.Event.ANIME_START         = ++X.Event._LAST_EVENT;\r
161 X.Dom.Event.ANIME               = ++X.Event._LAST_EVENT;\r
162 X.Dom.Event.ANIME_END           = ++X.Event._LAST_EVENT;\r
163 X.Dom.Event.ANIME_BEFORE_STOP   = ++X.Event._LAST_EVENT; // xnode.stop() のみ、指定時間による停止では呼ばれない\r
164 X.Dom.Event.ANIME_STOP          = ++X.Event._LAST_EVENT;\r
165 X.Dom.Event._LAST_EVENT         = X.Event._LAST_EVENT; // ここに書いてあるイベントの最後の値 X.Dom.Event.ANIME_STOP と同じ値\r
166 \r
167 \r
168 X.Dom.Node.prototype.listen = function( type, arg1, arg2, arg3 /* [ listener || ( context + function ) || function ][ arguments ] */ ){\r
169         var elm;\r
170         \r
171         if( this._xnodeType === 0 || this._xnodeType === 3 || !arg1 ) return this;\r
172         \r
173         ( !this._listeners || !this._listeners[ type ] ) && this._addEvent( type );\r
174         \r
175         return typeof arg1 === 'function' ?\r
176                 X.EventDispatcher.prototype.listen.call( this, type, this, arg1, arg2 ) :\r
177                 X.EventDispatcher.prototype.listen.apply( this, arguments );\r
178 };\r
179 \r
180 X.Dom.Node.prototype._addEvent =\r
181         document.removeEventListener ?\r
182                 (function( type ){\r
183                         this._rawNode && this._rawNode.addEventListener( type, this, false );\r
184                 }) :\r
185         document.detachEvent ?\r
186                 (function( type ){\r
187                         if( !this._rawNode ) return;\r
188                         this._handleEvent = this._handleEvent || X.Callback.create( this );\r
189                         this._rawNode.attachEvent( 'on' + type, this._handleEvent );\r
190                 }) :\r
191                 (function( type ){\r
192                         var elm = this._ie4getRawNode();\r
193                         if( !elm ) return;\r
194                         this._handleEvent = elm[ 'on' + type ] = this._handleEvent || X.Callback.create( this );\r
195                 });\r
196 \r
197 \r
198 X.Dom.Node.prototype.unlisten = function( type /* , arg1, arg2, arg3 */ ){\r
199         var list = this._listeners,\r
200                 l    = !this._dispatching && list && type !== undefined && list[ type ] && list[ type ].length;\r
201         \r
202         X.EventDispatcher.prototype.unlisten.apply( this, arguments );\r
203         \r
204         l && !list[ type ] && this._removeEvent( type );\r
205         \r
206         return this;\r
207 };\r
208 \r
209 X.Dom.Node.prototype._removeEvent =\r
210         document.removeEventListener ?\r
211                 (function( type ){\r
212                         var elm = this._rawNode;\r
213                         if( !elm ) return;\r
214                         elm.removeEventListener( type, this, false );\r
215                 }) :\r
216         document.detachEvent ?\r
217                 (function( type ){\r
218                         var elm = this._rawNode;\r
219                         if( !elm ) return;\r
220                         elm.detachEvent( 'on' + type, this._handleEvent );\r
221                         if( !this._listeners ){\r
222                                 X.Callback._correct( this._handleEvent );\r
223                                 delete this._handleEvent;\r
224                         };\r
225                 }) :\r
226                 (function( type ){\r
227                         var elm = this._rawNode || this._ie4getRawNode();\r
228                         if( !elm ) return;\r
229                         elm[ 'on' + type ] = X.emptyFunction;\r
230                         elm[ 'on' + type ] = '';\r
231                         if( !this._listeners ){\r
232                                 X.Callback._correct( this._handleEvent );\r
233                                 delete this._handleEvent;\r
234                         };\r
235                 });\r
236 \r
237 \r
238 X.Dom.Node.prototype.handleEvent =\r
239         document.removeEventListener ?\r
240                 (function( e ){\r
241                         var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( e, this ) );\r
242 \r
243                         if( ret & X.Callback.STOP_PROPAGATION ){\r
244                                 e.stopPropagation();\r
245                         };\r
246                         if( ret & X.Callback.PREVENT_DEFAULT ){\r
247                                 this._tag === 'A' && this._rawNode.blur();\r
248                                 e.preventDefault();\r
249                                 return false;\r
250                         };\r
251                 }) :\r
252                 (function(){\r
253                         var ret = X.EventDispatcher.prototype.dispatch.call( this, new X.Dom.Event( event, this, this._rawNode ) );\r
254 \r
255                         if( ret & X.Callback.STOP_PROPAGATION ){\r
256                                 event.cancelBubble = true;\r
257                         };\r
258                         if( ret & X.Callback.PREVENT_DEFAULT ){\r
259                                 this._tag === 'A' && this._rawNode.blur();\r
260                                 return event.returnValue = false;\r
261                         };\r
262                 });\r
263 \r
264 \r
265 // イベントの退避、dom が画面から抜かれる場合に実施しておく\r
266 X.Dom.Node.prototype._migrateEvent = function(){\r
267         var hash = this._listeners,\r
268                 type;\r
269         if( !hash ) return;\r
270         for( type in hash ){\r
271                 this._removeEvent( type );\r
272         };\r
273 };\r
274 \r
275 // 退避したイベントの復帰\r
276 X.Dom.Node.prototype._restoreEvent = function(){\r
277         var hash = this._listeners,\r
278                 type;\r
279         if( !hash ) return;\r
280         for( type in hash ){\r
281                 this._addEvent( type );\r
282         };\r
283 };\r
284 \r
285 \r
286 \r
287 /* -----------------------------------------------\r
288  * Document Ready\r
289  *  Dean Edwards/Matthias Miller/John Resig\r
290  */\r
291 /* for ie9+/Mozilla/Opera9 */\r
292 if( document.addEventListener ){\r
293         X.Dom.Node._document.listenOnce( 'DOMContentLoaded', X.Dom._init );\r
294 } else\r
295 if( 5 <= X.UA.IE && X.inHead ){\r
296         // if this script in Head\r
297         document.write( "<script id=__ie_onload defer src=javascript:void(0)><\/script>" );\r
298         X.Dom._script = document.getElementById( "__ie_onload" );\r
299         X.Dom._script.onreadystatechange = function(){\r
300                 this.readyState === 'complete' && X.Dom._init();\r
301         };\r
302 } else\r
303 if( X.UA.WebKit ){ // sniff\r
304         X.Timer.add( 10, function(){\r
305                 if( !X.Dom._init ) return X.Callback.UN_LISTEN;\r
306                 if( 'loaded|complete'.indexOf( document.readyState ) !== -1 ) return X.Dom._init();\r
307         });\r
308 };\r
309 \r
310 /* for other browsers */\r
311 X.Dom.Node._window.listenOnce( 'load', X.Dom._init );\r
312 \r
313 //\r
314 X.Dom.listenOnce( X.Dom.Event.XDOM_READY, function(e){ console.log( 'X.Dom XDomReady ' + X.Dom.readyState ); } );\r
315 \r
316 X.Dom.listenOnce( X.Dom.Event.VIEW_RESIZED, function(e){ console.log( 'X.Dom VIEW_RESIZED ' + e.w + 'x' + e.h ); } );\r
317 \r