js_stack 0.5.7 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +7 -7
  4. data/lib/js_stack/version.rb +1 -1
  5. data/vendor/assets/javascripts/js_stack/base/marionette/{1.8.0.js → 1.8.3.js} +173 -8
  6. data/vendor/assets/javascripts/js_stack/base/marionette.js +1 -1
  7. data/vendor/assets/javascripts/js_stack/plugins/backbone/stickit/0.8.0.js +595 -0
  8. data/vendor/assets/javascripts/js_stack/plugins/backbone.stickit.js +1 -1
  9. metadata +4 -17
  10. data/vendor/assets/javascripts/js_stack/base/backbone/1.1.0.js +0 -1581
  11. data/vendor/assets/javascripts/js_stack/base/backbone/1.1.1.js +0 -1609
  12. data/vendor/assets/javascripts/js_stack/base/marionette/1.6.2.js +0 -2555
  13. data/vendor/assets/javascripts/js_stack/base/marionette/1.7.0.js +0 -2746
  14. data/vendor/assets/javascripts/js_stack/base/marionette/1.7.3.js +0 -2765
  15. data/vendor/assets/javascripts/js_stack/plugins/backbone/associations/0.5.1.js +0 -533
  16. data/vendor/assets/javascripts/js_stack/plugins/backbone/associations/0.5.4.js +0 -574
  17. data/vendor/assets/javascripts/js_stack/plugins/backbone/mutators/0.4.1.js +0 -207
  18. data/vendor/assets/javascripts/js_stack/plugins/backbone/pageable/1.4.5.js +0 -1318
  19. data/vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.11.js +0 -345
  20. data/vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.12.js +0 -351
  21. data/vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.14.js +0 -398
  22. data/vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.5.js +0 -293
  23. data/vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.8.js +0 -340
@@ -0,0 +1,595 @@
1
+ // Backbone.Stickit v0.8.0, MIT Licensed
2
+ // Copyright (c) 2012 The New York Times, CMS Group, Matthew DeLambo <delambo@gmail.com>
3
+
4
+ (function (factory) {
5
+
6
+ // Set up Stickit appropriately for the environment. Start with AMD.
7
+ if (typeof define === 'function' && define.amd) {
8
+ define(['underscore', 'backbone', 'exports'], factory);
9
+ }
10
+
11
+ // Next for Node.js or CommonJS.
12
+ else if (typeof exports === 'object') {
13
+ factory(require('underscore'), require('backbone'), exports);
14
+ }
15
+
16
+ // Finally, as a browser global.
17
+ else {
18
+ factory(_, Backbone, {});
19
+ }
20
+
21
+ }(function (_, Backbone, Stickit) {
22
+
23
+ // Stickit Namespace
24
+ // --------------------------
25
+
26
+ Stickit._handlers = [];
27
+
28
+ Stickit.addHandler = function(handlers) {
29
+ // Fill-in default values.
30
+ handlers = _.map(_.flatten([handlers]), function(handler) {
31
+ return _.extend({
32
+ updateModel: true,
33
+ updateView: true,
34
+ updateMethod: 'text'
35
+ }, handler);
36
+ });
37
+ this._handlers = this._handlers.concat(handlers);
38
+ };
39
+
40
+ // Backbone.View Mixins
41
+ // --------------------
42
+
43
+ Stickit.ViewMixin = {
44
+
45
+ // Collection of model event bindings.
46
+ // [{model,event,fn,config}, ...]
47
+ _modelBindings: null,
48
+
49
+ // Unbind the model and event bindings from `this._modelBindings` and
50
+ // `this.$el`. If the optional `model` parameter is defined, then only
51
+ // delete bindings for the given `model` and its corresponding view events.
52
+ unstickit: function(model, bindingSelector) {
53
+ // Support bindings hash in place of selector.
54
+ if (_.isObject(bindingSelector)) {
55
+ _.each(_.keys(bindingSelector), function(selector) {
56
+ this.unstickit(model, selector);
57
+ }, this);
58
+ return;
59
+ }
60
+
61
+ var models = [], destroyFns = [];
62
+ _.each(this._modelBindings, function(binding, i) {
63
+ if (model && binding.model !== model) { return; }
64
+ if (bindingSelector && binding.config.selector != bindingSelector) return;
65
+ destroyFns.push(binding.config._destroy);
66
+ binding.model.off(binding.event, binding.fn);
67
+ models.push(binding.model);
68
+ delete this._modelBindings[i];
69
+ }, this);
70
+
71
+ // Trigger an event for each model that was unbound.
72
+ _.invoke(_.uniq(models), 'trigger', 'stickit:unstuck', this.cid);
73
+ // Call `_destroy` on a unique list of the binding callbacks.
74
+ _.each(_.uniq(destroyFns), function(fn) { fn.call(this); }, this);
75
+ // Cleanup the null values.
76
+ this._modelBindings = _.compact(this._modelBindings);
77
+
78
+ this.$el.off('.stickit' + (model ? '.' + model.cid : ''), bindingSelector);
79
+ },
80
+
81
+ // Using `this.bindings` configuration or the `optionalBindingsConfig`, binds `this.model`
82
+ // or the `optionalModel` to elements in the view.
83
+ stickit: function(optionalModel, optionalBindingsConfig) {
84
+ var model = optionalModel || this.model,
85
+ bindings = optionalBindingsConfig || _.result(this, "bindings") || {};
86
+
87
+ this._modelBindings || (this._modelBindings = []);
88
+
89
+ // Iterate through the selectors in the bindings configuration and configure
90
+ // the various options for each field.
91
+ this.addBinding(model, bindings);
92
+
93
+ // Wrap `view.remove` to unbind stickit model and dom events.
94
+ var remove = this.remove;
95
+ if (!remove.stickitWrapped) {
96
+ this.remove = function() {
97
+ var ret = this;
98
+ this.unstickit();
99
+ if (remove) ret = remove.apply(this, arguments);
100
+ return ret;
101
+ };
102
+ }
103
+ this.remove.stickitWrapped = true;
104
+ return this;
105
+ },
106
+
107
+ // Add a single model binding to the view
108
+ addBinding: function(optionalModel, second, _binding) {
109
+ var $el, options, modelAttr, config, selector,
110
+ model = optionalModel || this.model,
111
+ namespace = '.stickit.' + model.cid,
112
+ binding = _binding || {},
113
+ bindId = _.uniqueId();
114
+
115
+ // Allow jQuery-style {key: val} event maps
116
+ if (_.isString(second)) {
117
+ selector = second;
118
+ } else {
119
+ var bindings = second;
120
+ _.each(bindings, function(v, selector) {
121
+ this.addBinding(model, selector, bindings[selector]);
122
+ }, this);
123
+ return;
124
+ }
125
+
126
+ // Support ':el' selector - special case selector for the view managed delegate.
127
+ $el = selector === ':el' ? this.$el : this.$(selector);
128
+
129
+ this.unstickit(model, selector);
130
+
131
+ // Fail fast if the selector didn't match an element.
132
+ if (!$el.length) return;
133
+
134
+ // Allow shorthand setting of model attributes - `'selector':'observe'`.
135
+ if (_.isString(binding)) binding = {observe:binding};
136
+
137
+ // Handle case where `observe` is in the form of a function.
138
+ if (_.isFunction(binding.observe)) binding.observe = binding.observe.call(this);
139
+
140
+ config = getConfiguration($el, binding);
141
+ config.selector = selector;
142
+ modelAttr = config.observe;
143
+
144
+ // Create the model set options with a unique `bindId` so that we
145
+ // can avoid double-binding in the `change:attribute` event handler.
146
+ config.bindId = bindId;
147
+
148
+ // Add a reference to the view for handlers of stickitChange events
149
+ config.view = this;
150
+ options = _.extend({stickitChange:config}, config.setOptions);
151
+
152
+ // Add a `_destroy` callback to the configuration, in case `destroy`
153
+ // is a named function and we need a unique function when unsticking.
154
+ config._destroy = function() {
155
+ applyViewFn(this, config.destroy, $el, model, config);
156
+ };
157
+
158
+ initializeAttributes(this, $el, config, model, modelAttr);
159
+
160
+ initializeClasses(this, $el, config, model, modelAttr);
161
+
162
+ initializeVisible(this, $el, config, model, modelAttr);
163
+
164
+ if (modelAttr) {
165
+ // Setup one-way, form element to model, bindings.
166
+ _.each(config.events, function(type) {
167
+ var event = type + namespace;
168
+ var method = function(event) {
169
+ var val = config.getVal.call(this, $el, event, config, _.rest(arguments));
170
+ // Don't update the model if false is returned from the `updateModel` configuration.
171
+ if (evaluateBoolean(this, config.updateModel, val, event, config))
172
+ setAttr(model, modelAttr, val, options, this, config);
173
+ };
174
+ method = _.bind(method, this);
175
+ if (selector === ':el') this.$el.on(event, method);
176
+ else this.$el.on(event, selector, method);
177
+ }, this);
178
+
179
+ // Setup a `change:modelAttr` observer to keep the view element in sync.
180
+ // `modelAttr` may be an array of attributes or a single string value.
181
+ _.each(_.flatten([modelAttr]), function(attr) {
182
+ observeModelEvent(model, this, 'change:'+attr, config, function(model, val, options) {
183
+ var changeId = options && options.stickitChange && options.stickitChange.bindId || null;
184
+ if (changeId !== bindId)
185
+ updateViewBindEl(this, $el, config, getAttr(model, modelAttr, config, this), model);
186
+ });
187
+ }, this);
188
+
189
+ updateViewBindEl(this, $el, config, getAttr(model, modelAttr, config, this), model, true);
190
+ }
191
+
192
+ // After each binding is setup, call the `initialize` callback.
193
+ applyViewFn(this, config.initialize, $el, model, config);
194
+ }
195
+ };
196
+
197
+ _.extend(Backbone.View.prototype, Stickit.ViewMixin);
198
+
199
+ // Helpers
200
+ // -------
201
+
202
+ // Evaluates the given `path` (in object/dot-notation) relative to the given
203
+ // `obj`. If the path is null/undefined, then the given `obj` is returned.
204
+ var evaluatePath = function(obj, path) {
205
+ var parts = (path || '').split('.');
206
+ var result = _.reduce(parts, function(memo, i) { return memo[i]; }, obj);
207
+ return result == null ? obj : result;
208
+ };
209
+
210
+ // If the given `fn` is a string, then view[fn] is called, otherwise it is
211
+ // a function that should be executed.
212
+ var applyViewFn = function(view, fn) {
213
+ if (fn) return (_.isString(fn) ? evaluatePath(view,fn) : fn).apply(view, _.rest(arguments, 2));
214
+ };
215
+
216
+ var getSelectedOption = function($select) { return $select.find('option').not(function(){ return !this.selected; }); };
217
+
218
+ // Given a function, string (view function reference), or a boolean
219
+ // value, returns the truthy result. Any other types evaluate as false.
220
+ var evaluateBoolean = function(view, reference) {
221
+ if (_.isBoolean(reference)) return reference;
222
+ else if (_.isFunction(reference) || _.isString(reference))
223
+ return applyViewFn.apply(this, arguments);
224
+ return false;
225
+ };
226
+
227
+ // Setup a model event binding with the given function, and track the event
228
+ // in the view's _modelBindings.
229
+ var observeModelEvent = function(model, view, event, config, fn) {
230
+ model.on(event, fn, view);
231
+ view._modelBindings.push({model:model, event:event, fn:fn, config:config});
232
+ };
233
+
234
+ // Prepares the given `val`ue and sets it into the `model`.
235
+ var setAttr = function(model, attr, val, options, context, config) {
236
+ var value = {};
237
+ if (config.onSet)
238
+ val = applyViewFn(context, config.onSet, val, config);
239
+
240
+ if (config.set)
241
+ applyViewFn(context, config.set, attr, val, options, config);
242
+ else {
243
+ value[attr] = val;
244
+ // If `observe` is defined as an array and `onSet` returned
245
+ // an array, then map attributes to their values.
246
+ if (_.isArray(attr) && _.isArray(val)) {
247
+ value = _.reduce(attr, function(memo, attribute, index) {
248
+ memo[attribute] = _.has(val, index) ? val[index] : null;
249
+ return memo;
250
+ }, {});
251
+ }
252
+ model.set(value, options);
253
+ }
254
+ };
255
+
256
+ // Returns the given `attr`'s value from the `model`, escaping and
257
+ // formatting if necessary. If `attr` is an array, then an array of
258
+ // respective values will be returned.
259
+ var getAttr = function(model, attr, config, context) {
260
+ var val,
261
+ retrieveVal = function(field) {
262
+ return model[config.escape ? 'escape' : 'get'](field);
263
+ },
264
+ sanitizeVal = function(val) {
265
+ return val == null ? '' : val;
266
+ };
267
+ val = _.isArray(attr) ? _.map(attr, retrieveVal) : retrieveVal(attr);
268
+ if (config.onGet) val = applyViewFn(context, config.onGet, val, config);
269
+ return _.isArray(val) ? _.map(val, sanitizeVal) : sanitizeVal(val);
270
+ };
271
+
272
+ // Find handlers in `Backbone.Stickit._handlers` with selectors that match
273
+ // `$el` and generate a configuration by mixing them in the order that they
274
+ // were found with the given `binding`.
275
+ var getConfiguration = Stickit.getConfiguration = function($el, binding) {
276
+ var handlers = [{
277
+ updateModel: false,
278
+ updateMethod: 'text',
279
+ update: function($el, val, m, opts) { if ($el[opts.updateMethod]) $el[opts.updateMethod](val); },
280
+ getVal: function($el, e, opts) { return $el[opts.updateMethod](); }
281
+ }];
282
+ handlers = handlers.concat(_.filter(Stickit._handlers, function(handler) {
283
+ return $el.is(handler.selector);
284
+ }));
285
+ handlers.push(binding);
286
+ var config = _.extend.apply(_, handlers);
287
+ // `updateView` is defaulted to false for configutrations with
288
+ // `visible`; otherwise, `updateView` is defaulted to true.
289
+ if (config.visible && !_.has(config, 'updateView')) config.updateView = false;
290
+ else if (!_.has(config, 'updateView')) config.updateView = true;
291
+ return config;
292
+ };
293
+
294
+ // Setup the attributes configuration - a list that maps an attribute or
295
+ // property `name`, to an `observe`d model attribute, using an optional
296
+ // `onGet` formatter.
297
+ //
298
+ // attributes: [{
299
+ // name: 'attributeOrPropertyName',
300
+ // observe: 'modelAttrName'
301
+ // onGet: function(modelAttrVal, modelAttrName) { ... }
302
+ // }, ...]
303
+ //
304
+ var initializeAttributes = function(view, $el, config, model, modelAttr) {
305
+ var props = ['autofocus', 'autoplay', 'async', 'checked', 'controls', 'defer', 'disabled', 'hidden', 'indeterminate', 'loop', 'multiple', 'open', 'readonly', 'required', 'scoped', 'selected'];
306
+
307
+ _.each(config.attributes || [], function(attrConfig) {
308
+ var lastClass = '', observed, updateAttr;
309
+ attrConfig = _.clone(attrConfig);
310
+ observed = attrConfig.observe || (attrConfig.observe = modelAttr),
311
+ updateAttr = function() {
312
+ var updateType = _.indexOf(props, attrConfig.name, true) > -1 ? 'prop' : 'attr',
313
+ val = getAttr(model, observed, attrConfig, view);
314
+ // If it is a class then we need to remove the last value and add the new.
315
+ if (attrConfig.name === 'class') {
316
+ $el.removeClass(lastClass).addClass(val);
317
+ lastClass = val;
318
+ }
319
+ else $el[updateType](attrConfig.name, val);
320
+ };
321
+ _.each(_.flatten([observed]), function(attr) {
322
+ observeModelEvent(model, view, 'change:' + attr, config, updateAttr);
323
+ });
324
+ updateAttr();
325
+ });
326
+ };
327
+
328
+ var initializeClasses = function(view, $el, config, model, modelAttr) {
329
+ _.each(config.classes || [], function(classConfig, name) {
330
+ var observed, updateClass;
331
+ observed = classConfig.observe || classConfig;
332
+ updateClass = function() {
333
+ var val = getAttr(model, observed, classConfig, view);
334
+ $el.toggleClass(name, !!val);
335
+ };
336
+
337
+ _.each(_.flatten([observed]), function(attr) {
338
+ observeModelEvent(model, view, 'change:' + attr, config, updateClass);
339
+ });
340
+ updateClass();
341
+ });
342
+ };
343
+
344
+ // If `visible` is configured, then the view element will be shown/hidden
345
+ // based on the truthiness of the modelattr's value or the result of the
346
+ // given callback. If a `visibleFn` is also supplied, then that callback
347
+ // will be executed to manually handle showing/hiding the view element.
348
+ //
349
+ // observe: 'isRight',
350
+ // visible: true, // or function(val, options) {}
351
+ // visibleFn: function($el, isVisible, options) {} // optional handler
352
+ //
353
+ var initializeVisible = function(view, $el, config, model, modelAttr) {
354
+ if (config.visible == null) return;
355
+ var visibleCb = function() {
356
+ var visible = config.visible,
357
+ visibleFn = config.visibleFn,
358
+ val = getAttr(model, modelAttr, config, view),
359
+ isVisible = !!val;
360
+ // If `visible` is a function then it should return a boolean result to show/hide.
361
+ if (_.isFunction(visible) || _.isString(visible)) isVisible = !!applyViewFn(view, visible, val, config);
362
+ // Either use the custom `visibleFn`, if provided, or execute the standard show/hide.
363
+ if (visibleFn) applyViewFn(view, visibleFn, $el, isVisible, config);
364
+ else {
365
+ $el.toggle(isVisible);
366
+ }
367
+ };
368
+ _.each(_.flatten([modelAttr]), function(attr) {
369
+ observeModelEvent(model, view, 'change:' + attr, config, visibleCb);
370
+ });
371
+ visibleCb();
372
+ };
373
+
374
+ // Update the value of `$el` using the given configuration and trigger the
375
+ // `afterUpdate` callback. This action may be blocked by `config.updateView`.
376
+ //
377
+ // update: function($el, val, model, options) {}, // handler for updating
378
+ // updateView: true, // defaults to true
379
+ // afterUpdate: function($el, val, options) {} // optional callback
380
+ //
381
+ var updateViewBindEl = function(view, $el, config, val, model, isInitializing) {
382
+ if (!evaluateBoolean(view, config.updateView, val, config)) return;
383
+ applyViewFn(view, config.update, $el, val, model, config);
384
+ if (!isInitializing) applyViewFn(view, config.afterUpdate, $el, val, config);
385
+ };
386
+
387
+ // Default Handlers
388
+ // ----------------
389
+
390
+ Stickit.addHandler([{
391
+ selector: '[contenteditable="true"]',
392
+ updateMethod: 'html',
393
+ events: ['input', 'change']
394
+ }, {
395
+ selector: 'input',
396
+ events: ['propertychange', 'input', 'change'],
397
+ update: function($el, val) { $el.val(val); },
398
+ getVal: function($el) {
399
+ return $el.val();
400
+ }
401
+ }, {
402
+ selector: 'textarea',
403
+ events: ['propertychange', 'input', 'change'],
404
+ update: function($el, val) { $el.val(val); },
405
+ getVal: function($el) { return $el.val(); }
406
+ }, {
407
+ selector: 'input[type="radio"]',
408
+ events: ['change'],
409
+ update: function($el, val) {
410
+ $el.filter('[value="'+val+'"]').prop('checked', true);
411
+ },
412
+ getVal: function($el) {
413
+ return $el.filter(':checked').val();
414
+ }
415
+ }, {
416
+ selector: 'input[type="checkbox"]',
417
+ events: ['change'],
418
+ update: function($el, val, model, options) {
419
+ if ($el.length > 1) {
420
+ // There are multiple checkboxes so we need to go through them and check
421
+ // any that have value attributes that match what's in the array of `val`s.
422
+ val || (val = []);
423
+ $el.each(function(i, el) {
424
+ var checkbox = Backbone.$(el);
425
+ var checked = _.contains(val, checkbox.val());
426
+ checkbox.prop('checked', checked);
427
+ });
428
+ } else {
429
+ var checked = _.isBoolean(val) ? val : val === $el.val();
430
+ $el.prop('checked', checked);
431
+ }
432
+ },
433
+ getVal: function($el) {
434
+ var val;
435
+ if ($el.length > 1) {
436
+ val = _.reduce($el, function(memo, el) {
437
+ var checkbox = Backbone.$(el);
438
+ if (checkbox.prop('checked')) memo.push(checkbox.val());
439
+ return memo;
440
+ }, []);
441
+ } else {
442
+ val = $el.prop('checked');
443
+ // If the checkbox has a value attribute defined, then
444
+ // use that value. Most browsers use "on" as a default.
445
+ var boxval = $el.val();
446
+ if (boxval !== 'on' && boxval != null) {
447
+ val = val ? $el.val() : null;
448
+ }
449
+ }
450
+ return val;
451
+ }
452
+ }, {
453
+ selector: 'select',
454
+ events: ['change'],
455
+ update: function($el, val, model, options) {
456
+ var optList,
457
+ selectConfig = options.selectOptions,
458
+ list = selectConfig && selectConfig.collection || undefined,
459
+ isMultiple = $el.prop('multiple');
460
+
461
+ // If there are no `selectOptions` then we assume that the `<select>`
462
+ // is pre-rendered and that we need to generate the collection.
463
+ if (!selectConfig) {
464
+ selectConfig = {};
465
+ var getList = function($el) {
466
+ return $el.map(function() {
467
+ return {value:this.value, label:this.text};
468
+ }).get();
469
+ };
470
+ if ($el.find('optgroup').length) {
471
+ list = {opt_labels:[]};
472
+ // Search for options without optgroup
473
+ if ($el.find('> option').length) {
474
+ list.opt_labels.push(undefined);
475
+ _.each($el.find('> option'), function(el) {
476
+ list[undefined] = getList(Backbone.$(el));
477
+ });
478
+ }
479
+ _.each($el.find('optgroup'), function(el) {
480
+ var label = Backbone.$(el).attr('label');
481
+ list.opt_labels.push(label);
482
+ list[label] = getList(Backbone.$(el).find('option'));
483
+ });
484
+ } else {
485
+ list = getList($el.find('option'));
486
+ }
487
+ }
488
+
489
+ // Fill in default label and path values.
490
+ selectConfig.valuePath = selectConfig.valuePath || 'value';
491
+ selectConfig.labelPath = selectConfig.labelPath || 'label';
492
+
493
+ var addSelectOptions = function(optList, $el, fieldVal) {
494
+ _.each(optList, function(obj) {
495
+ var option = Backbone.$('<option/>'), optionVal = obj;
496
+
497
+ var fillOption = function(text, val) {
498
+ option.text(text);
499
+ optionVal = val;
500
+ // Save the option value as data so that we can reference it later.
501
+ option.data('stickit_bind_val', optionVal);
502
+ if (!_.isArray(optionVal) && !_.isObject(optionVal)) option.val(optionVal);
503
+ };
504
+
505
+ if (obj === '__default__')
506
+ fillOption(selectConfig.defaultOption.label, selectConfig.defaultOption.value);
507
+ else
508
+ fillOption(evaluatePath(obj, selectConfig.labelPath), evaluatePath(obj, selectConfig.valuePath));
509
+
510
+ // Determine if this option is selected.
511
+ if (!isMultiple && optionVal != null && fieldVal != null && optionVal === fieldVal || (_.isObject(fieldVal) && _.isEqual(optionVal, fieldVal)))
512
+ option.prop('selected', true);
513
+ else if (isMultiple && _.isArray(fieldVal)) {
514
+ _.each(fieldVal, function(val) {
515
+ if (_.isObject(val)) val = evaluatePath(val, selectConfig.valuePath);
516
+ if (val === optionVal || (_.isObject(val) && _.isEqual(optionVal, val)))
517
+ option.prop('selected', true);
518
+ });
519
+ }
520
+
521
+ $el.append(option);
522
+ });
523
+ };
524
+
525
+ $el.find('*').remove();
526
+
527
+ // The `list` configuration is a function that returns the options list or a string
528
+ // which represents the path to the list relative to `window` or the view/`this`.
529
+ var evaluate = function(view, list) {
530
+ var context = window;
531
+ if (list.indexOf('this.') === 0) context = view;
532
+ list = list.replace(/^[a-z]*\.(.+)$/, '$1');
533
+ return evaluatePath(context, list);
534
+ };
535
+ if (_.isString(list)) optList = evaluate(this, list);
536
+ else if (_.isFunction(list)) optList = applyViewFn(this, list, $el, options);
537
+ else optList = list;
538
+
539
+ // Support Backbone.Collection and deserialize.
540
+ if (optList instanceof Backbone.Collection) optList = optList.toJSON();
541
+
542
+ if (selectConfig.defaultOption) {
543
+ addSelectOptions(["__default__"], $el);
544
+ }
545
+
546
+ if (_.isArray(optList)) {
547
+ addSelectOptions(optList, $el, val);
548
+ } else if (optList.opt_labels) {
549
+ // To define a select with optgroups, format selectOptions.collection as an object
550
+ // with an 'opt_labels' property, as in the following:
551
+ //
552
+ // {
553
+ // 'opt_labels': ['Looney Tunes', 'Three Stooges'],
554
+ // 'Looney Tunes': [{id: 1, name: 'Bugs Bunny'}, {id: 2, name: 'Donald Duck'}],
555
+ // 'Three Stooges': [{id: 3, name : 'moe'}, {id: 4, name : 'larry'}, {id: 5, name : 'curly'}]
556
+ // }
557
+ //
558
+ _.each(optList.opt_labels, function(label) {
559
+ var $group = Backbone.$('<optgroup/>').attr('label', label);
560
+ addSelectOptions(optList[label], $group, val);
561
+ $el.append($group);
562
+ });
563
+ // With no 'opt_labels' parameter, the object is assumed to be a simple value-label map.
564
+ // Pass a selectOptions.comparator to override the default order of alphabetical by label.
565
+ } else {
566
+ var opts = [], opt;
567
+ for (var i in optList) {
568
+ opt = {};
569
+ opt[selectConfig.valuePath] = i;
570
+ opt[selectConfig.labelPath] = optList[i];
571
+ opts.push(opt);
572
+ }
573
+ addSelectOptions(_.sortBy(opts, selectConfig.comparator || selectConfig.labelPath), $el, val);
574
+ }
575
+ },
576
+ getVal: function($el) {
577
+ var val;
578
+ if ($el.prop('multiple')) {
579
+ val = Backbone.$(getSelectedOption($el).map(function() {
580
+ return Backbone.$(this).data('stickit_bind_val');
581
+ })).get();
582
+ } else {
583
+ val = getSelectedOption($el).data('stickit_bind_val');
584
+ }
585
+ return val;
586
+ }
587
+ }]);
588
+
589
+
590
+ // Export onto Backbone object
591
+ Backbone.Stickit = Stickit;
592
+
593
+ return Backbone.Stickit;
594
+
595
+ }));
@@ -1 +1 @@
1
- //= require js_stack/plugins/backbone/stickit/0.7.0
1
+ //= require js_stack/plugins/backbone/stickit/0.8.0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: js_stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.7
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomasz Pewiński
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-15 00:00:00.000000000 Z
12
+ date: 2014-04-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: haml_coffee_assets
@@ -103,8 +103,6 @@ files:
103
103
  - vendor/assets/javascripts/js_stack/base.js
104
104
  - vendor/assets/javascripts/js_stack/base/backbone.js
105
105
  - vendor/assets/javascripts/js_stack/base/backbone/1.0.0.js
106
- - vendor/assets/javascripts/js_stack/base/backbone/1.1.0.js
107
- - vendor/assets/javascripts/js_stack/base/backbone/1.1.1.js
108
106
  - vendor/assets/javascripts/js_stack/base/backbone/1.1.2.js
109
107
  - vendor/assets/javascripts/js_stack/base/hamlcoffee.js
110
108
  - vendor/assets/javascripts/js_stack/base/jsroutes.js
@@ -112,12 +110,9 @@ files:
112
110
  - vendor/assets/javascripts/js_stack/base/marionette/1.1.0.js
113
111
  - vendor/assets/javascripts/js_stack/base/marionette/1.4.1.js
114
112
  - vendor/assets/javascripts/js_stack/base/marionette/1.5.1.js
115
- - vendor/assets/javascripts/js_stack/base/marionette/1.6.2.js
116
113
  - vendor/assets/javascripts/js_stack/base/marionette/1.6.4.js
117
- - vendor/assets/javascripts/js_stack/base/marionette/1.7.0.js
118
- - vendor/assets/javascripts/js_stack/base/marionette/1.7.3.js
119
114
  - vendor/assets/javascripts/js_stack/base/marionette/1.7.4.js
120
- - vendor/assets/javascripts/js_stack/base/marionette/1.8.0.js
115
+ - vendor/assets/javascripts/js_stack/base/marionette/1.8.3.js
121
116
  - vendor/assets/javascripts/js_stack/base/underscore.js
122
117
  - vendor/assets/javascripts/js_stack/base/underscore/1.5.2.js
123
118
  - vendor/assets/javascripts/js_stack/base/underscore/1.6.0.js
@@ -130,27 +125,19 @@ files:
130
125
  - vendor/assets/javascripts/js_stack/plugins/backbone.stickit.js
131
126
  - vendor/assets/javascripts/js_stack/plugins/backbone.validation.js
132
127
  - vendor/assets/javascripts/js_stack/plugins/backbone.virtualcollection.js
133
- - vendor/assets/javascripts/js_stack/plugins/backbone/associations/0.5.1.js
134
- - vendor/assets/javascripts/js_stack/plugins/backbone/associations/0.5.4.js
135
128
  - vendor/assets/javascripts/js_stack/plugins/backbone/associations/0.5.5.js
136
129
  - vendor/assets/javascripts/js_stack/plugins/backbone/associations/0.6.1.js
137
130
  - vendor/assets/javascripts/js_stack/plugins/backbone/deepmodel/0.10.4.js
138
- - vendor/assets/javascripts/js_stack/plugins/backbone/mutators/0.4.1.js
139
131
  - vendor/assets/javascripts/js_stack/plugins/backbone/mutators/0.4.2.js
140
132
  - vendor/assets/javascripts/js_stack/plugins/backbone/pageable/1.3.2.js
141
- - vendor/assets/javascripts/js_stack/plugins/backbone/pageable/1.4.5.js
142
133
  - vendor/assets/javascripts/js_stack/plugins/backbone/pageable/1.4.8.js
143
134
  - vendor/assets/javascripts/js_stack/plugins/backbone/routefilter/0.2.0.js
144
135
  - vendor/assets/javascripts/js_stack/plugins/backbone/stickit/0.6.3.js
145
136
  - vendor/assets/javascripts/js_stack/plugins/backbone/stickit/0.7.0.js
137
+ - vendor/assets/javascripts/js_stack/plugins/backbone/stickit/0.8.0.js
146
138
  - vendor/assets/javascripts/js_stack/plugins/backbone/validation/0.8.1.js
147
139
  - vendor/assets/javascripts/js_stack/plugins/backbone/validation/0.9.1.js
148
- - vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.11.js
149
- - vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.12.js
150
- - vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.14.js
151
140
  - vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.15.js
152
- - vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.5.js
153
- - vendor/assets/javascripts/js_stack/plugins/backbone/virtualcollection/0.4.8.js
154
141
  - vendor/assets/javascripts/js_stack/plugins/cocktail.js
155
142
  - vendor/assets/javascripts/js_stack/plugins/cocktail/0.5.3.js
156
143
  - vendor/assets/javascripts/js_stack/plugins/moment.js