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