js_stack 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,293 @@
1
+ (function (global) {
2
+ 'use strict';
3
+
4
+ var _ = global._, Backbone = global.Backbone, vc, iterators;
5
+
6
+ if ((!_ || !Backbone) && (typeof require !== 'undefined')) {
7
+ _ = require('underscore');
8
+ Backbone = require('backbone');
9
+ }
10
+
11
+ iterators = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
12
+ 'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
13
+ 'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
14
+ 'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
15
+ 'tail', 'drop', 'last', 'without', 'indexOf', 'shuffle', 'lastIndexOf',
16
+ 'isEmpty', 'chain'];
17
+
18
+ /**
19
+ * Constructor for the virtual collection
20
+ * @param {Collection} collection
21
+ * @param {Function|Object} filter function, or hash of properties to match
22
+ * @param {Object} options
23
+ * @param {[Function|Object]} filter function, or hash of properties to match
24
+ * @param {[Function|String]} comparator
25
+ */
26
+ function VirtualCollection(collection, options) {
27
+ this.collection = collection;
28
+ options = options || {};
29
+ this.comparator = options.comparator;
30
+
31
+ _.bindAll(this, 'each', 'map', 'get', 'at', 'indexOf', 'sort', 'closeWith',
32
+ '_rebuildIndex', '_models', '_onAdd', '_onRemove', '_onChange', '_onReset',
33
+ '_indexAdd', '_indexRemove');
34
+
35
+ if (!options.filter) {
36
+ this.filter = function () { return true; };
37
+ } else if (_.isFunction(options.filter)) {
38
+ this.filter = options.filter;
39
+ } else if (options.filter.constructor === Object) {
40
+ this.filter = VirtualCollection.buildFilterFromHash(options.filter);
41
+ }
42
+
43
+ // build index
44
+ this._rebuildIndex();
45
+
46
+ this.listenTo(this.collection, 'add', this._onAdd, this);
47
+ this.listenTo(this.collection, 'remove', this._onRemove, this);
48
+ this.listenTo(this.collection, 'change', this._onChange, this);
49
+ this.listenTo(this.collection, 'reset', this._onReset, this);
50
+
51
+ if (options.close_with) {
52
+ this.closeWith(options.close_with);
53
+ }
54
+ }
55
+
56
+ /**
57
+ * [static] Returns a function that returns true for models that meet the specified conditions
58
+ * @param {Object} hash of model attributes
59
+ * @return {Function} filtering function
60
+ */
61
+ VirtualCollection.buildFilterFromHash = function (hash) {
62
+ return function (model) {
63
+ return !Boolean(_(Object.keys(hash)).detect(function (key) {
64
+ return model.get(key) !== hash[key];
65
+ }));
66
+ };
67
+ };
68
+
69
+ vc = VirtualCollection.prototype;
70
+
71
+
72
+ // mix in Underscore method as proxies
73
+ _.each(iterators, function (method) {
74
+ vc[method] = function () {
75
+ var args = Array.prototype.slice.call(arguments);
76
+ args.unshift(this._models());
77
+ return _[method].apply(_, args);
78
+ };
79
+ });
80
+
81
+ /**
82
+ * Returns a model if it belongs to the virtual collection
83
+ * @param {String} id
84
+ * @return {Model}
85
+ */
86
+ vc.get = function (id) {
87
+ var model = this.collection.get(id);
88
+ if (model && this.filter(model)) {
89
+ return model;
90
+ }
91
+ };
92
+
93
+ /**
94
+ * Returns the model at the position in the index
95
+ * @param {Number} index
96
+ * @return {Model}
97
+ */
98
+ vc.at = function (index) {
99
+ return this.collection.get(this.index[index]);
100
+ };
101
+
102
+ /**
103
+ * Returns the index of the model in the virtual collection
104
+ * @param {Model} model
105
+ * @return {Number} index
106
+ */
107
+ vc.indexOf = function (model) {
108
+ return this.index.indexOf(model.cid);
109
+ };
110
+
111
+ /**
112
+ * Sorts the models in the virtual collection
113
+ *
114
+ * You only need to trigger this manually if you change the comparator
115
+ * @param {Object} options
116
+ * @return {VirtualCollection}
117
+ */
118
+ vc.sort = function (options) {
119
+ var self = this;
120
+ if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
121
+ options = options || {};
122
+
123
+ // Run sort based on type of `comparator`.
124
+ if (_.isString(this.comparator)) {
125
+ this.index = _.sortBy(this.index, function (cid) {
126
+ var model = this.collection.get(cid);
127
+ return model.get(this.comparator);
128
+ }, this);
129
+ } else if (this.comparator.length === 1) {
130
+ this.index = _.sortBy(this.index, function (cid) {
131
+ var model = this.collection.get(cid);
132
+ return this.comparator.call(self, model);
133
+ }, this);
134
+ } else {
135
+ this.index.sort(function (cid1, cid2) {
136
+ var model1 = self.collection.get(cid1),
137
+ model2 = self.collection.get(cid2);
138
+
139
+ return self.comparator.call(self, model1, model2);
140
+ });
141
+ }
142
+
143
+ if (!options.silent) this.trigger('sort', this, options);
144
+ return this;
145
+ };
146
+
147
+ /**
148
+ * A utility function for unbiding listeners
149
+ * @param {View} view (marionette view)
150
+ */
151
+ vc.closeWith = function (view) {
152
+ view.on('close', function () {
153
+ this.stopListening();
154
+ }, this);
155
+ };
156
+
157
+ // private
158
+
159
+ vc._rebuildIndex = function () {
160
+ this.index = [];
161
+ this.collection.each(function (model) {
162
+ if (this.filter(model)) {
163
+ this.index.push(model.cid);
164
+ }
165
+ }, this);
166
+ if (this.comparator) {
167
+ this.sort({silent: true});
168
+ }
169
+ this.length = this.index.length;
170
+ };
171
+
172
+ /**
173
+ * Returns an array of models in the virtual collection
174
+ * @return {Array}
175
+ */
176
+ vc._models = function () {
177
+ return _.map(this.index, function (cid) {
178
+ return this.collection.get(cid);
179
+ }, this);
180
+ };
181
+
182
+ /**
183
+ * Handles the collection:add event
184
+ * May update the virtual collection's index
185
+ * @param {Model} model
186
+ * @return {undefined}
187
+ */
188
+ vc._onAdd = function (model, collection, options) {
189
+ if (this.filter(model)) {
190
+ this._indexAdd(model);
191
+ this.trigger('add', model, this, options);
192
+ }
193
+ };
194
+
195
+ /**
196
+ * Handles the collection:remove event
197
+ * May update the virtual collection's index
198
+ * @param {Model} model
199
+ * @return {undefined}
200
+ */
201
+ vc._onRemove = function (model, collection, options) {
202
+ if (_(this.index).contains(model.cid)) {
203
+ this._indexRemove(model);
204
+ this.trigger('remove', model, this, options);
205
+ }
206
+ };
207
+
208
+ /**
209
+ * Handles the collection:change event
210
+ * May update the virtual collection's index
211
+ * @param {Model} model
212
+ * @param {Object} object
213
+ */
214
+ vc._onChange = function (model, options) {
215
+ var already_here = _.contains(this.index, model.cid);
216
+ if (this.filter(model)) {
217
+ if (already_here) {
218
+ this.trigger('change', model, this, options);
219
+ } else {
220
+ this._indexAdd(model);
221
+ this.trigger('add', model, this, options);
222
+ }
223
+ } else {
224
+ if (already_here) {
225
+ this._indexRemove(model);
226
+ this.trigger('remove', model, this, options);
227
+ }
228
+ }
229
+ };
230
+
231
+ /**
232
+ * Handles the collection:reset event
233
+ * @param {Collection} collection
234
+ * @param {Object} object
235
+ */
236
+ vc._onReset = function (collection, options) {
237
+ this._rebuildIndex();
238
+ this.trigger('reset', this, options);
239
+ };
240
+
241
+ /**
242
+ * Adds a model to the virtual collection index
243
+ * Inserting it in the correct order
244
+ * @param {Model} model
245
+ * @return {undefined}
246
+ */
247
+ vc._indexAdd = function (model) {
248
+ if (this.index.indexOf(model.cid) === -1) {
249
+
250
+ if (!this.comparator) { // order inherit's from parent collection
251
+ var i, orig_index = this.collection.indexOf(model);
252
+ for (i = 0; i < this.length; i++) {
253
+ if (this.collection.indexOf(this.collection.get(this.index[i])) > orig_index) {
254
+ break;
255
+ }
256
+ }
257
+ this.index.splice(i, 0, model.cid);
258
+
259
+ } else { // the virtual collection has a custom order
260
+ this.index.push(model.cid);
261
+ this.sort({silent: true});
262
+ }
263
+ this.length = this.index.length;
264
+ }
265
+ };
266
+
267
+ /**
268
+ * Removes a model from the virtual collection index
269
+ * @param {Model} model
270
+ * @return {undefined}
271
+ */
272
+ vc._indexRemove = function (model) {
273
+ var i = this.index.indexOf(model.cid);
274
+ if (i !== -1) {
275
+ this.index.splice(i, 1);
276
+ this.length = this.index.length;
277
+ }
278
+ };
279
+
280
+ if (!_ && (typeof require !== 'undefined')) {
281
+ _ = require('underscore');
282
+ }
283
+ if (!Backbone && (typeof require !== 'undefined')) {
284
+ Backbone = require('backbone');
285
+ }
286
+ if (typeof module !== 'undefined' && module.exports) {
287
+ module.exports = VirtualCollection;
288
+ }
289
+ _.extend(vc, Backbone.Events);
290
+
291
+ Backbone.VirtualCollection = VirtualCollection;
292
+
293
+ }(this));
@@ -0,0 +1 @@
1
+ //= require js_stack/backbone.virtualcollection/backbone.virtualcollection-0.4.5
@@ -0,0 +1 @@
1
+ //= require backbone.marionette
@@ -0,0 +1,8 @@
1
+ //= require js_stack/backbone
2
+ //= require js_stack/backbone.stickit
3
+ //= require js_stack/marionette
4
+ //= require js_stack/backbone.validation
5
+ //= require js_stack/backbone.pageable
6
+ //= require js_stack/backbone.deepmodel
7
+ //= require js_stack/backbone.associations
8
+ //= require js_stack/backbone.virtualcollection
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: js_stack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tomasz Pewiński
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: backbone-rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: marionette-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: standard SPA stack used at netguru.co
70
+ email:
71
+ - pewniak747@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - Gemfile
77
+ - Gemfile.lock
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - js_stack.gemspec
82
+ - js_stack/.gitignore
83
+ - lib/js_stack.rb
84
+ - lib/js_stack/version.rb
85
+ - vendor/assets/javascripts/js_stack.js
86
+ - vendor/assets/javascripts/js_stack/backbone.associations.js
87
+ - vendor/assets/javascripts/js_stack/backbone.associations/backbone.associations-0.5.1.js
88
+ - vendor/assets/javascripts/js_stack/backbone.deepmodel.js
89
+ - vendor/assets/javascripts/js_stack/backbone.deepmodel/backbone.deepmodel-0.10.4.js
90
+ - vendor/assets/javascripts/js_stack/backbone.js
91
+ - vendor/assets/javascripts/js_stack/backbone.pageable.js
92
+ - vendor/assets/javascripts/js_stack/backbone.pageable/backbone.pageable-1.3.2.js
93
+ - vendor/assets/javascripts/js_stack/backbone.stickit.js
94
+ - vendor/assets/javascripts/js_stack/backbone.stickit/backbone.stickit-0.6.3.js
95
+ - vendor/assets/javascripts/js_stack/backbone.validation.js
96
+ - vendor/assets/javascripts/js_stack/backbone.validation/backbone.validation-0.8.1.js
97
+ - vendor/assets/javascripts/js_stack/backbone.virtualcollection.js
98
+ - vendor/assets/javascripts/js_stack/backbone.virtualcollection/backbone.virtualcollection-0.4.5.js
99
+ - vendor/assets/javascripts/js_stack/marionette.js
100
+ homepage: https://github.com/netguru/js_stack
101
+ licenses:
102
+ - MIT
103
+ metadata: {}
104
+ post_install_message:
105
+ rdoc_options: []
106
+ require_paths:
107
+ - lib
108
+ required_ruby_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 2.0.3
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: standard SPA stack used at netguru.co
124
+ test_files: []