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