sudojs-rails 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,19 +11,36 @@ var sudo = {
11
11
  //
12
12
  // `namespace`
13
13
  ext: {},
14
- // ###_inherit_
14
+ // ###getPath
15
+ // Extract a value located at `path` relative to the passed in object
16
+ //
17
+ // `param` {String} `path`. The key in the form of a dot-delimited path.
18
+ // `param` {object} `obj`. An object literal to operate on.
19
+ //
20
+ // `returns` {*|undefined}. The value at keypath or undefined if not found.
21
+ getPath: function getPath(path, obj) {
22
+ var key, p;
23
+ p = path.split('.');
24
+ for (key; p.length && (key = p.shift());) {
25
+ if(!p.length) {
26
+ return obj[key];
27
+ } else {
28
+ obj = obj[key] || {};
29
+ }
30
+ }
31
+ return obj;
32
+ },
33
+ // ###inherit
15
34
  // Inherit the prototype from a parent to a child.
16
35
  // Set the childs constructor for subclasses of child.
17
- // A _private_ method as subclasses of the library base classes will not
36
+ // Subclasses of the library base classes will not
18
37
  // want to use this function in *most* use-cases. Why? User Sudo Class Objects
19
38
  // possess their own constructors and any call back to a `superclass` constructor
20
39
  // will generally be looking for the library Object's constructor.
21
40
  //
22
41
  // `param` {function} `parent`
23
42
  // `param` {function} `child`
24
- //
25
- // `private`
26
- _inherit_: function _inherit_(parent, child) {
43
+ inherit: function inherit(parent, child) {
27
44
  child.prototype = Object.create(parent.prototype);
28
45
  child.prototype.constructor = child;
29
46
  },
@@ -34,13 +51,12 @@ var sudo = {
34
51
  // `returns` {string}
35
52
  makeMeASandwich: function makeMeASandwich() {return 'Okay.';},
36
53
  // ###namespace
37
- // Convenience method for assuring a Namespace is defined. Uses
38
- // the optional `obj` arg with the Base objects `setPath` method.
54
+ // Method for assuring a Namespace is defined.
39
55
  //
40
56
  // `param` {string} `path`. The path that leads to a blank Object.
41
57
  namespace: function namespace(path) {
42
- if (!sudo.Base.prototype.getPath.call(this, path, window)) {
43
- sudo.Base.prototype.setPath.call(this, path, {}, window);
58
+ if (!this.getPath(path, window)) {
59
+ this.setPath(path, {}, window);
44
60
  }
45
61
  },
46
62
  // ###premier
@@ -48,39 +64,69 @@ var sudo = {
48
64
  //
49
65
  // `type` {Object}
50
66
  premier: null,
51
- // ####_uid_
67
+ // ###setPath
68
+ // Traverse the keypath and get each object
69
+ // (or make blank ones) eventually setting the value
70
+ // at the end of the path
71
+ //
72
+ // `param` {string} `path`. The path to traverse when setting a value.
73
+ // `param` {*} `value`. What to set.
74
+ // `param` {Object} `obj`. The object literal to operate on.
75
+ setPath: function setPath(path, value, obj) {
76
+ var p = path.split('.'), key;
77
+ for (key; p.length && (key = p.shift());) {
78
+ if(!p.length) {
79
+ obj[key] = value;
80
+ } else if (obj[key]) {
81
+ obj = obj[key];
82
+ } else {
83
+ obj = obj[key] = {};
84
+ }
85
+ }
86
+ },
87
+ // ####uid
52
88
  // Some sudo Objects use a unique integer as a `tag` for identification.
53
89
  // (Views for example). This ensures they are indeed unique.
54
- //
55
- // `private`
56
- _uid_: 0,
57
- // ####_unique_
90
+ uid: 0,
91
+ // ####unique
58
92
  // An integer used as 'tags' by some sudo Objects as well
59
93
  // as a unique string for views when needed
60
94
  //
61
95
  // `param` {string} prefix. Optional string identifier
62
- //
63
- // `private`
64
- _unique_: function _unique_(prefix) {
65
- return prefix ? prefix + this._uid_++ : this._uid_++;
96
+ unique: function unique(prefix) {
97
+ return prefix ? prefix + this.uid++ : this.uid++;
98
+ },
99
+ // ###unsetPath
100
+ // Remove a key:value pair from this object's data store
101
+ // located at <path>
102
+ //
103
+ // `param` {String} `path`
104
+ // `param` {Object} `obj` The object to operate on.
105
+ unsetPath: function unsetPath(path, obj) {
106
+ var p = path.split('.'), key;
107
+ for (key; p.length && (key = p.shift());) {
108
+ if(!p.length) {
109
+ delete obj[key];
110
+ } else {
111
+ // this can fail if a faulty path is passed.
112
+ // using getPath beforehand can prevent that
113
+ obj = obj[key];
114
+ }
115
+ }
66
116
  }
67
117
  };
68
118
  // ##Base Class Object
69
119
  //
70
- // All sudo.js objects inherit base
71
- //
72
- // `param` {Object} data. An optional data object for this instance.
120
+ // All sudo.js objects inherit base, giving the ability
121
+ // to utilize delegation, the `base` function and the
122
+ // `construct` convenience method.
73
123
  //
74
124
  // `constructor`
75
- sudo.Base = function(data) {
76
- this._data_ = data || {};
125
+ sudo.Base = function() {
77
126
  // can delegate
78
- this._delegates_ = [];
79
- // may implement `observable`
80
- this._callbacks_ = [];
81
- this._changeRecords_ = [];
127
+ this.delegates = [];
82
128
  // a beautiful and unique snowflake
83
- this._uid_ = sudo._unique_();
129
+ this.uid = sudo.unique();
84
130
  };
85
131
  // ###addDelegate
86
132
  // Push an instance of a Class Object into this object's `_delegates_` list.
@@ -88,8 +134,8 @@ sudo.Base = function(data) {
88
134
  // `param` {Object} an instance of a sudo.delegates Class Object
89
135
  // `returns` {Object} `this`
90
136
  sudo.Base.prototype.addDelegate = function addDelegate(del) {
91
- del._delegator_ = this;
92
- this._delegates_.push(del);
137
+ del.delegator = this;
138
+ this.delegates.push(del);
93
139
  return this;
94
140
  };
95
141
  // ###base
@@ -99,6 +145,7 @@ sudo.Base.prototype.addDelegate = function addDelegate(del) {
99
145
  // that the first match is not the function that called `base`.
100
146
  //
101
147
  // `params` {*} any other number of arguments to be passed to the looked up method
148
+ // along with the initial method name
102
149
  sudo.Base.prototype.base = function base() {
103
150
  var args = Array.prototype.slice.call(arguments),
104
151
  name = args.shift(),
@@ -127,28 +174,20 @@ sudo.Base.prototype.construct = function construct() {
127
174
  // 1. if `meth` is falsy return the delegate.
128
175
  // 2 if `meth` is truthy bind its method (to the delegate) and return the method
129
176
  //
130
- // `param` {String} `role` The _role_ property to match in this object's delegates list
177
+ // `param` {String} `role` The role property to match in this object's delegates list
131
178
  // `param` {String} `meth` Optional method to bind to the action this delegate is being used for
132
179
  // `returns`
133
180
  sudo.Base.prototype.delegate = function delegate(role, meth) {
134
- var del = this._delegates_, i;
181
+ var del = this.delegates, i;
135
182
  for(i = 0; i < del.length; i++) {
136
- if(del[i]._role_ === role) {
183
+ if(del[i].role === role) {
137
184
  if(!meth) return del[i];
138
185
  return del[i][meth].bind(del[i]);
139
186
  }
140
187
  }
141
188
  };
142
- // ###get
143
- // Returns the value associated with a key in this object's data store.
144
- //
145
- // `param` {String} `key`. The name of the key
146
- // `returns` {*}. The value associated with the key or false if not found.
147
- sudo.Base.prototype.get = function get(key) {
148
- return this._data_[key];
149
- };
150
189
  // ###getDelegate
151
- // Fetch a delegate whose _role_ property matches the passed in argument.
190
+ // Fetch a delegate whose role property matches the passed in argument.
152
191
  // Uses the `delegate` method in its 'single argument' form, included for
153
192
  // API consistency
154
193
  //
@@ -157,24 +196,59 @@ sudo.Base.prototype.get = function get(key) {
157
196
  sudo.Base.prototype.getDelegate = function getDelegate(role) {
158
197
  return this.delegate(role);
159
198
  };
160
- // ###getPath
161
- // Extract a value located at `path` relative to this objects data store
199
+ // ###removeDelegate
200
+ // From this objects `delegates` list remove the object (there should only ever be 1)
201
+ // whose role matches the passed in argument
162
202
  //
163
- // `param` {String} `path`. The key in the form of a dot-delimited path.
164
- // `param` {boolean} `obj`. Optional override, forcing getPath to operate on the passed in `obj`
165
- // argument rather than the default data store owned by `this` Object.
166
- // `returns` {*|undefined}. The value at keypath or undefined if not found.
167
- sudo.Base.prototype.getPath = function getPath(path, obj) {
168
- var key, curr = obj || this._data_, p;
169
- p = path.split('.');
170
- for (key; p.length && (key = p.shift());) {
171
- if(!p.length) {
172
- return curr[key];
173
- } else {
174
- curr = curr[key] || {};
203
+ // `param` {String} `role`
204
+ // `returns` {Object} `this`
205
+ sudo.Base.prototype.removeDelegate = function removeDelegate(role) {
206
+ var del = this.delegates, i;
207
+ for(i = 0; i < del.length; i++) {
208
+ if(del[i].role === role) {
209
+ // no _delegator_ for you
210
+ del[i].delegator = void 0;
211
+ del.splice(i, 1);
212
+ return this;
175
213
  }
176
214
  }
177
- return curr;
215
+ return this;
216
+ };
217
+ // `private`
218
+ sudo.Base.prototype.role = 'base';
219
+ // ##Model Class Object
220
+ //
221
+ // Model Objects expose methods for setting and getting data, and
222
+ // can be observed if implementing the `Observable Extension`
223
+ //
224
+ // `param` {object} data. An initial state for this model.
225
+ //
226
+ // `constructor`
227
+ sudo.Model = function(data) {
228
+ this.data = data || {};
229
+ // only models are `observable`
230
+ this.callbacks = [];
231
+ this.changeRecords = [];
232
+ };
233
+ // Model inherits from sudo.Base
234
+ // `private`
235
+ sudo.inherit(sudo.Base, sudo.Model);
236
+ // ###get
237
+ // Returns the value associated with a key.
238
+ //
239
+ // `param` {String} `key`. The name of the key
240
+ // `returns` {*}. The value associated with the key or false if not found.
241
+ sudo.Model.prototype.get = function get(key) {
242
+ return this.data[key];
243
+ };
244
+ // ###getPath
245
+ //
246
+ // Uses the sudo namespace's getpath function operating on the model's
247
+ // data hash.
248
+ //
249
+ // `returns` {*|undefined}. The value at keypath or undefined if not found.
250
+ sudo.Model.prototype.getPath = function getPath(path) {
251
+ return sudo.getPath(path, this.data);
178
252
  };
179
253
  // ###gets
180
254
  // Assembles and returns an object of key:value pairs for each key
@@ -182,66 +256,38 @@ sudo.Base.prototype.getPath = function getPath(path, obj) {
182
256
  //
183
257
  // `param` {array} `ary`. An array of keys.
184
258
  // `returns` {object}
185
- sudo.Base.prototype.gets = function gets(ary) {
259
+ sudo.Model.prototype.gets = function gets(ary) {
186
260
  var i, obj = {};
187
261
  for (i = 0; i < ary.length; i++) {
188
- obj[ary[i]] = ary[i].indexOf('.') === -1 ? this._data_[ary[i]] :
262
+ obj[ary[i]] = ary[i].indexOf('.') === -1 ? this.data[ary[i]] :
189
263
  this.getPath(ary[i]);
190
264
  }
191
265
  return obj;
192
266
  };
193
- // ###removeDelegate
194
- // From this objects `delegates` list remove the object (there should only ever be 1)
195
- // whose _role_ matches the passed in argument
196
- //
197
- // `param` {String} `role`
198
- // `returns` {Object} `this`
199
- sudo.Base.prototype.removeDelegate = function removeDelegate(role) {
200
- var del = this._delegates_, i;
201
- for(i = 0; i < del.length; i++) {
202
- if(del[i]._role_ === role) {
203
- // no _delegator_ for you
204
- del[i]._delegator_ = void 0;
205
- del.splice(i, 1);
206
- return this;
207
- }
208
- }
209
- return this;
210
- };
211
267
  // `private`
212
- sudo.Base.prototype._role_ = 'base';
268
+ sudo.Model.prototype.role = 'model';
213
269
  // ###set
214
- // Set a key:value pair in `this` object's data store.
270
+ // Set a key:value pair.
215
271
  //
216
272
  // `param` {String} `key`. The name of the key.
217
273
  // `param` {*} `value`. The value associated with the key.
218
274
  // `returns` {Object} `this`
219
- sudo.Base.prototype.set = function set(key, value) {
275
+ sudo.Model.prototype.set = function set(key, value) {
220
276
  // _NOTE: intentional possibilty of setting a falsy value_
221
- this._data_[key] = value;
277
+ this.data[key] = value;
222
278
  return this;
223
279
  };
224
280
  // ###setPath
225
- // Traverse the keypath and get each object
226
- // (or make blank ones) eventually setting the value
227
- // at the end of the path
228
281
  //
229
- // `param` {string} `path`. The path to traverse when setting a value.
230
- // `param` {*} `value`. What to set.
231
- // `param` {Object} `obj`. Optional flag to force setPath to operate on the passed object.
232
- // `returns` {Object} `this`
233
- sudo.Base.prototype.setPath = function setPath(path, value, obj) {
234
- var curr = obj || this._data_, p = path.split('.'), key;
235
- for (key; p.length && (key = p.shift());) {
236
- if(!p.length) {
237
- curr[key] = value;
238
- } else if (curr[key]) {
239
- curr = curr[key];
240
- } else {
241
- curr = curr[key] = {};
242
- }
243
- }
244
- return this;
282
+ // Uses the sudo namespace's setpath function operating on the model's
283
+ // data hash.
284
+ //
285
+ // `param` {String} `path`
286
+ // `param` {*} `value`
287
+ // `returns` {Object} this.
288
+ sudo.Model.prototype.setPath = function setPath(path, value) {
289
+ sudo.setPath(path, value, this.data);
290
+ return this;
245
291
  };
246
292
  // ###sets
247
293
  // Invokes `set()` or `setPath()` for each key value pair in `obj`.
@@ -249,7 +295,7 @@ sudo.Base.prototype.setPath = function setPath(path, value, obj) {
249
295
  //
250
296
  // `param` {Object} `obj`. The keys and values to set.
251
297
  // `returns` {Object} `this`
252
- sudo.Base.prototype.sets = function sets(obj) {
298
+ sudo.Model.prototype.sets = function sets(obj) {
253
299
  var i, k = Object.keys(obj);
254
300
  for(i = 0; i < k.length; i++) {
255
301
  k[i].indexOf('.') === -1 ? this.set(k[i], obj[k[i]]) :
@@ -262,35 +308,25 @@ sudo.Base.prototype.sets = function sets(obj) {
262
308
  //
263
309
  // `param` {String} key
264
310
  // `returns` {Object} `this`
265
- sudo.Base.prototype.unset = function unset(key) {
266
- delete this._data_[key];
311
+ sudo.Model.prototype.unset = function unset(key) {
312
+ delete this.data[key];
267
313
  return this;
268
314
  };
269
315
  // ###unsetPath
270
- // Remove a key:value pair from this object's data store
271
- // located at <path>
316
+ // Uses `sudo.unsetPath` operating on this models data hash
272
317
  //
273
318
  // `param` {String} path
274
319
  // `returns` {Object} `this`
275
- sudo.Base.prototype.unsetPath = function unsetPath(path) {
276
- var curr = this._data_, p = path.split('.'), key;
277
- for (key; p.length && (key = p.shift());) {
278
- if(!p.length) {
279
- delete curr[key];
280
- } else {
281
- // this can fail if a faulty path is passed.
282
- // using getPath beforehand can prevent that
283
- curr = curr[key];
284
- }
285
- }
286
- return this;
320
+ sudo.Model.prototype.unsetPath = function unsetPath(path) {
321
+ sudo.unsetPath(path, this.data);
322
+ return this;
287
323
  };
288
324
  // ###unsets
289
325
  // Deletes a number of keys or paths from this object's data store
290
326
  //
291
327
  // `param` {array} `ary`. An array of keys or paths.
292
328
  // `returns` {Objaect} `this`
293
- sudo.Base.prototype.unsets = function unsets(ary) {
329
+ sudo.Model.prototype.unsets = function unsets(ary) {
294
330
  var i;
295
331
  for(i = 0; i < ary.length; i++) {
296
332
  ary[i].indexOf('.') === -1 ? this.unset(ary[i]) :
@@ -304,13 +340,13 @@ sudo.Base.prototype.unsets = function unsets(ary) {
304
340
  // itself be contained
305
341
  //
306
342
  // `constructor`
307
- sudo.Container = function(data) {
308
- sudo.Base.call(this, data);
309
- this._children_ = [];
310
- this._childNames_ = {};
343
+ sudo.Container = function() {
344
+ sudo.Base.call(this);
345
+ this.children = [];
346
+ this.childNames = {};
311
347
  };
312
- // `private`
313
- sudo._inherit_(sudo.Base, sudo.Container);
348
+ // Container is a subclass of sudo.Base
349
+ sudo.inherit(sudo.Base, sudo.Container);
314
350
  // ###addChild
315
351
  // Adds a View to this container's list of children.
316
352
  // Also adds an 'index' property and an entry in the childNames hash.
@@ -320,12 +356,12 @@ sudo._inherit_(sudo.Base, sudo.Container);
320
356
  // `param` {String} `name`. An optional name for the child that will go in the childNames hash.
321
357
  // `returns` {Object} `this`
322
358
  sudo.Container.prototype.addChild = function addChild(child, name) {
323
- var c = this._children_;
324
- child._parent_ = this;
325
- child._index_ = c.length;
359
+ var c = this.children;
360
+ child.parent = this;
361
+ child.index = c.length;
326
362
  if(name) {
327
- child._name_ = name;
328
- this._childNames_[name] = child._index_;
363
+ child.name = name;
364
+ this.childNames[name] = child.index;
329
365
  }
330
366
  c.push(child);
331
367
  if('addedToParent' in child) child.addedToParent(this);
@@ -335,7 +371,7 @@ sudo.Container.prototype.addChild = function addChild(child, name) {
335
371
  // By default, `bubble` returns the current view's parent (if it has one)
336
372
  //
337
373
  // `returns` {Object|undefined}
338
- sudo.Container.prototype.bubble = function bubble() {return this._parent_;};
374
+ sudo.Container.prototype.bubble = function bubble() {return this.parent;};
339
375
  // ###getChild
340
376
  // If a child was added with a name, via `addChild`,
341
377
  // that object can be fetched by name. This prevents us from having to reference a
@@ -344,8 +380,8 @@ sudo.Container.prototype.bubble = function bubble() {return this._parent_;};
344
380
  // `param` {String|Number} `id`. The string `name` or numeric `index` of the child to fetch.
345
381
  // `returns` {Object|undefined} The found child
346
382
  sudo.Container.prototype.getChild = function getChild(id) {
347
- return typeof id === 'string' ? this._children_[this._childNames_[id]] :
348
- this._children_[id];
383
+ return typeof id === 'string' ? this.children[this.childNames[id]] :
384
+ this.children[id];
349
385
  };
350
386
  // ###_indexChildren_
351
387
  // Method is called with the `index` property of a subview that is being removed.
@@ -353,11 +389,11 @@ sudo.Container.prototype.getChild = function getChild(id) {
353
389
  // `param` {Number} `i`
354
390
  // `private`
355
391
  sudo.Container.prototype._indexChildren_ = function _indexChildren_(i) {
356
- var c = this._children_, obj = this._childNames_, len;
392
+ var c = this.children, obj = this.childNames, len;
357
393
  for (len = c.length; i < len; i++) {
358
- c[i]._index_--;
394
+ c[i].index--;
359
395
  // adjust any entries in childNames
360
- if(c[i]._name_ in obj) obj[c[i]._name_] = c[i]._index_;
396
+ if(c[i].name in obj) obj[c[i].name] = c[i].index;
361
397
  }
362
398
  };
363
399
  // ###removeChild
@@ -370,28 +406,19 @@ sudo.Container.prototype._indexChildren_ = function _indexChildren_(i) {
370
406
  // An object will be assumed to be an actual sudo Class Object.
371
407
  // `returns` {Object} `this`
372
408
  sudo.Container.prototype.removeChild = function removeChild(arg) {
373
- var t = typeof arg, c;
374
- // passed an object (or an array - which will fail so don't do that), proceed
375
- if(t === 'object') this._removeChild_(arg);
376
- else {
377
- c = t === 'string' ? this._children_[this._childNames_[arg]] : this._children_[arg];
378
- this._removeChild_(c);
379
- }
380
- return this;
381
- };
382
- // ###_removeChild_
383
- // Helper method for 'public' removeChild
384
- // `param` {Object} `child`. The view that is going to be removed.
385
- // `private`
386
- sudo.Container.prototype._removeChild_ = function _removeChild_(child) {
387
- var i = child._index_;
409
+ var i, t = typeof arg, c;
410
+ // normalize the input
411
+ if(t === 'object') c = arg;
412
+ else c = t === 'string' ? this.children[this.childNames[arg]] : this.children[arg];
413
+ i = c.index;
388
414
  // remove from the children Array
389
- this._children_.splice(i, 1);
415
+ this.children.splice(i, 1);
390
416
  // remove from the named child hash if present
391
- delete this._childNames_[child._name_];
417
+ delete this.childNames[c.name];
392
418
  // child is now an `orphan`
393
- delete child._parent_;
419
+ delete c.parent;
394
420
  this._indexChildren_(i);
421
+ return this;
395
422
  };
396
423
  // ###removeFromParent
397
424
  // Remove this object from its parents list of children.
@@ -399,10 +426,10 @@ sudo.Container.prototype._removeChild_ = function _removeChild_(child) {
399
426
  // or chaining method calls
400
427
  sudo.Container.prototype.removeFromParent = function removeFromParent() {
401
428
  // will error without a parent, but that would be your fault...
402
- this._parent_._removeChild_(this);
429
+ this.parent.removeChild(this);
403
430
  return this;
404
431
  };
405
- sudo.Container.prototype._role_ = 'container';
432
+ sudo.Container.prototype.role = 'container';
406
433
  // ###send
407
434
  // The call to the specific method on a (un)specified target happens here.
408
435
  // If this Object is part of a `sudo.ext.container` maintained hierarchy
@@ -414,14 +441,14 @@ sudo.Container.prototype._role_ = 'container';
414
441
  // A sendMethod will be located by:
415
442
  // 1. using the first argument if it is a string
416
443
  // 2. looking for a `sendMethod` property if it is an object
417
- // In the case a specified target exists at `this.get('sendTarget')` it will be used
444
+ // In the case a specified target exists at `this.model.get('sendTarget')` it will be used
418
445
  // Any other args will be passed to the sendMethod after `this`
419
446
  // `returns` {Object} `this`
420
447
  sudo.Container.prototype.send = function send(/*args*/) {
421
448
  var args = Array.prototype.slice.call(arguments),
422
- meth, targ, fn;
449
+ d = this.model && this.model.data, meth, targ, fn;
423
450
  // normalize the input, common use cases first
424
- if('sendMethod' in this._data_) meth = this._data_.sendMethod;
451
+ if(d && 'sendMethod' in d) meth = d.sendMethod;
425
452
  else if(typeof args[0] === 'string') meth = args.shift();
426
453
  // less common but viable options
427
454
  if(!meth) {
@@ -431,7 +458,7 @@ sudo.Container.prototype.send = function send(/*args*/) {
431
458
  args[0].sendMethod || void 0;
432
459
  }
433
460
  // target is either specified or my parent
434
- targ = this._data_['sendTarget'] || this._parent_;
461
+ targ = d && d.sendTarget || this.parent;
435
462
  // obvious chance for errors here, don't be dumb
436
463
  fn = targ[meth];
437
464
  while(!fn && (targ = targ.bubble())) {
@@ -459,17 +486,19 @@ sudo.Container.prototype.send = function send(/*args*/) {
459
486
  // a shortcut for `this.$el.find(selector)`
460
487
  //
461
488
  // `param` {string|element|jQuery} `el`. Otional el for the View instance.
462
- // `param` {Object} `data`. Optional data object.
489
+ // `param` {Object} `data`. Optional data object which becomes the initial state
490
+ // of a new model located at `this.model`.
463
491
  //
464
492
  // `constructor`
465
493
  sudo.View = function(el, data) {
466
- sudo.Container.call(this, data);
494
+ sudo.Container.call(this);
495
+ if(data) this.model = new sudo.Model(data);
467
496
  this.setEl(el);
468
- if(this._role_ === 'view') this.init();
497
+ if(this.role === 'view') this.init();
469
498
  };
470
499
  // View inherits from Container
471
500
  // `private`
472
- sudo._inherit_(sudo.Container, sudo.View);
501
+ sudo.inherit(sudo.Container, sudo.View);
473
502
  // ###becomePremier
474
503
  // Premier functionality provides hooks for behavioral differentiation
475
504
  // among elements or class objects.
@@ -477,11 +506,11 @@ sudo._inherit_(sudo.Container, sudo.View);
477
506
  // `returns` {Object} `this`
478
507
  sudo.View.prototype.becomePremier = function becomePremier() {
479
508
  var p, f = function() {
480
- this._isPremier_ = true;
509
+ this.isPremier = true;
481
510
  sudo.premier = this;
482
511
  }.bind(this);
483
512
  // is there an existing premier that isn't me?
484
- if((p = sudo.premier) && p._uid_ !== this._uid_) {
513
+ if((p = sudo.premier) && p.uid !== this.uid) {
485
514
  // ask it to resign and call the cb
486
515
  p.resignPremier(f);
487
516
  } else f(); // no existing premier
@@ -510,9 +539,9 @@ sudo.View.prototype._normalizedEl_ = function _normalizedEl_(el) {
510
539
  // `returns` {Object} `this`
511
540
  sudo.View.prototype.resignPremier = function resignPremier(cb) {
512
541
  var p;
513
- this._isPremier_ = false;
542
+ this.isPremier = false;
514
543
  // only remove the global premier if it is me
515
- if((p = sudo.premier) && p._uid_ === this._uid_) {
544
+ if((p = sudo.premier) && p.uid === this.uid) {
516
545
  sudo.premier = null;
517
546
  }
518
547
  // fire the cb if passed
@@ -520,7 +549,7 @@ sudo.View.prototype.resignPremier = function resignPremier(cb) {
520
549
  return this;
521
550
  };
522
551
  // `private`
523
- sudo.View.prototype._role_ = 'view';
552
+ sudo.View.prototype.role = 'view';
524
553
  // ###setEl
525
554
  // A view must have an element, set that here.
526
555
  // Stores a jquerified object as `this.$el` the raw
@@ -529,12 +558,12 @@ sudo.View.prototype._role_ = 'view';
529
558
  // `param` {string=|element} `el`
530
559
  // `returns` {Object} `this`
531
560
  sudo.View.prototype.setEl = function setEl(el) {
532
- var a, t;
561
+ var d = this.model && this.model.data, a, t;
533
562
  if(!el) {
534
563
  // normalize any relevant data
535
- t = this._data_['tagName'] || 'div';
564
+ t = d ? d.tagName || 'div': 'div';
536
565
  this.$el = $(document.createElement(t));
537
- if((a = this._data_['attributes'])) this.$el.attr(a);
566
+ if(d && (a = d.attributes)) this.$el.attr(a);
538
567
  } else {
539
568
  this.$el = this._normalizedEl_(el);
540
569
  }
@@ -550,7 +579,9 @@ sudo.View.prototype.$ = function(sel) {
550
579
  return this.$el.find(sel);
551
580
  };
552
581
  // ## Observable Extension Object
553
- // Implementaion of the ES6 Harmony Observer pattern
582
+ // Implementaion of the ES6 Harmony Observer pattern.
583
+ // Extend a `sudo.Model` class with this object if
584
+ // data-mutation-observation is required
554
585
  sudo.ext.observable = {
555
586
  // ###_deliver_
556
587
  // Called from deliverChangeRecords when ready to send
@@ -558,7 +589,7 @@ sudo.ext.observable = {
558
589
  //
559
590
  // `private`
560
591
  _deliver_: function _deliver_(obj) {
561
- var i, cb = this._callbacks_;
592
+ var i, cb = this.callbacks;
562
593
  for(i = 0; i < cb.length; i++) {
563
594
  cb[i](obj);
564
595
  }
@@ -569,7 +600,7 @@ sudo.ext.observable = {
569
600
  //
570
601
  // `returns` {Object} `this`
571
602
  deliverChangeRecords: function deliverChangeRecords() {
572
- var rec, cr = this._changeRecords_;
603
+ var rec, cr = this.changeRecords;
573
604
  // FIFO
574
605
  for(rec; cr.length && (rec = cr.shift());) {
575
606
  this._deliver_(rec);
@@ -594,7 +625,7 @@ sudo.ext.observable = {
594
625
  observe: function observe(fn) {
595
626
  // this will fail if mixed-in and no `callbacks` created so don't do that.
596
627
  // Per the spec, do not allow the same callback to be added
597
- var d = this._callbacks_;
628
+ var d = this.callbacks;
598
629
  if(d.indexOf(fn) === -1) d.push(fn);
599
630
  return fn;
600
631
  },
@@ -620,16 +651,16 @@ sudo.ext.observable = {
620
651
  //
621
652
  // `returns` {Object|*} `this` or calls deliverChangeRecords
622
653
  set: function set(key, value, hold) {
623
- var obj = {name: key, object: this._data_};
654
+ var obj = {name: key, object: this.data};
624
655
  // did this key exist already
625
- if(key in this._data_) {
656
+ if(key in this.data) {
626
657
  obj.type = 'updated';
627
658
  // then there is an oldValue
628
- obj.oldValue = this._data_[key];
659
+ obj.oldValue = this.data[key];
629
660
  } else obj.type = 'new';
630
661
  // now actually set the value
631
- this._data_[key] = value;
632
- this._changeRecords_.push(obj);
662
+ this.data[key] = value;
663
+ this.changeRecords.push(obj);
633
664
  // call the observers or not
634
665
  if(hold) return this;
635
666
  return this.deliverChangeRecords();
@@ -638,7 +669,7 @@ sudo.ext.observable = {
638
669
  // Overrides sudo.Base.setPath to check for observers.
639
670
  // Change records originating from a `setPath` operation
640
671
  // send back the passed in `path` as `name` as well as the
641
- // top level object being observed (this observable's _data_).
672
+ // top level object being observed (this observable's data).
642
673
  // this allows for easy filtering either manually or via a
643
674
  // `change delegate`
644
675
  //
@@ -648,7 +679,7 @@ sudo.ext.observable = {
648
679
  // to be delivered upon a call to deliverChangeRecords (truthy)
649
680
  // `returns` {Object|*} `this` or calls deliverChangeRecords
650
681
  setPath: function setPath(path, value, hold) {
651
- var curr = this._data_, obj = {name: path, object: this._data_},
682
+ var curr = this.data, obj = {name: path, object: this.data},
652
683
  p = path.split('.'), key;
653
684
  for (key; p.length && (key = p.shift());) {
654
685
  if(!p.length) {
@@ -664,7 +695,7 @@ sudo.ext.observable = {
664
695
  curr = curr[key] = {};
665
696
  }
666
697
  }
667
- this._changeRecords_.push(obj);
698
+ this.changeRecords.push(obj);
668
699
  // call all observers or not
669
700
  if(hold) return this;
670
701
  return this.deliverChangeRecords();
@@ -689,7 +720,7 @@ sudo.ext.observable = {
689
720
  // `param` {Function} the function passed in to `observe`
690
721
  // `returns` {Object} `this`
691
722
  unobserve: function unobserve(fn) {
692
- var cb = this._callbacks_, i = cb.indexOf(fn);
723
+ var cb = this.callbacks, i = cb.indexOf(fn);
693
724
  if(i !== -1) cb.splice(i, 1);
694
725
  return this;
695
726
  },
@@ -713,9 +744,9 @@ sudo.ext.observable = {
713
744
  //
714
745
  // `returns` {Object|*} `this` or calls deliverChangeRecords
715
746
  unset: function unset(key, hold) {
716
- var obj = {name: key, object: this._data_, type: 'deleted'},
717
- val = !!this._data_[key];
718
- delete this._data_[key];
747
+ var obj = {name: key, object: this.data, type: 'deleted'},
748
+ val = !!this.data[key];
749
+ delete this.data[key];
719
750
  // call the observers if there was a val to delete
720
751
  return this._unset_(obj, val, hold);
721
752
  },
@@ -725,7 +756,7 @@ sudo.ext.observable = {
725
756
  // `private`
726
757
  _unset_: function _unset_(o, v, h) {
727
758
  if(v) {
728
- this._changeRecords_.push(o);
759
+ this.changeRecords.push(o);
729
760
  if(h) return this;
730
761
  return this.deliverChangeRecords();
731
762
  }
@@ -740,8 +771,8 @@ sudo.ext.observable = {
740
771
  //
741
772
  // `returns` {Object|*} `this` or calls deliverChangeRecords
742
773
  unsetPath: function unsetPath(path, hold) {
743
- var obj = {name: path, object: this._data_, type: 'deleted'},
744
- curr = this._data_, p = path.split('.'),
774
+ var obj = {name: path, object: this.data, type: 'deleted'},
775
+ curr = this.data, p = path.split('.'),
745
776
  key, val;
746
777
  for (key; p.length && (key = p.shift());) {
747
778
  if(!p.length) {
@@ -772,7 +803,7 @@ sudo.ext.observable = {
772
803
  return this.deliverChangeRecords();
773
804
  }
774
805
  };
775
- sudo.version = "0.8.0";
806
+ sudo.version = "0.9.0";
776
807
  window.sudo = sudo;
777
808
  if(typeof window._ === "undefined") window._ = sudo;
778
809
  }).call(this, this);