/*!
- * OOjs UI v0.1.0-pre (6379e76bf5)
+ * OOjs UI v0.1.0-pre (b9d403a678)
* https://www.mediawiki.org/wiki/OOjs_UI
*
* Copyright 2011–2014 OOjs Team and other contributors.
* Released under the MIT license
* http://oojs.mit-license.org
*
- * Date: Mon Jun 02 2014 17:52:03 GMT-0700 (PDT)
+ * Date: 2014-06-26T23:45:59Z
*/
( function ( OO ) {
'use strict';
+
/**
* Namespace for all classes, static methods and static properties.
*
( function () {
-/**
- * Message store for the default implementation of OO.ui.msg
- *
- * Environments that provide a localization system should not use this, but should override
- * OO.ui.msg altogether.
- *
- * @private
- */
-var messages = {
- // Label text for button to exit from dialog
- 'ooui-dialog-action-close': 'Close',
- // Tool tip for a button that moves items in a list down one place
- 'ooui-outline-control-move-down': 'Move item down',
- // Tool tip for a button that moves items in a list up one place
- 'ooui-outline-control-move-up': 'Move item up',
- // Tool tip for a button that removes items from a list
- 'ooui-outline-control-remove': 'Remove item',
- // Label for the toolbar group that contains a list of all other available tools
- 'ooui-toolbar-more': 'More',
-
- // Label for the generic dialog used to confirm things
- 'ooui-dialog-confirm-title': 'Confirm',
- // The default prompt of a confirmation dialog
- 'ooui-dialog-confirm-default-prompt': 'Are you sure?',
- // The default OK button text on a confirmation dialog
- 'ooui-dialog-confirm-default-ok': 'OK',
- // The default cancel button text on a confirmation dialog
- 'ooui-dialog-confirm-default-cancel': 'Cancel'
-};
+ /**
+ * Message store for the default implementation of OO.ui.msg
+ *
+ * Environments that provide a localization system should not use this, but should override
+ * OO.ui.msg altogether.
+ *
+ * @private
+ */
+ var messages = {
+ // Label text for button to exit from dialog
+ 'ooui-dialog-action-close': 'Close',
+ // Tool tip for a button that moves items in a list down one place
+ 'ooui-outline-control-move-down': 'Move item down',
+ // Tool tip for a button that moves items in a list up one place
+ 'ooui-outline-control-move-up': 'Move item up',
+ // Tool tip for a button that removes items from a list
+ 'ooui-outline-control-remove': 'Remove item',
+ // Label for the toolbar group that contains a list of all other available tools
+ 'ooui-toolbar-more': 'More',
+
+ // Label for the generic dialog used to confirm things
+ 'ooui-dialog-confirm-title': 'Confirm',
+ // The default prompt of a confirmation dialog
+ 'ooui-dialog-confirm-default-prompt': 'Are you sure?',
+ // The default OK button text on a confirmation dialog
+ 'ooui-dialog-confirm-default-ok': 'OK',
+ // The default cancel button text on a confirmation dialog
+ 'ooui-dialog-confirm-default-cancel': 'Cancel'
+ };
-/**
- * Get a localized message.
- *
- * In environments that provide a localization system, this function should be overridden to
- * return the message translated in the user's language. The default implementation always returns
- * English messages.
- *
- * After the message key, message parameters may optionally be passed. In the default implementation,
- * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.
- * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as
- * they support unnamed, ordered message parameters.
- *
- * @abstract
- * @param {string} key Message key
- * @param {Mixed...} [params] Message parameters
- * @return {string} Translated message with parameters substituted
- */
-OO.ui.msg = function ( key ) {
- var message = messages[key], params = Array.prototype.slice.call( arguments, 1 );
- if ( typeof message === 'string' ) {
- // Perform $1 substitution
- message = message.replace( /\$(\d+)/g, function ( unused, n ) {
- var i = parseInt( n, 10 );
- return params[i - 1] !== undefined ? params[i - 1] : '$' + n;
- } );
- } else {
- // Return placeholder if message not found
- message = '[' + key + ']';
- }
- return message;
-};
+ /**
+ * Get a localized message.
+ *
+ * In environments that provide a localization system, this function should be overridden to
+ * return the message translated in the user's language. The default implementation always returns
+ * English messages.
+ *
+ * After the message key, message parameters may optionally be passed. In the default implementation,
+ * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.
+ * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as
+ * they support unnamed, ordered message parameters.
+ *
+ * @abstract
+ * @param {string} key Message key
+ * @param {Mixed...} [params] Message parameters
+ * @return {string} Translated message with parameters substituted
+ */
+ OO.ui.msg = function ( key ) {
+ var message = messages[key], params = Array.prototype.slice.call( arguments, 1 );
+ if ( typeof message === 'string' ) {
+ // Perform $1 substitution
+ message = message.replace( /\$(\d+)/g, function ( unused, n ) {
+ var i = parseInt( n, 10 );
+ return params[i - 1] !== undefined ? params[i - 1] : '$' + n;
+ } );
+ } else {
+ // Return placeholder if message not found
+ message = '[' + key + ']';
+ }
+ return message;
+ };
-/** */
-OO.ui.deferMsg = function ( key ) {
- return function () {
- return OO.ui.msg( key );
+ /** */
+ OO.ui.deferMsg = function ( key ) {
+ return function () {
+ return OO.ui.msg( key );
+ };
};
-};
-/** */
-OO.ui.resolveMsg = function ( msg ) {
- if ( $.isFunction( msg ) ) {
- return msg();
- }
- return msg;
-};
+ /** */
+ OO.ui.resolveMsg = function ( msg ) {
+ if ( $.isFunction( msg ) ) {
+ return msg();
+ }
+ return msg;
+ };
} )();
+
/**
* DOM element abstraction.
*
// Configuration initialization
config = config || {};
- var anim = {},
+ var rel, anim = {},
callback = typeof config.complete === 'function' && config.complete,
sc = this.getClosestScrollableContainer( el, config.direction ),
$sc = $( sc ),
eld = this.getDimensions( el ),
scd = this.getDimensions( sc ),
+ $win = $( this.getWindow( el ) );
+
+ // Compute the distances between the edges of el and the edges of the scroll viewport
+ if ( $sc.is( 'body' ) ) {
+ // If the scrollable container is the <body> this is easy
+ rel = {
+ 'top': eld.rect.top,
+ 'bottom': $win.innerHeight() - eld.rect.bottom,
+ 'left': eld.rect.left,
+ 'right': $win.innerWidth() - eld.rect.right
+ };
+ } else {
+ // Otherwise, we have to subtract el's coordinates from sc's coordinates
rel = {
'top': eld.rect.top - ( scd.rect.top + scd.borders.top ),
'bottom': scd.rect.bottom - scd.borders.bottom - scd.scrollbar.bottom - eld.rect.bottom,
'left': eld.rect.left - ( scd.rect.left + scd.borders.left ),
'right': scd.rect.right - scd.borders.right - scd.scrollbar.right - eld.rect.right
};
+ }
if ( !config.direction || config.direction === 'y' ) {
if ( rel.top < 0 ) {
/**
* Bind a handler for an event on this.$element
*
+ * @deprecated Use jQuery#on instead.
* @param {string} event
* @param {Function} callback
*/
/**
* Unbind a handler bound with #offDOMEvent
*
+ * @deprecated Use jQuery#off instead.
* @param {string} event
* @param {Function} callback
*/
};
( function () {
- // Static
-
- // jQuery 1.8.3 has a bug with handling focusin/focusout events inside iframes.
- // Firefox doesn't support focusin/focusout at all, so we listen for 'focus'/'blur' on the
- // document, and simulate a 'focusin'/'focusout' event on the target element and make
- // it bubble from there.
- //
- // - http://jsfiddle.net/sw3hr/
- // - http://bugs.jquery.com/ticket/14180
- // - https://github.com/jquery/jquery/commit/1cecf64e5aa4153
- function specialEvent( simulatedName, realName ) {
- function handler( e ) {
- jQuery.event.simulate(
- simulatedName,
- e.target,
- jQuery.event.fix( e ),
- /* bubble = */ true
- );
- }
-
- return {
- setup: function () {
- var doc = this.ownerDocument || this,
- attaches = $.data( doc, 'ooui-' + simulatedName + '-attaches' );
- if ( !attaches ) {
- doc.addEventListener( realName, handler, true );
- }
- $.data( doc, 'ooui-' + simulatedName + '-attaches', ( attaches || 0 ) + 1 );
- },
- teardown: function () {
- var doc = this.ownerDocument || this,
- attaches = $.data( doc, 'ooui-' + simulatedName + '-attaches' ) - 1;
- if ( !attaches ) {
- doc.removeEventListener( realName, handler, true );
- $.removeData( doc, 'ooui-' + simulatedName + '-attaches' );
- } else {
- $.data( doc, 'ooui-' + simulatedName + '-attaches', attaches );
- }
- }
- };
- }
-
- var hasOwn = Object.prototype.hasOwnProperty,
- specialEvents = {
- focusin: specialEvent( 'focusin', 'focus' ),
- focusout: specialEvent( 'focusout', 'blur' )
- };
-
/**
* Bind a handler for an event on a DOM element.
*
- * Uses jQuery internally for everything except for events which are
- * known to have issues in the browser or in jQuery. This method
- * should become obsolete eventually.
+ * Used to be for working around a jQuery bug (jqbug.com/14180),
+ * but obsolete as of jQuery 1.11.0.
*
* @static
+ * @deprecated Use jQuery#on instead.
* @param {HTMLElement|jQuery} el DOM element
* @param {string} event Event to bind
* @param {Function} callback Callback to call when the event fires
*/
OO.ui.Element.onDOMEvent = function ( el, event, callback ) {
- var orig;
-
- if ( hasOwn.call( specialEvents, event ) ) {
- // Replace jQuery's override with our own
- orig = $.event.special[event];
- $.event.special[event] = specialEvents[event];
-
- $( el ).on( event, callback );
-
- // Restore
- $.event.special[event] = orig;
- } else {
- $( el ).on( event, callback );
- }
+ $( el ).on( event, callback );
};
/**
* Unbind a handler bound with #static-method-onDOMEvent.
*
+ * @deprecated Use jQuery#off instead.
* @static
* @param {HTMLElement|jQuery} el DOM element
* @param {string} event Event to unbind
* @param {Function} [callback] Callback to unbind
*/
OO.ui.Element.offDOMEvent = function ( el, event, callback ) {
- var orig;
- if ( hasOwn.call( specialEvents, event ) ) {
- // Replace jQuery's override with our own
- orig = $.event.special[event];
- $.event.special[event] = specialEvents[event];
-
- $( el ).off( event, callback );
-
- // Restore
- $.event.special[event] = orig;
- } else {
- $( el ).off( event, callback );
- }
+ $( el ).off( event, callback );
};
}() );
+
/**
* Embedded iframe with the same styles as its parent.
*
this.$element.css( { 'width': width, 'height': height } );
return this;
};
+
/**
* Container for elements in a child frame.
*
/* Events */
/**
- * Open window.
+ * Window is setup.
*
- * Fired after window has been opened.
+ * Fired after the setup process has been executed.
*
- * @event open
+ * @event setup
* @param {Object} data Window opening data
*/
/**
- * Close window.
+ * Window is ready.
*
- * Fired after window has been closed.
+ * Fired after the ready process has been executed.
*
- * @event close
+ * @event ready
+ * @param {Object} data Window opening data
+ */
+
+/**
+ * Window is torn down
+ *
+ * Fired after the teardown process has been executed.
+ *
+ * @event teardown
* @param {Object} data Window closing data
*/
* @return {boolean} Window is opening
*/
OO.ui.Window.prototype.isOpening = function () {
- return !!this.opening && this.opening.state() !== 'resolved';
+ return !!this.opening && this.opening.state() === 'pending';
};
/**
* @return {boolean} Window is closing
*/
OO.ui.Window.prototype.isClosing = function () {
- return !!this.closing && this.closing.state() !== 'resolved';
+ return !!this.closing && this.closing.state() === 'pending';
};
/**
* @return {boolean} Window is opened
*/
OO.ui.Window.prototype.isOpened = function () {
- return !!this.opened && this.opened.state() !== 'resolved';
+ return !!this.opened && this.opened.state() === 'pending';
};
/**
/**
* Open window.
*
- * Do not override this method. Use #geSetupProcess to do something each time the window closes.
+ * Do not override this method. Use #getSetupProcess to do something each time the window closes.
*
* @param {Object} [data] Window opening data
* @fires initialize
// Open the window
this.opening = $.Deferred();
+
+ this.$ariaHidden = $( 'body' ).children().not( this.$element.parentsUntil( 'body' ).last() )
+ .attr( 'aria-hidden', '' );
+
this.frame.load().done( OO.ui.bind( function () {
this.$element.show();
this.visible = true;
- this.emit( 'opening', data );
this.getSetupProcess( data ).execute().done( OO.ui.bind( function () {
- this.emit( 'open', data );
+ this.$element.addClass( 'oo-ui-window-setup' );
+ this.emit( 'setup', data );
setTimeout( OO.ui.bind( function () {
- // Focus the content div (which has a tabIndex) to inactivate
- // (but not clear) selections in the parent frame.
- // Must happen after 'open' is emitted (to ensure it is visible)
- // but before 'ready' is emitted (so subclasses can give focus to something
- // else)
this.frame.$content.focus();
this.getReadyProcess( data ).execute().done( OO.ui.bind( function () {
+ this.$element.addClass( 'oo-ui-window-ready' );
this.emit( 'ready', data );
this.opened = $.Deferred();
- this.opening.resolve( this.opened.promise() );
// Now that we are totally done opening, it's safe to allow closing
this.closing = null;
+ this.opening.resolve( this.opened.promise() );
}, this ) );
}, this ) );
}, this ) );
* @return {jQuery.Promise} Promise resolved when window is closed
*/
OO.ui.Window.prototype.close = function ( data ) {
+ var close;
+
// Return existing promise if already closing or closed
if ( this.closing ) {
return this.closing.promise();
}
+ // Close after opening is done if opening is in progress
+ if ( this.opening && this.opening.state() === 'pending' ) {
+ close = OO.ui.bind( function () {
+ return this.close( data );
+ }, this );
+ return this.opening.then( close, close );
+ }
+
// Close the window
// This.closing needs to exist before we emit the closing event so that handlers can call
// window.close() and trigger the safety check above
this.closing = $.Deferred();
this.frame.$content.find( ':focus' ).blur();
- this.emit( 'closing', data );
+ this.$element.removeClass( 'oo-ui-window-ready' );
this.getTeardownProcess( data ).execute().done( OO.ui.bind( function () {
+ this.$element.removeClass( 'oo-ui-window-setup' );
+ this.emit( 'teardown', data );
// To do something different with #opened, resolve/reject #opened in the teardown process
- if ( this.opened.state() === 'pending' ) {
+ if ( this.opened && this.opened.state() === 'pending' ) {
this.opened.resolve();
}
- this.emit( 'close', data );
this.$element.hide();
+ if ( this.$ariaHidden ) {
+ this.$ariaHidden.removeAttr( 'aria-hidden' );
+ this.$ariaHidden = undefined;
+ }
this.visible = false;
this.closing.resolve();
// Now that we are totally done closing, it's safe to allow opening
return this.closing.promise();
};
+
/**
* Set of mutually exclusive windows.
*
/* Events */
/**
- * @event opening
- * @param {OO.ui.Window} win Window that's being opened
+ * @event setup
+ * @param {OO.ui.Window} win Window that's been setup
* @param {Object} config Window opening information
*/
/**
- * @event open
- * @param {OO.ui.Window} win Window that's been opened
+ * @event ready
+ * @param {OO.ui.Window} win Window that's ready
* @param {Object} config Window opening information
*/
/**
- * @event closing
- * @param {OO.ui.Window} win Window that's being closed
- * @param {Object} config Window closing information
- */
-
-/**
- * @event close
- * @param {OO.ui.Window} win Window that's been closed
+ * @event teardown
+ * @param {OO.ui.Window} win Window that's been torn down
* @param {Object} config Window closing information
*/
/* Methods */
/**
- * Handle a window that's being opened.
+ * Handle a window setup event.
*
- * @param {OO.ui.Window} win Window that's being opened
+ * @param {OO.ui.Window} win Window that's been setup
* @param {Object} [config] Window opening information
- * @fires opening
+ * @fires setup
*/
-OO.ui.WindowSet.prototype.onWindowOpening = function ( win, config ) {
+OO.ui.WindowSet.prototype.onWindowSetup = function ( win, config ) {
if ( this.currentWindow && this.currentWindow !== win ) {
this.currentWindow.close();
}
this.currentWindow = win;
- this.emit( 'opening', win, config );
+ this.emit( 'setup', win, config );
};
/**
- * Handle a window that's been opened.
+ * Handle a window ready event.
*
- * @param {OO.ui.Window} win Window that's been opened
+ * @param {OO.ui.Window} win Window that's ready
* @param {Object} [config] Window opening information
- * @fires open
+ * @fires ready
*/
-OO.ui.WindowSet.prototype.onWindowOpen = function ( win, config ) {
- this.emit( 'open', win, config );
+OO.ui.WindowSet.prototype.onWindowReady = function ( win, config ) {
+ this.emit( 'ready', win, config );
};
/**
- * Handle a window that's being closed.
+ * Handle a window teardown event.
*
- * @param {OO.ui.Window} win Window that's being closed
+ * @param {OO.ui.Window} win Window that's been torn down
* @param {Object} [config] Window closing information
- * @fires closing
+ * @fires teardown
*/
-OO.ui.WindowSet.prototype.onWindowClosing = function ( win, config ) {
+OO.ui.WindowSet.prototype.onWindowTeardown = function ( win, config ) {
this.currentWindow = null;
- this.emit( 'closing', win, config );
-};
-
-/**
- * Handle a window that's been closed.
- *
- * @param {OO.ui.Window} win Window that's been closed
- * @param {Object} [config] Window closing information
- * @fires close
- */
-OO.ui.WindowSet.prototype.onWindowClose = function ( win, config ) {
- this.emit( 'close', win, config );
+ this.emit( 'teardown', win, config );
};
/**
* Connects event handlers and attaches it to the DOM. Calling
* OO.ui.Window#open will not work until the window is added to the set.
*
- * @param {OO.ui.Window} win
+ * @param {OO.ui.Window} win Window to add
*/
OO.ui.WindowSet.prototype.addWindow = function ( win ) {
if ( this.windowList.indexOf( win ) !== -1 ) {
this.windowList.push( win );
win.connect( this, {
- 'opening': [ 'onWindowOpening', win ],
- 'open': [ 'onWindowOpen', win ],
- 'closing': [ 'onWindowClosing', win ],
- 'close': [ 'onWindowClose', win ]
+ 'setup': [ 'onWindowSetup', win ],
+ 'ready': [ 'onWindowReady', win ],
+ 'teardown': [ 'onWindowTeardown', win ]
} );
this.$element.append( win.$element );
};
+
/**
* Modal dialog window.
*
// Events
this.$element.on( 'mousedown', false );
- this.connect( this, { 'open': 'onOpen' } );
// Initialization
- this.$element.addClass( 'oo-ui-dialog' );
+ this.$element.addClass( 'oo-ui-dialog' ).attr( 'role', 'dialog' );
this.setSize( config.size );
};
}
};
-/**
- * Handle window open events.
- */
-OO.ui.Dialog.prototype.onOpen = function () {
- this.$element.addClass( 'oo-ui-dialog-open' );
-};
-
/**
* Set dialog size.
*
state = name === size;
cssClass = sizeCssClasses[name];
this.$element.toggleClass( cssClass, state );
- if ( this.frame.$content ) {
- this.frame.$content.toggleClass( cssClass, state );
- }
}
};
OO.ui.Dialog.prototype.getTeardownProcess = function ( data ) {
return OO.ui.Dialog.super.prototype.getTeardownProcess.call( this, data )
.first( function () {
- this.$element.removeClass( 'oo-ui-dialog-open' );
+ // Wait for closing transition
return OO.ui.Process.static.delay( 250 );
}, this )
.next( function () {
return this;
};
+
/**
* Container for elements.
*
OO.inheritClass( OO.ui.Layout, OO.ui.Element );
OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
+
/**
* User interface control.
*
this.wasDisabled = isDisabled;
return this;
};
+
/**
* A list of functions, called in sequence.
*
this.steps.push( [ step, context || null ] );
return this;
};
+
/**
* Dialog for showing a confirmation/warning message.
*
this.$promptContainer = this.$( '<div>' ).addClass( 'oo-ui-dialog-confirm-promptContainer' );
this.cancelButton = new OO.ui.ButtonWidget();
- this.cancelButton.connect( this, { 'click': [ 'emit', 'done', 'cancel' ] } );
+ this.cancelButton.connect( this, { 'click': [ 'close', 'cancel' ] } );
this.okButton = new OO.ui.ButtonWidget();
- this.okButton.connect( this, { 'click': [ 'emit', 'done', 'ok' ] } );
+ this.okButton.connect( this, { 'click': [ 'close', 'ok' ] } );
// Make the buttons
contentLayout.$element.append( this.$promptContainer );
this.okButton.$element,
this.cancelButton.$element
);
-
- this.connect( this, {
- 'done': 'close',
- 'close': [ 'emit', 'cancel' ]
- } );
};
/*
- * Open a confirmation dialog.
+ * Setup a confirmation dialog.
*
* @param {Object} [data] Window opening data including text of the dialog and text for the buttons
* @param {jQuery|string} [data.prompt] Text to display or list of nodes to use as content of the dialog.
* @param {jQuery|string|Function|null} [data.cancelLabel] Label of the cancel button
* @param {string|string[]} [data.okFlags="constructive"] Flags for the OK button
* @param {string|string[]} [data.cancelFlags="destructive"] Flags for the cancel button
+ * @return {OO.ui.Process} Setup process
*/
-OO.ui.ConfirmationDialog.prototype.setup = function ( data ) {
+OO.ui.ConfirmationDialog.prototype.getSetupProcess = function ( data ) {
// Parent method
- OO.ui.Dialog.prototype.setup.call( this, data );
-
- var prompt = data.prompt || OO.ui.deferMsg( 'ooui-dialog-confirm-default-prompt' ),
- okLabel = data.okLabel || OO.ui.deferMsg( 'ooui-dialog-confirm-default-ok' ),
- cancelLabel = data.cancelLabel || OO.ui.deferMsg( 'ooui-dialog-confirm-default-cancel' ),
- okFlags = data.okFlags || 'constructive',
- cancelFlags = data.cancelFlags || 'destructive';
+ return OO.ui.ConfirmationDialog.super.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ var prompt = data.prompt || OO.ui.deferMsg( 'ooui-dialog-confirm-default-prompt' ),
+ okLabel = data.okLabel || OO.ui.deferMsg( 'ooui-dialog-confirm-default-ok' ),
+ cancelLabel = data.cancelLabel || OO.ui.deferMsg( 'ooui-dialog-confirm-default-cancel' ),
+ okFlags = data.okFlags || 'constructive',
+ cancelFlags = data.cancelFlags || 'destructive';
+
+ if ( typeof prompt === 'string' ) {
+ this.$promptContainer.text( prompt );
+ } else {
+ this.$promptContainer.empty().append( prompt );
+ }
- if ( typeof prompt === 'string' ) {
- this.$promptContainer.text( prompt );
- } else {
- this.$promptContainer.empty().append( prompt );
- }
+ this.okButton.setLabel( okLabel ).clearFlags().setFlags( okFlags );
+ this.cancelButton.setLabel( cancelLabel ).clearFlags().setFlags( cancelFlags );
+ }, this );
+};
- this.okButton.setLabel( okLabel ).clearFlags().setFlags( okFlags );
- this.cancelButton.setLabel( cancelLabel ).clearFlags().setFlags( cancelFlags );
+/**
+ * @inheritdoc
+ */
+OO.ui.ConfirmationDialog.prototype.getTeardownProcess = function ( data ) {
+ // Parent method
+ return OO.ui.ConfirmationDialog.super.prototype.getTeardownProcess.call( this, data )
+ .first( function () {
+ if ( data === 'ok' ) {
+ this.opened.resolve();
+ } else { // data === 'cancel', or no data
+ this.opened.reject();
+ }
+ }, this );
};
+
/**
* Element with a button.
*
this.$button.toggleClass( 'oo-ui-buttonedElement-active', !!value );
return this;
};
+
/**
* Element that can be automatically clipped to visible boundaies.
*
if ( clipWidth ) {
this.$clippable.css( { 'overflow-x': 'auto', 'width': desiredWidth } );
} else {
- this.$clippable.css( { 'overflow-x': '', 'width': this.idealWidth || '' } );
+ this.$clippable.css( 'width', this.idealWidth || '' );
+ this.$clippable.width(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
+ this.$clippable.css( 'overflow-x', '' );
}
if ( clipHeight ) {
this.$clippable.css( { 'overflow-y': 'auto', 'height': desiredHeight } );
} else {
- this.$clippable.css( { 'overflow-y': '', 'height': this.idealHeight || '' } );
+ this.$clippable.css( 'height', this.idealHeight || '' );
+ this.$clippable.height(); // Force reflow for https://code.google.com/p/chromium/issues/detail?id=387290
+ this.$clippable.css( 'overflow-y', '' );
}
this.clipped = clipWidth || clipHeight;
return this;
};
+
/**
* Element with named flags that can be added, removed, listed and checked.
*
}
return this;
};
+
/**
* Element containing a sequence of child elements.
*
// Properties
this.$group = $group;
this.items = [];
- this.$items = this.$( [] );
this.aggregateItemEvents = {};
};
*/
OO.ui.GroupElement.prototype.addItems = function ( items, index ) {
var i, len, item, event, events, currentIndex,
- $items = this.$( [] );
+ itemElements = [];
for ( i = 0, len = items.length; i < len; i++ ) {
item = items[i];
item.connect( this, events );
}
item.setElementGroup( this );
- $items = $items.add( item.$element );
+ itemElements.push( item.$element.get( 0 ) );
}
if ( index === undefined || index < 0 || index >= this.items.length ) {
- this.$group.append( $items );
+ this.$group.append( itemElements );
this.items.push.apply( this.items, items );
} else if ( index === 0 ) {
- this.$group.prepend( $items );
+ this.$group.prepend( itemElements );
this.items.unshift.apply( this.items, items );
} else {
- this.$items.eq( index ).before( $items );
+ this.items[index].$element.before( itemElements );
this.items.splice.apply( this.items, [ index, 0 ].concat( items ) );
}
- this.$items = this.$items.add( $items );
-
return this;
};
item.setElementGroup( null );
this.items.splice( index, 1 );
item.$element.detach();
- this.$items = this.$items.not( item.$element );
}
}
item.disconnect( this, remove );
}
item.setElementGroup( null );
+ item.$element.detach();
}
- this.items = [];
- this.$items.detach();
- this.$items = this.$( [] );
+ this.items = [];
return this;
};
+
/**
* Element containing an icon.
*
OO.ui.IconedElement.prototype.getIcon = function () {
return this.icon;
};
+
/**
* Element containing an indicator.
*
OO.ui.IndicatedElement.prototype.getIndicatorTitle = function () {
return this.indicatorTitle;
};
+
/**
* Element containing a label.
*
}
return this;
};
+
/**
* Popuppable element.
*
OO.ui.PopuppableElement.prototype.hidePopup = function () {
this.popup.hide();
};
+
/**
* Element with a title.
*
OO.ui.TitledElement.prototype.getTitle = function () {
return this.title;
};
+
/**
* Generic toolbar tool.
*
this.toolbar.disconnect( this );
this.$element.remove();
};
+
/**
* Collection of tool groups.
*
OO.ui.Toolbar.prototype.getToolAccelerator = function () {
return undefined;
};
+
/**
* Factory for tools.
*
}
return names;
};
+
/**
* Collection of tools.
*
}
this.$element.remove();
};
+
/**
* Factory for tool groups.
*
OO.ui.MenuToolGroup
];
};
+
/**
* Layout made of a fieldset and optional legend.
*
/* Static Properties */
OO.ui.FieldsetLayout.static.tagName = 'div';
+
/**
* Layout made of a field and optional label.
*
return this;
};
+
/**
* Layout made of proportionally sized columns and rows.
*
OO.ui.GridLayout.prototype.getPanel = function ( x, y ) {
return this.panels[( x * this.widths.length ) + y];
};
+
/**
* Layout containing a series of pages.
*
* @cfg {boolean} [autoFocus=true] Focus on the first focusable element when changing to a page
* @cfg {boolean} [outlined=false] Show an outline
* @cfg {boolean} [editable=false] Show controls for adding, removing and reordering pages
- * @cfg {Object[]} [adders] List of adders for controls, each with name, icon and title properties
*/
OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
// Initialize configuration
this.outlined = !!config.outlined;
if ( this.outlined ) {
this.editable = !!config.editable;
- this.adders = config.adders || null;
this.outlineControlsWidget = null;
this.outlineWidget = new OO.ui.OutlineWidget( { '$': this.$ } );
this.outlinePanel = new OO.ui.PanelLayout( { '$': this.$, 'scrollable': true } );
this.outlineVisible = true;
if ( this.editable ) {
this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
- this.outlineWidget,
- { '$': this.$, 'adders': this.adders }
+ this.outlineWidget, { '$': this.$ }
);
}
}
return this;
};
+
/**
* Layout that expands to cover the entire area of its parent, with optional scrolling and padding.
*
/* Setup */
OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
+
/**
* Page within an booklet layout.
*
this.emit( 'active', this.active );
}
};
+
/**
* Layout containing a series of mutually exclusive pages.
*
* @fires set
*/
OO.ui.StackLayout.prototype.setItem = function ( item ) {
+ var i, len;
+
if ( item !== this.currentItem ) {
if ( !this.continuous ) {
- this.$items.css( 'display', '' );
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.items[i].$element.css( 'display', '' );
+ }
}
if ( $.inArray( item, this.items ) !== -1 ) {
if ( !this.continuous ) {
return this;
};
+
/**
* Horizontal bar layout of tools as icon buttons.
*
OO.ui.BarToolGroup.static.accelTooltips = true;
OO.ui.BarToolGroup.static.name = 'bar';
+
/**
* Popup list of tools with an icon and optional label.
*
}
}
};
+
/**
* Drop down list layout of tools as labeled icon buttons.
*
OO.ui.ListToolGroup.static.accelTooltips = true;
OO.ui.ListToolGroup.static.name = 'list';
+
/**
* Drop down menu layout of tools as selectable menu items.
*
this.setLabel( labelTexts.join( ', ' ) || ' ' );
};
+
/**
* Tool that shows a popup when selected.
*
OO.ui.PopupTool.prototype.onUpdateState = function () {
this.setActive( false );
};
+
/**
* Group widget.
*
return this;
};
+
/**
* Item widget.
*
return this;
};
+
/**
* Icon widget.
*
/* Static Properties */
OO.ui.IconWidget.static.tagName = 'span';
+
/**
* Indicator widget.
*
/* Static Properties */
OO.ui.IndicatorWidget.static.tagName = 'span';
+
/**
* Container for multiple related buttons.
*
OO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );
OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.GroupElement );
+
/**
* Button widget.
*
}
return false;
};
+
/**
* Input widget.
*
this.$input.focus();
return this;
};
+
/**
* Checkbox widget.
*
}, this ) );
}
};
+
/**
* Label widget.
*
this.input.simulateLabelClick();
return false;
};
+
/**
* Lookup input widget.
*
// Stub, implemented in subclass
return [];
};
+
/**
* Option widget.
*
* @chainable
*/
OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
- if ( !this.isDisabled() && this.constructor.static.selectable ) {
+ if ( this.constructor.static.selectable ) {
this.selected = !!state;
if ( this.selected ) {
this.$element.addClass( 'oo-ui-optionWidget-selected' );
* @chainable
*/
OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
- if ( !this.isDisabled() && this.constructor.static.highlightable ) {
+ if ( this.constructor.static.highlightable ) {
this.highlighted = !!state;
if ( this.highlighted ) {
this.$element.addClass( 'oo-ui-optionWidget-highlighted' );
* @chainable
*/
OO.ui.OptionWidget.prototype.setPressed = function ( state ) {
- if ( !this.isDisabled() && this.constructor.static.pressable ) {
+ if ( this.constructor.static.pressable ) {
this.pressed = !!state;
if ( this.pressed ) {
this.$element.addClass( 'oo-ui-optionWidget-pressed' );
OO.ui.OptionWidget.prototype.getData = function () {
return this.data;
};
+
/**
* Selection of options.
*
return this;
};
+
/**
* Menu item widget.
*
/* Setup */
OO.inheritClass( OO.ui.MenuItemWidget, OO.ui.OptionWidget );
+
/**
* Menu widget.
*
return this;
};
+
/**
* Inline menu of options.
*
}
return false;
};
+
/**
* Menu section item widget.
*
OO.ui.MenuSectionItemWidget.static.selectable = false;
OO.ui.MenuSectionItemWidget.static.highlightable = false;
+
/**
* Create an OO.ui.OutlineWidget object.
*
/* Setup */
OO.inheritClass( OO.ui.OutlineWidget, OO.ui.SelectWidget );
+
/**
* Creates an OO.ui.OutlineControlsWidget object.
*
// Initialization
this.$element.addClass( 'oo-ui-outlineControlsWidget' );
- this.$group.addClass( 'oo-ui-outlineControlsWidget-adders' );
+ this.$group.addClass( 'oo-ui-outlineControlsWidget-items' );
this.$movers
.addClass( 'oo-ui-outlineControlsWidget-movers' )
.append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );
this.downButton.setDisabled( !movable || selectedItem === lastMovable );
this.removeButton.setDisabled( !removable );
};
+
/**
* Creates an OO.ui.OutlineItemWidget object.
*
return this;
};
+
/**
* Option widget that looks like a button.
*
OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
OO.ui.ButtonOptionWidget.super.prototype.setSelected.call( this, state );
- this.setActive( state );
+ if ( this.constructor.static.selectable ) {
+ this.setActive( state );
+ }
return this;
};
+
/**
* Select widget containing button options.
*
/* Setup */
OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
+
/**
* Container for content that is overlaid and positioned absolutely.
*
return this;
};
+
/**
* Button that shows and hides a popup.
*
}
return false;
};
+
/**
* Search widget.
*
OO.ui.SearchWidget.prototype.getResults = function () {
return this.results;
};
+
/**
* Text input widget.
*
this.$input.select();
return this;
};
+
/**
* Menu for a text input widget.
*
// Fix for RTL (for some reason, no need to fix if the frameoffset is set)
if ( this.$element.css( 'direction' ) === 'rtl' ) {
dimensions.right = this.$element.parent().position().left -
- dimensions.width - dimensions.left;
+ $container.width() - dimensions.left;
// Erase the value for 'left':
delete dimensions.left;
}
this.setIdealSize( $container.width() );
return this;
};
+
/**
* Width with on and off states.
*
}
return this;
};
+
/**
* Button that toggles on and off.
*
return this;
};
+
/**
* Switch that slides on and off.
*
this.setValue( !this.value );
}
};
+
}( OO ) );
+
+//# sourceMappingURL=oojs-ui.js.map
\ No newline at end of file