Mooeypoo has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/243068

Change subject: [wip] Add an OO.List object
......................................................................

[wip] Add an OO.List object

Upstream ooui's GroupElement into a stripped-down OO.List that
handles a group of items and their events.

Change-Id: Ib94e4e4a49011736b3027239e6836343901a9022
---
A src/List.js
1 file changed, 246 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/oojs/core refs/changes/68/243068/1

diff --git a/src/List.js b/src/List.js
new file mode 100644
index 0000000..5224a7f
--- /dev/null
+++ b/src/List.js
@@ -0,0 +1,246 @@
+( function () {
+
+       /**
+        * @class OO.List
+        * @mixin
+        * Contains and manages a list of OO.EventEmitter items.
+        *
+        * @constructor
+        */
+       oo.List = function OoList() {
+               this.items = [];
+               this.aggregateItemEvents = {};
+       };
+
+       /* Events */
+
+       /**
+        * @event add Items have been added
+        * @param {OO.EventEmitter[]} items Added items
+        * @param {number} index Index items were added at
+        */
+
+       /**
+        * @event remove Items have been removed
+        * @param {OO.EventEmitter[]} items Removed items
+        */
+
+       /* Methods */
+
+       /**
+        * Get all items
+        *
+        * @return {OO.EventEmitter[]} Items in the list
+        */
+       oo.List.prototype.getItems = function () {
+               return this.items.slice( 0 );
+       };
+
+       /**
+        * Get the index of a specific item
+        *
+        * @param {OO.EventEmitter} item Requested item
+        * @return {number} Index of the item
+        */
+       oo.List.prototype.getItemIndex = function ( item ) {
+               return this.items.indexOf( item );
+       };
+
+       /**
+        * Get number of items
+        *
+        * @return {number} Number of items in the list
+        */
+       oo.List.prototype.getItemCount = function () {
+               return this.items.length;
+       };
+
+       /**
+        * Check if a list contains no items.
+        *
+        * @return {boolean} Group is empty
+        */
+       oo.List.prototype.isEmpty = function () {
+               return !this.items.length;
+       };
+
+       /**
+        * 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.List.prototype.aggregate = function ( events ) {
+               var i, 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; i < this.items.length; 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; i < this.items.length; i++ ) {
+                                       item = this.items[ i ];
+                                       if ( item.connect && item.disconnect ) {
+                                               add = {};
+                                               add[ itemEvent ] = [ 'emit', 
groupEvent, item ];
+                                               item.connect( this, add );
+                                       }
+                               }
+                       }
+               }
+       };
+
+       /**
+        * Add items
+        *
+        * @param {OO.EventEmitter[]} items Items to add
+        * @param {number} index Index to add items at
+        * @chainable
+        * @fires add
+        */
+       oo.List.prototype.addItems = function ( items, index ) {
+               var i, item, event, events, currentIndex, existingItem, at;
+
+               if ( items.length === 0 ) {
+                       return this;
+               }
+
+               // Support adding existing items at new locations
+               for ( i = 0; i < items.length; i++ ) {
+                       item = items[ i ];
+                       existingItem = this.getItemById( item.getId() );
+
+                       // Check if item exists then remove it first, 
effectively "moving" it
+                       currentIndex = this.items.indexOf( existingItem );
+                       if ( currentIndex >= 0 ) {
+                               this.removeItems( [ existingItem ] );
+                               // Adjust index to compensate for removal
+                               if ( currentIndex < index ) {
+                                       index--;
+                               }
+                       }
+
+                       // Add the item
+                       if ( item.connect && item.disconnect ) {
+                               events = {};
+                               for ( event in this.aggregateItemEvents ) {
+                                       events[ event ] = [ 'emit', 
this.aggregateItemEvents[ event ], item ];
+                               }
+                               item.connect( this, events );
+                       }
+               }
+               if ( index === undefined || index < 0 || index >= 
this.items.length ) {
+                       at = this.items.length;
+               } else {
+                       at = index;
+               }
+
+               this.items.splice.apply( this.items, [ at, 0 ].concat( items ) 
);
+
+               // if ( index === undefined || index < 0 || index >= 
this.items.length ) {
+               //      at = this.items.length;
+               //      this.items.push.apply( this.items, items );
+               // } else if ( index === 0 ) {
+               //      at = 0;
+               //      this.items.unshift.apply( this.items, items );
+               // } else {
+               //      at = index;
+               //      this.items.splice.apply( this.items, [ index, 0 
].concat( items ) );
+               // }
+               this.emit( 'add', items, at );
+
+               return this;
+       };
+
+       /**
+        * Remove items
+        *
+        * @param {OO.EventEmitter[]} items Items to remove
+        * @chainable
+        * @fires remove
+        */
+       oo.List.prototype.removeItems = function ( items ) {
+               var i, item, index, remove, itemEvent,
+                       removed = [];
+
+               if ( items.length === 0 ) {
+                       return this;
+               }
+
+               // Remove specific items
+               for ( i = 0; i < items.length; i++ ) {
+                       item = items[ i ];
+                       index = this.items.indexOf( item );
+                       if ( index !== -1 ) {
+                               if ( item.connect && item.disconnect ) {
+                                       remove = {};
+                                       if ( 
Object.prototype.hasOwnProperty.call( this.aggregateItemEvents, itemEvent ) ) {
+                                               remove[ itemEvent ] = [ 'emit', 
this.aggregateItemEvents[ itemEvent ], item ];
+                                       }
+                                       item.disconnect( this, remove );
+                               }
+                               this.items.splice( index, 1 );
+                       }
+               }
+               this.emit( 'remove', removed );
+
+               return this;
+       };
+
+       /**
+        * Clear all items
+        *
+        * @fires clear
+        */
+       oo.List.prototype.clearItems = function () {
+               var i, item, remove, itemEvent,
+                       items = this.items.splice( 0, this.items.length );
+
+               // Remove all items
+               for ( i = 0; i < items.length; i++ ) {
+                       item = items[ i ];
+                       if ( item.connect && item.disconnect ) {
+                               remove = {};
+                               if ( Object.prototype.hasOwnProperty.call( 
this.aggregateItemEvents, itemEvent ) ) {
+                                       remove[ itemEvent ] = [ 'emit', 
this.aggregateItemEvents[ itemEvent ], item ];
+                               }
+                               item.disconnect( this, remove );
+                       }
+               }
+
+               this.emit( 'clear' );
+
+               return this;
+       };
+
+}() );

-- 
To view, visit https://gerrit.wikimedia.org/r/243068
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib94e4e4a49011736b3027239e6836343901a9022
Gerrit-PatchSet: 1
Gerrit-Project: oojs/core
Gerrit-Branch: master
Gerrit-Owner: Mooeypoo <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to