emerson 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -20,4 +20,5 @@ tmp
20
20
  .rspec
21
21
  .rvmrc
22
22
  .import/
23
- .sublime*
23
+ .sublime*
24
+ .wiprc
@@ -1,3 +1,3 @@
1
1
  module Emerson
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -1,4 +1,4 @@
1
- // Emerson.js 0.0.6
1
+ // Emerson.js 0.0.7
2
2
  //
3
3
  // (c) 2012 Corey Innis
4
4
  // Emerson may be freely distributed under the MIT license.
@@ -21,7 +21,7 @@
21
21
  }
22
22
 
23
23
  // Current version of the library. Keep in sync with `package.json`.
24
- Emerson.VERSION = '0.0.6';
24
+ Emerson.VERSION = '0.0.7';
25
25
 
26
26
  // Reference the base lib (one of jQuery, Zepto or Ender) as $.
27
27
  var $ = Emerson.base = (root.jQuery || root.Zepto || root.ender);
@@ -79,12 +79,12 @@
79
79
  var as_trait = element.add(element.find(selectors.traits)).filter(selectors.traits);
80
80
 
81
81
  _.each(as_view, function(html) {
82
- var element = $(html);
82
+ var element = $(html); // why jQuery here, if $sub() in a moment?
83
83
  attach.call(element, views, [element.data(attrs.view)]);
84
84
  });
85
85
 
86
86
  _.each(as_trait, function(html) {
87
- var element = $(html);
87
+ var element = $(html); // why jQuery here, if $sub() in a moment?
88
88
  attach.call(element, traits, element.data(attrs.traits).split(/\s+/), true);
89
89
  });
90
90
  });
@@ -97,21 +97,68 @@
97
97
  // --------------------------------------------------------------------------
98
98
 
99
99
  // ### View constructor.
100
- //
101
100
  // View instances are "subclasses" of the base lib object, decorated with our
102
101
  // View.prototype and the provided definition.
103
102
  function View() {}
104
103
 
105
- // View instance setup definition.
104
+ // ### View setup definition.
106
105
  _.extend(View, {
107
106
  setup : {
108
107
  initialize : function() {},
108
+ connected : false,
109
109
  subscribe : {}
110
110
  }
111
111
  });
112
112
 
113
- // View instance prototype definition.
114
- _.extend(View.prototype, {});
113
+ // ### View prototype definition.
114
+ // **TODO**: Add specs for #connect & #outlet.
115
+ //
116
+ // * `connect` specifies which, if any, `outlets` should be registered as
117
+ // methods on the instance.
118
+ //
119
+ // false - do not connect any outlets (default)
120
+ // true - connect all outlets
121
+ // [outlet(s)] - connect the named outlets.
122
+ //
123
+ // * `outlet` returns descendent element(s) with matching a `data-outlet`
124
+ // attribute. This may be used for a given outlet whether or not it has
125
+ // been "connected". Outlets are useful as a means of allowing for View
126
+ // and Trait definitions with somewhat flexible DOM. Rather than using
127
+ // specific selectors (or polluting the `class` attribute), the DOM for
128
+ // a given instance indicates which nodes should match for the View.
129
+ _.extend(View.prototype, {
130
+ connect : function(config) {
131
+ var self = this;
132
+ var outlets = this.find('[data-outlet]');
133
+
134
+ if(config === true) {
135
+ _.each(outlets, function(subject) {
136
+ var outlet = $(subject);
137
+
138
+ self[outlet.data('outlet')] = function() {
139
+ return outlet;
140
+ };
141
+ });
142
+ }
143
+ else if($.isArray(config)) {
144
+ _.each(config, function(key) {
145
+ var outlet = self.find('[data-outlet="' + key + '"]');
146
+
147
+ if(outlet.length) {
148
+ self[key] = function() {
149
+ return outlet;
150
+ };
151
+ }
152
+ });
153
+ }
154
+
155
+ return this;
156
+ },
157
+
158
+ outlet : function(key) {
159
+ return this.find('[data-outlet="' + key + '"]');
160
+ }
161
+ });
115
162
 
116
163
 
117
164
  // Internal Implementation
@@ -195,7 +242,7 @@
195
242
  var id = eid(this[0]);
196
243
 
197
244
  _.each(_.flatten(keys), function(key) {
198
- var mode, match, built, init, events, set;
245
+ var mode, match, built, init, events, set, setup;
199
246
 
200
247
  if(mode_p && (match = /^([^(]+)\((.+)\)/.exec(key))) {
201
248
  key = match[1];
@@ -208,17 +255,17 @@
208
255
  return; // do not re-apply.
209
256
  }
210
257
 
211
- // Build an instance, attach event handlers, initialize and record.
258
+ // Build an instance, connect outlets, bind events, init and record.
212
259
  if(def = library[key]) {
213
- built = def(self, self.context);
214
- init = def.setup.initialize;
215
- events = def.setup.subscribe;
260
+ setup = def.setup;
261
+ built = def(self, self.context);
262
+ built.connect(setup.connected);
216
263
 
217
- _.each(events, function(handler, key) {
264
+ _.each(setup.subscribe, function(handler, key) {
218
265
  bind(built, key, handler);
219
266
  });
220
267
 
221
- init.call(built, mode);
268
+ setup.initialize.call(built, mode);
222
269
  set.push(id);
223
270
  }
224
271
  });
@@ -231,17 +278,20 @@
231
278
  //
232
279
  // Emerson.view(key, {
233
280
  // subscribe : {
234
- // 'click' : handler, // simple
235
- // 'click focus' : handler, // multiple event types
236
- // 'selector' : { // specific child target
281
+ // 'click' : handler, // simple
282
+ // 'click focus' : handler, // multiple event types
283
+ // 'selector' : { // specific child target
237
284
  // 'click' : handler,
238
285
  // 'focus' : handler
239
286
  // },
240
- // document : { // bind document, for events
241
- // 'click' : handler // fired outside of the view
242
- // 'selector' : { // TODO
287
+ // document : { // bind document, for events
288
+ // 'click' : handler // fired outside of the view
289
+ // 'selector' : {
243
290
  // 'click' : handler
244
- // }
291
+ // }
292
+ // },
293
+ // 'outlet:name' : { // a custom key to specify a
294
+ // 'click' : handler // defined outlet as the scope
245
295
  // }
246
296
  // }
247
297
  // });
@@ -251,31 +301,38 @@
251
301
  // event argument is unadultered, allowing access to the full set of targets
252
302
  // as defined by the baselib (e.g., jQuery).
253
303
  //
254
- // Note that, in the document-binding case, an event like `click` would be a
255
- // bad idea. A more useful (and less costly) use case would be a form of
256
- // pub/sub.
304
+ // **Special notes regarding document-bound handlers**:
305
+ //
306
+ // Binding an event like `click` (without selector scope) to the document
307
+ // would likely be a bad idea. A more useful (and less costly) use case
308
+ // would be a sort of pub/sub. For example, view "A" could trigger an event
309
+ // indicating that it has rendered a new instance, to which "B" (elsewhere)
310
+ // would listen in order to update, say, a count of instances of "A".
257
311
  //
258
- // For example, view "A" could trigger an event indicating that it has
259
- // rendered a new instance, to which "B" (elsewhere) would listen in order
260
- // to update, say, a count of instances of "A".
261
- function bind(instance, key, handler, selector) {
312
+ // Additionally, event handlers bound to the document will not be cleaned
313
+ // up when the associated view instance is removed.
314
+ function bind(instance, key, handler, selector, binder) {
262
315
  if($.isPlainObject(handler)) {
263
- _.each(handler, function(subhandler, subkey) {
264
- bind(instance, subkey, subhandler, key);
265
- });
266
- }
267
- else {
268
- if(selector === 'document') {
269
- $(document).on(key, function() {
270
- return handler.apply(instance, arguments);
316
+ if(key === 'document') {
317
+ _.each(handler, function(subhandler, subkey) {
318
+ bind(instance, subkey, subhandler, undefined, $(document));
271
319
  });
272
320
  }
273
321
  else {
274
- instance.on(key, selector, function() {
275
- return handler.apply(instance, arguments);
322
+ _.each(handler, function(subhandler, subkey) {
323
+ bind(instance, subkey, subhandler, key, binder);
276
324
  });
277
325
  }
278
326
  }
327
+ else {
328
+ if(/^outlet/.test(selector)) {
329
+ selector = '[data-outlet="' + selector.split(':')[1] + '"]';
330
+ }
331
+
332
+ (binder || instance).on(key, selector, function() { // selector may be undefined
333
+ return handler.apply(instance, arguments);
334
+ });
335
+ }
279
336
  }
280
337
 
281
338
  // ### $sub
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emerson
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-13 00:00:00.000000000 Z
12
+ date: 2012-05-16 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: transcendent views
15
15
  email: