/*!
- * OOjs UI v0.1.0-pre (c5ae888f67)
+ * 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: Wed Jun 11 2014 18:10:09 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.
*
// 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.opened.resolve();
}
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.
*
} );
this.$element.append( win.$element );
};
+
/**
* Modal dialog window.
*
this.$element.on( 'mousedown', false );
// Initialization
- this.$element.addClass( 'oo-ui-dialog' );
+ this.$element.addClass( 'oo-ui-dialog' ).attr( 'role', 'dialog' );
this.setSize( config.size );
};
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.okButton.$element,
this.cancelButton.$element
);
-
- this.connect( this, { 'teardown': [ 'close', 'cancel' ] } );
};
/*
.first( function () {
if ( data === 'ok' ) {
this.opened.resolve();
- } else if ( data === 'cancel' ) {
+ } 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.
*
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.
*
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.
*
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.
*
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.
*
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.
*
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.
*
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