jquery.ui.dialog.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808
  1. /*!
  2. * jQuery UI Dialog 1.10.3
  3. * http://jqueryui.com
  4. *
  5. * Copyright 2013 jQuery Foundation and other contributors
  6. * Released under the MIT license.
  7. * http://jquery.org/license
  8. *
  9. * http://api.jqueryui.com/dialog/
  10. *
  11. * Depends:
  12. * jquery.ui.core.js
  13. * jquery.ui.widget.js
  14. * jquery.ui.button.js
  15. * jquery.ui.draggable.js
  16. * jquery.ui.mouse.js
  17. * jquery.ui.position.js
  18. * jquery.ui.resizable.js
  19. */
  20. (function( $, undefined ) {
  21. var sizeRelatedOptions = {
  22. buttons: true,
  23. height: true,
  24. maxHeight: true,
  25. maxWidth: true,
  26. minHeight: true,
  27. minWidth: true,
  28. width: true
  29. },
  30. resizableRelatedOptions = {
  31. maxHeight: true,
  32. maxWidth: true,
  33. minHeight: true,
  34. minWidth: true
  35. };
  36. $.widget( "ui.dialog", {
  37. version: "1.10.3",
  38. options: {
  39. appendTo: "body",
  40. autoOpen: true,
  41. buttons: [],
  42. closeOnEscape: true,
  43. closeText: "close",
  44. dialogClass: "",
  45. draggable: true,
  46. hide: null,
  47. height: "auto",
  48. maxHeight: null,
  49. maxWidth: null,
  50. minHeight: 150,
  51. minWidth: 150,
  52. modal: false,
  53. position: {
  54. my: "center",
  55. at: "center",
  56. of: window,
  57. collision: "fit",
  58. // Ensure the titlebar is always visible
  59. using: function( pos ) {
  60. var topOffset = $( this ).css( pos ).offset().top;
  61. if ( topOffset < 0 ) {
  62. $( this ).css( "top", pos.top - topOffset );
  63. }
  64. }
  65. },
  66. resizable: true,
  67. show: null,
  68. title: null,
  69. width: 300,
  70. // callbacks
  71. beforeClose: null,
  72. close: null,
  73. drag: null,
  74. dragStart: null,
  75. dragStop: null,
  76. focus: null,
  77. open: null,
  78. resize: null,
  79. resizeStart: null,
  80. resizeStop: null
  81. },
  82. _create: function() {
  83. this.originalCss = {
  84. display: this.element[0].style.display,
  85. width: this.element[0].style.width,
  86. minHeight: this.element[0].style.minHeight,
  87. maxHeight: this.element[0].style.maxHeight,
  88. height: this.element[0].style.height
  89. };
  90. this.originalPosition = {
  91. parent: this.element.parent(),
  92. index: this.element.parent().children().index( this.element )
  93. };
  94. this.originalTitle = this.element.attr("title");
  95. this.options.title = this.options.title || this.originalTitle;
  96. this._createWrapper();
  97. this.element
  98. .show()
  99. .removeAttr("title")
  100. .addClass("ui-dialog-content ui-widget-content")
  101. .appendTo( this.uiDialog );
  102. this._createTitlebar();
  103. this._createButtonPane();
  104. if ( this.options.draggable && $.fn.draggable ) {
  105. this._makeDraggable();
  106. }
  107. if ( this.options.resizable && $.fn.resizable ) {
  108. this._makeResizable();
  109. }
  110. this._isOpen = false;
  111. },
  112. _init: function() {
  113. if ( this.options.autoOpen ) {
  114. this.open();
  115. }
  116. },
  117. _appendTo: function() {
  118. var element = this.options.appendTo;
  119. if ( element && (element.jquery || element.nodeType) ) {
  120. return $( element );
  121. }
  122. return this.document.find( element || "body" ).eq( 0 );
  123. },
  124. _destroy: function() {
  125. var next,
  126. originalPosition = this.originalPosition;
  127. this._destroyOverlay();
  128. this.element
  129. .removeUniqueId()
  130. .removeClass("ui-dialog-content ui-widget-content")
  131. .css( this.originalCss )
  132. // Without detaching first, the following becomes really slow
  133. .detach();
  134. this.uiDialog.stop( true, true ).remove();
  135. if ( this.originalTitle ) {
  136. this.element.attr( "title", this.originalTitle );
  137. }
  138. next = originalPosition.parent.children().eq( originalPosition.index );
  139. // Don't try to place the dialog next to itself (#8613)
  140. if ( next.length && next[0] !== this.element[0] ) {
  141. next.before( this.element );
  142. } else {
  143. originalPosition.parent.append( this.element );
  144. }
  145. },
  146. widget: function() {
  147. return this.uiDialog;
  148. },
  149. disable: $.noop,
  150. enable: $.noop,
  151. close: function( event ) {
  152. var that = this;
  153. if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
  154. return;
  155. }
  156. this._isOpen = false;
  157. this._destroyOverlay();
  158. if ( !this.opener.filter(":focusable").focus().length ) {
  159. // Hiding a focused element doesn't trigger blur in WebKit
  160. // so in case we have nothing to focus on, explicitly blur the active element
  161. // https://bugs.webkit.org/show_bug.cgi?id=47182
  162. $( this.document[0].activeElement ).blur();
  163. }
  164. this._hide( this.uiDialog, this.options.hide, function() {
  165. that._trigger( "close", event );
  166. });
  167. },
  168. isOpen: function() {
  169. return this._isOpen;
  170. },
  171. moveToTop: function() {
  172. this._moveToTop();
  173. },
  174. _moveToTop: function( event, silent ) {
  175. var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
  176. if ( moved && !silent ) {
  177. this._trigger( "focus", event );
  178. }
  179. return moved;
  180. },
  181. open: function() {
  182. var that = this;
  183. if ( this._isOpen ) {
  184. if ( this._moveToTop() ) {
  185. this._focusTabbable();
  186. }
  187. return;
  188. }
  189. this._isOpen = true;
  190. this.opener = $( this.document[0].activeElement );
  191. this._size();
  192. this._position();
  193. this._createOverlay();
  194. this._moveToTop( null, true );
  195. this._show( this.uiDialog, this.options.show, function() {
  196. that._focusTabbable();
  197. that._trigger("focus");
  198. });
  199. this._trigger("open");
  200. },
  201. _focusTabbable: function() {
  202. // Set focus to the first match:
  203. // 1. First element inside the dialog matching [autofocus]
  204. // 2. Tabbable element inside the content element
  205. // 3. Tabbable element inside the buttonpane
  206. // 4. The close button
  207. // 5. The dialog itself
  208. var hasFocus = this.element.find("[autofocus]");
  209. if ( !hasFocus.length ) {
  210. hasFocus = this.element.find(":tabbable");
  211. }
  212. if ( !hasFocus.length ) {
  213. hasFocus = this.uiDialogButtonPane.find(":tabbable");
  214. }
  215. if ( !hasFocus.length ) {
  216. hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
  217. }
  218. if ( !hasFocus.length ) {
  219. hasFocus = this.uiDialog;
  220. }
  221. hasFocus.eq( 0 ).focus();
  222. },
  223. _keepFocus: function( event ) {
  224. function checkFocus() {
  225. var activeElement = this.document[0].activeElement,
  226. isActive = this.uiDialog[0] === activeElement ||
  227. $.contains( this.uiDialog[0], activeElement );
  228. if ( !isActive ) {
  229. this._focusTabbable();
  230. }
  231. }
  232. event.preventDefault();
  233. checkFocus.call( this );
  234. // support: IE
  235. // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
  236. // so we check again later
  237. this._delay( checkFocus );
  238. },
  239. _createWrapper: function() {
  240. this.uiDialog = $("<div>")
  241. .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
  242. this.options.dialogClass )
  243. .hide()
  244. .attr({
  245. // Setting tabIndex makes the div focusable
  246. tabIndex: -1,
  247. role: "dialog"
  248. })
  249. .appendTo( this._appendTo() );
  250. this._on( this.uiDialog, {
  251. keydown: function( event ) {
  252. if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
  253. event.keyCode === $.ui.keyCode.ESCAPE ) {
  254. event.preventDefault();
  255. this.close( event );
  256. return;
  257. }
  258. // prevent tabbing out of dialogs
  259. if ( event.keyCode !== $.ui.keyCode.TAB ) {
  260. return;
  261. }
  262. var tabbables = this.uiDialog.find(":tabbable"),
  263. first = tabbables.filter(":first"),
  264. last = tabbables.filter(":last");
  265. if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
  266. first.focus( 1 );
  267. event.preventDefault();
  268. } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
  269. last.focus( 1 );
  270. event.preventDefault();
  271. }
  272. },
  273. mousedown: function( event ) {
  274. if ( this._moveToTop( event ) ) {
  275. this._focusTabbable();
  276. }
  277. }
  278. });
  279. // We assume that any existing aria-describedby attribute means
  280. // that the dialog content is marked up properly
  281. // otherwise we brute force the content as the description
  282. if ( !this.element.find("[aria-describedby]").length ) {
  283. this.uiDialog.attr({
  284. "aria-describedby": this.element.uniqueId().attr("id")
  285. });
  286. }
  287. },
  288. _createTitlebar: function() {
  289. var uiDialogTitle;
  290. this.uiDialogTitlebar = $("<div>")
  291. .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
  292. .prependTo( this.uiDialog );
  293. this._on( this.uiDialogTitlebar, {
  294. mousedown: function( event ) {
  295. // Don't prevent click on close button (#8838)
  296. // Focusing a dialog that is partially scrolled out of view
  297. // causes the browser to scroll it into view, preventing the click event
  298. if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
  299. // Dialog isn't getting focus when dragging (#8063)
  300. this.uiDialog.focus();
  301. }
  302. }
  303. });
  304. this.uiDialogTitlebarClose = $("<button></button>")
  305. .button({
  306. label: this.options.closeText,
  307. icons: {
  308. primary: "ui-icon-closethick"
  309. },
  310. text: false
  311. })
  312. .addClass("ui-dialog-titlebar-close")
  313. .appendTo( this.uiDialogTitlebar );
  314. this._on( this.uiDialogTitlebarClose, {
  315. click: function( event ) {
  316. event.preventDefault();
  317. this.close( event );
  318. }
  319. });
  320. uiDialogTitle = $("<span>")
  321. .uniqueId()
  322. .addClass("ui-dialog-title")
  323. .prependTo( this.uiDialogTitlebar );
  324. this._title( uiDialogTitle );
  325. this.uiDialog.attr({
  326. "aria-labelledby": uiDialogTitle.attr("id")
  327. });
  328. },
  329. _title: function( title ) {
  330. if ( !this.options.title ) {
  331. title.html("&#160;");
  332. }
  333. title.text( this.options.title );
  334. },
  335. _createButtonPane: function() {
  336. this.uiDialogButtonPane = $("<div>")
  337. .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");
  338. this.uiButtonSet = $("<div>")
  339. .addClass("ui-dialog-buttonset")
  340. .appendTo( this.uiDialogButtonPane );
  341. this._createButtons();
  342. },
  343. _createButtons: function() {
  344. var that = this,
  345. buttons = this.options.buttons;
  346. // if we already have a button pane, remove it
  347. this.uiDialogButtonPane.remove();
  348. this.uiButtonSet.empty();
  349. if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
  350. this.uiDialog.removeClass("ui-dialog-buttons");
  351. return;
  352. }
  353. $.each( buttons, function( name, props ) {
  354. var click, buttonOptions;
  355. props = $.isFunction( props ) ?
  356. { click: props, text: name } :
  357. props;
  358. // Default to a non-submitting button
  359. props = $.extend( { type: "button" }, props );
  360. // Change the context for the click callback to be the main element
  361. click = props.click;
  362. props.click = function() {
  363. click.apply( that.element[0], arguments );
  364. };
  365. buttonOptions = {
  366. icons: props.icons,
  367. text: props.showText
  368. };
  369. delete props.icons;
  370. delete props.showText;
  371. $( "<button></button>", props )
  372. .button( buttonOptions )
  373. .appendTo( that.uiButtonSet );
  374. });
  375. this.uiDialog.addClass("ui-dialog-buttons");
  376. this.uiDialogButtonPane.appendTo( this.uiDialog );
  377. },
  378. _makeDraggable: function() {
  379. var that = this,
  380. options = this.options;
  381. function filteredUi( ui ) {
  382. return {
  383. position: ui.position,
  384. offset: ui.offset
  385. };
  386. }
  387. this.uiDialog.draggable({
  388. cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
  389. handle: ".ui-dialog-titlebar",
  390. containment: "document",
  391. start: function( event, ui ) {
  392. $( this ).addClass("ui-dialog-dragging");
  393. that._blockFrames();
  394. that._trigger( "dragStart", event, filteredUi( ui ) );
  395. },
  396. drag: function( event, ui ) {
  397. that._trigger( "drag", event, filteredUi( ui ) );
  398. },
  399. stop: function( event, ui ) {
  400. options.position = [
  401. ui.position.left - that.document.scrollLeft(),
  402. ui.position.top - that.document.scrollTop()
  403. ];
  404. $( this ).removeClass("ui-dialog-dragging");
  405. that._unblockFrames();
  406. that._trigger( "dragStop", event, filteredUi( ui ) );
  407. }
  408. });
  409. },
  410. _makeResizable: function() {
  411. var that = this,
  412. options = this.options,
  413. handles = options.resizable,
  414. // .ui-resizable has position: relative defined in the stylesheet
  415. // but dialogs have to use absolute or fixed positioning
  416. position = this.uiDialog.css("position"),
  417. resizeHandles = typeof handles === "string" ?
  418. handles :
  419. "n,e,s,w,se,sw,ne,nw";
  420. function filteredUi( ui ) {
  421. return {
  422. originalPosition: ui.originalPosition,
  423. originalSize: ui.originalSize,
  424. position: ui.position,
  425. size: ui.size
  426. };
  427. }
  428. this.uiDialog.resizable({
  429. cancel: ".ui-dialog-content",
  430. containment: "document",
  431. alsoResize: this.element,
  432. maxWidth: options.maxWidth,
  433. maxHeight: options.maxHeight,
  434. minWidth: options.minWidth,
  435. minHeight: this._minHeight(),
  436. handles: resizeHandles,
  437. start: function( event, ui ) {
  438. $( this ).addClass("ui-dialog-resizing");
  439. that._blockFrames();
  440. that._trigger( "resizeStart", event, filteredUi( ui ) );
  441. },
  442. resize: function( event, ui ) {
  443. that._trigger( "resize", event, filteredUi( ui ) );
  444. },
  445. stop: function( event, ui ) {
  446. options.height = $( this ).height();
  447. options.width = $( this ).width();
  448. $( this ).removeClass("ui-dialog-resizing");
  449. that._unblockFrames();
  450. that._trigger( "resizeStop", event, filteredUi( ui ) );
  451. }
  452. })
  453. .css( "position", position );
  454. },
  455. _minHeight: function() {
  456. var options = this.options;
  457. return options.height === "auto" ?
  458. options.minHeight :
  459. Math.min( options.minHeight, options.height );
  460. },
  461. _position: function() {
  462. // Need to show the dialog to get the actual offset in the position plugin
  463. var isVisible = this.uiDialog.is(":visible");
  464. if ( !isVisible ) {
  465. this.uiDialog.show();
  466. }
  467. this.uiDialog.position( this.options.position );
  468. if ( !isVisible ) {
  469. this.uiDialog.hide();
  470. }
  471. },
  472. _setOptions: function( options ) {
  473. var that = this,
  474. resize = false,
  475. resizableOptions = {};
  476. $.each( options, function( key, value ) {
  477. that._setOption( key, value );
  478. if ( key in sizeRelatedOptions ) {
  479. resize = true;
  480. }
  481. if ( key in resizableRelatedOptions ) {
  482. resizableOptions[ key ] = value;
  483. }
  484. });
  485. if ( resize ) {
  486. this._size();
  487. this._position();
  488. }
  489. if ( this.uiDialog.is(":data(ui-resizable)") ) {
  490. this.uiDialog.resizable( "option", resizableOptions );
  491. }
  492. },
  493. _setOption: function( key, value ) {
  494. /*jshint maxcomplexity:15*/
  495. var isDraggable, isResizable,
  496. uiDialog = this.uiDialog;
  497. if ( key === "dialogClass" ) {
  498. uiDialog
  499. .removeClass( this.options.dialogClass )
  500. .addClass( value );
  501. }
  502. if ( key === "disabled" ) {
  503. return;
  504. }
  505. this._super( key, value );
  506. if ( key === "appendTo" ) {
  507. this.uiDialog.appendTo( this._appendTo() );
  508. }
  509. if ( key === "buttons" ) {
  510. this._createButtons();
  511. }
  512. if ( key === "closeText" ) {
  513. this.uiDialogTitlebarClose.button({
  514. // Ensure that we always pass a string
  515. label: "" + value
  516. });
  517. }
  518. if ( key === "draggable" ) {
  519. isDraggable = uiDialog.is(":data(ui-draggable)");
  520. if ( isDraggable && !value ) {
  521. uiDialog.draggable("destroy");
  522. }
  523. if ( !isDraggable && value ) {
  524. this._makeDraggable();
  525. }
  526. }
  527. if ( key === "position" ) {
  528. this._position();
  529. }
  530. if ( key === "resizable" ) {
  531. // currently resizable, becoming non-resizable
  532. isResizable = uiDialog.is(":data(ui-resizable)");
  533. if ( isResizable && !value ) {
  534. uiDialog.resizable("destroy");
  535. }
  536. // currently resizable, changing handles
  537. if ( isResizable && typeof value === "string" ) {
  538. uiDialog.resizable( "option", "handles", value );
  539. }
  540. // currently non-resizable, becoming resizable
  541. if ( !isResizable && value !== false ) {
  542. this._makeResizable();
  543. }
  544. }
  545. if ( key === "title" ) {
  546. this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
  547. }
  548. },
  549. _size: function() {
  550. // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
  551. // divs will both have width and height set, so we need to reset them
  552. var nonContentHeight, minContentHeight, maxContentHeight,
  553. options = this.options;
  554. // Reset content sizing
  555. this.element.show().css({
  556. width: "auto",
  557. minHeight: 0,
  558. maxHeight: "none",
  559. height: 0
  560. });
  561. if ( options.minWidth > options.width ) {
  562. options.width = options.minWidth;
  563. }
  564. // reset wrapper sizing
  565. // determine the height of all the non-content elements
  566. nonContentHeight = this.uiDialog.css({
  567. height: "auto",
  568. width: options.width
  569. })
  570. .outerHeight();
  571. minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
  572. maxContentHeight = typeof options.maxHeight === "number" ?
  573. Math.max( 0, options.maxHeight - nonContentHeight ) :
  574. "none";
  575. if ( options.height === "auto" ) {
  576. this.element.css({
  577. minHeight: minContentHeight,
  578. maxHeight: maxContentHeight,
  579. height: "auto"
  580. });
  581. } else {
  582. this.element.height( Math.max( 0, options.height - nonContentHeight ) );
  583. }
  584. if (this.uiDialog.is(":data(ui-resizable)") ) {
  585. this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
  586. }
  587. },
  588. _blockFrames: function() {
  589. this.iframeBlocks = this.document.find( "iframe" ).map(function() {
  590. var iframe = $( this );
  591. return $( "<div>" )
  592. .css({
  593. position: "absolute",
  594. width: iframe.outerWidth(),
  595. height: iframe.outerHeight()
  596. })
  597. .appendTo( iframe.parent() )
  598. .offset( iframe.offset() )[0];
  599. });
  600. },
  601. _unblockFrames: function() {
  602. if ( this.iframeBlocks ) {
  603. this.iframeBlocks.remove();
  604. delete this.iframeBlocks;
  605. }
  606. },
  607. _allowInteraction: function( event ) {
  608. if ( $( event.target ).closest(".ui-dialog").length ) {
  609. return true;
  610. }
  611. // TODO: Remove hack when datepicker implements
  612. // the .ui-front logic (#8989)
  613. return !!$( event.target ).closest(".ui-datepicker").length;
  614. },
  615. _createOverlay: function() {
  616. if ( !this.options.modal ) {
  617. return;
  618. }
  619. var that = this,
  620. widgetFullName = this.widgetFullName;
  621. if ( !$.ui.dialog.overlayInstances ) {
  622. // Prevent use of anchors and inputs.
  623. // We use a delay in case the overlay is created from an
  624. // event that we're going to be cancelling. (#2804)
  625. this._delay(function() {
  626. // Handle .dialog().dialog("close") (#4065)
  627. if ( $.ui.dialog.overlayInstances ) {
  628. this.document.bind( "focusin.dialog", function( event ) {
  629. if ( !that._allowInteraction( event ) ) {
  630. event.preventDefault();
  631. $(".ui-dialog:visible:last .ui-dialog-content")
  632. .data( widgetFullName )._focusTabbable();
  633. }
  634. });
  635. }
  636. });
  637. }
  638. this.overlay = $("<div>")
  639. .addClass("ui-widget-overlay ui-front")
  640. .appendTo( this._appendTo() );
  641. this._on( this.overlay, {
  642. mousedown: "_keepFocus"
  643. });
  644. $.ui.dialog.overlayInstances++;
  645. },
  646. _destroyOverlay: function() {
  647. if ( !this.options.modal ) {
  648. return;
  649. }
  650. if ( this.overlay ) {
  651. $.ui.dialog.overlayInstances--;
  652. if ( !$.ui.dialog.overlayInstances ) {
  653. this.document.unbind( "focusin.dialog" );
  654. }
  655. this.overlay.remove();
  656. this.overlay = null;
  657. }
  658. }
  659. });
  660. $.ui.dialog.overlayInstances = 0;
  661. // DEPRECATED
  662. if ( $.uiBackCompat !== false ) {
  663. // position option with array notation
  664. // just override with old implementation
  665. $.widget( "ui.dialog", $.ui.dialog, {
  666. _position: function() {
  667. var position = this.options.position,
  668. myAt = [],
  669. offset = [ 0, 0 ],
  670. isVisible;
  671. if ( position ) {
  672. if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
  673. myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
  674. if ( myAt.length === 1 ) {
  675. myAt[1] = myAt[0];
  676. }
  677. $.each( [ "left", "top" ], function( i, offsetPosition ) {
  678. if ( +myAt[ i ] === myAt[ i ] ) {
  679. offset[ i ] = myAt[ i ];
  680. myAt[ i ] = offsetPosition;
  681. }
  682. });
  683. position = {
  684. my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
  685. myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
  686. at: myAt.join(" ")
  687. };
  688. }
  689. position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
  690. } else {
  691. position = $.ui.dialog.prototype.options.position;
  692. }
  693. // need to show the dialog to get the actual offset in the position plugin
  694. isVisible = this.uiDialog.is(":visible");
  695. if ( !isVisible ) {
  696. this.uiDialog.show();
  697. }
  698. this.uiDialog.position( position );
  699. if ( !isVisible ) {
  700. this.uiDialog.hide();
  701. }
  702. }
  703. });
  704. }
  705. }( jQuery ) );