Trevor Parscal has uploaded a new change for review.
https://gerrit.wikimedia.org/r/68604
Change subject: Outline controls
......................................................................
Outline controls
Objectives:
* Allow reordering items in outline widgets using an outline control widget
* Use an outline control widget to reorder transclusion parts
Changes:
ve.ui.SelectWidget.js
* Emit add and remove events
ve.ui.OutlineItemWidget.js
* Add movable config options
* Add isMovable method
ve.ui.OutlineControlsWidget.js
* New class
* Displays move up/down buttons which are synchronized with an outline widget
* Doesn't actually move items (since an outline widget is probably data-driven)
just emits events
ve.ui.Widget.css
* Add disabled style for icon button widgets
* Add styles for outline controls widget
ve.ui.Icons*.css
* Add missing icon styles
ve.ui.Dialog.css
* Add styles for outline and controls in editable paged dialogs
ve.ui.GroupElement.js
* Fix bug where items are insertions are in the wrong place when "moving" them
ve.ui.PagedDialog.js
* Add editable config option which shows outline controls under the outline
* Pass through movable config option when creating pages
ve.ui.MWTranclusionDialog.js
* Configure paged dialog outline as editable
* Add initialize method to connect outline controls widget events
* Make addPart method automatically add parameters when templates are added
* Add handler for outline controls move event which re-orders parts
* Make parts movable (params are automatically ordered, so they aren't movable)
ve.dm.MWTransclusionModel.js
* Add addPart method and use it within the addContent and addTemplate methods
* Fix documentation lies
* Add getPartFromId method
*.php
* Add links to new files and messages
Change-Id: I919d4c3e9b85d07a97a99c0b2e8739a859bdf2b1
---
M VisualEditor.i18n.php
M VisualEditor.php
M demos/ve/index.php
M modules/ve/dm/models/ve.dm.MWTransclusionModel.js
M modules/ve/test/index.php
M modules/ve/ui/dialogs/ve.ui.MWTransclusionDialog.js
M modules/ve/ui/dialogs/ve.ui.PagedDialog.js
M modules/ve/ui/elements/ve.ui.GroupElement.js
M modules/ve/ui/styles/ve.ui.Dialog.css
M modules/ve/ui/styles/ve.ui.Icons-raster.css
M modules/ve/ui/styles/ve.ui.Icons-vector.css
M modules/ve/ui/styles/ve.ui.Widget.css
A modules/ve/ui/widgets/ve.ui.OutlineControlsWidget.js
M modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
M modules/ve/ui/widgets/ve.ui.SelectWidget.js
15 files changed, 296 insertions(+), 14 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/04/68604/1
diff --git a/VisualEditor.i18n.php b/VisualEditor.i18n.php
index aeca79e..6e04e76 100644
--- a/VisualEditor.i18n.php
+++ b/VisualEditor.i18n.php
@@ -99,6 +99,8 @@
'visualeditor-notification-created' => '$1 has been created.',
'visualeditor-notification-restored' => '$1 has been restored.',
'visualeditor-notification-saved' => 'Your changes to $1 have been
saved.',
+ 'visualeditor-outline-control-move-up' => 'Move item up',
+ 'visualeditor-outline-control-move-down' => 'Move item down',
'visualeditor-preference-enable' => 'Enable VisualEditor (only in the
[[{{MediaWiki:Visualeditor-mainnamespacepagelink}}|main]] and
[[{{MediaWiki:Visualeditor-usernamespacepagelink}}|user]] namespaces)',
'visualeditor-savedialog-label-create' => 'Create page',
'visualeditor-savedialog-label-report' => 'Report problem',
diff --git a/VisualEditor.php b/VisualEditor.php
index 0b82ce0..9eb9c9f 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -393,6 +393,7 @@
've/ui/widgets/ve.ui.TextInputWidget.js',
've/ui/widgets/ve.ui.OutlineItemWidget.js',
've/ui/widgets/ve.ui.OutlineWidget.js',
+ 've/ui/widgets/ve.ui.OutlineControlsWidget.js',
've/ui/widgets/ve.ui.MenuItemWidget.js',
've/ui/widgets/ve.ui.MenuSectionItemWidget.js',
've/ui/widgets/ve.ui.MenuWidget.js',
@@ -537,6 +538,8 @@
'visualeditor-notification-created',
'visualeditor-notification-restored',
'visualeditor-notification-saved',
+ 'visualeditor-outline-control-move-up',
+ 'visualeditor-outline-control-move-down',
'visualeditor-savedialog-label-create',
'visualeditor-savedialog-label-report',
'visualeditor-savedialog-label-resolve-conflict',
diff --git a/demos/ve/index.php b/demos/ve/index.php
index 2334670..a1d3d34 100644
--- a/demos/ve/index.php
+++ b/demos/ve/index.php
@@ -268,6 +268,7 @@
<script
src="../../modules/ve/ui/widgets/ve.ui.TextInputWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.OutlineWidget.js"></script>
+ <script
src="../../modules/ve/ui/widgets/ve.ui.OutlineControlsWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.MenuItemWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.MenuSectionItemWidget.js"></script>
<script
src="../../modules/ve/ui/widgets/ve.ui.MenuWidget.js"></script>
diff --git a/modules/ve/dm/models/ve.dm.MWTransclusionModel.js
b/modules/ve/dm/models/ve.dm.MWTransclusionModel.js
index c88cd89..9eca138 100644
--- a/modules/ve/dm/models/ve.dm.MWTransclusionModel.js
+++ b/modules/ve/dm/models/ve.dm.MWTransclusionModel.js
@@ -205,8 +205,7 @@
*/
ve.dm.MWTransclusionModel.prototype.addContent = function ( value, index ) {
var part = new ve.dm.MWTransclusionContentModel( this, value );
- this.parts.splice( index === undefined ? this.parts.length : index, 0,
part );
- this.emit( 'add', part );
+ this.addPart( part, index );
return part;
};
@@ -224,16 +223,28 @@
if ( this.specs.hasOwnProperty( title ) ) {
part.getSpec().extend( this.specs[title] );
}
+ this.addPart( part, index );
+ return part;
+};
+
+/**
+ * Add part.
+ *
+ * @method
+ * @param {ve.dm.MWTransclusionPartModel} part Part to add
+ * @param {number} [index] Specific index to add content at
+ * @emits add
+ */
+ve.dm.MWTransclusionModel.prototype.addPart = function ( part, index ) {
this.parts.splice( index === undefined ? this.parts.length : index, 0,
part );
this.emit( 'add', part );
- return part;
};
/**
* Remove a part.
*
* @method
- * @param {ve.dm.MWTransclusionPartModel} part Template part
+ * @param {ve.dm.MWTransclusionPartModel} part Part to remove
* @emits remove
*/
ve.dm.MWTransclusionModel.prototype.removePart = function ( part ) {
@@ -255,6 +266,24 @@
};
/**
+ * Get part by its ID.
+ *
+ * @method
+ * @param {string} id Part ID
+ * @returns {ve.dm.MWTransclusionPartModel|null} Part with matching ID, if
found
+ */
+ve.dm.MWTransclusionModel.prototype.getPartFromId = function ( id ) {
+ var i, len;
+
+ for ( i = 0, len = this.parts.length; i < len; i++ ) {
+ if ( this.parts[i].getId() === id ) {
+ return this.parts[i];
+ }
+ }
+ return null;
+};
+
+/**
* Get a template specification.
*
* @method
diff --git a/modules/ve/test/index.php b/modules/ve/test/index.php
index 3ce587d..ac64440 100644
--- a/modules/ve/test/index.php
+++ b/modules/ve/test/index.php
@@ -221,6 +221,7 @@
<script
src="../../ve/ui/widgets/ve.ui.TextInputWidget.js"></script>
<script
src="../../ve/ui/widgets/ve.ui.OutlineItemWidget.js"></script>
<script
src="../../ve/ui/widgets/ve.ui.OutlineWidget.js"></script>
+ <script
src="../../ve/ui/widgets/ve.ui.OutlineControlsWidget.js"></script>
<script
src="../../ve/ui/widgets/ve.ui.MenuItemWidget.js"></script>
<script
src="../../ve/ui/widgets/ve.ui.MenuSectionItemWidget.js"></script>
<script src="../../ve/ui/widgets/ve.ui.MenuWidget.js"></script>
diff --git a/modules/ve/ui/dialogs/ve.ui.MWTransclusionDialog.js
b/modules/ve/ui/dialogs/ve.ui.MWTransclusionDialog.js
index ab7b41d..e50f76b 100644
--- a/modules/ve/ui/dialogs/ve.ui.MWTransclusionDialog.js
+++ b/modules/ve/ui/dialogs/ve.ui.MWTransclusionDialog.js
@@ -19,6 +19,9 @@
* @param {Object} [config] Config options
*/
ve.ui.MWTransclusionDialog = function VeUiMWTransclusionDialog( surface,
config ) {
+ // Configuration initialization
+ config = ve.extendObject( {}, config, { 'editable': true } );
+
// Parent constructor
ve.ui.PagedDialog.call( this, surface, config );
@@ -40,6 +43,18 @@
ve.ui.MWTransclusionDialog.static.modelClasses = [ ve.dm.MWTransclusionNode ];
/* Methods */
+
+/**
+ * Handle frame ready events.
+ *
+ * @method
+ */
+ve.ui.MWTransclusionDialog.prototype.initialize = function () {
+ // Call parent method
+ ve.ui.PagedDialog.prototype.initialize.call( this );
+
+ this.outlineControlsWidget.connect( this, { 'move':
'onOutlineControlsMove' } );
+};
/**
* Handle frame open events.
@@ -106,17 +121,27 @@
* @param {ve.dm.MWTransclusionPartModel} part Added part
*/
ve.ui.MWTransclusionDialog.prototype.onAddPart = function ( part ) {
- var page;
+ var i, len, page, params, param, names;
if ( part instanceof ve.dm.MWTemplateModel ) {
page = this.getTemplatePage( part );
- part.connect( this, { 'add': 'onAddParameter', 'remove':
'onRemoveParameter' } );
} else if ( part instanceof ve.dm.MWTransclusionContentModel ) {
page = this.getContentPage( part );
}
- page.index = this.getPageIndex( part ) + 1;
+ page.index = this.getPageIndex( part );
if ( page ) {
this.addPage( part.getId(), page );
+ if ( part instanceof ve.dm.MWTemplateModel ) {
+ names = part.getParameterNames();
+ params = part.getParameters();
+ for ( i = 0, len = names.length; i < len; i++ ) {
+ param = params[names[i]];
+ page = this.getParameterPage( param );
+ page.index = this.getPageIndex( param ) + 1;
+ this.addPage( param.getId(), page );
+ }
+ part.connect( this, { 'add': 'onAddParameter',
'remove': 'onRemoveParameter' } );
+ }
}
};
@@ -161,6 +186,27 @@
this.removePage( param.getId() );
// Return to template page
this.setPageByName( param.getTemplate().getId() );
+};
+
+/**
+ * Handle outline controls move events.
+ *
+ * @method
+ * @param {number} places Number of places to move the selected item.
+ */
+ve.ui.MWTransclusionDialog.prototype.onOutlineControlsMove = function ( places
) {
+ var part, index, name,
+ parts = this.transclusion.getParts(),
+ item = this.outlineWidget.getSelectedItem();
+
+ if ( item ) {
+ name = item.getData();
+ part = this.transclusion.getPartFromId( name );
+ index = ve.indexOf( part, parts );
+ this.transclusion.removePart( part );
+ this.transclusion.addPart( part, index + places );
+ this.setPageByName( name );
+ }
};
/**
@@ -284,7 +330,8 @@
return {
'label': ve.msg( 'visualeditor-dialog-transclusion-content' ),
'icon': 'source',
- '$content': valueFieldset.$.add( optionsFieldset.$ )
+ '$content': valueFieldset.$.add( optionsFieldset.$ ),
+ 'moveable': true
};
};
@@ -360,7 +407,8 @@
return {
'label': label,
'icon': 'template',
- '$content': infoFieldset.$.add( addParameterFieldset.$ ).add(
optionsFieldset.$ )
+ '$content': infoFieldset.$.add( addParameterFieldset.$ ).add(
optionsFieldset.$ ),
+ 'moveable': true
};
};
diff --git a/modules/ve/ui/dialogs/ve.ui.PagedDialog.js
b/modules/ve/ui/dialogs/ve.ui.PagedDialog.js
index 735cc72..a832c8c 100644
--- a/modules/ve/ui/dialogs/ve.ui.PagedDialog.js
+++ b/modules/ve/ui/dialogs/ve.ui.PagedDialog.js
@@ -19,12 +19,17 @@
* @constructor
* @param {ve.ui.Surface} surface
* @param {Object} [config] Config options
+ * @cfg {boolean} [editable] Show controls for adding, removing and reordering
items in the outline
*/
ve.ui.PagedDialog = function VeUiPagedDialog( surface, config ) {
+ // Configuration initialization
+ config = config || {};
+
// Parent constructor
ve.ui.Dialog.call( this, surface, config );
// Properties
+ this.editable = !!config.editable;
this.pages = {};
this.currentPageName = null;
};
@@ -51,12 +56,24 @@
[this.outlinePanel, this.pagesPanel], { '$$': this.frame.$$,
'widths': [1, 2] }
);
this.outlineWidget = new ve.ui.OutlineWidget( { '$$': this.frame.$$ } );
+ if ( this.editable ) {
+ this.outlineControlsWidget = new ve.ui.OutlineControlsWidget(
+ this.outlineWidget, { '$$': this.frame.$$ }
+ );
+ }
// Events
this.outlineWidget.connect( this, { 'select': 'onOutlineSelect' } );
// Initialization
- this.outlinePanel.$.append( this.outlineWidget.$ ).addClass(
've-ui-pagedDialog-outlinePanel' );
+ this.outlinePanel.$
+ .addClass( 've-ui-pagedDialog-outlinePanel' )
+ .append( this.outlineWidget.$ );
+ if ( this.editable ) {
+ this.outlinePanel.$
+ .addClass( 've-ui-pagedDialog-outlinePanel-editable' )
+ .append( this.outlineControlsWidget.$ );
+ }
this.pagesPanel.$.addClass( 've-ui-pagedDialog-pagesPanel' );
this.$body.append( this.layout.$ );
};
@@ -84,6 +101,7 @@
* @param {number} [config.level=0] Indentation level
* @param {number} [config.index] Specific index to insert page at
* @param {jQuery} [config.$content] Page content
+ * @param {jQuery} [config.moveable] Allow page to be moved in the outline
* @chainable
*/
ve.ui.PagedDialog.prototype.addPage = function ( name, config ) {
@@ -99,7 +117,8 @@
'$$': this.frame.$$,
'label': config.label || name,
'level': config.level || 0,
- 'icon': config.icon
+ 'icon': config.icon,
+ 'moveable': config.moveable
} )
],
config.index
@@ -169,7 +188,7 @@
* @param {string} name Symbolic name of page
*/
ve.ui.PagedDialog.prototype.setPage = function ( name ) {
- if ( name in this.pages ) {
+ if ( this.pages[name] ) {
this.currentPageName = name;
this.pagesPanel.showItem( this.pages[name] );
this.pages[name].$.find( ':input:first' ).focus();
diff --git a/modules/ve/ui/elements/ve.ui.GroupElement.js
b/modules/ve/ui/elements/ve.ui.GroupElement.js
index 48845f5..fad63e9 100644
--- a/modules/ve/ui/elements/ve.ui.GroupElement.js
+++ b/modules/ve/ui/elements/ve.ui.GroupElement.js
@@ -42,15 +42,20 @@
* @chainable
*/
ve.ui.GroupElement.prototype.addItems = function ( items, index ) {
- var i, len, item,
+ var i, len, item, currentIndex,
$items = $( [] );
for ( i = 0, len = items.length; i < len; i++ ) {
item = items[i];
// Check if item exists then remove it first, effectively
"moving" it
- if ( this.items.indexOf( item ) !== -1 ) {
+ currentIndex = this.items.indexOf( item );
+ if ( currentIndex >= 0 ) {
this.removeItems( [ item ] );
+ // Adjust index to compensate for removal
+ if ( currentIndex < index ) {
+ index--;
+ }
}
// Add the item
$items = $items.add( item.$ );
diff --git a/modules/ve/ui/styles/ve.ui.Dialog.css
b/modules/ve/ui/styles/ve.ui.Dialog.css
index 92bdb85..8c8bf45 100644
--- a/modules/ve/ui/styles/ve.ui.Dialog.css
+++ b/modules/ve/ui/styles/ve.ui.Dialog.css
@@ -120,6 +120,23 @@
border-right: solid 1px #ddd;
}
+.ve-ui-pagedDialog-outlinePanel-editable .ve-ui-outlineWidget {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 3em;
+ overflow-y: auto;
+}
+
+.ve-ui-pagedDialog-outlinePanel .ve-ui-outlineControlsWidget {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ box-shadow: 0 0 0.25em rgba(0,0,0,0.25);
+}
+
.ve-ui-pagedDialog-pagesPanel .ve-ui-panelLayout {
padding: 1.5em;
width: 100%;
diff --git a/modules/ve/ui/styles/ve.ui.Icons-raster.css
b/modules/ve/ui/styles/ve.ui.Icons-raster.css
index 27d9076..9d94bd7 100644
--- a/modules/ve/ui/styles/ve.ui.Icons-raster.css
+++ b/modules/ve/ui/styles/ve.ui.Icons-raster.css
@@ -239,3 +239,13 @@
/* @embed */
background-image: url(images/icons/search-big.png);
}
+
+.ve-ui-icon-expand {
+ /* @embed */
+ background-image: url(images/icons/expand.png);
+}
+
+.ve-ui-icon-collapse {
+ /* @embed */
+ background-image: url(images/icons/collapse.png);
+}
diff --git a/modules/ve/ui/styles/ve.ui.Icons-vector.css
b/modules/ve/ui/styles/ve.ui.Icons-vector.css
index 00dc6e1..17636ec 100644
--- a/modules/ve/ui/styles/ve.ui.Icons-vector.css
+++ b/modules/ve/ui/styles/ve.ui.Icons-vector.css
@@ -239,3 +239,13 @@
/* @embed */
background-image: url(images/icons/search-big.svg);
}
+
+.ve-ui-icon-expand {
+ /* @embed */
+ background-image: url(images/icons/expand.svg);
+}
+
+.ve-ui-icon-collapse {
+ /* @embed */
+ background-image: url(images/icons/collapse.svg);
+}
diff --git a/modules/ve/ui/styles/ve.ui.Widget.css
b/modules/ve/ui/styles/ve.ui.Widget.css
index 33ee614..557c403 100644
--- a/modules/ve/ui/styles/ve.ui.Widget.css
+++ b/modules/ve/ui/styles/ve.ui.Widget.css
@@ -25,6 +25,10 @@
opacity: 1;
}
+.ve-ui-iconButtonWidget.ve-ui-widget-disabled {
+ opacity: 0.2;
+}
+
/* ve.ui.ButtonWidget */
.ve-ui-buttonWidget {
@@ -202,6 +206,26 @@
text-shadow: 0 1px 1px rgba(255,255,255,0.5);
}
+/* ve.ui.OutlineControlsWidget */
+
+.ve-ui-outlineControlsWidget {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ height: 3em;
+ padding: 0.5em;
+ background-color: #fff;
+}
+
+.ve-ui-outlineControlsWidget-addButton {
+ float: left;
+}
+
+.ve-ui-outlineControlsWidget-upButton,
+.ve-ui-outlineControlsWidget-downButton {
+ float: right;
+}
+
/* ve.ui.InputLabelWidget */
.ve-ui-inputLabelWidget {
diff --git a/modules/ve/ui/widgets/ve.ui.OutlineControlsWidget.js
b/modules/ve/ui/widgets/ve.ui.OutlineControlsWidget.js
new file mode 100644
index 0000000..c8b1f16
--- /dev/null
+++ b/modules/ve/ui/widgets/ve.ui.OutlineControlsWidget.js
@@ -0,0 +1,81 @@
+/*!
+ * VisualEditor UserInterface OutlineControlsWidget class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * Creates an ve.ui.OutlineControlsWidget object.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {ve.ui.OutlineWidget} outline Outline to control
+ * @param {Object} [config] Config options
+ */
+ve.ui.OutlineControlsWidget = function VeUiOutlineControlsWidget( outline,
config ) {
+ // Parent constructor
+ ve.ui.Widget.call( this, config );
+
+ // Properties
+ this.outline = outline;
+ this.upButton = new ve.ui.IconButtonWidget( {
+ '$$': this.$$, 'icon': 'collapse', 'title': ve.msg(
'visualeditor-outline-control-move-up' )
+ } );
+ this.downButton = new ve.ui.IconButtonWidget( {
+ '$$': this.$$, 'icon': 'expand', 'title': ve.msg(
'visualeditor-outline-control-move-down' )
+ } );
+
+ // Events
+ outline.connect( this, {
+ 'select': 'onOutlineChange',
+ 'add': 'onOutlineChange',
+ 'remove': 'onOutlineChange'
+ } );
+ this.upButton.connect( this, { 'click': ['emit', 'move', -1] } );
+ this.downButton.connect( this, { 'click': ['emit', 'move', 1] } );
+
+ // Initialization
+ this.$.addClass( 've-ui-outlineControlsWidget' );
+ this.upButton.$.addClass( 've-ui-outlineControlsWidget-upButton' );
+ this.downButton.$.addClass( 've-ui-outlineControlsWidget-downButton' );
+ this.$.append( this.upButton.$, this.downButton.$ );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ui.OutlineControlsWidget, ve.ui.Widget );
+
+/* Events */
+
+/**
+ * @event move
+ * @param {number} places Number of places to move
+ */
+
+/* Methods */
+
+ve.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
+ var i, len, item, firstMoveable, lastMoveable,
+ moveable = false,
+ items = this.outline.getItems(),
+ selectedItem = this.outline.getSelectedItem();
+
+ if ( selectedItem ) {
+ for ( i = 0, len = items.length; i < len; i++ ) {
+ item = items[i];
+ if ( item.isMoveable() ) {
+ if ( item === selectedItem ) {
+ moveable = true;
+ }
+ if ( !firstMoveable ) {
+ firstMoveable = item;
+ }
+ lastMoveable = item;
+ }
+ }
+ }
+ this.upButton.setDisabled( !moveable || selectedItem === firstMoveable
);
+ this.downButton.setDisabled( !moveable || selectedItem === lastMoveable
);
+};
diff --git a/modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
b/modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
index 1eda48b..6ba9a98 100644
--- a/modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
+++ b/modules/ve/ui/widgets/ve.ui.OutlineItemWidget.js
@@ -16,6 +16,7 @@
* @param {Object} [config] Config options
* @cfg {string} [icon] Symbolic name of icon
* @cfg {number} [level] Indentation level
+ * @cfg {boolean} [moveable] Allow modification from outline controls
*/
ve.ui.OutlineItemWidget = function VeUiOutlineItemWidget( data, config ) {
// Config intialization
@@ -26,6 +27,7 @@
// Properties
this.level = 0;
+ this.moveable = !!config.moveable;
// Initialization
this.$.addClass( 've-ui-outlineItemWidget' );
@@ -50,6 +52,17 @@
/* Methods */
/**
+ * Check if item is moveable.
+ *
+ * Moveablilty is used by outline controls.
+ *
+ * @returns {boolean} Item is moveable
+ */
+ve.ui.OutlineItemWidget.prototype.isMoveable = function () {
+ return this.moveable;
+};
+
+/**
* Get indentation level.
*
* @returns {number} Indentation level
diff --git a/modules/ve/ui/widgets/ve.ui.SelectWidget.js
b/modules/ve/ui/widgets/ve.ui.SelectWidget.js
index 52d4ad8..92156a4 100644
--- a/modules/ve/ui/widgets/ve.ui.SelectWidget.js
+++ b/modules/ve/ui/widgets/ve.ui.SelectWidget.js
@@ -56,6 +56,17 @@
* @param {ve.ui.OptionWidget|null} item Selected item or null if no item is
selected
*/
+/**
+ * @event add
+ * @param {ve.ui.OptionWidget[]} items Added items
+ * @param {number|undefined} index Index items were added at
+ */
+
+/**
+ * @event remove
+ * @param {ve.ui.OptionWidget[]} items Removed items
+ */
+
/* Static Properties */
ve.ui.SelectWidget.static.tagName = 'ul';
@@ -347,6 +358,8 @@
}
ve.ui.GroupElement.prototype.addItems.call( this, items, index );
+ this.emit( 'add', items, index );
+
return this;
};
@@ -372,6 +385,8 @@
}
ve.ui.GroupElement.prototype.removeItems.call( this, items );
+ this.emit( 'remove', items );
+
return this;
};
@@ -384,9 +399,13 @@
* @chainable
*/
ve.ui.SelectWidget.prototype.clearItems = function () {
+ var items = this.items.slice();
+
// Clear all items
this.hashes = {};
ve.ui.GroupElement.prototype.clearItems.call( this );
+ this.emit( 'remove', items );
+
return this;
};
--
To view, visit https://gerrit.wikimedia.org/r/68604
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I919d4c3e9b85d07a97a99c0b2e8739a859bdf2b1
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Trevor Parscal <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits