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
@@ -5,23 +5,214 @@
|
|
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
|
+
module.exports = factory(require("underscore"),
|
13
|
+
require("backbone"),
|
14
|
+
require("backgrid"),
|
15
|
+
require("backbone-pageable"));
|
16
|
+
}
|
17
|
+
// Browser
|
18
|
+
else {
|
19
|
+
factory(root._, root.Backbone, root.Backgrid);
|
20
|
+
}
|
21
|
+
|
22
|
+
}(this, function (_, Backbone, Backgrid) {
|
10
23
|
|
11
24
|
"use strict";
|
12
25
|
|
26
|
+
/**
|
27
|
+
PageHandle is a class that renders the actual page handles and reacts to
|
28
|
+
click events for pagination.
|
29
|
+
|
30
|
+
This class acts in two modes - control or discrete page handle modes. If
|
31
|
+
one of the `is*` flags is `true`, an instance of this class is under
|
32
|
+
control page handle mode. Setting a `pageIndex` to an instance of this
|
33
|
+
class under control mode has no effect and the correct page index will
|
34
|
+
always be inferred from the `is*` flag. Only one of the `is*` flags should
|
35
|
+
be set to `true` at a time. For example, an instance of this class cannot
|
36
|
+
simultaneously be a rewind control and a fast forward control. A `label`
|
37
|
+
and a `title` template or a string are required to be passed to the
|
38
|
+
constuctor under this mode. If a `title` template is provided, it __MUST__
|
39
|
+
accept a parameter `label`. When the `label` is provided to the `title`
|
40
|
+
template function, its result will be used to render the generated anchor's
|
41
|
+
title attribute.
|
42
|
+
|
43
|
+
If all of the `is*` flags is set to `false`, which is the default, an
|
44
|
+
instance of this class will be in discrete page handle mode. An instance
|
45
|
+
under this mode requires the `pageIndex` to be passed from the constructor
|
46
|
+
as an option and it __MUST__ be a 0-based index of the list of page numbers
|
47
|
+
to render. The constuctor will normalize the base to the same base the
|
48
|
+
underlying PageableCollection collection instance uses. A `label` is not
|
49
|
+
required under this mode, which will default to the equivalent 1-based page
|
50
|
+
index calculated from `pageIndex` and the underlying PageableCollection
|
51
|
+
instance. A provided `label` will still be honored however. The `title`
|
52
|
+
parameter is also not required under this mode, in which case the default
|
53
|
+
`title` template will be used. You are encouraged to provide your own
|
54
|
+
`title` template however if you wish to localize the title strings.
|
55
|
+
|
56
|
+
If this page handle represents the current page, an `active` class will be
|
57
|
+
placed on the root list element.
|
58
|
+
|
59
|
+
If this page handle is at the border of the list of pages, a `disabled`
|
60
|
+
class will be placed on the root list element.
|
61
|
+
|
62
|
+
Only page handles that are neither `active` nor `disabled` will respond to
|
63
|
+
click events and triggers pagination.
|
64
|
+
|
65
|
+
@class Backgrid.Extension.PageHandle
|
66
|
+
*/
|
67
|
+
var PageHandle = Backgrid.Extension.PageHandle = Backbone.View.extend({
|
68
|
+
|
69
|
+
/** @property */
|
70
|
+
tagName: "li",
|
71
|
+
|
72
|
+
/** @property */
|
73
|
+
events: {
|
74
|
+
"click a": "changePage"
|
75
|
+
},
|
76
|
+
|
77
|
+
/**
|
78
|
+
@property {string|function(Object.<string, string>): string} title
|
79
|
+
The title to use for the `title` attribute of the generated page handle
|
80
|
+
anchor elements. It can be a string or an Underscore template function
|
81
|
+
that takes a mandatory `label` parameter.
|
82
|
+
*/
|
83
|
+
title: _.template('Page <%- label %>', null, {variable: null}),
|
84
|
+
|
85
|
+
/**
|
86
|
+
@property {boolean} isRewind Whether this handle represents a rewind
|
87
|
+
control
|
88
|
+
*/
|
89
|
+
isRewind: false,
|
90
|
+
|
91
|
+
/**
|
92
|
+
@property {boolean} isBack Whether this handle represents a back
|
93
|
+
control
|
94
|
+
*/
|
95
|
+
isBack: false,
|
96
|
+
|
97
|
+
/**
|
98
|
+
@property {boolean} isForward Whether this handle represents a forward
|
99
|
+
control
|
100
|
+
*/
|
101
|
+
isForward: false,
|
102
|
+
|
103
|
+
/**
|
104
|
+
@property {boolean} isFastForward Whether this handle represents a fast
|
105
|
+
forward control
|
106
|
+
*/
|
107
|
+
isFastForward: false,
|
108
|
+
|
109
|
+
/**
|
110
|
+
Initializer.
|
111
|
+
|
112
|
+
@param {Object} options
|
113
|
+
@param {Backbone.Collection} options.collection
|
114
|
+
@param {number} pageIndex 0-based index of the page number this handle
|
115
|
+
handles. This parameter will be normalized to the base the underlying
|
116
|
+
PageableCollection uses.
|
117
|
+
@param {string} [options.label] If provided it is used to render the
|
118
|
+
anchor text, otherwise the normalized pageIndex will be used
|
119
|
+
instead. Required if any of the `is*` flags is set to `true`.
|
120
|
+
@param {string} [options.title]
|
121
|
+
@param {boolean} [options.isRewind=false]
|
122
|
+
@param {boolean} [options.isBack=false]
|
123
|
+
@param {boolean} [options.isForward=false]
|
124
|
+
@param {boolean} [options.isFastForward=false]
|
125
|
+
*/
|
126
|
+
initialize: function (options) {
|
127
|
+
var collection = this.collection;
|
128
|
+
var state = collection.state;
|
129
|
+
var currentPage = state.currentPage;
|
130
|
+
var firstPage = state.firstPage;
|
131
|
+
var lastPage = state.lastPage;
|
132
|
+
|
133
|
+
_.extend(this, _.pick(options,
|
134
|
+
["isRewind", "isBack", "isForward", "isFastForward"]));
|
135
|
+
|
136
|
+
var pageIndex;
|
137
|
+
if (this.isRewind) pageIndex = firstPage;
|
138
|
+
else if (this.isBack) pageIndex = Math.max(firstPage, currentPage - 1);
|
139
|
+
else if (this.isForward) pageIndex = Math.min(lastPage, currentPage + 1);
|
140
|
+
else if (this.isFastForward) pageIndex = lastPage;
|
141
|
+
else {
|
142
|
+
pageIndex = +options.pageIndex;
|
143
|
+
pageIndex = (firstPage ? pageIndex + 1 : pageIndex);
|
144
|
+
}
|
145
|
+
this.pageIndex = pageIndex;
|
146
|
+
|
147
|
+
this.label = (options.label || (firstPage ? pageIndex : pageIndex + 1)) + '';
|
148
|
+
var title = options.title || this.title;
|
149
|
+
this.title = _.isFunction(title) ? title({label: this.label}) : title;
|
150
|
+
},
|
151
|
+
|
152
|
+
/**
|
153
|
+
Renders a clickable anchor element under a list item.
|
154
|
+
*/
|
155
|
+
render: function () {
|
156
|
+
this.$el.empty();
|
157
|
+
var anchor = document.createElement("a");
|
158
|
+
anchor.href = '#';
|
159
|
+
if (this.title) anchor.title = this.title;
|
160
|
+
anchor.innerHTML = this.label;
|
161
|
+
this.el.appendChild(anchor);
|
162
|
+
|
163
|
+
var collection = this.collection;
|
164
|
+
var state = collection.state;
|
165
|
+
var currentPage = state.currentPage;
|
166
|
+
var pageIndex = this.pageIndex;
|
167
|
+
|
168
|
+
if (this.isRewind && currentPage == state.firstPage ||
|
169
|
+
this.isBack && !collection.hasPreviousPage() ||
|
170
|
+
this.isForward && !collection.hasNextPage() ||
|
171
|
+
this.isFastForward && (currentPage == state.lastPage || state.totalPages < 1)) {
|
172
|
+
this.$el.addClass("disabled");
|
173
|
+
}
|
174
|
+
else if (!(this.isRewind ||
|
175
|
+
this.isBack ||
|
176
|
+
this.isForward ||
|
177
|
+
this.isFastForward) &&
|
178
|
+
state.currentPage == pageIndex) {
|
179
|
+
this.$el.addClass("active");
|
180
|
+
}
|
181
|
+
|
182
|
+
this.delegateEvents();
|
183
|
+
return this;
|
184
|
+
},
|
185
|
+
|
186
|
+
/**
|
187
|
+
jQuery click event handler. Goes to the page this PageHandle instance
|
188
|
+
represents. No-op if this page handle is currently active or disabled.
|
189
|
+
*/
|
190
|
+
changePage: function (e) {
|
191
|
+
e.preventDefault();
|
192
|
+
var $el = this.$el, col = this.collection;
|
193
|
+
if (!$el.hasClass("active") && !$el.hasClass("disabled")) {
|
194
|
+
if (this.isRewind) col.getFirstPage();
|
195
|
+
else if (this.isBack) col.getPreviousPage();
|
196
|
+
else if (this.isForward) col.getNextPage();
|
197
|
+
else if (this.isFastForward) col.getLastPage();
|
198
|
+
else col.getPage(this.pageIndex, {reset: true});
|
199
|
+
}
|
200
|
+
return this;
|
201
|
+
}
|
202
|
+
|
203
|
+
});
|
204
|
+
|
13
205
|
/**
|
14
206
|
Paginator is a Backgrid extension that renders a series of configurable
|
15
207
|
pagination handles. This extension is best used for splitting a large data
|
16
208
|
set across multiple pages. If the number of pages is larger then a
|
17
209
|
threshold, which is set to 10 by default, the page handles are rendered
|
18
|
-
within a sliding window, plus the
|
19
|
-
|
20
|
-
handles can be turned off.
|
210
|
+
within a sliding window, plus the rewind, back, forward and fast forward
|
211
|
+
control handles. The individual control handles can be turned off.
|
21
212
|
|
22
213
|
@class Backgrid.Extension.Paginator
|
23
214
|
*/
|
24
|
-
Backgrid.Extension.Paginator = Backbone.View.extend({
|
215
|
+
var Paginator = Backgrid.Extension.Paginator = Backbone.View.extend({
|
25
216
|
|
26
217
|
/** @property */
|
27
218
|
className: "backgrid-paginator",
|
@@ -30,97 +221,122 @@
|
|
30
221
|
windowSize: 10,
|
31
222
|
|
32
223
|
/**
|
33
|
-
@property {
|
34
|
-
|
224
|
+
@property {number} slideScale the number used by #slideHowMuch to scale
|
225
|
+
`windowSize` to yield the number of pages to slide. For example, the
|
226
|
+
default windowSize(10) * slideScale(0.5) yields 5, which means the window
|
227
|
+
will slide forward 5 pages as soon as you've reached page 6. The smaller
|
228
|
+
the scale factor the less pages to slide, and vice versa.
|
229
|
+
|
230
|
+
Also See:
|
231
|
+
|
232
|
+
- #slideMaybe
|
233
|
+
- #slideHowMuch
|
35
234
|
*/
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
235
|
+
slideScale: 0.5,
|
236
|
+
|
237
|
+
/**
|
238
|
+
@property {Object.<string, Object.<string, string>>} controls You can
|
239
|
+
disable specific control handles by setting the keys in question to
|
240
|
+
null. The defaults will be merged with your controls object, with your
|
241
|
+
changes taking precedent.
|
242
|
+
*/
|
243
|
+
controls: {
|
244
|
+
rewind: {
|
245
|
+
label: "《",
|
246
|
+
title: "First"
|
247
|
+
},
|
248
|
+
back: {
|
249
|
+
label: "〈",
|
250
|
+
title: "Previous"
|
251
|
+
},
|
252
|
+
forward: {
|
253
|
+
label: "〉",
|
254
|
+
title: "Next"
|
255
|
+
},
|
256
|
+
fastForward: {
|
257
|
+
label: "》",
|
258
|
+
title: "Last"
|
259
|
+
}
|
41
260
|
},
|
42
261
|
|
43
262
|
/** @property */
|
44
|
-
|
263
|
+
renderIndexedPageHandles: true,
|
264
|
+
|
265
|
+
/**
|
266
|
+
@property {Backgrid.Extension.PageHandle} pageHandle. The PageHandle
|
267
|
+
class to use for rendering individual handles
|
268
|
+
*/
|
269
|
+
pageHandle: PageHandle,
|
45
270
|
|
46
271
|
/** @property */
|
47
|
-
|
48
|
-
"click a": "changePage"
|
49
|
-
},
|
272
|
+
goBackFirstOnSort: true,
|
50
273
|
|
51
274
|
/**
|
52
275
|
Initializer.
|
53
276
|
|
54
277
|
@param {Object} options
|
55
278
|
@param {Backbone.Collection} options.collection
|
56
|
-
@param {boolean} [options.
|
279
|
+
@param {boolean} [options.controls]
|
280
|
+
@param {boolean} [options.pageHandle=Backgrid.Extension.PageHandle]
|
281
|
+
@param {boolean} [options.goBackFirstOnSort=true]
|
57
282
|
*/
|
58
283
|
initialize: function (options) {
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
284
|
+
var self = this;
|
285
|
+
self.controls = _.defaults(options.controls || {}, self.controls,
|
286
|
+
Paginator.prototype.controls);
|
287
|
+
|
288
|
+
_.extend(self, _.pick(options || {}, "windowSize", "pageHandle",
|
289
|
+
"slideScale", "goBackFirstOnSort",
|
290
|
+
"renderIndexedPageHandles"));
|
291
|
+
|
292
|
+
var col = self.collection;
|
293
|
+
self.listenTo(col, "add", self.render);
|
294
|
+
self.listenTo(col, "remove", self.render);
|
295
|
+
self.listenTo(col, "reset", self.render);
|
296
|
+
self.listenTo(col, "backgrid:sorted", function () {
|
297
|
+
if (self.goBackFirstOnSort) col.getFirstPage({reset: true});
|
298
|
+
});
|
73
299
|
},
|
74
300
|
|
75
301
|
/**
|
76
|
-
|
77
|
-
|
302
|
+
Decides whether the window should slide. This method should return 1 if
|
303
|
+
sliding should occur and 0 otherwise. The default is sliding should occur
|
304
|
+
if half of the pages in a window has been reached.
|
78
305
|
|
79
|
-
|
80
|
-
*/
|
81
|
-
changePage: function (e) {
|
82
|
-
e.preventDefault();
|
306
|
+
__Note__: All the parameters have been normalized to be 0-based.
|
83
307
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
var collection = this.collection;
|
91
|
-
|
92
|
-
if (ffLabels) {
|
93
|
-
switch (label) {
|
94
|
-
case ffLabels.first:
|
95
|
-
collection.getFirstPage();
|
96
|
-
return;
|
97
|
-
case ffLabels.prev:
|
98
|
-
collection.getPreviousPage();
|
99
|
-
return;
|
100
|
-
case ffLabels.next:
|
101
|
-
collection.getNextPage();
|
102
|
-
return;
|
103
|
-
case ffLabels.last:
|
104
|
-
collection.getLastPage();
|
105
|
-
return;
|
106
|
-
}
|
107
|
-
}
|
308
|
+
@param {number} firstPage
|
309
|
+
@param {number} lastPage
|
310
|
+
@param {number} currentPage
|
311
|
+
@param {number} windowSize
|
312
|
+
@param {number} slideScale
|
108
313
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
314
|
+
@return {0|1}
|
315
|
+
*/
|
316
|
+
slideMaybe: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
|
317
|
+
return Math.round(currentPage % windowSize / windowSize);
|
113
318
|
},
|
114
319
|
|
115
320
|
/**
|
116
|
-
|
117
|
-
|
321
|
+
Decides how many pages to slide when sliding should occur. The default
|
322
|
+
simply scales the `windowSize` to arrive at a fraction of the `windowSize`
|
323
|
+
to increment.
|
118
324
|
|
119
|
-
|
325
|
+
__Note__: All the parameters have been normalized to be 0-based.
|
326
|
+
|
327
|
+
@param {number} firstPage
|
328
|
+
@param {number} lastPage
|
329
|
+
@param {number} currentPage
|
330
|
+
@param {number} windowSize
|
331
|
+
@param {number} slideScale
|
332
|
+
|
333
|
+
@return {number}
|
120
334
|
*/
|
121
|
-
|
335
|
+
slideThisMuch: function (firstPage, lastPage, currentPage, windowSize, slideScale) {
|
336
|
+
return ~~(windowSize * slideScale);
|
337
|
+
},
|
122
338
|
|
123
|
-
|
339
|
+
_calculateWindow: function () {
|
124
340
|
var collection = this.collection;
|
125
341
|
var state = collection.state;
|
126
342
|
|
@@ -130,51 +346,55 @@
|
|
130
346
|
lastPage = Math.max(0, firstPage ? lastPage - 1 : lastPage);
|
131
347
|
var currentPage = Math.max(state.currentPage, state.firstPage);
|
132
348
|
currentPage = firstPage ? currentPage - 1 : currentPage;
|
133
|
-
var
|
134
|
-
var
|
135
|
-
|
136
|
-
if (
|
137
|
-
|
138
|
-
|
139
|
-
label: i + 1,
|
140
|
-
title: "No. " + (i + 1),
|
141
|
-
className: currentPage === i ? "active" : undefined
|
142
|
-
});
|
143
|
-
}
|
349
|
+
var windowSize = this.windowSize;
|
350
|
+
var slideScale = this.slideScale;
|
351
|
+
var windowStart = Math.floor(currentPage / windowSize) * windowSize;
|
352
|
+
if (currentPage <= lastPage - this.slideThisMuch()) {
|
353
|
+
windowStart += (this.slideMaybe(firstPage, lastPage, currentPage, windowSize, slideScale) *
|
354
|
+
this.slideThisMuch(firstPage, lastPage, currentPage, windowSize, slideScale));
|
144
355
|
}
|
356
|
+
var windowEnd = Math.min(lastPage + 1, windowStart + windowSize);
|
357
|
+
return [windowStart, windowEnd];
|
358
|
+
},
|
145
359
|
|
146
|
-
|
147
|
-
|
360
|
+
/**
|
361
|
+
Creates a list of page handle objects for rendering.
|
148
362
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
className: collection.hasPrevious() ? void 0 : "disabled"
|
153
|
-
});
|
154
|
-
}
|
363
|
+
@return {Array.<Object>} an array of page handle objects hashes
|
364
|
+
*/
|
365
|
+
makeHandles: function () {
|
155
366
|
|
156
|
-
|
157
|
-
|
158
|
-
label: ffLabels.first,
|
159
|
-
className: collection.hasPrevious() ? void 0 : "disabled"
|
160
|
-
});
|
161
|
-
}
|
367
|
+
var handles = [];
|
368
|
+
var collection = this.collection;
|
162
369
|
|
163
|
-
|
164
|
-
|
165
|
-
label: ffLabels.next,
|
166
|
-
className: collection.hasNext() ? void 0 : "disabled"
|
167
|
-
});
|
168
|
-
}
|
370
|
+
var window = this._calculateWindow();
|
371
|
+
var winStart = window[0], winEnd = window[1];
|
169
372
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
373
|
+
if (this.renderIndexedPageHandles) {
|
374
|
+
for (var i = winStart; i < winEnd; i++) {
|
375
|
+
handles.push(new this.pageHandle({
|
376
|
+
collection: collection,
|
377
|
+
pageIndex: i
|
378
|
+
}));
|
175
379
|
}
|
176
380
|
}
|
177
381
|
|
382
|
+
var controls = this.controls;
|
383
|
+
_.each(["back", "rewind", "forward", "fastForward"], function (key) {
|
384
|
+
var value = controls[key];
|
385
|
+
if (value) {
|
386
|
+
var handleCtorOpts = {
|
387
|
+
collection: collection,
|
388
|
+
title: value.title,
|
389
|
+
label: value.label
|
390
|
+
};
|
391
|
+
handleCtorOpts["is" + key.slice(0, 1).toUpperCase() + key.slice(1)] = true;
|
392
|
+
var handle = new this.pageHandle(handleCtorOpts);
|
393
|
+
if (key == "rewind" || key == "back") handles.unshift(handle);
|
394
|
+
else handles.push(handle);
|
395
|
+
}
|
396
|
+
}, this);
|
397
|
+
|
178
398
|
return handles;
|
179
399
|
},
|
180
400
|
|
@@ -184,15 +404,24 @@
|
|
184
404
|
render: function () {
|
185
405
|
this.$el.empty();
|
186
406
|
|
187
|
-
|
188
|
-
|
189
|
-
|
407
|
+
if (this.handles) {
|
408
|
+
for (var i = 0, l = this.handles.length; i < l; i++) {
|
409
|
+
this.handles[i].remove();
|
410
|
+
}
|
411
|
+
}
|
190
412
|
|
191
|
-
this.
|
413
|
+
var handles = this.handles = this.makeHandles();
|
414
|
+
|
415
|
+
var ul = document.createElement("ul");
|
416
|
+
for (var i = 0; i < handles.length; i++) {
|
417
|
+
ul.appendChild(handles[i].render().el);
|
418
|
+
}
|
419
|
+
|
420
|
+
this.el.appendChild(ul);
|
192
421
|
|
193
422
|
return this;
|
194
423
|
}
|
195
424
|
|
196
425
|
});
|
197
426
|
|
198
|
-
}
|
427
|
+
}));
|