rootsdev /
gedcomx-js
| 1 | var utils = module.exports = { |
||
| 2 | |||
| 3 | /** |
||
| 4 | * Check whether the given object is an instance of the specified class. |
||
| 5 | * The necessity for this is discussed in PR #13: https://github.com/rootsdev/gedcomx-js/pull/13 |
||
| 6 | * |
||
| 7 | * We put this functionality in a method to be DRY, even though it's short. |
||
| 8 | * This could easily change in the future for correction and performance. |
||
| 9 | * |
||
| 10 | * It could be handy to expose this on GedcomX somewhere so that users of the |
||
| 11 | * library can use it too. But then we would need to add a way for them to |
||
| 12 | * easily get the _gedxClass property without being tied to that private |
||
| 13 | * property name. In other words, a static method such as Person.getClass() |
||
| 14 | * |
||
| 15 | * @param {Object} obj |
||
| 16 | * @param {String} className |
||
| 17 | * @returns {Boolean} |
||
| 18 | */ |
||
| 19 | isInstance: function(obj, className){ |
||
| 20 | return obj && Object.getPrototypeOf(obj) !== Object.prototype && obj._gedxClass === className; |
||
| 21 | }, |
||
| 22 | |||
| 23 | /** |
||
| 24 | * Returns a copy of the object with undefined attributes removed. |
||
| 25 | * |
||
| 26 | * @param {Object} object |
||
| 27 | * @return {Object} |
||
| 28 | */ |
||
| 29 | removeEmpty: function(object){ |
||
| 30 | var dest = {}; |
||
| 31 | for(var a in object){ |
||
| 32 | if(object.hasOwnProperty(a) && object[a] !== undefined){ |
||
| 33 | dest[a] = object[a]; |
||
| 34 | } |
||
| 35 | } |
||
| 36 | return dest; |
||
| 37 | }, |
||
| 38 | |||
| 39 | /** |
||
| 40 | * Returns an object containing the properties from the source object |
||
| 41 | * |
||
| 42 | * @param {Object} obj |
||
|
0 ignored issues
–
show
Documentation
introduced
by
Loading history...
|
|||
| 43 | * @param {String[]} properties |
||
| 44 | * @return {Object} |
||
| 45 | */ |
||
| 46 | pick: function(object, properties){ |
||
| 47 | var dest = {}, |
||
| 48 | attr; |
||
| 49 | for(var i = 0; i < properties.length; i++){ |
||
| 50 | attr = properties[i]; |
||
| 51 | if(object.hasOwnProperty(attr)){ |
||
| 52 | dest[attr] = object[attr]; |
||
| 53 | } |
||
| 54 | } |
||
| 55 | return dest; |
||
| 56 | }, |
||
| 57 | |||
| 58 | /** |
||
| 59 | * Merge multiple objects |
||
| 60 | * |
||
| 61 | * Inspired by http://stackoverflow.com/a/16178864 |
||
| 62 | * |
||
| 63 | * @param {Object} destination |
||
|
0 ignored issues
–
show
|
|||
| 64 | * @param {Object} source |
||
|
0 ignored issues
–
show
|
|||
| 65 | * @param {Object=} source |
||
|
0 ignored issues
–
show
|
|||
| 66 | */ |
||
| 67 | merge: function(){ |
||
| 68 | var args = [].splice.call(arguments, 0), |
||
| 69 | dest = args.shift(), |
||
| 70 | src, attr; |
||
| 71 | while(args.length > 0){ |
||
| 72 | src = args.shift(); |
||
| 73 | if(typeof src === 'object'){ |
||
| 74 | for(attr in src){ |
||
| 75 | if(src.hasOwnProperty(attr)){ |
||
| 76 | if(typeof src[attr] === 'object' && !Array.isArray(src[attr])){ |
||
| 77 | dest[attr] = utils.merge(dest[attr] || {}, src[attr]); |
||
| 78 | } else { |
||
| 79 | dest[attr] = src[attr]; |
||
| 80 | } |
||
| 81 | } |
||
| 82 | } |
||
| 83 | } |
||
| 84 | } |
||
| 85 | return dest; |
||
| 86 | }, |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Recursively calls .toJSON() on values in an object that have the .toJSON() |
||
| 90 | * method defined. |
||
| 91 | * |
||
| 92 | * @param {Object} object |
||
| 93 | * @return {Object} |
||
| 94 | */ |
||
| 95 | toJSON: function(object){ |
||
| 96 | |||
| 97 | // Arrays - recursively call utils.toJSON() on the array items |
||
| 98 | if(Array.isArray(object)){ |
||
| 99 | return object.map(function(o){ |
||
| 100 | return utils.toJSON(o); |
||
| 101 | }); |
||
| 102 | } |
||
| 103 | |||
| 104 | // All remaining non-objects - just return them |
||
| 105 | if(typeof object !== 'object'){ |
||
| 106 | return object; |
||
| 107 | } |
||
| 108 | |||
| 109 | // At this point we only have objects |
||
| 110 | var dest = {}, |
||
| 111 | value; |
||
| 112 | for(var a in object){ |
||
| 113 | if(object.hasOwnProperty(a)){ |
||
| 114 | value = object[a]; |
||
| 115 | |||
| 116 | // Skip undefined values |
||
| 117 | if(typeof value === 'undefined'){ |
||
| 118 | continue; |
||
|
0 ignored issues
–
show
|
|||
| 119 | } |
||
| 120 | |||
| 121 | // Dates - get their time. We have to deal with dates down here instead |
||
| 122 | // of above because Date has a native toJSON method, meaning it would |
||
| 123 | // be cause by the case below and have the method called but we don't |
||
| 124 | // want to call the native method because it returns an ISO string while |
||
| 125 | // GEDCOMX requires a timestamp. |
||
| 126 | else if(typeof value.getTime === 'function'){ |
||
| 127 | dest[a] = value.getTime(); |
||
| 128 | } |
||
| 129 | |||
| 130 | // Call the object's .toJSON() method if it's available |
||
| 131 | else if (typeof value.toJSON === 'function'){ |
||
| 132 | dest[a] = value.toJSON(); |
||
| 133 | } |
||
| 134 | |||
| 135 | // Otherwise we recursively call utils.toJSON() on the value |
||
| 136 | else { |
||
| 137 | dest[a] = utils.toJSON(value); |
||
| 138 | } |
||
| 139 | } |
||
| 140 | } |
||
| 141 | return dest; |
||
| 142 | } |
||
| 143 | |||
| 144 | }; |