jenkins-bot has submitted this change and it was merged. Change subject: Refactor OutlineControlsWidget, add remove button ......................................................................
Refactor OutlineControlsWidget, add remove button * Adders turn out to be very instance specific, so abstracting them makes things pretty awkward. Rather than generate adders from a configuration object, mix in GroupElement and use its API for managing items. * Add remove button and event to OutlineControlsWidget * Add removable state to OutlineItemWidget * Use IconedElement to render + icon for adders, rather than faking it with a button that doesn't do anything * Blur focused inputs on page change * Add method for getting the closest page to another, taking into consideration depth when a booklet is outlined Change-Id: I35ae249b0b1597188dc6d06cdaf78ba08027be80 --- M i18n/en.json M i18n/qqq.json M src/OO.ui.js M src/layouts/OO.ui.BookletLayout.js M src/styles/OO.ui.Widget.less M src/widgets/OO.ui.OutlineControlsWidget.js M src/widgets/OO.ui.OutlineItemWidget.js 7 files changed, 132 insertions(+), 61 deletions(-) Approvals: Catrope: Looks good to me, approved jenkins-bot: Verified diff --git a/i18n/en.json b/i18n/en.json index d402de8..5ff9915 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -19,5 +19,6 @@ "ooui-dialog-action-close": "Close", "ooui-outline-control-move-down": "Move item down", "ooui-outline-control-move-up": "Move item up", + "ooui-outline-control-remove": "Remove item", "ooui-toolbar-more": "More" } diff --git a/i18n/qqq.json b/i18n/qqq.json index 78a70d9..c5b8ffa 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -22,5 +22,6 @@ "ooui-dialog-action-close": "Label text for button to exit from dialog.\n\n{{Identical|Close}}", "ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place", "ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place", + "ooui-outline-control-remove": "Tool tip for a button that removes items from a list", "ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}" } \ No newline at end of file diff --git a/src/OO.ui.js b/src/OO.ui.js index 1480c83..59a9640 100644 --- a/src/OO.ui.js +++ b/src/OO.ui.js @@ -74,6 +74,8 @@ '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' }; diff --git a/src/layouts/OO.ui.BookletLayout.js b/src/layouts/OO.ui.BookletLayout.js index f0ce75e..f110ba3 100644 --- a/src/layouts/OO.ui.BookletLayout.js +++ b/src/layouts/OO.ui.BookletLayout.js @@ -124,6 +124,7 @@ */ OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) { if ( page ) { + this.stackLayout.$element.find( ':focus' ).blur(); page.scrollElementIntoView( { 'complete': OO.ui.bind( function () { this.ignoreFocus = true; if ( this.autoFocus ) { @@ -164,6 +165,41 @@ */ OO.ui.BookletLayout.prototype.isEditable = function () { return this.editable; +}; + +/** + * Get the outline widget. + * + * @method + * @param {OO.ui.PageLayout} page Page to be selected + * @returns {OO.ui.PageLayout|null} Closest page to another + */ +OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) { + var next, prev, level, + pages = this.stackLayout.getItems(), + index = $.inArray( page, pages ); + + if ( index !== -1 ) { + next = pages[index + 1]; + prev = pages[index - 1]; + // Prefer adjacent pages at the same level + if ( this.outlined ) { + level = this.outlineWidget.getItemFromData( page.getName() ).getLevel(); + if ( + prev && + level === this.outlineWidget.getItemFromData( prev.getName() ).getLevel() + ) { + return prev; + } + if ( + next && + level === this.outlineWidget.getItemFromData( next.getName() ).getLevel() + ) { + return next; + } + } + } + return prev || next || null; }; /** @@ -220,26 +256,39 @@ * @chainable */ OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) { - var i, len, name, page, item, - items = [], - remove = []; + var i, len, name, page, item, currentIndex, + stackLayoutPages = this.stackLayout.getItems(), + remove = [], + items = []; + // Remove pages with same names for ( i = 0, len = pages.length; i < len; i++ ) { page = pages[i]; name = page.getName(); - if ( name in this.pages ) { - // Remove page with same name + + if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) { + // Correct the insertion index + currentIndex = $.inArray( this.pages[name], stackLayoutPages ); + if ( currentIndex !== -1 && currentIndex + 1 < index ) { + index--; + } remove.push( this.pages[name] ); } + } + if ( remove.length ) { + this.removePages( remove ); + } + + // Add new pages + for ( i = 0, len = pages.length; i < len; i++ ) { + page = pages[i]; + name = page.getName(); this.pages[page.getName()] = page; if ( this.outlined ) { item = new OO.ui.OutlineItemWidget( name, page, { '$': this.$ } ); page.setOutlineItem( item ); items.push( item ); } - } - if ( remove.length ) { - this.removePages( remove ); } if ( this.outlined && items.length ) { diff --git a/src/styles/OO.ui.Widget.less b/src/styles/OO.ui.Widget.less index 61ff212..734fdb4 100644 --- a/src/styles/OO.ui.Widget.less +++ b/src/styles/OO.ui.Widget.less @@ -134,7 +134,11 @@ opacity: 0.5; } &.oo-ui-flaggableElement-empty .oo-ui-labeledElement-label { - color: #698AA0; + color: #777; + } + + &.oo-ui-indicatedElement .oo-ui-labeledElement-label { + padding-right: 1.5em; } &-level-0 { @@ -173,21 +177,27 @@ -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; - height: 3em; - padding: 0.5em; + height: 2em; + margin: 0.5em; + padding: 0; + } + + > .oo-ui-iconedElement-icon { + float: left; + width: 1.5em; + height: 2em; + margin: 0.5em 0 0.5em 0.5em; + background-position: right center; + background-repeat: no-repeat; + opacity: 0.2; } &-adders { float: left; + margin-left: 0; .oo-ui-buttonWidget { float: left; - - &:first-child, - &:first-child:hover { - opacity: 0.25; - cursor: default; - } } } &-movers { diff --git a/src/widgets/OO.ui.OutlineControlsWidget.js b/src/widgets/OO.ui.OutlineControlsWidget.js index 39c8826..d67c0d5 100644 --- a/src/widgets/OO.ui.OutlineControlsWidget.js +++ b/src/widgets/OO.ui.OutlineControlsWidget.js @@ -6,26 +6,21 @@ * @constructor * @param {OO.ui.OutlineWidget} outline Outline to control * @param {Object} [config] Configuration options - * @cfg {Object[]} [adders] List of icons to show as addable item types, each an object with - * name, title and icon properties */ OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) { // Configuration initialization - config = config || {}; + config = $.extend( { 'icon': 'add-item' }, config ); // Parent constructor OO.ui.Widget.call( this, config ); + // Mixin constructors + OO.ui.GroupElement.call( this, this.$( '<div>' ), config ); + OO.ui.IconedElement.call( this, this.$( '<div>' ), config ); + // Properties this.outline = outline; - this.adders = {}; - this.$adders = this.$( '<div>' ); this.$movers = this.$( '<div>' ); - this.addButton = new OO.ui.ButtonWidget( { - '$': this.$, - 'frameless': true, - 'icon': 'add-item' - } ); this.upButton = new OO.ui.ButtonWidget( { '$': this.$, 'frameless': true, @@ -38,6 +33,12 @@ 'icon': 'expand', 'title': OO.ui.msg( 'ooui-outline-control-move-down' ) } ); + this.removeButton = new OO.ui.ButtonWidget( { + '$': this.$, + 'frameless': true, + 'icon': 'remove', + 'title': OO.ui.msg( 'ooui-outline-control-remove' ) + } ); // Events outline.connect( this, { @@ -47,28 +48,33 @@ } ); this.upButton.connect( this, { 'click': ['emit', 'move', -1] } ); this.downButton.connect( this, { 'click': ['emit', 'move', 1] } ); + this.removeButton.connect( this, { 'click': ['emit', 'remove'] } ); // Initialization this.$element.addClass( 'oo-ui-outlineControlsWidget' ); - this.$adders.addClass( 'oo-ui-outlineControlsWidget-adders' ); + this.$group.addClass( 'oo-ui-outlineControlsWidget-adders' ); this.$movers .addClass( 'oo-ui-outlineControlsWidget-movers' ) - .append( this.upButton.$element, this.downButton.$element ); - this.$element.append( this.$adders, this.$movers ); - if ( config.adders && config.adders.length ) { - this.setupAdders( config.adders ); - } + .append( this.removeButton.$element, this.upButton.$element, this.downButton.$element ); + this.$element.append( this.$icon, this.$group, this.$movers ); }; /* Inheritance */ OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget ); +OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.GroupElement ); +OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.IconedElement ); + /* Events */ /** * @event move * @param {number} places Number of places to move + */ + +/** + * @event remove */ /* Methods */ @@ -80,12 +86,12 @@ */ OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () { var i, len, firstMovable, lastMovable, - movable = false, items = this.outline.getItems(), - selectedItem = this.outline.getSelectedItem(); + selectedItem = this.outline.getSelectedItem(), + movable = selectedItem && selectedItem.isMovable(), + removable = selectedItem && selectedItem.isRemovable(); - if ( selectedItem && selectedItem.isMovable() ) { - movable = true; + if ( movable ) { i = -1; len = items.length; while ( ++i < len ) { @@ -104,28 +110,5 @@ } this.upButton.setDisabled( !movable || selectedItem === firstMovable ); this.downButton.setDisabled( !movable || selectedItem === lastMovable ); -}; - -/** - * Setup adders icons. - * - * @method - * @param {Object[]} adders List of configuations for adder buttons, each containing a name, title - * and icon property - */ -OO.ui.OutlineControlsWidget.prototype.setupAdders = function ( adders ) { - var i, len, addition, button, - $buttons = this.$( [] ); - - this.$adders.append( this.addButton.$element ); - for ( i = 0, len = adders.length; i < len; i++ ) { - addition = adders[i]; - button = new OO.ui.ButtonWidget( { - '$': this.$, 'frameless': true, 'icon': addition.icon, 'title': addition.title - } ); - button.connect( this, { 'click': ['emit', 'add', addition.name] } ); - this.adders[addition.name] = button; - this.$adders.append( button.$element ); - $buttons = $buttons.add( button.$element ); - } + this.removeButton.setDisabled( !removable ); }; diff --git a/src/widgets/OO.ui.OutlineItemWidget.js b/src/widgets/OO.ui.OutlineItemWidget.js index 48f9c39..3d0bd93 100644 --- a/src/widgets/OO.ui.OutlineItemWidget.js +++ b/src/widgets/OO.ui.OutlineItemWidget.js @@ -20,6 +20,7 @@ // Properties this.level = 0; this.movable = !!config.movable; + this.removable = !!config.removable; // Initialization this.$element.addClass( 'oo-ui-outlineItemWidget' ); @@ -54,6 +55,17 @@ }; /** + * Check if item is removable. + * + * Removablilty is used by outline controls. + * + * @returns {boolean} Item is removable + */ +OO.ui.OutlineItemWidget.prototype.isRemovable = function () { + return this.removable; +}; + +/** * Get indentation level. * * @returns {number} Indentation level @@ -76,6 +88,19 @@ }; /** + * Set removability. + * + * Removablilty is used by outline controls. + * + * @param {boolean} movable Item is removable + * @chainable + */ +OO.ui.OutlineItemWidget.prototype.setRemovable = function ( removable ) { + this.removable = !!removable; + return this; +}; + +/** * Set indentation level. * * @method -- To view, visit https://gerrit.wikimedia.org/r/116001 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I35ae249b0b1597188dc6d06cdaf78ba08027be80 Gerrit-PatchSet: 4 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: Jforrester <jforres...@wikimedia.org> Gerrit-Reviewer: Krinkle <krinklem...@gmail.com> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits