/* * def.js: Simple Ruby-style inheritance for JavaScript * * Copyright (c) 2010 Tobias Schneider * This script is freely distributable under the terms of the MIT license. * * Featuring contributions by * John-David Dalton * Dmitry A. Soshnikov * Devon Govett */ (function(global){ // used to defer setup of superclass and properties var deferred; function extend(source){ var prop, target = this.prototype; for(var key in source) if(source.hasOwnProperty(key)){ prop = target[key] = source[key]; // check if we're overwriting an existing function if('function' == typeof prop){ // mark each method with its name and surrounding class prop._name = key; prop._class = this; } } return this; } // calls same method as its caller but in the superclass // based on http://github.com/shergin/legacy by Valentin Shergin function base(){ // cross browser support > strict mode compatibility var caller = arguments.callee.caller; // arguments automatically passed to super if none provided return caller._class._super.prototype[caller._name] .apply(this, arguments.length ? arguments : caller.arguments); } function def(context, klassName){ klassName || (klassName = context, context = global); // create class on given context (defaults to global object) var Klass = context[klassName] = function Klass(){ if(context != this){ // called as a constructor // allow init to return a different class/object return this.init && this.init.apply(this, arguments); } // called as a function - defer setup of superclass and properties deferred._super = Klass; deferred._props = arguments[0] || { }; } // make this class extendable Klass.extend = extend; // called as function to set properties deferred = function(props){ return Klass.extend(props); }; // dummy subclass function Subclass(){ } // valueOf is called to setup inheritance from a superclass deferred.valueOf = function(){ var Superclass = deferred._super; if(!Superclass){ return Klass; } // inherit from superclass Subclass.prototype = Superclass.prototype; var proto = Klass.prototype = new Subclass; // reference base and superclass Klass._class = Klass; Klass._super = Superclass; Klass.toString = function(){ return klassName; }; // enforce the constructor to be what we expect proto.constructor = Klass; // to call original methods in the superclass proto._super = base; // set properties deferred(deferred._props); }; return deferred; } // expose def to the global object global.def = def; }(this));