vendor/assets/javascripts/emerson/view.js in emerson-0.0.3 vs vendor/assets/javascripts/emerson/view.js in emerson-0.0.4

- old
+ new

@@ -7,18 +7,30 @@ // Emerson Extension // -------------------------------------------------------------------------- // ### Emerson.view module // Entry point for defining a new View. - var define = ns.view = function(name, setup) { - return (library[name] = construct(name, setup || {})); + var view = ns.view = function(name, setup) { + return (views[name] = construct(name, setup || {})); }; + // ### Emerson.trait module + // Entry point for defining a new "trait". + // + // A trait can be thought of as a set of related behaviors and is essentially + // a special form of view. + // + // Traits have the additional capability of responding to an optional "mode" + // at intialization. + var trait = ns.trait = function(name, setup) { + return (traits[name] = construct(name, setup || {})); + }; + // ### Module API // * `ns` is a reference to the namespace. // * `init` is a hook for initializing the module. - _.extend(define, { + _.extend(view, { ns : ns, init : function init() { configure(); $('body').view(); } @@ -34,25 +46,21 @@ // ### $.view // // $.view(key); // // Accessor for defined Views. + $.view = function(key) { + return views[key]; + }; + + // ### $.trait // - // Note that, while it is possible to manually execute View methods on an - // object like so: + // $.trait(key); // - // $.view(key).fn.method.apply(object, arguments); - // - // such usage is not recommended as it: - // - // 1. circumvents the intentional transience provided by the framework. - // 2. is likely to cause issues in that the called method will be working - // with a non-initialized/-decorated object which may not have the - // expected API. - // - $.view = function(key) { - return library[key]; + // Accessor for defined Traits. See `$.view`. + $.trait = function(key) { + return traits[key]; }; // ### $.fn.view // // $(target).view() @@ -70,18 +78,16 @@ var as_view = element.add(element.find(selectors.view)).filter(selectors.view); var as_trait = element.add(element.find(selectors.traits)).filter(selectors.traits); _.each(as_view, function(html) { var element = $(html); - attach.apply(element, [element.data(attrs.view)]); + attach.call(element, views, [element.data(attrs.view)]); }); _.each(as_trait, function(html) { var element = $(html); - attach.apply(element, _.map(element.data(attrs.traits).split(/\s+/), function(key) { - return [':', key].join(''); - })); + attach.call(element, traits, element.data(attrs.traits).split(/\s+/), true); }); }); return this; }; @@ -119,12 +125,16 @@ // @private var selectors = {}; // Storage place for the defined Views. // @private - var library = {}; + var views = {}; + // Storage place for the defined Traits. + // @private + var traits = {}; + // Storage place for attachments made. // @private var attachments = {}; // emerson id, for tracking attachments. @@ -164,29 +174,38 @@ return sub; } // ### attach - // Given a (complex) list of keys, search the library for applicable View and - // Trait definitions to apply to the object. + // Given a (complex) list of keys, search the libraries for applicable View + // and Trait definitions to apply to the object. // // Keeps track of which definitions have been applied, and does not re-apply. // // NOTE: `this`, in this call, should be a baselib-extended object containing // a single element. e.g., // // _.each($(selector), function(element) { - // attach.apply($(element), [key, [subkey]]); + // attach.apply($(element), views, [key, [subkey]]); // }); - function attach() { + // + // The `mode_p` predicate argument indicates whether the view type may accept + // a "mode", which should be true for traits (not for views). + function attach(library, keys, mode_p) { var self = this, def; var id = eid(this[0]); - _.each(_.flatten(arguments), function(key) { - var set = (attachments[key] || (attachments[key] = [])); - var built, init, events; + _.each(_.flatten(keys), function(key) { + var mode, match, built, init, events, set; + if(mode_p && (match = /^([^(]+)\((.+)\)/.exec(key))) { + key = match[1]; + mode = match[2]; + } + + set = (attachments[key] || (attachments[key] = [])); + if(_.include(set, id)) { return; // do not re-apply. } // Build an instance, attach event handlers, initialize and record. @@ -197,11 +216,11 @@ _.each(events, function(handler, key) { bind(built, key, handler); }); - init.call(built); + init.call(built, mode); set.push(id); } }); return this; @@ -218,12 +237,20 @@ // 'click' : handler, // 'focus' : handler // }, // document : { // bind document, for events // 'click' : handler // fired outside of the view + // 'selector' : { // TODO + // 'click' : handler + // } // } // } // }); + // + // Emerson event handling differs from that of, say, stock jQuery in that + // `this` within the context of the handler will be a view instance. The + // event argument is unadultered, allowing access to the full set of targets + // as defined by the baselib (e.g., jQuery). // // Note that, in the document-binding case, an event like `click` would be a // bad idea. A more useful (and less costly) use case would be a form of // pub/sub. //