(function () { /** @namespace itm */ itm = this.itm || {}; itm.version = "0.1"; /** Class function
* Designed to create JavaScript Classes
*
* It does the inheritance, checks for arguments,
* adds the core patch to it and calls the init() method.
*
*
* To create a class do this: *

     * myClass=itm.Class(mySuperClass,myPrototype) //(mySuperClass and myPrototype are optional)
     * myClass.protoype.init=function()
     * {
	 *  	//call constructor of superclass
	 *  	mySuperClass.prototype.init.call(this,arg1,arg2...);
	 *  	//or this.superInit(mySuperClass,arg1,arg2...);
	 *  	//or this.superInitApply(mySuperClass,arguments);
	 *
	 *  	//your constructor
	 * }
     * 
* * @memberOf itm * @param {function} [superClass] * @param {object} [prototype] * @returns {function} newClass */ itm.Class = function (superClass, prototype) { var _superClass = superClass; var _prototype = prototype; if (typeof _superClass == "object") { _prototype = _superClass; _superClass = null; } var newClass = function () { if (this instanceof itm.Patch) { this.init.apply(this, arguments); } else if (arguments.length > 0) { itm.Class.attachListener(this); new itm.Patch(this); this.init.apply(this, arguments); this.fireListeners("created"); } }; newClass.prototype.superInit = function (_class/*,arg1,arg2,...,argN*/) { _class.prototype.init.apply(this, [].slice.call(arguments, 1)); }; newClass.prototype.superInitApply = function (_class, args) { this.superInit.apply(this, [_class].concat([].slice.call(args))); }; if (_superClass) { newClass.prototype = new _superClass(); } newClass.prototype.constructor = newClass; for (var i in _prototype) { newClass.prototype[i] = _prototype[i]; } return newClass; }; /** * @param {object} scope target for listeners */ itm.Class.attachListener = function (scope) { var created = [function () { created.fired = true; }]; created.fired = false; created._push = created.push; created.push = function (fn) { if (this.fired) fn(); else this._push(fn); }; scope.listeners = {"created": created}; scope.createListener = function (type/*,fn1,fn2,...,fnN*/) { var typeArr = type.split(/[ |,]+/); for (var i = 0; i < typeArr.length; i++) { if (this.listeners[typeArr[i]] == null) this.listeners[typeArr[i]] = []; } this.addListener.apply(this, arguments); }; scope.addListener = function (type/*,fn1,fn2,...,fnN*/) { var typeArr = type.split(/[ |,]+/); var rtnArr = []; var fnArr = [].slice.call(arguments, 1); for (var i = 0; i < typeArr.length; i++) { if (this.listeners[typeArr[i]] != null) { for (var f = 0; f < fnArr.length; f++) rtnArr.push(this.listeners[typeArr[i]].push(fnArr[f])); } } return rtnArr; }; scope.removeListener = function (type/*,fn1,fn2,...,fnN*/) { var typeArr = type.split(/[ |,]+/); var fnArr = [].slice.call(arguments, 1); for (var i = 0; i < typeArr.length; i++) { if (this.listeners[typeArr[i]]) { for (var k = 0; k < this.listeners[typeArr[i]].length; k++) { for (var j = 0; j < fnArr.length; j++) { if (fnArr[j] == this.listeners[typeArr[i]][k]) { this.listeners[typeArr[i]].splice(k, 1); k--; j = fnArr.length; } } } } } }; scope.removeAllListeners = function (type) { if (type == "ALL") { for (var i in this.listeners) { this.listeners[i] = []; } } else { var typeArr = type.split(/[ |,]+/); for (var i = 0; i < typeArr.length; i++) { if (this.listeners[typeArr[i]] != null) this.listeners[typeArr[i]] = []; } } }; scope.fireListeners = function (type/*,arg1,arg2,...,argN*/) { var rtn = true; for (var i = 0; this.listeners[type] && i < this.listeners[type].length && rtn; i++) { rtn = this.listeners[type][i].apply(this, arguments) !== false; } return rtn; }; }; itm.Patch = itm.Class( /** @lends itm.Patch# */ { /** Patch
* Adds functionality to an instance
*
* Patches add themself in a the "patches" map of the instance with their patchID
* The core patch adds the "patches" map and the functions "hasPatch" and "getPatch"
*
* Normally a Patch does not add functions direct to the instance but uses listeners
*
*
* To create a new patch do sth. like this: *

         * var myPatch=itm.Class(itm.patch,
         * {
         * 		patchID:"myPatchID",
         * 		patch:function(param,noListeners)
         * 		{
         * 			this.superPatch(itm.patch);//call super.patch // in case of itm.Patch its not necessary
         * 			//your constructor after instance is created
         * 		}
         * }
         * 
* The "patch" function is called on the create event (when the constructor of the instance is finished)
* If the instance has no listeners, "noListeners" is true and "patch" was called immediately
*
* If you want to override the init function do it like this: *

         * var myPatch=itm.Class(mySuperPatch,
         * {
         * 		patchID:"myPatchID",
         * 		init:function(instance,param)
         * 		{
         * 			//call constructor of superclass
         * 			this.superInit(mySuperPatch,instance,param);
         * 			//or this.superInitApply(mySuperPatch,arguments);
         *
         * 			if(this.instance!=null)
         * 			{
         * 				//your constructor
         * 				//post patch:  this.instance.addListener("created",function(param,noListeners){})
         * 			}
         * 		},
         * 		patch:function(param,noListeners)
         * 		{
         * 			this.superPatch(mySuperPatch,param,noListeners);
         * 			//post constructor
         * 		}
         * }
         * 
* @name itm.Patch * @class * @constructor * @abstract * @param {object} instance * @param {*} [param] */ init: function (instance, param) { if (this.constructor === itm.Patch && instance) { if (!instance.patches) { instance.patches = {}; instance.hasPatch = function (patch) { return this.getPatch(patch) != null; }; instance.getPatch = function (patch) { return this.patches[patch.patchID || patch.prototype.patchID]; }; } } else if (instance && !instance.hasPatch(this)) { this.instance = instance; instance.patches[this.patchID] = this; if (this.instance.addListener) { var _self = this; this.instance.addListener("created", function () { _self.patch(param); }); } else { this.patch(param, true); } } }, /** * @abstract * @param {*} param * @param {boolean} noListeners */ patch: function (param, noListeners) { }, /** * @param {function} _class * @param {...*} [args] */ superPatch: function (_class/*,arg1,arg2,...,argN*/) { _class.prototype.patch.apply(this, [].slice.call(arguments, 1)); }, /** * * @param {function} _class * @param {Array} args */ superPatchApply: function (_class, args) { this.superPatch.apply(this, [_class].concat([].slice.call(args))); } }); /** * checks if instance is already patched * @static * @memberOf itm.Patch * @param {object} instance * @param {function|itm.Patch} patch * @returns {boolean} */ itm.Patch.hasPatch = function (instance, patch) { return itm.Patch.getPatch(instance, patch) != null; }; /** * @static * @memberOf itm.Patch * @param {object} instance * @param {function|itm.Patch} patch * @returns {null|itm.Patch} */ itm.Patch.getPatch = function (instance, patch) { return instance.getPatch && instance.getPatch(patch) || null; }; /** * patches an instance and returns it
* patch and param can be repeated as much as you like * * @static * @memberOf itm.Patch * @param {object} instance * @param {function} patch * @param {*} param * @returns {object} instance */ itm.Patch.Factory = function (instance, patch, param/*,patch,param,...*/) { for (var i = 1; i < arguments.length; i += 2) new arguments[i](instance, arguments[i + 1]); return instance; }; })();