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 = cc || {}; 35 36 // 37 function ClassManager(){ 38 //tells own name 39 return arguments.callee.name || (arguments.callee.toString()).match(/^function ([^(]+)/)[1]; 40 } 41 ClassManager.id=(0|(Math.random()*998)); 42 ClassManager.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 //find name of ClassManager 71 var Cstr = arguments.callee.ClassManager(); 72 73 //replace this._super 74 str = str.substring(0, sp)+ Cstr+'['+id+'].'+name+'.call(this'+coma+str.substring(bp+1); 75 } 76 return Function(params, str); 77 }; 78 ClassManager.compileSuper.ClassManager = ClassManager; 79 ClassManager.getNewID=function(){ 80 return this.id++; 81 }; 82 83 84 (function () { 85 var initializing = false, fnTest = /\b_super\b/; 86 var releaseMode = (document['ccConfig'] && document['ccConfig']['CLASS_RELEASE_MODE']) ? document['ccConfig']['CLASS_RELEASE_MODE'] : null; 87 if(releaseMode) 88 { 89 console.log("release Mode"); 90 } 91 92 /** 93 * The base Class implementation (does nothing) 94 * @class 95 */ 96 cc.Class = function () { 97 }; 98 99 /** 100 * Create a new Class that inherits from this Class 101 * @param {object} prop 102 * @return {function} 103 */ 104 cc.Class.extend = function (prop) { 105 var _super = this.prototype; 106 107 // Instantiate a base Class (but only create the instance, 108 // don't run the init constructor) 109 initializing = true; 110 var prototype = new this(); 111 initializing = false; 112 113 // The dummy Class constructor 114 function Class() { 115 // All construction is actually done in the init method 116 if (!initializing && this.ctor) 117 this.ctor.apply(this, arguments); 118 } 119 Class.id = ClassManager.getNewID(); 120 ClassManager[Class.id] = _super; 121 // Copy the properties over onto the new prototype 122 for (var name in prop) { 123 if(releaseMode && typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) 124 { 125 prototype[name] = ClassManager.compileSuper(prop[name], name, Class.id); 126 } 127 else if(typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])){ 128 prototype[name] = (function (name, fn) { 129 return function () { 130 var tmp = this._super; 131 132 // Add a new ._super() method that is the same method 133 // but on the super-Class 134 this._super = _super[name]; 135 136 // The method only need to be bound temporarily, so we 137 // remove it when we're done executing 138 var ret = fn.apply(this, arguments); 139 this._super = tmp; 140 141 return ret; 142 }; 143 })(name, prop[name]); 144 } 145 else{ 146 prototype[name] = prop[name]; 147 } 148 } 149 prototype.__pid = Class.id; 150 151 // Populate our constructed prototype object 152 Class.prototype = prototype; 153 154 // Enforce the constructor to be what we expect 155 Class.prototype.constructor = Class; 156 157 // And make this Class extendable 158 Class.extend = arguments.callee; 159 160 //add implementation method 161 Class.implement = function (prop) { 162 for (var name in prop) { 163 prototype[name] = prop[name]; 164 } 165 }; 166 return Class; 167 }; 168 })(); 169 170 // 171 // Another way to subclass: Using Google Closure. 172 // The following code was copied + pasted from goog.base / goog.inherits 173 // 174 cc.inherits = function (childCtor, parentCtor) { 175 /** @constructor */ 176 function tempCtor() {} 177 tempCtor.prototype = parentCtor.prototype; 178 childCtor.superClass_ = parentCtor.prototype; 179 childCtor.prototype = new tempCtor(); 180 childCtor.prototype.constructor = childCtor; 181 182 // Copy "static" method, but doesn't generate subclasses. 183 // for( var i in parentCtor ) { 184 // childCtor[ i ] = parentCtor[ i ]; 185 // } 186 }; 187 cc.base = function(me, opt_methodName, var_args) { 188 var caller = arguments.callee.caller; 189 if (caller.superClass_) { 190 // This is a constructor. Call the superclass constructor. 191 ret = caller.superClass_.constructor.apply( me, Array.prototype.slice.call(arguments, 1)); 192 return ret; 193 } 194 195 var args = Array.prototype.slice.call(arguments, 2); 196 var foundCaller = false; 197 for (var ctor = me.constructor; 198 ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) { 199 if (ctor.prototype[opt_methodName] === caller) { 200 foundCaller = true; 201 } else if (foundCaller) { 202 return ctor.prototype[opt_methodName].apply(me, args); 203 } 204 } 205 206 // If we did not find the caller in the prototype chain, 207 // then one of two things happened: 208 // 1) The caller is an instance method. 209 // 2) This method was not called by the right caller. 210 if (me[opt_methodName] === caller) { 211 return me.constructor.prototype[opt_methodName].apply(me, args); 212 } else { 213 throw Error( 214 'cc.base called from a method of one name ' + 215 'to a method of a different name'); 216 } 217 }; 218