1 /**
  2  * NowUtil: an assorted collection of general-purpose functions used
  3  * in NowJS.
  4  */
  5 
  6 Object.defineProperty(Array.prototype,
  7                       'toJSON',
  8                       { enumerable: false,
  9                         value: function () {
 10                           if (Array.isArray(this)) {
 11                             return this;
 12                           }
 13                           var toReturn = [];
 14  15                           for (var i = 0, ll = this.length; i < ll; i++) {
 16                             toReturn[i] = this[i];
 17                           }
 18                           return toReturn;
 19                         }
 20                       });
 21 
 22 var util = {
 23   parseCookie: function (cookie) {
 24     if (typeof cookie !== 'string') {
 25       return {};
 26     }
 27     var regex = /(.+?)(;|$)\s*/g;
 28     var match = cookie.match(regex);
 29     if (!match) {
 30       return {};
 31     }
 32     var jsonCookie = {};
 33     var m, end, index;
 34     for (var i = 0; i < match.length; i++) {
 35       m = match[i];
 36       index = m.indexOf('=');
 37       end = m.lastIndexOf(';');
 38       if (index === -1) {
 39         jsonCookie[m.substr(index + 1,
 40                             end + 1 ?
 41                             end - index - 1:
 42                             undefined)] = true;
 43       } else {
 44         jsonCookie[m.substr(0, index)] = m.substr(index + 1,
 45                                                   (end + 1 ?
 46                                                    end - index - 1 :
 47                                                    undefined));
 48       }
 49     }
 50     return jsonCookie;
 51   },
 52 
 53   hasProperty: function (obj, prop) {
 54     return Object.prototype.hasOwnProperty.call(Object(obj), prop);
 55   },
 56 
 57   noop: function () {
 58   },
 59 
 60   clone: function (proto, obj) {
 61     // note regarding speed and C++ bindings: evidently it's slightly
 62     // faster to provide a wrapper function than adding an additional
 63     // level of lookup.
 64     if (!(obj && typeof obj === 'object')) {
 65       obj = {};
 66     }
 67     obj.__proto__ = proto;
 68     return obj;
 69   },
 70 
 71   generateRandomString: function () {
 72     return ("" + Math.random()).substring(2);
 73   },
 74 
 75   error: function (err) {
 76     console.log(err);
 77     if (util.hasProperty(err, 'stack')) {
 78       console.log(err.stack);
 79     }
 80   },
 81 
 82   getAllChildFqns: function (parentObj, parentFqn) {
 83     var fqns = [];
 84     var prop;
 85     function getAllChildFqnsHelper(parentObj, parentFqn) {
 86       for (var i = 0, keys = Object.keys(parentObj), ll = keys.length; i < ll; i++ ) {
 87         prop = keys[i];
 88         if (parentObj[prop] && typeof parentObj[prop] === 'object') {
 89           getAllChildFqnsHelper(parentObj[prop], parentFqn + '.' + prop);
 90         } else {
 91           fqns.push(parentFqn + '.' + prop);
 92         }
 93       }
 94       if (ll == 0) {
 95         fqns.push(parentFqn);
 96       }
 97     }
 98     getAllChildFqnsHelper(parentObj, parentFqn);
 99     return fqns;
100   },
101 
102   extend: function (target, obj) {
103     for (var i = 0, keys = Object.keys(obj), ii = keys.length; i < ii; i++) {
104       var key = keys[i];
105       if (obj[key] && typeof obj[key] === 'object') {
106         if(Array.isArray(obj[key])) {
107           target[key] = target[key] || [];
108         } else {
109           target[key] = target[key] || {};
110         }
111         util.extend(target[key], obj[key]);
112       } else {
113         target[key] = obj[key];
114       }
115     }
116   },
117 
118   getVarFromFqn: function (fqn, scope) {
119     var path = fqn.split('.');
120     path.shift();
121     var currVar = scope;
122     var prop;
123     while (path.length > 0) {
124       prop = path.shift();
125       if (util.hasProperty(currVar, prop)) {
126         currVar = currVar[prop];
127       } else {
128         return false;
129       }
130     }
131     return currVar;
132   },
133 
134   stringify: JSON.stringify,
135 
136   parse: JSON.parse,
137 
138   flatten: function (val, fqn) {
139     var vals = {};
140     var fqns = util.getAllChildFqns(val, '');
141     var m;
142     for (var i = 0, ii = fqns.length; i < ii; i++) {
143       m = util.getVarFromFqn(fqns[i], val);
144       vals[fqn + fqns[i]] = m;
145     }
146     return vals;
147   },
148 
149   getValOrFqn: function (val, fqn) {
150     if (typeof val === 'function') {
151       return {fqn: fqn};
152     } else {
153       return val;
154     }
155   },
156 
157   isEmptyObj: function (obj) {
158     for (var i in obj) {
159       return false;
160     }
161     return true;
162   }
163 };
164 
165 exports.nowUtil = util;
166