sonata_jqueryui_js_jquery.ui.position_10.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /*!
  2. * jQuery UI Position 1.10.4
  3. * http://jqueryui.com
  4. *
  5. * Copyright 2014 jQuery Foundation and other contributors
  6. * Released under the MIT license.
  7. * http://jquery.org/license
  8. *
  9. * http://api.jqueryui.com/position/
  10. */
  11. (function( $, undefined ) {
  12. $.ui = $.ui || {};
  13. var cachedScrollbarWidth,
  14. max = Math.max,
  15. abs = Math.abs,
  16. round = Math.round,
  17. rhorizontal = /left|center|right/,
  18. rvertical = /top|center|bottom/,
  19. roffset = /[\+\-]\d+(\.[\d]+)?%?/,
  20. rposition = /^\w+/,
  21. rpercent = /%$/,
  22. _position = $.fn.position;
  23. function getOffsets( offsets, width, height ) {
  24. return [
  25. parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
  26. parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
  27. ];
  28. }
  29. function parseCss( element, property ) {
  30. return parseInt( $.css( element, property ), 10 ) || 0;
  31. }
  32. function getDimensions( elem ) {
  33. var raw = elem[0];
  34. if ( raw.nodeType === 9 ) {
  35. return {
  36. width: elem.width(),
  37. height: elem.height(),
  38. offset: { top: 0, left: 0 }
  39. };
  40. }
  41. if ( $.isWindow( raw ) ) {
  42. return {
  43. width: elem.width(),
  44. height: elem.height(),
  45. offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
  46. };
  47. }
  48. if ( raw.preventDefault ) {
  49. return {
  50. width: 0,
  51. height: 0,
  52. offset: { top: raw.pageY, left: raw.pageX }
  53. };
  54. }
  55. return {
  56. width: elem.outerWidth(),
  57. height: elem.outerHeight(),
  58. offset: elem.offset()
  59. };
  60. }
  61. $.position = {
  62. scrollbarWidth: function() {
  63. if ( cachedScrollbarWidth !== undefined ) {
  64. return cachedScrollbarWidth;
  65. }
  66. var w1, w2,
  67. div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
  68. innerDiv = div.children()[0];
  69. $( "body" ).append( div );
  70. w1 = innerDiv.offsetWidth;
  71. div.css( "overflow", "scroll" );
  72. w2 = innerDiv.offsetWidth;
  73. if ( w1 === w2 ) {
  74. w2 = div[0].clientWidth;
  75. }
  76. div.remove();
  77. return (cachedScrollbarWidth = w1 - w2);
  78. },
  79. getScrollInfo: function( within ) {
  80. var overflowX = within.isWindow || within.isDocument ? "" :
  81. within.element.css( "overflow-x" ),
  82. overflowY = within.isWindow || within.isDocument ? "" :
  83. within.element.css( "overflow-y" ),
  84. hasOverflowX = overflowX === "scroll" ||
  85. ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
  86. hasOverflowY = overflowY === "scroll" ||
  87. ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
  88. return {
  89. width: hasOverflowY ? $.position.scrollbarWidth() : 0,
  90. height: hasOverflowX ? $.position.scrollbarWidth() : 0
  91. };
  92. },
  93. getWithinInfo: function( element ) {
  94. var withinElement = $( element || window ),
  95. isWindow = $.isWindow( withinElement[0] ),
  96. isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
  97. return {
  98. element: withinElement,
  99. isWindow: isWindow,
  100. isDocument: isDocument,
  101. offset: withinElement.offset() || { left: 0, top: 0 },
  102. scrollLeft: withinElement.scrollLeft(),
  103. scrollTop: withinElement.scrollTop(),
  104. width: isWindow ? withinElement.width() : withinElement.outerWidth(),
  105. height: isWindow ? withinElement.height() : withinElement.outerHeight()
  106. };
  107. }
  108. };
  109. $.fn.position = function( options ) {
  110. if ( !options || !options.of ) {
  111. return _position.apply( this, arguments );
  112. }
  113. // make a copy, we don't want to modify arguments
  114. options = $.extend( {}, options );
  115. var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
  116. target = $( options.of ),
  117. within = $.position.getWithinInfo( options.within ),
  118. scrollInfo = $.position.getScrollInfo( within ),
  119. collision = ( options.collision || "flip" ).split( " " ),
  120. offsets = {};
  121. dimensions = getDimensions( target );
  122. if ( target[0].preventDefault ) {
  123. // force left top to allow flipping
  124. options.at = "left top";
  125. }
  126. targetWidth = dimensions.width;
  127. targetHeight = dimensions.height;
  128. targetOffset = dimensions.offset;
  129. // clone to reuse original targetOffset later
  130. basePosition = $.extend( {}, targetOffset );
  131. // force my and at to have valid horizontal and vertical positions
  132. // if a value is missing or invalid, it will be converted to center
  133. $.each( [ "my", "at" ], function() {
  134. var pos = ( options[ this ] || "" ).split( " " ),
  135. horizontalOffset,
  136. verticalOffset;
  137. if ( pos.length === 1) {
  138. pos = rhorizontal.test( pos[ 0 ] ) ?
  139. pos.concat( [ "center" ] ) :
  140. rvertical.test( pos[ 0 ] ) ?
  141. [ "center" ].concat( pos ) :
  142. [ "center", "center" ];
  143. }
  144. pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
  145. pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
  146. // calculate offsets
  147. horizontalOffset = roffset.exec( pos[ 0 ] );
  148. verticalOffset = roffset.exec( pos[ 1 ] );
  149. offsets[ this ] = [
  150. horizontalOffset ? horizontalOffset[ 0 ] : 0,
  151. verticalOffset ? verticalOffset[ 0 ] : 0
  152. ];
  153. // reduce to just the positions without the offsets
  154. options[ this ] = [
  155. rposition.exec( pos[ 0 ] )[ 0 ],
  156. rposition.exec( pos[ 1 ] )[ 0 ]
  157. ];
  158. });
  159. // normalize collision option
  160. if ( collision.length === 1 ) {
  161. collision[ 1 ] = collision[ 0 ];
  162. }
  163. if ( options.at[ 0 ] === "right" ) {
  164. basePosition.left += targetWidth;
  165. } else if ( options.at[ 0 ] === "center" ) {
  166. basePosition.left += targetWidth / 2;
  167. }
  168. if ( options.at[ 1 ] === "bottom" ) {
  169. basePosition.top += targetHeight;
  170. } else if ( options.at[ 1 ] === "center" ) {
  171. basePosition.top += targetHeight / 2;
  172. }
  173. atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
  174. basePosition.left += atOffset[ 0 ];
  175. basePosition.top += atOffset[ 1 ];
  176. return this.each(function() {
  177. var collisionPosition, using,
  178. elem = $( this ),
  179. elemWidth = elem.outerWidth(),
  180. elemHeight = elem.outerHeight(),
  181. marginLeft = parseCss( this, "marginLeft" ),
  182. marginTop = parseCss( this, "marginTop" ),
  183. collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
  184. collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
  185. position = $.extend( {}, basePosition ),
  186. myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
  187. if ( options.my[ 0 ] === "right" ) {
  188. position.left -= elemWidth;
  189. } else if ( options.my[ 0 ] === "center" ) {
  190. position.left -= elemWidth / 2;
  191. }
  192. if ( options.my[ 1 ] === "bottom" ) {
  193. position.top -= elemHeight;
  194. } else if ( options.my[ 1 ] === "center" ) {
  195. position.top -= elemHeight / 2;
  196. }
  197. position.left += myOffset[ 0 ];
  198. position.top += myOffset[ 1 ];
  199. // if the browser doesn't support fractions, then round for consistent results
  200. if ( !$.support.offsetFractions ) {
  201. position.left = round( position.left );
  202. position.top = round( position.top );
  203. }
  204. collisionPosition = {
  205. marginLeft: marginLeft,
  206. marginTop: marginTop
  207. };
  208. $.each( [ "left", "top" ], function( i, dir ) {
  209. if ( $.ui.position[ collision[ i ] ] ) {
  210. $.ui.position[ collision[ i ] ][ dir ]( position, {
  211. targetWidth: targetWidth,
  212. targetHeight: targetHeight,
  213. elemWidth: elemWidth,
  214. elemHeight: elemHeight,
  215. collisionPosition: collisionPosition,
  216. collisionWidth: collisionWidth,
  217. collisionHeight: collisionHeight,
  218. offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
  219. my: options.my,
  220. at: options.at,
  221. within: within,
  222. elem : elem
  223. });
  224. }
  225. });
  226. if ( options.using ) {
  227. // adds feedback as second argument to using callback, if present
  228. using = function( props ) {
  229. var left = targetOffset.left - position.left,
  230. right = left + targetWidth - elemWidth,
  231. top = targetOffset.top - position.top,
  232. bottom = top + targetHeight - elemHeight,
  233. feedback = {
  234. target: {
  235. element: target,
  236. left: targetOffset.left,
  237. top: targetOffset.top,
  238. width: targetWidth,
  239. height: targetHeight
  240. },
  241. element: {
  242. element: elem,
  243. left: position.left,
  244. top: position.top,
  245. width: elemWidth,
  246. height: elemHeight
  247. },
  248. horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
  249. vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
  250. };
  251. if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
  252. feedback.horizontal = "center";
  253. }
  254. if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
  255. feedback.vertical = "middle";
  256. }
  257. if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
  258. feedback.important = "horizontal";
  259. } else {
  260. feedback.important = "vertical";
  261. }
  262. options.using.call( this, props, feedback );
  263. };
  264. }
  265. elem.offset( $.extend( position, { using: using } ) );
  266. });
  267. };
  268. $.ui.position = {
  269. fit: {
  270. left: function( position, data ) {
  271. var within = data.within,
  272. withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
  273. outerWidth = within.width,
  274. collisionPosLeft = position.left - data.collisionPosition.marginLeft,
  275. overLeft = withinOffset - collisionPosLeft,
  276. overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
  277. newOverRight;
  278. // element is wider than within
  279. if ( data.collisionWidth > outerWidth ) {
  280. // element is initially over the left side of within
  281. if ( overLeft > 0 && overRight <= 0 ) {
  282. newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
  283. position.left += overLeft - newOverRight;
  284. // element is initially over right side of within
  285. } else if ( overRight > 0 && overLeft <= 0 ) {
  286. position.left = withinOffset;
  287. // element is initially over both left and right sides of within
  288. } else {
  289. if ( overLeft > overRight ) {
  290. position.left = withinOffset + outerWidth - data.collisionWidth;
  291. } else {
  292. position.left = withinOffset;
  293. }
  294. }
  295. // too far left -> align with left edge
  296. } else if ( overLeft > 0 ) {
  297. position.left += overLeft;
  298. // too far right -> align with right edge
  299. } else if ( overRight > 0 ) {
  300. position.left -= overRight;
  301. // adjust based on position and margin
  302. } else {
  303. position.left = max( position.left - collisionPosLeft, position.left );
  304. }
  305. },
  306. top: function( position, data ) {
  307. var within = data.within,
  308. withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
  309. outerHeight = data.within.height,
  310. collisionPosTop = position.top - data.collisionPosition.marginTop,
  311. overTop = withinOffset - collisionPosTop,
  312. overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
  313. newOverBottom;
  314. // element is taller than within
  315. if ( data.collisionHeight > outerHeight ) {
  316. // element is initially over the top of within
  317. if ( overTop > 0 && overBottom <= 0 ) {
  318. newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
  319. position.top += overTop - newOverBottom;
  320. // element is initially over bottom of within
  321. } else if ( overBottom > 0 && overTop <= 0 ) {
  322. position.top = withinOffset;
  323. // element is initially over both top and bottom of within
  324. } else {
  325. if ( overTop > overBottom ) {
  326. position.top = withinOffset + outerHeight - data.collisionHeight;
  327. } else {
  328. position.top = withinOffset;
  329. }
  330. }
  331. // too far up -> align with top
  332. } else if ( overTop > 0 ) {
  333. position.top += overTop;
  334. // too far down -> align with bottom edge
  335. } else if ( overBottom > 0 ) {
  336. position.top -= overBottom;
  337. // adjust based on position and margin
  338. } else {
  339. position.top = max( position.top - collisionPosTop, position.top );
  340. }
  341. }
  342. },
  343. flip: {
  344. left: function( position, data ) {
  345. var within = data.within,
  346. withinOffset = within.offset.left + within.scrollLeft,
  347. outerWidth = within.width,
  348. offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
  349. collisionPosLeft = position.left - data.collisionPosition.marginLeft,
  350. overLeft = collisionPosLeft - offsetLeft,
  351. overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
  352. myOffset = data.my[ 0 ] === "left" ?
  353. -data.elemWidth :
  354. data.my[ 0 ] === "right" ?
  355. data.elemWidth :
  356. 0,
  357. atOffset = data.at[ 0 ] === "left" ?
  358. data.targetWidth :
  359. data.at[ 0 ] === "right" ?
  360. -data.targetWidth :
  361. 0,
  362. offset = -2 * data.offset[ 0 ],
  363. newOverRight,
  364. newOverLeft;
  365. if ( overLeft < 0 ) {
  366. newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
  367. if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
  368. position.left += myOffset + atOffset + offset;
  369. }
  370. }
  371. else if ( overRight > 0 ) {
  372. newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
  373. if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
  374. position.left += myOffset + atOffset + offset;
  375. }
  376. }
  377. },
  378. top: function( position, data ) {
  379. var within = data.within,
  380. withinOffset = within.offset.top + within.scrollTop,
  381. outerHeight = within.height,
  382. offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
  383. collisionPosTop = position.top - data.collisionPosition.marginTop,
  384. overTop = collisionPosTop - offsetTop,
  385. overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
  386. top = data.my[ 1 ] === "top",
  387. myOffset = top ?
  388. -data.elemHeight :
  389. data.my[ 1 ] === "bottom" ?
  390. data.elemHeight :
  391. 0,
  392. atOffset = data.at[ 1 ] === "top" ?
  393. data.targetHeight :
  394. data.at[ 1 ] === "bottom" ?
  395. -data.targetHeight :
  396. 0,
  397. offset = -2 * data.offset[ 1 ],
  398. newOverTop,
  399. newOverBottom;
  400. if ( overTop < 0 ) {
  401. newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
  402. if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
  403. position.top += myOffset + atOffset + offset;
  404. }
  405. }
  406. else if ( overBottom > 0 ) {
  407. newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
  408. if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
  409. position.top += myOffset + atOffset + offset;
  410. }
  411. }
  412. }
  413. },
  414. flipfit: {
  415. left: function() {
  416. $.ui.position.flip.left.apply( this, arguments );
  417. $.ui.position.fit.left.apply( this, arguments );
  418. },
  419. top: function() {
  420. $.ui.position.flip.top.apply( this, arguments );
  421. $.ui.position.fit.top.apply( this, arguments );
  422. }
  423. }
  424. };
  425. // fraction support test
  426. (function () {
  427. var testElement, testElementParent, testElementStyle, offsetLeft, i,
  428. body = document.getElementsByTagName( "body" )[ 0 ],
  429. div = document.createElement( "div" );
  430. //Create a "fake body" for testing based on method used in jQuery.support
  431. testElement = document.createElement( body ? "div" : "body" );
  432. testElementStyle = {
  433. visibility: "hidden",
  434. width: 0,
  435. height: 0,
  436. border: 0,
  437. margin: 0,
  438. background: "none"
  439. };
  440. if ( body ) {
  441. $.extend( testElementStyle, {
  442. position: "absolute",
  443. left: "-1000px",
  444. top: "-1000px"
  445. });
  446. }
  447. for ( i in testElementStyle ) {
  448. testElement.style[ i ] = testElementStyle[ i ];
  449. }
  450. testElement.appendChild( div );
  451. testElementParent = body || document.documentElement;
  452. testElementParent.insertBefore( testElement, testElementParent.firstChild );
  453. div.style.cssText = "position: absolute; left: 10.7432222px;";
  454. offsetLeft = $( div ).offset().left;
  455. $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
  456. testElement.innerHTML = "";
  457. testElementParent.removeChild( testElement );
  458. })();
  459. }( jQuery ) );