| 1 | efrain | 1 | YUI.add('arraysort', function (Y, NAME) {
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | /*jshint expr:true, onevar:false */
 | 
        
           |  |  | 4 |   | 
        
           |  |  | 5 | /**
 | 
        
           |  |  | 6 | Provides comparator functions useful for sorting arrays.
 | 
        
           |  |  | 7 |   | 
        
           |  |  | 8 | @module arraysort
 | 
        
           |  |  | 9 | **/
 | 
        
           |  |  | 10 |   | 
        
           |  |  | 11 | var LANG = Y.Lang,
 | 
        
           |  |  | 12 |     ISVALUE = LANG.isValue,
 | 
        
           |  |  | 13 |     ISSTRING = LANG.isString;
 | 
        
           |  |  | 14 |   | 
        
           |  |  | 15 | /**
 | 
        
           |  |  | 16 | Provides comparator functions useful for sorting arrays.
 | 
        
           |  |  | 17 |   | 
        
           |  |  | 18 | @class ArraySort
 | 
        
           |  |  | 19 | @static
 | 
        
           |  |  | 20 | **/
 | 
        
           |  |  | 21 |   | 
        
           |  |  | 22 | var ArraySort = Y.ArraySort = {
 | 
        
           |  |  | 23 |     // -- Public Methods -------------------------------------------------------
 | 
        
           |  |  | 24 |   | 
        
           |  |  | 25 |     /**
 | 
        
           |  |  | 26 |     Comparator function for simple case-insensitive sorting of an array of
 | 
        
           |  |  | 27 |     strings.
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 |     @method compare
 | 
        
           |  |  | 30 |     @param a {Object} First sort argument.
 | 
        
           |  |  | 31 |     @param b {Object} Second sort argument.
 | 
        
           |  |  | 32 |     @param desc {Boolean} `true` if sort direction is descending, `false` if
 | 
        
           |  |  | 33 |         sort direction is ascending.
 | 
        
           |  |  | 34 |     @return {Boolean} -1 when a < b. 0 when a == b. 1 when a > b.
 | 
        
           |  |  | 35 |     @static
 | 
        
           |  |  | 36 |     */
 | 
        
           |  |  | 37 |     compare: function(a, b, desc) {
 | 
        
           |  |  | 38 |         if(!ISVALUE(a)) {
 | 
        
           |  |  | 39 |             if(!ISVALUE(b)) {
 | 
        
           |  |  | 40 |                 return 0;
 | 
        
           |  |  | 41 |             }
 | 
        
           |  |  | 42 |             else {
 | 
        
           |  |  | 43 |                 return 1;
 | 
        
           |  |  | 44 |             }
 | 
        
           |  |  | 45 |         }
 | 
        
           |  |  | 46 |         else if(!ISVALUE(b)) {
 | 
        
           |  |  | 47 |             return -1;
 | 
        
           |  |  | 48 |         }
 | 
        
           |  |  | 49 |   | 
        
           |  |  | 50 |         if(ISSTRING(a)) {
 | 
        
           |  |  | 51 |             a = a.toLowerCase();
 | 
        
           |  |  | 52 |         }
 | 
        
           |  |  | 53 |         if(ISSTRING(b)) {
 | 
        
           |  |  | 54 |             b = b.toLowerCase();
 | 
        
           |  |  | 55 |         }
 | 
        
           |  |  | 56 |         if(a < b) {
 | 
        
           |  |  | 57 |             return (desc) ? 1 : -1;
 | 
        
           |  |  | 58 |         }
 | 
        
           |  |  | 59 |         else if (a > b) {
 | 
        
           |  |  | 60 |             return (desc) ? -1 : 1;
 | 
        
           |  |  | 61 |         }
 | 
        
           |  |  | 62 |         else {
 | 
        
           |  |  | 63 |             return 0;
 | 
        
           |  |  | 64 |         }
 | 
        
           |  |  | 65 |     },
 | 
        
           |  |  | 66 |   | 
        
           |  |  | 67 |     /**
 | 
        
           |  |  | 68 |     Performs a natural-order comparison of two strings or numbers (or a string
 | 
        
           |  |  | 69 |     and a number). This ensures that a value like 'foo2' will be sorted before
 | 
        
           |  |  | 70 |     'foo10', whereas a standard ASCII sort would sort 'foo10' first.
 | 
        
           |  |  | 71 |   | 
        
           |  |  | 72 |     @example
 | 
        
           |  |  | 73 |   | 
        
           |  |  | 74 |         var items = ['item10', 'item2', 'item1', 10, '1', 2];
 | 
        
           |  |  | 75 |   | 
        
           |  |  | 76 |         items.sort(Y.ArraySort.naturalCompare);
 | 
        
           |  |  | 77 |         console.log(items); // => ['1', 2, 10, 'item1', 'item2', 'item10']
 | 
        
           |  |  | 78 |   | 
        
           |  |  | 79 |     @method naturalCompare
 | 
        
           |  |  | 80 |     @param {Number|String} a First value to compare.
 | 
        
           |  |  | 81 |     @param {Number|String} b Second value to compare.
 | 
        
           |  |  | 82 |     @param {Object} [options] Options.
 | 
        
           |  |  | 83 |         @param {Boolean} [options.caseSensitive=false] If `true`, a
 | 
        
           |  |  | 84 |             case-sensitive comparison will be performed. By default the
 | 
        
           |  |  | 85 |             comparison is case-insensitive.
 | 
        
           |  |  | 86 |         @param {Boolean} [options.descending=false] If `true`, the sort order
 | 
        
           |  |  | 87 |             will be reversed so that larger values are sorted before smaller
 | 
        
           |  |  | 88 |             values.
 | 
        
           |  |  | 89 |     @return {Number} `0` if the two items are equal, a negative number if _a_
 | 
        
           |  |  | 90 |         should be sorted before _b_, or a positive number if _b_ should be
 | 
        
           |  |  | 91 |         sorted before _a_.
 | 
        
           |  |  | 92 |     @static
 | 
        
           |  |  | 93 |     @since 3.11.0
 | 
        
           |  |  | 94 |     **/
 | 
        
           |  |  | 95 |     naturalCompare: function (a, b, options) {
 | 
        
           |  |  | 96 |         // Coerce `a` and `b` to strings.
 | 
        
           |  |  | 97 |         a += '';
 | 
        
           |  |  | 98 |         b += '';
 | 
        
           |  |  | 99 |   | 
        
           |  |  | 100 |         // Convert `a` and `b` to lowercase unless `options.caseSensitive` is
 | 
        
           |  |  | 101 |         // truthy.
 | 
        
           |  |  | 102 |         if (!options || !options.caseSensitive) {
 | 
        
           |  |  | 103 |             a = a.toLowerCase();
 | 
        
           |  |  | 104 |             b = b.toLowerCase();
 | 
        
           |  |  | 105 |         }
 | 
        
           |  |  | 106 |   | 
        
           |  |  | 107 |         // Split `a` and `b` into alpha parts and numeric parts.
 | 
        
           |  |  | 108 |         var aParts = ArraySort._splitAlphaNum(a),
 | 
        
           |  |  | 109 |             bParts = ArraySort._splitAlphaNum(b),
 | 
        
           |  |  | 110 |             length = Math.min(aParts.length, bParts.length),
 | 
        
           |  |  | 111 |             result = 0,
 | 
        
           |  |  | 112 |   | 
        
           |  |  | 113 |             aPart,
 | 
        
           |  |  | 114 |             bPart,
 | 
        
           |  |  | 115 |             i;
 | 
        
           |  |  | 116 |   | 
        
           |  |  | 117 |         // Compare each part of `a` with each part of `b`.
 | 
        
           |  |  | 118 |         for (i = 0; i < length; i++) {
 | 
        
           |  |  | 119 |             aPart = aParts[i];
 | 
        
           |  |  | 120 |             bPart = bParts[i];
 | 
        
           |  |  | 121 |   | 
        
           |  |  | 122 |             // If the two parts aren't equal, compare them and stop iterating.
 | 
        
           |  |  | 123 |             if (aPart !== bPart) {
 | 
        
           |  |  | 124 |                 // First, try comparing them as numbers.
 | 
        
           |  |  | 125 |                 result = aPart - bPart;
 | 
        
           |  |  | 126 |   | 
        
           |  |  | 127 |                 // If that didn't work, compare them as strings. This falsiness
 | 
        
           |  |  | 128 |                 // check works because `result` can't be 0 (we checked for
 | 
        
           |  |  | 129 |                 // equality above) and NaN is falsy.
 | 
        
           |  |  | 130 |                 if (!result) {
 | 
        
           |  |  | 131 |                     result = aPart > bPart ? 1 : -1;
 | 
        
           |  |  | 132 |                 }
 | 
        
           |  |  | 133 |   | 
        
           |  |  | 134 |                 // At this point we know enough to be able to sort the two
 | 
        
           |  |  | 135 |                 // strings, so we don't need to compare any more parts.
 | 
        
           |  |  | 136 |                 break;
 | 
        
           |  |  | 137 |             }
 | 
        
           |  |  | 138 |         }
 | 
        
           |  |  | 139 |   | 
        
           |  |  | 140 |         // If we get here and `result` is still 0, then sort the shorter string
 | 
        
           |  |  | 141 |         // before the longer string.
 | 
        
           |  |  | 142 |         result || (result = a.length - b.length);
 | 
        
           |  |  | 143 |   | 
        
           |  |  | 144 |         // Return the result, flipping the order if `options.descending` is
 | 
        
           |  |  | 145 |         // truthy.
 | 
        
           |  |  | 146 |         return options && options.descending ? -result : result;
 | 
        
           |  |  | 147 |     },
 | 
        
           |  |  | 148 |   | 
        
           |  |  | 149 |     // -- Protected Methods ----------------------------------------------------
 | 
        
           |  |  | 150 |   | 
        
           |  |  | 151 |     /**
 | 
        
           |  |  | 152 |     Splits a string into an array of alpha character and digit character parts.
 | 
        
           |  |  | 153 |   | 
        
           |  |  | 154 |     @example
 | 
        
           |  |  | 155 |   | 
        
           |  |  | 156 |         Y.ArraySort._splitAlphaNum('abc123def456');
 | 
        
           |  |  | 157 |         // => ['abc', '123', 'def', '456']
 | 
        
           |  |  | 158 |   | 
        
           |  |  | 159 |     @method _splitAlphaNum
 | 
        
           |  |  | 160 |     @param {String} string String to split.
 | 
        
           |  |  | 161 |     @return {String[]} Array of alpha parts and digit parts.
 | 
        
           |  |  | 162 |     @protected
 | 
        
           |  |  | 163 |     @static
 | 
        
           |  |  | 164 |     @since 3.11.0
 | 
        
           |  |  | 165 |     **/
 | 
        
           |  |  | 166 |     _splitAlphaNum: function (string) {
 | 
        
           |  |  | 167 |         /*jshint boss:true */
 | 
        
           |  |  | 168 |         var parts = [],
 | 
        
           |  |  | 169 |             regex = /(\d+|\D+)/g,
 | 
        
           |  |  | 170 |             match;
 | 
        
           |  |  | 171 |   | 
        
           |  |  | 172 |         while (match = regex.exec(string)) { // assignment
 | 
        
           |  |  | 173 |             parts.push(match[1]);
 | 
        
           |  |  | 174 |         }
 | 
        
           |  |  | 175 |   | 
        
           |  |  | 176 |         return parts;
 | 
        
           |  |  | 177 |     }
 | 
        
           |  |  | 178 | };
 | 
        
           |  |  | 179 |   | 
        
           |  |  | 180 |   | 
        
           |  |  | 181 | }, '3.18.1', {"requires": ["yui-base"]});
 |