UNPKG

9.52 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;
92 if (obj.constructor)
93 has_is_property_of_method = hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf");
94 // Not own constructor property must be Object
95 if (obj.constructor && !has_own_constructor && !has_is_property_of_method)
96 return false;
97 // Own properties are enumerated firstly, so to speed up,
98 // if last one is own, then all properties are own.
99 var last_key;
100 for (var key in obj)
101 last_key = key;
102 return typeof last_key === "undefined" || hasOwnProperty.call(obj, last_key);
103 };
104 for (; i < length; i++) {
105 // Only deal with non-null/undefined values
106 if ((options = arguments[i]) !== null) {
107 // Extend the base object
108 for (name in options) {
109 src = target[name];
110 copy = options[name];
111 // Prevent never-ending loop
112 if (target === copy)
113 continue;
114 // Recurse if we're merging object literal values or arrays
115 if (deep && copy && (isPlainObject(copy) || Array.isArray(copy))) {
116 var clone = src && (isPlainObject(src) || Array.isArray(src)) ? src : Array.isArray(copy) ? [] : {};
117 // Never move original objects, clone them
118 target[name] = extend(deep, clone, copy);
119 // Don't bring in undefined values
120 } else if (typeof copy !== "undefined")
121 target[name] = copy;
122 }
123 }
124 }
125 // Return the modified object
126 return target;
127}
128}
129
130if (!util.shallowMerge) {
131 util.shallowMerge = function (dest, src, filter) {
132 Object.keys(src).forEach(function (key) {
133 if ((!filter || -1 != filter.indexOf(key)) && null == dest[key]) {
134 dest[key] = src[key];
135 }
136 });
137 return dest;
138 };
139}
140
141if (!util.clone) {
142 util.clone = function(object) {
143
144 var result;
145
146 if (object.constructor === Array) {
147 result = object.map(function(item) {
148 return util.clone(item);
149 });
150 } else if (object.constructor === Object) {
151 result = {};
152 util.extend(result, object);
153 } else {
154 result = object;
155 }
156
157 return result;
158
159 }
160}
161
162try {
163 if (process.pid) {
164 global.$isClientSide = false;
165 global.$isServerSide = true;
166 global.$mainModule = process.mainModule;
167 global.$scope = 'process.mainModule';
168 global.$stash = {};
169 global.$isCordova = false;
170 global.$global = global;
171 } else {
172 throw 'WTF?';
173 }
174} catch (e) {
175 window.$isClientSide = true;
176 window.$isServerSide = false;
177 window.$mainModule = window;
178 window.$scope = 'window';
179 window.$stash = {};
180 window.$global = window;
181 try {
182 if (window.PhoneGap || window.Cordova || window.cordova) window.$isCordova = true;
183 } catch (e) {
184 console.log (e);
185 window.$isCordova = false;
186 }
187}
188
189Number.prototype.hours = Number.prototype.hour
190 = function () {return this * 60 * 60 * 1e3}
191Number.prototype.minutes = Number.prototype.minute
192 = function () {return this * 60 * 1e3}
193Number.prototype.seconds = Number.prototype.second
194 = function () {return this * 1e3}
195
196Number.prototype.times = function (cb) {
197 var a = [];
198 for (var i = 0; i < this; i++)
199 a[i] = cb (i);
200 return a;
201}
202
203// especially for stupid loaders
204if (0)
205 module.exports = {};
206
207module.exports.$global = $global;
208
209// overwrite subject with values from object (merge object with subject)
210var mergeObjects = module.exports.mergeObjects = function (object, subjectParent, subjectKey) {
211 // subject parent here for js's lack of pass by reference
212
213 if (subjectParent[subjectKey] === void 0)
214 subjectParent[subjectKey] = {};
215 var subject = subjectParent[subjectKey];
216 for (var objectField in object) {
217 subject[objectField] = object[objectField];
218 }
219};
220
221var getByPath = module.exports.getByPath = function (path, origin) {
222 var value = origin || $global;
223 var scope, key;
224 var validPath = path.split('.').every(function (prop) {
225 scope = value;
226 key = prop;
227 if (null == scope) {
228 // break
229 return false;
230 } else {
231 value = scope[key];
232 return true;
233 }
234 });
235 return validPath && { value: value, scope: scope, key: key };
236};
237
238var pathToVal = module.exports.pathToVal = function (dict, path, value, method) {
239 var chunks = 'string' == typeof path ? path.split('.') : path;
240 var chunk = chunks[0];
241 var rest = chunks.slice(1);
242 if (chunks.length == 1) {
243 var oldValue = dict[chunk];
244 if (value !== undefined) {
245 if (method !== undefined) {
246 method(value, dict, chunk);
247 } else {
248 dict[chunk] = value;
249 }
250 }
251 return oldValue;
252 }
253 return pathToVal(dict[chunk], rest, value, method);
254};
255
256String.prototype.interpolate = function (dict, marks) {
257 if (!marks)
258 marks = {};
259 marks.start = marks.start || '{';
260 marks.end = marks.end || '}';
261 marks.path = marks.path || '.';
262 marks.typeSafe = marks.typeSafe || '$';
263 marks.typeRaw = marks.typeRaw || '*';
264
265 // TODO: escape character range delims
266 var re = new RegExp([
267 '[', marks.start, ']',
268 '([', marks.typeSafe, marks.typeRaw, '])',
269 '([^', marks.end, ']+)',
270 '[', marks.end, ']'
271 ].join(''), 'g');
272
273 var startRe = new RegExp([
274 '[', marks.start, ']',
275 '([', marks.typeSafe, marks.typeRaw, '])'
276 ].join(''), 'g');
277
278 var values = [];
279
280 var replacedStr = this.replace(re, function (_, varType, varPath) {
281 if (varPath.indexOf(marks.path) > -1) {
282 var value = pathToVal(dict, varPath);
283 } else {
284 value = dict[varPath];
285 }
286
287 if (isEmpty(value) && varType == marks.typeSafe) {
288 value = undefined;
289 }
290
291 values.push(value);
292
293 return value;
294 });
295
296 if (values.some(function (v) { return (typeof v === "undefined"); })) {
297 return undefined;
298 }
299
300 if (values.length === 1 && (values[0] + '') === replacedStr) {
301 return values[0];
302 }
303
304 return replacedStr;
305};
306
307/**
308 * [waitAll wait all events to complete]
309 * @param {[type]} events array of event arrays: [[subject, eventName, description]]
310 * @param {Function} callback called after all events handled
311 * @return {[type]} [description]
312 */
313module.exports.waitAll = function waitAll (events, callback) {
314 var remaining = [];
315 function _listener (eventName) {
316 remaining.some (function (remainingName, idx) {
317 if (remainingName == eventName) {
318 remaining.splice (idx, 1);
319 return true;
320 }
321 })
322 // console.log ("wait for " + remaining.length + " more: " + remaining.join (', '));
323 if (!remaining.length)
324 callback();
325 }
326 events.forEach (function (event) {
327 var subject = event[0];
328 var eventName = event[1];
329 var eventLogName = eventName + ' ' + event[2];
330 remaining.push (eventLogName);
331 if (typeof subject === "function") {
332 subject (_listener.bind ($global, eventLogName));
333 } else {
334 if (subject.addEventListener) {
335 subject.addEventListener (eventName, _listener.bind (subject, eventLogName), false);
336 } else {
337 subject.on (eventName, _listener.bind (subject, eventLogName), false);
338 }
339
340 }
341
342 });
343}
344
345module.exports.isEmpty = isEmpty;