tableling-rails 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -2
- data/lib/tableling-rails/version.rb +1 -1
- data/spec/dummy/app/assets/javascripts/application.js +6 -1
- data/spec/dummy/app/assets/javascripts/books.js +6 -4
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/log/development.log +5136 -4946
- data/spec/dummy/tmp/cache/assets/BF1/770/sprockets%2F8228a53c539c582499241527570aa216 +0 -0
- data/spec/dummy/tmp/cache/assets/C3F/0C0/sprockets%2F4643701467ac62c314510c8dd021916f +0 -0
- data/spec/dummy/tmp/cache/assets/C53/AD0/sprockets%2F712078516a81502575c831cb0a8e898e +0 -0
- data/spec/dummy/tmp/cache/assets/C59/0F0/sprockets%2F099f4e84a443568245ff0674030f6e05 +0 -0
- data/spec/dummy/tmp/cache/assets/C60/CF0/sprockets%2F32a45292ee67867d8715952f3072ad84 +0 -0
- data/spec/dummy/tmp/cache/assets/C6F/0E0/sprockets%2F82372776487d948ef7666d304d6fb345 +0 -0
- data/spec/dummy/tmp/cache/assets/C80/840/sprockets%2F562c2d168da585f80579347d10790a0a +0 -0
- data/spec/dummy/tmp/cache/assets/C82/F20/sprockets%2F117015d65237e3682f5b21c87d58ab95 +0 -0
- data/spec/dummy/tmp/cache/assets/C86/280/sprockets%2F1345c9947753f018f45371ec5083fa2d +0 -0
- data/spec/dummy/tmp/cache/assets/C91/350/sprockets%2F6864c49a10954375948d9f306db308fb +0 -0
- data/spec/dummy/tmp/cache/assets/C9A/900/sprockets%2Fc1b5b7611d7c10e124512724f29f241d +0 -0
- data/spec/dummy/tmp/cache/assets/CAF/540/sprockets%2F8f42e689b84f0b25c0180046467adf31 +0 -0
- data/spec/dummy/tmp/cache/assets/CB1/9A0/sprockets%2F57805dfa396248a9665cb4a0c85116d0 +0 -0
- data/spec/dummy/tmp/cache/assets/CC1/4E0/sprockets%2F6ef77414c793c84a437244d7d965ba90 +0 -0
- data/spec/dummy/tmp/cache/assets/CC3/B10/sprockets%2F0a2c59284c7a5d99581883a9763b5ad8 +0 -0
- data/spec/dummy/tmp/cache/assets/CC9/940/sprockets%2F8128c279185cf97dba7914278ce838b4 +0 -0
- data/spec/dummy/tmp/cache/assets/CCA/0C0/sprockets%2F6c3e053393afe303432ca73f1b41490b +0 -0
- data/spec/dummy/tmp/cache/assets/CD5/2C0/sprockets%2F166c056119ebdfb8b7104c97b424b423 +0 -0
- data/spec/dummy/tmp/cache/assets/CDB/610/sprockets%2F7adf20860b018477a95cdb8321b49d16 +0 -0
- data/spec/dummy/tmp/cache/assets/CDD/F50/sprockets%2F7353f31f80f1139aade47728a62af336 +0 -0
- data/spec/dummy/tmp/cache/assets/CE9/760/sprockets%2F5ae7fab601683996918936cad21fc244 +0 -0
- data/spec/dummy/tmp/cache/assets/CE9/B90/sprockets%2Fea2eb066933b1d8b5949972c3c79353a +0 -0
- data/spec/dummy/tmp/cache/assets/CF1/AF0/sprockets%2F14dc9633b61024231ebec0c1a4a0259f +0 -0
- data/spec/dummy/tmp/cache/assets/D02/340/sprockets%2Fae58ed66f72137a594b0912bab600e03 +0 -0
- data/spec/dummy/tmp/cache/assets/D0A/AC0/sprockets%2Fc154991d0a7564e15c0fb4a555c5c73d +0 -0
- data/spec/dummy/tmp/cache/assets/D0B/190/sprockets%2F68cb0d1054ca546fc473274c4ac8737c +0 -0
- data/spec/dummy/tmp/cache/assets/D11/530/sprockets%2F13bc8c66140adef2e97648630866aae3 +0 -0
- data/spec/dummy/tmp/cache/assets/D16/AA0/sprockets%2Ff181e659a47e2cf9c257f32d80452bd3 +0 -0
- data/spec/dummy/tmp/cache/assets/D18/840/sprockets%2F50c1885539f61359c48af74fcae1df31 +0 -0
- data/spec/dummy/tmp/cache/assets/D1B/940/sprockets%2F7c4819d1dd9b64a22941d8c7bd1e6954 +0 -0
- data/spec/dummy/tmp/cache/assets/D2B/1F0/sprockets%2F6a4c116e8316d082bb0ffae02e94b107 +0 -0
- data/spec/dummy/tmp/cache/assets/D3C/E20/sprockets%2Ffc6c44ec250bc532c55649e5292b5c1f +0 -0
- data/spec/dummy/tmp/cache/assets/D4B/C30/sprockets%2Fe8aa746e637d69ff0ac1e71e528c5292 +0 -0
- data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/spec/dummy/tmp/cache/assets/D5A/E20/sprockets%2Febf23d670481ba70b341aa2eb6e37b08 +0 -0
- data/spec/dummy/tmp/cache/assets/D5C/1F0/sprockets%2F2d3f2cfd98bf787168fb59f84ab24784 +0 -0
- data/spec/dummy/tmp/cache/assets/D5D/C60/sprockets%2Ffa0336b42d01aa9173d9d4c12fc4e82d +0 -0
- data/spec/dummy/tmp/cache/assets/D65/DD0/sprockets%2Fed4503679ef66f0e597bfc738bc9e698 +0 -0
- data/spec/dummy/tmp/cache/assets/D68/930/sprockets%2F5a15e52e84502f9fceb7ea04020f65fc +0 -0
- data/spec/dummy/tmp/cache/assets/D8C/140/sprockets%2F2afdbb3902a1be5d2f045cfc837903a3 +0 -0
- data/spec/dummy/tmp/cache/assets/D8E/660/sprockets%2F3a3eed926bdf64000ccacb36022f78d4 +0 -0
- data/spec/dummy/tmp/cache/assets/D95/690/sprockets%2Fe4d19a04705ee5d72c7fa64dc2070ddb +0 -0
- data/spec/dummy/tmp/cache/assets/DA4/EC0/sprockets%2F8da2289e16c1d0cac94aa825ee18d99d +0 -0
- data/spec/dummy/tmp/cache/assets/DA6/120/sprockets%2Fc5880aca76ccbb51f9388362e8afc1e6 +0 -0
- data/spec/dummy/tmp/cache/assets/DA7/390/sprockets%2F25e744cd1b6f8f7ce1d52c1e86a8f19a +0 -0
- data/spec/dummy/tmp/cache/assets/DAB/3E0/sprockets%2F63d2fa621beec4fe878f9eb2884426ab +0 -0
- data/spec/dummy/tmp/cache/assets/DAB/660/sprockets%2F9a8c36769afcc7027b4b6ee0c3e77ce5 +0 -0
- data/spec/dummy/tmp/cache/assets/DBF/EB0/sprockets%2F2afcec323c8ba12a2b7c852f23aa589e +0 -0
- data/spec/dummy/tmp/cache/assets/DCE/9F0/sprockets%2F8fa8c08ea8da97c06cd6c32fe3e613b0 +0 -0
- data/spec/dummy/tmp/cache/assets/DCF/E50/sprockets%2Fc39ff2ed4e1fb4269c39d415acf0d90b +0 -0
- data/spec/dummy/tmp/cache/assets/DD8/0A0/sprockets%2Fb2c3097effcd6084ec75e1f745d1d7dd +0 -0
- data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/spec/dummy/tmp/cache/assets/DF0/040/sprockets%2F04bbbe1ee5ca914173cd90cf6e8a4e0b +0 -0
- data/spec/dummy/tmp/cache/assets/DF7/C80/sprockets%2Ff503b3666caf04beb7cfe54cbdb0575e +0 -0
- data/spec/dummy/tmp/cache/assets/DFA/B70/sprockets%2F262fb95d3f7cfc16febb0f0128ac38ce +0 -0
- data/spec/dummy/tmp/cache/assets/E03/260/sprockets%2Fd1fcfea59ff53c32557ffcd93016cb2e +0 -0
- data/spec/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/spec/dummy/tmp/cache/assets/E0A/510/sprockets%2F8efee416ba436e75bea85d4d367faea7 +0 -0
- data/spec/dummy/tmp/cache/assets/E43/810/sprockets%2F79b0ef75ceb26a9c8fca797db3efba96 +0 -0
- data/spec/dummy/tmp/cache/assets/E96/1B0/sprockets%2F6d5fe51f9c1a3d2f898becd0bcddef3e +0 -0
- data/spec/dummy/tmp/cache/assets/ED4/410/sprockets%2F082adbb8e2abd8a21c8b34aebbbfbfad +0 -0
- data/spec/dummy/tmp/pids/server.pid +1 -0
- data/vendor/assets/javascripts/tableling.js +3 -543
- data/vendor/assets/javascripts/tableling/bootstrap.js +230 -0
- data/vendor/assets/javascripts/tableling/core.js +321 -0
- metadata +11 -99
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +0 -78
- data/spec/dummy/tmp/cache/assets/C20/C20/sprockets%2F932e86665765e61017be1015b249d270 +0 -0
- data/spec/dummy/tmp/cache/assets/C98/B70/sprockets%2F64db420a3a172209bf0b734312a4888a +0 -0
- data/spec/dummy/tmp/cache/assets/CC1/B50/sprockets%2F13559b77aaaf524896e427719ef5d354 +0 -0
- data/spec/dummy/tmp/cache/assets/CD4/420/sprockets%2F19b3d492932dc6a59093dfb1aa852101 +0 -0
- data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
- data/spec/dummy/tmp/cache/assets/CD8/520/sprockets%2F89128ce416ae74c4148c5c1f281e111c +0 -0
- data/spec/dummy/tmp/cache/assets/CDA/600/sprockets%2F98ab7e75433ba5d503533fb00b488c80 +0 -0
- data/spec/dummy/tmp/cache/assets/CE1/0F0/sprockets%2F92d30845fe3923e231cfe7e056a654b4 +0 -0
- data/spec/dummy/tmp/cache/assets/CE2/E70/sprockets%2Fd569808c7b411447dec0137e4d1ee707 +0 -0
- data/spec/dummy/tmp/cache/assets/D0A/780/sprockets%2F3d727e58c55c30009bbaf1462e466d4d +0 -0
- data/spec/dummy/tmp/cache/assets/D21/890/sprockets%2F73f9cd97cac4382d565e7b835709a2e3 +0 -0
- data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/spec/dummy/tmp/cache/assets/D3A/720/sprockets%2F0e2516c1cac22716289bfc87d5ea9a26 +0 -0
- data/spec/dummy/tmp/cache/assets/D4B/BF0/sprockets%2Fdf124de0072e308f8e157eae77b85d88 +0 -0
- data/spec/dummy/tmp/cache/assets/D54/910/sprockets%2F787b6a4c2386b5edf98f90508b85cc3d +0 -0
- data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/spec/dummy/tmp/cache/assets/D63/170/sprockets%2Fb5b73c3b0862ee59b701a6819b2aa4cd +0 -0
- data/spec/dummy/tmp/cache/assets/D66/580/sprockets%2Ffe6bb9bb5ef9c54f501650b1365c1b05 +0 -0
- data/spec/dummy/tmp/cache/assets/D6A/F40/sprockets%2F53fdbea64f1803eebb72f426f74110d8 +0 -0
- data/spec/dummy/tmp/cache/assets/D6B/D30/sprockets%2Faeb25572f539ffdbb122e9de1218572a +0 -0
- data/spec/dummy/tmp/cache/assets/D6F/110/sprockets%2F2c8c9177efb7e5be1a7055bb0d44792a +0 -0
- data/spec/dummy/tmp/cache/assets/D76/3F0/sprockets%2Fbb569c97f9cc01af670906b40c6be9e2 +0 -0
- data/spec/dummy/tmp/cache/assets/D81/510/sprockets%2F3e6bd5a2d6d0d88f61f5b616f7d879b5 +0 -0
- data/spec/dummy/tmp/cache/assets/D82/940/sprockets%2F29cd0ae31066baa6f2cb92b5c6305aa2 +0 -0
- data/spec/dummy/tmp/cache/assets/D85/D20/sprockets%2F7f7f398c298ca8a1e812b6c9832bcf6e +0 -0
- data/spec/dummy/tmp/cache/assets/D97/230/sprockets%2F0f46cb65e018de57d2c8b480a0ec5dd3 +0 -0
- data/spec/dummy/tmp/cache/assets/DA1/F00/sprockets%2F7b23e35dd61e9d734a59179e2d2aebea +0 -0
- data/spec/dummy/tmp/cache/assets/DA3/950/sprockets%2F38737f6fa54dbda0dfe3ce4c51710e79 +0 -0
- data/spec/dummy/tmp/cache/assets/DB4/7A0/sprockets%2F900105aaabba7938ce23f1e0aade71e5 +0 -0
- data/spec/dummy/tmp/cache/assets/DB4/F90/sprockets%2Fcf5e68e329cedb58b84f445f2b8e37b5 +0 -0
- data/spec/dummy/tmp/cache/assets/DE2/6D0/sprockets%2Fdcaa7d2b2814413aa75d3ba6ada3c6b5 +0 -0
- data/spec/dummy/tmp/cache/assets/DF0/D60/sprockets%2F5a54a1ecc1db271edfc0727bfcb8d912 +0 -0
- data/spec/dummy/tmp/cache/assets/DFE/E10/sprockets%2F9a19dfdd7eb0bf5262919a0207ecfdbf +0 -0
- data/spec/dummy/tmp/cache/assets/E33/8F0/sprockets%2F4933e07f8ef2da7eb5bee9a6fcac3d41 +0 -0
- data/spec/dummy/tmp/cache/assets/E67/730/sprockets%2Fadd4efdfa7661cc60e8ea63cef1f0f98 +0 -0
- data/vendor/assets/javascripts/tableling.backbone.js +0 -3638
- data/vendor/assets/javascripts/tableling.world.js +0 -14768
@@ -0,0 +1,230 @@
|
|
1
|
+
/*!
|
2
|
+
* Tableling v0.0.4 - Bootstrap
|
3
|
+
* Copyright (c) 2012 Simon Oulevay (Alpha Hydrae)
|
4
|
+
* Distributed under MIT license
|
5
|
+
* https://github.com/AlphaHydrae/tableling
|
6
|
+
*/
|
7
|
+
|
8
|
+
(function(module) {
|
9
|
+
|
10
|
+
var Tableling = module.Tableling;
|
11
|
+
|
12
|
+
Tableling.Bootstrap = Tableling.Modular.extend({
|
13
|
+
|
14
|
+
className: 'tableling',
|
15
|
+
modules : [ 'table', 'pageSize', 'quickSearch', 'info', 'pagination' ],
|
16
|
+
template : _.template('<div class="tableling-headers"><div class="tableling-page-size pull-left" /><div class="tableling-quick-search pull-right" /></div><div class="tableling-table" /><div class="tableling-footers"><div class="tableling-info pull-left" /><div class="tableling-pagination pull-right" /></div>'),
|
17
|
+
|
18
|
+
regions : {
|
19
|
+
tableRegion : '.tableling-table',
|
20
|
+
pageSizeRegion : '.tableling-page-size',
|
21
|
+
quickSearchRegion : '.tableling-quick-search',
|
22
|
+
infoRegion : '.tableling-info',
|
23
|
+
paginationRegion : '.tableling-pagination'
|
24
|
+
}
|
25
|
+
});
|
26
|
+
|
27
|
+
_.extend(Tableling.Bootstrap, {
|
28
|
+
|
29
|
+
TableView : Backbone.Marionette.CompositeView.extend({
|
30
|
+
|
31
|
+
events : {
|
32
|
+
'click thead th' : 'updateSort'
|
33
|
+
},
|
34
|
+
|
35
|
+
initialize : function(options) {
|
36
|
+
// TODO: add auto-sort
|
37
|
+
this.vent = options.vent;
|
38
|
+
this.sort = [];
|
39
|
+
},
|
40
|
+
|
41
|
+
updateSort : function(ev) {
|
42
|
+
|
43
|
+
var el = $(ev.currentTarget);
|
44
|
+
if (!(el.hasClass('sorting') || el.hasClass('sorting-asc') || el.hasClass('sorting-desc'))) {
|
45
|
+
return;
|
46
|
+
}
|
47
|
+
|
48
|
+
var field = this.fieldName(el);
|
49
|
+
|
50
|
+
if (ev.shiftKey || this.sort.length == 1) {
|
51
|
+
|
52
|
+
var existing = _.find(this.sort, function(item) {
|
53
|
+
return item.field == field;
|
54
|
+
});
|
55
|
+
|
56
|
+
if (existing) {
|
57
|
+
existing.direction = existing.direction == 'asc' ? 'desc' : 'asc';
|
58
|
+
el.removeClass('sorting sorting-asc sorting-desc');
|
59
|
+
el.addClass('sorting-' + existing.direction);
|
60
|
+
return this.vent.trigger('tableling:update', this.config());
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
if (!ev.shiftKey) {
|
65
|
+
this.sort.length = 0;
|
66
|
+
this.$el.find('thead th').removeClass('sorting sorting-asc sorting-desc').addClass('sorting');
|
67
|
+
}
|
68
|
+
|
69
|
+
this.sort.push({
|
70
|
+
field: field,
|
71
|
+
direction: 'asc'
|
72
|
+
});
|
73
|
+
|
74
|
+
el.removeClass('sorting sorting-asc sorting-desc').addClass('sorting-asc');
|
75
|
+
|
76
|
+
this.vent.trigger('tableling:update', this.config());
|
77
|
+
},
|
78
|
+
|
79
|
+
config : function() {
|
80
|
+
return {
|
81
|
+
page : 1,
|
82
|
+
sort : this.sortConfig()
|
83
|
+
};
|
84
|
+
},
|
85
|
+
|
86
|
+
sortConfig : function() {
|
87
|
+
if (!this.sort.length) {
|
88
|
+
return null;
|
89
|
+
}
|
90
|
+
return _.map(this.sort, function(item) {
|
91
|
+
return item.field + ' ' + item.direction;
|
92
|
+
});
|
93
|
+
},
|
94
|
+
|
95
|
+
fieldName : function(el) {
|
96
|
+
return el.data('field') || el.text().toLowerCase();
|
97
|
+
}
|
98
|
+
})
|
99
|
+
});
|
100
|
+
|
101
|
+
_.extend(Tableling.Bootstrap, {
|
102
|
+
|
103
|
+
PageSizeView : Tableling.Modular.createFieldModule('pageSize', {
|
104
|
+
// TODO: update current page intelligently
|
105
|
+
template : _.template('<select name="pageSize" class="input-mini"><option>5</option><option>10</option><option>15</option></select> entries per page')
|
106
|
+
})
|
107
|
+
});
|
108
|
+
|
109
|
+
_.extend(Tableling.Bootstrap.prototype, {
|
110
|
+
pageSizeView : Tableling.Bootstrap.PageSizeView
|
111
|
+
});
|
112
|
+
|
113
|
+
_.extend(Tableling.Bootstrap, {
|
114
|
+
|
115
|
+
QuickSearchView : Tableling.Modular.createFieldModule('quickSearch', {
|
116
|
+
template : _.template('<input type="text" name="quickSearch" placeholder="Quick search..." />')
|
117
|
+
})
|
118
|
+
});
|
119
|
+
|
120
|
+
_.extend(Tableling.Bootstrap.prototype, {
|
121
|
+
quickSearchView : Tableling.Bootstrap.QuickSearchView
|
122
|
+
});
|
123
|
+
|
124
|
+
_.extend(Tableling.Bootstrap, {
|
125
|
+
|
126
|
+
InfoView : Tableling.Modular.createModule({
|
127
|
+
|
128
|
+
template : _.template('Showing <span class="first">0</span> to <span class="last">0</span> of <span class="total">0</span> entries'),
|
129
|
+
|
130
|
+
ui : {
|
131
|
+
first: '.first',
|
132
|
+
last: '.last',
|
133
|
+
total: '.total'
|
134
|
+
},
|
135
|
+
|
136
|
+
refresh : function(data) {
|
137
|
+
if (data) {
|
138
|
+
this.ui.first.text(this.firstRecord(data));
|
139
|
+
this.ui.last.text(this.lastRecord(data));
|
140
|
+
this.ui.total.text(data.total);
|
141
|
+
}
|
142
|
+
},
|
143
|
+
|
144
|
+
firstRecord : function(data) {
|
145
|
+
return data.length ? (data.page - 1) * data.pageSize + 1 : 0;
|
146
|
+
},
|
147
|
+
|
148
|
+
lastRecord : function(data) {
|
149
|
+
return data.length ? this.firstRecord(data) + data.length - 1 : 0;
|
150
|
+
}
|
151
|
+
})
|
152
|
+
});
|
153
|
+
|
154
|
+
_.extend(Tableling.Bootstrap.prototype, {
|
155
|
+
infoView : Tableling.Bootstrap.InfoView
|
156
|
+
});
|
157
|
+
|
158
|
+
_.extend(Tableling.Bootstrap, {
|
159
|
+
|
160
|
+
PaginationView : Tableling.Modular.createModule({
|
161
|
+
|
162
|
+
template : _.template('<div class="pagination"><ul><li class="first"><a href="#"><<</a></li><li class="previous"><a href="#"><</a></li><li class="next"><a href="#">></a></li><li class="last"><a href="#">>></a></li></ul></div>'),
|
163
|
+
|
164
|
+
ui : {
|
165
|
+
first : '.first',
|
166
|
+
previous : '.previous',
|
167
|
+
next : '.next',
|
168
|
+
last : '.last'
|
169
|
+
},
|
170
|
+
|
171
|
+
events : {
|
172
|
+
'click .first:not(.disabled)' : 'goToFirstPage',
|
173
|
+
'click .previous:not(.disabled)' : 'goToPreviousPage',
|
174
|
+
'click .next:not(.disabled)' : 'goToNextPage',
|
175
|
+
'click .last:not(.disabled)' : 'goToLastPage'
|
176
|
+
},
|
177
|
+
|
178
|
+
refresh : function(data) {
|
179
|
+
if (!data) {
|
180
|
+
this.ui.first.addClass('disabled');
|
181
|
+
this.ui.previous.addClass('disabled');
|
182
|
+
this.ui.next.addClass('disabled');
|
183
|
+
this.ui.last.addClass('disabled');
|
184
|
+
} else {
|
185
|
+
this.data = data;
|
186
|
+
this.enable(this.ui.first, data.page > 1);
|
187
|
+
this.enable(this.ui.previous, data.page > 1);
|
188
|
+
this.enable(this.ui.next, data.page < this.numberOfPages(data));
|
189
|
+
this.enable(this.ui.last, data.page < this.numberOfPages(data));
|
190
|
+
}
|
191
|
+
},
|
192
|
+
|
193
|
+
enable : function(el, enabled) {
|
194
|
+
el.removeClass('disabled');
|
195
|
+
if (!enabled) {
|
196
|
+
el.addClass('disabled');
|
197
|
+
}
|
198
|
+
},
|
199
|
+
|
200
|
+
numberOfPages : function() {
|
201
|
+
return Math.ceil(this.data.total / this.data.pageSize);
|
202
|
+
},
|
203
|
+
|
204
|
+
goToFirstPage : function() {
|
205
|
+
this.goToPage(1);
|
206
|
+
},
|
207
|
+
|
208
|
+
goToPreviousPage : function() {
|
209
|
+
this.goToPage(this.data.page - 1);
|
210
|
+
},
|
211
|
+
|
212
|
+
goToNextPage : function() {
|
213
|
+
this.goToPage(this.data.page + 1);
|
214
|
+
},
|
215
|
+
|
216
|
+
goToLastPage : function() {
|
217
|
+
this.goToPage(this.numberOfPages());
|
218
|
+
},
|
219
|
+
|
220
|
+
goToPage : function(n) {
|
221
|
+
this.vent.trigger('tableling:update', { page : n });
|
222
|
+
}
|
223
|
+
})
|
224
|
+
});
|
225
|
+
|
226
|
+
_.extend(Tableling.Bootstrap.prototype, {
|
227
|
+
paginationView : Tableling.Bootstrap.PaginationView
|
228
|
+
});
|
229
|
+
|
230
|
+
})(this);
|
@@ -0,0 +1,321 @@
|
|
1
|
+
/*!
|
2
|
+
* Tableling v0.0.4
|
3
|
+
* Copyright (c) 2012 Simon Oulevay (Alpha Hydrae)
|
4
|
+
* Distributed under MIT license
|
5
|
+
* https://github.com/AlphaHydrae/tableling
|
6
|
+
*/
|
7
|
+
|
8
|
+
(function(module) {
|
9
|
+
|
10
|
+
// Tableling
|
11
|
+
// ---------
|
12
|
+
//
|
13
|
+
// A tableling table is a Marionette layout which fetches data
|
14
|
+
// from a Backbone collection. It is controlled with an EventAggregator.
|
15
|
+
module.Tableling = Tableling = Backbone.Marionette.Layout.extend({
|
16
|
+
|
17
|
+
className: 'tableling',
|
18
|
+
|
19
|
+
// Default table options can be overriden by subclasses.
|
20
|
+
tableling : {
|
21
|
+
page : 1,
|
22
|
+
pageSize : 15
|
23
|
+
},
|
24
|
+
|
25
|
+
initialize : function(options) {
|
26
|
+
options = options || {};
|
27
|
+
|
28
|
+
// Table options can also be overriden for each instance by passing
|
29
|
+
// a `tableling` object in the options.
|
30
|
+
this.tableling = _.extend(_.clone(this.tableling), options.tableling || {});
|
31
|
+
|
32
|
+
// We use an event aggregator to manage the layout and its components.
|
33
|
+
// You can use your own by passing a `vent` option.
|
34
|
+
this.vent = options.vent || new Backbone.Marionette.EventAggregator();
|
35
|
+
|
36
|
+
// Components should trigger the `tableling:update` event to update
|
37
|
+
// the table (e.g. change page size, sort) and fetch the new data.
|
38
|
+
this.vent.on('tableling:update', this.update, this);
|
39
|
+
|
40
|
+
this.on('render', this.setup, this);
|
41
|
+
},
|
42
|
+
|
43
|
+
// Called once rendering is complete. By default, it updates the table.
|
44
|
+
setup : function() {
|
45
|
+
this.vent.trigger('tableling:update');
|
46
|
+
},
|
47
|
+
|
48
|
+
// Subclasses must return the Backbone.Collection used to fetch data.
|
49
|
+
getCollection : function() {
|
50
|
+
throw new Error('#getCollection not implemented. It should return the Backbone.Collection instance used to fetch data.');
|
51
|
+
},
|
52
|
+
|
53
|
+
// ### Refreshing the table
|
54
|
+
update : function(config, options) {
|
55
|
+
|
56
|
+
_.each(this.filterConfig(config || {}), _.bind(this.updateValue, this));
|
57
|
+
|
58
|
+
// Set the `refresh` option to false to update the table configuration
|
59
|
+
// without refreshing.
|
60
|
+
if (!options || typeof(options.refresh) == 'undefined' || options.refresh) {
|
61
|
+
this.refresh();
|
62
|
+
}
|
63
|
+
},
|
64
|
+
|
65
|
+
updateValue : function(value, key) {
|
66
|
+
if (value && value.toString().length) {
|
67
|
+
this.tableling[key] = value;
|
68
|
+
} else {
|
69
|
+
// Blank values are deleted to avoid sending them in ajax requests.
|
70
|
+
delete this.tableling[key];
|
71
|
+
}
|
72
|
+
},
|
73
|
+
|
74
|
+
refresh : function() {
|
75
|
+
|
76
|
+
// `tableling:refreshing` is triggered every time new data is being fetched.
|
77
|
+
// The first argument is the request data.
|
78
|
+
var data = this.requestData();
|
79
|
+
this.ventTrigger('tableling:refreshing', data);
|
80
|
+
|
81
|
+
// You can provide a `tableling.request` option to add properties to the
|
82
|
+
// fetch request.
|
83
|
+
//
|
84
|
+
// var MyTable = Tableling.extend({
|
85
|
+
// tableling : {
|
86
|
+
// type : 'POST' // fetch data with POST
|
87
|
+
// }
|
88
|
+
// });
|
89
|
+
this.getCollection().fetch(_.extend(this.tableling.request || {}, {
|
90
|
+
data: data,
|
91
|
+
success: _.bind(this.processResponse, this)
|
92
|
+
}));
|
93
|
+
},
|
94
|
+
|
95
|
+
// ### Response
|
96
|
+
processResponse : function(collection, response) {
|
97
|
+
|
98
|
+
this.tableling.length = collection.length;
|
99
|
+
|
100
|
+
// Tableling expects the response from a fetch to have a `total` property
|
101
|
+
// which is the total number of items (not just in the current page).
|
102
|
+
this.tableling.total = response.total;
|
103
|
+
|
104
|
+
// `tableling:refreshed` is triggered after every refresh. The first argument
|
105
|
+
// is the current table configuration with the following additional meta data:
|
106
|
+
//
|
107
|
+
// * `total` - the total number of items
|
108
|
+
// * `length` - the number of items in the current page
|
109
|
+
this.ventTrigger('tableling:refreshed', this.filterConfig(this.tableling, true));
|
110
|
+
},
|
111
|
+
|
112
|
+
// ### Request
|
113
|
+
// Builds the request data. Subclasses may override this if they need to
|
114
|
+
// send additional data.
|
115
|
+
requestData : function() {
|
116
|
+
return this.filterConfig(this.tableling);
|
117
|
+
},
|
118
|
+
|
119
|
+
// ### Utilities
|
120
|
+
// Whitelists the given configuration to contain only table configuration properties.
|
121
|
+
// Pass `true` as the second argument to include meta data (i.e. total & length).
|
122
|
+
filterConfig : function(config, all) {
|
123
|
+
if (all) {
|
124
|
+
return _.pick(config, 'page', 'pageSize', 'quickSearch', 'sort', 'length', 'total');
|
125
|
+
} else {
|
126
|
+
return _.pick(config, 'page', 'pageSize', 'quickSearch', 'sort');
|
127
|
+
}
|
128
|
+
},
|
129
|
+
|
130
|
+
// Triggers an event in the event aggregator. If `Tableling.debug` is set, it also
|
131
|
+
// logs the event and its arguments.
|
132
|
+
ventTrigger : function() {
|
133
|
+
|
134
|
+
var args = Array.prototype.slice.call(arguments);
|
135
|
+
this.vent.trigger.apply(this.vent, args);
|
136
|
+
|
137
|
+
if (Tableling.debug) {
|
138
|
+
console.log(args.shift() + ' - ' + JSON.stringify(args));
|
139
|
+
}
|
140
|
+
}
|
141
|
+
});
|
142
|
+
|
143
|
+
// Tableling.Collection
|
144
|
+
// --------------------
|
145
|
+
//
|
146
|
+
// Tableling expects fetch responses to have a `total` property in addition
|
147
|
+
// to the model data. You can extend this Backbone.Collection subclass which
|
148
|
+
// expects the following response format:
|
149
|
+
//
|
150
|
+
// {
|
151
|
+
// "total": 12,
|
152
|
+
// "data": [
|
153
|
+
// { /* ... model data ... */ },
|
154
|
+
// { /* ... model data ... */ }
|
155
|
+
// ]
|
156
|
+
// }
|
157
|
+
Tableling.Collection = Backbone.Collection.extend({
|
158
|
+
|
159
|
+
parse : function(response) {
|
160
|
+
return response.data;
|
161
|
+
}
|
162
|
+
});
|
163
|
+
|
164
|
+
// Tableling.Modular
|
165
|
+
// -----------------
|
166
|
+
//
|
167
|
+
// Tableling subclass which splits functionality into *modules*
|
168
|
+
// and handles rendering.
|
169
|
+
Tableling.Modular = Tableling.extend({
|
170
|
+
|
171
|
+
// The list of module names must be specified by subclasses.
|
172
|
+
modules : [],
|
173
|
+
|
174
|
+
// Modules are set up after rendering, before refreshing.
|
175
|
+
setup : function() {
|
176
|
+
|
177
|
+
this.moduleViews = {};
|
178
|
+
_.each(this.modules, _.bind(this.setupModule, this));
|
179
|
+
|
180
|
+
Tableling.prototype.setup.call(this);
|
181
|
+
},
|
182
|
+
|
183
|
+
// ### Modules
|
184
|
+
// Each module is identified by a name, for example `pageSize`.
|
185
|
+
setupModule : function(name) {
|
186
|
+
|
187
|
+
// The layout must have a region named after the module, e.g. `pageSizeRegion`.
|
188
|
+
var region = name + 'Region';
|
189
|
+
|
190
|
+
// It must have a view class, e.g. `pageSizeView`, which will be shown into
|
191
|
+
// the region.
|
192
|
+
var viewClass = this[name + 'View'];
|
193
|
+
|
194
|
+
// When instantiated, the view class will be passed the event
|
195
|
+
// aggregator as the `vent` option. Additional options can be
|
196
|
+
// given named after the view class, e.g. `pageSizeViewOptions`.
|
197
|
+
var options = _.extend(this[name + 'ViewOptions'] || {}, { vent: this.vent });
|
198
|
+
|
199
|
+
var view = new viewClass(options);
|
200
|
+
|
201
|
+
// Module view instances are stored by name in the `moduleViews` property
|
202
|
+
// for future reference.
|
203
|
+
this.moduleViews[name] = view;
|
204
|
+
|
205
|
+
this[region].show(view);
|
206
|
+
return view;
|
207
|
+
},
|
208
|
+
|
209
|
+
// By default, a modular table expects a `table` module which
|
210
|
+
// should have a collection (e.g. a Marionette CompositeView or
|
211
|
+
// CollectionView). If your subclass does not have that, it
|
212
|
+
// should override this method to return the Backbone.Collection
|
213
|
+
// used to fetch table data.
|
214
|
+
getCollection : function() {
|
215
|
+
return this.moduleViews.table.collection;
|
216
|
+
}
|
217
|
+
});
|
218
|
+
|
219
|
+
// ### Example
|
220
|
+
// This is how a `PageSizeView` module might be registered in a subclass:
|
221
|
+
//
|
222
|
+
// var MyTable = Tableling.Modular.extend({
|
223
|
+
//
|
224
|
+
// modules : [ 'pageSize' ],
|
225
|
+
//
|
226
|
+
// pageSizeView : PageSizeView,
|
227
|
+
// pageSizeViewOptions : {
|
228
|
+
// itemView : PageSizeItem
|
229
|
+
// },
|
230
|
+
//
|
231
|
+
// regions : {
|
232
|
+
// pageSizeRegion : '.pageSize'
|
233
|
+
// }
|
234
|
+
// });
|
235
|
+
|
236
|
+
// ### Utilities
|
237
|
+
_.extend(Tableling.Modular, {
|
238
|
+
|
239
|
+
// **createModule** creates an item view that is automatically bound
|
240
|
+
// to the layout's event aggregator.
|
241
|
+
createModule : function(options) {
|
242
|
+
return Backbone.Marionette.ItemView.extend(_.extend({
|
243
|
+
|
244
|
+
initialize : function(options) {
|
245
|
+
this.vent = options.vent;
|
246
|
+
|
247
|
+
// The `refresh` method of the view is called once the view is rendered
|
248
|
+
// and every time the table is refreshed.
|
249
|
+
this.vent.on('tableling:refreshed', this.refresh, this);
|
250
|
+
this.on('render', this.refresh, this);
|
251
|
+
},
|
252
|
+
|
253
|
+
// Call `update` to trigger an update of the table.
|
254
|
+
update : function() {
|
255
|
+
this.vent.trigger('tableling:update', this.config());
|
256
|
+
},
|
257
|
+
|
258
|
+
// Implementations should override this to stay up to date with
|
259
|
+
// the table state. Note that the data parameter will be undefined
|
260
|
+
// on the first refresh when the view is rendered.
|
261
|
+
refresh : function(data) {
|
262
|
+
},
|
263
|
+
|
264
|
+
// New table configuration to be sent on updates. For example,
|
265
|
+
// a page size view might update the `pageSize` property.
|
266
|
+
config : function() {
|
267
|
+
return {};
|
268
|
+
}
|
269
|
+
}, options));
|
270
|
+
},
|
271
|
+
|
272
|
+
// **createFieldModule** creates a basic module with a single form field.
|
273
|
+
// It comes with sensible defaults and only requires a `template` parameter.
|
274
|
+
createFieldModule : function(name, options) {
|
275
|
+
|
276
|
+
var definition = {
|
277
|
+
|
278
|
+
// The name attribute of the form field is expected to be the name of
|
279
|
+
// the module, e.g. `pageSize`.
|
280
|
+
ui : {
|
281
|
+
field : '[name="' + name + '"]'
|
282
|
+
},
|
283
|
+
|
284
|
+
events : {},
|
285
|
+
|
286
|
+
// The table property updated is the one with the same name as the module.
|
287
|
+
config : function() {
|
288
|
+
var config = {};
|
289
|
+
config[name] = this.ui.field.val();
|
290
|
+
return config;
|
291
|
+
}
|
292
|
+
};
|
293
|
+
|
294
|
+
// The `change` even triggers an update.
|
295
|
+
definition.events['change [name="' + name + '"]'] = 'update';
|
296
|
+
|
297
|
+
return Tableling.Modular.createModule(_.extend(definition, options));
|
298
|
+
}
|
299
|
+
|
300
|
+
// This is how a `PageSizeView` module might be implemented:
|
301
|
+
//
|
302
|
+
// var html = '<input type="text" name="pageSize" />';
|
303
|
+
//
|
304
|
+
// var PageSizeView =
|
305
|
+
// Tableling.Modular.createFieldModule('pageSize', {
|
306
|
+
//
|
307
|
+
// template : _.template(html)
|
308
|
+
// });
|
309
|
+
//
|
310
|
+
// When the value of the input field changes, the event aggregator will
|
311
|
+
// receive a `tableling:update` event with the `pageSize` property set
|
312
|
+
// to that value.
|
313
|
+
});
|
314
|
+
|
315
|
+
})(this);
|
316
|
+
|
317
|
+
// Implementations
|
318
|
+
// ---------------
|
319
|
+
//
|
320
|
+
// <a href="tableling-bootstrap.html">tableling-bootstrap</a> provides views styled
|
321
|
+
// with [Twitter Bootstrap](http://twitter.github.com/bootstrap/) classes.
|