jquery.ui.position.js (6462B)
1 /* 2 * jQuery UI Position 1.8 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 $.each( [ "left", "top" ], function( i, dir ) { 117 if ( $.ui.position[ collision[i] ] ) { 118 $.ui.position[ collision[i] ][ dir ]( position, { 119 targetWidth: targetWidth, 120 targetHeight: targetHeight, 121 elemWidth: elemWidth, 122 elemHeight: elemHeight, 123 offset: offset, 124 my: options.my, 125 at: options.at 126 }); 127 } 128 }); 129 130 if ( $.fn.bgiframe ) { 131 elem.bgiframe(); 132 } 133 elem.offset( $.extend( position, { using: options.using } ) ); 134 }); 135 }; 136 137 $.ui.position = { 138 fit: { 139 left: function( position, data ) { 140 var win = $( window ), 141 over = position.left + data.elemWidth - win.width() - win.scrollLeft(); 142 position.left = over > 0 ? position.left - over : Math.max( 0, position.left ); 143 }, 144 top: function( position, data ) { 145 var win = $( window ), 146 over = position.top + data.elemHeight - win.height() - win.scrollTop(); 147 position.top = over > 0 ? position.top - over : Math.max( 0, position.top ); 148 } 149 }, 150 151 flip: { 152 left: function( position, data ) { 153 if ( data.at[0] === "center" ) { 154 return; 155 } 156 var win = $( window ), 157 over = position.left + data.elemWidth - win.width() - win.scrollLeft(), 158 myOffset = data.my[ 0 ] === "left" ? 159 -data.elemWidth : 160 data.my[ 0 ] === "right" ? 161 data.elemWidth : 162 0, 163 offset = -2 * data.offset[ 0 ]; 164 position.left += position.left < 0 ? 165 myOffset + data.targetWidth + offset : 166 over > 0 ? 167 myOffset - data.targetWidth + offset : 168 0; 169 }, 170 top: function( position, data ) { 171 if ( data.at[1] === "center" ) { 172 return; 173 } 174 var win = $( window ), 175 over = position.top + data.elemHeight - win.height() - win.scrollTop(), 176 myOffset = data.my[ 1 ] === "top" ? 177 -data.elemHeight : 178 data.my[ 1 ] === "bottom" ? 179 data.elemHeight : 180 0, 181 atOffset = data.at[ 1 ] === "top" ? 182 data.targetHeight : 183 -data.targetHeight, 184 offset = -2 * data.offset[ 1 ]; 185 position.top += position.top < 0 ? 186 myOffset + data.targetHeight + offset : 187 over > 0 ? 188 myOffset + atOffset + offset : 189 0; 190 } 191 } 192 }; 193 194 // offset setter from jQuery 1.4 195 if ( !$.offset.setOffset ) { 196 $.offset.setOffset = function( elem, options ) { 197 // set position first, in-case top/left are set even on static elem 198 if ( /static/.test( $.curCSS( elem, "position" ) ) ) { 199 elem.style.position = "relative"; 200 } 201 var curElem = $( elem ), 202 curOffset = curElem.offset(), 203 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, 204 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, 205 props = { 206 top: (options.top - curOffset.top) + curTop, 207 left: (options.left - curOffset.left) + curLeft 208 }; 209 210 if ( 'using' in options ) { 211 options.using.call( elem, props ); 212 } else { 213 curElem.css( props ); 214 } 215 }; 216 217 $.fn.offset = function( options ) { 218 var elem = this[ 0 ]; 219 if ( !elem || !elem.ownerDocument ) { return null; } 220 if ( options ) { 221 return this.each(function() { 222 $.offset.setOffset( this, options ); 223 }); 224 } 225 return _offset.call( this ); 226 }; 227 } 228 229 }( jQuery ));