OSDN Git Service

c0a77d1d435eff5f2789e7269df347a529e42433
[pettanr/clientJs.git] / 0.6.x / js / 05_util / 01_XNinjaIframe.js
1 /**\r
2  * http://msdn.microsoft.com/ja-jp/library/ie/hh180174%28v=vs.85%29.aspx\r
3  * 孤立するとウィンドウ オブジェクトのプロパティが消去される\r
4  * \r
5  * http://qiita.com/sou/items/3380d4fa9b08b27bb387\r
6  * モバイルブラウザでの iframe の挙動(Mobile Safari, Chrome for Android)\r
7  * \r
8  * @alias X.Util.NinjaIframe\r
9  * @class NinjaIframe 隠し iframe 機能を提供します。\r
10  * @extends {Node}\r
11  */\r
12 var X_NinjaIframe = X[ 'Util' ][ 'NinjaIframe' ] = Node[ 'inherits' ](\r
13         'NinjaIframe',\r
14         \r
15         /** @lends NinjaIframe.prototype */\r
16         {\r
17                 /* autoRefresh  : 0, */\r
18                 \r
19                 /**\r
20                  * iframe の contentWindow\r
21                  * @private\r
22                  * @type {window} */\r
23                 _iwin        : null,\r
24                 \r
25                 /**\r
26                  * iframe に write する html 文字時列\r
27                  * @type {string} */\r
28                 _contentHTML : '',\r
29                 \r
30                 /**\r
31                  * iframe の name\r
32                  * @private\r
33                  * @type {string} */\r
34                 _name        : '',\r
35                 \r
36                 /**\r
37                  * iframe への html 文字列の write が完了した\r
38                  * @private\r
39                  * @type {string} */\r
40                 _ready       : false,\r
41                 \r
42                 'Constructor' : function( html ){\r
43                         // TODO src も設定可能に\r
44                         \r
45                         this._name = 'hidden-iframe-' + X_Timer_now();\r
46                         // https://github.com/polygonplanet/Pot.js/blob/master/src/Worker.js\r
47 \r
48                         this[ 'Super' ](\r
49                                 'IFRAME',\r
50                                 {\r
51                                         className         : 'hidden-iframe',\r
52                                         scrolling         : 'no',\r
53                                         allowtransparency : 'no',                                       \r
54                                         frameborder       : 0,\r
55                                         tabindex          : -1,\r
56                                         name              : this._name,\r
57                                         id                : this._name\r
58                                 }\r
59                         );\r
60                         \r
61                         // http://nanto.asablo.jp/blog/2011/12/08/6237308\r
62                         // IE 6/7 で文書間通信を実現するための一案\r
63                         if( X_UA[ 'IE' ] < 9 ){\r
64                                 this[ 'attr' ]( 'src', 'about:blank' );\r
65                         };\r
66                         // Safari 2.0.* bug: iframe's absolute position and src set.\r
67                         if( !X_UA[ 'Webkit' ]  ){\r
68                                 this[ 'css' ]( { position : 'absolute' } );\r
69                         };\r
70                         \r
71                         if( html ) this._contentHTML = html;                    \r
72                         \r
73                         this[ 'appendTo' ]( X_Node_systemNode )\r
74                                 [ 'listenOnce' ]( X_EVENT_KILL_INSTANCE, X_Util_NinjaIframe_handleEvent );\r
75                         \r
76                         X_ViewPort[ 'listenOnce' ]( X_EVENT_AFTER_UPDATE, this, X_Util_NinjaIframe_handleEvent );\r
77                 },\r
78                 \r
79                 /**\r
80                  * iframe 内をリフレッシュ、または内容を上書きする\r
81                  * @param {string=} opt_contentHTML html文字列\r
82                  * @return {NinjaIframe} チェーンメソッド\r
83                  */\r
84                 'refresh' : function( opt_contentHTML ){\r
85                         var raw = this[ '_rawObject' ],\r
86                                 idoc;\r
87                                 \r
88                         this._ready = false;\r
89                         \r
90                         if( !this._iwin ){\r
91                                 this._contentHTML = opt_contentHTML;\r
92                                 return this;\r
93                         };\r
94                         \r
95                         if( X_UA[ 'IE5x' ] ){\r
96                                 this._iwin.location.href = 'about:blank'; // reload() では、IE5.5(IETester)で2回目移行の操作でerrorが出る(doc取得やopen,writeで)\r
97                         } else {\r
98                                 this._iwin.location.reload();\r
99                         };\r
100                         \r
101                         if( !X_Type_isString( opt_contentHTML ) ) return this;\r
102                         \r
103                         this._contentHTML = opt_contentHTML;\r
104 \r
105                         if( !( X_UA[ 'IE' ] < 9 ) ){\r
106                                 X_Util_NinjaIframe_writeToIframe( this );\r
107                         };\r
108                         \r
109                         return this;\r
110                 }\r
111                 \r
112         }\r
113 );\r
114 \r
115 \r
116 function X_Util_NinjaIframe_handleEvent( e ){\r
117         var raw = this[ '_rawObject' ];\r
118         \r
119         switch( e.type ){\r
120                 case X_EVENT_AFTER_UPDATE :\r
121                         this._iwin = raw.contentWindow || ( raw.contentDocument && raw.contentDocument.parentWindow ) || window.frames[ this._name ];\r
122                         // http://d.hatena.ne.jp/NeoCat/20080921/1221940658\r
123                         // こちらに名前をsetしないとtargetが動作しない\r
124                         if( X_UA[ 'IE' ] ) this._iwin.name = this._name;\r
125                         \r
126                         this[ 'listen' ]( X_UA[ 'IE' ] < 9 ? 'readystatechange' : [ 'load', 'error' ], X_Util_NinjaIframe_handleEvent );\r
127                         \r
128                         if( !( X_UA[ 'IE' ] < 9 ) ){\r
129                                 X_Util_NinjaIframe_writeToIframe( this );\r
130                                 return;\r
131                         };\r
132                         //break; これあると IE8 で駄目!\r
133                         \r
134                 case 'readystatechange' :\r
135                         if( ( raw.readyState !== 'complete' && raw.readyState !== 'loaded' ) ) break;\r
136                         // ie9-\r
137                         if( !this._ready ){\r
138                                 X_Util_NinjaIframe_writeToIframe( this );\r
139                                 break;\r
140                         };\r
141                         // onload\r
142                 case 'load' :\r
143                         console.log( 'iframe load.' );\r
144                         this[ 'asyncDispatch' ]( 'ninjaload' );\r
145                         break;\r
146 \r
147                 case 'error' :\r
148                         this[ 'asyncDispatch' ]( 'ninjaerror' );\r
149                         break;\r
150                 \r
151                 case X_EVENT_KILL_INSTANCE :\r
152                         X_ViewPort[ 'unlisten' ]( X_EVENT_AFTER_UPDATE, this, X_Util_NinjaIframe_handleEvent );\r
153                         this._iwin && this._iwin.close();\r
154                         break;\r
155         };\r
156         \r
157         return X_CALLBACK_STOP_PROPAGATION;\r
158 };\r
159 \r
160 function X_Util_NinjaIframe_writeToIframe( that ){\r
161         var raw  = that[ '_rawObject' ],\r
162                 idoc = raw.contentDocument || that._iwin.document,\r
163                 html = that._contentHTML;\r
164         \r
165         that._ready = true; // これを削除すると ie6,7,8 で Stack overflow at line : 0 意味不明 'readystatechange' が繰り返し起こりループする??\r
166         delete that._contentHTML;\r
167 \r
168         idoc.open();\r
169         idoc.writeln( html );\r
170         idoc.close();\r
171 };\r
172 \r