      1 var comb = exports;
      2
      3 var merge = function(target, source) {
      4     var name, s;
      5     for (name in source) {
      6         s = source[name];
      7         if (!(name in target) || (target[name] !== s)) {
      8             target[name] = s;
      9         }
     10     }
     11     return target;
     12 };
     13
     14 /**
     15  * Merges objects together
     16  * NOTE: this function takes a variable number of objects to merge
     17  *
     18  * @example
     19  *
     20  * var myObj = {};
     21  * comb.merge(myObj, {test : true});
     22  *
     23  * myObj.test => true
     24  *
     25  * comb.merge(myObj, {test : false}, {test2 : false}, {test3 : "hello", test4 : "world"});
     26  * myObj.test => false
     27  * myObj.test2 => false
     28  * myObj.test3 => "hello"
     29  * myObj.test4 => "world"
     30  *
     31  *
     32  * @param {Object} obj the object to merge into
     33  * @param {Object} props variable number of objects to merge into the obj
     34  *
     35  * @returns {Object} the merged object
     36  */
     37 comb.merge = function(obj, props) {
     38     if (!obj) {
     39         obj = {};
     40     }
     41     for (var i = 1, l = arguments.length; i < l; i++) {
     42         merge(obj, arguments[i]);
     43     }
     44     return obj; // Object
     45 };
     46
     47 /**
     48  * Extends the prototype of an object if it exists otherwise it extends the object.
     49  *
     50  * @example
     51  *
     52  *  var MyObj = function(){};
     53  *  MyObj.prototype.test = true;
     54  *  comb.extend(MyObj, {test2 : false, test3 : "hello", test4 : "world"});
     55  *
     56  *  var myObj = new MyObj();
     57  *
     58  *  myObj.test => true
     59  *  myObj.test2 => false
     60  *  myObj.test3 => "hello"
     61  *  myObj.test4 => "world"
     62  *
     63  *  var myObj2 = {};
     64  *  myObj2.test = true;
     65  *  comb.extend(myObj2, {test2 : false, test3 : "hello", test4 : "world"});
     66  *
     67  *  myObj2.test => true
     68  *  myObj2.test2 => false
     69  *  myObj2.test3 => "hello"
     70  *  myObj2.test4 => "world"
     71  *
     72  *
     73  * @param {Object} parent the parent object to extend
     74  * @param {Object} extend the extension object to mixin to the parent
     75  *
     76  * @returns {Object} returns the extended object
     77  */
     78 comb.extend = function(parent, extend){
     79     var proto = parent.prototype || parent;
     80     return exports.merge(proto, extend);
     81 };
     82
     83 /**
     84  * Determines if obj is an object
     85  *
     86  * @param {Anything} obj the thing to test if it is an object
     87  *
     88  * @returns {Boolean} true if it is an object false otherwise
     89  */
     90 comb.isObject = function(obj) {
     91     var undef;
     92     return obj != null && obj != undef && typeof obj == "object";
     93 };
     94
     95 /**
     96  * Determins if an object is just a hash and not a qualified Object such as number
     97  *
     98  * @example
     99  *    comb.isHash({}) => true
    100  *    comb.isHash({1 : 2, a : "b"}) => true
    101  *    comb.isHash(new Date()) => false
    102  *    comb.isHash(new String()) => false
    103  *    comb.isHash(new Number()) => false
    104  *    comb.isHash(new Boolean()) => false
    105  *    comb.isHash() => false
    106  *    comb.isHash("") => false
    107  *    comb.isHash(1) => false
    108  *    comb.isHash(false) => false
    109  *    comb.isHash(true) => false
    110  * @param {Anything} obj the thing to test if it is a hash
    111  *
    112  * @returns {Boolean} true if it is a hash false otherwise
    113  */
    114 comb.isHash = function(obj){
    115     var ret = comb.isObject(obj);
    116     return ret && obj.constructor === Object;
    117 }
    118
    119 /**
    120  * Determines if an object is empty
    121  *
    122  * @example
    123  *
    124  * comb.isEmpty({}) => true
    125  * comg.isEmpty({a : 1}) => false
    126  *
    127  * @param object the object to test
    128  */
    129 comb.isEmpty = function(object) {
    130     if (object) {
    131         for (var i in object) {
    132             if (object.hasOwnProperty(i)) {
    133                 return false;
    134             }
    135         }
    136     }
    137     return true;
    138 }
    139