📄 array_sort.js
字号:
/*
* Isomorphic SmartClient
* Version 6.5 (2008-04-30)
* Copyright(c) 1998-2007 Isomorphic Software, Inc. All rights reserved.
* "SmartClient" is a trademark of Isomorphic Software, Inc.
*
* licensing@smartclient.com
*
* http://smartclient.com/license
*/
///////////////////////// Methods for sorting an array easily///////////////////////isc.addProperties(Array, { //> @type SortDirection // @visibility external // @group sorting ASCENDING:true, // @value "ascending" Sort in ascending order (eg: A-Z, larger items later in the list) DESCENDING:false // @value "descending" Sort in descending order (eg: Z-A, larger items earlier in the list) //<});isc.addMethods(Array, {//> @method Array.shouldSortAscending()// Returns the passed in sortDirection (string / boolean) as the appropriate boolean// @group sorting////<shouldSortAscending : function (sortDirection) { if (sortDirection == Array.ASCENDING) return true; if (sortDirection == Array.DESCENDING) return false; if (isc.isA.String(sortDirection)) { if (sortDirection.toLowerCase() == "ascending") return true; if (sortDirection.toLowerCase() == "descending") return false; } // Anything else is invalid - just return null return null;}});// add a bunch of methods to the Array prototype so all arrays can use themisc.addMethods(Array.prototype, {//> @method array.sortByProperty()// @include list.sortByProperty()//<sortByProperty : function (property, direction, normalizer, context) { return this.sortByProperties({property:property, direction:direction, normalizer:normalizer, context:context});}, //> @method array.sortByProperties()// Given an array of objects, sort them by the properties of the member objects.// Note that the sort will occur by the first property passed in, then for objects// with matching values for the first property, the second property will be used (and so on).// Can pass in an arbitary number of parameters.// @param sortData (object) Each parameter is an object of the following format:<br>// <code>{property:'propertyName', direction:direction, normalizer:normalizer}</code><br>// The only the "property" attribute is required. Pass in multiple arguments to sort by multiple// properties.// @return (array) the array itself//<// This method also supports being passed a 'context' parameter. If present, this is passed// into the sort normalizer method as a parameter// Example use case: ListGrids pass themselves into the 'sortBYProperty' method as the context// and are then available to the sort normalizer for the field.// The context, if present, should be passed in as the 'context' attribute of each parameter// object (so we can support 1 context per field name)// In addition to the documented parameter format, sortByProperties will take 4 arrays - an// array of property names, an array of sort directions, an array of normalizers and an array// of 'context' objects.// The normalizer / sortDirection / context for each property is then determined by // the position in the array (so the last 3 arrays are optional and may be sparse)sortByProperties : function () { var normalizedArray = Array._normalizedValues, wrongTypeArray = Array._unexpectedTypeValues; // Support being called with either the signature // (["prop1", "prop2", ...], [dir1, dir2, ...], [norm1, norm2, ...]) // or // ({property:"prop1", direction:dir1, normalizer:norm1}, {property:"prop2", ...},...) if (isc.isAn.Array(arguments[0])) { this.sortProps = arguments[0]; this.sortDirections = arguments[1] || []; this.normalizers = arguments[2] || []; this.contexts = arguments[3] || []; } else { // clear out any sortProps so we don't get additional (old) properties if (!this.sortProps) { this.sortProps = []; this.normalizers = []; this.sortDirections = []; this.contexts = []; } else { this.sortProps.clear(); this.sortDirections.clear(); this.normalizers.clear(); this.contexts.clear(); } for (var i = 0; i < arguments.length; i++) { this.sortProps[i] = arguments[i].property; this.sortDirections[i] = arguments[i].direction; this.normalizers[i] = arguments[i].normalizer; this.contexts[i] = arguments[i].context; } } // local refs var props = this.sortProps, norms = this.normalizers, contexts = this.contexts; for (var i = 0; i < props.length; i++) { // remember the sort directions on the Array object -- retrieved in _compareNormalized Array._sortDirections[i] = this.sortDirections[i]; var property = props[i], normalizer = norms[i], context = contexts[i]; // if not passed an explicit normalizer, choose the appropriate function to normalize data // (see above) var dataType; if (normalizer == null) { dataType = this._getSortDataType(props[i]); // catch the case where we were passed a data type rather than a normalizer function } else if (isc.isA.String(normalizer)) { dataType = normalizer; } if (dataType != null) normalizer = Array._getNormalizerFromType(dataType); //isc.Log.logWarn("For property:"+ property + ", dataType is: " + dataType + // ", normalizer is: " + normalizer); // In the case where we were unable to determine a custom data-type normalizer for the field // fall back on the default object normalizer. if (normalizer == null) normalizer = Array._normalizeObj; // Update the normalizer to point to the function this.normalizers[i] = normalizer; // if the list is empty, nothing to do but remember the sort details so methods such // as add() can reset the sort. if (this.length == 0) continue; // now apply the normalizer to each item, storing the normalized values in a property // where we will look for them later during the native sort() // Set up the array to store the normalized values for this prop in normalizedArray[i] = []; wrongTypeArray[i] = []; if (isc.isA.Function(normalizer)) { for (var ii = 0, l = this.length, item;ii < l;ii++) { item = this[ii]; if (item == null) { continue; } item._tempSortIndex = ii; var normalizedValue = normalizer(item, this.sortProps[i], context); normalizedArray[i][ii] = normalizedValue; // If we're sorting the field according to an explicit data type, store values // not of that type for separate comparison if (dataType != null && !Array._matchesType(item[this.sortProps[i]], dataType)) { wrongTypeArray[i][ii] = item[this.sortProps[i]]; } // a custom normalizer might produce NaN, which is a dangerous because, unlike // any other value, both "1 > NaN" and "1 < NaN" are false, which fools the // comparator into thinking everything is equal to NaN, so the sort order is // scrambled and changes each time, and the reason why isn't obvious to the // developer. Hence normalize NaN to the maximum negative value, like our // built-in numeric normalizer does. var undef; if (isc.isA.SpecialNumber(normalizedValue) && isNaN(normalizedValue)) { normalizedArray[i][ii] = 0-Number.MAX_VALUE; } } //isc.Log.logWarn("function normalizer: normalized values: " + normalizedArray[i] + // ", unexpected types: " + wrongTypeArray[i]); } else { // a non-null, non-dataType, non-function normalizer was passed, assume it's a // propertyValue -> normalizedValue map var normalizerMap = this.normalizers[i]; for (var ii = 0, l = this.length, item; ii < l ;ii++) { item = this[ii]; if (item == null) continue; var sortPropValue = item[this.sortProps[i]]; if (sortPropValue == null) sortPropValue = ''; var normalizedValue = normalizerMap[sortPropValue]; // if the normalizerMap had no normalizedValue for the value of the sortProp, // use the value of the sortProp itself as the normalizedValue if (normalizedValue == null) normalizedValue = sortPropValue; // store the normalized value on the item itself item._tempSortIndex = ii; normalizedArray[i][ii] = normalizedValue; } //isc.Log.logWarn("string normalizer: normalized values: " + normalizedArray[i] + // ", unexpected types: " + wrongTypeArray[i]); } } // END of the for loop // perform the actual sort this.sort(Array._compareNormalized); // If the comparitor funciton hit any nulls, notify the developer if (Array._containsNulls) { isc.Log.logWarn("Attempt to sort array by property hit null entry where a record should be. Array:" + isc.Log.echo(this)); Array._containsNulls = null; } // Clear out the index temporarily stored on each item, and empty the temp arrays of // sort values / directions this.clearProperty("_tempSortIndex"); normalizedArray.clear(); wrongTypeArray.clear(); Array._sortDirections.clear(); // call dataChanged in case anyone is observing it this.dataChanged(); return this;}, //> @method array.unsort() (A)// Turn sorting off for this array, indicating that the current sort// order should be preserved. Return true if this is supported in thist List.//// Some implementations may not support this -- they should return false// to indicate to the caller that sort order must be maintained (eg: in// the case where sort order is dervied from the server, etc).//// @group sorting//// @return (boolean) true == list supports unsorting, false == not supported.// @visibility external//<unsort : function () { if (this.sortProps) this.sortProps.clear(); return true;},// _getSortDataType() - given a field to sort this Array's member objects by, this method
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -