2 * jQuery UI Position 1.8.24
4 * Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
8 * http://docs.jquery.com/UI/Position
10 (function( $, undefined ) {
14 var horizontalPositions
= /left|center|right/,
15 verticalPositions
= /top|center|bottom/,
18 _position
= $.fn
.position
,
19 _offset
= $.fn
.offset
;
21 $.fn
.position = function( options
) {
22 if ( !options
|| !options
.of ) {
23 return _position
.apply( this, arguments
);
26 // make a copy, we don't want to modify arguments
27 options
= $.extend( {}, options
);
29 var target
= $( options
.of ),
30 targetElem
= target
[0],
31 collision
= ( options
.collision
|| "flip" ).split( " " ),
32 offset
= options
.offset
? options
.offset
.split( " " ) : [ 0, 0 ],
37 if ( targetElem
.nodeType
=== 9 ) {
38 targetWidth
= target
.width();
39 targetHeight
= target
.height();
40 basePosition
= { top
: 0, left
: 0 };
41 // TODO: use $.isWindow() in 1.9
42 } else if ( targetElem
.setTimeout
) {
43 targetWidth
= target
.width();
44 targetHeight
= target
.height();
45 basePosition
= { top
: target
.scrollTop(), left
: target
.scrollLeft() };
46 } else if ( targetElem
.preventDefault
) {
47 // force left top to allow flipping
48 options
.at
= "left top";
49 targetWidth
= targetHeight
= 0;
50 basePosition
= { top
: options
.of.pageY
, left
: options
.of.pageX
};
52 targetWidth
= target
.outerWidth();
53 targetHeight
= target
.outerHeight();
54 basePosition
= target
.offset();
57 // force my and at to have valid horizontal and veritcal positions
58 // if a value is missing or invalid, it will be converted to center
59 $.each( [ "my", "at" ], function() {
60 var pos
= ( options
[this] || "" ).split( " " );
61 if ( pos
.length
=== 1) {
62 pos
= horizontalPositions
.test( pos
[0] ) ?
63 pos
.concat( [center
] ) :
64 verticalPositions
.test( pos
[0] ) ?
65 [ center
].concat( pos
) :
68 pos
[ 0 ] = horizontalPositions
.test( pos
[0] ) ? pos
[ 0 ] : center
;
69 pos
[ 1 ] = verticalPositions
.test( pos
[1] ) ? pos
[ 1 ] : center
;
70 options
[ this ] = pos
;
73 // normalize collision option
74 if ( collision
.length
=== 1 ) {
75 collision
[ 1 ] = collision
[ 0 ];
78 // normalize offset option
79 offset
[ 0 ] = parseInt( offset
[0], 10 ) || 0;
80 if ( offset
.length
=== 1 ) {
81 offset
[ 1 ] = offset
[ 0 ];
83 offset
[ 1 ] = parseInt( offset
[1], 10 ) || 0;
85 if ( options
.at
[0] === "right" ) {
86 basePosition
.left
+= targetWidth
;
87 } else if ( options
.at
[0] === center
) {
88 basePosition
.left
+= targetWidth
/ 2;
91 if ( options
.at
[1] === "bottom" ) {
92 basePosition
.top
+= targetHeight
;
93 } else if ( options
.at
[1] === center
) {
94 basePosition
.top
+= targetHeight
/ 2;
97 basePosition
.left
+= offset
[ 0 ];
98 basePosition
.top
+= offset
[ 1 ];
100 return this.each(function() {
101 var elem
= $( this ),
102 elemWidth
= elem
.outerWidth(),
103 elemHeight
= elem
.outerHeight(),
104 marginLeft
= parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
105 marginTop
= parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
106 collisionWidth
= elemWidth
+ marginLeft
+
107 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
108 collisionHeight
= elemHeight
+ marginTop
+
109 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
110 position
= $.extend( {}, basePosition
),
113 if ( options
.my
[0] === "right" ) {
114 position
.left
-= elemWidth
;
115 } else if ( options
.my
[0] === center
) {
116 position
.left
-= elemWidth
/ 2;
119 if ( options
.my
[1] === "bottom" ) {
120 position
.top
-= elemHeight
;
121 } else if ( options
.my
[1] === center
) {
122 position
.top
-= elemHeight
/ 2;
125 // prevent fractions if jQuery version doesn't support them (see #5280)
126 if ( !support
.fractions
) {
127 position
.left
= Math
.round( position
.left
);
128 position
.top
= Math
.round( position
.top
);
131 collisionPosition
= {
132 left
: position
.left
- marginLeft
,
133 top
: position
.top
- marginTop
136 $.each( [ "left", "top" ], function( i
, dir
) {
137 if ( $.ui
.position
[ collision
[i
] ] ) {
138 $.ui
.position
[ collision
[i
] ][ dir
]( position
, {
139 targetWidth
: targetWidth
,
140 targetHeight
: targetHeight
,
141 elemWidth
: elemWidth
,
142 elemHeight
: elemHeight
,
143 collisionPosition
: collisionPosition
,
144 collisionWidth
: collisionWidth
,
145 collisionHeight
: collisionHeight
,
153 if ( $.fn
.bgiframe
) {
156 elem
.offset( $.extend( position
, { using
: options
.using
} ) );
162 left: function( position
, data
) {
163 var win
= $( window
),
164 over
= data
.collisionPosition
.left
+ data
.collisionWidth
- win
.width() - win
.scrollLeft();
165 position
.left
= over
> 0 ? position
.left
- over
: Math
.max( position
.left
- data
.collisionPosition
.left
, position
.left
);
167 top: function( position
, data
) {
168 var win
= $( window
),
169 over
= data
.collisionPosition
.top
+ data
.collisionHeight
- win
.height() - win
.scrollTop();
170 position
.top
= over
> 0 ? position
.top
- over
: Math
.max( position
.top
- data
.collisionPosition
.top
, position
.top
);
175 left: function( position
, data
) {
176 if ( data
.at
[0] === center
) {
179 var win
= $( window
),
180 over
= data
.collisionPosition
.left
+ data
.collisionWidth
- win
.width() - win
.scrollLeft(),
181 myOffset
= data
.my
[ 0 ] === "left" ?
183 data
.my
[ 0 ] === "right" ?
186 atOffset
= data
.at
[ 0 ] === "left" ?
189 offset
= -2 * data
.offset
[ 0 ];
190 position
.left
+= data
.collisionPosition
.left
< 0 ?
191 myOffset
+ atOffset
+ offset
:
193 myOffset
+ atOffset
+ offset
:
196 top: function( position
, data
) {
197 if ( data
.at
[1] === center
) {
200 var win
= $( window
),
201 over
= data
.collisionPosition
.top
+ data
.collisionHeight
- win
.height() - win
.scrollTop(),
202 myOffset
= data
.my
[ 1 ] === "top" ?
204 data
.my
[ 1 ] === "bottom" ?
207 atOffset
= data
.at
[ 1 ] === "top" ?
210 offset
= -2 * data
.offset
[ 1 ];
211 position
.top
+= data
.collisionPosition
.top
< 0 ?
212 myOffset
+ atOffset
+ offset
:
214 myOffset
+ atOffset
+ offset
:
220 // offset setter from jQuery 1.4
221 if ( !$.offset
.setOffset
) {
222 $.offset
.setOffset = function( elem
, options
) {
223 // set position first, in-case top/left are set even on static elem
224 if ( /static/.test( $.curCSS( elem
, "position" ) ) ) {
225 elem
.style
.position
= "relative";
227 var curElem
= $( elem
),
228 curOffset
= curElem
.offset(),
229 curTop
= parseInt( $.curCSS( elem
, "top", true ), 10 ) || 0,
230 curLeft
= parseInt( $.curCSS( elem
, "left", true ), 10) || 0,
232 top
: (options
.top
- curOffset
.top
) + curTop
,
233 left
: (options
.left
- curOffset
.left
) + curLeft
236 if ( 'using' in options
) {
237 options
.using
.call( elem
, props
);
239 curElem
.css( props
);
243 $.fn
.offset = function( options
) {
244 var elem
= this[ 0 ];
245 if ( !elem
|| !elem
.ownerDocument
) { return null; }
247 if ( $.isFunction( options
) ) {
248 return this.each(function( i
) {
249 $( this ).offset( options
.call( this, i
, $( this ).offset() ) );
252 return this.each(function() {
253 $.offset
.setOffset( this, options
);
256 return _offset
.call( this );
260 // jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
265 // fraction support test (older versions of jQuery don't support fractions)
267 var body
= document
.getElementsByTagName( "body" )[ 0 ],
268 div
= document
.createElement( "div" ),
269 testElement
, testElementParent
, testElementStyle
, offset
, offsetTotal
;
271 //Create a "fake body" for testing based on method used in jQuery.support
272 testElement
= document
.createElement( body
? "div" : "body" );
274 visibility
: "hidden",
282 $.extend( testElementStyle
, {
283 position
: "absolute",
288 for ( var i
in testElementStyle
) {
289 testElement
.style
[ i
] = testElementStyle
[ i
];
291 testElement
.appendChild( div
);
292 testElementParent
= body
|| document
.documentElement
;
293 testElementParent
.insertBefore( testElement
, testElementParent
.firstChild
);
295 div
.style
.cssText
= "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;";
297 offset
= $( div
).offset( function( _
, offset
) {
301 testElement
.innerHTML
= "";
302 testElementParent
.removeChild( testElement
);
304 offsetTotal
= offset
.top
+ offset
.left
+ ( body
? 2000 : 0 );
305 support
.fractions
= offsetTotal
> 21 && offsetTotal
< 22;