1 /* 2 Class, version 2.7 3 Copyright (c) 2006, 2007, 2008, Alex Arnell <alex@twologic.com> 4 Licensed under the new BSD License. See end of file for full license terms. 5 6 Project page: http://code.google.com/p/inheritance/ 7 */ 8 9 var Class = (function() { 10 var __extending = {}; 11 12 return { 13 extend: function(parent, def) { 14 if (arguments.length == 1) { def = parent; parent = null; } 15 var func = function() { 16 if (arguments[0] == __extending) { return; } 17 this.initialize.apply(this, arguments); 18 }; 19 if (typeof(parent) == 'function') { 20 func.prototype = new parent( __extending); 21 } 22 var mixins = []; 23 if (def && def.include) { 24 if (def.include.reverse) { 25 // methods defined in later mixins should override prior 26 mixins = mixins.concat(def.include.reverse()); 27 } else { 28 mixins.push(def.include); 29 } 30 delete def.include; // clean syntax sugar 31 } 32 if (def) Class.inherit(func.prototype, def); 33 for (var i = 0; (mixin = mixins[i]); i++) { 34 Class.mixin(func.prototype, mixin); 35 } 36 return func; 37 }, 38 mixin: function (dest, src, clobber) { 39 clobber = clobber || false; 40 if (typeof(src) != 'undefined' && src !== null) { 41 for (var prop in src) { 42 if (clobber || (!dest[prop] && typeof(src[prop]) == 'function')) { 43 dest[prop] = src[prop]; 44 } 45 } 46 } 47 return dest; 48 }, 49 inherit: function(dest, src, fname) { 50 if (arguments.length == 3) { 51 var ancestor = dest[fname], descendent = src[fname], method = descendent; 52 descendent = function() { 53 var ref = this.parent; this.parent = ancestor; 54 var result = method.apply(this, arguments); 55 ref ? this.parent = ref : delete this.parent; 56 return result; 57 }; 58 // mask the underlying method 59 descendent.valueOf = function() { return method; }; 60 descendent.toString = function() { return method.toString(); }; 61 dest[fname] = descendent; 62 } else { 63 for (var prop in src) { 64 if (dest[prop] && typeof(src[prop]) == 'function') { 65 Class.inherit(dest, src, prop); 66 } else if (src.__lookupGetter__(prop)) { 67 dest.__defineGetter__(prop, src.__lookupGetter__(prop)); 68 } else if (src.__lookupSetter__(prop)) { 69 dest.__defineSetter__(prop, src.__lookupSetter__(prop)); 70 } else { 71 dest[prop] = src[prop]; 72 } 73 } 74 } 75 return dest; 76 }, 77 singleton: function() { 78 var args = arguments; 79 if (args.length == 2 && args[0].getInstance) { 80 var klass = args[0].getInstance(__extending); 81 // we're extending a singleton swap it out for it's class 82 if (klass) { args[0] = klass; } 83 } 84 85 return (function(args){ 86 // store instance and class in private variables 87 var instance = false; 88 var klass = Class.extend.apply(args.callee, args); 89 return { 90 getInstance: function () { 91 if (arguments[0] == __extending) return klass; 92 if (instance) return instance; 93 return (instance = new klass()); 94 } 95 }; 96 })(args); 97 } 98 }; 99 })(); 100 101 // finally remap Class.create for backward compatability with prototype 102 Class.create = function() { 103 return Class.extend.apply(this, arguments); 104 }; 105 106 exports.Class = Class; 107 exports.Class.create = Class.create; 108 109 /* 110 Redistribution and use in source and binary forms, with or without modification, are 111 permitted provided that the following conditions are met: 112 113 * Redistributions of source code must retain the above copyright notice, this list 114 of conditions and the following disclaimer. 115 * Redistributions in binary form must reproduce the above copyright notice, this 116 list of conditions and the following disclaimer in the documentation and/or other 117 materials provided with the distribution. 118 * Neither the name of typicalnoise.com nor the names of its contributors may be 119 used to endorse or promote products derived from this software without specific prior 120 written permission. 121 122 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 123 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 124 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 125 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 126 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 127 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 128 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 129 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 130 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 131 */ 132