📄 array_sort.js
字号:
// returns the data type to treat these field values as. Used to determine the appropriate// normalizer function for the values.// Note that a "normalizer" function renders a variable in a standardized format// so we can sort by it easily. For example, dates are converted into msec, etc._getSortDataType : function (sortProp, value) { var list = (value != null ? (isc.isAn.Array(value) ? value : [value]) : this); // determine the type WRT sorting based on the type of the first non null value for (var i = 0; i < list.length; i++) { if (!isc.isAn.Object(list[i])) continue; value = list[i][sortProp]; // skip null entries if (value == null) continue; var type = Array._getType(value); if (type != null) return type; } return null;},// _getNormalizer() - method to give us a normalizer based on the data for the// appropriate field within this Array's member objects._getNormalizer : function (sortProp, value) { var type = this._getSortDataType(sortProp, value); var normalizer = Array._getNormalizerFromType(type); return normalizer || Array._normalizeObj;}, //> @method array.normalize() (A)// @group sorting// Normalize a property of an object based on the normalizer for this array // or the type of the property if that's this.normalizer is not set//// @return (any) normalized value //<normalize : function (obj, property) { var normalizer = (this.normalizer ? this.normalizer : this._getNormalizer(property, obj)); return normalizer(obj,property);} }); // END isc.addMethods(Array.prototype)// add static sort routines and variables to the Array objectisc.addProperties(Array,{ _SORT_TEMP : "__sort_temp", // name of the temporary variable to use as sort criteria _UNEXPECTED_TYPE : "__unexpected_type" // Used by sortByProperty when a value doesn't match // the field's expected data type});isc.addMethods(Array, {//> @method array._normalize()// @group sorting// Normalize one field into another for sorting// obj = object to normalize// property = property to normalize//// @param obj (object) object to normalize// @param property (string) name of the property of object to normalize//<_normalizeObj : function (obj, property) { return obj[property];},_normalizeStr : function (obj, property) { return (isc.isA.String(obj[property]) ? obj[property].toLowerCase() : isc.emptyString); },_normalizeNum : function (obj, property) { var val = obj[property]; // put non-numbers at the beginning of the sort return isc.isA.Number(val) ? val : (0-Number.MAX_VALUE);},_normalizeBool : function (obj, property) { var val = obj[property]; if (val == true) return 1; if (val == false) return 0; if (val == null) return -1; return -2;},_normalizeDate : function (obj, property) { var time = (obj[property] && isc.isA.Date(obj[property]) ? obj[property].getTime() : new Date(obj[property]).getTime()) // NOTE: "new Date([bad date])" creates a special invalidate date object for which // getTime() returns NaN in both Moz and IE. // Replace with zero to reliably sort at the top of ascending sort (or end of descending // sort). // NOTE: return the earliest valid date, not 0, which would be epoch time start (Jan 1 // 1970), which would sort into the middle of some sets of dates. if (isNaN(time)) return -8640000000000000; return time; },_normalizeTime : function (obj, property) { var val = obj[property]; if (!isc.isA.Date(val) && val != null) val = isc.Time.parseInput(val); if (isc.isA.Date(val)) return val.getTime(); return 0;},// Normalizer for sorting data of type string numericallytextToNumericNormalizer : function (obj, property) { var value = parseInt(obj[property], 10); if (isc.isA.Number(value)) return value; else return 0;},// Given a known data type - what is the appropriate sort-normalizer?_$string:"string", _$text:"text", _$number:"number", _$integer:"integer", _$float:"float", _$int:"int", _$boolean:"boolean", _$Date_ : "Date", _$Time:"Time",_$date : "date", _$time:"time",_getNormalizerFromType : function (type) { if (!type || !isc.isA.String(type)) return null; switch (type) { case this._$string: case this._$text: return Array._normalizeStr; case this._$boolean: return Array._normalizeBool; case this._$Date_: case this._$date: return Array._normalizeDate; case this._$Time: case this._$time: return Array._normalizeTime; case this._$number: case this._$integer: case this._$int: case this._$float: return Array._normalizeNum; } return Array._normalizObj;},// _getType() - returns the "type" name of an object for sorting normalization purposes_$object:"object",_getType : function (object) { var type = typeof object; if (type == this._$object) { if (isc.isA.Date(object)) type = this._$date; } return type;},// _matchesType() - helper method used by sortByProperty to catch unexpected type values// Note the 'type' specified for a field (like "float") may not match the value returned by// this._getType(object) - so we have to detect equivalent types, (like float and number)_standardTypeMap:{ "float":"number", "int:":"number", "integer":"number", "text":"string", "Date":"date", "Time":"date", "time":"date"},_matchesType : function (object, type) { var objectType = this._getType(object); if (objectType == type) return true; return (this._standardTypeMap[type] == objectType);},// Central array for temp storage of normalized values for sorting_normalizedValues:[],_unexpectedTypeValues:[],_sortDirections:[],// Comparitor function for sorting by property - uses already stored out normalized values and// sort-directions_compareNormalized : function (a,b) { // If any nulls were detected during the sort notify the developer if (a == null || b == null) { this._containsNulls = true; } var normalizedValues = Array._normalizedValues, unexpectedTypes = Array._unexpectedTypeValues, directions = Array._sortDirections, // For null values we'll always compare 'null' regardless of the field property aIndex = (a != null ? a._tempSortIndex : null), bIndex = (b != null ? b._tempSortIndex : null); for (var i = 0; i < normalizedValues.length; i++) { var aFieldValue = (aIndex != null ? normalizedValues[i][aIndex] : null), bFieldValue = (bIndex != null ? normalizedValues[i][bIndex] : null); // if both values were not the expected type, compare them directly in un-normalized // form. Note if only one value was unexpected type, by comparing normalized values we // will sort values of unexpected type to one end, since the standard normalizers all // normalize unexpected type values to the lowest values in the type's range. if (aFieldValue != null && bFieldValue != null) { var aWrongType = unexpectedTypes[i][aIndex], bWrongType = unexpectedTypes[i][bIndex]; if (aWrongType != null && bWrongType != null) { aFieldValue = aWrongType; bFieldValue = bWrongType; } } var returnVal = (directions[i] ? Array.compareAscending(aFieldValue, bFieldValue) : Array.compareDescending(aFieldValue, bFieldValue)); //isc.Log.logWarn("compared: " + isc.Log.echo(aFieldValue) + " to " + // isc.Log.echo(bFieldValue) + ", returning: " + returnVal); // If we have a non-equal result, return it, otherwise we'll check the next property // in array.sortProps if (returnVal != 0) return returnVal; } // at this point we've gone through every field in the sort, and these 2 items match in // each case -- just return 0 to indicate no order pref. return 0; },//> @classMethod Array.compareAscending() (A)// Compare two values for an ascending order sort, using locale-sensitive comparison.// @group sorting//// @param a (any) first value to compare// @param b (any) second value to compare//// @return (number) negative == second is larger, 0 == same value, positive == first is larger // @visibility external//<compareAscending : function (first, second) { if (first != null && first.localeCompare != null) { var lc = first.localeCompare(second); if (this.adjustLocaleCompare()) lc -= 2; return lc; } if (second != null && second.localeCompare != null) { var lc = second.localeCompare(first); if (this.adjustLocaleCompare()) lc -= 2; return lc; } return (second > first ? -1 : second < first ? 1 : 0);},//> @classMethod Array.compareDescending() (A)// Compare two values for a descending order sort, using locale-sensitive comparison.// @group sorting//// @param first (any) first value to compare// @param second (any) second value to compare//// @return (number) negative == first is larger, 0 == same value, positive == second is larger // @visibility external//<compareDescending : function (first, second) { if (first != null && first.localeCompare != null) { var lc = first.localeCompare(second); if (this.adjustLocaleCompare()) lc -= 2; return -1 * lc } if (second != null && second.localeCompare != null) { var lc = second.localeCompare(first); if (this.adjustLocaleCompare()) lc -= 2; return -1 * lc; } return (second < first ? -1 : second > first ? 1 : 0);},adjustLocaleCompare : function () { if (!isc.Browser.isSafari) return false; if (Array._mustAdjustNativeLocaleCompare == null) { var b = "b"; Array._mustAdjustNativeLocaleCompare = (b.localeCompare("a") == 3); } return Array._mustAdjustNativeLocaleCompare;}});
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -