1 /** 2 * Util Object 3 * 4 * Various object and string manipulation functions 5 * Note: these are based on similar phpjs functions: http://phpjs.org 6 */ 7 (function (){ 8 9 "use strict"; 10 11 var reverse_key_sort = function(o) 12 { 13 //Define some variables 14 var keys = [], 15 num_keys = 0, 16 new_o = {}, 17 i; 18 19 //Extract the keys 20 keys = u.object_keys(o); 21 22 //Sort the keys 23 keys.sort(function (b, a) { 24 var aFloat = parseFloat(a), 25 bFloat = parseFloat(b), 26 aNumeric = aFloat + '' === a, 27 bNumeric = bFloat + '' === b; 28 29 if (aNumeric && bNumeric) 30 { 31 return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0; 32 } 33 else if (aNumeric && !bNumeric) 34 { 35 return 1; 36 } 37 else if (!aNumeric && bNumeric) 38 { 39 return -1; 40 } 41 42 return a > b ? 1 : a < b ? -1 : 0; 43 }); 44 45 // cache object/array size 46 num_keys = keys.length; 47 48 // Recreate the object/array 49 for(i=0; i < num_keys; i++) 50 { 51 new_o[keys[i]] = o[keys[i]]; 52 } 53 54 return new_o; 55 }, 56 57 /** 58 * String and object manipulation utilities 59 * 60 * @namespace 61 * @name util 62 * @memberOf $_ 63 */ 64 u = { 65 /** 66 * Retrieve the keys, or member names of an object 67 * 68 * @name object_keys 69 * @memberOf $_.util 70 * @function 71 * @param object 72 * @return array 73 * @type array 74 */ 75 object_keys: function(o) 76 { 77 var keys = [], 78 k; 79 80 for(k in o) 81 { 82 if(o.hasOwnProperty(k)) 83 { 84 keys.push(k); 85 } 86 } 87 88 return keys; 89 }, 90 /** 91 * Retrieves the values of an object, and returns 92 * them as an array 93 * 94 * @name object_values 95 * @memberOf $_.util 96 * @function 97 * @param object 98 * @return array 99 * @type array 100 */ 101 object_values: function(o) 102 { 103 var vals = [], 104 prop; 105 106 for(prop in o) 107 { 108 vals.push(o[prop]); 109 } 110 111 return vals; 112 }, 113 /** 114 * Creates an object, with the property names of the first array, 115 * and the values of the second. If objects are passed, the values 116 * of the object are used. If the arrays or objects passed are 117 * not the same size, the function will return false. 118 * 119 * @name array_combine 120 * @memberOf $_.util 121 * @function 122 * @param array/object keys 123 * @param array/object vals 124 * @return object 125 * @type object 126 */ 127 array_combine: function(keys, vals) 128 { 129 var new_object = {}, 130 num_keys, 131 i = 0; 132 133 // Extract the keys or values if needed 134 if($_.type(keys) !== "array") 135 { 136 keys = this.object_values(keys); 137 } 138 if($_.type(vals) !== "array") 139 { 140 vals = this.object_values(vals); 141 } 142 143 // cache the number of keys 144 num_keys = keys.length; 145 146 if(num_keys !== vals.length) 147 { 148 return false; 149 } 150 151 // Create and return the new object 152 for(i = 0; i < num_keys; i++) 153 { 154 new_object[keys[i]] = vals[i]; 155 } 156 157 return new_object; 158 }, 159 /** 160 * Combines two or more objects/arrays. If the keys are numeric, the outputted 161 * object will have re-indexed keys. If a key/value pair exists in both objects, 162 * indentical values will be droped, but if a key exists with a different value, 163 * with the same key, the value in the second array will replace the value in the 164 * first 165 * 166 * @name object_merge 167 * @memberOf $_.util 168 * @function 169 * @param object [as many as you wish to combine] 170 * @type object 171 * @return object 172 */ 173 object_merge: function() 174 { 175 var args = Array.prototype.slice.call(arguments), 176 arg_len = args.length, 177 new_obj = {}, 178 arg, 179 iarg_len = 0, 180 i, 181 j, 182 x, 183 is_array = true; 184 185 // Check for an array in the arguments 186 for(i=0; i < arg_len; i++) 187 { 188 if($_.type(args[i]) !== "array") 189 { 190 is_array = false; 191 break; 192 } 193 } 194 195 // If all the arguments are javascript arrays 196 if(is_array) 197 { 198 new_obj = []; 199 // Let javascript do all the work! 200 for(i=0; i< arg_len; i++) 201 { 202 new_obj = new_obj.contact(args[i]); 203 } 204 205 // Return early 206 return new_obj; 207 } 208 209 // No, there's at least one object 210 for(i=0, x=0; i < arg_len; i++) 211 { 212 arg = args[i]; 213 214 // If the argument is an array, add the array items as 215 // numeric object properties 216 if ($_.type(arg) == "array") 217 { 218 for (j=0, iarg_len= arg.length; j < iarg_len; j++) 219 { 220 new_obj[x++] = arg[j]; 221 } 222 } 223 else 224 { 225 for (j in arg) 226 { 227 if(arg.hasOwnProperty(j)) 228 { 229 // If the key is numeric, add the property with 230 // a numeric key 231 if(parseInt(j, 10) + '' === j) 232 { 233 new_obj[x++] = arg[j]; 234 } 235 else 236 { 237 new_obj[j] = arg[j]; 238 } 239 } 240 } 241 } 242 } 243 244 return new_obj; 245 }, 246 /** 247 * Replaces sections of strings in a greedy fashion, 248 * starting with the longest replace pairs first. Accepts 249 * one replace pair as two parameters, or an object, with 250 * from => to replacements as key/value pairs 251 * 252 * @name str_trans 253 * @memberOf $_.util 254 * @function 255 * @param string input_string 256 * @param mixed from (string)/replace pairs (object) 257 * @param [string] 258 * @return string 259 * @type string 260 */ 261 str_trans: function(str, from, to) 262 { 263 var froms = [], 264 tos = [], 265 ret = '', 266 match = false, 267 from_len = 0, 268 str_len = 0, 269 to_len = 0, 270 to_is_str = '', 271 from_is_str = '', 272 strx = '', 273 strw = '', 274 stry = '', 275 from_strx = '', 276 new_str = '', 277 f, 278 i, 279 j; 280 281 //Replace pairs? add them to the internal arrays 282 if(typeof from === 'object') 283 { 284 // Sort the keys in descending order for better 285 // replacement functionality 286 from = reverse_key_sort(from); 287 288 for(f in from) 289 { 290 if(from.hasOwnProperty(f)) 291 { 292 froms.push(f); 293 tos.push(from[f]); 294 } 295 } 296 297 from = froms; 298 to = tos; 299 } 300 301 //Go through the string, and replace characters as needed 302 str_len = str.length; 303 from_len = from.length; 304 to_len = to.length; 305 to_is_str = typeof to === 'string'; 306 from_is_str = typeof from === 'string'; 307 308 for(i=0; i < str_len; i++) 309 { 310 match = false; 311 if(from_is_str) 312 { 313 strw = str.charAt(i-1); 314 strx = str.charAt(i); 315 stry = str.charAt(i+1); 316 for(j=0; j < from_len; j++) 317 { 318 if(strx == from.charAt(j)) 319 { 320 match = true; 321 break; 322 } 323 } 324 } 325 else 326 { 327 for(j=0; j < from_len; j++) 328 { 329 if(str.substr(i, from[j].length) == from[j]) 330 { 331 match = true; 332 333 //Go past the current match 334 i = (i + from[j].length) -1; 335 break; 336 337 } 338 } 339 } 340 341 if(match) 342 { 343 new_str += (to_is_str) ? to.charAt(j) : to[j]; 344 } 345 else 346 { 347 new_str += str.charAt(i); 348 } 349 } 350 351 return new_str; 352 353 } 354 355 }; 356 357 //Add it to the $_ object 358 $_.ext('util', u); 359 }());