/*!
- * OOUI v0.33.2
+ * OOUI v0.34.1-pre (3913589098)
* https://www.mediawiki.org/wiki/OOUI
*
* Copyright 2011–2019 OOUI Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: 2019-07-10T12:25:07Z
+ * Date: 2019-09-10T23:46:03Z
*/
( function ( OO ) {
/**
* A Process is a list of steps that are called in sequence. The step can be a number, a
- * jQuery promise, or a function:
+ * promise (jQuery, native, or any other “thenable”), or a function:
*
* - **number**: the process will wait for the specified number of milliseconds before proceeding.
* - **promise**: the process will continue to the next step when the promise is successfully
return $.Deferred().reject( result ).promise();
}
// Duck-type the object to see if it can produce a promise
- if ( result && typeof result.promise === 'function' ) {
+ if ( result && typeof result.then === 'function' ) {
// Use a promise generated from the result
- return result.promise();
+ return $.when( result ).promise();
}
// Use resolved promise for other results
return $.Deferred().resolve().promise();
* @return {Object} Step object, with `callback` and `context` properties
*/
OO.ui.Process.prototype.createStep = function ( step, context ) {
- if ( typeof step === 'number' || typeof step.promise === 'function' ) {
+ if ( typeof step === 'number' || typeof step.then === 'function' ) {
return {
callback: function () {
return step;
compatOpening.notify( { state: 'ready' } );
lifecycle.deferreds.opened.resolve( data );
compatOpening.resolve( manager.compatOpened.promise(), data );
+ manager.togglePreventIosScrolling( true );
}, function () {
lifecycle.deferreds.opened.reject();
compatOpening.reject();
compatOpened = manager.compatOpened;
manager.compatOpened = null;
compatOpened.resolve( compatClosing.promise(), data );
+ manager.togglePreventIosScrolling( false );
setTimeout( function () {
win.hold( data ).then( function () {
compatClosing.notify( { state: 'hold' } );
return this;
};
+/**
+ * Prevent scrolling of the document on iOS devices that don't respect `body { overflow: hidden; }`.
+ *
+ * This function is called when the window is opened (ready), and so the background is covered up,
+ * and the user won't see that we're doing weird things to the scroll position.
+ *
+ * @private
+ * @param {boolean} on
+ * @chainable
+ * @return {OO.ui.WindowManager} The manager, for chaining
+ */
+OO.ui.WindowManager.prototype.togglePreventIosScrolling = function ( on ) {
+ var
+ isIos = /ipad|iphone|ipod/i.test( navigator.userAgent ),
+ $body = $( this.getElementDocument().body ),
+ scrollableRoot = OO.ui.Element.static.getRootScrollableElement( $body[ 0 ] ),
+ stackDepth = $body.data( 'windowManagerGlobalEvents' ) || 0;
+
+ // Only if this is the first/last WindowManager (see #toggleGlobalEvents)
+ if ( !isIos || stackDepth !== 1 ) {
+ return this;
+ }
+
+ if ( on ) {
+ // We can't apply this workaround for non-fullscreen dialogs, because the user would see the
+ // scroll position change. If they have content that needs scrolling, you're out of luck…
+ // Always remember the scroll position in case dialog is closed with different size.
+ this.iosOrigScrollPosition = scrollableRoot.scrollTop;
+ if ( this.getCurrentWindow().getSize() === 'full' ) {
+ $body.add( $body.parent() ).addClass( 'oo-ui-windowManager-ios-modal-ready' );
+ }
+ } else {
+ // Always restore ability to scroll in case dialog was opened with different size.
+ $body.add( $body.parent() ).removeClass( 'oo-ui-windowManager-ios-modal-ready' );
+ if ( this.getCurrentWindow().getSize() === 'full' ) {
+ scrollableRoot.scrollTop = this.iosOrigScrollPosition;
+ }
+ }
+ return this;
+};
+
/**
* Bind or unbind global events for scrolling.
*
( Array.isArray( config.flags ) && config.flags.indexOf( flag ) !== -1 );
}
- // Default to unframed.
config = $.extend( { framed: true }, config );
if ( checkFlag( 'close' ) ) {
// Change close buttons to icon only.
icon: 'close',
invisibleLabel: true
} );
- } else if ( OO.ui.isMobile() && checkFlag( 'back' ) ) {
+ } else if ( checkFlag( 'back' ) ) {
// Change back buttons to icon only.
$.extend( config, {
icon: 'previous',