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 console.log("Object combine requires two arrays of the same size"); 149 return false; 150 } 151 152 // Create and return the new object 153 for(i = 0; i < num_keys; i++) 154 { 155 new_object[keys[i]] = vals[i]; 156 } 157 158 return new_object; 159 }, 160 /** 161 * Combines two or more objects/arrays. If the keys are numeric, the outputted 162 * object will have re-indexed keys. If a key/value pair exists in both objects, 163 * indentical values will be droped, but if a key exists with a different value, 164 * with the same key, the value in the second array will replace the value in the 165 * first 166 * 167 * @name object_merge 168 * @memberOf $_.util 169 * @function 170 * @param object [as many as you wish to combine] 171 * @type object 172 * @return object 173 */ 174 object_merge: function() 175 { 176 var args = Array.prototype.slice.call(arguments), 177 arg_len = args.length, 178 new_obj = {}, 179 arg, 180 iarg_len = 0, 181 i, 182 j, 183 x, 184 is_array = true; 185 186 // Check for an array in the arguments 187 for(i=0; i < arg_len; i++) 188 { 189 if($_.type(args[i]) !== "array") 190 { 191 is_array = false; 192 break; 193 } 194 } 195 196 // If all the arguments are javascript arrays 197 if(is_array) 198 { 199 new_obj = []; 200 // Let javascript do all the work! 201 for(i=0; i< arg_len; i++) 202 { 203 new_obj = new_obj.contact(args[i]); 204 } 205 206 // Return early 207 return new_obj; 208 } 209 210 // No, there's at least one object 211 for(i=0, x=0; i < arg_len; i++) 212 { 213 arg = args[i]; 214 215 // If the argument is an array, add the array items as 216 // numeric object properties 217 if ($_.type(arg) == "array") 218 { 219 for (j=0, iarg_len= arg.length; j < iarg_len; j++) 220 { 221 new_obj[x++] = arg[j]; 222 } 223 } 224 else 225 { 226 for (j in arg) 227 { 228 if(arg.hasOwnProperty(j)) 229 { 230 // If the key is numeric, add the property with 231 // a numeric key 232 if(parseInt(j, 10) + '' === j) 233 { 234 new_obj[x++] = arg[j]; 235 } 236 else 237 { 238 new_obj[j] = arg[j]; 239 } 240 } 241 } 242 } 243 } 244 245 return new_obj; 246 }, 247 /** 248 * Replaces sections of strings in a greedy fashion, 249 * starting with the longest replace pairs first. Accepts 250 * one replace pair as two parameters, or an object, with 251 * from => to replacements as key/value pairs 252 * 253 * @name str_trans 254 * @memberOf $_.util 255 * @function 256 * @param string input_string 257 * @param mixed from (string)/replace pairs (object) 258 * @param [string] 259 * @return string 260 * @type string 261 */ 262 str_trans: function(str, from, to) 263 { 264 var froms = [], 265 tos = [], 266 ret = '', 267 match = false, 268 from_len = 0, 269 str_len = 0, 270 to_len = 0, 271 to_is_str = '', 272 from_is_str = '', 273 strx = '', 274 strw = '', 275 stry = '', 276 from_strx = '', 277 new_str = '', 278 f, 279 i, 280 j; 281 282 //Replace pairs? add them to the internal arrays 283 if(typeof from === 'object') 284 { 285 // Sort the keys in descending order for better 286 // replacement functionality 287 from = reverse_key_sort(from); 288 289 for(f in from) 290 { 291 if(from.hasOwnProperty(f)) 292 { 293 froms.push(f); 294 tos.push(from[f]); 295 } 296 } 297 298 from = froms; 299 to = tos; 300 } 301 302 //Go through the string, and replace characters as needed 303 str_len = str.length; 304 from_len = from.length; 305 to_len = to.length; 306 to_is_str = typeof to === 'string'; 307 from_is_str = typeof from === 'string'; 308 309 for(i=0; i < str_len; i++) 310 { 311 match = false; 312 if(from_is_str) 313 { 314 strw = str.charAt(i-1); 315 strx = str.charAt(i); 316 stry = str.charAt(i+1); 317 for(j=0; j < from_len; j++) 318 { 319 if(strx == from.charAt(j)) 320 { 321 match = true; 322 break; 323 } 324 } 325 } 326 else 327 { 328 for(j=0; j < from_len; j++) 329 { 330 if(str.substr(i, from[j].length) == from[j]) 331 { 332 match = true; 333 334 //Go past the current match 335 i = (i + from[j].length) -1; 336 break; 337 338 } 339 } 340 } 341 342 if(match) 343 { 344 new_str += (to_is_str) ? to.charAt(j) : to[j]; 345 } 346 else 347 { 348 new_str += str.charAt(i); 349 } 350 } 351 352 return new_str; 353 354 } 355 356 }; 357 358 //Add it to the $_ object 359 $_.ext('util', u); 360 }()); 361 362