|
1 /* |
|
2 * jQuery UI Position 1.8.1 |
|
3 * |
|
4 * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about) |
|
5 * Dual licensed under the MIT (MIT-LICENSE.txt) |
|
6 * and GPL (GPL-LICENSE.txt) licenses. |
|
7 * |
|
8 * http://docs.jquery.com/UI/Position |
|
9 */ |
|
10 (function( $ ) { |
|
11 |
|
12 $.ui = $.ui || {}; |
|
13 |
|
14 var horizontalPositions = /left|center|right/, |
|
15 horizontalDefault = "center", |
|
16 verticalPositions = /top|center|bottom/, |
|
17 verticalDefault = "center", |
|
18 _position = $.fn.position, |
|
19 _offset = $.fn.offset; |
|
20 |
|
21 $.fn.position = function( options ) { |
|
22 if ( !options || !options.of ) { |
|
23 return _position.apply( this, arguments ); |
|
24 } |
|
25 |
|
26 // make a copy, we don't want to modify arguments |
|
27 options = $.extend( {}, options ); |
|
28 |
|
29 var target = $( options.of ), |
|
30 collision = ( options.collision || "flip" ).split( " " ), |
|
31 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], |
|
32 targetWidth, |
|
33 targetHeight, |
|
34 basePosition; |
|
35 |
|
36 if ( options.of.nodeType === 9 ) { |
|
37 targetWidth = target.width(); |
|
38 targetHeight = target.height(); |
|
39 basePosition = { top: 0, left: 0 }; |
|
40 } else if ( options.of.scrollTo && options.of.document ) { |
|
41 targetWidth = target.width(); |
|
42 targetHeight = target.height(); |
|
43 basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; |
|
44 } else if ( options.of.preventDefault ) { |
|
45 // force left top to allow flipping |
|
46 options.at = "left top"; |
|
47 targetWidth = targetHeight = 0; |
|
48 basePosition = { top: options.of.pageY, left: options.of.pageX }; |
|
49 } else { |
|
50 targetWidth = target.outerWidth(); |
|
51 targetHeight = target.outerHeight(); |
|
52 basePosition = target.offset(); |
|
53 } |
|
54 |
|
55 // force my and at to have valid horizontal and veritcal positions |
|
56 // if a value is missing or invalid, it will be converted to center |
|
57 $.each( [ "my", "at" ], function() { |
|
58 var pos = ( options[this] || "" ).split( " " ); |
|
59 if ( pos.length === 1) { |
|
60 pos = horizontalPositions.test( pos[0] ) ? |
|
61 pos.concat( [verticalDefault] ) : |
|
62 verticalPositions.test( pos[0] ) ? |
|
63 [ horizontalDefault ].concat( pos ) : |
|
64 [ horizontalDefault, verticalDefault ]; |
|
65 } |
|
66 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : horizontalDefault; |
|
67 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : verticalDefault; |
|
68 options[ this ] = pos; |
|
69 }); |
|
70 |
|
71 // normalize collision option |
|
72 if ( collision.length === 1 ) { |
|
73 collision[ 1 ] = collision[ 0 ]; |
|
74 } |
|
75 |
|
76 // normalize offset option |
|
77 offset[ 0 ] = parseInt( offset[0], 10 ) || 0; |
|
78 if ( offset.length === 1 ) { |
|
79 offset[ 1 ] = offset[ 0 ]; |
|
80 } |
|
81 offset[ 1 ] = parseInt( offset[1], 10 ) || 0; |
|
82 |
|
83 if ( options.at[0] === "right" ) { |
|
84 basePosition.left += targetWidth; |
|
85 } else if (options.at[0] === horizontalDefault ) { |
|
86 basePosition.left += targetWidth / 2; |
|
87 } |
|
88 |
|
89 if ( options.at[1] === "bottom" ) { |
|
90 basePosition.top += targetHeight; |
|
91 } else if ( options.at[1] === verticalDefault ) { |
|
92 basePosition.top += targetHeight / 2; |
|
93 } |
|
94 |
|
95 basePosition.left += offset[ 0 ]; |
|
96 basePosition.top += offset[ 1 ]; |
|
97 |
|
98 return this.each(function() { |
|
99 var elem = $( this ), |
|
100 elemWidth = elem.outerWidth(), |
|
101 elemHeight = elem.outerHeight(), |
|
102 position = $.extend( {}, basePosition ); |
|
103 |
|
104 if ( options.my[0] === "right" ) { |
|
105 position.left -= elemWidth; |
|
106 } else if ( options.my[0] === horizontalDefault ) { |
|
107 position.left -= elemWidth / 2; |
|
108 } |
|
109 |
|
110 if ( options.my[1] === "bottom" ) { |
|
111 position.top -= elemHeight; |
|
112 } else if ( options.my[1] === verticalDefault ) { |
|
113 position.top -= elemHeight / 2; |
|
114 } |
|
115 |
|
116 // prevent fractions (see #5280) |
|
117 position.left = parseInt( position.left ); |
|
118 position.top = parseInt( position.top ); |
|
119 |
|
120 $.each( [ "left", "top" ], function( i, dir ) { |
|
121 if ( $.ui.position[ collision[i] ] ) { |
|
122 $.ui.position[ collision[i] ][ dir ]( position, { |
|
123 targetWidth: targetWidth, |
|
124 targetHeight: targetHeight, |
|
125 elemWidth: elemWidth, |
|
126 elemHeight: elemHeight, |
|
127 offset: offset, |
|
128 my: options.my, |
|
129 at: options.at |
|
130 }); |
|
131 } |
|
132 }); |
|
133 |
|
134 if ( $.fn.bgiframe ) { |
|
135 elem.bgiframe(); |
|
136 } |
|
137 elem.offset( $.extend( position, { using: options.using } ) ); |
|
138 }); |
|
139 }; |
|
140 |
|
141 $.ui.position = { |
|
142 fit: { |
|
143 left: function( position, data ) { |
|
144 var win = $( window ), |
|
145 over = position.left + data.elemWidth - win.width() - win.scrollLeft(); |
|
146 position.left = over > 0 ? position.left - over : Math.max( 0, position.left ); |
|
147 }, |
|
148 top: function( position, data ) { |
|
149 var win = $( window ), |
|
150 over = position.top + data.elemHeight - win.height() - win.scrollTop(); |
|
151 position.top = over > 0 ? position.top - over : Math.max( 0, position.top ); |
|
152 } |
|
153 }, |
|
154 |
|
155 flip: { |
|
156 left: function( position, data ) { |
|
157 if ( data.at[0] === "center" ) { |
|
158 return; |
|
159 } |
|
160 var win = $( window ), |
|
161 over = position.left + data.elemWidth - win.width() - win.scrollLeft(), |
|
162 myOffset = data.my[ 0 ] === "left" ? |
|
163 -data.elemWidth : |
|
164 data.my[ 0 ] === "right" ? |
|
165 data.elemWidth : |
|
166 0, |
|
167 offset = -2 * data.offset[ 0 ]; |
|
168 position.left += position.left < 0 ? |
|
169 myOffset + data.targetWidth + offset : |
|
170 over > 0 ? |
|
171 myOffset - data.targetWidth + offset : |
|
172 0; |
|
173 }, |
|
174 top: function( position, data ) { |
|
175 if ( data.at[1] === "center" ) { |
|
176 return; |
|
177 } |
|
178 var win = $( window ), |
|
179 over = position.top + data.elemHeight - win.height() - win.scrollTop(), |
|
180 myOffset = data.my[ 1 ] === "top" ? |
|
181 -data.elemHeight : |
|
182 data.my[ 1 ] === "bottom" ? |
|
183 data.elemHeight : |
|
184 0, |
|
185 atOffset = data.at[ 1 ] === "top" ? |
|
186 data.targetHeight : |
|
187 -data.targetHeight, |
|
188 offset = -2 * data.offset[ 1 ]; |
|
189 position.top += position.top < 0 ? |
|
190 myOffset + data.targetHeight + offset : |
|
191 over > 0 ? |
|
192 myOffset + atOffset + offset : |
|
193 0; |
|
194 } |
|
195 } |
|
196 }; |
|
197 |
|
198 // offset setter from jQuery 1.4 |
|
199 if ( !$.offset.setOffset ) { |
|
200 $.offset.setOffset = function( elem, options ) { |
|
201 // set position first, in-case top/left are set even on static elem |
|
202 if ( /static/.test( $.curCSS( elem, "position" ) ) ) { |
|
203 elem.style.position = "relative"; |
|
204 } |
|
205 var curElem = $( elem ), |
|
206 curOffset = curElem.offset(), |
|
207 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, |
|
208 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, |
|
209 props = { |
|
210 top: (options.top - curOffset.top) + curTop, |
|
211 left: (options.left - curOffset.left) + curLeft |
|
212 }; |
|
213 |
|
214 if ( 'using' in options ) { |
|
215 options.using.call( elem, props ); |
|
216 } else { |
|
217 curElem.css( props ); |
|
218 } |
|
219 }; |
|
220 |
|
221 $.fn.offset = function( options ) { |
|
222 var elem = this[ 0 ]; |
|
223 if ( !elem || !elem.ownerDocument ) { return null; } |
|
224 if ( options ) { |
|
225 return this.each(function() { |
|
226 $.offset.setOffset( this, options ); |
|
227 }); |
|
228 } |
|
229 return _offset.call( this ); |
|
230 }; |
|
231 } |
|
232 |
|
233 }( jQuery )); |