X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=0.6.x%2Fjs%2F02_dom%2F04_XBoxModel.js;h=0a5c3429e2d788b7c38cbf3c618db29468b97b32;hb=3256f11c856314a1425b8459b9d000a88caf8258;hp=d6b1cb9631a8e60204f025f42aeecc0b9ddf8a13;hpb=d9cca45398f61025472f2858818519562a746e61;p=pettanr%2FclientJs.git diff --git a/0.6.x/js/02_dom/04_XBoxModel.js b/0.6.x/js/02_dom/04_XBoxModel.js index d6b1cb9..0a5c342 100644 --- a/0.6.x/js/02_dom/04_XBoxModel.js +++ b/0.6.x/js/02_dom/04_XBoxModel.js @@ -1,4 +1,4 @@ -X.Dom.BoxModel = { +var X_Node_BoxModel = { CONTENT_BOX : 1, PADDING_BOX : 2, BORDER_BOX : 3, @@ -7,65 +7,51 @@ X.Dom.BoxModel = { boxSizingEnabled : false, // TODO: offsetLeft, offsetTop の基準位置 - absoluteOffset : 0, - - vScrollbarSize : 0, - hScrollbarSize : 0 + absoluteOffset : 0 }; -X.ViewPort.listenOnce( X_TEMP.SYSTEM_EVENT_INIT, function(){ - - var node = Node._systemNode, - - // http://jsdo.it/imaya/kTYg - body = document.body, - defaultOverflow = document.body.style.overflow, - width, height; - - body.style.overflow = 'hidden'; - w = body.clientWidth; - h = body.clientHeight; - - body.style.overflow = 'scroll'; - w -= body.clientWidth; - h -= body.clientHeight; - - if( !w ) w = body.offsetWidth - body.clientWidth; - if( !h ) h = body.offsetHeight - body.clientHeight; - body.style.overflow = defaultOverflow; - - X.Dom.BoxModel.vScrollbarSize = w; - X.Dom.BoxModel.hScrollbarSize = h; - if( h <= 0 ){ // ie6, ie11, firefox で 負の値が返る - console.log( 'invalid hScrollbarSize: ' + h ); - X.Dom.BoxModel.hScrollbarSize = w; - }; - // +X_ViewPort.listenOnce( X_TEMP.SYSTEM_EVENT_INIT, function(){ + var node = X_Node_systemNode; node.cssText( 'width:10px;padding:1px;border:2px solid #0;margin:4px;' ); - X.Dom.BoxModel.defaultBoxModel = node.width() === 10 ? - X.Dom.BoxModel.BORDER_BOX : - X.Dom.BoxModel.CONTENT_BOX; + X_Node_BoxModel.defaultBoxModel = node.width() === 10 ? + X_Node_BoxModel.BORDER_BOX : + X_Node_BoxModel.CONTENT_BOX; - if( X.Dom.BoxModel.defaultBoxModel === X.Dom.BoxModel.CONTENT_BOX ){ - X.Dom.BoxModel.boxSizingEnabled = node.cssText( 'width:10px;padding:1px;border:2px solid #0;margin:4px;' + + if( X_Node_BoxModel.defaultBoxModel === X_Node_BoxModel.CONTENT_BOX ){ + X_Node_BoxModel.boxSizingEnabled = node.cssText( 'width:10px;padding:1px;border:2px solid #0;margin:4px;' + 'box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;-o-box-sizing:border-box;-ms-box-sizing:border-box;' ) .width() === 10; }; + + /* + * 古い Gekco、 Presto、 WebKit では影がレイアウトに影響します。たとえば、width が 100% のボックスに外向きの box-shadow を指定すると、横スクロールバーが表示されてしまいます。 + * TODO boxShadow が有効な要素に対して offsetWidth 等の補正(?) + */ + if( X_Node_CSS_Support[ 'boxShadow' ] && + node.cssText( + X_Node_CSS_uncamelize( X_Node_CSS_VENDER_PREFIX[ 'boxShadow' ] ) + ':10px 10px 0 0 #000;width:10px;' + ).width() !== 10 + ){ + console.log( node.cssText() + node.width() ); + X_Node_CSS_Support[ 'boxShadowLayoutBug' ] = true; + }; + // padding // border // margin // top - X.Dom.BoxModel.absoluteOffset = + X_Node_BoxModel.absoluteOffset = node.cssText( 'position:absolute;top:0;left:0;margin:1px;border:2px solid #000;padding:4px;' ) .append( '
' ) .firstChild().cssText( 'position:absolute;top:8px;left:8px;margin:16px;border:32px solid #666;padding:64px;' ) .y(); + node.cssText( '' ).empty(); }); @@ -82,18 +68,18 @@ Node.prototype.width = function(){ console.log( 'xnode.width() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.width() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'width' ); + // this.css( X_Node_CSS_Unit.px, 'width' ); return this._rawObject.offsetWidth; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).offsetWidth; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).offsetWidth; } else { }; @@ -104,18 +90,18 @@ Node.prototype.height = function(){ console.log( 'xnode.height() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.height() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'height' ); + // this.css( X_Node_CSS_Unit.px, 'height' ); return this._rawObject.offsetHeight; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).offsetHeight; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).offsetHeight; } else { }; @@ -126,18 +112,18 @@ Node.prototype.clientWidth = function(){ console.log( 'xnode.width() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.width() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'width' ); + // this.css( X_Node_CSS_Unit.px, 'width' ); return this._rawObject.clientWidth; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).clientWidth; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).clientWidth; } else { }; @@ -148,18 +134,18 @@ Node.prototype.clientHeight = function(){ console.log( 'xnode.height() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.height() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'height' ); + // this.css( X_Node_CSS_Unit.px, 'height' ); return this._rawObject.clientHeight; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).clientHeight; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).clientHeight; } else { }; @@ -170,18 +156,18 @@ Node.prototype.scrollWidth = function(){ console.log( 'xnode.width() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.width() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'width' ); + // this.css( X_Node_CSS_Unit.px, 'width' ); return this._rawObject.scrollWidth; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).scrollWidth; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).scrollWidth; } else { }; @@ -192,18 +178,18 @@ Node.prototype.scrollHeight = function(){ console.log( 'xnode.height() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.height() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'height' ); + // this.css( X_Node_CSS_Unit.px, 'height' ); return this._rawObject.scrollHeight; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).scrollHeight; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).scrollHeight; } else { }; @@ -214,18 +200,18 @@ Node.prototype.scrollLeft = function(){ console.log( 'xnode.scrollLeft() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.scrollLeft() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'width' ); + // this.css( X_Node_CSS_Unit.px, 'width' ); return this._rawObject.scrollLeft; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).scrollLeft; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).scrollLeft; } else { }; @@ -236,18 +222,18 @@ Node.prototype.scrollTop = function(){ console.log( 'xnode.scrollTop() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.scrollTop() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'width' ); + // this.css( X_Node_CSS_Unit.px, 'width' ); return this._rawObject.scrollTop; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).scrollTop; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).scrollTop; } else { }; @@ -256,29 +242,29 @@ Node.prototype.scrollTop = function(){ /* -------------------------------------- * x, y * position:absolute かつ x か y が設定されていたら、再描画しないで css オブジェクトから計算した値を返す。 float は? - * position:absolute の指定で自動で top,left を補う必要あり? -> X.Dom.Style + * position:absolute の指定で自動で top,left を補う必要あり? -> X.Node.CSS * 親要素 border 外側からの値。 IE, Firefox, Safari, Chrome の offsetLeft/Topでは、border 内側なので補正する。 * transformX, Y は加える? アニメーション中は? */ -// X.Dom.Style.transform, +// X_Node_CSS_transform, Node.prototype.x = function(){ if( !this.parent ){ console.log( 'xnode.x() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.x() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'left' ); - // this.css( X.Dom.Style.Unit.px, 'translateX' ); + // this.css( X_Node_CSS_Unit.px, 'left' ); + // this.css( X_Node_CSS_Unit.px, 'translateX' ); return this._rawObject.offsetLeft; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).offsetLeft; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).offsetLeft; } else { }; @@ -289,19 +275,19 @@ Node.prototype.y = function(){ console.log( 'xnode.y() : no parent' ); return 0; }; - Node._body._updateTimerID && Node._body._startUpdate(); + X_Node_updateTimerID && X_Node_startUpdate(); if( !this._root ){ console.log( 'xnode.y() : not belong tree.' ); return 0; }; if( this._state & X_Node_State.DISPLAY_NONE ) return 0; if( X_UA_DOM.W3C ){ - // this.css( X.Dom.Style.Unit.px, 'top' ); - // this.css( X.Dom.Style.Unit.px, 'transisitonY' ); + // this.css( X_Node_CSS_Unit.px, 'top' ); + // this.css( X_Node_CSS_Unit.px, 'transisitonY' ); return this._rawObject.offsetTop; } else if( X_UA_DOM.IE4 ){ - return ( this._rawObject || this._ie4getRawNode() ).offsetTop; + return ( this._rawObject || X_Node__ie4getRawNode( this ) ).offsetTop; } else { }; @@ -314,26 +300,30 @@ Node.prototype.offset = function( /* xnodeParent */ ){ console.log( 'xnode.offset() : no parent' ); return { x : 0, y : 0 }; }; - Node._body._updateTimerID && Node._body._startUpdate(); + if( !this._root ){ console.log( 'xnode.offset() : not belong tree.' ); return { x : 0, y : 0 }; }; - if( this._state & X_Node_State.DISPLAY_NONE ) return 0; + if( this._state & X_Node_State.DISPLAY_NONE ) return { x : 0, y : 0 }; - if( X.Dom.Node._body === this || X.Dom.Node._html === this ){ + if( X.Doc.body === this || X.Doc.html === this ){ return { x : 0, y : 0 }; }; + X_Node_updateTimerID && X_Node_startUpdate(); + if( X_UA_DOM.W3C ){ elm = this._rawObject; } else if( X_UA_DOM.IE4 ){ - elm = this._rawObject || this._ie4getRawNode(); + elm = this._rawObject || X_Node__ie4getRawNode( this ); } else { }; + return X_Node_getPosition( elm ); + while( elm && elm !== document.body ){ x += elm.offsetLeft; y += elm.offsetTop; @@ -341,3 +331,62 @@ Node.prototype.offset = function( /* xnodeParent */ ){ }; return { x : x, y : y }; }; + +// エレメントの座標取得 ~スクロール要素~ +// http://n-yagi.0r2.net/script/2009/06/post_14.html + +//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ +// エレメントの絶対座標を得たい +//------------------------------------------------------------------------------ +// 座標取得 +var X_Node_getPosition = + document.documentElement && document.documentElement.getBoundingClientRect ? + function( el ){ + var pos = el.getBoundingClientRect(), + html = document.documentElement, + body = document.body; + return { x:(pos.left + (body.scrollLeft||html.scrollLeft) - html.clientLeft) + , y:(pos.top + (body.scrollTop||html.scrollTop) - html.clientTop) }; + } : + X.UA.Opera < 10 ? + function( el ){ + var ex = 0; + var ey = 0; + do + { + ex += el.offsetLeft; + ey += el.offsetTop; + } + while( el = el.offsetParent ); + // + return {x:ex,y:ey}; + } : + function(target) + { + var ex = 0; + var ey = 0; + // + var el = target; + var bd = document.body; + + do + { + ex += el.offsetLeft || 0; + ey += el.offsetTop || 0; + } + while( el = el.offsetParent ); + // 要素内スクロール対応 + el = target; + do + { + ex -= el.scrollLeft || 0; + ey -= el.scrollTop || 0; + el = el.parentNode; + } + while( el!=bd ); + // + return {x:ex,y:ey}; + }; + +//■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ +