OSDN Git Service

acb093931f962c79f341a1ebdd2c30da220771c7
[pettanr/clientJs.git] / 0.6.x / js / 02_dom / 04_XBoxModel.js
1 var X_Node_BoxModel = {\r
2                 CONTENT_BOX      : 1,\r
3                 PADDING_BOX      : 2,\r
4                 BORDER_BOX       : 3\r
5         },\r
6         \r
7         X_Node_BoxModel_defaultBoxModel,\r
8         \r
9         X_Node_BoxModel_boxSizingEnabled,\r
10         // TODO: offsetLeft, offsetTop の基準位置\r
11         X_Node_BoxModel_absoluteOffset;\r
12 \r
13 X_ViewPort[ 'listenOnce' ]( X_EVENT_INIT, function(){\r
14         var node = X_Node_systemNode;\r
15         \r
16         node[ 'cssText' ]( 'width:10px;padding:1px;border:2px solid #0;margin:4px;' );\r
17         \r
18         X_Node_BoxModel_defaultBoxModel = node[ 'width' ]() === 10 ?\r
19                 X_Node_BoxModel.BORDER_BOX :\r
20                 X_Node_BoxModel.CONTENT_BOX;\r
21         \r
22         if( X_Node_BoxModel_defaultBoxModel === X_Node_BoxModel.CONTENT_BOX ){\r
23                 X_Node_BoxModel_boxSizingEnabled = node[ 'cssText' ]( 'width:10px;padding:1px;border:2px solid #0;margin:4px;' +\r
24                         'box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-o-box-sizing:border-box;-ms-box-sizing:border-box;' )\r
25                                                                                         [ 'width' ]() === 10;\r
26         };\r
27         \r
28         /*\r
29          * 古い Gekco、 Presto、 WebKit では影がレイアウトに影響します。たとえば、width が 100% のボックスに外向きの box-shadow を指定すると、横スクロールバーが表示されてしまいます。\r
30          * TODO boxShadow が有効な要素に対して offsetWidth 等の補正(?)\r
31          */\r
32         if( X_Node_CSS_Support[ 'boxShadow' ] &&\r
33                 node[ 'cssText' ](\r
34                                 X_Node_CSS_uncamelize( X_Node_CSS_VENDER_PREFIX[ 'boxShadow' ] ) + ':10px 10px 0 0 #000;width:10px;'\r
35                         )[ 'width' ]() !== 10\r
36         ){\r
37                 console.log( node[ 'cssText' ]() + node[ 'width' ]() );\r
38                 X_Node_CSS_Support[ 'boxShadowLayoutBug' ] = true;\r
39         };\r
40 \r
41         // padding\r
42         // border\r
43         // margin\r
44         // top\r
45 \r
46         X_Node_BoxModel_absoluteOffset =\r
47                 node[ 'cssText' ]( 'position:absolute;top:0;left:0;margin:1px;border:2px solid #000;padding:4px;' )\r
48                         [ 'append' ]( '<div></div>' )\r
49                         [ 'firstChild' ]()\r
50                                 [ 'cssText' ]( 'position:absolute;top:8px;left:8px;margin:16px;border:32px solid #666;padding:64px;' )\r
51                                 [ 'y' ]();\r
52 \r
53         node[ 'cssText' ]( '' )[ 'empty' ]();\r
54 });\r
55 \r
56 /* --------------------------------------\r
57  * Width, Height\r
58  *  display:blobk かつ overflow:hidden かつ size(px,em)が設定されていたら、再描画しないでその値を返す\r
59  *  display:none なら 0\r
60  * \r
61  * getBoxObjectFor\r
62  * getBoundingClientRect\r
63  */\r
64 \r
65 function X_Node_BoxModel_mesure( that, name ){\r
66         var flags = that[ '_flags' ], elm;\r
67         \r
68         if( ( flags & X_NodeFlags_IN_TREE ) === 0 || flags & X_NodeFlags_STYLE_IS_DISPLAY_NONE ) return 0;\r
69         \r
70         X_Node_updateTimerID && X_Node_startUpdate();\r
71         \r
72         elm = that[ '_rawObject' ] || X_Node__ie4getRawNode && X_Node__ie4getRawNode( that );\r
73         return elm ? elm[ name ] : 0;\r
74 };\r
75 \r
76 /**\r
77  * 要素の幅。elm.offsetWidth\r
78  * @alias Node.prototype.width\r
79  * @return {number} \r
80  * @example node.width();\r
81  */\r
82 function X_Node_width(){\r
83         return X_Node_BoxModel_mesure( this, 'offsetWidth' );\r
84         \r
85         // TODO width : length + overflow : hidden ならそれを返す? <- block or inline\r
86         // TODO TextNode どうする?\r
87         //if( X_UA_DOM.IE4 ) return elm ? elm.style.pixelWidth : 0;\r
88         //return elm ? elm.offsetWidth : 0;\r
89 };\r
90 \r
91 /**\r
92  * 要素の高さ。elm.offsetHeight\r
93  * @alias Node.prototype.height\r
94  * @return {number} \r
95  * @example node.height();\r
96  */\r
97 function X_Node_height(){\r
98         return X_Node_BoxModel_mesure( this, 'offsetHeight' );\r
99         \r
100         // this[ 'css' ]( X_Node_CSS_Unit.px, 'height' );\r
101         //if( X_UA_DOM.IE4 ) return elm ? elm.style.pixelHeight : 0;\r
102         //return elm ? elm.offsetHeight : 0;\r
103 };\r
104 \r
105 /**\r
106  * 要素のコンテンツ領域の幅。elm.clientWidth\r
107  * @alias Node.prototype.clientWidth\r
108  * @return {number} \r
109  * @example node.clientWidth();\r
110  */\r
111 function X_Node_clientWidth(){\r
112         return X_Node_BoxModel_mesure( this, 'clientWidth' );\r
113         \r
114         // this[ 'css' ]( X_Node_CSS_Unit.px, 'width' );\r
115         //return elm ? elm.clientWidth : 0;\r
116 };\r
117 \r
118 /**\r
119  * 要素のコンテンツ領域の高さ。elm.clientHeight\r
120  * @alias Node.prototype.clientHeight\r
121  * @return {number} \r
122  * @example node.clientHeight();\r
123  */\r
124 function X_Node_clientHeight(){\r
125         return X_Node_BoxModel_mesure( this, 'clientHeight' );\r
126 \r
127         // this[ 'css' ]( X_Node_CSS_Unit.px, 'height' );\r
128         //return elm ? elm.clientHeight : 0;\r
129 };\r
130 \r
131 /**\r
132  * 要素のスクロール領域の幅。elm.scrollWidth\r
133  * @alias Node.prototype.scrollWidth\r
134  * @return {number} \r
135  * @example node.scrollWidth();\r
136  */\r
137 function X_Node_scrollWidth(){\r
138         return X_Node_BoxModel_mesure( this, 'scrollWidth' );\r
139 \r
140         // this[ 'css' ]( X_Node_CSS_Unit.px, 'width' );\r
141         //return elm ? elm.scrollWidth : 0;\r
142 };\r
143 \r
144 /**\r
145  * 要素のスクロール領域の高さ。elm.scrollHeight\r
146  * @alias Node.prototype.scrollHeight\r
147  * @return {number} \r
148  * @example node.scrollHeight();\r
149  */\r
150 function X_Node_scrollHeight(){\r
151         return X_Node_BoxModel_mesure( this, 'scrollHeight' );\r
152 };\r
153 \r
154 /**\r
155  * 要素のスクロール位置。elm.scrollLeft\r
156  * @alias Node.prototype.scrollLeft\r
157  * @return {number} \r
158  * @example node.scrollLeft();\r
159  */\r
160 function X_Node_scrollLeft(){\r
161         return X_Node_BoxModel_mesure( this, 'scrollLeft' );\r
162 };\r
163 \r
164 /**\r
165  * 要素のスクロール位置。elm.scrollTop\r
166  * @alias Node.prototype.scrollTop\r
167  * @return {number} \r
168  * @example node.scrollTop();\r
169  */\r
170 function X_Node_scrollTop(){\r
171         return X_Node_BoxModel_mesure( this, 'scrollTop' );\r
172 };\r
173 \r
174 /* --------------------------------------\r
175  *  x, y\r
176  *  position:absolute かつ x か y が設定されていたら、再描画しないで css オブジェクトから計算した値を返す。 float は?\r
177  *  position:absolute の指定で自動で top,left を補う必要あり? -> X.Node.CSS\r
178  *  親要素 border 外側からの値。 IE, Firefox, Safari, Chrome の offsetLeft/Topでは、border 内側なので補正する。\r
179  * transformX, Y は加える? アニメーション中は?\r
180  * \r
181  * http://www.din.or.jp/~hagi3/JavaScript/JSTips/DHTML/ProbIE5.htm#StyleObject\r
182  */\r
183 // TODO X_Node_CSS_transform,\r
184 \r
185 /**\r
186  * 要素の親要素に対する位置。offsetLeft\r
187  * @alias Node.prototype.x\r
188  * @return {number} \r
189  * @example node.x();\r
190  */\r
191 function X_Node_x(){\r
192         return X_Node_BoxModel_mesure( this, 'offsetLeft' );\r
193         \r
194         // this[ 'css' ]( X_Node_CSS_Unit.px, 'left' );\r
195         // this[ 'css' ]( X_Node_CSS_Unit.px, 'translateX' );\r
196         //if( X_UA_DOM.IE4 ) return elm ? elm.style.pixelLeft : 0;\r
197         //return elm ? elm.offsetLeft : 0;\r
198 };\r
199 \r
200 /**\r
201  * 要素の親要素に対する位置。offsetTop\r
202  * @alias Node.prototype.y\r
203  * @return {number} \r
204  * @example node.y();\r
205  */\r
206 function X_Node_y(){\r
207         return X_Node_BoxModel_mesure( this, 'offsetTop' );\r
208         \r
209         // this[ 'css' ]( X_Node_CSS_Unit.px, 'top' );\r
210         // this[ 'css' ]( X_Node_CSS_Unit.px, 'transisitonY' );\r
211         //if( X_UA_DOM.IE4 ) return elm ? elm.style.pixelTop : 0;\r
212         //return elm ? elm.offsetTop : 0;\r
213 };\r
214 \r
215 /**\r
216  * 要素の親要素に対する位置。\r
217  * @alias Node.prototype.offset\r
218  * @return {object} { x: {number}, y : {number} }\r
219  * @example node.offset();\r
220  */\r
221 function X_Node_offset( /* xnodeParent */ ){\r
222         var flags = this[ '_flags' ], elm;\r
223         \r
224         if( ( flags & X_NodeFlags_IN_TREE ) === 0 || flags & X_NodeFlags_STYLE_IS_DISPLAY_NONE ) return { x : 0, y : 0 };\r
225         \r
226         if( X_Node_body === this || X_Node_html === this ){\r
227                 return { x : 0, y : 0 };\r
228         };\r
229         \r
230         X_Node_updateTimerID && X_Node_startUpdate();\r
231         \r
232         elm = this[ '_rawObject' ] || X_Node__ie4getRawNode && X_Node__ie4getRawNode( this );\r
233         \r
234         return elm ? X_Node_getPosition( elm ) : { x : 0, y : 0 };\r
235 };\r
236 \r
237 // エレメントの座標取得 ~スクロール要素~\r
238 // http://n-yagi.0r2.net/script/2009/06/post_14.html\r
239 \r
240 //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\r
241 //  エレメントの絶対座標を得たい\r
242 //------------------------------------------------------------------------------\r
243 //  座標取得\r
244 var X_Node_getPosition =\r
245         document.documentElement && document.documentElement.getBoundingClientRect ?\r
246                 function( el ){\r
247                 var pos  = el.getBoundingClientRect(),\r
248                         html = document.documentElement,\r
249                         body = document.body;\r
250                 return  {   x:(pos.left +   (body.scrollLeft||html.scrollLeft)  -   html.clientLeft)\r
251                         ,   y:(pos.top  +   (body.scrollTop||html.scrollTop)    -   html.clientTop) };\r
252                 } :\r
253         X_UA[ 'Opera' ] < 10 ?\r
254                 function( el ){\r
255             var ex  =   0;\r
256             var ey  =   0;\r
257             do\r
258             { \r
259                 ex  +=  el.offsetLeft;\r
260                 ey  +=  el.offsetTop;\r
261             }\r
262             while(  el  =   el.offsetParent );\r
263             //\r
264             return  {x:ex,y:ey};\r
265                 } :\r
266                 function(target)\r
267         {\r
268             var ex  =   0;\r
269             var ey  =   0;\r
270             //\r
271             var el  =   target;\r
272             var bd  =   document.body;\r
273             \r
274             do\r
275             { \r
276                 ex  +=  el.offsetLeft   ||  0;\r
277                 ey  +=  el.offsetTop    ||  0;\r
278             }\r
279             while(  el  =   el.offsetParent );\r
280             //  要素内スクロール対応\r
281             el  =   target;\r
282             do\r
283             {\r
284                 ex  -=  el.scrollLeft   ||  0;\r
285                 ey  -=  el.scrollTop    ||  0;\r
286                 el  =   el.parentNode;\r
287             }\r
288             while(  el!=bd  );\r
289             //\r
290             return  {x:ex,y:ey};\r
291         };\r
292 \r
293 //■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■\r
294 \r