📄 list.js
字号:
//<duplicate : function () { return this.newInstance().addList(this);},// --------------------------------------------------------------------------------------------// Modification Interface// --------------------------------------------------------------------------------------------// Basics that must be implemented// --------------------------------------------------------------------------------------------//> @method list.set()// Change the array element at a particular position.// <P>// set() can be used to expand the length of the list.//// @group modification// @param pos (number) position in the list to change// @param obj (object) new value for that position//// @return (object) whatever's at that position, null if not found // @visibility external//<// expected to be implemented by target//> @method list.addAt()// Add a single item to this array at a specific position in the list, sliding other items over// to fit.//// @group modification// @param obj (object) object to add// @param pos (number) position in the list to add at//// @return (object) object that was added // @visibility external//<// expected to be implemented by target//> @method list.removeAt()// Remove the item at the specified position, rearranging all subsequent items to fill the gap//// @group modification// @param pos (number) position to remove//// @return (any) item that was removed// @visibility external//<// expected to be implemented by target// Implementable in terms of basics// --------------------------------------------------------------------------------------------//> @method list.add()// Add an object to this list, at the end//// @group modification// @param object (any) object to add//// @return (any) pointer to the object passed in // @visibility external//<// As implemented below, if no position is specified, the object will be added to the end of// the list.// Note that array.add will attempt to preserve sort order if it is currently sorted when// add() is called with no explicit position param.add : function (object, secondArg) { var undefined; if (secondArg !== undefined) { // support calling as add(object, index) return this.addAt(object, secondArg); } this.addAt(object, this.getLength()); // return the object that was added return object;},//> @method list.addList()// Add a list of items to this array.// <P>// Note: you can specify that a subset range be added by passing start and end indices//// @group modification// @param list (array) list of items to add// @param [listStartRow] (number) optional start index in list// @param [listEndRow] (number) optional end index in list (non-inclusive)//// @return (list) list of items that were added// @visibility external//<// [stolen from Array]// Below might need custom implementations for performance// --------------------------------------------------------------------------------------------//> @method list.setLength()// Set the length of this list.// <P>// If the length of the list is shortened, any elements past the new length of the list are removed.// If the length is increased, all positions past the old length have the value// <code>undefined</code>.//// @group modification// @param length (number) new length// @visibility external//<setLength : function (length) { this._startChangingData(); if (length > this.getLength()) { // pad the list with empty slots var undefined; while (length > this.getLength()) this.add(undefined); } else { // remove everything beyond the specified length while (length < this.getLength()) this.removeAt(this.getLength()-1); } this._doneChangingData();},// Below methods need to shift indices of all existing items// --------------------------------------------------------------------------------------------//> @method list.addListAt()// Add list of items list to this array at item pos. All items after array[pos] will slide down to// fit new items.//// @group modification// @param list (array) new array of items// @param pos (number) position in this list to put the new items//// @return (array) the list of items that was added// @visibility external//<addListAt : function (list, pos) { this._startChangingData(); var length = list.getLength(); for (var i = 0; i < length; i++) { this.addAt(list.get(i), pos+i); } this._doneChangingData(); // return the list that was added return list;}, //> @method list.remove()// Remove first instance of the passed object from this array, sliding other items around to// fill gaps.//// @group modification// @param obj (any) item to remove//// @return (boolean) true if a matching object was found and removed, false if no matching// object was found and the list remains unchanged.// @visibility external//<remove : function (obj) { // return removed item, per java.util.List // if (isc.isA.Number(obj)) return this.removeAt(obj); var index = this.indexOf(obj); if (index == -1) return false; this._startChangingData(); var length = this.getLength(); for (var i = index; i < length; i++) this.set(i, this.get(i+1)); this.setLength(length-1); this._doneChangingData(); return true; // indicating object was removed, per java.util.Collection}, //> @method list.removeList()// Remove all instances of objects in the specified list from this list, sliding the remaining// objects around to fill gaps.//// @group modification// @param list (array) list of items to remove//// @return (list) list of items passed in// @visibility external//<removeList : function (removeList) { if (removeList == null) return null; // get ready to change data... this._startChangingData(); var changed = false; for (var i = 0; i < this.getLength(); i++) { var item = this.get(i); // remove the current item and stay at the same position in the list if (removeList.contains(item)) { changed = true; this.removeAt(i); i--; } } this._doneChangingData(); // return whether the list was changed return removeList;}, //> @method list.sort()// Sorts the elements of the List in place.// <P>// The optional comparator function should take two parameters "a" and "b" which are the two list// items to compare, and should return:// <ul>// <li> a value less than zero, if "a" is less than "b" such that "a" should appear earlier in the// list// <li> zero, if "a" and "b" are equal// <li> a value greater than zero, if "a" is greater than "b" such that "b" should appear earlier in// the list// </ul>// // @param [comparator] (function) comparator function to use// @return (List) the list itself// @visibility external//<sort : function (comparator) { // dump all the items to a native Array and sort them var items = this.getRange(0, this.getLength()); items.sort(comparator); // then set every slot in the current List for (var i = 0; i < items.length; i++) this.set(i, items[i]); return this;},//> @method list.sortByProperty()// Sort a list of objects by a given property of each item.// <P>// The optional normalizer, if passed as a function, is called for each item in the List, and// should return whatever value should be used for sorting, which does not have to agree with// the property value. By passing a normalizer function you can achieve any kind of sorting// you'd like, including sorting by multiple properties.// <P>// NOTE: string sort is case INsensitive by default//// @group sorting//// @param property (string) name of the property to sort by// @param up (boolean) true == sort ascending, false == sort descending// @param [normalizer] (function or ValueMap) // May be specified as a function, with signature // <code>normalize(item, propertyName, context)</code>, where <code>item</code> is// a pointer to the item in the array, <code>propertyName</code> is the // property by which the array is being sorted, and <code>context</code> is the// arbitrary context passed into this method. Normalizer function should return// the value normalized for sorting.<br>// May also be specified as a ValueMap which maps property values to sortable values.// @param [context] (any) Callers may pass an arbitrary context into the sort method, which// will then be made available to the normalizer function// @return (List) the list itself//// @visibility external//<sortByProperty : function (property, direction, normalizer, context) { // dump all the items to a native Array and sort them var items = this.getRange(0, this.getLength()); items.sortByProperty(property, direction, normalizer, context); // then set every slot in the current List for (var i = 0; i < items.length; i++) this.set(i, items[i]); return this;},//> @method list.getValueMap()// Get a map of the form <code>{ item[idField] -> item[displayField] }</code>, for all // items in the list. Note that if more than one item has the same <code>idProperty</code>, // the value for the later item in the list will clobber the value for the earlier item.//// @param idField (string) Property to use as ID (data value) in the valueMap// @param displayField (string) Property to use a display value in the valueMap// @return (object) valueMap object// @visibility external//<// imported as part of isc._stealArrayMethods // DataChanged notification// --------------------------------------------------------------------------------------------//> @method list.dataChanged() (A)// Method called when this array changes in some way. Observe the method to react to changes in// this list.// <P>// Note: dataChanged() will only fire when items are added, removed or rearranged. If a list// contains objects, dataChanged() will not fire if changes are made to objects within the list// without changing their position within the list. If an observer of dataChanged() needs to react// to such a change, you can manually fire dataChanged() by simply calling it.// <P>// Note: may be called multiple times as the result of a multi-item add or remove, etc.//// @group modification// @visibility external//<dataChanged : function () {}//> @method list._startChangingData() (A)// Internal method to indicate that data will be changed within the context of a function.// Each occurance of a call to this method should be matched with an occurance of// _doneChangingData() -- when they balance, the public dataChanged() method will be called// exactly once. This lets observers of the dataChanged() method only get called once for// a set of changes.// // For example, clearRange() calls clearItem() repeatedly; we don't want each of // these "nested" calls to clearItem to generate a dataChanged message,// (we only want one when clearRange is done). However, clearItem() when called by// itself (outside of any higher-level operation) *should* call dataChanged when it// is done.////<// [stolen from Array]//> @method list._doneChangingData() (A)// Internal method to indicate that we're done changing data in the current scope.// See list._startChangingData()//<// [stolen from Array]});// steal methods from Array isc._stealArrayMethods = function () { var methodList = [ // methods that are implemented using only the List API on Array (because // performance difference doesn't matter) "isEmpty", "contains", "containsAll", "intersect", "equals", "getItems", "addList", "getValueMap", "removeEvery", "_startChangingData", "_doneChangingData", "_isChangingData", // old ISC backcompat "getItem", "setItem", "removeItem", "clearAll", // find "find", "findIndex", "findNextMatch", "findAllMatches", "findByKeys", // Java.util.List compat "size", "subList", "addAll", "removeAll", "clear"]; // NOTE: applyMask won't work here, since the input is an Array instance, which is // ambiguous with passing an Array full of objects to mask. var methods = {}; for (var i = 0; i < methodList.length; i++) { var methodName = methodList[i]; methods[methodName] = Array.prototype[methodName]; } isc.List.addInterfaceMethods(methods);}isc._stealArrayMethods();// Override isA.List to return true for arrays as well as lists// we have to do this here after the List interface has been defined...isc.addMethods(isc.isA, {//> @classMethod isA.List()// Does <code>object</code> implement the <code>List</code> interface?// @param object (object) object to test// @return (boolean) <code>true</code> if the object is an Array or belongs to another class that// implements the <code>List</code> API.// @visibility external//<_$List:"List",List : function (object) { if (object == null) return false; if (isc.isA.Array(object)) return true; // standard implementation for objects inheriting from interfaces/classes return object.isA && object.isA(this._$List);}});
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -