backgridjs-rails 0.2.6

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.
Files changed (26) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +25 -0
  4. data/Rakefile +27 -0
  5. data/lib/backgridjs-rails.rb +5 -0
  6. data/lib/backgridjs-rails.rb~ +2 -0
  7. data/lib/backgridjs-rails/engine.rb +8 -0
  8. data/lib/backgridjs-rails/engine.rb~ +8 -0
  9. data/lib/backgridjs-rails/version.rb +3 -0
  10. data/lib/backgridjs-rails/version.rb~ +3 -0
  11. data/lib/tasks/backgridjs-rails_tasks.rake +4 -0
  12. data/vendor/assets/javascripts/backgrid-extensions/backgrid-filter.js +365 -0
  13. data/vendor/assets/javascripts/backgrid-extensions/backgrid-moment-cell.js +175 -0
  14. data/vendor/assets/javascripts/backgrid-extensions/backgrid-paginator.js +198 -0
  15. data/vendor/assets/javascripts/backgrid-extensions/backgrid-select-all.js +215 -0
  16. data/vendor/assets/javascripts/backgrid-extensions/backgrid-select2-cell.js +121 -0
  17. data/vendor/assets/javascripts/backgrid-extensions/backgrid-text-cell.js +159 -0
  18. data/vendor/assets/javascripts/backgrid.js +2531 -0
  19. data/vendor/assets/stylesheets/backgrid-extensions/backgrid-filter.css +19 -0
  20. data/vendor/assets/stylesheets/backgrid-extensions/backgrid-moment-cell.css +14 -0
  21. data/vendor/assets/stylesheets/backgrid-extensions/backgrid-paginator.css +58 -0
  22. data/vendor/assets/stylesheets/backgrid-extensions/backgrid-select-all.css +11 -0
  23. data/vendor/assets/stylesheets/backgrid-extensions/backgrid-select2-cell.css +19 -0
  24. data/vendor/assets/stylesheets/backgrid-extensions/backgrid-text-cell.css +31 -0
  25. data/vendor/assets/stylesheets/backgrid.css +215 -0
  26. metadata +82 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjE2OTQ4Y2JjNTM2YzM2MWFkYmEzM2U0MjBhNGViMTQxN2JkZjBiZA==
5
+ data.tar.gz: !binary |-
6
+ ZTNiOGU0MGViYmI1ZTUzMTExNmUzMWYyYjNiNzVmNzU4ZWQ1OTliZA==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ MWY3MDhiNDhjNDkyOTQ1ZTBiNDM5MTQ0YWUwYWUwMDhmOWNkNjQ4YmFhNTdm
10
+ NTljZGUyYzMxNzM4NDg0MGIyNDJjY2RkZmM4OGEzOThjNjc2OTcwYThlNTNj
11
+ Y2FlYjc5ZDRhYzM2MDg3ODQ3ODg1MDc0ODA4ODFiYjAzMzMzMTU=
12
+ data.tar.gz: !binary |-
13
+ YzNlNjQ4MTg5YTg1N2Q5ZDE4YTkyYmJkOGE1N2ZmODEwMjg1NDJjMDc2MDc2
14
+ MDk5MzY3ZTRjYTU1OWU0M2FhYzc2YjZiMmJhMmEzMWE5NWY5MGIxODQ2NzQy
15
+ N2Y4ZDIwY2E3YWY1YWQ0Y2MyNTMxMjMzOWQ4MWQ0NTg2YjkwMDk=
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ = BackgridjsRails
2
+
3
+ Vendors backgrid js and extensions into rails asset pipeline
4
+
5
+ == Installation
6
+
7
+ Add the gem to your Gemfile
8
+
9
+ gem 'backgridjs-rails'
10
+
11
+ Then add backgrid to the app/assets/javascripts/application.js
12
+
13
+ //= require backgrid
14
+
15
+ And to app/assets/stylesheets/application.css.scss
16
+
17
+ *= require backgrid
18
+
19
+ == Extensions
20
+
21
+ The backgrid extensions are included too, to use them add the revelant one to application.js and application.css.scss
22
+
23
+ //= require backgrid-extensions/backgrid-filter
24
+
25
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'BackgridjsRails'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
@@ -0,0 +1,5 @@
1
+ module BackgridjsRails
2
+ module Rails
3
+ require 'backgridjs-rails/engine'
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ module BackgridjsRails
2
+ end
@@ -0,0 +1,8 @@
1
+ require 'rails'
2
+
3
+ module BackgridjsRails
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'rails'
2
+
3
+ module Backgridjs
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ module BackgridjsRails
2
+ VERSION = "0.2.6"
3
+ end
@@ -0,0 +1,3 @@
1
+ module BackgridjsRails
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :backgridjs-rails do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,365 @@
1
+ /*
2
+ backgrid-filter
3
+ http://github.com/wyuenho/backgrid
4
+
5
+ Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
6
+ Licensed under the MIT @license.
7
+ */
8
+
9
+ (function ($, _, Backbone, Backgrid, lunr) {
10
+
11
+ "use strict";
12
+
13
+ /**
14
+ ServerSideFilter is a search form widget that submits a query to the server
15
+ for filtering the current collection.
16
+
17
+ @class Backgrid.Extension.ServerSideFilter
18
+ */
19
+ var ServerSideFilter = Backgrid.Extension.ServerSideFilter = Backbone.View.extend({
20
+
21
+ /** @property */
22
+ tagName: "form",
23
+
24
+ /** @property */
25
+ className: "backgrid-filter form-search",
26
+
27
+ /** @property {function(Object, ?Object=): string} template */
28
+ template: _.template('<div class="input-prepend input-append"><span class="add-on"><i class="icon-search"></i></span><input type="text" <% if (placeholder) { %> placeholder="<%- placeholder %>" <% } %> name="<%- name %>" /><span class="add-on"><a class="close" href="#">&times;</a></span></div>'),
29
+
30
+ /** @property */
31
+ events: {
32
+ "click .close": "clear",
33
+ "submit": "search"
34
+ },
35
+
36
+ /** @property {string} [name='q'] Query key */
37
+ name: "q",
38
+
39
+ /** @property The HTML5 placeholder to appear beneath the search box. */
40
+ placeholder: null,
41
+
42
+ /**
43
+ @param {Object} options
44
+ @param {Backbone.Collection} options.collection
45
+ @param {String} [options.name]
46
+ @param {String} [options.placeholder]
47
+ */
48
+ initialize: function (options) {
49
+ Backgrid.requireOptions(options, ["collection"]);
50
+ Backbone.View.prototype.initialize.apply(this, arguments);
51
+ this.name = options.name || this.name;
52
+ this.placeholder = options.placeholder || this.placeholder;
53
+
54
+ var collection = this.collection, self = this;
55
+ if (Backbone.PageableCollection &&
56
+ collection instanceof Backbone.PageableCollection &&
57
+ collection.mode == "server") {
58
+ collection.queryParams[this.name] = function () {
59
+ return self.$el.find("input[type=text]").val();
60
+ };
61
+ }
62
+ },
63
+
64
+ /**
65
+ Upon search form submission, this event handler constructs a query
66
+ parameter object and pass it to Collection#fetch for server-side
67
+ filtering.
68
+ */
69
+ search: function (e) {
70
+ if (e) e.preventDefault();
71
+ var data = {};
72
+ data[this.name] = this.$el.find("input[type=text]").val();
73
+ this.collection.fetch({data: data});
74
+ },
75
+
76
+ /**
77
+ Event handler for the close button. Clears the search box and refetch the
78
+ collection.
79
+ */
80
+ clear: function (e) {
81
+ if (e) e.preventDefault();
82
+ this.$("input[type=text]").val(null);
83
+ this.collection.fetch();
84
+ },
85
+
86
+ /**
87
+ Renders a search form with a text box, optionally with a placeholder and
88
+ a preset value if supplied during initialization.
89
+ */
90
+ render: function () {
91
+ this.$el.empty().append(this.template({
92
+ name: this.name,
93
+ placeholder: this.placeholder,
94
+ value: this.value
95
+ }));
96
+ this.delegateEvents();
97
+ return this;
98
+ }
99
+
100
+ });
101
+
102
+ /**
103
+ ClientSideFilter is a search form widget that searches a collection for
104
+ model matches against a query on the client side. The exact matching
105
+ algorithm can be overriden by subclasses.
106
+
107
+ @class Backgrid.Extension.ClientSideFilter
108
+ @extends Backgrid.Extension.ServerSideFilter
109
+ */
110
+ var ClientSideFilter = Backgrid.Extension.ClientSideFilter = ServerSideFilter.extend({
111
+
112
+ /** @property */
113
+ events: {
114
+ "click .close": function (e) {
115
+ e.preventDefault();
116
+ this.clear();
117
+ },
118
+ "change input[type=text]": "search",
119
+ "keyup input[type=text]": "search",
120
+ "submit": function (e) {
121
+ e.preventDefault();
122
+ this.search();
123
+ }
124
+ },
125
+
126
+ /**
127
+ @property {?Array.<string>} A list of model field names to search
128
+ for matches. If null, all of the fields will be searched.
129
+ */
130
+ fields: null,
131
+
132
+ /**
133
+ @property wait The time in milliseconds to wait since for since the last
134
+ change to the search box's value before searching. This value can be
135
+ adjusted depending on how often the search box is used and how large the
136
+ search index is.
137
+ */
138
+ wait: 149,
139
+
140
+ /**
141
+ Debounces the #search and #clear methods and makes a copy of the given
142
+ collection for searching.
143
+
144
+ @param {Object} options
145
+ @param {Backbone.Collection} options.collection
146
+ @param {String} [options.placeholder]
147
+ @param {String} [options.fields]
148
+ @param {String} [options.wait=149]
149
+ */
150
+ initialize: function (options) {
151
+ ServerSideFilter.prototype.initialize.apply(this, arguments);
152
+
153
+ this.fields = options.fields || this.fields;
154
+ this.wait = options.wait || this.wait;
155
+
156
+ this._debounceMethods(["search", "clear"]);
157
+
158
+ var collection = this.collection;
159
+ var shadowCollection = this.shadowCollection = collection.clone();
160
+ shadowCollection.url = collection.url;
161
+ shadowCollection.sync = collection.sync;
162
+ shadowCollection.parse = collection.parse;
163
+
164
+ this.listenTo(collection, "add", function (model, collection, options) {
165
+ shadowCollection.add(model, options);
166
+ });
167
+ this.listenTo(collection, "remove", function (model, collection, options) {
168
+ shadowCollection.remove(model, options);
169
+ });
170
+ this.listenTo(collection, "sort reset", function (collection, options) {
171
+ options = _.extend({reindex: true}, options || {});
172
+ if (options.reindex) shadowCollection.reset(collection.models);
173
+ });
174
+ },
175
+
176
+ _debounceMethods: function (methodNames) {
177
+ if (_.isString(methodNames)) methodNames = [methodNames];
178
+
179
+ this.undelegateEvents();
180
+
181
+ for (var i = 0, l = methodNames.length; i < l; i++) {
182
+ var methodName = methodNames[i];
183
+ var method = this[methodName];
184
+ this[methodName] = _.debounce(method, this.wait);
185
+ }
186
+
187
+ this.delegateEvents();
188
+ },
189
+
190
+ /**
191
+ This default implementation takes a query string and returns a matcher
192
+ function that looks for matches in the model's #fields or all of its
193
+ fields if #fields is null, for any of the words in the query
194
+ case-insensitively.
195
+
196
+ Subclasses overriding this method must take care to conform to the
197
+ signature of the matcher function. In addition, when the matcher function
198
+ is called, its context will be bound to this ClientSideFilter object so
199
+ it has access to the filter's attributes and methods.
200
+
201
+ @param {string} query The search query in the search box.
202
+ @return {function(Backbone.Model):boolean} A matching function.
203
+ */
204
+ makeMatcher: function (query) {
205
+ var regexp = new RegExp(query.trim().split(/\W/).join("|"), "i");
206
+ return function (model) {
207
+ var keys = this.fields || model.keys();
208
+ for (var i = 0, l = keys.length; i < l; i++) {
209
+ if (regexp.test(model.get(keys[i]) + "")) return true;
210
+ }
211
+ return false;
212
+ };
213
+ },
214
+
215
+ /**
216
+ Takes the query from the search box, constructs a matcher with it and
217
+ loops through collection looking for matches. Reset the given collection
218
+ when all the matches have been found.
219
+ */
220
+ search: function () {
221
+ var matcher = _.bind(this.makeMatcher(this.$("input[type=text]").val()), this);
222
+ this.collection.reset(this.shadowCollection.filter(matcher), {reindex: false});
223
+ },
224
+
225
+ /**
226
+ Clears the search box and reset the collection to its original.
227
+ */
228
+ clear: function () {
229
+ this.$("input[type=text]").val(null);
230
+ this.collection.reset(this.shadowCollection.models, {reindex: false});
231
+ }
232
+
233
+ });
234
+
235
+ /**
236
+ LunrFilter is a ClientSideFilter that uses [lunrjs](http://lunrjs.com/) to
237
+ index the text fields of each model for a collection, and performs
238
+ full-text searching.
239
+
240
+ @class Backgrid.Extension.LunrFilter
241
+ @extends Backgrid.Extension.ClientSideFilter
242
+ */
243
+ Backgrid.Extension.LunrFilter = ClientSideFilter.extend({
244
+
245
+ /**
246
+ @property {string} [ref="id"]`lunrjs` document reference attribute name.
247
+ */
248
+ ref: "id",
249
+
250
+ /**
251
+ @property {Object} fields A hash of `lunrjs` index field names and boost
252
+ value. Unlike ClientSideFilter#fields, LunrFilter#fields is _required_ to
253
+ initialize the index.
254
+ */
255
+ fields: null,
256
+
257
+ /**
258
+ Indexes the underlying collection on construction. The index will refresh
259
+ when the underlying collection is reset. If any model is added, removed
260
+ or if any indexed fields of any models has changed, the index will be
261
+ updated.
262
+
263
+ @param {Object} options
264
+ @param {Backbone.Collection} options.collection
265
+ @param {String} [options.placeholder]
266
+ @param {string} [options.ref] `lunrjs` document reference attribute name.
267
+ @param {Object} [options.fields] A hash of `lunrjs` index field names and
268
+ boost value.
269
+ @param {number} [options.wait]
270
+ */
271
+ initialize: function (options) {
272
+ ClientSideFilter.prototype.initialize.apply(this, arguments);
273
+
274
+ this.ref = options.ref || this.ref;
275
+
276
+ var collection = this.collection;
277
+ this.listenTo(collection, "add", this.addToIndex);
278
+ this.listenTo(collection, "remove", this.removeFromIndex);
279
+ this.listenTo(collection, "reset", this.resetIndex);
280
+ this.listenTo(collection, "change", this.updateIndex);
281
+
282
+ this.resetIndex(collection);
283
+ },
284
+
285
+ /**
286
+ Reindex the collection. If `options.reindex` is `false`, this method is a
287
+ no-op.
288
+
289
+ @param {Backbone.Collection} collection
290
+ @param {Object} [options]
291
+ @param {boolean} [options.reindex=true]
292
+ */
293
+ resetIndex: function (collection, options) {
294
+ options = _.extend({reindex: true}, options || {});
295
+
296
+ if (options.reindex) {
297
+ var self = this;
298
+ this.index = lunr(function () {
299
+ _.each(self.fields, function (boost, fieldName) {
300
+ this.field(fieldName, boost);
301
+ this.ref(self.ref);
302
+ }, this);
303
+ });
304
+
305
+ collection.each(function (model) {
306
+ this.addToIndex(model);
307
+ }, this);
308
+ }
309
+ },
310
+
311
+ /**
312
+ Adds the given model to the index.
313
+
314
+ @param {Backbone.Model} model
315
+ */
316
+ addToIndex: function (model) {
317
+ var index = this.index;
318
+ var doc = model.toJSON();
319
+ if (index.documentStore.has(doc[this.ref])) index.update(doc);
320
+ else index.add(doc);
321
+ },
322
+
323
+ /**
324
+ Removes the given model from the index.
325
+
326
+ @param {Backbone.Model} model
327
+ */
328
+ removeFromIndex: function (model) {
329
+ var index = this.index;
330
+ var doc = model.toJSON();
331
+ if (index.documentStore.has(doc[this.ref])) index.remove(doc);
332
+ },
333
+
334
+ /**
335
+ Updates the index for the given model.
336
+
337
+ @param {Backbone.Model} model
338
+ */
339
+ updateIndex: function (model) {
340
+ var changed = model.changedAttributes();
341
+ if (changed && !_.isEmpty(_.intersection(_.keys(this.fields),
342
+ _.keys(changed)))) {
343
+ this.index.update(model.toJSON());
344
+ }
345
+ },
346
+
347
+ /**
348
+ Takes the query from the search box and performs a full-text search on
349
+ the client-side. The search result is returned by resetting the
350
+ underlying collection to the models after interrogating the index for the
351
+ query answer.
352
+ */
353
+ search: function () {
354
+ var searchResults = this.index.search(this.$("input[type=text]").val());
355
+ var models = [];
356
+ for (var i = 0; i < searchResults.length; i++) {
357
+ var result = searchResults[i];
358
+ models.push(this.shadowCollection.get(result.ref));
359
+ }
360
+ this.collection.reset(models, {reindex: false});
361
+ }
362
+
363
+ });
364
+
365
+ }(jQuery, _, Backbone, Backgrid, lunr));