OSDN Git Service

4590e526905d2a9ea90d0d5039a2f0bff21142ba
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 00_XDom.js
1 \r
2 var X_Dom_readyState,\r
3         X_Dom_active = !!window.parent || !!document.activeElement, // parent は frameに読み込まれた場合のieのerror回避\r
4         X_Dom_rootElement,\r
5         X_Dom_lock,\r
6         X_Dom_width,\r
7         X_Dom_height,\r
8         X_Dom_baseFontSize,\r
9         X_Dom_orientationFlag;\r
10 \r
11 X.Dom = X.Class._override(\r
12         new X.EventDispatcher(),\r
13         {\r
14 \r
15                 handleEvent : function( e ){\r
16                         var href;\r
17                         switch( e.type ){\r
18                                 case 'beforeunload' :\r
19                                         \r
20                                         // ie では a href="javascript" な要素でも beforeunload が起こる\r
21                                         href = e.target && e.target.attr && e.target.attr( 'href' );\r
22                                         if( href && href.indexOf && href.indexOf( 'javascript:' ) === 0 ) return X.Callback.PREVENT_DEFAULT | X.Callback.STOP_PROPAGATION;\r
23                                         \r
24                                         return X.Dom.dispatch( X.Dom.Event.BEFORE_UNLOAD );\r
25                                 case 'unload' :\r
26                                         X.Dom.dispatch( X.Dom.Event.UNLOAD );\r
27                                         \r
28                                         Node._window.unlisten();\r
29                                         Node._document.unlisten();\r
30                                         Node._html._actualRemove( true );\r
31                                         break;\r
32                                 case 'visibilitychange' :\r
33                                         X.Dom.dispatch( { type : ( X_Dom_active = document[ 'hidden' ] ) ? X.Dom.Event.VIEW_DEACTIVATE : X.Dom.Event.VIEW_ACTIVATE } );\r
34                                         break;\r
35                                 case 'webkitvisibilitychange' :\r
36                                         X.Dom.dispatch( { type : ( X_Dom_active = document[ 'webkitHidden' ] ) ? X.Dom.Event.VIEW_DEACTIVATE : X.Dom.Event.VIEW_ACTIVATE } );\r
37                                         break;\r
38                                 case 'pageshow' :\r
39                                 case 'focus' :\r
40                                         X_Dom_active = true;\r
41                                         X.Dom.dispatch( X.Dom.Event.VIEW_ACTIVATE );\r
42                                         break;\r
43                                 case 'pagehide' :\r
44                                 case 'blur' :\r
45                                         X_Dom_active = false;\r
46                                         X.Dom.dispatch( X.Dom.Event.VIEW_DEACTIVATE );\r
47                                         break;\r
48                         };\r
49                 },\r
50 \r
51                 listen : function( type ){\r
52                         if( type <= X_Dom_readyState ){\r
53                                 /*\r
54                                  * X.Event.XDOM_READY 以後に listen した場合の対策\r
55                                  */\r
56                                 X.Dom.asyncDispatch( 0, { type : type, w : X_Dom_width, h : X_Dom_height } );\r
57                         };\r
58                         return X_EventDispatcher_listen.apply( X.Dom, arguments );\r
59                 },\r
60                 \r
61                 getPointerPosition : function(){\r
62                         \r
63                 },\r
64                 \r
65                 /* 要素が視界に入った  http://remysharp.com/2009/01/26/element-in-view-event-plugin/ */\r
66                 inView : function( elm ){\r
67                         \r
68                 },\r
69                 \r
70                 getSize : function(){\r
71                         return [ X_Dom_width, X_Dom_height ];\r
72                 },\r
73 //https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect\r
74 //use window.pageXOffset and window.pageYOffset instead of window.scrollX and window.scrollY\r
75 //(((t = document.documentElement) || (t = document.body.parentNode)) && typeof t.ScrollLeft == 'number' ? t : document.body).ScrollLeft;\r
76 //(((t = document.documentElement) || (t = document.body.parentNode)) && typeof t.ScrollTop == 'number' ? t : document.body).ScrollTop\r
77                 \r
78                 getDocumentSize : function(){\r
79                         // Opera は互換モードでは document.body.scrollHeight、標準モードでは document.documentElement.scrollHeight でページの高さが取れる。と思ってたんだけど、例外があった。\r
80                         // http://orera.g.hatena.ne.jp/edvakf/20100515/1273908051\r
81                 //http://onozaty.hatenablog.com/entry/20060803/p1\r
82                 // Safari2.0.4では標準・互換どちらも document.body\r
83                         \r
84                         Node._body._updateTimerID && Node._body._startUpdate();\r
85                         /*X.UA.Opera ?\r
86                                 ( document.documentElement && document.documentElement.clientWidth ?\r
87                                         new Function( 'return[document.documentElement.clientWidth,document.documentElement.clientHeight]' ) :\r
88                                         new Function( 'return[document.body.clientWidth,document.body.clientHeight]' )\r
89                                 ) :*/                   \r
90                         return [\r
91                                 X_Dom_rootElement.scrollWidth  || X_Dom_rootElement.offsetWidth,\r
92                                 X_Dom_rootElement.scrollHeight || X_Dom_rootElement.offsetHeight\r
93                         ];\r
94                 },\r
95                 \r
96                 getScrollPosition :\r
97                         window.pageXOffset !== undefined ?\r
98                                 ( function(){\r
99                                         Node._body._updateTimerID && Node._body._startUpdate();\r
100                                         return[ window.pageXOffset, window.pageYOffset ];\r
101                                 } ) :\r
102                         window.scrollLeft  !== undefined ?\r
103                                 ( function(){\r
104                                         Node._body._updateTimerID && Node._body._startUpdate();\r
105                                         return[ window.scrollLeft, window.scrollTop ];\r
106                                 } ) :\r
107                                 ( function(){\r
108                                         Node._body._updateTimerID && Node._body._startUpdate();\r
109                                         // body は Safari2-\r
110                                         return[ X_Dom_rootElement.scrollLeft || document.body.scrollLeft, X_Dom_rootElement.scrollTop || document.body.scrollTop ];\r
111                                 } ),\r
112 \r
113                 getScrollbarSize : function(){\r
114                         return [ X.Dom.BoxModel.vScrollbarSize, X.Dom.BoxModel.hScrollbarSize ];        \r
115                 },\r
116                 \r
117                 getBaseFontSize : function(){\r
118                         if( Node._body._updateTimerID ){\r
119                                 Node._body._startUpdate();\r
120                                 return Node._fontSizeNode._rawObject.offsetHeight;\r
121                         };\r
122                         return X_Dom_baseFontSize;\r
123                 }\r
124         }\r
125 );\r
126 \r
127 \r
128 \r
129 \r
130 \r
131 \r
132 /* -----------------------------------------------\r
133  * Resize\r
134  *  original : uupaa.js\r
135  * \r
136  * TODO\r
137  *  https://w3g.jp/blog/studies/ios7_1_minimal-ui_warning\r
138  *  iOS7.0からあったiPad Safariの高さ100%コンテンツでlandscape(横向き)時に起きる不具合\r
139  * \r
140  * http://looxu.blogspot.jp/2013/11/ios7mobile-safariwindowinnerheight.html\r
141  * iOS7にて、Mobile Safariのwindow.innerHeightを正しく取得する方法\r
142  * \r
143  *  http://tenderfeel.xsrv.jp/javascript/1182/\r
144  *  アドレスバーの高さの算出\r
145  * \r
146  * http://sssslide.com/www.slideshare.net/hiroakiwakamatsu/javascript-14514208\r
147  * 1. 傾き時の画面サイズ取得ー 対処方法の例\r
148  * (1)ー? タイマーを使って、画面サイズ取得の タイミングを少しだけ遅延させる\r
149  * window.onorientationchange = function() { setTimeout(function() { alert("W: " + window.innerWidth + ", H: " + window.innerHeight); }, 200); }\r
150  * 横に傾けた時、正常に横向け時の 幅と高さが取得できている ただし、端末によってはうまく取得できな い場合がある(Galaxy S IIIとか・・・) 7 \r
151  * \r
152  * http://sssslide.com/www.slideshare.net/hiroakiwakamatsu/ss-12718639\r
153  * \r
154  * \r
155  * getBoundingClientRect で fontsize の調査\r
156  */\r
157                 var X_Dom_resize =\r
158                         // iOS もループで回す,,,iOS3.1.3, iOS6 で確認\r
159                         X.UA.IE < 9 || X.UA.iOS ?\r
160                                 (function(){\r
161                                         var size;\r
162                                         if( !X_Dom_lock ){\r
163                                                 size = X_Dom_getWindowSize();\r
164                                                 if( X_Dom_width !== size[ 0 ] || X_Dom_height !== size[ 1 ] ){\r
165                                                         X_Dom_width = size[ 0 ];\r
166                                                         X_Dom_height = size[ 1 ];\r
167                                                         X.Timer.once( 100, X_Dom_detectFinishResizing );\r
168                                                         X_Dom_lock = true;\r
169                                                 };\r
170                                         };\r
171                                         \r
172                                         size = Node._fontSizeNode._rawObject.offsetHeight;\r
173                                         if( X_Dom_baseFontSize !== size ){\r
174                                                 X_Dom_baseFontSize && X.Dom.asyncDispatch( 0, { type : X.Dom.Event.BASE_FONT_RESIZED, fontSize : size, w : X_Dom_width, h : X_Dom_height  } );\r
175                                                 X_Dom_baseFontSize = size;\r
176                                         };\r
177                                         \r
178                                 }) :\r
179                                 (function( e ){\r
180                                         console.log( '-- resize : ' + X_Timer_now() );\r
181                                         \r
182                                         !X_Dom_lock && ( X_Dom_lock = true ) && X.Timer.once( 100, X_Dom_detectFinishResizing );\r
183                                         return X.Callback.PREVENT_DEFAULT | X.Callback.STOP_PROPAGATION;\r
184                                 });\r
185                 \r
186                 function X_Dom_detectFinishResizing(){\r
187                         var size = X_Dom_getWindowSize();\r
188                         if( X_Dom_width !== size[ 0 ] || X_Dom_height !== size[ 1 ] ){\r
189                                 X_Dom_width = size[ 0 ];\r
190                                 X_Dom_height = size[ 1 ];\r
191                                 X.Timer.once( 100, X_Dom_detectFinishResizing );\r
192                         } else {\r
193                                 console.log( '-- detectFinishResizing : ' + X_Timer_now() );\r
194                                 \r
195                                 X.Dom.asyncDispatch( 0, { type : X.Dom.Event.VIEW_RESIZED, fontSize : size, w : X_Dom_width, h : X_Dom_height } );\r
196                                 X_Dom_lock = false;\r
197                                 if( X_Dom_orientationFlag ){\r
198                                         X_Dom_orientationFlag = false;\r
199                                         X.Dom.asyncDispatch( 100, { type : X.Dom.Event.VIEW_TURNED, orientation : window.orientation } );\r
200                                 };\r
201                         };\r
202                 };\r
203 \r
204                 X_TEMP.onDomContentLoaded = function(){\r
205                         var s, size, elmHtml, elmHead, elmBody, html, head, body;\r
206                         \r
207                         if( X_TEMP.SYSTEM_EVENT_PRE_INIT <= X_Dom_readyState ) return X_Callback_UN_LISTEN;\r
208                         X_Dom_readyState = X_TEMP.SYSTEM_EVENT_PRE_INIT;\r
209                         \r
210                         // DOMContentLoaded の無いブラウザで X_TEMP.onDomContentLoaded への参照が残り続けるのを回避\r
211                         Node._document.unlisten( 'DOMContentLoaded', X_TEMP.onDomContentLoaded );\r
212                         delete X_TEMP.onDomContentLoaded;\r
213                         \r
214                         elmHtml = document.documentElement ||\r
215                                 X_UA_DOM.W3C ? document.getElementsByTagName( 'html' )[ 0 ] :\r
216                                 X_UA_DOM.IE4 ? document.all.tags( 'html' )[ 0 ] : null;\r
217                         \r
218                         elmHead = \r
219                                 X_UA_DOM.W3C ? document.getElementsByTagName( 'head' )[ 0 ] :\r
220                                 X_UA_DOM.IE4 ? document.all.tags( 'head' )[ 0 ] : null;\r
221 \r
222                         elmBody = document.body;\r
223 \r
224                         X_Dom_rootElement = document.compatMode !== 'CSS1Compat' ? elmBody : elmHtml || elmBody;\r
225 \r
226                         html = Node._html = elmHtml && new Node( elmHtml );\r
227                 \r
228                         head = Node._head = elmHead && new Node( elmHead );\r
229                 \r
230                         body = Node._body = new Node( elmBody );\r
231                         \r
232                         body._root   = html._root = head._root = body;// _root は html だろ\r
233                         body.parent  = head.parent = html;\r
234                         html._xnodes = [ head, body ];                  \r
235                         \r
236                         Node.root = body; // 後方互換\r
237                         \r
238                         html.appendTo = html.appendToRoot = html.before = html.after = html.clone = html.remove = html.destroy = html.prevNode = html.nextNode =\r
239                         html.create = html.createText = html.createAt = html.createTextAt = html.append = html.appendAt = html.empty = html.html = html.text =\r
240                         head.appendTo = head.appendToRoot = head.before = head.after = head.clone = head.remove = head.destroy = head.prevNode = head.nextNode =\r
241                         head.empty = head.html = head.text =\r
242                         body.appendTo = body.appendToRoot = body.before = body.after = body.clone = body.remove = body.destroy = body.prevNode = body.nextNode = new Function( 'return this' );\r
243 \r
244                         X.Dom.listenOnce( X_TEMP.SYSTEM_EVENT_PRE_INIT, function(){\r
245                                 X_Dom_readyState = X_TEMP.SYSTEM_EVENT_XTREE;\r
246                                 !X_TEMP.X_Dom_useBuilder && X.Dom.asyncDispatch( 0, X_TEMP.SYSTEM_EVENT_XTREE );\r
247                         } );\r
248                         \r
249                         X.Dom.listenOnce( X_TEMP.SYSTEM_EVENT_XTREE, function(){\r
250                                 X_Dom_readyState = X_TEMP.SYSTEM_EVENT_INIT;\r
251                                 //X.UA.Opera7 && alert( 'bc' );\r
252                                 Node._body.appendAt( 0,\r
253                                         Node._systemNode = Node.create( 'div', { 'class' : 'hidden-system-node' } ),\r
254                                         Node._fontSizeNode = Node.create( 'div', { 'class' : 'hidden-system-node' } ).cssText( 'line-height:1;height:1em;' ).text( 'X' )\r
255                                 )._startUpdate();\r
256 \r
257                                 X.Dom.asyncDispatch( 0, X_TEMP.SYSTEM_EVENT_INIT );\r
258                         } );\r
259 \r
260                         X.Dom.listenOnce( X_TEMP.SYSTEM_EVENT_INIT, function(){\r
261                                 var size = X_Dom_getWindowSize();\r
262                                 \r
263                                 if( X_Dom_orientationchange ){\r
264                                         X.Dom.Node._window.listen( 'orientationchange', X_Dom_orientationchange );\r
265                                 };\r
266                                 \r
267                                 if( X_Dom_detectFontSize ){\r
268                                         X.Dom.Node._window.listen( 'resize', X_Dom_resize );\r
269                                         X.Timer.add( 333, X_Dom_detectFontSize );\r
270                                 } else {\r
271                                         X.Timer.add( 333, X_Dom_resize );\r
272                                 };\r
273                                 \r
274                                 X_Dom_baseFontSize = Node._fontSizeNode._rawObject.offsetHeight;\r
275                                 \r
276                                 X_Dom_readyState = X.Event.XDOM_READY;\r
277                                 X.Dom.asyncDispatch( 0, { type : X.Event.XDOM_READY, w : X_Dom_width = size[ 0 ], h : X_Dom_height = size[ 1 ] } );\r
278                         } );\r
279 \r
280                         X.Dom.asyncDispatch( 0, X_TEMP.SYSTEM_EVENT_PRE_INIT ); \r
281 \r
282                         Node._window\r
283                                 .listen( 'beforeunload', X.Dom )\r
284                                 .listenOnce( 'unload', X.Dom );\r
285 \r
286 //ブラウザの戻るボタンで戻ったときに呼ばれるイベントとかキャッシュとかそこらへんのこと\r
287 //http://d.hatena.ne.jp/koumiya/20080916/1221580149\r
288 \r
289                         if( document[ 'hidden' ] !== undefined ) {// iOS 7+\r
290                                 Node._document.listen( 'visibilitychange', X.Dom );\r
291                         } else\r
292                         if( document[ 'webkitHidden' ] !== undefined ) {\r
293                                 Node._document.listen( 'webkitvisibilitychange', X.Dom );\r
294                         } else\r
295                         if( X.UA.iOS && window[ 'onpageshow' ] !== undefined ) {\r
296                                 Node._window.listen( 'pageshow', X.Dom )\r
297                                                         .listen( 'pagehide', X.Dom );   \r
298                         } else {\r
299                                 Node._window.listen( 'focus', X.Dom )\r
300                                                         .listen( 'blur', X.Dom );\r
301                         };\r
302 \r
303                         return X_Callback_UN_LISTEN;\r
304                 };\r
305 \r
306                 function X_Dom_getWindowSize(){\r
307                         return X.UA.IE ?\r
308                                 [ X_Dom_rootElement.clientWidth, X_Dom_rootElement.clientHeight ] :\r
309                                 [ window.innerWidth, window.innerHeight ];\r
310                 };\r
311 \r
312 \r
313 if( !( X.UA.IE < 9 || X.UA.iOS ) ){\r
314         var X_Dom_detectFontSize = function(){\r
315                 var size = Node._fontSizeNode._rawObject.offsetHeight;\r
316                 if( X_Dom_baseFontSize !== size ){\r
317                         X_Dom_baseFontSize && X.Dom.asyncDispatch( 0, { type : X.Dom.Event.BASE_FONT_RESIZED, fontSize : size, w : X_Dom_width, h : X_Dom_height } );\r
318                         X_Dom_baseFontSize = size;\r
319                 };\r
320         };\r
321 };\r
322 \r
323 if( window[ 'orientation' ] !== undefined ){\r
324         var X_Dom_orientationchange = function( e ){\r
325                 X_Dom_orientationFlag = true;\r
326                 !X.UA.Android && X_Dom_resize();\r
327                 //console.log( '-- orientationchange : ' + X.Dom.getSize[ 0 ] + ' ' + X.Dom.getSize[ 1 ] );\r
328         },\r
329         X_Dom_orientationFlag;\r
330 };\r
331 \r
332 console.log( 'X.Dom dom:w3c=' + X_UA_DOM.W3C + ' ev:w3c=' + X_UA_EVENT.W3C );\r