backgridjs-rails 0.2.6 → 0.3.5
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.
- checksums.yaml +6 -14
- data/lib/backgridjs-rails/version.rb +1 -1
- data/vendor/assets/javascripts/backgrid-extensions/backgrid-filter.js +192 -49
- data/vendor/assets/javascripts/backgrid-extensions/backgrid-moment-cell.js +15 -5
- data/vendor/assets/javascripts/backgrid-extensions/backgrid-paginator.js +341 -112
- data/vendor/assets/javascripts/backgrid-extensions/backgrid-select-all.js +109 -32
- data/vendor/assets/javascripts/backgrid-extensions/backgrid-select2-cell.js +42 -14
- data/vendor/assets/javascripts/backgrid-extensions/backgrid-text-cell.js +18 -9
- data/vendor/assets/javascripts/backgrid.js +689 -336
- data/vendor/assets/stylesheets/backgrid-extensions/backgrid-filter.css +181 -7
- data/vendor/assets/stylesheets/backgrid-extensions/backgrid-moment-cell.css +2 -1
- data/vendor/assets/stylesheets/backgrid-extensions/backgrid-paginator.css +5 -5
- data/vendor/assets/stylesheets/backgrid-extensions/backgrid-select-all.css +2 -1
- data/vendor/assets/stylesheets/backgrid-extensions/backgrid-select2-cell.css +1 -1
- data/vendor/assets/stylesheets/backgrid-extensions/backgrid-text-cell.css +3 -3
- data/vendor/assets/stylesheets/backgrid.css +35 -10
- metadata +18 -21
- data/lib/backgridjs-rails.rb~ +0 -2
- data/lib/backgridjs-rails/engine.rb~ +0 -8
- data/lib/backgridjs-rails/version.rb~ +0 -3
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
MWY3MDhiNDhjNDkyOTQ1ZTBiNDM5MTQ0YWUwYWUwMDhmOWNkNjQ4YmFhNTdm
|
10
|
-
NTljZGUyYzMxNzM4NDg0MGIyNDJjY2RkZmM4OGEzOThjNjc2OTcwYThlNTNj
|
11
|
-
Y2FlYjc5ZDRhYzM2MDg3ODQ3ODg1MDc0ODA4ODFiYjAzMzMzMTU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
YzNlNjQ4MTg5YTg1N2Q5ZDE4YTkyYmJkOGE1N2ZmODEwMjg1NDJjMDc2MDc2
|
14
|
-
MDk5MzY3ZTRjYTU1OWU0M2FhYzc2YjZiMmJhMmEzMWE5NWY5MGIxODQ2NzQy
|
15
|
-
N2Y4ZDIwY2E3YWY1YWQ0Y2MyNTMxMjMzOWQ4MWQ0NTg2YjkwMDk=
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1ab7aafbde55ffeca00bdf228fce029974a92330
|
4
|
+
data.tar.gz: b800be2fe7b2eba3a228ee2cd1b3a17991dc89c5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c78c96f141e13784f227aac7c34d99e8a14a382c20304de71986a45f04b2f14cd52481fec128e8b2ccfa44e490dc9bd099a412ab1825e7076f9d6c48180c140a
|
7
|
+
data.tar.gz: 4f0f4a01bf087193b623468ca02634e6ca426bb09aecb37a9660c3f1a1f82028098a9031a8383fd7804a47e0045d10f0c80e4a199527ebf0b0061c90f7740642
|
@@ -5,8 +5,25 @@
|
|
5
5
|
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
6
6
|
Licensed under the MIT @license.
|
7
7
|
*/
|
8
|
-
|
9
|
-
|
8
|
+
(function (root, factory) {
|
9
|
+
|
10
|
+
// CommonJS
|
11
|
+
if (typeof exports == "object") {
|
12
|
+
(function () {
|
13
|
+
var lunr;
|
14
|
+
try { lunr = require("lunr"); } catch (e) {}
|
15
|
+
module.exports = factory(require("underscore"),
|
16
|
+
require("backbone"),
|
17
|
+
require("backgrid"),
|
18
|
+
lunr);
|
19
|
+
}());
|
20
|
+
}
|
21
|
+
// Browser
|
22
|
+
else {
|
23
|
+
factory(root._, root.Backbone, root.Backgrid, root.lunr);
|
24
|
+
}
|
25
|
+
|
26
|
+
}(this, function (_, Backbone, Backgrid, lunr) {
|
10
27
|
|
11
28
|
"use strict";
|
12
29
|
|
@@ -25,62 +42,140 @@
|
|
25
42
|
className: "backgrid-filter form-search",
|
26
43
|
|
27
44
|
/** @property {function(Object, ?Object=): string} template */
|
28
|
-
template: _.template('<
|
45
|
+
template: _.template('<span class="search"> </span><input type="search" <% if (placeholder) { %> placeholder="<%- placeholder %>" <% } %> name="<%- name %>" <% if (value) { %> value="<%- value %>" <% } %>/><a class="clear" data-backgrid-action="clear" href="#">×</a>', null, {variable: null}),
|
29
46
|
|
30
47
|
/** @property */
|
31
48
|
events: {
|
32
|
-
"
|
49
|
+
"keyup input[type=search]": "showClearButtonMaybe",
|
50
|
+
"click a[data-backgrid-action=clear]": "clear",
|
33
51
|
"submit": "search"
|
34
52
|
},
|
35
53
|
|
36
54
|
/** @property {string} [name='q'] Query key */
|
37
55
|
name: "q",
|
38
56
|
|
39
|
-
/** @property
|
57
|
+
/** @property {string} [value] The search box value. */
|
58
|
+
value: null,
|
59
|
+
|
60
|
+
/**
|
61
|
+
@property {string} [placeholder] The HTML5 placeholder to appear beneath
|
62
|
+
the search box.
|
63
|
+
*/
|
40
64
|
placeholder: null,
|
41
65
|
|
42
66
|
/**
|
43
67
|
@param {Object} options
|
44
68
|
@param {Backbone.Collection} options.collection
|
45
|
-
@param {
|
46
|
-
@param {
|
69
|
+
@param {string} [options.name]
|
70
|
+
@param {string} [options.value]
|
71
|
+
@param {string} [options.placeholder]
|
72
|
+
@param {function(Object): string} [options.template]
|
47
73
|
*/
|
48
74
|
initialize: function (options) {
|
49
|
-
|
50
|
-
Backbone.View.prototype.initialize.apply(this, arguments);
|
75
|
+
ServerSideFilter.__super__.initialize.apply(this, arguments);
|
51
76
|
this.name = options.name || this.name;
|
77
|
+
this.value = options.value || this.value;
|
52
78
|
this.placeholder = options.placeholder || this.placeholder;
|
79
|
+
this.template = options.template || this.template;
|
53
80
|
|
81
|
+
// Persist the query on pagination
|
54
82
|
var collection = this.collection, self = this;
|
55
83
|
if (Backbone.PageableCollection &&
|
56
84
|
collection instanceof Backbone.PageableCollection &&
|
57
85
|
collection.mode == "server") {
|
58
86
|
collection.queryParams[this.name] = function () {
|
59
|
-
return self
|
87
|
+
return self.searchBox().val() || null;
|
60
88
|
};
|
61
89
|
}
|
62
90
|
},
|
63
91
|
|
92
|
+
/**
|
93
|
+
Event handler. Clear the search box and reset the internal search value.
|
94
|
+
*/
|
95
|
+
clearSearchBox: function() {
|
96
|
+
this.value = null;
|
97
|
+
this.searchBox().val(null);
|
98
|
+
this.showClearButtonMaybe();
|
99
|
+
},
|
100
|
+
|
101
|
+
/**
|
102
|
+
Event handler. Show the clear button when the search box has text, hide
|
103
|
+
it otherwise.
|
104
|
+
*/
|
105
|
+
showClearButtonMaybe: function () {
|
106
|
+
var $clearButton = this.clearButton();
|
107
|
+
var searchTerms = this.searchBox().val();
|
108
|
+
if (searchTerms) $clearButton.show();
|
109
|
+
else $clearButton.hide();
|
110
|
+
},
|
111
|
+
|
112
|
+
/**
|
113
|
+
Returns the search input box.
|
114
|
+
*/
|
115
|
+
searchBox: function () {
|
116
|
+
return this.$el.find("input[type=search]");
|
117
|
+
},
|
118
|
+
|
119
|
+
/**
|
120
|
+
Returns the clear button.
|
121
|
+
*/
|
122
|
+
clearButton: function () {
|
123
|
+
return this.$el.find("a[data-backgrid-action=clear]");
|
124
|
+
},
|
125
|
+
|
126
|
+
|
127
|
+
/**
|
128
|
+
Returns the current search query.
|
129
|
+
*/
|
130
|
+
query: function() {
|
131
|
+
this.value = this.searchBox().val();
|
132
|
+
return this.value;
|
133
|
+
},
|
134
|
+
|
64
135
|
/**
|
65
136
|
Upon search form submission, this event handler constructs a query
|
66
137
|
parameter object and pass it to Collection#fetch for server-side
|
67
138
|
filtering.
|
139
|
+
|
140
|
+
If the collection is a PageableCollection, searching will go back to the
|
141
|
+
first page.
|
68
142
|
*/
|
69
143
|
search: function (e) {
|
70
144
|
if (e) e.preventDefault();
|
145
|
+
|
71
146
|
var data = {};
|
72
|
-
|
73
|
-
this.
|
147
|
+
var query = this.query();
|
148
|
+
if (query) data[this.name] = query;
|
149
|
+
|
150
|
+
var collection = this.collection;
|
151
|
+
|
152
|
+
// go back to the first page on search
|
153
|
+
if (Backbone.PageableCollection &&
|
154
|
+
collection instanceof Backbone.PageableCollection) {
|
155
|
+
collection.getFirstPage({data: data, reset: true, fetch: true});
|
156
|
+
}
|
157
|
+
else collection.fetch({data: data, reset: true});
|
74
158
|
},
|
75
159
|
|
76
160
|
/**
|
77
|
-
Event handler for the
|
161
|
+
Event handler for the clear button. Clears the search box and refetch the
|
78
162
|
collection.
|
163
|
+
|
164
|
+
If the collection is a PageableCollection, clearing will go back to the
|
165
|
+
first page.
|
79
166
|
*/
|
80
167
|
clear: function (e) {
|
81
168
|
if (e) e.preventDefault();
|
82
|
-
this
|
83
|
-
|
169
|
+
this.clearSearchBox();
|
170
|
+
|
171
|
+
var collection = this.collection;
|
172
|
+
|
173
|
+
// go back to the first page on clear
|
174
|
+
if (Backbone.PageableCollection &&
|
175
|
+
collection instanceof Backbone.PageableCollection) {
|
176
|
+
collection.getFirstPage({reset: true, fetch: true});
|
177
|
+
}
|
178
|
+
else collection.fetch({reset: true});
|
84
179
|
},
|
85
180
|
|
86
181
|
/**
|
@@ -93,6 +188,7 @@
|
|
93
188
|
placeholder: this.placeholder,
|
94
189
|
value: this.value
|
95
190
|
}));
|
191
|
+
this.showClearButtonMaybe();
|
96
192
|
this.delegateEvents();
|
97
193
|
return this;
|
98
194
|
}
|
@@ -110,27 +206,26 @@
|
|
110
206
|
var ClientSideFilter = Backgrid.Extension.ClientSideFilter = ServerSideFilter.extend({
|
111
207
|
|
112
208
|
/** @property */
|
113
|
-
events: {
|
114
|
-
"click
|
209
|
+
events: _.extend({}, ServerSideFilter.prototype.events, {
|
210
|
+
"click a[data-backgrid-action=clear]": function (e) {
|
115
211
|
e.preventDefault();
|
116
212
|
this.clear();
|
117
213
|
},
|
118
|
-
"
|
119
|
-
"keyup input[type=text]": "search",
|
214
|
+
"keydown input[type=search]": "search",
|
120
215
|
"submit": function (e) {
|
121
216
|
e.preventDefault();
|
122
217
|
this.search();
|
123
218
|
}
|
124
|
-
},
|
219
|
+
}),
|
125
220
|
|
126
221
|
/**
|
127
|
-
@property {?Array.<string>} A list of model field names to
|
128
|
-
for matches. If null, all of the fields will be searched.
|
222
|
+
@property {?Array.<string>} [fields] A list of model field names to
|
223
|
+
search for matches. If null, all of the fields will be searched.
|
129
224
|
*/
|
130
225
|
fields: null,
|
131
226
|
|
132
227
|
/**
|
133
|
-
@property wait The time in milliseconds to wait since
|
228
|
+
@property [wait=149] The time in milliseconds to wait since the last
|
134
229
|
change to the search box's value before searching. This value can be
|
135
230
|
adjusted depending on how often the search box is used and how large the
|
136
231
|
search index is.
|
@@ -143,23 +238,20 @@
|
|
143
238
|
|
144
239
|
@param {Object} options
|
145
240
|
@param {Backbone.Collection} options.collection
|
146
|
-
@param {
|
147
|
-
@param {
|
148
|
-
@param {
|
241
|
+
@param {string} [options.placeholder]
|
242
|
+
@param {string} [options.fields]
|
243
|
+
@param {string} [options.wait=149]
|
149
244
|
*/
|
150
245
|
initialize: function (options) {
|
151
|
-
|
246
|
+
ClientSideFilter.__super__.initialize.apply(this, arguments);
|
152
247
|
|
153
248
|
this.fields = options.fields || this.fields;
|
154
249
|
this.wait = options.wait || this.wait;
|
155
250
|
|
156
251
|
this._debounceMethods(["search", "clear"]);
|
157
252
|
|
158
|
-
var collection = this.collection;
|
253
|
+
var collection = this.collection = this.collection.fullCollection || this.collection;
|
159
254
|
var shadowCollection = this.shadowCollection = collection.clone();
|
160
|
-
shadowCollection.url = collection.url;
|
161
|
-
shadowCollection.sync = collection.sync;
|
162
|
-
shadowCollection.parse = collection.parse;
|
163
255
|
|
164
256
|
this.listenTo(collection, "add", function (model, collection, options) {
|
165
257
|
shadowCollection.add(model, options);
|
@@ -167,9 +259,14 @@
|
|
167
259
|
this.listenTo(collection, "remove", function (model, collection, options) {
|
168
260
|
shadowCollection.remove(model, options);
|
169
261
|
});
|
170
|
-
this.listenTo(collection, "sort
|
262
|
+
this.listenTo(collection, "sort", function (col) {
|
263
|
+
if (!this.searchBox().val()) shadowCollection.reset(col.models);
|
264
|
+
});
|
265
|
+
this.listenTo(collection, "reset", function (col, options) {
|
171
266
|
options = _.extend({reindex: true}, options || {});
|
172
|
-
if (options.reindex
|
267
|
+
if (options.reindex && options.from == null && options.to == null) {
|
268
|
+
shadowCollection.reset(col.models);
|
269
|
+
}
|
173
270
|
});
|
174
271
|
},
|
175
272
|
|
@@ -187,22 +284,47 @@
|
|
187
284
|
this.delegateEvents();
|
188
285
|
},
|
189
286
|
|
287
|
+
/**
|
288
|
+
Constructs a Javascript regular expression object for #makeMatcher.
|
289
|
+
|
290
|
+
This default implementation takes a query string and returns a Javascript
|
291
|
+
RegExp object that matches any of the words contained in the query string
|
292
|
+
case-insensitively. Override this method to return a different regular
|
293
|
+
expression matcher if this behavior is not desired.
|
294
|
+
|
295
|
+
@param {string} query The search query in the search box.
|
296
|
+
@return {RegExp} A RegExp object to match against model #fields.
|
297
|
+
*/
|
298
|
+
makeRegExp: function (query) {
|
299
|
+
return new RegExp(query.trim().split(/\s+/).join("|"), "i");
|
300
|
+
},
|
301
|
+
|
190
302
|
/**
|
191
303
|
This default implementation takes a query string and returns a matcher
|
192
304
|
function that looks for matches in the model's #fields or all of its
|
193
305
|
fields if #fields is null, for any of the words in the query
|
194
|
-
case-insensitively
|
306
|
+
case-insensitively using the regular expression object returned from
|
307
|
+
#makeRegExp.
|
308
|
+
|
309
|
+
Most of time, you'd want to override the regular expression used for
|
310
|
+
matching. If so, please refer to the #makeRegExp documentation,
|
311
|
+
otherwise, you can override this method to return a custom matching
|
312
|
+
function.
|
195
313
|
|
196
314
|
Subclasses overriding this method must take care to conform to the
|
197
|
-
signature of the matcher function.
|
198
|
-
|
199
|
-
|
315
|
+
signature of the matcher function. The matcher function is a function
|
316
|
+
that takes a model as paramter and returns true if the model matches a
|
317
|
+
search, or false otherwise.
|
318
|
+
|
319
|
+
In addition, when the matcher function is called, its context will be
|
320
|
+
bound to this ClientSideFilter object so it has access to the filter's
|
321
|
+
attributes and methods.
|
200
322
|
|
201
323
|
@param {string} query The search query in the search box.
|
202
324
|
@return {function(Backbone.Model):boolean} A matching function.
|
203
325
|
*/
|
204
326
|
makeMatcher: function (query) {
|
205
|
-
var regexp =
|
327
|
+
var regexp = this.makeRegExp(query);
|
206
328
|
return function (model) {
|
207
329
|
var keys = this.fields || model.keys();
|
208
330
|
for (var i = 0, l = keys.length; i < l; i++) {
|
@@ -216,18 +338,28 @@
|
|
216
338
|
Takes the query from the search box, constructs a matcher with it and
|
217
339
|
loops through collection looking for matches. Reset the given collection
|
218
340
|
when all the matches have been found.
|
341
|
+
|
342
|
+
If the collection is a PageableCollection, searching will go back to the
|
343
|
+
first page.
|
219
344
|
*/
|
220
345
|
search: function () {
|
221
|
-
var matcher = _.bind(this.makeMatcher(this
|
222
|
-
this.collection
|
346
|
+
var matcher = _.bind(this.makeMatcher(this.query()), this);
|
347
|
+
var col = this.collection;
|
348
|
+
if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
|
349
|
+
col.reset(this.shadowCollection.filter(matcher), {reindex: false});
|
223
350
|
},
|
224
351
|
|
225
352
|
/**
|
226
353
|
Clears the search box and reset the collection to its original.
|
354
|
+
|
355
|
+
If the collection is a PageableCollection, clearing will go back to the
|
356
|
+
first page.
|
227
357
|
*/
|
228
358
|
clear: function () {
|
229
|
-
this
|
230
|
-
this.collection
|
359
|
+
this.clearSearchBox();
|
360
|
+
var col = this.collection;
|
361
|
+
if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
|
362
|
+
col.reset(this.shadowCollection.models, {reindex: false});
|
231
363
|
}
|
232
364
|
|
233
365
|
});
|
@@ -240,7 +372,7 @@
|
|
240
372
|
@class Backgrid.Extension.LunrFilter
|
241
373
|
@extends Backgrid.Extension.ClientSideFilter
|
242
374
|
*/
|
243
|
-
Backgrid.Extension.LunrFilter = ClientSideFilter.extend({
|
375
|
+
var LunrFilter = Backgrid.Extension.LunrFilter = ClientSideFilter.extend({
|
244
376
|
|
245
377
|
/**
|
246
378
|
@property {string} [ref="id"]`lunrjs` document reference attribute name.
|
@@ -262,18 +394,18 @@
|
|
262
394
|
|
263
395
|
@param {Object} options
|
264
396
|
@param {Backbone.Collection} options.collection
|
265
|
-
@param {
|
397
|
+
@param {string} [options.placeholder]
|
266
398
|
@param {string} [options.ref] `lunrjs` document reference attribute name.
|
267
399
|
@param {Object} [options.fields] A hash of `lunrjs` index field names and
|
268
400
|
boost value.
|
269
401
|
@param {number} [options.wait]
|
270
402
|
*/
|
271
403
|
initialize: function (options) {
|
272
|
-
|
404
|
+
LunrFilter.__super__.initialize.apply(this, arguments);
|
273
405
|
|
274
406
|
this.ref = options.ref || this.ref;
|
275
407
|
|
276
|
-
var collection = this.collection;
|
408
|
+
var collection = this.collection = this.collection.fullCollection || this.collection;
|
277
409
|
this.listenTo(collection, "add", this.addToIndex);
|
278
410
|
this.listenTo(collection, "remove", this.removeFromIndex);
|
279
411
|
this.listenTo(collection, "reset", this.resetIndex);
|
@@ -349,17 +481,28 @@
|
|
349
481
|
the client-side. The search result is returned by resetting the
|
350
482
|
underlying collection to the models after interrogating the index for the
|
351
483
|
query answer.
|
484
|
+
|
485
|
+
If the collection is a PageableCollection, searching will go back to the
|
486
|
+
first page.
|
352
487
|
*/
|
353
488
|
search: function () {
|
354
|
-
var
|
489
|
+
var col = this.collection;
|
490
|
+
if (!this.query()) {
|
491
|
+
col.reset(this.shadowCollection.models, {reindex: false});
|
492
|
+
return;
|
493
|
+
}
|
494
|
+
|
495
|
+
var searchResults = this.index.search(this.query());
|
355
496
|
var models = [];
|
356
497
|
for (var i = 0; i < searchResults.length; i++) {
|
357
498
|
var result = searchResults[i];
|
358
499
|
models.push(this.shadowCollection.get(result.ref));
|
359
500
|
}
|
360
|
-
|
501
|
+
|
502
|
+
if (col.pageableCollection) col.pageableCollection.getFirstPage({silent: true});
|
503
|
+
col.reset(models, {reindex: false});
|
361
504
|
}
|
362
505
|
|
363
506
|
});
|
364
507
|
|
365
|
-
}
|
508
|
+
}));
|
@@ -5,7 +5,17 @@
|
|
5
5
|
Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
|
6
6
|
Licensed under the MIT @license.
|
7
7
|
*/
|
8
|
-
(function (
|
8
|
+
(function (root, factory) {
|
9
|
+
|
10
|
+
// CommonJS
|
11
|
+
if (typeof exports == "object") {
|
12
|
+
module.exports = factory(require("underscore"), require("backgrid"),
|
13
|
+
require("moment"));
|
14
|
+
}
|
15
|
+
// Browser
|
16
|
+
else factory(root._, root.Backgrid, root.moment);
|
17
|
+
|
18
|
+
}(this, function (_, Backgrid, moment) {
|
9
19
|
|
10
20
|
/**
|
11
21
|
MomentFormatter converts bi-directionally any datetime values in any format
|
@@ -152,14 +162,14 @@
|
|
152
162
|
*/
|
153
163
|
initialize: function (options) {
|
154
164
|
|
155
|
-
|
165
|
+
MomentCell.__super__.initialize.apply(this, arguments);
|
156
166
|
|
157
167
|
var formatterDefaults = MomentFormatter.prototype.defaults;
|
158
168
|
var formatterDefaultKeys = _.keys(formatterDefaults);
|
159
|
-
var
|
169
|
+
var instanceAttrs = _.pick(this, formatterDefaultKeys);
|
160
170
|
var formatterOptions = _.pick(options, formatterDefaultKeys);
|
161
171
|
|
162
|
-
|
172
|
+
_.extend(this.formatter, formatterDefaults, instanceAttrs, formatterOptions);
|
163
173
|
|
164
174
|
this.editor = this.editor.extend({
|
165
175
|
attributes: _.extend({}, this.editor.prototype.attributes || this.editor.attributes || {}, {
|
@@ -172,4 +182,4 @@
|
|
172
182
|
|
173
183
|
_.extend(MomentCell.prototype, MomentFormatter.prototype.defaults);
|
174
184
|
|
175
|
-
}
|
185
|
+
}));
|