diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2015-12-17 09:15:42 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2015-12-17 09:44:51 +0100 |
commit | a1789ddde42033f1b05cc4929491214ee6e79383 (patch) | |
tree | 63615735c4ddffaaabf2428946bb26f90899f7bf /vendor/oojs/oojs-ui/src/WindowManager.js | |
parent | 9e06a62f265e3a2aaabecc598d4bc617e06fa32d (diff) |
Update to MediaWiki 1.26.0
Diffstat (limited to 'vendor/oojs/oojs-ui/src/WindowManager.js')
-rw-r--r-- | vendor/oojs/oojs-ui/src/WindowManager.js | 675 |
1 files changed, 0 insertions, 675 deletions
diff --git a/vendor/oojs/oojs-ui/src/WindowManager.js b/vendor/oojs/oojs-ui/src/WindowManager.js deleted file mode 100644 index 4731011a..00000000 --- a/vendor/oojs/oojs-ui/src/WindowManager.js +++ /dev/null @@ -1,675 +0,0 @@ -/** - * Window managers are used to open and close {@link OO.ui.Window windows} and control their presentation. - * Managed windows are mutually exclusive. If a new window is opened while a current window is opening - * or is opened, the current window will be closed and any ongoing {@link OO.ui.Process process} will be cancelled. Windows - * themselves are persistent and—rather than being torn down when closed—can be repopulated with the - * pertinent data and reused. - * - * Over the lifecycle of a window, the window manager makes available three promises: `opening`, - * `opened`, and `closing`, which represent the primary stages of the cycle: - * - * **Opening**: the opening stage begins when the window manager’s #openWindow or a window’s - * {@link OO.ui.Window#open open} method is used, and the window manager begins to open the window. - * - * - an `opening` event is emitted with an `opening` promise - * - the #getSetupDelay method is called and the returned value is used to time a pause in execution before - * the window’s {@link OO.ui.Window#getSetupProcess getSetupProcess} method is called on the - * window and its result executed - * - a `setup` progress notification is emitted from the `opening` promise - * - the #getReadyDelay method is called the returned value is used to time a pause in execution before - * the window’s {@link OO.ui.Window#getReadyProcess getReadyProcess} method is called on the - * window and its result executed - * - a `ready` progress notification is emitted from the `opening` promise - * - the `opening` promise is resolved with an `opened` promise - * - * **Opened**: the window is now open. - * - * **Closing**: the closing stage begins when the window manager's #closeWindow or the - * window's {@link OO.ui.Window#close close} methods is used, and the window manager begins - * to close the window. - * - * - the `opened` promise is resolved with `closing` promise and a `closing` event is emitted - * - the #getHoldDelay method is called and the returned value is used to time a pause in execution before - * the window's {@link OO.ui.Window#getHoldProcess getHoldProces} method is called on the - * window and its result executed - * - a `hold` progress notification is emitted from the `closing` promise - * - the #getTeardownDelay() method is called and the returned value is used to time a pause in execution before - * the window's {@link OO.ui.Window#getTeardownProcess getTeardownProcess} method is called on the - * window and its result executed - * - a `teardown` progress notification is emitted from the `closing` promise - * - the `closing` promise is resolved. The window is now closed - * - * See the [OOjs UI documentation on MediaWiki][1] for more information. - * - * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers - * - * @class - * @extends OO.ui.Element - * @mixins OO.EventEmitter - * - * @constructor - * @param {Object} [config] Configuration options - * @cfg {OO.Factory} [factory] Window factory to use for automatic instantiation - * Note that window classes that are instantiated with a factory must have - * a {@link OO.ui.Dialog#static-name static name} property that specifies a symbolic name. - * @cfg {boolean} [modal=true] Prevent interaction outside the dialog - */ -OO.ui.WindowManager = function OoUiWindowManager( config ) { - // Configuration initialization - config = config || {}; - - // Parent constructor - OO.ui.WindowManager.super.call( this, config ); - - // Mixin constructors - OO.EventEmitter.call( this ); - - // Properties - this.factory = config.factory; - this.modal = config.modal === undefined || !!config.modal; - this.windows = {}; - this.opening = null; - this.opened = null; - this.closing = null; - this.preparingToOpen = null; - this.preparingToClose = null; - this.currentWindow = null; - this.globalEvents = false; - this.$ariaHidden = null; - this.onWindowResizeTimeout = null; - this.onWindowResizeHandler = this.onWindowResize.bind( this ); - this.afterWindowResizeHandler = this.afterWindowResize.bind( this ); - - // Initialization - this.$element - .addClass( 'oo-ui-windowManager' ) - .toggleClass( 'oo-ui-windowManager-modal', this.modal ); -}; - -/* Setup */ - -OO.inheritClass( OO.ui.WindowManager, OO.ui.Element ); -OO.mixinClass( OO.ui.WindowManager, OO.EventEmitter ); - -/* Events */ - -/** - * An 'opening' event is emitted when the window begins to be opened. - * - * @event opening - * @param {OO.ui.Window} win Window that's being opened - * @param {jQuery.Promise} opening An `opening` promise resolved with a value when the window is opened successfully. - * When the `opening` promise is resolved, the first argument of the value is an 'opened' promise, the second argument - * is the opening data. The `opening` promise emits `setup` and `ready` notifications when those processes are complete. - * @param {Object} data Window opening data - */ - -/** - * A 'closing' event is emitted when the window begins to be closed. - * - * @event closing - * @param {OO.ui.Window} win Window that's being closed - * @param {jQuery.Promise} closing A `closing` promise is resolved with a value when the window - * is closed successfully. The promise emits `hold` and `teardown` notifications when those - * processes are complete. When the `closing` promise is resolved, the first argument of its value - * is the closing data. - * @param {Object} data Window closing data - */ - -/** - * A 'resize' event is emitted when a window is resized. - * - * @event resize - * @param {OO.ui.Window} win Window that was resized - */ - -/* Static Properties */ - -/** - * Map of the symbolic name of each window size and its CSS properties. - * - * @static - * @inheritable - * @property {Object} - */ -OO.ui.WindowManager.static.sizes = { - small: { - width: 300 - }, - medium: { - width: 500 - }, - large: { - width: 700 - }, - larger: { - width: 900 - }, - full: { - // These can be non-numeric because they are never used in calculations - width: '100%', - height: '100%' - } -}; - -/** - * Symbolic name of the default window size. - * - * The default size is used if the window's requested size is not recognized. - * - * @static - * @inheritable - * @property {string} - */ -OO.ui.WindowManager.static.defaultSize = 'medium'; - -/* Methods */ - -/** - * Handle window resize events. - * - * @private - * @param {jQuery.Event} e Window resize event - */ -OO.ui.WindowManager.prototype.onWindowResize = function () { - clearTimeout( this.onWindowResizeTimeout ); - this.onWindowResizeTimeout = setTimeout( this.afterWindowResizeHandler, 200 ); -}; - -/** - * Handle window resize events. - * - * @private - * @param {jQuery.Event} e Window resize event - */ -OO.ui.WindowManager.prototype.afterWindowResize = function () { - if ( this.currentWindow ) { - this.updateWindowSize( this.currentWindow ); - } -}; - -/** - * Check if window is opening. - * - * @return {boolean} Window is opening - */ -OO.ui.WindowManager.prototype.isOpening = function ( win ) { - return win === this.currentWindow && !!this.opening && this.opening.state() === 'pending'; -}; - -/** - * Check if window is closing. - * - * @return {boolean} Window is closing - */ -OO.ui.WindowManager.prototype.isClosing = function ( win ) { - return win === this.currentWindow && !!this.closing && this.closing.state() === 'pending'; -}; - -/** - * Check if window is opened. - * - * @return {boolean} Window is opened - */ -OO.ui.WindowManager.prototype.isOpened = function ( win ) { - return win === this.currentWindow && !!this.opened && this.opened.state() === 'pending'; -}; - -/** - * Check if a window is being managed. - * - * @param {OO.ui.Window} win Window to check - * @return {boolean} Window is being managed - */ -OO.ui.WindowManager.prototype.hasWindow = function ( win ) { - var name; - - for ( name in this.windows ) { - if ( this.windows[ name ] === win ) { - return true; - } - } - - return false; -}; - -/** - * Get the number of milliseconds to wait after opening begins before executing the ‘setup’ process. - * - * @param {OO.ui.Window} win Window being opened - * @param {Object} [data] Window opening data - * @return {number} Milliseconds to wait - */ -OO.ui.WindowManager.prototype.getSetupDelay = function () { - return 0; -}; - -/** - * Get the number of milliseconds to wait after setup has finished before executing the ‘ready’ process. - * - * @param {OO.ui.Window} win Window being opened - * @param {Object} [data] Window opening data - * @return {number} Milliseconds to wait - */ -OO.ui.WindowManager.prototype.getReadyDelay = function () { - return 0; -}; - -/** - * Get the number of milliseconds to wait after closing has begun before executing the 'hold' process. - * - * @param {OO.ui.Window} win Window being closed - * @param {Object} [data] Window closing data - * @return {number} Milliseconds to wait - */ -OO.ui.WindowManager.prototype.getHoldDelay = function () { - return 0; -}; - -/** - * Get the number of milliseconds to wait after the ‘hold’ process has finished before - * executing the ‘teardown’ process. - * - * @param {OO.ui.Window} win Window being closed - * @param {Object} [data] Window closing data - * @return {number} Milliseconds to wait - */ -OO.ui.WindowManager.prototype.getTeardownDelay = function () { - return this.modal ? 250 : 0; -}; - -/** - * Get a window by its symbolic name. - * - * If the window is not yet instantiated and its symbolic name is recognized by a factory, it will be - * instantiated and added to the window manager automatically. Please see the [OOjs UI documentation on MediaWiki][3] - * for more information about using factories. - * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers - * - * @param {string} name Symbolic name of the window - * @return {jQuery.Promise} Promise resolved with matching window, or rejected with an OO.ui.Error - * @throws {Error} An error is thrown if the symbolic name is not recognized by the factory. - * @throws {Error} An error is thrown if the named window is not recognized as a managed window. - */ -OO.ui.WindowManager.prototype.getWindow = function ( name ) { - var deferred = $.Deferred(), - win = this.windows[ name ]; - - if ( !( win instanceof OO.ui.Window ) ) { - if ( this.factory ) { - if ( !this.factory.lookup( name ) ) { - deferred.reject( new OO.ui.Error( - 'Cannot auto-instantiate window: symbolic name is unrecognized by the factory' - ) ); - } else { - win = this.factory.create( name ); - this.addWindows( [ win ] ); - deferred.resolve( win ); - } - } else { - deferred.reject( new OO.ui.Error( - 'Cannot get unmanaged window: symbolic name unrecognized as a managed window' - ) ); - } - } else { - deferred.resolve( win ); - } - - return deferred.promise(); -}; - -/** - * Get current window. - * - * @return {OO.ui.Window|null} Currently opening/opened/closing window - */ -OO.ui.WindowManager.prototype.getCurrentWindow = function () { - return this.currentWindow; -}; - -/** - * Open a window. - * - * @param {OO.ui.Window|string} win Window object or symbolic name of window to open - * @param {Object} [data] Window opening data - * @return {jQuery.Promise} An `opening` promise resolved when the window is done opening. - * See {@link #event-opening 'opening' event} for more information about `opening` promises. - * @fires opening - */ -OO.ui.WindowManager.prototype.openWindow = function ( win, data ) { - var manager = this, - opening = $.Deferred(); - - // Argument handling - if ( typeof win === 'string' ) { - return this.getWindow( win ).then( function ( win ) { - return manager.openWindow( win, data ); - } ); - } - - // Error handling - if ( !this.hasWindow( win ) ) { - opening.reject( new OO.ui.Error( - 'Cannot open window: window is not attached to manager' - ) ); - } else if ( this.preparingToOpen || this.opening || this.opened ) { - opening.reject( new OO.ui.Error( - 'Cannot open window: another window is opening or open' - ) ); - } - - // Window opening - if ( opening.state() !== 'rejected' ) { - // If a window is currently closing, wait for it to complete - this.preparingToOpen = $.when( this.closing ); - // Ensure handlers get called after preparingToOpen is set - this.preparingToOpen.done( function () { - if ( manager.modal ) { - manager.toggleGlobalEvents( true ); - manager.toggleAriaIsolation( true ); - } - manager.currentWindow = win; - manager.opening = opening; - manager.preparingToOpen = null; - manager.emit( 'opening', win, opening, data ); - setTimeout( function () { - win.setup( data ).then( function () { - manager.updateWindowSize( win ); - manager.opening.notify( { state: 'setup' } ); - setTimeout( function () { - win.ready( data ).then( function () { - manager.opening.notify( { state: 'ready' } ); - manager.opening = null; - manager.opened = $.Deferred(); - opening.resolve( manager.opened.promise(), data ); - } ); - }, manager.getReadyDelay() ); - } ); - }, manager.getSetupDelay() ); - } ); - } - - return opening.promise(); -}; - -/** - * Close a window. - * - * @param {OO.ui.Window|string} win Window object or symbolic name of window to close - * @param {Object} [data] Window closing data - * @return {jQuery.Promise} A `closing` promise resolved when the window is done closing. - * See {@link #event-closing 'closing' event} for more information about closing promises. - * @throws {Error} An error is thrown if the window is not managed by the window manager. - * @fires closing - */ -OO.ui.WindowManager.prototype.closeWindow = function ( win, data ) { - var manager = this, - closing = $.Deferred(), - opened; - - // Argument handling - if ( typeof win === 'string' ) { - win = this.windows[ win ]; - } else if ( !this.hasWindow( win ) ) { - win = null; - } - - // Error handling - if ( !win ) { - closing.reject( new OO.ui.Error( - 'Cannot close window: window is not attached to manager' - ) ); - } else if ( win !== this.currentWindow ) { - closing.reject( new OO.ui.Error( - 'Cannot close window: window already closed with different data' - ) ); - } else if ( this.preparingToClose || this.closing ) { - closing.reject( new OO.ui.Error( - 'Cannot close window: window already closing with different data' - ) ); - } - - // Window closing - if ( closing.state() !== 'rejected' ) { - // If the window is currently opening, close it when it's done - this.preparingToClose = $.when( this.opening ); - // Ensure handlers get called after preparingToClose is set - this.preparingToClose.done( function () { - manager.closing = closing; - manager.preparingToClose = null; - manager.emit( 'closing', win, closing, data ); - opened = manager.opened; - manager.opened = null; - opened.resolve( closing.promise(), data ); - setTimeout( function () { - win.hold( data ).then( function () { - closing.notify( { state: 'hold' } ); - setTimeout( function () { - win.teardown( data ).then( function () { - closing.notify( { state: 'teardown' } ); - if ( manager.modal ) { - manager.toggleGlobalEvents( false ); - manager.toggleAriaIsolation( false ); - } - manager.closing = null; - manager.currentWindow = null; - closing.resolve( data ); - } ); - }, manager.getTeardownDelay() ); - } ); - }, manager.getHoldDelay() ); - } ); - } - - return closing.promise(); -}; - -/** - * Add windows to the window manager. - * - * Windows can be added by reference, symbolic name, or explicitly defined symbolic names. - * See the [OOjs ui documentation on MediaWiki] [2] for examples. - * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers - * - * @param {Object.<string,OO.ui.Window>|OO.ui.Window[]} windows An array of window objects specified - * by reference, symbolic name, or explicitly defined symbolic names. - * @throws {Error} An error is thrown if a window is added by symbolic name, but has neither an - * explicit nor a statically configured symbolic name. - */ -OO.ui.WindowManager.prototype.addWindows = function ( windows ) { - var i, len, win, name, list; - - if ( Array.isArray( windows ) ) { - // Convert to map of windows by looking up symbolic names from static configuration - list = {}; - for ( i = 0, len = windows.length; i < len; i++ ) { - name = windows[ i ].constructor.static.name; - if ( typeof name !== 'string' ) { - throw new Error( 'Cannot add window' ); - } - list[ name ] = windows[ i ]; - } - } else if ( OO.isPlainObject( windows ) ) { - list = windows; - } - - // Add windows - for ( name in list ) { - win = list[ name ]; - this.windows[ name ] = win.toggle( false ); - this.$element.append( win.$element ); - win.setManager( this ); - } -}; - -/** - * Remove the specified windows from the windows manager. - * - * Windows will be closed before they are removed. If you wish to remove all windows, you may wish to use - * the #clearWindows method instead. If you no longer need the window manager and want to ensure that it no - * longer listens to events, use the #destroy method. - * - * @param {string[]} names Symbolic names of windows to remove - * @return {jQuery.Promise} Promise resolved when window is closed and removed - * @throws {Error} An error is thrown if the named windows are not managed by the window manager. - */ -OO.ui.WindowManager.prototype.removeWindows = function ( names ) { - var i, len, win, name, cleanupWindow, - manager = this, - promises = [], - cleanup = function ( name, win ) { - delete manager.windows[ name ]; - win.$element.detach(); - }; - - for ( i = 0, len = names.length; i < len; i++ ) { - name = names[ i ]; - win = this.windows[ name ]; - if ( !win ) { - throw new Error( 'Cannot remove window' ); - } - cleanupWindow = cleanup.bind( null, name, win ); - promises.push( this.closeWindow( name ).then( cleanupWindow, cleanupWindow ) ); - } - - return $.when.apply( $, promises ); -}; - -/** - * Remove all windows from the window manager. - * - * Windows will be closed before they are removed. Note that the window manager, though not in use, will still - * listen to events. If the window manager will not be used again, you may wish to use the #destroy method instead. - * To remove just a subset of windows, use the #removeWindows method. - * - * @return {jQuery.Promise} Promise resolved when all windows are closed and removed - */ -OO.ui.WindowManager.prototype.clearWindows = function () { - return this.removeWindows( Object.keys( this.windows ) ); -}; - -/** - * Set dialog size. In general, this method should not be called directly. - * - * Fullscreen mode will be used if the dialog is too wide to fit in the screen. - * - * @chainable - */ -OO.ui.WindowManager.prototype.updateWindowSize = function ( win ) { - // Bypass for non-current, and thus invisible, windows - if ( win !== this.currentWindow ) { - return; - } - - var viewport = OO.ui.Element.static.getDimensions( win.getElementWindow() ), - sizes = this.constructor.static.sizes, - size = win.getSize(); - - if ( !sizes[ size ] ) { - size = this.constructor.static.defaultSize; - } - if ( size !== 'full' && viewport.rect.right - viewport.rect.left < sizes[ size ].width ) { - size = 'full'; - } - - this.$element.toggleClass( 'oo-ui-windowManager-fullscreen', size === 'full' ); - this.$element.toggleClass( 'oo-ui-windowManager-floating', size !== 'full' ); - win.setDimensions( sizes[ size ] ); - - this.emit( 'resize', win ); - - return this; -}; - -/** - * Bind or unbind global events for scrolling. - * - * @private - * @param {boolean} [on] Bind global events - * @chainable - */ -OO.ui.WindowManager.prototype.toggleGlobalEvents = function ( on ) { - on = on === undefined ? !!this.globalEvents : !!on; - - var scrollWidth, bodyMargin, - $body = $( this.getElementDocument().body ), - // We could have multiple window managers open so only modify - // the body css at the bottom of the stack - stackDepth = $body.data( 'windowManagerGlobalEvents' ) || 0 ; - - if ( on ) { - if ( !this.globalEvents ) { - $( this.getElementWindow() ).on( { - // Start listening for top-level window dimension changes - 'orientationchange resize': this.onWindowResizeHandler - } ); - if ( stackDepth === 0 ) { - scrollWidth = window.innerWidth - document.documentElement.clientWidth; - bodyMargin = parseFloat( $body.css( 'margin-right' ) ) || 0; - $body.css( { - overflow: 'hidden', - 'margin-right': bodyMargin + scrollWidth - } ); - } - stackDepth++; - this.globalEvents = true; - } - } else if ( this.globalEvents ) { - $( this.getElementWindow() ).off( { - // Stop listening for top-level window dimension changes - 'orientationchange resize': this.onWindowResizeHandler - } ); - stackDepth--; - if ( stackDepth === 0 ) { - $body.css( { - overflow: '', - 'margin-right': '' - } ); - } - this.globalEvents = false; - } - $body.data( 'windowManagerGlobalEvents', stackDepth ); - - return this; -}; - -/** - * Toggle screen reader visibility of content other than the window manager. - * - * @private - * @param {boolean} [isolate] Make only the window manager visible to screen readers - * @chainable - */ -OO.ui.WindowManager.prototype.toggleAriaIsolation = function ( isolate ) { - isolate = isolate === undefined ? !this.$ariaHidden : !!isolate; - - if ( isolate ) { - if ( !this.$ariaHidden ) { - // Hide everything other than the window manager from screen readers - this.$ariaHidden = $( 'body' ) - .children() - .not( this.$element.parentsUntil( 'body' ).last() ) - .attr( 'aria-hidden', '' ); - } - } else if ( this.$ariaHidden ) { - // Restore screen reader visibility - this.$ariaHidden.removeAttr( 'aria-hidden' ); - this.$ariaHidden = null; - } - - return this; -}; - -/** - * Destroy the window manager. - * - * Destroying the window manager ensures that it will no longer listen to events. If you would like to - * continue using the window manager, but wish to remove all windows from it, use the #clearWindows method - * instead. - */ -OO.ui.WindowManager.prototype.destroy = function () { - this.toggleGlobalEvents( false ); - this.toggleAriaIsolation( false ); - this.clearWindows(); - this.$element.remove(); -}; |