Jforrester has uploaded a new change for review.
https://gerrit.wikimedia.org/r/306307
Change subject: Have GroupElement use OO.EmitterList
......................................................................
Have GroupElement use OO.EmitterList
The new OO.EmitterList covers the functionality of the
GroupElement mixin.
[Re-applied.]
Bug: T114707
Change-Id: Ib2b287b2f078c2f19d98fe55642fe05c38da20cc
---
M src/mixins/GroupElement.js
1 file changed, 74 insertions(+), 165 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/07/306307/1
diff --git a/src/mixins/GroupElement.js b/src/mixins/GroupElement.js
index 49908d4..d07bb35 100644
--- a/src/mixins/GroupElement.js
+++ b/src/mixins/GroupElement.js
@@ -8,6 +8,7 @@
*
* @abstract
* @class
+ * @mixins OO.EmitterList
*
* @constructor
* @param {Object} [config] Configuration options
@@ -18,14 +19,17 @@
// Configuration initialization
config = config || {};
+ // Mixin constructors
+ OO.EmitterList.call( this );
+
// Properties
this.$group = null;
- this.items = [];
- this.aggregateItemEvents = {};
// Initialization
this.setGroupElement( config.$group || $( '<div>' ) );
};
+
+OO.mixinClass( OO.ui.mixin.GroupElement, OO.EmitterList );
/* Events */
@@ -53,28 +57,6 @@
for ( i = 0, len = this.items.length; i < len; i++ ) {
this.$group.append( this.items[ i ].$element );
}
-};
-
-/**
- * Check if a group contains no items.
- *
- * @return {boolean} Group is empty
- */
-OO.ui.mixin.GroupElement.prototype.isEmpty = function () {
- return !this.items.length;
-};
-
-/**
- * Get all items in the group.
- *
- * The method returns an array of item references (e.g., [button1, button2,
button3]) and is useful
- * when synchronizing groups of items, or whenever the references are required
(e.g., when removing items
- * from a group).
- *
- * @return {OO.ui.Element[]} An array of items.
- */
-OO.ui.mixin.GroupElement.prototype.getItems = function () {
- return this.items.slice( 0 );
};
/**
@@ -124,177 +106,104 @@
};
/**
- * Aggregate the events emitted by the group.
- *
- * When events are aggregated, the group will listen to all contained items
for the event,
- * and then emit the event under a new name. The new event will contain an
additional leading
- * parameter containing the item that emitted the original event. Other
arguments emitted from
- * the original event are passed through.
- *
- * @param {Object.<string,string|null>} events An object keyed by the name of
the event that should be
- * aggregated (e.g., ‘click’) and the value of the new name to use (e.g.,
‘groupClick’).
- * A `null` value will remove aggregated events.
-
- * @throws {Error} An error is thrown if aggregation already exists.
- */
-OO.ui.mixin.GroupElement.prototype.aggregate = function ( events ) {
- var i, len, item, add, remove, itemEvent, groupEvent;
-
- for ( itemEvent in events ) {
- groupEvent = events[ itemEvent ];
-
- // Remove existing aggregated event
- if ( Object.prototype.hasOwnProperty.call(
this.aggregateItemEvents, itemEvent ) ) {
- // Don't allow duplicate aggregations
- if ( groupEvent ) {
- throw new Error( 'Duplicate item event
aggregation for ' + itemEvent );
- }
- // Remove event aggregation from existing items
- for ( i = 0, len = this.items.length; i < len; i++ ) {
- item = this.items[ i ];
- if ( item.connect && item.disconnect ) {
- remove = {};
- remove[ itemEvent ] = [ 'emit',
this.aggregateItemEvents[ itemEvent ], item ];
- item.disconnect( this, remove );
- }
- }
- // Prevent future items from aggregating event
- delete this.aggregateItemEvents[ itemEvent ];
- }
-
- // Add new aggregate event
- if ( groupEvent ) {
- // Make future items aggregate event
- this.aggregateItemEvents[ itemEvent ] = groupEvent;
- // Add event aggregation to existing items
- for ( i = 0, len = this.items.length; i < len; i++ ) {
- item = this.items[ i ];
- if ( item.connect && item.disconnect ) {
- add = {};
- add[ itemEvent ] = [ 'emit',
groupEvent, item ];
- item.connect( this, add );
- }
- }
- }
- }
-};
-
-/**
- * Add items to the group.
- *
- * Items will be added to the end of the group array unless the optional
`index` parameter specifies
- * a different insertion point. Adding an existing item will move it to the
end of the array or the point specified by the `index`.
- *
- * @param {OO.ui.Element[]} items An array of items to add to the group
- * @param {number} [index] Index of the insertion point
- * @chainable
+ * @inheritdoc
*/
OO.ui.mixin.GroupElement.prototype.addItems = function ( items, index ) {
- var i, len, item, itemEvent, events, currentIndex,
- itemElements = [];
+ // Mixin method
+ OO.EmitterList.prototype.addItems.call( this, items, index );
- for ( i = 0, len = items.length; i < len; i++ ) {
- item = items[ i ];
-
- // Check if item exists then remove it first, effectively
"moving" it
- currentIndex = this.items.indexOf( item );
- if ( currentIndex >= 0 ) {
- this.removeItems( [ item ] );
- // Adjust index to compensate for removal
- if ( currentIndex < index ) {
- index--;
- }
- }
- // Add the item
- if ( item.connect && item.disconnect && !$.isEmptyObject(
this.aggregateItemEvents ) ) {
- events = {};
- for ( itemEvent in this.aggregateItemEvents ) {
- events[ itemEvent ] = [ 'emit',
this.aggregateItemEvents[ itemEvent ], item ];
- }
- item.connect( this, events );
- }
- item.setElementGroup( this );
- itemElements.push( item.$element.get( 0 ) );
- }
-
- if ( index === undefined || index < 0 || index >= this.items.length ) {
- this.$group.append( itemElements );
- this.items.push.apply( this.items, items );
- } else if ( index === 0 ) {
- this.$group.prepend( itemElements );
- this.items.unshift.apply( this.items, items );
- } else {
- this.items[ index ].$element.before( itemElements );
- this.items.splice.apply( this.items, [ index, 0 ].concat( items
) );
- }
-
+ // Event
this.emit( 'change', this.getItems() );
+
return this;
};
/**
- * Remove the specified items from a group.
+ * @inheritdoc
+ */
+OO.ui.mixin.GroupElement.prototype.moveItem = function ( item, newIndex ) {
+ // Get the normalized index for the move by calling the parent
+ var index = OO.EmitterList.prototype.insertItem.call( this, item,
newIndex );
+
+ this.attachElementToDom( item, index );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.mixin.GroupElement.prototype.insertItem = function ( item, index ) {
+ // Get the normalized index for the move by calling the parent
+ index = OO.EmitterList.prototype.insertItem.call( this, item, index );
+
+ item.setElementGroup( this );
+ this.attachElementToDom( item, index );
+
+ return index;
+};
+
+/**
+ * Attach the item element into the DOM in its proper place.
*
- * Removed items are detached (not removed) from the DOM so that they may be
reused.
- * To remove all items from a group, you may wish to use the #clearItems
method instead.
- *
- * @param {OO.ui.Element[]} items An array of items to remove
- * @chainable
+ * @private
+ * @param {OO.EventEmitter} item Item
+ * @param {number} index Insertion index
+ */
+OO.ui.mixin.GroupElement.prototype.attachElementToDom = function ( item, index
) {
+ if ( index === undefined || index < 0 || index >= this.items.length - 1
) {
+ this.$group.append( item.$element.get( 0 ) );
+ } else {
+ this.items[ index + 1 ].$element.before( item.$element.get( 0 )
);
+ }
+};
+
+/**
+ * @inheritdoc
*/
OO.ui.mixin.GroupElement.prototype.removeItems = function ( items ) {
- var i, len, item, index, events, itemEvent;
+ var i, item, index;
- // Remove specific items
- for ( i = 0, len = items.length; i < len; i++ ) {
- item = items[ i ];
- index = this.items.indexOf( item );
- if ( index !== -1 ) {
- if ( item.connect && item.disconnect &&
!$.isEmptyObject( this.aggregateItemEvents ) ) {
- events = {};
- for ( itemEvent in this.aggregateItemEvents ) {
- events[ itemEvent ] = [ 'emit',
this.aggregateItemEvents[ itemEvent ], item ];
- }
- item.disconnect( this, events );
+ if ( !Array.isArray( items ) ) {
+ items = [ items ];
+ }
+
+ if ( items.length > 0 ) {
+ // Remove specific items
+ for ( i = 0; i < items.length; i++ ) {
+ item = items[ i ];
+ index = this.items.indexOf( item );
+ if ( index !== -1 ) {
+ item.setElementGroup( null );
+ item.$element.detach();
}
- item.setElementGroup( null );
- this.items.splice( index, 1 );
- item.$element.detach();
}
}
+ // Mixin method
+ OO.EmitterList.prototype.removeItems.call( this, items );
+
+ // Event
this.emit( 'change', this.getItems() );
+
return this;
};
/**
- * Clear all items from the group.
- *
- * Cleared items are detached from the DOM, not removed, so that they may be
reused.
- * To remove only a subset of items from a group, use the #removeItems method.
- *
- * @chainable
+ * @inheritdoc
*/
OO.ui.mixin.GroupElement.prototype.clearItems = function () {
- var i, len, item, remove, itemEvent;
+ var i, len, item;
- // Remove all items
for ( i = 0, len = this.items.length; i < len; i++ ) {
item = this.items[ i ];
- if (
- item.connect && item.disconnect &&
- !$.isEmptyObject( this.aggregateItemEvents )
- ) {
- remove = {};
- if ( Object.prototype.hasOwnProperty.call(
this.aggregateItemEvents, itemEvent ) ) {
- remove[ itemEvent ] = [ 'emit',
this.aggregateItemEvents[ itemEvent ], item ];
- }
- item.disconnect( this, remove );
- }
item.setElementGroup( null );
item.$element.detach();
}
+ // Mixin method
+ OO.EmitterList.prototype.clearItems.call( this );
+
+ // Event
this.emit( 'change', this.getItems() );
- this.items = [];
+
return this;
};
--
To view, visit https://gerrit.wikimedia.org/r/306307
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib2b287b2f078c2f19d98fe55642fe05c38da20cc
Gerrit-PatchSet: 1
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Jforrester <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits