js_stack 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 393d1a96109e84e9d653ee620aec8514276f293c
4
- data.tar.gz: e09d9e2565dd19abccd3e8481e82e20d6f20071b
3
+ metadata.gz: 5dba30cdf10a542fc2075be0e211dc211082f1f4
4
+ data.tar.gz: 672fe6206d90b5f212b986b0b768016046a89960
5
5
  SHA512:
6
- metadata.gz: 6d9142008b1b9a8f73ce7bb947b3cd34f9fef57aeaf58a87b6446a69683507765f92670dea7dd625b625f3aebe3e42c236b0bc096a6531ac2abe643a2ac1185d
7
- data.tar.gz: 0cde1e7d3fff8c8b5c9bea7f5d125d97d1400e2b002e4c6fc1de8002af3500380c2ee2f9e4dec6dd4d2f4b1550e7c62d36aa26e927139f7b59c6bcb4b08cae14
6
+ metadata.gz: b9fd43d12fa92b7d590a572d9d9d2ec13bd4d27f6f3d1577e1fc299ed3a9c6e4432791e32d5d50bfca63cae6749c84d25825fcdd4c5a62ece74973afd927682e
7
+ data.tar.gz: fd9ca35a353a30a01aa33fbfcab7323ee7e4255d98169613b3769a0196b9592678daca64aa0ce74203972ab48303fe47e5376cb329f2b0f1215f4727d416e51d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## libs
4
+ * underscore - [changelog](http://underscorejs.org/#changelog)
5
+ * backbone - [changelog](http://backbonejs.org/#changelog)
6
+ * marionette - [changelog](https://github.com/marionettejs/backbone.marionette/blob/master/changelog.md)
7
+ * backbone.stickit - [changelog](http://nytimes.github.io/backbone.stickit/#change-log)
8
+ * backbone.validation - [changelog](https://github.com/thedersen/backbone.validation#release-notes)
9
+ * backbone-associations - [changelog](https://github.com/dhruvaray/backbone-associations/blob/master/CHANGELOG.md)
10
+ * backbone-pageable - [changelog](https://github.com/backbone-paginator/backbone-pageable#change-log)
11
+ * backbone.deepmodel - [changelog](https://github.com/powmedia/backbone-deep-model#changelog)
12
+ * backbone-virtualcollection - [changelog](https://github.com/p3drosola/Backbone.VirtualCollection#changelog)
13
+
14
+ ## v0.2.0
15
+
16
+ * updated *backbone-stickit* 0.6.3 -> 0.7.0 [@gvl]
17
+ * updated marionette 1.4.0 -> 1.4.1 [@gvl]
18
+ * updated backbone-pageable 1.4.1 -> 1.4.3 [@gvl]
19
+
20
+ ### Breaking Changes
21
+ * see http://nytimes.github.io/backbone.stickit/#change-log for breaking changes in backbone-stickit
22
+
3
23
  ## v0.1.0
4
24
 
5
25
  * updated *backbone* 1.0.0 -> 1.1.0 - http://backbonejs.org/#changelog [@gvl]
data/README.md CHANGED
@@ -42,7 +42,7 @@ http://backbonejs.org/
42
42
  #= require js_stack/backbone
43
43
  ```
44
44
 
45
- ### marionette.js 1.4.0
45
+ ### marionette.js 1.4.1
46
46
 
47
47
  https://github.com/marionettejs/backbone.marionette/tree/master/docs
48
48
 
@@ -50,7 +50,7 @@ https://github.com/marionettejs/backbone.marionette/tree/master/docs
50
50
  #= require js_stack/marionette
51
51
  ```
52
52
 
53
- ### backbone.stickit 0.6.3
53
+ ### backbone.stickit 0.7.0
54
54
 
55
55
  http://nytimes.github.io/backbone.stickit/
56
56
 
@@ -75,7 +75,7 @@ http://dhruvaray.github.io/backbone-associations/
75
75
  #= require js_stack/backbone.associations
76
76
  ```
77
77
 
78
- ### backbone-pageable 1.4.1
78
+ ### backbone-pageable 1.4.3
79
79
 
80
80
  https://github.com/wyuenho/backbone-pageable
81
81
 
@@ -1,3 +1,3 @@
1
1
  module JsStack
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,5 +1,5 @@
1
1
  /*
2
- backbone-pageable 1.4.1
2
+ backbone-pageable 1.4.3
3
3
  http://github.com/wyuenho/backbone-pageable
4
4
 
5
5
  Copyright (c) 2013 Jimmy Yuen Ho Wong
@@ -425,7 +425,11 @@
425
425
  fullIndex;
426
426
  }
427
427
 
428
- ++state.totalRecords;
428
+ if (!options.onRemove) {
429
+ ++state.totalRecords;
430
+ delete options.onRemove;
431
+ }
432
+
429
433
  pageCol.state = pageCol._checkState(state);
430
434
 
431
435
  if (colToAdd) {
@@ -436,9 +440,8 @@
436
440
  pageCol.at(pageSize) :
437
441
  null;
438
442
  if (modelToRemove) {
439
- var popOptions = {onAdd: true};
440
443
  runOnceAtLastHandler(collection, event, function () {
441
- pageCol.remove(modelToRemove, popOptions);
444
+ pageCol.remove(modelToRemove, {onAdd: true});
442
445
  });
443
446
  }
444
447
  }
@@ -463,16 +466,18 @@
463
466
  if (collection == pageCol) {
464
467
  if (nextModel = fullCol.at(pageEnd)) {
465
468
  runOnceAtLastHandler(pageCol, event, function () {
466
- pageCol.push(nextModel);
469
+ pageCol.push(nextModel, {onRemove: true});
467
470
  });
468
471
  }
469
472
  fullCol.remove(model);
470
473
  }
471
474
  else if (removedIndex >= pageStart && removedIndex < pageEnd) {
475
+ if (nextModel = fullCol.at(pageEnd - 1)) {
476
+ runOnceAtLastHandler(pageCol, event, function() {
477
+ pageCol.push(nextModel, {onRemove: true});
478
+ });
479
+ }
472
480
  pageCol.remove(model);
473
- var at = removedIndex + 1
474
- nextModel = fullCol.at(at) || fullCol.last();
475
- if (nextModel) pageCol.add(nextModel, {at: at});
476
481
  }
477
482
  }
478
483
  else delete options.onAdd;
@@ -578,8 +583,6 @@
578
583
  else if (currentPage < firstPage ||
579
584
  (totalPages > 0 &&
580
585
  (firstPage ? currentPage > totalPages : currentPage >= totalPages))) {
581
- var op = firstPage ? ">=" : ">";
582
-
583
586
  throw new RangeError("`currentPage` must be firstPage <= currentPage " +
584
587
  (firstPage ? ">" : ">=") +
585
588
  " totalPages if " + firstPage + "-based. Got " +
@@ -1132,7 +1135,7 @@
1132
1135
  then reset.
1133
1136
 
1134
1137
  The query string is constructed by translating the current pagination
1135
- state to your server API query parameter using #queryParams. The current
1138
+ state to your server API query parameter using #queryParams. The current
1136
1139
  page will reset after fetch.
1137
1140
 
1138
1141
  @param {Object} [options] Accepts all
@@ -1209,13 +1212,16 @@
1209
1212
 
1210
1213
  var models = col.models;
1211
1214
  if (mode == "client") fullCol.reset(models, opts);
1212
- else fullCol.add(models, _extend({at: fullCol.length}, opts));
1215
+ else {
1216
+ fullCol.add(models, _extend({at: fullCol.length}, opts));
1217
+ self.trigger("reset", self, opts);
1218
+ }
1213
1219
 
1214
1220
  if (success) success(col, resp, opts);
1215
1221
  };
1216
1222
 
1217
1223
  // silent the first reset from backbone
1218
- return BBColProto.fetch.call(self, _extend({}, options, {silent: true}));
1224
+ return BBColProto.fetch.call(this, _extend({}, options, {silent: true}));
1219
1225
  }
1220
1226
 
1221
1227
  return BBColProto.fetch.call(this, options);
@@ -1 +1 @@
1
- //= require js_stack/backbone.pageable/backbone.pageable-1.4.1
1
+ //= require js_stack/backbone.pageable/backbone.pageable-1.4.3
@@ -0,0 +1,537 @@
1
+ //
2
+ // backbone.stickit - v0.7.0
3
+ // The MIT License
4
+ // Copyright (c) 2012 The New York Times, CMS Group, Matthew DeLambo <delambo@gmail.com>
5
+ //
6
+ (function (factory) {
7
+
8
+ // Set up Stickit appropriately for the environment. Start with AMD.
9
+ if (typeof define === 'function' && define.amd)
10
+ define(['underscore', 'backbone'], factory);
11
+
12
+ // Next for Node.js or CommonJS.
13
+ else if (typeof exports === 'object')
14
+ factory(require('underscore'), require('backbone'));
15
+
16
+ // Finally, as a browser global.
17
+ else
18
+ factory(_, Backbone);
19
+
20
+ }(function (_, Backbone) {
21
+
22
+ // Backbone.Stickit Namespace
23
+ // --------------------------
24
+
25
+ Backbone.Stickit = {
26
+
27
+ _handlers: [],
28
+
29
+ addHandler: function(handlers) {
30
+ // Fill-in default values.
31
+ handlers = _.map(_.flatten([handlers]), function(handler) {
32
+ return _.extend({
33
+ updateModel: true,
34
+ updateView: true,
35
+ updateMethod: 'text'
36
+ }, handler);
37
+ });
38
+ this._handlers = this._handlers.concat(handlers);
39
+ }
40
+ };
41
+
42
+ // Backbone.View Mixins
43
+ // --------------------
44
+
45
+ _.extend(Backbone.View.prototype, {
46
+
47
+ // Collection of model event bindings.
48
+ // [{model,event,fn}, ...]
49
+ _modelBindings: null,
50
+
51
+ // Unbind the model and event bindings from `this._modelBindings` and
52
+ // `this.$el`. If the optional `model` parameter is defined, then only
53
+ // delete bindings for the given `model` and its corresponding view events.
54
+ unstickit: function(model) {
55
+ var models = [];
56
+ _.each(this._modelBindings, function(binding, i) {
57
+ if (model && binding.model !== model) return false;
58
+ binding.model.off(binding.event, binding.fn);
59
+ models.push(binding.model);
60
+ delete this._modelBindings[i];
61
+ }, this);
62
+
63
+ // Trigger an event for each model that was unbound.
64
+ _.invoke(_.uniq(models), 'trigger', 'stickit:unstuck', this.cid);
65
+ // Cleanup the null values.
66
+ this._modelBindings = _.compact(this._modelBindings);
67
+
68
+ this.$el.off('.stickit' + (model ? '.' + model.cid : ''));
69
+ },
70
+
71
+ // Using `this.bindings` configuration or the `optionalBindingsConfig`, binds `this.model`
72
+ // or the `optionalModel` to elements in the view.
73
+ stickit: function(optionalModel, optionalBindingsConfig) {
74
+ var model = optionalModel || this.model,
75
+ namespace = '.stickit.' + model.cid,
76
+ bindings = optionalBindingsConfig || _.result(this, "bindings") || {};
77
+
78
+ this._modelBindings || (this._modelBindings = []);
79
+ this.unstickit(model);
80
+
81
+ // Iterate through the selectors in the bindings configuration and configure
82
+ // the various options for each field.
83
+ _.each(bindings, function(v, selector) {
84
+ var $el, options, modelAttr, config,
85
+ binding = bindings[selector] || {},
86
+ bindId = _.uniqueId();
87
+
88
+ // Support ':el' selector - special case selector for the view managed delegate.
89
+ $el = selector === ':el' ? this.$el : this.$(selector);
90
+
91
+ // Fail fast if the selector didn't match an element.
92
+ if (!$el.length) return;
93
+
94
+ // Allow shorthand setting of model attributes - `'selector':'observe'`.
95
+ if (_.isString(binding)) binding = {observe:binding};
96
+
97
+ // Handle case where `observe` is in the form of a function.
98
+ if (_.isFunction(binding.observe)) binding.observe = binding.observe.call(this);
99
+
100
+ config = getConfiguration($el, binding);
101
+
102
+ modelAttr = config.observe;
103
+
104
+ // Create the model set options with a unique `bindId` so that we
105
+ // can avoid double-binding in the `change:attribute` event handler.
106
+ config.bindId = bindId;
107
+ // Add a reference to the view for handlers of stickitChange events
108
+ config.view = this;
109
+ options = _.extend({stickitChange:config}, config.setOptions);
110
+
111
+ initializeAttributes(this, $el, config, model, modelAttr);
112
+
113
+ initializeVisible(this, $el, config, model, modelAttr);
114
+
115
+ if (modelAttr) {
116
+ // Setup one-way, form element to model, bindings.
117
+ _.each(config.events, function(type) {
118
+ var event = type + namespace;
119
+ var method = function(event) {
120
+ var val = config.getVal.call(this, $el, event, config, _.rest(arguments));
121
+ // Don't update the model if false is returned from the `updateModel` configuration.
122
+ if (evaluateBoolean(this, config.updateModel, val, event, config))
123
+ setAttr(model, modelAttr, val, options, this, config);
124
+ };
125
+ method = _.bind(method, this);
126
+ if (selector === ':el') this.$el.on(event, method);
127
+ else this.$el.on(event, selector, method);
128
+ }, this);
129
+
130
+ // Setup a `change:modelAttr` observer to keep the view element in sync.
131
+ // `modelAttr` may be an array of attributes or a single string value.
132
+ _.each(_.flatten([modelAttr]), function(attr) {
133
+ observeModelEvent(model, this, 'change:'+attr, function(model, val, options) {
134
+ var changeId = options && options.stickitChange && options.stickitChange.bindId || null;
135
+ if (changeId !== bindId)
136
+ updateViewBindEl(this, $el, config, getAttr(model, modelAttr, config, this), model);
137
+ });
138
+ }, this);
139
+
140
+ updateViewBindEl(this, $el, config, getAttr(model, modelAttr, config, this), model, true);
141
+ }
142
+
143
+ model.once('stickit:unstuck', function(cid) {
144
+ if (cid === this.cid) applyViewFn(this, config.destroy, $el, model, config);
145
+ }, this);
146
+
147
+ // After each binding is setup, call the `initialize` callback.
148
+ applyViewFn(this, config.initialize, $el, model, config);
149
+ }, this);
150
+
151
+ // Wrap `view.remove` to unbind stickit model and dom events.
152
+ var remove = this.remove;
153
+ this.remove = function() {
154
+ var ret = this;
155
+ this.unstickit();
156
+ if (remove) ret = remove.apply(this, _.rest(arguments));
157
+ return ret;
158
+ };
159
+ }
160
+ });
161
+
162
+ // Helpers
163
+ // -------
164
+
165
+ // Evaluates the given `path` (in object/dot-notation) relative to the given
166
+ // `obj`. If the path is null/undefined, then the given `obj` is returned.
167
+ var evaluatePath = function(obj, path) {
168
+ var parts = (path || '').split('.');
169
+ var result = _.reduce(parts, function(memo, i) { return memo[i]; }, obj);
170
+ return result == null ? obj : result;
171
+ };
172
+
173
+ // If the given `fn` is a string, then view[fn] is called, otherwise it is
174
+ // a function that should be executed.
175
+ var applyViewFn = function(view, fn) {
176
+ if (fn) return (_.isString(fn) ? evaluatePath(view,fn) : fn).apply(view, _.rest(arguments, 2));
177
+ };
178
+
179
+ var getSelectedOption = function($select) { return $select.find('option').not(function(){ return !this.selected; }); };
180
+
181
+ // Given a function, string (view function reference), or a boolean
182
+ // value, returns the truthy result. Any other types evaluate as false.
183
+ var evaluateBoolean = function(view, reference) {
184
+ if (_.isBoolean(reference)) return reference;
185
+ else if (_.isFunction(reference) || _.isString(reference))
186
+ return applyViewFn.apply(this, arguments);
187
+ return false;
188
+ };
189
+
190
+ // Setup a model event binding with the given function, and track the event
191
+ // in the view's _modelBindings.
192
+ var observeModelEvent = function(model, view, event, fn) {
193
+ model.on(event, fn, view);
194
+ view._modelBindings.push({model:model, event:event, fn:fn});
195
+ };
196
+
197
+ // Prepares the given `val`ue and sets it into the `model`.
198
+ var setAttr = function(model, attr, val, options, context, config) {
199
+ var value = {};
200
+ if (config.onSet)
201
+ val = applyViewFn(context, config.onSet, val, config);
202
+
203
+ if (config.set)
204
+ applyViewFn(context, config.set, attr, val, options, config);
205
+ else {
206
+ value[attr] = val;
207
+ // If `observe` is defined as an array and `onSet` returned
208
+ // an array, then map attributes to their values.
209
+ if (_.isArray(attr) && _.isArray(val)) {
210
+ value = _.reduce(attr, function(memo, attribute, index) {
211
+ memo[attribute] = _.has(val, index) ? val[index] : null;
212
+ return memo;
213
+ }, {});
214
+ }
215
+ model.set(value, options);
216
+ }
217
+ };
218
+
219
+ // Returns the given `attr`'s value from the `model`, escaping and
220
+ // formatting if necessary. If `attr` is an array, then an array of
221
+ // respective values will be returned.
222
+ var getAttr = function(model, attr, config, context) {
223
+ var val,
224
+ retrieveVal = function(field) {
225
+ return model[config.escape ? 'escape' : 'get'](field);
226
+ },
227
+ sanitizeVal = function(val) {
228
+ return val == null ? '' : val;
229
+ };
230
+ val = _.isArray(attr) ? _.map(attr, retrieveVal) : retrieveVal(attr);
231
+ if (config.onGet) val = applyViewFn(context, config.onGet, val, config);
232
+ return _.isArray(val) ? _.map(val, sanitizeVal) : sanitizeVal(val);
233
+ };
234
+
235
+ // Find handlers in `Backbone.Stickit._handlers` with selectors that match
236
+ // `$el` and generate a configuration by mixing them in the order that they
237
+ // were found with the given `binding`.
238
+ var getConfiguration = Backbone.Stickit.getConfiguration = function($el, binding) {
239
+ var handlers = [{
240
+ updateModel: false,
241
+ updateMethod: 'text',
242
+ update: function($el, val, m, opts) { if ($el[opts.updateMethod]) $el[opts.updateMethod](val); },
243
+ getVal: function($el, e, opts) { return $el[opts.updateMethod](); }
244
+ }];
245
+ handlers = handlers.concat(_.filter(Backbone.Stickit._handlers, function(handler) {
246
+ return $el.is(handler.selector);
247
+ }));
248
+ handlers.push(binding);
249
+ var config = _.extend.apply(_, handlers);
250
+ // `updateView` is defaulted to false for configutrations with
251
+ // `visible`; otherwise, `updateView` is defaulted to true.
252
+ if (config.visible && !_.has(config, 'updateView')) config.updateView = false;
253
+ else if (!_.has(config, 'updateView')) config.updateView = true;
254
+ delete config.selector;
255
+ return config;
256
+ };
257
+
258
+ // Setup the attributes configuration - a list that maps an attribute or
259
+ // property `name`, to an `observe`d model attribute, using an optional
260
+ // `onGet` formatter.
261
+ //
262
+ // attributes: [{
263
+ // name: 'attributeOrPropertyName',
264
+ // observe: 'modelAttrName'
265
+ // onGet: function(modelAttrVal, modelAttrName) { ... }
266
+ // }, ...]
267
+ //
268
+ var initializeAttributes = function(view, $el, config, model, modelAttr) {
269
+ var props = ['autofocus', 'autoplay', 'async', 'checked', 'controls', 'defer', 'disabled', 'hidden', 'indeterminate', 'loop', 'multiple', 'open', 'readonly', 'required', 'scoped', 'selected'];
270
+
271
+ _.each(config.attributes || [], function(attrConfig) {
272
+ var lastClass = '', observed, updateAttr;
273
+ attrConfig = _.clone(attrConfig);
274
+ observed = attrConfig.observe || (attrConfig.observe = modelAttr),
275
+ updateAttr = function() {
276
+ var updateType = _.indexOf(props, attrConfig.name, true) > -1 ? 'prop' : 'attr',
277
+ val = getAttr(model, observed, attrConfig, view);
278
+ // If it is a class then we need to remove the last value and add the new.
279
+ if (attrConfig.name === 'class') {
280
+ $el.removeClass(lastClass).addClass(val);
281
+ lastClass = val;
282
+ }
283
+ else $el[updateType](attrConfig.name, val);
284
+ };
285
+ _.each(_.flatten([observed]), function(attr) {
286
+ observeModelEvent(model, view, 'change:' + attr, updateAttr);
287
+ });
288
+ updateAttr();
289
+ });
290
+ };
291
+
292
+ // If `visible` is configured, then the view element will be shown/hidden
293
+ // based on the truthiness of the modelattr's value or the result of the
294
+ // given callback. If a `visibleFn` is also supplied, then that callback
295
+ // will be executed to manually handle showing/hiding the view element.
296
+ //
297
+ // observe: 'isRight',
298
+ // visible: true, // or function(val, options) {}
299
+ // visibleFn: function($el, isVisible, options) {} // optional handler
300
+ //
301
+ var initializeVisible = function(view, $el, config, model, modelAttr) {
302
+ if (config.visible == null) return;
303
+ var visibleCb = function() {
304
+ var visible = config.visible,
305
+ visibleFn = config.visibleFn,
306
+ val = getAttr(model, modelAttr, config, view),
307
+ isVisible = !!val;
308
+ // If `visible` is a function then it should return a boolean result to show/hide.
309
+ if (_.isFunction(visible) || _.isString(visible)) isVisible = !!applyViewFn(view, visible, val, config);
310
+ // Either use the custom `visibleFn`, if provided, or execute the standard show/hide.
311
+ if (visibleFn) applyViewFn(view, visibleFn, $el, isVisible, config);
312
+ else {
313
+ $el.toggle(isVisible);
314
+ }
315
+ };
316
+ _.each(_.flatten([modelAttr]), function(attr) {
317
+ observeModelEvent(model, view, 'change:' + attr, visibleCb);
318
+ });
319
+ visibleCb();
320
+ };
321
+
322
+ // Update the value of `$el` using the given configuration and trigger the
323
+ // `afterUpdate` callback. This action may be blocked by `config.updateView`.
324
+ //
325
+ // update: function($el, val, model, options) {}, // handler for updating
326
+ // updateView: true, // defaults to true
327
+ // afterUpdate: function($el, val, options) {} // optional callback
328
+ //
329
+ var updateViewBindEl = function(view, $el, config, val, model, isInitializing) {
330
+ if (!evaluateBoolean(view, config.updateView, val, config)) return;
331
+ applyViewFn(view, config.update, $el, val, model, config);
332
+ if (!isInitializing) applyViewFn(view, config.afterUpdate, $el, val, config);
333
+ };
334
+
335
+ // Default Handlers
336
+ // ----------------
337
+
338
+ Backbone.Stickit.addHandler([{
339
+ selector: '[contenteditable="true"]',
340
+ updateMethod: 'html',
341
+ events: ['input', 'change']
342
+ }, {
343
+ selector: 'input',
344
+ events: ['propertychange', 'input', 'change'],
345
+ update: function($el, val) { $el.val(val); },
346
+ getVal: function($el) {
347
+ return $el.val();
348
+ }
349
+ }, {
350
+ selector: 'textarea',
351
+ events: ['propertychange', 'input', 'change'],
352
+ update: function($el, val) { $el.val(val); },
353
+ getVal: function($el) { return $el.val(); }
354
+ }, {
355
+ selector: 'input[type="radio"]',
356
+ events: ['change'],
357
+ update: function($el, val) {
358
+ $el.filter('[value="'+val+'"]').prop('checked', true);
359
+ },
360
+ getVal: function($el) {
361
+ return $el.filter(':checked').val();
362
+ }
363
+ }, {
364
+ selector: 'input[type="checkbox"]',
365
+ events: ['change'],
366
+ update: function($el, val, model, options) {
367
+ if ($el.length > 1) {
368
+ // There are multiple checkboxes so we need to go through them and check
369
+ // any that have value attributes that match what's in the array of `val`s.
370
+ val || (val = []);
371
+ $el.each(function(i, el) {
372
+ var checkbox = Backbone.$(el);
373
+ var checked = _.indexOf(val, checkbox.val()) > -1;
374
+ checkbox.prop('checked', checked);
375
+ });
376
+ } else {
377
+ var checked = _.isBoolean(val) ? val : val === $el.val();
378
+ $el.prop('checked', checked);
379
+ }
380
+ },
381
+ getVal: function($el) {
382
+ var val;
383
+ if ($el.length > 1) {
384
+ val = _.reduce($el, function(memo, el) {
385
+ var checkbox = Backbone.$(el);
386
+ if (checkbox.prop('checked')) memo.push(checkbox.val());
387
+ return memo;
388
+ }, []);
389
+ } else {
390
+ val = $el.prop('checked');
391
+ // If the checkbox has a value attribute defined, then
392
+ // use that value. Most browsers use "on" as a default.
393
+ var boxval = $el.val();
394
+ if (boxval !== 'on' && boxval != null) {
395
+ val = val ? $el.val() : null;
396
+ }
397
+ }
398
+ return val;
399
+ }
400
+ }, {
401
+ selector: 'select',
402
+ events: ['change'],
403
+ update: function($el, val, model, options) {
404
+ var optList,
405
+ selectConfig = options.selectOptions,
406
+ list = selectConfig && selectConfig.collection || undefined,
407
+ isMultiple = $el.prop('multiple');
408
+
409
+ // If there are no `selectOptions` then we assume that the `<select>`
410
+ // is pre-rendered and that we need to generate the collection.
411
+ if (!selectConfig) {
412
+ selectConfig = {};
413
+ var getList = function($el) {
414
+ return $el.map(function() {
415
+ return {value:this.value, label:this.text};
416
+ }).get();
417
+ };
418
+ if ($el.find('optgroup').length) {
419
+ list = {opt_labels:[]};
420
+ // Search for options without optgroup
421
+ if ($el.find('> option').length) {
422
+ list.opt_labels.push(undefined);
423
+ _.each($el.find('> option'), function(el) {
424
+ list[undefined] = getList(Backbone.$(el));
425
+ });
426
+ }
427
+ _.each($el.find('optgroup'), function(el) {
428
+ var label = Backbone.$(el).attr('label');
429
+ list.opt_labels.push(label);
430
+ list[label] = getList(Backbone.$(el).find('option'));
431
+ });
432
+ } else {
433
+ list = getList($el.find('option'));
434
+ }
435
+ }
436
+
437
+ // Fill in default label and path values.
438
+ selectConfig.valuePath = selectConfig.valuePath || 'value';
439
+ selectConfig.labelPath = selectConfig.labelPath || 'label';
440
+
441
+ var addSelectOptions = function(optList, $el, fieldVal) {
442
+ _.each(optList, function(obj) {
443
+ var option = Backbone.$('<option/>'), optionVal = obj;
444
+
445
+ var fillOption = function(text, val) {
446
+ option.text(text);
447
+ optionVal = val;
448
+ // Save the option value as data so that we can reference it later.
449
+ option.data('stickit_bind_val', optionVal);
450
+ if (!_.isArray(optionVal) && !_.isObject(optionVal)) option.val(optionVal);
451
+ };
452
+
453
+ if (obj === '__default__')
454
+ fillOption(selectConfig.defaultOption.label, selectConfig.defaultOption.value);
455
+ else
456
+ fillOption(evaluatePath(obj, selectConfig.labelPath), evaluatePath(obj, selectConfig.valuePath));
457
+
458
+ // Determine if this option is selected.
459
+ if (!isMultiple && optionVal != null && fieldVal != null && optionVal === fieldVal || (_.isObject(fieldVal) && _.isEqual(optionVal, fieldVal)))
460
+ option.prop('selected', true);
461
+ else if (isMultiple && _.isArray(fieldVal)) {
462
+ _.each(fieldVal, function(val) {
463
+ if (_.isObject(val)) val = evaluatePath(val, selectConfig.valuePath);
464
+ if (val === optionVal || (_.isObject(val) && _.isEqual(optionVal, val)))
465
+ option.prop('selected', true);
466
+ });
467
+ }
468
+
469
+ $el.append(option);
470
+ });
471
+ };
472
+
473
+ $el.html('');
474
+
475
+ // The `list` configuration is a function that returns the options list or a string
476
+ // which represents the path to the list relative to `window` or the view/`this`.
477
+ var evaluate = function(view, list) {
478
+ var context = window;
479
+ if (list.indexOf('this.') === 0) context = view;
480
+ list = list.replace(/^[a-z]*\.(.+)$/, '$1');
481
+ return evaluatePath(context, list);
482
+ };
483
+ if (_.isString(list)) optList = evaluate(this, list);
484
+ else if (_.isFunction(list)) optList = applyViewFn(this, list, $el, options);
485
+ else optList = list;
486
+
487
+ // Support Backbone.Collection and deserialize.
488
+ if (optList instanceof Backbone.Collection) optList = optList.toJSON();
489
+
490
+ if (selectConfig.defaultOption) {
491
+ addSelectOptions(["__default__"], $el);
492
+ }
493
+
494
+ if (_.isArray(optList)) {
495
+ addSelectOptions(optList, $el, val);
496
+ } else if (optList.opt_labels) {
497
+ // To define a select with optgroups, format selectOptions.collection as an object
498
+ // with an 'opt_labels' property, as in the following:
499
+ //
500
+ // {
501
+ // 'opt_labels': ['Looney Tunes', 'Three Stooges'],
502
+ // 'Looney Tunes': [{id: 1, name: 'Bugs Bunny'}, {id: 2, name: 'Donald Duck'}],
503
+ // 'Three Stooges': [{id: 3, name : 'moe'}, {id: 4, name : 'larry'}, {id: 5, name : 'curly'}]
504
+ // }
505
+ //
506
+ _.each(optList.opt_labels, function(label) {
507
+ var $group = Backbone.$('<optgroup/>').attr('label', label);
508
+ addSelectOptions(optList[label], $group, val);
509
+ $el.append($group);
510
+ });
511
+ // With no 'opt_labels' parameter, the object is assumed to be a simple value-label map.
512
+ // Pass a selectOptions.comparator to override the default order of alphabetical by label.
513
+ } else {
514
+ var opts = [], opt;
515
+ for (var i in optList) {
516
+ opt = {};
517
+ opt[selectConfig.valuePath] = i;
518
+ opt[selectConfig.labelPath] = optList[i];
519
+ opts.push(opt);
520
+ }
521
+ addSelectOptions(_.sortBy(opts, selectConfig.comparator || selectConfig.labelPath), $el, val);
522
+ }
523
+ },
524
+ getVal: function($el) {
525
+ var val;
526
+ if ($el.prop('multiple')) {
527
+ val = Backbone.$(getSelectedOption($el).map(function() {
528
+ return Backbone.$(this).data('stickit_bind_val');
529
+ })).get();
530
+ } else {
531
+ val = getSelectedOption($el).data('stickit_bind_val');
532
+ }
533
+ return val;
534
+ }
535
+ }]);
536
+
537
+ }));
@@ -1 +1 @@
1
- //= require js_stack/backbone.stickit/backbone.stickit-0.6.3
1
+ //= require js_stack/backbone.stickit/backbone.stickit-0.7.0
@@ -1,6 +1,6 @@
1
1
  // MarionetteJS (Backbone.Marionette)
2
2
  // ----------------------------------
3
- // v1.4.0
3
+ // v1.4.1
4
4
  //
5
5
  // Copyright (c)2013 Derick Bailey, Muted Solutions, LLC.
6
6
  // Distributed under MIT license
@@ -1211,7 +1211,7 @@ Marionette.View = Backbone.View.extend({
1211
1211
  // this is a backfill since backbone removed the assignment
1212
1212
  // of this.options
1213
1213
  // at some point however this may be removed
1214
- this.options = options || {};
1214
+ this.options = _.extend({}, this.options, options);
1215
1215
 
1216
1216
  // parses out the @ui DSL for events
1217
1217
  this.events = this.normalizeUIKeys(_.result(this, 'events'));
@@ -1 +1 @@
1
- //= require js_stack/marionette/marionette-1.4.0
1
+ //= require js_stack/marionette/marionette-1.4.1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: js_stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomasz Pewiński
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-29 00:00:00.000000000 Z
11
+ date: 2014-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: haml_coffee_assets
@@ -106,9 +106,10 @@ files:
106
106
  - vendor/assets/javascripts/js_stack/backbone.js
107
107
  - vendor/assets/javascripts/js_stack/backbone.pageable.js
108
108
  - vendor/assets/javascripts/js_stack/backbone.pageable/backbone.pageable-1.3.2.js
109
- - vendor/assets/javascripts/js_stack/backbone.pageable/backbone.pageable-1.4.1.js
109
+ - vendor/assets/javascripts/js_stack/backbone.pageable/backbone.pageable-1.4.3.js
110
110
  - vendor/assets/javascripts/js_stack/backbone.stickit.js
111
111
  - vendor/assets/javascripts/js_stack/backbone.stickit/backbone.stickit-0.6.3.js
112
+ - vendor/assets/javascripts/js_stack/backbone.stickit/backbone.stickit-0.7.0.js
112
113
  - vendor/assets/javascripts/js_stack/backbone.validation.js
113
114
  - vendor/assets/javascripts/js_stack/backbone.validation/backbone.validation-0.8.1.js
114
115
  - vendor/assets/javascripts/js_stack/backbone.validation/backbone.validation-0.9.0.js
@@ -121,7 +122,7 @@ files:
121
122
  - vendor/assets/javascripts/js_stack/jsroutes.js
122
123
  - vendor/assets/javascripts/js_stack/marionette.js
123
124
  - vendor/assets/javascripts/js_stack/marionette/marionette-1.1.0.js
124
- - vendor/assets/javascripts/js_stack/marionette/marionette-1.4.0.js
125
+ - vendor/assets/javascripts/js_stack/marionette/marionette-1.4.1.js
125
126
  - vendor/assets/javascripts/js_stack/moment.js
126
127
  - vendor/assets/javascripts/js_stack/underscore.js
127
128
  homepage: https://github.com/netguru/js_stack