1 /** 2 * @fileOverview Helper methods for Objects 3 * @author <a href="http://www.bobs-bits.com">Stephen Reay</a> 4 */ 5 6 if (!Object.size) { 7 /** 8 * Calculate the size of an Object 9 * @param object the object to get the size of 10 * @returns {Number} the size of the object 11 */ 12 Object.size = function size(object) { 13 if (object.length) { 14 return object.length; 15 } 16 if (object.__count__) { 17 return object.__count__; 18 } 19 var count = 0; 20 21 for (var i in object) { 22 if (object.hasOwnProperty(i)) { 23 count++; 24 } 25 } 26 return count; 27 }; 28 } 29 30 if (!Object.update) { 31 /** 32 * Updates an Object with key:value pairs from another Object 33 * @param {Object} object the Object to update 34 * @param {Object} updates the new key:value pairs to update the original Object with 35 * @returns {Object} the original Object updated with new key:value pairs 36 * @see Object.merge 37 * @example 38 * var obj = {'cow':'moo', 'dog':'woof'}; 39 * Object.update(obj, {'cow':'milk','sheep':'wool'}); //{'cow':'milk', 'dog':'woof', 'sheep':'wool'} 40 */ 41 Object.update = function update(object, updates) { 42 if(Object.isUndefined(updates)) { 43 return object; 44 } 45 for (var att in updates) { 46 if (updates.hasOwnProperty(att)) { 47 if (object.hasOwnProperty(att) && Object.isObject(object[att]) && Object.isObject(updates[att])) { 48 Object.update(object[att], updates[att]); 49 } 50 else { 51 object[att] = updates[att]; 52 } 53 } 54 } 55 56 return object; 57 }; 58 } 59 60 if (!Object.merge) { 61 /** 62 * Creates a new Object, by combining the key:value pairs from two Objects 63 * @param {Object} object the first of the Objects to merge 64 * @param {Object} updates the second of the Objects to merge 65 * @returns {Object} new Object updated with new key:value pairs 66 * @see Object.update 67 * @example 68 * var obj = {'cow':'moo', 'dog':'woof'}; 69 * var obj2 = Object.merge(obj, {'cow':'milk','sheep':'wool'}); 70 * //obj2 == {'cow':'milk', 'dog':'woof', 'sheep':'wool'} 71 * //obj is unchanged 72 */ 73 Object.merge = function merge(object, updates) { 74 var newObj = {}; 75 for (var att in object) { 76 if (object.hasOwnProperty(att)) { 77 newObj[att] = object[att]; 78 } 79 } 80 return Object.update(newObj, updates); 81 }; 82 } 83 84 if (!Object.prototype.inherits) { 85 /** 86 * Extend a Class with another's prototype to mimic Class inheritance 87 * @param {Class} parentClass the Class to inherit from 88 * @param [1...n] Arguments to initiate the parent Class with 89 * @author <a href="http://www.coolpage.com/developer/javascript/Correct%20OOP%20for%20Javascript.html">Shelby H. Moore III</a> 90 * @see Function.prototype.inherits 91 * @example 92 * function ClassA(arg) { 93 * this.prop = arg || false; 94 * } 95 * 96 * ClassB.inherits(ClassA); 97 * function ClassB(arg) { 98 * this.inherits(ClassA); 99 * this.prop2 = arg || 'default'; 100 * } 101 */ 102 Object.prototype.inherits = function inherits(parentClass) { 103 if (Object.isFunction(parentClass)) { 104 if (this.constructor === parentClass) { 105 throw new ReferenceError("A Class can't inherit from itself"); 106 } 107 if (arguments.length > 1) { 108 parentClass.apply(this, Array.prototype.slice.call(arguments, 1)); 109 } 110 else { 111 parentClass.call(this); 112 } 113 } 114 }; 115 } 116 117 if (!Object.isObject) { 118 /** 119 * Convenience method to check if an object is an Object 120 * @param object the object to check the type of 121 * @returns {Boolean} true if object is an Object, false if not 122 */ 123 Object.isObject = function isObject(object) { 124 return !Object.isUndefined(object) && object.constructor === Object; 125 }; 126 } 127 128 if (!Object.isArray) { 129 /** 130 * Convenience method to check if an object is an Array 131 * @param object the object to check the type of 132 * @returns {Boolean} true if object is an Array, false if not 133 */ 134 Object.isArray = function isArray(object) { 135 return !Object.isUndefined(object) && object.constructor === Array; 136 }; 137 } 138 139 if (!Object.isString) { 140 /** 141 * Convenience method to check if an object is a String 142 * @param object the object to check the type of 143 * @returns {Boolean} true if object is a String, false if not 144 */ 145 Object.isString = function isString(object) { 146 return !Object.isUndefined(object) && object.constructor === String; 147 }; 148 } 149 150 if (!Object.isNumber) { 151 /** 152 * Convenience method to check if an object is a Number 153 * @param object the object to check the type of 154 * @returns {Boolean} true if object is a Number, false if not 155 */ 156 Object.isNumber = function isNumber(object) { 157 return !Object.isUndefined(object) && object.constructor === Number; 158 }; 159 } 160 161 if (!Object.isDate) { 162 /** 163 * Convenience method to check if an object is a Number 164 * @param object the object to check the type of 165 * @returns {Boolean} true if object is a Number, false if not 166 */ 167 Object.isDate = function isDate(object) { 168 return !Object.isUndefined(object) && object.constructor === Date; 169 }; 170 } 171 172 if (!Object.isRegExp) { 173 /** 174 * Convenience method to check if an object is a Regular Expression 175 * @param object the object to check the type of 176 * @returns {Boolean} true if object is a Regular Expression, false if not 177 */ 178 Object.isRegExp = function isRegExp(object) { 179 return !Object.isUndefined(object) && object.constructor === RegExp; 180 }; 181 } 182 183 if (!Object.isFunction) { 184 /** 185 * Convenience method to check if an object is a Function 186 * @param object the object to check the type of 187 * @returns {Boolean} true if object is a Function, false if not 188 */ 189 Object.isFunction = function isFunction(object) { 190 return !Object.isUndefined(object) && object.constructor === Function; 191 }; 192 } 193 194 if (!Object.isBoolean) { 195 /** 196 * Convenience method to check if an object is a Boolean 197 * @param object the object to check the type of 198 * @returns {Boolean} true if object is a Boolean, false if not 199 */ 200 Object.isBoolean = function isBoolean(object) { 201 return !Object.isUndefined(object) && object.constructor === Boolean; 202 }; 203 } 204 205 if (!Object.isElement) { 206 /** 207 * Convenience method to check if an object is a DOM Element 208 * @param object the object to check the type of 209 * @returns {Boolean} true if object is a DOM Element, false if not 210 */ 211 Object.isElement = function isElement(object, tag) { 212 return !Object.isUndefined(object) && object.nodeType === 1 && (Object.isUndefined(tag) || object.nodeName.toLowerCase() === tag.toLowerCase()); 213 }; 214 } 215 216 if (!Object.isUndefined) { 217 /** 218 * Convenience method to check if an object is defined 219 * @param object the object to check 220 * @returns {Boolean} true if object is undefined, false if object is defined 221 */ 222 Object.isUndefined = function isUndefined(object) { 223 return typeof object === 'undefined'; 224 }; 225 } 226 227 if (!Object.toArray) { 228 /** 229 * Convert an array-like object into a true Array 230 * @param {Array-like} array array-like object to create true Array from 231 * @returns {Array} new Array created from original object 232 * @example 233 * function foo() { 234 * var args = Object.toArray(arguments); ['moo','cow'] 235 * args.forEach(someOtherFunc); 236 * } 237 * foo('moo', 'cow'); 238 */ 239 Object.toArray = function toArray(object) { 240 if (Object.isArray(object)) { 241 return object; 242 } 243 try { //This might bomb in Explorer! 244 return Array.prototype.slice.call(object, 0); 245 } 246 catch(e) { 247 return Array.prototype.map.call(object, function(a) { 248 return a; 249 }); 250 } 251 }; 252 } 253 254 if (!Object.forEach) { 255 /** 256 * Executes a provided function once per object element. 257 * @param {Object} object the Object to iterate over 258 * @param {Function} callback function to execute for each element 259 * @param {Object} [context] to use as this when executing callback 260 * @see Array#forEach 261 * @example 262 * Object.forEach({'moo':'cow', 'woof':'dog'}, myFunc); 263 */ 264 Object.forEach = function forEach(object, callback, context) { 265 if (!Object.isFunction(callback)) { 266 throw new TypeError(); 267 } 268 269 for (var i in object) { 270 if (object.hasOwnProperty(i)) { 271 callback.call(context, object[i], i, object); 272 } 273 } 274 }; 275 } 276 277 if (!Object.map) { 278 /** 279 * Creates a new Object with the results of calling a provided function on every element in this Object 280 * @param {Object} object the Object to iterate over 281 * @param {Function} callback function that produces an element of the new Object from an element of the current one 282 * @param {Object} [context] to use as this when executing callback 283 * @returns {Object} new Object with the results of calling a provided function on every element in this Object 284 * @see Array#map 285 * @example 286 * function makePseudoPlural(single) { 287 * return single.replace(/o/g, "e"); 288 * } 289 * var singles = {"human":"foot", "dinner":"goose", "target":"moose"]; 290 * var plurals = Object.map(singles, makePseudoPlural); //{"human":"feet", "dinner":"geese", "target":"meese"} 291 */ 292 Object.map = function map(object, callback, context) { 293 if (!Object.isFunction(callback)) { 294 throw new TypeError(); 295 } 296 297 var obj = {}; 298 299 for (var i in object) { 300 if (object.hasOwnProperty(i)) { 301 obj[i] = callback.call(context, object[i], i, object); 302 } 303 } 304 305 return obj; 306 }; 307 } 308 309 if (!Object.every) { 310 /** 311 * Tests whether all elements in the Object pass the test implemented by the provided function 312 * @param {Object} object the Object to iterate over 313 * @param {Function} callback function to test for each element 314 * @param {Object} [context] to use as this when executing callback 315 * @returns {Boolean} true if all elements pass the test implented by callback, false if not 316 * @see Array#every 317 */ 318 Object.every = function every(object, callback, context) { 319 if (!Object.isFunction(callback)) { 320 throw new TypeError(); 321 } 322 323 for (var i in object) { 324 if (object.hasOwnProperty(i) && !callback.call(context, object[i], i, object)) { 325 return false; 326 } 327 } 328 return true; 329 }; 330 } 331 332 if (!Object.some) { 333 /** 334 * Tests whether some element in the array passes the test implemented by the provided function 335 * @param {Object} object the Object to iterate over 336 * @param {Function} callback function to test for each element 337 * @param {Object} [context] to use as this when executing callback 338 * @returns {Boolean} true if some element passes the test implented by callback, false if not 339 * @see Array#some 340 */ 341 Object.some = function some(object, callback, context) { 342 if (!Object.isFunction(callback)) { 343 throw new TypeError(); 344 } 345 346 for (var i in object) { 347 if (object.hasOwnProperty(i) && callback.call(context, object[i], i, object)) { 348 return true; 349 } 350 return true; 351 } 352 return false; 353 }; 354 } 355 356 if (!Object.filter) { 357 /** 358 * Creates a new Object with all elements that pass the test implemented by the provided function. 359 * @param {Object} object the Object to iterate over 360 * @param {Function} callback function to test each element of the array 361 * @param {Object} [context] to use as this when executing callback 362 * @returns {Object} a new Object with all elements that pass the test implemented by the provided function 363 * @see Array#filter 364 */ 365 Object.filter = function filter(object, callback, context) { 366 if (!Object.isFunction(callback)) { 367 throw new TypeError(); 368 } 369 370 var obj = {}; 371 372 for (var i in object) { 373 if (object.hasOwnProperty(i)) { 374 var val = object[i]; 375 if (callback.call(context, val, i, object)) { 376 obj[i] = val; 377 } 378 } 379 } 380 381 return obj; 382 }; 383 } 384 385 if (!Object.serialize) { 386 /** 387 * Serialize an Object into a string. If the value of a property is an array, the entries will be added multiple times 388 * @param {Object} object the data object to serialize 389 * @param {String} [seperator='&'] the seperator to use between the values in the generated string 390 * @returns {String} the serialized version of the data 391 */ 392 Object.serialize = function serialize(object, seperator) { 393 seperator = seperator || '&'; 394 var serializedString = ""; 395 for (var i in object) { 396 if (object.hasOwnProperty(i) && !Object.isFunction(object[i])) { 397 if (serializedString.length > 0) { 398 serializedString += seperator; 399 } 400 if (Object.isArray(object[i])) { 401 serializedString += (i + '=' + object[i].join(seperator + i + '=')); 402 } 403 else { 404 serializedString += (i + '=' + object[i]); 405 } 406 } 407 } 408 409 return serializedString; 410 }; 411 } 412 413 if (!Object.getKeys) { 414 /** 415 * Get the keys (property names) from an Object as an Array 416 * @param {Object} object the Object to get the keys (property names) from 417 * @returns {Array} the keys (property names) from the object 418 */ 419 Object.getKeys = function getKeys(object) { 420 var newArr = []; 421 for (var i in object) { 422 if (object.hasOwnProperty(i)) { 423 newArr.push(i); 424 } 425 } 426 427 return newArr; 428 }; 429 } 430 431 if (!Object.getValues) { 432 /** 433 * Get the values from an Object as an Array 434 * @param {Object} object the Object to get the values from 435 * @returns {Array} the values from the object 436 */ 437 Object.getValues = function getValues(object) { 438 var newArr = []; 439 for (var i in object) { 440 if (object.hasOwnProperty(i)) { 441 newArr.push(object[i]); 442 } 443 } 444 445 return newArr; 446 }; 447 }