Merge "Add ss_active_users in SiteStats::isSane"
[mediawiki.git] / resources / jquery.ui / jquery.ui.position.js
blob8b20179b1b30a4917d2daa0f311c01f63a3ac10f
1 /*!
2  * jQuery UI Position 1.8.24
3  *
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
7  *
8  * http://docs.jquery.com/UI/Position
9  */
10 (function( $, undefined ) {
12 $.ui = $.ui || {};
14 var horizontalPositions = /left|center|right/,
15         verticalPositions = /top|center|bottom/,
16         center = "center",
17         support = {},
18         _position = $.fn.position,
19         _offset = $.fn.offset;
21 $.fn.position = function( options ) {
22         if ( !options || !options.of ) {
23                 return _position.apply( this, arguments );
24         }
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 ],
33                 targetWidth,
34                 targetHeight,
35                 basePosition;
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 };
51         } else {
52                 targetWidth = target.outerWidth();
53                 targetHeight = target.outerHeight();
54                 basePosition = target.offset();
55         }
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 ) :
66                                         [ center, center ];
67                 }
68                 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
69                 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
70                 options[ this ] = pos;
71         });
73         // normalize collision option
74         if ( collision.length === 1 ) {
75                 collision[ 1 ] = collision[ 0 ];
76         }
78         // normalize offset option
79         offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
80         if ( offset.length === 1 ) {
81                 offset[ 1 ] = offset[ 0 ];
82         }
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;
89         }
91         if ( options.at[1] === "bottom" ) {
92                 basePosition.top += targetHeight;
93         } else if ( options.at[1] === center ) {
94                 basePosition.top += targetHeight / 2;
95         }
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 ),
111                         collisionPosition;
113                 if ( options.my[0] === "right" ) {
114                         position.left -= elemWidth;
115                 } else if ( options.my[0] === center ) {
116                         position.left -= elemWidth / 2;
117                 }
119                 if ( options.my[1] === "bottom" ) {
120                         position.top -= elemHeight;
121                 } else if ( options.my[1] === center ) {
122                         position.top -= elemHeight / 2;
123                 }
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 );
129                 }
131                 collisionPosition = {
132                         left: position.left - marginLeft,
133                         top: position.top - marginTop
134                 };
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,
146                                         offset: offset,
147                                         my: options.my,
148                                         at: options.at
149                                 });
150                         }
151                 });
153                 if ( $.fn.bgiframe ) {
154                         elem.bgiframe();
155                 }
156                 elem.offset( $.extend( position, { using: options.using } ) );
157         });
160 $.ui.position = {
161         fit: {
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 );
166                 },
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 );
171                 }
172         },
174         flip: {
175                 left: function( position, data ) {
176                         if ( data.at[0] === center ) {
177                                 return;
178                         }
179                         var win = $( window ),
180                                 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
181                                 myOffset = data.my[ 0 ] === "left" ?
182                                         -data.elemWidth :
183                                         data.my[ 0 ] === "right" ?
184                                                 data.elemWidth :
185                                                 0,
186                                 atOffset = data.at[ 0 ] === "left" ?
187                                         data.targetWidth :
188                                         -data.targetWidth,
189                                 offset = -2 * data.offset[ 0 ];
190                         position.left += data.collisionPosition.left < 0 ?
191                                 myOffset + atOffset + offset :
192                                 over > 0 ?
193                                         myOffset + atOffset + offset :
194                                         0;
195                 },
196                 top: function( position, data ) {
197                         if ( data.at[1] === center ) {
198                                 return;
199                         }
200                         var win = $( window ),
201                                 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
202                                 myOffset = data.my[ 1 ] === "top" ?
203                                         -data.elemHeight :
204                                         data.my[ 1 ] === "bottom" ?
205                                                 data.elemHeight :
206                                                 0,
207                                 atOffset = data.at[ 1 ] === "top" ?
208                                         data.targetHeight :
209                                         -data.targetHeight,
210                                 offset = -2 * data.offset[ 1 ];
211                         position.top += data.collisionPosition.top < 0 ?
212                                 myOffset + atOffset + offset :
213                                 over > 0 ?
214                                         myOffset + atOffset + offset :
215                                         0;
216                 }
217         }
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";
226                 }
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,
231                         props     = {
232                                 top:  (options.top  - curOffset.top)  + curTop,
233                                 left: (options.left - curOffset.left) + curLeft
234                         };
235                 
236                 if ( 'using' in options ) {
237                         options.using.call( elem, props );
238                 } else {
239                         curElem.css( props );
240                 }
241         };
243         $.fn.offset = function( options ) {
244                 var elem = this[ 0 ];
245                 if ( !elem || !elem.ownerDocument ) { return null; }
246                 if ( options ) {
247                         if ( $.isFunction( options ) ) {
248                                 return this.each(function( i ) {
249                                         $( this ).offset( options.call( this, i, $( this ).offset() ) );
250                                 });
251                         }
252                         return this.each(function() {
253                                 $.offset.setOffset( this, options );
254                         });
255                 }
256                 return _offset.call( this );
257         };
260 // jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css
261 if ( !$.curCSS ) {
262         $.curCSS = $.css;
265 // fraction support test (older versions of jQuery don't support fractions)
266 (function () {
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" );
273         testElementStyle = {
274                 visibility: "hidden",
275                 width: 0,
276                 height: 0,
277                 border: 0,
278                 margin: 0,
279                 background: "none"
280         };
281         if ( body ) {
282                 $.extend( testElementStyle, {
283                         position: "absolute",
284                         left: "-1000px",
285                         top: "-1000px"
286                 });
287         }
288         for ( var i in testElementStyle ) {
289                 testElement.style[ i ] = testElementStyle[ i ];
290         }
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 ) {
298                 return offset;
299         }).offset();
301         testElement.innerHTML = "";
302         testElementParent.removeChild( testElement );
304         offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 );
305         support.fractions = offsetTotal > 21 && offsetTotal < 22;
306 })();
308 }( jQuery ));