jenkins-bot has submitted this change and it was merged. Change subject: FieldLayout, styling improvements and standardization ......................................................................
FieldLayout, styling improvements and standardization FieldLayout - Added FieldLayout which provides label and layout features to a widget - Made Fieldset support adding FieldLayout items - Removed CheckboxWidget (not needed now, just place a checkbox in a FieldLayout and set 'align' to 'inline' - Updated demo to use FieldLayout - Moved input cleverness of InputLabelWidget to FieldLayout, and renamed it to LabelWidget Styling improvements - Made ButtonGroup and ButtonSelect widgets never wrap - Made Fieldsets use IconedElement mixin instead of rolling its own icon support Standardization - Added support for passing 'items' config option to most widgets that mixin GroupElement (not all should have this, so it's not done at the top level) - Updated all uses of mixins to include final config argument allowing config options to be added to mixin classes without updating all callers - Added config option to clippable element for future use - Renamed 'options' to 'config' in Toolbar Change-Id: I87e1bdf5ccb67ce58022926c4faede0c70a1f4a4 --- M build/modules.json M demos/widgets.js M src/OO.ui.Element.js M src/OO.ui.ToolFactory.js M src/OO.ui.ToolGroup.js M src/OO.ui.Toolbar.js M src/elements/OO.ui.ClippableElement.js M src/elements/OO.ui.FlaggableElement.js M src/elements/OO.ui.GroupElement.js A src/layouts/OO.ui.FieldLayout.js M src/layouts/OO.ui.FieldsetLayout.js M src/layouts/OO.ui.StackLayout.js M src/styles/OO.ui.Layout.css M src/styles/OO.ui.Widget.css M src/toolgroups/OO.ui.PopupToolGroup.js M src/widgets/OO.ui.ButtonGroupWidget.js D src/widgets/OO.ui.CheckboxWidget.js D src/widgets/OO.ui.InputLabelWidget.js M src/widgets/OO.ui.InputWidget.js A src/widgets/OO.ui.LabelWidget.js M src/widgets/OO.ui.MenuWidget.js M src/widgets/OO.ui.SelectWidget.js 22 files changed, 492 insertions(+), 334 deletions(-) Approvals: Catrope: Looks good to me, approved jenkins-bot: Verified diff --git a/build/modules.json b/build/modules.json index 0cae465..d77e9ef 100644 --- a/build/modules.json +++ b/build/modules.json @@ -24,6 +24,7 @@ "src/OO.ui.ToolFactory.js", "src/OO.ui.ToolGroup.js", "src/layouts/OO.ui.FieldsetLayout.js", + "src/layouts/OO.ui.FieldLayout.js", "src/layouts/OO.ui.GridLayout.js", "src/layouts/OO.ui.BookletLayout.js", "src/layouts/OO.ui.PanelLayout.js", @@ -40,8 +41,7 @@ "src/widgets/OO.ui.ButtonWidget.js", "src/widgets/OO.ui.InputWidget.js", "src/widgets/OO.ui.CheckboxInputWidget.js", - "src/widgets/OO.ui.CheckboxWidget.js", - "src/widgets/OO.ui.InputLabelWidget.js", + "src/widgets/OO.ui.LabelWidget.js", "src/widgets/OO.ui.LookupInputWidget.js", "src/widgets/OO.ui.OptionWidget.js", "src/widgets/OO.ui.SelectWidget.js", diff --git a/demos/widgets.js b/demos/widgets.js index fe4a21e..69b4bb1 100644 --- a/demos/widgets.js +++ b/demos/widgets.js @@ -1,237 +1,234 @@ $( function () { - var i, name, len, item, items, fieldset, + var name, fieldset, $demo = $( '.oo-ui-demo' ), sections = { 'Widgets': [ - { - 'label': 'ButtonWidget', - 'widget': new OO.ui.ButtonWidget( { 'label': 'Normal' } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'label': 'Normal' } ), + { 'label': 'ButtonWidget (normal)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'label': 'Primary', 'flags': [ 'primary' ] - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (primary)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'label': 'Constructive', 'flags': [ 'constructive' ] - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (constructive)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'label': 'Destructive', 'flags': [ 'destructive' ] - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (destructive)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'label': 'Disabled', 'disabled': true - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (disabled)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'label': 'Iconed', 'icon': 'check' - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (iconed)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'label': 'Indicated', 'indicator': 'down' - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (indicated)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'frameless': true, 'icon': 'help', 'title': 'Icon only' - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (icon only)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'frameless': true, 'icon': 'alert', 'label': 'Labeled' - } ) - }, - { - 'widget': new OO.ui.ButtonWidget( { + } ), + { 'label': 'ButtonWidget (frameless)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonWidget( { 'frameless': true, 'icon': 'menu', 'label': 'Disabled', 'disabled': true - } ) - }, - { - 'label': 'ButtonGroupWidget', - 'widget': new OO.ui.ButtonGroupWidget(), - 'items': [ - new OO.ui.ButtonWidget( { 'icon': 'check', 'indicator': 'down' } ), - new OO.ui.ToggleButtonWidget( { - 'label': 'Primary', - 'flags': [ 'primary' ] - } ), - new OO.ui.ToggleButtonWidget( { - 'label': 'Constructive', - 'flags': [ 'constructive' ] - } ), - new OO.ui.ToggleButtonWidget( { - 'label': 'Destructive', - 'flags': [ 'destructive' ] - } ) - ] - }, - { - 'label': 'ButtonSelectWidget', - 'widget': new OO.ui.ButtonSelectWidget(), - 'items': [ - new OO.ui.ButtonOptionWidget( 'a', { 'icon': 'check', 'indicator': 'down' } ), - new OO.ui.ButtonOptionWidget( 'b', { - 'label': 'Primary', - 'flags': [ 'primary' ] - } ), - new OO.ui.ButtonOptionWidget( 'c', { - 'label': 'Constructive', - 'flags': [ 'constructive' ] - } ), - new OO.ui.ButtonOptionWidget( 'd', { - 'label': 'Destructive', - 'flags': [ 'destructive' ] - } ) - ] - }, - { - 'widget': new OO.ui.ButtonSelectWidget( { + } ), + { 'label': 'ButtonWidget (frameless, disabled)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonGroupWidget( { + 'items': [ + new OO.ui.ButtonWidget( { 'icon': 'check', 'indicator': 'down' } ), + new OO.ui.ToggleButtonWidget( { + 'label': 'Primary', + 'flags': [ 'primary' ] + } ), + new OO.ui.ToggleButtonWidget( { + 'label': 'Constructive', + 'flags': [ 'constructive' ] + } ), + new OO.ui.ToggleButtonWidget( { + 'label': 'Destructive', + 'flags': [ 'destructive' ] + } ) + ] + } ), + { 'label': 'ButtonGroupWidget' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonSelectWidget( { + 'items': [ + new OO.ui.ButtonOptionWidget( 'a', { + 'icon': 'check', 'indicator': 'down' + } ), + new OO.ui.ButtonOptionWidget( 'b', { + 'label': 'Primary', + 'flags': [ 'primary' ] + } ), + new OO.ui.ButtonOptionWidget( 'c', { + 'label': 'Constructive', + 'flags': [ 'constructive' ] + } ), + new OO.ui.ButtonOptionWidget( 'd', { + 'label': 'Destructive', + 'flags': [ 'destructive' ] + } ) + ] + } ), + { 'label': 'ButtonSelectWidget' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonSelectWidget( { + 'disabled': true, + 'items': [ + new OO.ui.ButtonOptionWidget( 1, { + 'label': 'Disabled', + } ), + new OO.ui.ButtonOptionWidget( 2, { + 'label': 'state', + } ), + new OO.ui.ButtonOptionWidget( 3, { + 'label': 'is', + } ), + new OO.ui.ButtonOptionWidget( 3, { + 'label': 'inherited', + } ) + ] + } ), + { 'label': 'ButtonSelectWidget (disabled)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ButtonSelectWidget( { + 'items': [ + new OO.ui.ButtonOptionWidget( 1, { + 'label': 'Disabled', + 'disabled': true + } ), + new OO.ui.ButtonOptionWidget( 2, { + 'label': 'Enabled' + } ), + new OO.ui.ButtonOptionWidget( 3, { + 'label': 'Disabled', + 'disabled': true + } ), + new OO.ui.ButtonOptionWidget( 3, { + 'label': 'Enabled' + } ) + ] + } ), + { 'label': 'ButtonSelectWidget (disabled items)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ToggleButtonWidget( { 'label': 'Toggle' } ), + { 'label': 'ToggleButtonWidget' } + ), + new OO.ui.FieldLayout( + new OO.ui.ToggleButtonWidget( { 'icon': 'next' } ), + { 'label': 'ToggleButtonWidget (icon only)' } + ), + new OO.ui.FieldLayout( + new OO.ui.ToggleSwitchWidget(), + { 'label': 'ToggleSwitchWidget' } + ), + new OO.ui.FieldLayout( + new OO.ui.ToggleSwitchWidget( { 'disabled': true } ), + { 'label': 'ToggleSwitchWidget (disabled)' } + ), + new OO.ui.FieldLayout( + new OO.ui.CheckboxInputWidget( { + 'value': true + } ), + { + 'align': 'inline', + 'label': 'CheckboxInputWidget' + } + ), + new OO.ui.FieldLayout( + new OO.ui.CheckboxInputWidget( { + 'value': true, 'disabled': true } ), - 'items': [ - new OO.ui.ButtonOptionWidget( 1, { - 'label': 'Disabled', - } ), - new OO.ui.ButtonOptionWidget( 2, { - 'label': 'state', - } ), - new OO.ui.ButtonOptionWidget( 3, { - 'label': 'is', - } ), - new OO.ui.ButtonOptionWidget( 3, { - 'label': 'inherited', - } ) - ] - }, - { - 'widget': new OO.ui.ButtonSelectWidget(), - 'items': [ - new OO.ui.ButtonOptionWidget( 1, { - 'label': 'Disabled', - 'disabled': true - } ), - new OO.ui.ButtonOptionWidget( 2, { - 'label': 'Enabled' - } ), - new OO.ui.ButtonOptionWidget( 3, { - 'label': 'Disabled', - 'disabled': true - } ), - new OO.ui.ButtonOptionWidget( 3, { - 'label': 'Enabled' - } ) - ] - }, - { - 'label': 'ToggleButtonWidget', - 'widget': new OO.ui.ToggleButtonWidget( { 'label': 'Toggle' } ) - }, - { - 'widget': new OO.ui.ToggleButtonWidget( { - 'icon': 'next' - } ) - }, - { - 'label': 'ToggleSwitchWidget', - 'widget': new OO.ui.ToggleSwitchWidget() - }, - { - 'widget': new OO.ui.ToggleSwitchWidget( { - 'offLabel': 'Disabled', - 'disabled': true - } ) - }, - { - 'label': 'CheckboxInputWidget', - 'widget': new OO.ui.CheckboxInputWidget( { - 'value': true - } ) - }, - { - 'label': 'CheckboxWidget', - 'widget': new OO.ui.CheckboxWidget( { - 'value': true, - 'label': 'Labeled' - } ) - }, - { - 'widget': new OO.ui.CheckboxWidget( { - 'value': true, - 'label': 'Disabled', - 'disabled': true - } ) - }, - { - 'label': 'TextInputWidget', - 'widget': new OO.ui.TextInputWidget( { 'value': 'Text input' } ) - }, - { - 'widget': new OO.ui.TextInputWidget( { - 'placeholder': 'Placeholder' - } ) - }, - { - 'widget': new OO.ui.TextInputWidget( { + { + 'align': 'inline', + 'label': 'CheckboxInputWidget (disabled)' + } + ), + new OO.ui.FieldLayout( + new OO.ui.TextInputWidget( { 'value': 'Text input' } ), + { 'label': 'TextInputWidget' } + ), + new OO.ui.FieldLayout( + new OO.ui.TextInputWidget( { 'placeholder': 'Placeholder' } ), + { 'label': 'TextInputWidget (placeholder)' } + ), + new OO.ui.FieldLayout( + new OO.ui.TextInputWidget( { 'value': 'Readonly', 'readOnly': true - } ) - }, - { - 'widget': new OO.ui.TextInputWidget( { + } ), + { 'label': 'TextInputWidget (readonly)' } + ), + new OO.ui.FieldLayout( + new OO.ui.TextInputWidget( { 'value': 'Disabled', 'disabled': true - } ) - }, - { - 'widget': new OO.ui.TextInputWidget( { + } ), + { 'label': 'TextInputWidget (disabled)' } + ), + new OO.ui.FieldLayout( + new OO.ui.TextInputWidget( { 'multiline': true, 'value': 'Multiline' - } ) - } + } ), + { 'label': 'TextInputWidget (multiline)' } + ) ] }; for ( name in sections ) { fieldset = new OO.ui.FieldsetLayout( { 'label': name } ); - items = sections[name]; - for ( i = 0, len = items.length; i < len; i++ ) { - item = items[i]; - if ( item.items ) { - item.widget.addItems( item.items ); - } - fieldset.$element.append( - $( '<div>' ) - .addClass( 'oo-ui-demo-item' ) - .append( - $( '<div>' ) - .addClass( 'oo-ui-demo-item-label' ) - .text( item.label ), - $( '<div>' ) - .addClass( 'oo-ui-demo-item-widget' ) - .append( item.widget.$element ), - OO.ui.demo.buildConsole( item ) - ) - ); - } + fieldset.addItems( sections[name] ); + // TODO: Update buildConsole to add consoles to fieldsets full of field layouts + // OO.ui.demo.buildConsole( item ); $demo.append( fieldset.$element ); } } ); diff --git a/src/OO.ui.Element.js b/src/OO.ui.Element.js index 5e76b8e..59a3850 100644 --- a/src/OO.ui.Element.js +++ b/src/OO.ui.Element.js @@ -20,7 +20,7 @@ this.elementGroup = null; // Initialization - if ( Array.isArray( config.classes ) ) { + if ( $.isArray( config.classes ) ) { this.$element.addClass( config.classes.join( ' ' ) ); } if ( config.$content ) { diff --git a/src/OO.ui.ToolFactory.js b/src/OO.ui.ToolFactory.js index f0a4bfd..95d110b 100644 --- a/src/OO.ui.ToolFactory.js +++ b/src/OO.ui.ToolFactory.js @@ -71,7 +71,7 @@ } } } - } else if ( Array.isArray( collection ) ) { + } else if ( $.isArray( collection ) ) { for ( i = 0, len = collection.length; i < len; i++ ) { item = collection[i]; // Allow plain strings as shorthand for named tools diff --git a/src/OO.ui.ToolGroup.js b/src/OO.ui.ToolGroup.js index 6797c76..15f78f3 100644 --- a/src/OO.ui.ToolGroup.js +++ b/src/OO.ui.ToolGroup.js @@ -27,7 +27,7 @@ OO.ui.Widget.call( this, config ); // Mixin constructors - OO.ui.GroupElement.call( this, this.$( '<div>' ) ); + OO.ui.GroupElement.call( this, this.$( '<div>' ), config ); // Properties this.toolbar = toolbar; diff --git a/src/OO.ui.Toolbar.js b/src/OO.ui.Toolbar.js index f364f36..faea30a 100644 --- a/src/OO.ui.Toolbar.js +++ b/src/OO.ui.Toolbar.js @@ -8,20 +8,20 @@ * * @constructor * @param {OO.Factory} toolFactory Factory for creating tools - * @param {Object} [options] Configuration options + * @param {Object} [config] Configuration options * @cfg {boolean} [actions] Add an actions section opposite to the tools * @cfg {boolean} [shadow] Add a shadow below the toolbar */ -OO.ui.Toolbar = function OoUiToolbar( toolFactory, options ) { +OO.ui.Toolbar = function OoUiToolbar( toolFactory, config ) { // Configuration initialization - options = options || {}; + config = config || {}; // Parent constructor - OO.ui.Element.call( this, options ); + OO.ui.Element.call( this, config ); // Mixin constructors OO.EventEmitter.call( this ); - OO.ui.GroupElement.call( this, this.$( '<div>' ) ); + OO.ui.GroupElement.call( this, this.$( '<div>' ), config ); // Properties this.toolFactory = toolFactory; @@ -39,12 +39,12 @@ // Initialization this.$group.addClass( 'oo-ui-toolbar-tools' ); this.$bar.addClass( 'oo-ui-toolbar-bar' ).append( this.$group ); - if ( options.actions ) { + if ( config.actions ) { this.$actions.addClass( 'oo-ui-toolbar-actions' ); this.$bar.append( this.$actions ); } this.$bar.append( '<div style="clear:both"></div>' ); - if ( options.shadow ) { + if ( config.shadow ) { this.$bar.append( '<div class="oo-ui-toolbar-shadow"></div>' ); } this.$element.addClass( 'oo-ui-toolbar' ).append( this.$bar ); diff --git a/src/elements/OO.ui.ClippableElement.js b/src/elements/OO.ui.ClippableElement.js index aa29967..dd62b4e 100644 --- a/src/elements/OO.ui.ClippableElement.js +++ b/src/elements/OO.ui.ClippableElement.js @@ -6,8 +6,12 @@ * * @constructor * @param {jQuery} $clippable Nodes to clip, assigned to #$clippable + * @param {Object} [config] Configuration options */ -OO.ui.ClippableElement = function OoUiClippableElement( $clippable ) { +OO.ui.ClippableElement = function OoUiClippableElement( $clippable, config ) { + // Configuration initialization + config = config || {}; + // Properties this.$clippable = $clippable; this.clipping = false; diff --git a/src/elements/OO.ui.FlaggableElement.js b/src/elements/OO.ui.FlaggableElement.js index 8adb731..4513395 100644 --- a/src/elements/OO.ui.FlaggableElement.js +++ b/src/elements/OO.ui.FlaggableElement.js @@ -54,7 +54,7 @@ var i, len, flag, classPrefix = 'oo-ui-flaggableElement-'; - if ( Array.isArray( flags ) ) { + if ( $.isArray( flags ) ) { for ( i = 0, len = flags.length; i < len; i++ ) { flag = flags[i]; // Set diff --git a/src/elements/OO.ui.GroupElement.js b/src/elements/OO.ui.GroupElement.js index f8341c6..3c62626 100644 --- a/src/elements/OO.ui.GroupElement.js +++ b/src/elements/OO.ui.GroupElement.js @@ -49,7 +49,7 @@ item = items[i]; // Check if item exists then remove it first, effectively "moving" it - currentIndex = this.items.indexOf( item ); + currentIndex = $.inArray( item, this.items ); if ( currentIndex >= 0 ) { this.removeItems( [ item ] ); // Adjust index to compensate for removal @@ -100,7 +100,7 @@ // Remove specific items for ( i = 0, len = items.length; i < len; i++ ) { item = items[i]; - index = this.items.indexOf( item ); + index = $.inArray( item, this.items ); if ( index !== -1 ) { if ( this.aggregate ) { item.disconnect( this ); diff --git a/src/layouts/OO.ui.FieldLayout.js b/src/layouts/OO.ui.FieldLayout.js new file mode 100644 index 0000000..5109310 --- /dev/null +++ b/src/layouts/OO.ui.FieldLayout.js @@ -0,0 +1,106 @@ +/** + * Layout made of a field and optional label. + * + * @class + * @extends OO.ui.Layout + * @mixins OO.ui.LabeledElement + * + * Available label alignment modes include: + * - 'left': Label is before the field and aligned away from it, best for when the user will be + * scanning for a specific label in a form with many fields + * - 'right': Label is before the field and aligned toward it, best for forms the user is very + * familiar with and will tab through field checking quickly to verify which field they are in + * - 'top': Label is before the field and above it, best for when the use will need to fill out all + * fields from top to bottom in a form with few fields + * - 'inline': Label is after the field and aligned toward it, best for small boolean fields like + * checkboxes or radio buttons + * + * @constructor + * @param {OO.ui.Widget} field Field widget + * @param {Object} [config] Configuration options + * @cfg {string} [align='left'] Alignment mode, either 'left', 'right', 'top' or 'inline' + */ +OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) { + // Config initialization + config = $.extend( { 'align': 'left' }, config ); + + // Parent constructor + OO.ui.Layout.call( this, config ); + + // Mixin constructors + OO.ui.LabeledElement.call( this, this.$( '<label>' ), config ); + + // Properties + this.$field = this.$( '<div>' ); + this.field = field; + this.align = null; + + // Events + if ( this.field instanceof OO.ui.InputWidget ) { + this.$label.on( 'click', OO.ui.bind( this.onLabelClick, this ) ); + } + + // Initialization + this.$element.addClass( 'oo-ui-fieldLayout' ); + this.$field + .addClass( 'oo-ui-fieldLayout-field' ) + .append( this.field.$element ); + this.setAlignment( config.align ); +}; + +/* Inheritance */ + +OO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout ); + +OO.mixinClass( OO.ui.FieldLayout, OO.ui.LabeledElement ); + +/* Methods */ + +/** + * Handles label mouse click events. + * + * @method + * @param {jQuery.Event} e Mouse click event + */ +OO.ui.FieldLayout.prototype.onLabelClick = function () { + this.field.simulateLabelClick(); + return false; +}; + +/** + * Get the field. + * + * @returns {OO.ui.Widget} Field widget + */ +OO.ui.FieldLayout.prototype.getField = function () { + return this.field; +}; + +/** + * Set the field alignment mode. + * + * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline' + * @chainable + */ +OO.ui.FieldLayout.prototype.setAlignment = function ( value ) { + if ( value !== this.align ) { + // Default to 'left' + if ( [ 'left', 'right', 'top', 'inline' ].indexOf( value ) === -1 ) { + value = 'left'; + } + // Reorder elements + if ( value === 'inline' ) { + this.$element.append( this.$field, this.$label ); + } else { + this.$element.append( this.$label, this.$field ); + } + // Set classes + if ( this.align ) { + this.$element.removeClass( 'oo-ui-fieldLayout-align-' + this.align ); + } + this.align = value; + this.$element.addClass( 'oo-ui-fieldLayout-align-' + this.align ); + } + + return this; +}; diff --git a/src/layouts/OO.ui.FieldsetLayout.js b/src/layouts/OO.ui.FieldsetLayout.js index 55745af..0d457a7 100644 --- a/src/layouts/OO.ui.FieldsetLayout.js +++ b/src/layouts/OO.ui.FieldsetLayout.js @@ -1,13 +1,18 @@ /** * Layout made of a fieldset and optional legend. * + * Just add OO.ui.FieldLayout items. + * * @class * @extends OO.ui.Layout * @mixins OO.ui.LabeledElement + * @mixins OO.ui.IconedElement + * @mixins OO.ui.GroupElement * * @constructor * @param {Object} [config] Configuration options * @cfg {string} [icon] Symbolic icon name + * @cfg {OO.ui.FieldLayout[]} [items] Items to add */ OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) { // Config initialization @@ -17,18 +22,16 @@ OO.ui.Layout.call( this, config ); // Mixin constructors + OO.ui.IconedElement.call( this, this.$( '<div>' ), config ); OO.ui.LabeledElement.call( this, this.$( '<legend>' ), config ); + OO.ui.GroupElement.call( this, this.$( '<div>' ), config ); // Initialization - if ( config.icon ) { - this.$element.addClass( 'oo-ui-fieldsetLayout-decorated' ); - this.$label.addClass( 'oo-ui-icon-' + config.icon ); - } - this.$element.addClass( 'oo-ui-fieldsetLayout' ); - if ( config.icon || config.label ) { - this.$element - .addClass( 'oo-ui-fieldsetLayout-labeled' ) - .append( this.$label ); + this.$element + .addClass( 'oo-ui-fieldsetLayout' ) + .append( this.$icon, this.$label, this.$group ); + if ( $.isArray( config.items ) ) { + this.addItems( config.items ); } }; @@ -36,7 +39,9 @@ OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout ); +OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.IconedElement ); OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.LabeledElement ); +OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.GroupElement ); /* Static Properties */ diff --git a/src/layouts/OO.ui.StackLayout.js b/src/layouts/OO.ui.StackLayout.js index 92c68ca..695b493 100644 --- a/src/layouts/OO.ui.StackLayout.js +++ b/src/layouts/OO.ui.StackLayout.js @@ -9,6 +9,7 @@ * @param {Object} [config] Configuration options * @cfg {boolean} [continuous=false] Show all pages, one after another * @cfg {string} [icon=''] Symbolic icon name + * @cfg {OO.ui.Layout[]} [items] Layouts to add */ OO.ui.StackLayout = function OoUiStackLayout( config ) { // Config initialization @@ -28,6 +29,9 @@ this.$element.addClass( 'oo-ui-stackLayout' ); if ( this.continuous ) { this.$element.addClass( 'oo-ui-stackLayout-continuous' ); + } + if ( $.isArray( config.items ) ) { + this.addItems( config.items ); } }; @@ -77,7 +81,7 @@ */ OO.ui.StackLayout.prototype.removeItems = function ( items ) { OO.ui.GroupElement.prototype.removeItems.call( this, items ); - if ( items.indexOf( this.currentItem ) !== -1 ) { + if ( $.inArray( this.currentItem, items ) !== -1 ) { this.currentItem = null; if ( !this.currentItem && this.items.length ) { this.setItem( this.items[0] ); @@ -115,7 +119,7 @@ if ( !this.continuous ) { this.$items.css( 'display', '' ); } - if ( this.items.indexOf( item ) !== -1 ) { + if ( $.inArray( item, this.items ) !== -1 ) { if ( !this.continuous ) { item.$element.css( 'display', 'block' ); } diff --git a/src/styles/OO.ui.Layout.css b/src/styles/OO.ui.Layout.css index a77753a..9b78185 100644 --- a/src/styles/OO.ui.Layout.css +++ b/src/styles/OO.ui.Layout.css @@ -21,6 +21,7 @@ /* OO.ui.FieldsetLayout */ .oo-ui-fieldsetLayout { + position: relative; border: none; margin: 0; padding: 0; @@ -37,14 +38,80 @@ .oo-ui-fieldsetLayout > legend.oo-ui-labeledElement-label { font-size: 1.5em; margin-bottom: 0.5em; + padding-left: 0; } -.oo-ui-fieldsetLayout-decorated > legend.oo-ui-labeledElement-label { +.oo-ui-fieldsetLayout.oo-ui-iconedElement > legend.oo-ui-labeledElement-label { padding-left: 1.75em; - background-position: left center; +} + +.oo-ui-fieldsetLayout.oo-ui-iconedElement > .oo-ui-iconedElement-icon { + display: block; + position: absolute; + left: 0; + top: 0.5em; + width: 2em; + height: 2em; + background-position: center center; background-repeat: no-repeat; } +/* OO.ui.FieldLayout */ + +.oo-ui-fieldLayout { + margin-bottom: 1em; +} + +.oo-ui-fieldLayout:last-child { + margin-bottom: 0; +} + +.oo-ui-fieldLayout:before, +.oo-ui-fieldLayout:after { + content: " "; + display: table; +} + +.oo-ui-fieldLayout:after { + clear: both; +} + +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-labeledElement-label, +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label { + display: block; + float: left; + width: 35%; + padding-top: 0.5em; + margin-right: 5%; +} + +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-field, +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-field { + display: block; + float: left; + width: 60%; +} + +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-labeledElement-label { + text-align: right; +} + +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-labeledElement-label { + display: inline-block; + vertical-align: middle; + padding: 0.75em 0.5em 0.5em 0.5em; +} + +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-field { + display: inline-block; + vertical-align: middle; + padding: 0.5em 0; +} + +.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-labeledElement-label { + padding: 0.5em 0; +} + /* OO.ui.BookletLayout */ .oo-ui-bookletLayout-stackLayout .oo-ui-panelLayout { diff --git a/src/styles/OO.ui.Widget.css b/src/styles/OO.ui.Widget.css index bf09b4b..82f167d 100644 --- a/src/styles/OO.ui.Widget.css +++ b/src/styles/OO.ui.Widget.css @@ -21,6 +21,7 @@ .oo-ui-buttonGroupWidget { display: inline-block; + white-space: nowrap; border-radius: 0.3em; } @@ -191,9 +192,9 @@ cursor: default; } -/* OO.ui.InputLabelWidget */ +/* OO.ui.LabelWidget */ -.oo-ui-inputLabelWidget { +.oo-ui-labelWidget { padding: 0.5em 0; } @@ -276,21 +277,6 @@ background-repeat: no-repeat; } -/* OO.ui.CheckboxWidget */ -.oo-ui-checkboxWidget .oo-ui-labeledElement-label { - display: inline-block; - vertical-align: middle; - padding-left: 0.5em; -} - -.oo-ui-checkboxWidget input { - vertical-align: middle; -} - -.oo-ui-checkboxWidget.oo-ui-widget-disabled .oo-ui-labeledElement-label { - opacity: 0.5; -} - /* OO.ui.MenuWidget */ .oo-ui-menuWidget { @@ -344,6 +330,7 @@ .oo-ui-buttonSelectWidget { display: inline-block; + white-space: nowrap; border-radius: 0.3em; } diff --git a/src/toolgroups/OO.ui.PopupToolGroup.js b/src/toolgroups/OO.ui.PopupToolGroup.js index 1bb3f95..48d0a29 100644 --- a/src/toolgroups/OO.ui.PopupToolGroup.js +++ b/src/toolgroups/OO.ui.PopupToolGroup.js @@ -26,7 +26,7 @@ OO.ui.IndicatedElement.call( this, this.$( '<span>' ), config ); OO.ui.LabeledElement.call( this, this.$( '<span>' ), config ); OO.ui.TitledElement.call( this, this.$element, config ); - OO.ui.ClippableElement.call( this, this.$group ); + OO.ui.ClippableElement.call( this, this.$group, config ); // Properties this.active = false; diff --git a/src/widgets/OO.ui.ButtonGroupWidget.js b/src/widgets/OO.ui.ButtonGroupWidget.js index 40faf65..dd0842f 100644 --- a/src/widgets/OO.ui.ButtonGroupWidget.js +++ b/src/widgets/OO.ui.ButtonGroupWidget.js @@ -7,6 +7,7 @@ * * @constructor * @param {Object} [config] Configuration options + * @cfg {OO.ui.ButtonWidget} [items] Buttons to add */ OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) { // Parent constructor @@ -17,6 +18,9 @@ // Initialization this.$element.addClass( 'oo-ui-buttonGroupWidget' ); + if ( $.isArray( config.items ) ) { + this.addItems( config.items ); + } }; /* Inheritance */ diff --git a/src/widgets/OO.ui.CheckboxWidget.js b/src/widgets/OO.ui.CheckboxWidget.js deleted file mode 100644 index d64c0da..0000000 --- a/src/widgets/OO.ui.CheckboxWidget.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Creates an OO.ui.CheckboxWidget object. - * - * @class - * @extends OO.ui.CheckboxInputWidget - * @mixins OO.ui.LabeledElement - * - * @constructor - * @param {Object} [config] Configuration options - * @cfg {string} [label=''] Label - */ -OO.ui.CheckboxWidget = function OoUiCheckboxWidget( config ) { - // Configuration initialization - config = config || {}; - - // Parent constructor - OO.ui.CheckboxInputWidget.call( this, config ); - - // Mixin constructors - OO.ui.LabeledElement.call( this, this.$( '<span>' ) , config ); - - // Initialization - this.$element - .addClass( 'oo-ui-checkboxWidget' ) - .append( this.$( '<label>' ).append( this.$input, this.$label ) ); -}; - -/* Inheritance */ - -OO.inheritClass( OO.ui.CheckboxWidget, OO.ui.CheckboxInputWidget ); - -OO.mixinClass( OO.ui.CheckboxWidget, OO.ui.LabeledElement ); diff --git a/src/widgets/OO.ui.InputLabelWidget.js b/src/widgets/OO.ui.InputLabelWidget.js deleted file mode 100644 index 991bd2e..0000000 --- a/src/widgets/OO.ui.InputLabelWidget.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Creates an OO.ui.InputLabelWidget object. - * - * CSS classes will be added to the button for each flag, each prefixed with 'oo-ui-InputLabelWidget-' - * - * @class - * @extends OO.ui.Widget - * @mixins OO.ui.LabeledElement - * - * @constructor - * @param {Object} [config] Configuration options - * @cfg {OO.ui.InputWidget|null} [input] Related input widget - */ -OO.ui.InputLabelWidget = function OoUiInputLabelWidget( config ) { - // Config intialization - config = $.extend( { 'input': null }, config ); - - // Parent constructor - OO.ui.Widget.call( this, config ); - - // Mixin constructors - OO.ui.LabeledElement.call( this, this.$element, config ); - - // Properties - this.input = config.input; - - // Events - this.$element.on( 'click', OO.ui.bind( this.onClick, this ) ); - - // Initialization - this.$element.addClass( 'oo-ui-inputLabelWidget' ); -}; - -/* Inheritance */ - -OO.inheritClass( OO.ui.InputLabelWidget, OO.ui.Widget ); - -OO.mixinClass( OO.ui.InputLabelWidget, OO.ui.LabeledElement ); - -/* Static Properties */ - -OO.ui.InputLabelWidget.static.tagName = 'label'; - -/* Methods */ - -/** - * Handles mouse click events. - * - * @method - * @param {jQuery.Event} e Mouse click event - */ -OO.ui.InputLabelWidget.prototype.onClick = function () { - if ( !this.disabled && this.input ) { - this.input.$input.focus(); - } - return false; -}; diff --git a/src/widgets/OO.ui.InputWidget.js b/src/widgets/OO.ui.InputWidget.js index 72e22ac..8d169b8 100644 --- a/src/widgets/OO.ui.InputWidget.js +++ b/src/widgets/OO.ui.InputWidget.js @@ -144,6 +144,21 @@ }; /** + * Simulate the behavior of clicking on a label bound to this input. + * + * @method + */ +OO.ui.InputWidget.prototype.simulateLabelClick = function () { + if ( !this.isDisabled() ) { + if ( this.$input.is( ':checkbox,:radio' ) ) { + this.$input.click(); + } else if ( this.$input.is( ':input' ) ) { + this.$input.focus(); + } + } +}; + +/** * Check if the widget is read-only. * * @method @@ -177,4 +192,4 @@ this.$input.prop( 'disabled', this.disabled ); } return this; -}; \ No newline at end of file +}; diff --git a/src/widgets/OO.ui.LabelWidget.js b/src/widgets/OO.ui.LabelWidget.js new file mode 100644 index 0000000..7577921 --- /dev/null +++ b/src/widgets/OO.ui.LabelWidget.js @@ -0,0 +1,54 @@ +/** + * Creates an OO.ui.LabelWidget object. + * + * @class + * @extends OO.ui.Widget + * @mixins OO.ui.LabeledElement + * + * @constructor + * @param {Object} [config] Configuration options + */ +OO.ui.LabelWidget = function OoUiLabelWidget( config ) { + // Config intialization + config = config || {}; + + // Parent constructor + OO.ui.Widget.call( this, config ); + + // Mixin constructors + OO.ui.LabeledElement.call( this, this.$element, config ); + + // Properties + this.input = config.input; + + // Events + if ( this.input instanceof OO.ui.InputWidget ) { + this.$element.on( 'click', OO.ui.bind( this.onClick, this ) ); + } + + // Initialization + this.$element.addClass( 'oo-ui-labelWidget' ); +}; + +/* Inheritance */ + +OO.inheritClass( OO.ui.LabelWidget, OO.ui.Widget ); + +OO.mixinClass( OO.ui.LabelWidget, OO.ui.LabeledElement ); + +/* Static Properties */ + +OO.ui.LabelWidget.static.tagName = 'label'; + +/* Methods */ + +/** + * Handles label mouse click events. + * + * @method + * @param {jQuery.Event} e Mouse click event + */ +OO.ui.LabelWidget.prototype.onClick = function () { + this.input.simulateLabelClick(); + return false; +}; diff --git a/src/widgets/OO.ui.MenuWidget.js b/src/widgets/OO.ui.MenuWidget.js index a8d42f3..a6fa154 100644 --- a/src/widgets/OO.ui.MenuWidget.js +++ b/src/widgets/OO.ui.MenuWidget.js @@ -17,7 +17,7 @@ OO.ui.SelectWidget.call( this, config ); // Mixin constructors - OO.ui.ClippableElement.call( this, this.$group ); + OO.ui.ClippableElement.call( this, this.$group, config ); // Properties this.newItems = []; diff --git a/src/widgets/OO.ui.SelectWidget.js b/src/widgets/OO.ui.SelectWidget.js index 5bae115..7b11b53 100644 --- a/src/widgets/OO.ui.SelectWidget.js +++ b/src/widgets/OO.ui.SelectWidget.js @@ -8,6 +8,7 @@ * * @constructor * @param {Object} [config] Configuration options + * @cfg {OO.ui.OptionWidget[]} [items] Options to add */ OO.ui.SelectWidget = function OoUiSelectWidget( config ) { // Config intialization @@ -35,6 +36,9 @@ // Initialization this.$element.addClass( 'oo-ui-selectWidget' ); + if ( $.isArray( config.items ) ) { + this.addItems( config.items ); + } }; /* Inheritance */ @@ -313,7 +317,7 @@ var inc = direction > 0 ? 1 : -1, len = this.items.length, index = item instanceof OO.ui.OptionWidget ? - this.items.indexOf( item ) : ( inc > 0 ? -1 : 0 ), + $.inArray( item, this.items ) : ( inc > 0 ? -1 : 0 ), stopAt = Math.max( Math.min( index, len - 1 ), 0 ), i = inc > 0 ? // Default to 0 instead of -1, if nothing is selected let's start at the beginning -- To view, visit https://gerrit.wikimedia.org/r/108955 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I87e1bdf5ccb67ce58022926c4faede0c70a1f4a4 Gerrit-PatchSet: 7 Gerrit-Project: oojs/ui Gerrit-Branch: master Gerrit-Owner: Trevor Parscal <tpars...@wikimedia.org> Gerrit-Reviewer: Catrope <roan.katt...@gmail.com> Gerrit-Reviewer: Esanders <esand...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits