| 
									
										
										
										
											2016-08-20 23:45:54 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-08-21 01:52:57 +03:00
										 |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)( | 
					
						
							| 
									
										
										
										
											2016-08-20 23:45:54 +03:00
										 |  |  | function(require){ var module={} // makes module AMD/node compatible...
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-08-21 02:27:54 +03:00
										 |  |  | // Helpers...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX is this the right place for this???
 | 
					
						
							|  |  |  | // 		...when moving take care that ImageGrid's core.doc uses this...
 | 
					
						
							|  |  |  | var normalizeIndent = | 
					
						
							|  |  |  | module.normalizeIndent = | 
					
						
							|  |  |  | function(text){ | 
					
						
							|  |  |  | 	var lines = text.split(/\n/) | 
					
						
							|  |  |  | 	var l = lines  | 
					
						
							|  |  |  | 		.reduce(function(l, e, i){ | 
					
						
							|  |  |  | 			var indent = e.length - e.trimLeft().length | 
					
						
							|  |  |  | 			return e.trim().length == 0  | 
					
						
							|  |  |  | 					// ignore 0 indent of first line...
 | 
					
						
							|  |  |  | 					|| (i == 0 && indent == 0) ? l  | 
					
						
							|  |  |  | 				: l < 0 ?  | 
					
						
							|  |  |  | 					indent  | 
					
						
							|  |  |  | 				: Math.min(l, indent) | 
					
						
							|  |  |  | 		}, -1) | 
					
						
							|  |  |  | 	return lines | 
					
						
							|  |  |  | 		.map(function(line, i){  | 
					
						
							|  |  |  | 			return i == 0 ? line : line.slice(l) }) | 
					
						
							|  |  |  | 		.join('\n') | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2016-08-20 23:45:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 21:32:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Find the next parent method in the prototype chain.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	parent(meth, this)
 | 
					
						
							|  |  |  | // 	parent(meth, name, this)
 | 
					
						
							|  |  |  | // 		-> meth
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: there are cases where method.name is not set, so a name can be 
 | 
					
						
							|  |  |  | // 		passed explicitly.
 | 
					
						
							|  |  |  | // NOTE: this is super(..) replacement...
 | 
					
						
							|  |  |  | // NOTE: if method is root (no super method) this will return undefined.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // XXX should this return the method or the object???
 | 
					
						
							|  |  |  | var parent =  | 
					
						
							|  |  |  | module.parent = | 
					
						
							|  |  |  | function(method, name, that){ | 
					
						
							|  |  |  | 	if(arguments.length == 2){ | 
					
						
							|  |  |  | 		that = name | 
					
						
							|  |  |  | 		name = method.name | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// find the current method in the prototype chain...
 | 
					
						
							|  |  |  | 	while(!that.hasOwnProperty(name) || that[name] !== method){ | 
					
						
							|  |  |  | 		that = that.__proto__ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// return the next method...
 | 
					
						
							|  |  |  | 	return that.__proto__[name] | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-05 20:14:28 +03:00
										 |  |  | // Create an object and mix in sets of methods/props/attrs...
 | 
					
						
							| 
									
										
										
										
											2018-12-24 21:32:47 +03:00
										 |  |  | //
 | 
					
						
							|  |  |  | // 	mixin(root, object, ...)
 | 
					
						
							|  |  |  | // 		-> object
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This will create a new object per set of methods given and 
 | 
					
						
							|  |  |  | // Object.assign(..) the method set into this object leaving the 
 | 
					
						
							|  |  |  | // original objects intact.
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // 		root <-- object1_copy <-- .. <-- objectN_copy
 | 
					
						
							|  |  |  | // 				
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | var mixin =  | 
					
						
							|  |  |  | module.mixin =  | 
					
						
							|  |  |  | function(root, ...objects){ | 
					
						
							|  |  |  | 	return objects | 
					
						
							|  |  |  | 		.reduce(function(res, cur){ | 
					
						
							| 
									
										
										
										
											2019-07-05 20:14:28 +03:00
										 |  |  | 			var o = Object.create(res) | 
					
						
							|  |  |  | 			Object.keys(cur) | 
					
						
							|  |  |  | 				.map(function(k){ | 
					
						
							|  |  |  | 					Object.defineProperty(o, k, | 
					
						
							|  |  |  | 						Object.getOwnPropertyDescriptor(cur, k)) }) | 
					
						
							|  |  |  | 			return o }, root) } | 
					
						
							| 
									
										
										
										
											2018-12-24 21:32:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-05 20:34:19 +03:00
										 |  |  | // Like .mixin(..) but will mixin all the methods/props/attrs directly 
 | 
					
						
							|  |  |  | // (flatly) into root...
 | 
					
						
							|  |  |  | var mixinFlat =  | 
					
						
							|  |  |  | module.mixinFlat =  | 
					
						
							|  |  |  | function(root, ...objects){ | 
					
						
							|  |  |  | 	return objects | 
					
						
							|  |  |  | 		.reduce(function(root, cur){ | 
					
						
							|  |  |  | 			Object.keys(cur) | 
					
						
							|  |  |  | 				.map(function(k){ | 
					
						
							|  |  |  | 					Object.defineProperty(root, k, | 
					
						
							|  |  |  | 						Object.getOwnPropertyDescriptor(cur, k)) }) | 
					
						
							|  |  |  | 			return root }, root) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 21:32:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-21 02:27:54 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2016-08-20 23:45:54 +03:00
										 |  |  | // Make a JavaScrip object constructor...	
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Make a constructor with an object prototype...
 | 
					
						
							|  |  |  | // 		makeConstructor(<name>, <proto>)
 | 
					
						
							|  |  |  | // 			-> constructor
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Make a constructor with an init function prototype...
 | 
					
						
							|  |  |  | // 		makeConstructor(<name>, <init-func>)
 | 
					
						
							|  |  |  | // 			-> constructor
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Make a constructor with a prototype (object/function) and a class
 | 
					
						
							|  |  |  | // 	prototype...
 | 
					
						
							|  |  |  | // 		makeConstructor(<name>, <proto>, <class-proto>)
 | 
					
						
							|  |  |  | // 		makeConstructor(<name>, <init-func>, <class-proto>)
 | 
					
						
							|  |  |  | // 			-> constructor
 | 
					
						
							|  |  |  | // 			NOTE: the <class-proto> defines a set of class methods and 
 | 
					
						
							|  |  |  | // 					attributes.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The resulting constructor can produce objects in one of these ways:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Basic constructor use...
 | 
					
						
							|  |  |  | // 		constructor()
 | 
					
						
							|  |  |  | // 		new constructor
 | 
					
						
							|  |  |  | // 		new constructor()
 | 
					
						
							|  |  |  | // 			-> instance
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	Pass arguments to the constructor...
 | 
					
						
							|  |  |  | // 		constructor(<arg>[, ...])
 | 
					
						
							|  |  |  | // 		new constructor(<arg>[, ...])
 | 
					
						
							|  |  |  | // 			-> instance
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // All produced objects are instances of the constructor
 | 
					
						
							|  |  |  | // 		instance instanceof constructor
 | 
					
						
							|  |  |  | // 			-> true
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Init protocol:
 | 
					
						
							|  |  |  | // 	1) the base instance object is prepared (.__proto__ is set)
 | 
					
						
							|  |  |  | // 	2) if <init-func> is present, then it is called with instance as 
 | 
					
						
							|  |  |  | // 		context and passed the constructor arguments
 | 
					
						
							|  |  |  | // 	3) if <proto>.__init__(..) is present, it is called with the instance
 | 
					
						
							|  |  |  | // 		as context and passed the constructor arguments.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Inheritance:
 | 
					
						
							|  |  |  | // 	A simple way to build C -> B -> A chain would be:
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		var A = makeConstructor('A', {})
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		// NOTE: the prototype is an instance and not a constructor,
 | 
					
						
							|  |  |  | // 		//		this is obvious if one considers that in JS there are
 | 
					
						
							|  |  |  | // 		//		no classes and inheritance is done via object prototypes
 | 
					
						
							|  |  |  | // 		//		but this might be a gotcha to people coming from the 
 | 
					
						
							|  |  |  | // 		//		class-object world.
 | 
					
						
							|  |  |  | // 		var B = makeConstructor('B', A())
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		var C = makeConstructor('C', B())
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		var c = C()
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		c instanceof C		// -> true
 | 
					
						
							|  |  |  | // 		c instanceof B		// -> true
 | 
					
						
							|  |  |  | // 		c instanceof A		// -> true
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		A.prototype.x = 123
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 		c.x 				// -> 123
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Motivation:
 | 
					
						
							|  |  |  | // 	The general motivation here is to standardise the constructor protocol
 | 
					
						
							|  |  |  | // 	and make a single simple way to go with minimal variation. This is due
 | 
					
						
							|  |  |  | // 	to the JavaScript base protocol though quite simple, being too flexible
 | 
					
						
							|  |  |  | // 	making it very involved to produce objects in a consistent manner by 
 | 
					
						
							|  |  |  | // 	hand, especially in long running projects, in turn spreading all the 
 | 
					
						
							|  |  |  | // 	refactoring over multiple sites and styles.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // 	This removes part of the flexibility and in return gives us:
 | 
					
						
							|  |  |  | // 		- single, well defined protocol
 | 
					
						
							|  |  |  | // 		- one single spot where all the "magic" happens
 | 
					
						
							|  |  |  | // 		- full support for existing JavaScript ways of doing things
 | 
					
						
							|  |  |  | // 		- easy refactoring without touching the client code
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // NOTE: this sets the proto's .constructor attribute, this rendering it
 | 
					
						
							|  |  |  | // 		not reusable, to use the same prototype for multiple objects clone
 | 
					
						
							|  |  |  | // 		it via. Object.create(..) or copy it...
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // XXX might be a good idea to be able to make an instance without 
 | 
					
						
							|  |  |  | // 		initializing it...
 | 
					
						
							|  |  |  | // 		...mainly for inheritance.
 | 
					
						
							|  |  |  | // 		...would also be helpful in this case to call all the 
 | 
					
						
							|  |  |  | // 		constructors in the chain
 | 
					
						
							|  |  |  | var makeConstructor = | 
					
						
							|  |  |  | module.makeConstructor = | 
					
						
							|  |  |  | function makeConstructor(name, a, b){ | 
					
						
							|  |  |  | 	var proto = b == null ? a : b | 
					
						
							|  |  |  | 	var cls_proto = b == null ? b : a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var _constructor = function Constructor(){ | 
					
						
							|  |  |  | 		/* | 
					
						
							|  |  |  | 		// XXX BUG: if the constructor is called from it's instance this will 
 | 
					
						
							|  |  |  | 		// 		return the instance and not a new object...
 | 
					
						
							|  |  |  | 		// in case this is called as a function (without new)...
 | 
					
						
							|  |  |  | 		if(this.constructor !== _constructor){ | 
					
						
							|  |  |  | 			// NOTE: the following does the job of the 'new' operator but
 | 
					
						
							|  |  |  | 			// 		with one advantage, we can now pass arbitrary args 
 | 
					
						
							|  |  |  | 			// 		in...
 | 
					
						
							|  |  |  | 			// 		This is equivalent to:
 | 
					
						
							|  |  |  | 			//			return new _constructor(json)
 | 
					
						
							|  |  |  | 			var obj = {} | 
					
						
							|  |  |  | 			obj.__proto__ = _constructor.prototype | 
					
						
							|  |  |  | 			// XXX for some reason this does not resolve from .__proto__
 | 
					
						
							|  |  |  | 			obj.constructor = _constructor | 
					
						
							|  |  |  | 			//obj.__proto__.constructor = _constructor
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			var obj = this | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// NOTE: the following does the job of the 'new' operator but
 | 
					
						
							|  |  |  | 		// 		with one advantage, we can now pass arbitrary args 
 | 
					
						
							|  |  |  | 		// 		in...
 | 
					
						
							|  |  |  | 		// 		This is equivalent to:
 | 
					
						
							|  |  |  | 		//			return new _constructor(json)
 | 
					
						
							|  |  |  | 		var obj = {} | 
					
						
							|  |  |  | 		obj.__proto__ = _constructor.prototype | 
					
						
							|  |  |  | 		// XXX for some reason this does not resolve from .__proto__
 | 
					
						
							|  |  |  | 		// XXX this also is a regular attr and not a prop...
 | 
					
						
							|  |  |  | 		//obj.constructor = _constructor
 | 
					
						
							|  |  |  | 		Object.defineProperty(obj, 'constructor', { | 
					
						
							|  |  |  | 			value: _constructor, | 
					
						
							|  |  |  | 			enumerable: false, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 		//obj.__proto__.constructor = _constructor
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// explicit init...
 | 
					
						
							|  |  |  | 		if(proto instanceof Function){ | 
					
						
							|  |  |  | 			proto.apply(obj, arguments) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// load initial state...
 | 
					
						
							|  |  |  | 		if(obj.__init__ != null){ | 
					
						
							|  |  |  | 			obj.__init__.apply(obj, arguments) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return obj | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* XXX for some reason this works for the _constructor but all  | 
					
						
							|  |  |  | 	 * 		instances get the wrong name resolved... | 
					
						
							|  |  |  | 	Object.defineProperty(_constructor, 'name', { | 
					
						
							|  |  |  | 		value: name, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// just in case the browser refuses to change the name, we'll make it
 | 
					
						
							|  |  |  | 	// a different offer ;)
 | 
					
						
							|  |  |  | 	if(_constructor.name == 'Constructor'){ | 
					
						
							|  |  |  | 			// skip for chrome app...
 | 
					
						
							|  |  |  | 			//&& !(window.chrome && chrome.runtime && chrome.runtime.id)){
 | 
					
						
							|  |  |  | 		eval('_constructor = '+ _constructor | 
					
						
							|  |  |  | 				.toString() | 
					
						
							|  |  |  | 				.replace(/Constructor/g, name)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-20 16:01:37 +03:00
										 |  |  | 	// set an informative .toString...
 | 
					
						
							|  |  |  | 	// NOTE: do this only if .toString(..) is not defined by user...
 | 
					
						
							| 
									
										
										
										
											2018-08-20 16:10:06 +03:00
										 |  |  | 	if((cls_proto || {}).toString() == ({}).toString()){ | 
					
						
							| 
									
										
										
										
											2018-08-20 16:01:37 +03:00
										 |  |  | 		// XXX is this the right way to go or should we set this openly???
 | 
					
						
							|  |  |  | 		Object.defineProperty(_constructor, 'toString', { | 
					
						
							|  |  |  | 			value: function(){  | 
					
						
							|  |  |  | 				var args = proto.__init__ ? | 
					
						
							|  |  |  | 					proto.__init__ | 
					
						
							|  |  |  | 						.toString() | 
					
						
							|  |  |  | 						.split(/\n/)[0].replace(/function\(([^)]*)\){.*/, '$1') | 
					
						
							|  |  |  | 					: '' | 
					
						
							|  |  |  | 				var code = proto.__init__ ? | 
					
						
							|  |  |  | 					proto.__init__ | 
					
						
							|  |  |  | 						.toString() | 
					
						
							|  |  |  | 						.replace(/[^{]*{/, '{') | 
					
						
							|  |  |  | 					: '{ .. }' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-21 02:27:54 +03:00
										 |  |  | 				return `${this.name}(${args})${normalizeIndent(code)}` | 
					
						
							| 
									
										
										
										
											2018-08-20 16:01:37 +03:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 			enumerable: false, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-19 16:10:23 +03:00
										 |  |  | 	_constructor.__proto__ = cls_proto | 
					
						
							| 
									
										
										
										
											2016-08-20 23:45:54 +03:00
										 |  |  | 	_constructor.prototype = proto | 
					
						
							|  |  |  | 	_constructor.prototype.constructor = _constructor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return _constructor | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-24 21:20:38 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-20 23:45:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | /********************************************************************** | 
					
						
							|  |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |