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