diff options
author | Jörn Zaefferer <joern.zaefferer@gmail.com> | 2011-06-09 16:40:50 +0200 |
---|---|---|
committer | Jörn Zaefferer <joern.zaefferer@gmail.com> | 2011-06-09 16:40:50 +0200 |
commit | 433ed6eecf055eba327ced7e7c0ff0ce9b5fc304 (patch) | |
tree | bc7b781a57a59def551b6713ef50961b3db36b06 /ui | |
parent | 3dea8f1786e07b17458f4fecff1dbb8b04f79a2d (diff) | |
parent | 40c008872154965d7572cda7911d42857e9fc3a9 (diff) | |
download | jquery-ui-433ed6eecf055eba327ced7e7c0ff0ce9b5fc304.tar.gz jquery-ui-433ed6eecf055eba327ced7e7c0ff0ce9b5fc304.zip |
Merge remote branch 'davidmurdoch/ticket-5645'
Diffstat (limited to 'ui')
-rw-r--r-- | ui/jquery.ui.position.js | 112 |
1 files changed, 80 insertions, 32 deletions
diff --git a/ui/jquery.ui.position.js b/ui/jquery.ui.position.js index 98b8198e2..5ebff5d16 100644 --- a/ui/jquery.ui.position.js +++ b/ui/jquery.ui.position.js @@ -19,6 +19,34 @@ var rhorizontal = /left|center|right/, center = "center", _position = $.fn.position; +$.position = { + scrollbarWidth : function() { + var div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), + innerDiv = div.children()[0], + w1, w2; + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); + + w2 = innerDiv.offsetWidth; + + if ( w1 === w2 ) { + w2 = div[0].clientWidth; + } + + div.remove(); + + return w1 - w2; + }, + getScrollInfo : function( within ) { + var that = within[0], + scrollHeight = within.height() < that.scrollHeight, + scrollWidth = within.width() < that.scrollWidth, + scrollbarWidth = $.position.scrollbarWidth(); + return { height : scrollHeight ? scrollbarWidth : 0, width : scrollWidth ? scrollbarWidth : 0 }; + } +}; + $.fn.position = function( options ) { if ( !options || !options.of ) { return _position.apply( this, arguments ); @@ -28,6 +56,7 @@ $.fn.position = function( options ) { options = $.extend( {}, options ); var target = $( options.of ), + within = $( options.within || window ), targetElem = target[0], collision = ( options.collision || "flip" ).split( " " ), offsets = {}, @@ -110,7 +139,7 @@ $.fn.position = function( options ) { parseInt( offsets.at[ 1 ], 10 ) * ( rpercent.test( offsets.at[ 1 ] ) ? targetHeight / 100 : 1 ) ]; - basePosition.left += atOffset[ 0 ], + basePosition.left += atOffset[ 0 ]; basePosition.top += atOffset[ 1 ]; return this.each(function() { @@ -119,10 +148,11 @@ $.fn.position = function( options ) { elemHeight = elem.outerHeight(), marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, + scrollInfo = $.position.getScrollInfo( within ), collisionWidth = elemWidth + marginLeft + - ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), + ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ) + scrollInfo.width, collisionHeight = elemHeight + marginTop + - ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), + ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ) + scrollInfo.height, position = $.extend( {}, basePosition ), myOffset = [ parseInt( offsets.my[ 0 ], 10 ) * @@ -168,7 +198,8 @@ $.fn.position = function( options ) { collisionHeight: collisionHeight, offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], my: options.my, - at: options.at + at: options.at, + within: within }); } }); @@ -183,32 +214,40 @@ $.fn.position = function( options ) { $.ui.position = { fit: { left: function( position, data ) { - var win = $( window ), - overLeft = win.scrollLeft() - data.collisionPosition.left, - overRight = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? win.scrollLeft() : within.offset().left, + outerWidth = isWindow ? win.width() : within.outerWidth(), + overLeft = withinOffset - data.collisionPosition.left, + overRight = data.collisionPosition.left + data.collisionWidth - outerWidth - withinOffset; // element is wider than window or too far left -> align with left edge - if ( data.collisionWidth > win.width() || overLeft > 0 ) { - position.left = position.left + overLeft; + if ( data.collisionWidth > outerWidth || overLeft > 0 ) { + position.left += overLeft; // too far right -> align with right edge } else if ( overRight > 0 ) { - position.left = position.left - overRight; + position.left -= overRight; // adjust based on position and margin } else { position.left = Math.max( position.left - data.collisionPosition.left, position.left ); } }, top: function( position, data ) { - var win = $( window ), - overTop = win.scrollTop() - data.collisionPosition.top, - overBottom = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? win.scrollTop() : within.offset().top, + outerHeight = isWindow ? win.height() : within.outerHeight(), + overTop = withinOffset - data.collisionPosition.top, + overBottom = data.collisionPosition.top + data.collisionHeight - outerHeight - withinOffset; // element is taller than window or too far up -> align with top edge - if ( data.collisionHeight > win.height() || overTop > 0 ) { - position.top = position.top + overTop; + if ( data.collisionHeight > outerHeight || overTop > 0 ) { + position.top += overTop; // too far down -> align with bottom edge } else if ( overBottom > 0 ) { - position.top = position.top - overBottom; + position.top -= overBottom; // adjust based on position and margin } else { position.top = Math.max( position.top - data.collisionPosition.top, position.top ); @@ -220,8 +259,15 @@ $.ui.position = { if ( data.at[ 0 ] === center ) { return; } - var win = $( window ), - over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), + + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? 0 : within.offset().left, + outerWidth = isWindow ? within.width() : within.outerWidth(), + overLeft = data.collisionPosition.left - withinOffset, + overRight = data.collisionPosition.left + data.collisionWidth - outerWidth - withinOffset, + left = data.my[ 0 ] === "left", myOffset = data.my[ 0 ] === "left" ? -data.elemWidth : data.my[ 0 ] === "right" ? @@ -231,19 +277,23 @@ $.ui.position = { data.targetWidth : -data.targetWidth, offset = -2 * data.offset[ 0 ]; - position.left += data.collisionPosition.left < 0 ? - myOffset + atOffset + offset : - over > 0 ? - myOffset + atOffset + offset : - 0; + if ( overLeft < 0 || overRight > 0 ) { + position.left += myOffset + atOffset + offset; + } }, top: function( position, data ) { if ( data.at[ 1 ] === center ) { return; } - var win = $( window ), - over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), - myOffset = data.my[ 1 ] === "top" ? + var within = data.within, + win = $( window ), + isWindow = $.isWindow( data.within[0] ), + withinOffset = isWindow ? 0 : within.offset().top, + outerHeight = isWindow ? within.height() : within.outerHeight(), + overTop = data.collisionPosition.top - withinOffset, + overBottom = data.collisionPosition.top + data.collisionHeight - outerHeight - withinOffset, + top = data.my[ 1 ] === "top", + myOffset = top ? -data.elemHeight : data.my[ 1 ] === "bottom" ? data.elemHeight : @@ -252,11 +302,9 @@ $.ui.position = { data.targetHeight : -data.targetHeight, offset = -2 * data.offset[ 1 ]; - position.top += data.collisionPosition.top < 0 ? - myOffset + atOffset + offset : - over > 0 ? - myOffset + atOffset + offset : - 0; + if ( overTop < 0 || overBottom > 0) { + position.top += myOffset + atOffset + offset; + } } } }; @@ -297,4 +345,4 @@ if ( $.uiBackCompat !== false ) { }( jQuery ) ); } -}( jQuery ) ); +}( jQuery ) );
\ No newline at end of file |