UNPKG

9.47 kBJavaScriptView Raw
1var util = require ('util');
2
3Object.PLATFORM_NATIVE_TYPES = {
4 // Buffer seems to be the only custom type in the Node core
5 'Buffer': true
6};
7
8Object.lookUpCustomType = function (obj) {
9 var name = obj && obj.constructor && obj.constructor.name;
10 if (name && name in Object.PLATFORM_NATIVE_TYPES) {
11 return name;
12 }
13};
14/**
15 * Get the type of any object.
16 * Usage:
17 * Object.typeOf([ 1, 2, 3 ]); // 'Array'
18 * Object.typeOf(null); // 'Null'
19 * Object.typeOf(new Buffer('')); // 'Buffer'
20 */
21Object.typeOf = function (obj) {
22 return Object.lookUpCustomType(obj) ||
23 Object.prototype.toString.call(obj).slice(8, -1);
24};
25
26/**
27 * Safe and universal type check.
28 * Usage:
29 * Object.is('Number', 4); // true
30 * Object.is('Undefined', undefined); // true
31 */
32Object.is = function (type, obj) {
33 return type == Object.typeOf(obj);
34};
35
36function isEmpty(obj) {
37 var type = Object.typeOf(obj);
38 return (
39 ('Undefined' == type) ||
40 ('Null' == type) ||
41 ('Boolean' == type && false === obj) ||
42 ('Number' == type && (0 === obj || isNaN(obj))) ||
43 ('String' == type && 0 == obj.length) ||
44 ('Array' == type && 0 == obj.length) ||
45 ('Object' == type && 0 == Object.keys(obj).length)
46 );
47}
48
49var Project;
50var projectRoot;
51var projectInstance;
52
53if (!util.inherits) {
54 util.inherits = function (ctor, superCtor) {
55 ctor.super_ = superCtor;
56 ctor.prototype = Object.create (superCtor.prototype, {
57 constructor: {
58 value: ctor,
59 enumerable: false,
60 writable: true,
61 configurable: true
62 }});
63 };
64 // http://stackoverflow.com/questions/13201775/looking-for-a-javascript-implementation-of-nodes-util-inherits
65 // B.prototype = Object.create(A.prototype); B.prototype.constructor = B;
66}
67
68if (!util.extend) {
69util.extend = function extend () {
70 var hasOwnProperty = Object.prototype.hasOwnProperty;
71
72 // copy reference to target object
73 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
74 // Handle a deep copy situation
75 if (typeof target === "boolean") {
76 deep = target;
77 target = arguments[1] || {};
78 // skip the boolean and the target
79 i = 2;
80 }
81 // Handle case when target is a string or something (possible in deep copy)
82 if (typeof target !== "object" && !typeof target === 'function')
83 target = {};
84 var isPlainObject = function(obj) {
85 // Must be an Object.
86 // Because of IE, we also have to check the presence of the constructor property.
87 // Make sure that DOM nodes and window objects don't pass through, as well
88 if (!obj || !Object.is('Object', obj) || obj.nodeType || obj.setInterval)
89 return false;
90 var has_own_constructor = hasOwnProperty.call(obj, "constructor");
91 var has_is_property_of_method = hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf");
92 // Not own constructor property must be Object
93 if (obj.constructor && !has_own_constructor && !has_is_property_of_method)
94 return false;
95 // Own properties are enumerated firstly, so to speed up,
96 // if last one is own, then all properties are own.
97 var last_key;
98 for (var key in obj)
99 last_key = key;
100 return typeof last_key === "undefined" || hasOwnProperty.call(obj, last_key);
101 };
102 for (; i < length; i++) {
103 // Only deal with non-null/undefined values
104 if ((options = arguments[i]) !== null) {
105 // Extend the base object
106 for (name in options) {
107 src = target[name];
108 copy = options[name];
109 // Prevent never-ending loop
110 if (target === copy)
111 continue;
112 // Recurse if we're merging object literal values or arrays
113 if (deep && copy && (isPlainObject(copy) || Array.isArray(copy))) {
114 var clone = src && (isPlainObject(src) || Array.isArray(src)) ? src : Array.isArray(copy) ? [] : {};
115 // Never move original objects, clone them
116 target[name] = extend(deep, clone, copy);
117 // Don't bring in undefined values
118 } else if (typeof copy !== "undefined")
119 target[name] = copy;
120 }
121 }
122 }
123 // Return the modified object
124 return target;
125}
126}
127
128if (!util.shallowMerge) {
129 util.shallowMerge = function (dest, src, filter) {
130 Object.keys(src).forEach(function (key) {
131 if ((!filter || -1 != filter.indexOf(key)) && null == dest[key]) {
132 dest[key] = src[key];
133 }
134 });
135 return dest;
136 };
137}
138
139if (!util.clone) {
140 util.clone = function(object) {
141
142 var result;
143
144 if (object.constructor === Array) {
145 result = object.map(function(item) {
146 return util.clone(item);
147 });
148 } else if (object.constructor === Object) {
149 result = {};
150 util.extend(result, object);
151 } else {
152 result = object;
153 }
154
155 return result;
156
157 }
158}
159
160try {
161 if (process.pid) {
162 global.$isClientSide = false;
163 global.$isServerSide = true;
164 global.$mainModule = process.mainModule;
165 global.$scope = 'process.mainModule';
166 global.$stash = {};
167 global.$isPhoneGap = false;
168 global.$global = global;
169 } else {
170 throw 'WTF?';
171 }
172} catch (e) {
173 window.$isClientSide = true;
174 window.$isServerSide = false;
175 window.$mainModule = window;
176 window.$scope = 'window';
177 window.$stash = {};
178 window.$global = window;
179 try {
180 if (window.PhoneGap || window.Cordova || window.cordova) window.$isPhoneGap = true;
181 } catch (e) {
182 console.log (e);
183 window.$isPhoneGap = false;
184 }
185}
186
187Number.prototype.hours = Number.prototype.hour
188 = function () {return this * 60 * 60 * 1e3}
189Number.prototype.minutes = Number.prototype.minute
190 = function () {return this * 60 * 1e3}
191Number.prototype.seconds = Number.prototype.second
192 = function () {return this * 1e3}
193
194Number.prototype.times = function (cb) {
195 var a = [];
196 for (var i = 0; i < this; i++)
197 a[i] = cb (i);
198 return a;
199}
200
201// especially for stupid loaders
202if (0)
203 module.exports = {};
204
205module.exports.$global = $global;
206
207// overwrite subject with values from object (merge object with subject)
208var mergeObjects = module.exports.mergeObjects = function (object, subjectParent, subjectKey) {
209 // subject parent here for js's lack of pass by reference
210
211 if (subjectParent[subjectKey] === void 0)
212 subjectParent[subjectKey] = {};
213 var subject = subjectParent[subjectKey];
214 for (var objectField in object) {
215 subject[objectField] = object[objectField];
216 }
217};
218
219var getByPath = module.exports.getByPath = function (path, origin) {
220 var value = origin || $global;
221 var scope, key;
222 var validPath = path.split('.').every(function (prop) {
223 scope = value;
224 key = prop;
225 if (null == scope) {
226 // break
227 return false;
228 } else {
229 value = scope[key];
230 return true;
231 }
232 });
233 return validPath && { value: value, scope: scope, key: key };
234};
235
236var pathToVal = module.exports.pathToVal = function (dict, path, value, method) {
237 var chunks = 'string' == typeof path ? path.split('.') : path;
238 var chunk = chunks[0];
239 var rest = chunks.slice(1);
240 if (chunks.length == 1) {
241 var oldValue = dict[chunk];
242 if (value !== undefined) {
243 if (method !== undefined) {
244 method(value, dict, chunk);
245 } else {
246 dict[chunk] = value;
247 }
248 }
249 return oldValue;
250 }
251 return pathToVal(dict[chunk], rest, value, method);
252};
253
254String.prototype.interpolate = function (dict, marks) {
255 if (!marks)
256 marks = {};
257 marks.start = marks.start || '{';
258 marks.end = marks.end || '}';
259 marks.path = marks.path || '.';
260 marks.typeSafe = marks.typeSafe || '$';
261 marks.typeRaw = marks.typeRaw || '*';
262
263 // TODO: escape character range delims
264 var re = new RegExp([
265 '[', marks.start, ']',
266 '([', marks.typeSafe, marks.typeRaw, '])',
267 '([^', marks.end, ']+)',
268 '[', marks.end, ']'
269 ].join(''), 'g');
270
271 var startRe = new RegExp([
272 '[', marks.start, ']',
273 '([', marks.typeSafe, marks.typeRaw, '])'
274 ].join(''), 'g');
275
276 var values = [];
277
278 var replacedStr = this.replace(re, function (_, varType, varPath) {
279 if (varPath.indexOf(marks.path) > -1) {
280 var value = pathToVal(dict, varPath);
281 } else {
282 value = dict[varPath];
283 }
284
285 if (isEmpty(value) && varType == marks.typeSafe) {
286 value = undefined;
287 }
288
289 values.push(value);
290
291 return value;
292 });
293
294 if (values.some(function (v) { return (typeof v === "undefined"); })) {
295 return undefined;
296 }
297
298 if (values.length === 1 && (values[0] + '') === replacedStr) {
299 return values[0];
300 }
301
302 return replacedStr;
303};
304
305/**
306 * [waitAll wait all events to complete]
307 * @param {[type]} events array of event arrays: [[subject, eventName, description]]
308 * @param {Function} callback called after all events handled
309 * @return {[type]} [description]
310 */
311module.exports.waitAll = function waitAll (events, callback) {
312 var remaining = [];
313 function _listener (eventName) {
314 remaining.some (function (remainingName, idx) {
315 if (remainingName == eventName) {
316 remaining.splice (idx, 1);
317 return true;
318 }
319 })
320 // console.log ("wait for " + remaining.length + " more: " + remaining.join (', '));
321 if (!remaining.length)
322 callback();
323 }
324 events.forEach (function (event) {
325 var subject = event[0];
326 var eventName = event[1];
327 var eventLogName = eventName + ' ' + event[2];
328 remaining.push (eventLogName);
329 if (typeof subject === "function") {
330 subject (_listener.bind ($global, eventLogName));
331 } else {
332 if (subject.addEventListener) {
333 subject.addEventListener (eventName, _listener.bind (subject, eventLogName), false);
334 } else {
335 subject.on (eventName, _listener.bind (subject, eventLogName), false);
336 }
337
338 }
339
340 });
341}
342
343module.exports.isEmpty = isEmpty;