1 /**************************************************************************** 2 Copyright (c) 2010-2012 cocos2d-x.org 3 Copyright (c) 2008-2010 Ricardo Quesada 4 Copyright (c) 2011 Zynga Inc. 5 6 http://www.cocos2d-x.org 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy 9 of this software and associated documentation files (the "Software"), to deal 10 in the Software without restriction, including without limitation the rights 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 copies of the Software, and to permit persons to whom the Software is 13 furnished to do so, subject to the following conditions: 14 15 The above copyright notice and this permission notice shall be included in 16 all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 THE SOFTWARE. 25 ****************************************************************************/ 26 /* Managed JavaScript Inheritance 27 * Based on John Resig's Simple JavaScript Inheritance http://ejohn.org/blog/simple-javascript-inheritance/ 28 * MIT Licensed. 29 */ 30 31 /** 32 * @namespace 33 */ 34 var cc = cc || {}; 35 36 // 37 var ClassManager = { 38 id : (0|(Math.random()*998)), 39 40 instanceId : (0|(Math.random()*998)), 41 42 compileSuper : function(func, name, id){ 43 //make the func to a string 44 var str = func.toString(); 45 //find parameters 46 var pstart = str.indexOf('('); 47 var pend = str.indexOf(')'); 48 var params = str.substring(pstart+1, pend); 49 params = params.trim(); 50 51 //find function body 52 var bstart = str.indexOf('{'); 53 var bend = str.lastIndexOf('}'); 54 var str = str.substring(bstart+1, bend); 55 56 //now we have the content of the function, replace this._super 57 //find this._super 58 while(str.indexOf('this._super')!= -1) 59 { 60 var sp = str.indexOf('this._super'); 61 //find the first '(' from this._super) 62 var bp = str.indexOf('(', sp); 63 64 //find if we are passing params to super 65 var bbp = str.indexOf(')', bp); 66 var superParams = str.substring(bp+1, bbp); 67 superParams = superParams.trim(); 68 var coma = superParams? ',':''; 69 70 //replace this._super 71 str = str.substring(0, sp)+ 'ClassManager['+id+'].'+name+'.call(this'+coma+str.substring(bp+1); 72 } 73 return Function(params, str); 74 }, 75 76 getNewID : function(){ 77 return this.id++; 78 }, 79 80 getNewInstanceId : function(){ 81 return this.instanceId++; 82 } 83 }; 84 ClassManager.compileSuper.ClassManager = ClassManager; 85 86 (function () { 87 var initializing = false, fnTest = /\b_super\b/; 88 var releaseMode = (document['ccConfig'] && document['ccConfig']['CLASS_RELEASE_MODE']) ? document['ccConfig']['CLASS_RELEASE_MODE'] : null; 89 if(releaseMode) { 90 console.log("release Mode"); 91 } 92 93 /** 94 * The base Class implementation (does nothing) 95 * @class 96 */ 97 cc.Class = function () { 98 }; 99 100 /** 101 * Create a new Class that inherits from this Class 102 * @param {object} prop 103 * @return {function} 104 */ 105 cc.Class.extend = function (prop) { 106 var _super = this.prototype; 107 108 // Instantiate a base Class (but only create the instance, 109 // don't run the init constructor) 110 var prototype = Object.create(_super); 111 112 var classId = ClassManager.getNewID(); 113 ClassManager[classId] = _super; 114 // Copy the properties over onto the new prototype. We make function 115 // properties non-eumerable as this makes typeof === 'function' check 116 // unneccessary in the for...in loop used 1) for generating Class() 117 // 2) for cc.clone and perhaps more. It is also required to make 118 // these function properties cacheable in Carakan. 119 var desc = { writable: true, enumerable: false, configurable: true }; 120 for (var name in prop) { 121 if(releaseMode && typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) { 122 desc.value = ClassManager.compileSuper(prop[name], name, classId); 123 Object.defineProperty(prototype, name, desc); 124 } else if(typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])){ 125 desc.value = (function (name, fn) { 126 return function () { 127 var tmp = this._super; 128 129 // Add a new ._super() method that is the same method 130 // but on the super-Class 131 this._super = _super[name]; 132 133 // The method only need to be bound temporarily, so we 134 // remove it when we're done executing 135 var ret = fn.apply(this, arguments); 136 this._super = tmp; 137 138 return ret; 139 }; 140 })(name, prop[name]); 141 Object.defineProperty(prototype, name, desc); 142 } else if(typeof prop[name] == "function") { 143 desc.value = prop[name]; 144 Object.defineProperty(prototype, name, desc); 145 } else{ 146 prototype[name] = prop[name]; 147 } 148 } 149 prototype.__instanceId = null; 150 151 // The dummy Class constructor 152 function Class() { 153 this.__instanceId = ClassManager.getNewInstanceId(); 154 // All construction is actually done in the init method 155 if (this.ctor) 156 this.ctor.apply(this, arguments); 157 } 158 159 Class.id = classId; 160 // desc = { writable: true, enumerable: false, configurable: true, 161 // value: XXX }; Again, we make this non-enumerable. 162 desc.value = classId; 163 Object.defineProperty(prototype, '__pid', desc); 164 165 // Populate our constructed prototype object 166 Class.prototype = prototype; 167 168 // Enforce the constructor to be what we expect 169 desc.value = Class; 170 Object.defineProperty(Class.prototype, 'constructor', desc); 171 172 // And make this Class extendable 173 Class.extend = cc.Class.extend; 174 175 //add implementation method 176 Class.implement = function (prop) { 177 for (var name in prop) { 178 prototype[name] = prop[name]; 179 } 180 }; 181 return Class; 182 }; 183 184 Function.prototype.bind = Function.prototype.bind || function (bind) { 185 var self = this; 186 var args = Array.prototype.slice.call(arguments, 1); 187 return function () { 188 return self.apply(bind || null, args.concat(Array.prototype.slice.call(arguments))); 189 }; 190 }; 191 192 })(); 193 194 // 195 // Another way to subclass: Using Google Closure. 196 // The following code was copied + pasted from goog.base / goog.inherits 197 // 198 cc.inherits = function (childCtor, parentCtor) { 199 /** @constructor */ 200 function tempCtor() {} 201 tempCtor.prototype = parentCtor.prototype; 202 childCtor.superClass_ = parentCtor.prototype; 203 childCtor.prototype = new tempCtor(); 204 childCtor.prototype.constructor = childCtor; 205 206 // Copy "static" method, but doesn't generate subclasses. 207 // for( var i in parentCtor ) { 208 // childCtor[ i ] = parentCtor[ i ]; 209 // } 210 }; 211 cc.base = function(me, opt_methodName, var_args) { 212 var caller = arguments.callee.caller; 213 if (caller.superClass_) { 214 // This is a constructor. Call the superclass constructor. 215 ret = caller.superClass_.constructor.apply( me, Array.prototype.slice.call(arguments, 1)); 216 return ret; 217 } 218 219 var args = Array.prototype.slice.call(arguments, 2); 220 var foundCaller = false; 221 for (var ctor = me.constructor; ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) { 222 if (ctor.prototype[opt_methodName] === caller) { 223 foundCaller = true; 224 } else if (foundCaller) { 225 return ctor.prototype[opt_methodName].apply(me, args); 226 } 227 } 228 229 // If we did not find the caller in the prototype chain, 230 // then one of two things happened: 231 // 1) The caller is an instance method. 232 // 2) This method was not called by the right caller. 233 if (me[opt_methodName] === caller) { 234 return me.constructor.prototype[opt_methodName].apply(me, args); 235 } else { 236 throw Error( 237 'cc.base called from a method of one name ' + 238 'to a method of a different name'); 239 } 240 }; 241 242 cc.concatObjectProperties = function(dstObject, srcObject){ 243 if(!dstObject) 244 dstObject = {}; 245 246 for(var selKey in srcObject){ 247 dstObject[selKey] = srcObject[selKey]; 248 } 249 return dstObject; 250 }; 251 252