From: David Schoonover Date: Mon, 18 Jun 2012 19:54:13 +0000 (-0700) Subject: Adds generic non-Backbone base class. X-Git-Url: http://git.less.ly:3516/?a=commitdiff_plain;h=7c805a5bf548259b2fc4faaefb72f915cd3f5eb2;p=limn.git Adds generic non-Backbone base class. --- diff --git a/lib/base/base.co b/lib/base/base.co new file mode 100644 index 0000000..c35ed5d --- /dev/null +++ b/lib/base/base.co @@ -0,0 +1,73 @@ +{EventEmitter} = require 'events' +EventEmitter::trigger = EventEmitter::emit + +{ _, op +} = require 'kraken/util' + + + +/** + * @class Eventful base class. + * @extends EventEmitter + */ +class Base extends EventEmitter + + /** + * After the super chain has exhausted (but not necessarily at the end + * of init -- it depends on when you super()), Base will publish a 'new' + * event on the instance's class, allowing anyone to subscribe to + * notifications about new objects. + * @constructor + */ + -> + @__class__ = @.. + @__superclass__ = @..superclass + @__apply_bind__() + super() + @__class__.emit 'new', this + + + ### Auto-Bound methods + + /** + * A list of method-names to bind on `initialize`; set this on a subclass to override. + * @type Array + */ + __bind__ : [] + + /** + * Applies the contents of `__bind__`. + */ + __apply_bind__: -> + names = _ @pluckSuperAndSelf '__bind__' .chain().flatten().compact().unique().value() + _.bindAll this, ...names if names.length + + + + getClassName: -> + "#{@..name or @..displayName}" + + toString: -> + "#{@getClassName()}()" + + + + ### Class Methods + + @extended = (Subclass) -> + # copy over all class methods, including this + for own k, v in this + Subclass[k] = v if typeof v is 'function' + Subclass.__super__ = @:: + Subclass + + + + +for k of <[ getSuperClasses pluckSuper pluckSuperAndSelf ]> + Base[k] = Base::[k] = _.methodize _[k] + +Base import EventEmitter:: + + +module.exports = Base diff --git a/lib/base/index.co b/lib/base/index.co index 9a31587..17b6726 100644 --- a/lib/base/index.co +++ b/lib/base/index.co @@ -1,7 +1,9 @@ +exports.Base = require 'kraken/base/base' mixins = require 'kraken/base/base-mixin' models = require 'kraken/base/base-model' views = require 'kraken/base/base-view' cache = require 'kraken/base/model-cache' cascading = require 'kraken/base/cascading-model' data_binding = require 'kraken/base/data-binding' -exports import mixins import models import views import cache import cascading import data_binding +exports import mixins import models import views \ + import cache import cascading import data_binding diff --git a/lib/util/event/ready-emitter.co b/lib/util/event/ready-emitter.co index a247026..049ad1c 100644 --- a/lib/util/event/ready-emitter.co +++ b/lib/util/event/ready-emitter.co @@ -1,11 +1,10 @@ -{EventEmitter} = require 'events' -EventEmitter::trigger = EventEmitter::emit +Base = require 'kraken/base/base' /** * @class An EventEmitter that auto-triggers new handlers once "ready". */ -class ReadyEmitter extends EventEmitter +class ReadyEmitter extends Base readyEventName : 'ready' ready : false diff --git a/lib/util/event/waiting-emitter.co b/lib/util/event/waiting-emitter.co index 3cc2733..3f29ddf 100644 --- a/lib/util/event/waiting-emitter.co +++ b/lib/util/event/waiting-emitter.co @@ -1,12 +1,11 @@ -{EventEmitter} = require 'events' -EventEmitter::trigger = EventEmitter::emit - +Base = require 'kraken/base/base' /** * @class An EventEmitter with a ratchet-up waiting counter. + * @extends Base */ -class WaitingEmitter extends EventEmitter +class WaitingEmitter extends Base /** * Count of outstanding tasks. diff --git a/lib/util/underscore/functions.co b/lib/util/underscore/_functions.co similarity index 100% rename from lib/util/underscore/functions.co rename to lib/util/underscore/_functions.co diff --git a/lib/util/underscore/class.co b/lib/util/underscore/class.co new file mode 100644 index 0000000..1381cb4 --- /dev/null +++ b/lib/util/underscore/class.co @@ -0,0 +1,53 @@ +_ = require 'underscore' + + +_cls = + + /** + * @returns {Array} The list of all superclasses for this class + * or object. Typically does not include Object or Function due to + * the prototype's constructor being set by the subclass. + */ + getSuperClasses : function getSuperClasses(Cls) + return [] unless Cls + + if Cls.__superclass__ or Cls.superclass or Cls.__super__?.constructor + superclass = that unless that is Cls + unless superclass + Cls = Cls.constructor if typeof Cls is not 'function' + if Cls.__superclass__ or Cls.superclass or Cls.__super__?.constructor + superclass = that unless that is Cls + unless superclass then [] + else [superclass].concat getSuperClasses superclass + + /** + * Looks up an attribute on the prototype of each class in the class + * hierarchy. Values from Object or Function are not typically included -- + * see the note at `getSuperClasses()`. + * + * @param {Object} obj Object on which to reflect. + * @param {String} prop Property to nab. + * @returns {Array} List of the values, from closest parent to furthest. + */ + pluckSuper : (obj, prop) -> + return [] unless obj + _ _cls.getSuperClasses(obj) .chain() + .pluck 'prototype' + .pluck prop + .value() + + /** + * As `.pluckSuper()` but includes value of `prop` on passed `obj`. Values + * from Object or Function are not typically included -- see the note + * at `getSuperClasses()`. + * + * @returns {Array} List of the values, starting with the object's own + * value, and then moving from closest parent to furthest. + */ + pluckSuperAndSelf : (obj, prop) -> + return [] unless obj + [ obj[prop] ].concat _cls.pluckSuper(obj, prop) + + + +exports import _cls diff --git a/lib/util/underscore/function.co b/lib/util/underscore/function.co new file mode 100644 index 0000000..a6e50b7 --- /dev/null +++ b/lib/util/underscore/function.co @@ -0,0 +1,27 @@ +_ = require 'underscore' + +_fn = + + /** + * Decorates a function so that its receiver (`this`) is always added as the + * first argument, followed by the call arguments. + * @returns {Function} + */ + methodize : (fn) -> + m = fn.__methodized__ + return m if m + + g = fn.__genericized__ + return that if g?.__wraps__ + + m = fn.__methodized__ = (...args) -> + args.unshift this + fn.apply this, args + + m.__wraps__ = fn + m + + + +exports import _fn + diff --git a/lib/util/underscore/index.co b/lib/util/underscore/index.co index d24ced1..f59c17f 100644 --- a/lib/util/underscore/index.co +++ b/lib/util/underscore/index.co @@ -2,8 +2,10 @@ _ = require 'underscore' _.str = require 'underscore.string' _.mixin _.str.exports() +_.mixin require 'kraken/util/underscore/function' _.mixin require 'kraken/util/underscore/array' _.mixin require 'kraken/util/underscore/object' +_.mixin require 'kraken/util/underscore/class' _.mixin require 'kraken/util/underscore/kv' _.mixin require 'kraken/util/underscore/string'