filterjs-rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +21 -0
- data/README.md +33 -0
- data/Rakefile +1 -0
- data/filterjs-rails.gemspec +22 -0
- data/lib/filterjs-rails.rb +8 -0
- data/lib/filterjs-rails/version.rb +5 -0
- data/vendor/assets/javascripts/filter.js +1727 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5342b3c97143e1cd7e9ab71978670e64cc9b2c6f
|
4
|
+
data.tar.gz: 871398441f3458b4d7d69a41d3cf2482d386bf5f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8d20045420a7bc51002f45da9feaaf69d4cfca9c359c8b1b506efa937611ce2481fe1205f1b9f629e27f28672149552786d0cd79c8feb3eccb50fca5b3729a18
|
7
|
+
data.tar.gz: b8511e2a8891e6df1e046af5f35360b7bff3c29c8e5808581d4c727ac25b12f7c016e616bae322867260b4bcea97417a1d8f208fa788c0924d8a6b44915ae619
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Kazuho Yamaguchi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# Filter.js for Rails
|
2
|
+
|
3
|
+
Integrate [Filter.js](https://github.com/jiren/filter.js) into Rails
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'filterjs-rails'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
```console
|
15
|
+
$ bundle
|
16
|
+
```
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
```console
|
21
|
+
$ gem install filterjs-rails
|
22
|
+
```
|
23
|
+
|
24
|
+
Add this to your application.js file:
|
25
|
+
|
26
|
+
```javascript
|
27
|
+
//= require filter
|
28
|
+
```
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Visit: https://github.com/jiren/filter.js
|
33
|
+
Demo: http://jiren.github.io/filter.js/
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require File.expand_path('../lib/filterjs-rails/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "filterjs-rails"
|
6
|
+
spec.version = Filterjs::Rails::VERSION
|
7
|
+
spec.authors = ["Kazuho Yamaguchi"]
|
8
|
+
spec.email = ["kzh.yap@gmail.com"]
|
9
|
+
|
10
|
+
spec.summary = %q{Filter.js for Rails}
|
11
|
+
spec.description = %q{Filter.js for Ruby on Rails}
|
12
|
+
spec.homepage = "https://github.com/kyamaguchi/filterjs-rails"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "railties", "> 3.1"
|
22
|
+
end
|
@@ -0,0 +1,1727 @@
|
|
1
|
+
/*
|
2
|
+
* filter.js
|
3
|
+
* 2.1.0 (2016-08-09)
|
4
|
+
*
|
5
|
+
* Released under the MIT license
|
6
|
+
* http://opensource.org/licenses/MIT
|
7
|
+
*
|
8
|
+
* Copyright 2011-2016 Jiren Patel[jirenpatel@gmail.com]
|
9
|
+
*
|
10
|
+
* Dependency:
|
11
|
+
* jQuery(v1.9 >=)
|
12
|
+
*/
|
13
|
+
|
14
|
+
/*
|
15
|
+
* JsonQuery
|
16
|
+
* 0.0.2 (2015-08-06)
|
17
|
+
*
|
18
|
+
* Released under the MIT license
|
19
|
+
* http://opensource.org/licenses/MIT
|
20
|
+
*
|
21
|
+
* Copyright 2011-2015 Jiren Patel[jirenpatel@gmail.com]
|
22
|
+
*
|
23
|
+
*/
|
24
|
+
|
25
|
+
(function(window) {
|
26
|
+
|
27
|
+
'use strict';
|
28
|
+
|
29
|
+
var JsonQuery = function(records, opts){
|
30
|
+
return new _JsonQuery(records, opts || {});
|
31
|
+
};
|
32
|
+
|
33
|
+
window.JsonQuery = JsonQuery;
|
34
|
+
|
35
|
+
JsonQuery.VERSION = '0.0.2'
|
36
|
+
|
37
|
+
JsonQuery.Config = {
|
38
|
+
id: 'id',
|
39
|
+
latitude: 'latitude',
|
40
|
+
longitude: 'longitude',
|
41
|
+
date_regx: /^\d{4}-\d{2}-\d{2}$/
|
42
|
+
}
|
43
|
+
|
44
|
+
JsonQuery.blankClone = function(jq, records){
|
45
|
+
return new _JsonQuery(records, {
|
46
|
+
getterFns: jq.getterFns,
|
47
|
+
schema: jq.schema,
|
48
|
+
id: jq.id,
|
49
|
+
latitude: jq.latitude,
|
50
|
+
longitude: jq.longitude
|
51
|
+
})
|
52
|
+
}
|
53
|
+
|
54
|
+
var Config = JsonQuery.Config;
|
55
|
+
|
56
|
+
var each = function(objs, callback, context){
|
57
|
+
if (objs.length === +objs.length) {
|
58
|
+
for (var i = 0, l = objs.length; i < l; i++) {
|
59
|
+
callback.call(context, objs[i], i);
|
60
|
+
}
|
61
|
+
}else{
|
62
|
+
for (var key in objs) {
|
63
|
+
if (hasOwnProperty.call(objs, key)) {
|
64
|
+
callback.call(context, objs[key], key);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
};
|
69
|
+
|
70
|
+
var eachWithBreak = function(objs, callback, context){
|
71
|
+
for (var i = 0, l = objs.length; i < l; i++) {
|
72
|
+
if(callback.call(context, objs[i], i) === false){
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
}
|
76
|
+
};
|
77
|
+
|
78
|
+
|
79
|
+
var _JsonQuery = function(records, opts){
|
80
|
+
this.records = records || [];
|
81
|
+
this.getterFns = opts.getterFns || {};
|
82
|
+
this.lat = opts.latitude || Config.latitude;
|
83
|
+
this.lng = opts.longitude || Config.longitude;
|
84
|
+
this.id = opts.id;
|
85
|
+
|
86
|
+
if(opts.schema){
|
87
|
+
this.schema = opts.schema;
|
88
|
+
}
|
89
|
+
|
90
|
+
if(this.records.length && !this.schema){
|
91
|
+
initSchema(this, records[0], opts.schema);
|
92
|
+
}
|
93
|
+
};
|
94
|
+
|
95
|
+
var JQ = _JsonQuery.prototype;
|
96
|
+
|
97
|
+
var initSchema = function(context, record, hasSchema){
|
98
|
+
context.schema = {};
|
99
|
+
|
100
|
+
if(!context.id){
|
101
|
+
context.id = record._id ? '_id' : Config.id;
|
102
|
+
}
|
103
|
+
|
104
|
+
if(!hasSchema){
|
105
|
+
buildSchema.call(context, record);
|
106
|
+
buildPropGetters.call(context, record);
|
107
|
+
}
|
108
|
+
};
|
109
|
+
|
110
|
+
var getDataType = function(val){
|
111
|
+
if(val == null){
|
112
|
+
return 'String';
|
113
|
+
}
|
114
|
+
|
115
|
+
/*
|
116
|
+
* @info Fix for IE 10 & 11
|
117
|
+
* @bug Invalid calling object
|
118
|
+
*/
|
119
|
+
var type = Object.prototype.toString.call(val).slice(8, -1);
|
120
|
+
|
121
|
+
if(type == 'String' && val.match(Config.date_regx)){
|
122
|
+
return 'Date';
|
123
|
+
}
|
124
|
+
|
125
|
+
return type;
|
126
|
+
};
|
127
|
+
|
128
|
+
var parseValue = function(type, value){
|
129
|
+
if(!value && value != 0){
|
130
|
+
return value;
|
131
|
+
}
|
132
|
+
|
133
|
+
if(type == 'String'){
|
134
|
+
return String(value);
|
135
|
+
}else if(type == 'Number'){
|
136
|
+
return Number(value)
|
137
|
+
}else if(type == 'Boolean'){
|
138
|
+
return (value == 'true' || value == true || value == '1') ? true : false;
|
139
|
+
}else if(type == 'Date'){
|
140
|
+
return new Date(value)
|
141
|
+
}else{
|
142
|
+
return value
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
var buildSchema = function(obj, parentField){
|
147
|
+
var field, dataType, fullPath, fieldValue;
|
148
|
+
|
149
|
+
for(field in obj){
|
150
|
+
fieldValue = obj[field];
|
151
|
+
dataType = getDataType(fieldValue);
|
152
|
+
|
153
|
+
fullPath = parentField ? (parentField + '.' + field) : field;
|
154
|
+
this.schema[fullPath] = dataType;
|
155
|
+
|
156
|
+
if(dataType == 'Object'){
|
157
|
+
buildSchema.call(this, fieldValue, fullPath);
|
158
|
+
}else if(dataType == 'Array'){
|
159
|
+
|
160
|
+
if(['Object', 'Array'].indexOf(getDataType(fieldValue[0])) > -1){
|
161
|
+
buildSchema.call(this, obj[field][0], fullPath);
|
162
|
+
}else{
|
163
|
+
this.schema[fullPath] = getDataType(fieldValue[0]);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
}
|
167
|
+
};
|
168
|
+
|
169
|
+
var parseDate = function(dates){
|
170
|
+
if(dates.constructor.name == 'Array'){
|
171
|
+
return dates.map(function(d){ return (d ? new Date(d) : null ) });
|
172
|
+
}
|
173
|
+
return (dates ? new Date(dates) : null);
|
174
|
+
};
|
175
|
+
|
176
|
+
var buildPropGetters = function(record){
|
177
|
+
var selector, type, val;
|
178
|
+
|
179
|
+
for(selector in this.schema){
|
180
|
+
type = this.schema[selector];
|
181
|
+
|
182
|
+
try{
|
183
|
+
if(!this.getterFns[selector]){
|
184
|
+
this.getterFns[selector] = buildGetPropFn.call(this, selector, type);
|
185
|
+
}
|
186
|
+
|
187
|
+
//Remap if it is array
|
188
|
+
val = this.getterFns[selector](record);
|
189
|
+
if(getDataType(val) == 'Array'){
|
190
|
+
this.schema[selector] = 'Array';
|
191
|
+
}
|
192
|
+
}catch(err){
|
193
|
+
console.log("Error while generating getter function for selector : " + selector + " NOTE: Define manually");
|
194
|
+
}
|
195
|
+
}
|
196
|
+
};
|
197
|
+
|
198
|
+
var countArrHierarchy = function(schema, nestedPath){
|
199
|
+
var lastArr = 0,
|
200
|
+
arrCount = 0,
|
201
|
+
path,
|
202
|
+
pathLength = nestedPath.length - 1;
|
203
|
+
|
204
|
+
for(var i = nestedPath.length - 1; i >= 0; i--){
|
205
|
+
path = nestedPath.slice(0, i + 1).join('.');
|
206
|
+
|
207
|
+
if(schema[path] == 'Array' && i < pathLength){
|
208
|
+
lastArr = i;
|
209
|
+
arrCount = arrCount + 1;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
return (arrCount > 1 ? (lastArr + 1) : -1);
|
213
|
+
};
|
214
|
+
|
215
|
+
var buildGetPropFn = function(field, type){
|
216
|
+
var accessPath = '',
|
217
|
+
nestedPath = field.split('.'),
|
218
|
+
path,
|
219
|
+
lastArr = countArrHierarchy(this.schema, nestedPath),
|
220
|
+
prefix,
|
221
|
+
accessFnBody;
|
222
|
+
|
223
|
+
for(var i = nestedPath.length - 1; i >= 0; i--){
|
224
|
+
path = nestedPath.slice(0, i + 1).join('.');
|
225
|
+
prefix = "['" + nestedPath[i] +"']";
|
226
|
+
|
227
|
+
if(this.schema[path] == 'Array'){
|
228
|
+
if(lastArr == i){
|
229
|
+
accessPath = prefix + (accessPath.length ? ".every(function(r" + i +"){ objs.push(r" + i + accessPath + ")})" : '');
|
230
|
+
}else{
|
231
|
+
accessPath = prefix + (accessPath.length ? ".map(function(r" + i +"){ return r" + i + accessPath + "})" : '');
|
232
|
+
}
|
233
|
+
}else{
|
234
|
+
accessPath = prefix + accessPath;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
if(lastArr > -1){
|
239
|
+
accessFnBody = 'var objs = []; obj' + accessPath + ';' + (this.schema['path'] == 'Date' ? 'return parseDate(objs)' : 'return objs;');
|
240
|
+
}else{
|
241
|
+
accessFnBody = 'return ' + (this.schema['path'] == 'Date' ? 'parseDate(obj'+ accessPath +');' : 'obj'+ accessPath +';') ;
|
242
|
+
}
|
243
|
+
|
244
|
+
return new Function('obj', accessFnBody);
|
245
|
+
};
|
246
|
+
|
247
|
+
JQ.operators = {
|
248
|
+
eq: function(v1, v2){ return v1 == v2},
|
249
|
+
ne: function(v1, v2){ return v1 != v2},
|
250
|
+
lt: function(v1, v2){ return v1 < v2},
|
251
|
+
lte: function(v1, v2){ return v1 <= v2},
|
252
|
+
gt: function(v1, v2){ return v1 > v2},
|
253
|
+
gte: function(v1, v2){ return v1 >= v2},
|
254
|
+
in: function(v1, v2){ return v2.indexOf(v1) > -1},
|
255
|
+
ni: function(v1, v2){ return v2.indexOf(v1) == -1},
|
256
|
+
li: function(v, regx) { return regx.test(v)},
|
257
|
+
bt: function(v1, v2){ return (v1 >= v2[0] && v1 <= v2[1])}
|
258
|
+
};
|
259
|
+
|
260
|
+
JQ.addOperator = function(name, fn){
|
261
|
+
this.operators[name] = fn;
|
262
|
+
};
|
263
|
+
|
264
|
+
// rVal = Record Value
|
265
|
+
// cVal = Condition Value
|
266
|
+
var arrayMatcher = function(rVal, cVal, cFn){
|
267
|
+
var i = 0, l = rVal.length;
|
268
|
+
|
269
|
+
for(i; i < l; i++){
|
270
|
+
if(cFn(rVal[i], cVal)) return true;
|
271
|
+
}
|
272
|
+
};
|
273
|
+
|
274
|
+
JQ.addCondition = function(name, func){
|
275
|
+
this.operators[name] = func;
|
276
|
+
};
|
277
|
+
|
278
|
+
JQ.getCriteria = function(criteria){
|
279
|
+
var fieldCondition = criteria.split('.$');
|
280
|
+
|
281
|
+
return {
|
282
|
+
field: fieldCondition[0],
|
283
|
+
operator: fieldCondition[1] || 'eq'
|
284
|
+
};
|
285
|
+
};
|
286
|
+
|
287
|
+
JQ.setGetterFn = function(field, fn){
|
288
|
+
this.getterFns[field] = fn;
|
289
|
+
};
|
290
|
+
|
291
|
+
JQ.addRecords = function(records){
|
292
|
+
if(!records || !records.length){
|
293
|
+
return false;
|
294
|
+
}
|
295
|
+
|
296
|
+
if(getDataType(records) == 'Array'){
|
297
|
+
this.records = this.records.concat(records);
|
298
|
+
}else{
|
299
|
+
this.records.push(records);
|
300
|
+
}
|
301
|
+
|
302
|
+
if(!this.schema){
|
303
|
+
initSchema(this, records[0]);
|
304
|
+
}
|
305
|
+
|
306
|
+
return true;
|
307
|
+
};
|
308
|
+
|
309
|
+
JQ._findAll = function(records, qField, cVal, cOpt){
|
310
|
+
var result = [],
|
311
|
+
cFn,
|
312
|
+
rVal,
|
313
|
+
qFn = this.getterFns[qField], arrayCFn;
|
314
|
+
|
315
|
+
if(cOpt == 'li' && typeof cVal == 'string'){
|
316
|
+
cVal = new RegExp(cVal);
|
317
|
+
}
|
318
|
+
|
319
|
+
cFn = this.operators[cOpt];
|
320
|
+
|
321
|
+
if(this.schema[qField] == 'Array'){
|
322
|
+
arrayCFn = cFn;
|
323
|
+
cFn = arrayMatcher;
|
324
|
+
}
|
325
|
+
|
326
|
+
each(records, function(v){
|
327
|
+
rVal = qFn(v);
|
328
|
+
|
329
|
+
if(cFn(rVal, cVal, arrayCFn)) {
|
330
|
+
result.push(v);
|
331
|
+
}
|
332
|
+
});
|
333
|
+
|
334
|
+
return result;
|
335
|
+
};
|
336
|
+
|
337
|
+
JQ.find = function(field, value){
|
338
|
+
var result, qFn;
|
339
|
+
|
340
|
+
if(!value){
|
341
|
+
value = field;
|
342
|
+
field = this.id;
|
343
|
+
}
|
344
|
+
|
345
|
+
qFn = this.getterFns[field];
|
346
|
+
|
347
|
+
eachWithBreak(this.records, function(r){
|
348
|
+
if(qFn(r) == value){
|
349
|
+
result = r;
|
350
|
+
return false;
|
351
|
+
}
|
352
|
+
});
|
353
|
+
|
354
|
+
return result;
|
355
|
+
};
|
356
|
+
|
357
|
+
each(['where', 'or', 'groupBy', 'select', 'pluck', 'limit', 'offset', 'order', 'uniq', 'near'], function(c){
|
358
|
+
JQ[c] = function(query){
|
359
|
+
var q = new Query(this, this.records);
|
360
|
+
q[c].apply(q, arguments);
|
361
|
+
return q;
|
362
|
+
};
|
363
|
+
});
|
364
|
+
|
365
|
+
each(['update_all', 'destroy_all'], function(c){
|
366
|
+
JQ[c] = function(query){
|
367
|
+
var q = new Query(this, this.records);
|
368
|
+
return q[c].apply(q, arguments);
|
369
|
+
};
|
370
|
+
});
|
371
|
+
|
372
|
+
each(['count', 'first', 'last', 'all'], function(c){
|
373
|
+
Object.defineProperty(JQ, c, {
|
374
|
+
get: function(){
|
375
|
+
return (new Query(this, this.records))[c];
|
376
|
+
}
|
377
|
+
});
|
378
|
+
});
|
379
|
+
|
380
|
+
var compareObj = function(obj1, obj2, fields){
|
381
|
+
for(var i = 0, l = fields.length; i < l; i++){
|
382
|
+
if(this.getterFns[fields[i]](obj1) !== this.getterFns[fields[i]](obj2)){
|
383
|
+
return false;
|
384
|
+
}
|
385
|
+
}
|
386
|
+
|
387
|
+
return true;
|
388
|
+
};
|
389
|
+
|
390
|
+
var execWhere = function(query, records){
|
391
|
+
var q, criteria, result;
|
392
|
+
|
393
|
+
for(q in query){
|
394
|
+
criteria = this.jQ.getCriteria(q);
|
395
|
+
result = this.jQ._findAll(result || records, criteria.field, query[q], criteria.operator);
|
396
|
+
}
|
397
|
+
|
398
|
+
return result;
|
399
|
+
};
|
400
|
+
|
401
|
+
var execGroupBy = function(field, records){
|
402
|
+
var fn = this.jQ.getterFns[field], v, result = {}, i = 0, l = records.length;
|
403
|
+
|
404
|
+
each(records, function(r){
|
405
|
+
v = fn(r);
|
406
|
+
(result[v] || (result[v] = [])).push(r);
|
407
|
+
});
|
408
|
+
|
409
|
+
return result;
|
410
|
+
};
|
411
|
+
|
412
|
+
var execOrder = function(orders, records){
|
413
|
+
var fn,
|
414
|
+
direction,
|
415
|
+
_records = records.slice(0);
|
416
|
+
|
417
|
+
for(var i = 0, l = orders.length; i < l; i++){
|
418
|
+
fn = this.jQ.getterFns[orders[i].field],
|
419
|
+
direction = orders[i].direction == 'asc' ? 1 : -1;
|
420
|
+
|
421
|
+
_records.sort(function(r1,r2){
|
422
|
+
var a = fn(r1), b = fn(r2);
|
423
|
+
|
424
|
+
return (a < b ? -1 : a > b ? 1 : 0)*direction;
|
425
|
+
})
|
426
|
+
}
|
427
|
+
|
428
|
+
return _records;
|
429
|
+
};
|
430
|
+
|
431
|
+
var execSelect = function(fields, records){
|
432
|
+
var self = this, result = [], getFn;
|
433
|
+
|
434
|
+
each(fields, function(f){
|
435
|
+
getFn = self.jQ.getterFns[f];
|
436
|
+
|
437
|
+
each(records, function(r, i){
|
438
|
+
(result[i] || (result[i] = {}))[f] = getFn(r);
|
439
|
+
});
|
440
|
+
});
|
441
|
+
|
442
|
+
return result;
|
443
|
+
};
|
444
|
+
|
445
|
+
var execPluck = function(field, records){
|
446
|
+
var getFn = this.jQ.getterFns[field], result = [];
|
447
|
+
|
448
|
+
each(records, function(r){
|
449
|
+
result.push(getFn(r));
|
450
|
+
});
|
451
|
+
|
452
|
+
return result;
|
453
|
+
};
|
454
|
+
|
455
|
+
var execUniq = function(fields, records){
|
456
|
+
var result = [], self = this;
|
457
|
+
|
458
|
+
if(getDataType(records[0]) != 'Object'){
|
459
|
+
each(records, function(r){
|
460
|
+
if(result.indexOf(r) == -1){
|
461
|
+
result.push(r);
|
462
|
+
}
|
463
|
+
});
|
464
|
+
|
465
|
+
return result;
|
466
|
+
}
|
467
|
+
|
468
|
+
result.push(records[0]);
|
469
|
+
|
470
|
+
each(records, function(r){
|
471
|
+
var present = false;
|
472
|
+
|
473
|
+
for(var i = 0, l = result.length; i < l; i++){
|
474
|
+
if(compareObj.call(self.jQ, result[i], r, fields)){
|
475
|
+
present = true;
|
476
|
+
}
|
477
|
+
}
|
478
|
+
|
479
|
+
if(!present){
|
480
|
+
result.push(r);
|
481
|
+
}
|
482
|
+
});
|
483
|
+
|
484
|
+
return result;
|
485
|
+
};
|
486
|
+
|
487
|
+
|
488
|
+
|
489
|
+
var Query = function(jQ, records){
|
490
|
+
this.jQ = jQ;
|
491
|
+
this.records = records;
|
492
|
+
this.criteria = {};
|
493
|
+
return this;
|
494
|
+
};
|
495
|
+
|
496
|
+
var Q = Query.prototype;
|
497
|
+
|
498
|
+
Q.each = function(callback, context){
|
499
|
+
each(this.exec() || [], callback, context)
|
500
|
+
};
|
501
|
+
|
502
|
+
Q.exec = Q.toArray = function(callback){
|
503
|
+
var result, c;
|
504
|
+
|
505
|
+
if(this.criteria['all']){
|
506
|
+
result = this.records;
|
507
|
+
}
|
508
|
+
|
509
|
+
if(this.criteria['where']){
|
510
|
+
result = execWhere.call(this, this.criteria['where'], result || this.records);
|
511
|
+
}
|
512
|
+
|
513
|
+
if(this.criteria['or']){
|
514
|
+
result = result.concat(execWhere.call(this, this.criteria['or'], this.records));
|
515
|
+
result = execUniq.call(this, [this.jQ.id], result);
|
516
|
+
}
|
517
|
+
|
518
|
+
if(this.criteria['order']){
|
519
|
+
result = execOrder.call(this, this.criteria['order'], result || this.records);
|
520
|
+
}
|
521
|
+
|
522
|
+
if(this.criteria['near']){
|
523
|
+
result = execNear.call(this, this.criteria['near'], result || this.records);
|
524
|
+
}
|
525
|
+
|
526
|
+
if(this.criteria['uniq']){
|
527
|
+
result = execUniq.call(this, this.criteria['uniq'], result || this.records);
|
528
|
+
}
|
529
|
+
|
530
|
+
if(this.criteria['select']){
|
531
|
+
result = execSelect.call(this, this.criteria['select'], result || this.records);
|
532
|
+
}
|
533
|
+
|
534
|
+
if(this.criteria['pluck']){
|
535
|
+
result = execPluck.call(this, this.criteria['pluck'], result || this.records);
|
536
|
+
}
|
537
|
+
|
538
|
+
if(this.criteria['limit']){
|
539
|
+
result = (result || this.records).slice(this.criteria['offset'] || 0, (this.criteria['offset'] || 0) + this.criteria['limit']);
|
540
|
+
}
|
541
|
+
|
542
|
+
if(this.criteria['group_by']){
|
543
|
+
result = execGroupBy.call(this, this.criteria['group_by'], result || this.records);
|
544
|
+
}
|
545
|
+
|
546
|
+
if(!result){
|
547
|
+
result = this.records;
|
548
|
+
}
|
549
|
+
|
550
|
+
if(callback){
|
551
|
+
each(result, callback);
|
552
|
+
}
|
553
|
+
|
554
|
+
if(this.jQ.onResult){
|
555
|
+
this.jQ.onResult(result, this.criteria);
|
556
|
+
}
|
557
|
+
|
558
|
+
return result;
|
559
|
+
}
|
560
|
+
|
561
|
+
var addToCriteria = function(type, query){
|
562
|
+
var c;
|
563
|
+
|
564
|
+
if(!this.criteria[type]){
|
565
|
+
this.criteria[type] = {};
|
566
|
+
}
|
567
|
+
|
568
|
+
for(c in query){
|
569
|
+
this.criteria[type][c] = query[c];
|
570
|
+
}
|
571
|
+
|
572
|
+
return this;
|
573
|
+
};
|
574
|
+
|
575
|
+
Q.where = function(query){
|
576
|
+
return addToCriteria.call(this, 'where', query);
|
577
|
+
};
|
578
|
+
|
579
|
+
Q.or = function(query){
|
580
|
+
return addToCriteria.call(this, 'or', query);
|
581
|
+
};
|
582
|
+
|
583
|
+
Q.groupBy = function(field){
|
584
|
+
this.criteria['group_by'] = field;
|
585
|
+
return this;
|
586
|
+
};
|
587
|
+
|
588
|
+
Q.select = function(){
|
589
|
+
this.criteria['select'] = arguments;
|
590
|
+
return this;
|
591
|
+
};
|
592
|
+
|
593
|
+
Q.pluck = function(field){
|
594
|
+
this.criteria['pluck'] = field;
|
595
|
+
return this;
|
596
|
+
};
|
597
|
+
|
598
|
+
Q.limit = function(l){
|
599
|
+
this.criteria['limit'] = l;
|
600
|
+
return this;
|
601
|
+
};
|
602
|
+
|
603
|
+
Q.offset = function(o){
|
604
|
+
this.criteria['offset'] = o;
|
605
|
+
return this;
|
606
|
+
};
|
607
|
+
|
608
|
+
Q.order = function(criteria){
|
609
|
+
var field;
|
610
|
+
this.criteria['order'] = this.criteria['order'] || [];
|
611
|
+
|
612
|
+
for(field in criteria){
|
613
|
+
this.criteria['order'].push({field: field, direction: criteria[field].toLowerCase()});
|
614
|
+
}
|
615
|
+
|
616
|
+
return this;
|
617
|
+
};
|
618
|
+
|
619
|
+
Q.uniq = function(){
|
620
|
+
this.criteria['uniq'] = (arguments.length > 0 ? arguments : true);
|
621
|
+
return this;
|
622
|
+
};
|
623
|
+
|
624
|
+
Object.defineProperty(Q, 'count', {
|
625
|
+
get: function(){
|
626
|
+
this.criteria['count'] = true;
|
627
|
+
var r = this.exec();
|
628
|
+
|
629
|
+
if(getDataType(r) == 'Array'){
|
630
|
+
return this.exec().length;
|
631
|
+
}else{
|
632
|
+
return Object.keys(r).length;
|
633
|
+
}
|
634
|
+
}
|
635
|
+
});
|
636
|
+
|
637
|
+
Object.defineProperty(Q, 'all', {
|
638
|
+
get: function(){
|
639
|
+
this.criteria['all'] = true;
|
640
|
+
return this.exec();
|
641
|
+
}
|
642
|
+
});
|
643
|
+
|
644
|
+
Object.defineProperty(Q, 'first', {
|
645
|
+
get: function(){
|
646
|
+
this.criteria['first'] = true;
|
647
|
+
return this.exec()[0];
|
648
|
+
}
|
649
|
+
});
|
650
|
+
|
651
|
+
Object.defineProperty(Q, 'last', {
|
652
|
+
get: function(){
|
653
|
+
this.criteria['last'] = true;
|
654
|
+
var r = this.exec();
|
655
|
+
return r[r.length - 1];
|
656
|
+
}
|
657
|
+
});
|
658
|
+
|
659
|
+
//Geocoding
|
660
|
+
var GEO = {
|
661
|
+
redius: 6371,
|
662
|
+
toRad: function(v){
|
663
|
+
return v * Math.PI / 180;
|
664
|
+
}
|
665
|
+
};
|
666
|
+
|
667
|
+
var calculateDistance = function(lat1, lat2, lng1, lng2){
|
668
|
+
var dLat = GEO.toRad(lat2 - lat1),
|
669
|
+
dLon = GEO.toRad(lng2 - lng1),
|
670
|
+
lat1 = GEO.toRad(lat1),
|
671
|
+
lat2 = GEO.toRad(lat2);
|
672
|
+
|
673
|
+
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
674
|
+
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
|
675
|
+
|
676
|
+
return (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))) * GEO.redius;
|
677
|
+
};
|
678
|
+
|
679
|
+
var execNear = function(opts, records){
|
680
|
+
var result = [],
|
681
|
+
self = this,
|
682
|
+
unit_c = opts.unit == 'mile' ? 0.6214 : 1,
|
683
|
+
latFn = self.jQ.getterFns[self.jQ.lat],
|
684
|
+
lngFn = self.jQ.getterFns[self.jQ.lng];
|
685
|
+
|
686
|
+
each(records, function(r){
|
687
|
+
r._distance = calculateDistance(latFn(r), opts.lat, lngFn(r), opts.lng) * unit_c;
|
688
|
+
|
689
|
+
if(r._distance <= opts.distance){
|
690
|
+
result.push(r);
|
691
|
+
}
|
692
|
+
});
|
693
|
+
|
694
|
+
result.sort(function(a, b){
|
695
|
+
return (a._distance < b._distance ? -1 : a._distance > b._distance ? 1 : 0);
|
696
|
+
})
|
697
|
+
|
698
|
+
return result;
|
699
|
+
};
|
700
|
+
|
701
|
+
Q.near = function(lat, lng, distance, unit){
|
702
|
+
this.criteria['near'] = {lat: lat, lng: lng, distance: distance, unit: (unit || 'km')};
|
703
|
+
return this;
|
704
|
+
};
|
705
|
+
|
706
|
+
//Helpers
|
707
|
+
Q.map = Q.collect = function(fn){
|
708
|
+
var result = [], out;
|
709
|
+
|
710
|
+
this.exec(function(r){
|
711
|
+
if(out = fn(r)){
|
712
|
+
result.push(out);
|
713
|
+
}
|
714
|
+
})
|
715
|
+
return result;
|
716
|
+
};
|
717
|
+
|
718
|
+
Q.sum = function(field){
|
719
|
+
var result = 0,
|
720
|
+
group,
|
721
|
+
getFn = this.jQ.getterFns[field];
|
722
|
+
|
723
|
+
if(this.criteria['group_by']){
|
724
|
+
group = true;
|
725
|
+
result = {};
|
726
|
+
}
|
727
|
+
|
728
|
+
this.exec(function(r, i){
|
729
|
+
if(group){
|
730
|
+
result[i] = 0;
|
731
|
+
|
732
|
+
each(r, function(e){
|
733
|
+
result[i] = result[i] + (getFn(e) || 0);
|
734
|
+
})
|
735
|
+
}else{
|
736
|
+
result = result + (getFn(r) || 0);
|
737
|
+
}
|
738
|
+
});
|
739
|
+
|
740
|
+
return result;
|
741
|
+
};
|
742
|
+
|
743
|
+
Q.toJQ = function(){
|
744
|
+
var q = JsonQuery(this.all, {schema: true});
|
745
|
+
q.schema = this.jQ.schema;
|
746
|
+
q.getterFns = this.jQ.getterFns;
|
747
|
+
|
748
|
+
return q;
|
749
|
+
};
|
750
|
+
|
751
|
+
Q.destroy_all = Q.destroy = function(){
|
752
|
+
var marked_records = this.all;
|
753
|
+
|
754
|
+
each(marked_records, function(r, i){
|
755
|
+
r._destroy_ = true;
|
756
|
+
});
|
757
|
+
|
758
|
+
this.records = this.jQ.records = this.records.filter(function(r){
|
759
|
+
return !r._destroy_;
|
760
|
+
});
|
761
|
+
|
762
|
+
return marked_records;
|
763
|
+
};
|
764
|
+
|
765
|
+
Q.update_all = Q.update = function(attrs){
|
766
|
+
if(!attrs){
|
767
|
+
return false;
|
768
|
+
}
|
769
|
+
|
770
|
+
var updated_count = 0;
|
771
|
+
|
772
|
+
each(this.all, function(r){
|
773
|
+
each(attrs, function(value, key){
|
774
|
+
r[key] = value;
|
775
|
+
});
|
776
|
+
updated_count = updated_count + 1;
|
777
|
+
});
|
778
|
+
|
779
|
+
return updated_count;
|
780
|
+
};
|
781
|
+
|
782
|
+
|
783
|
+
//In IE 8 indexOf method not define.
|
784
|
+
if (!Array.prototype.indexOf) {
|
785
|
+
Array.prototype.indexOf = function(obj, start) {
|
786
|
+
for (var i = (start || 0), j = this.length; i < j; i++) {
|
787
|
+
if (this[i] === obj) { return i; }
|
788
|
+
}
|
789
|
+
return -1;
|
790
|
+
}
|
791
|
+
}
|
792
|
+
|
793
|
+
if(!Object.defineProperty){
|
794
|
+
Object.defineProperty = function(obj, name, opts){
|
795
|
+
obj[name] = opts.get
|
796
|
+
}
|
797
|
+
}
|
798
|
+
|
799
|
+
|
800
|
+
|
801
|
+
|
802
|
+
})(this);
|
803
|
+
|
804
|
+
;(function($, window, document) {
|
805
|
+
|
806
|
+
"use strict";
|
807
|
+
|
808
|
+
|
809
|
+
//View Template
|
810
|
+
// Ref: Underscopre.js
|
811
|
+
//JavaScript micro-templating, similar to John Resig's implementation.
|
812
|
+
var templateSettings = {
|
813
|
+
evaluate : /<%([\s\S]+?)%>/g,
|
814
|
+
interpolate : /<%=([\s\S]+?)%>/g,
|
815
|
+
escape : /<%-([\s\S]+?)%>/g
|
816
|
+
};
|
817
|
+
|
818
|
+
var escapeStr = function(string) {
|
819
|
+
return (''+string).replace(/&/g, '&')
|
820
|
+
.replace(/</g, '<')
|
821
|
+
.replace(/>/g, '>')
|
822
|
+
.replace(/"/g, '"')
|
823
|
+
.replace(/'/g, ''')
|
824
|
+
.replace(/\//g, '/');
|
825
|
+
};
|
826
|
+
|
827
|
+
function templateBuilder(str, data) {
|
828
|
+
var c = templateSettings;
|
829
|
+
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
|
830
|
+
'with(obj||{}){__p.push(\'' +
|
831
|
+
str.replace(/\\/g, '\\\\')
|
832
|
+
.replace(/'/g, "\\'")
|
833
|
+
.replace(c.escape, function(match, code) {
|
834
|
+
return "',escapeStr(" + code.replace(/\\'/g, "'") + "),'";
|
835
|
+
})
|
836
|
+
.replace(c.interpolate, function(match, code) {
|
837
|
+
return "'," + code.replace(/\\'/g, "'") + ",'";
|
838
|
+
})
|
839
|
+
.replace(c.evaluate || null, function(match, code) {
|
840
|
+
return "');" + code.replace(/\\'/g, "'")
|
841
|
+
.replace(/[\r\n\t]/g, ' ') + ";__p.push('";
|
842
|
+
})
|
843
|
+
.replace(/\r/g, '\\r')
|
844
|
+
.replace(/\n/g, '\\n')
|
845
|
+
.replace(/\t/g, '\\t')
|
846
|
+
+ "');}return __p.join('');";
|
847
|
+
|
848
|
+
var func = new Function('obj', tmpl);
|
849
|
+
return data ? func(data) : function(data) { return func(data) };
|
850
|
+
};
|
851
|
+
|
852
|
+
|
853
|
+
function each (objs, callback, context){
|
854
|
+
for (var i = 0, l = objs.length; i < l; i++) {
|
855
|
+
callback.call(context, objs[i], i);
|
856
|
+
}
|
857
|
+
}
|
858
|
+
|
859
|
+
|
860
|
+
var FJS = function(records, container, options) {
|
861
|
+
var self = this;
|
862
|
+
|
863
|
+
this.opts = options || {};
|
864
|
+
this.callbacks = this.opts.callbacks || {};
|
865
|
+
this.$container = $(container);
|
866
|
+
this.view = this.opts.view || renderRecord;
|
867
|
+
this.criterias = [];
|
868
|
+
this._index = 1;
|
869
|
+
this.appendToContainer = this.opts.appendToContainer || appendToContainer;
|
870
|
+
this.has_pagination = !!this.opts.pagination;
|
871
|
+
this.search_text = '';
|
872
|
+
this.anyFilterSelected = false;
|
873
|
+
|
874
|
+
this.setTemplate(this.opts.template);
|
875
|
+
|
876
|
+
$.each(this.opts.criterias || [], function(){
|
877
|
+
self.addCriteria(this);
|
878
|
+
});
|
879
|
+
|
880
|
+
this.Model = JsonQuery();
|
881
|
+
this.Model.getterFns['_fid'] = function(r){ return r['_fid'];};
|
882
|
+
this.addRecords(records, this.opts['filter_on_init'] || false);
|
883
|
+
|
884
|
+
if(this.has_pagination){
|
885
|
+
this.initPagination();
|
886
|
+
}
|
887
|
+
};
|
888
|
+
|
889
|
+
var F = FJS.prototype;
|
890
|
+
|
891
|
+
Object.defineProperty(F, 'records', {
|
892
|
+
get: function(){ return this.Model.records; }
|
893
|
+
});
|
894
|
+
|
895
|
+
Object.defineProperty(F, 'recordsCount', {
|
896
|
+
get: function(){ return this.Model.records.length; }
|
897
|
+
});
|
898
|
+
|
899
|
+
F.templateBuilder = templateBuilder;
|
900
|
+
|
901
|
+
//Callback
|
902
|
+
F.execCallback = function(){
|
903
|
+
var name = arguments[0];
|
904
|
+
|
905
|
+
if(this.callbacks[name]) {
|
906
|
+
this.callbacks[name].apply(this, Array.prototype.slice.call(arguments, 1));
|
907
|
+
}
|
908
|
+
};
|
909
|
+
|
910
|
+
F.addCallback = function(name, fns){
|
911
|
+
if(name && fns){
|
912
|
+
this.callbacks[name] = fns;
|
913
|
+
}
|
914
|
+
};
|
915
|
+
|
916
|
+
//Add Data
|
917
|
+
F.addRecords = function(records, applyFilter){
|
918
|
+
var has_scheme = !!this.Model.schema;
|
919
|
+
|
920
|
+
this.execCallback('beforeAddRecords', records);
|
921
|
+
|
922
|
+
if(this.Model.addRecords(records)){
|
923
|
+
if(!this.has_scheme){
|
924
|
+
this.initSearch(this.opts.search);
|
925
|
+
}
|
926
|
+
|
927
|
+
this.render(records);
|
928
|
+
if(applyFilter !== false){
|
929
|
+
this.filter();
|
930
|
+
}
|
931
|
+
}
|
932
|
+
|
933
|
+
this.execCallback('afterAddRecords', records);
|
934
|
+
};
|
935
|
+
|
936
|
+
F.removeRecords = function(criteria){
|
937
|
+
var ids;
|
938
|
+
|
939
|
+
if($.isPlainObject(criteria)){
|
940
|
+
ids = this.Model.where(criteria).pluck('_fid').all;
|
941
|
+
}else if($.isArray(criteria)){
|
942
|
+
ids = this.Model.where({'id.$in': criteria}).pluck('_fid').all;
|
943
|
+
}
|
944
|
+
|
945
|
+
if(!ids){
|
946
|
+
return false;
|
947
|
+
}
|
948
|
+
|
949
|
+
var records = this.Model.records,
|
950
|
+
removedCount = 0,
|
951
|
+
idsLength = ids.length,
|
952
|
+
fid;
|
953
|
+
|
954
|
+
for(var i = records.length - 1; i > -1; i--){
|
955
|
+
fid = records[i]._fid
|
956
|
+
|
957
|
+
if(ids.indexOf(fid) > -1){
|
958
|
+
records.splice(i, 1);
|
959
|
+
removedCount ++;
|
960
|
+
|
961
|
+
$('#fjs_' + fid).remove();
|
962
|
+
}
|
963
|
+
|
964
|
+
if(removedCount == idsLength){
|
965
|
+
break;
|
966
|
+
}
|
967
|
+
}
|
968
|
+
|
969
|
+
this.execCallback('afterRemove');
|
970
|
+
|
971
|
+
return true;
|
972
|
+
};
|
973
|
+
|
974
|
+
var renderRecord = function(record, index){
|
975
|
+
return this.templateFn(record);
|
976
|
+
};
|
977
|
+
|
978
|
+
F.render = function(records){
|
979
|
+
var self = this,
|
980
|
+
ele,
|
981
|
+
cbName;
|
982
|
+
|
983
|
+
if(!records.length){return; }
|
984
|
+
|
985
|
+
this.execCallback('beforeRender', records);
|
986
|
+
cbName = 'beforeRecordRender';
|
987
|
+
|
988
|
+
$.each(records, function(i){
|
989
|
+
self.execCallback(cbName, this);
|
990
|
+
this._fid = (self._index++);
|
991
|
+
|
992
|
+
if(!self.has_pagination){
|
993
|
+
self.renderItem(this, i);
|
994
|
+
}
|
995
|
+
});
|
996
|
+
};
|
997
|
+
|
998
|
+
F.renderItem = function(record, i){
|
999
|
+
if(!record){
|
1000
|
+
return;
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
var ele = this.view(record, i);
|
1004
|
+
|
1005
|
+
if(typeof ele == 'string'){
|
1006
|
+
ele = $($.trim(ele));
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
ele.attr('id', 'fjs_' + record._fid).addClass('fjs_item');
|
1010
|
+
|
1011
|
+
this.appendToContainer(ele, record);
|
1012
|
+
};
|
1013
|
+
|
1014
|
+
var appendToContainer = function(html_ele, record){
|
1015
|
+
this.$container.append(html_ele);
|
1016
|
+
};
|
1017
|
+
|
1018
|
+
var setDefaultCriteriaOpts = function(criteria){
|
1019
|
+
var ele = criteria.$ele,
|
1020
|
+
eleType = criteria.$ele.attr('type');
|
1021
|
+
|
1022
|
+
if(!criteria.selector){
|
1023
|
+
if (ele.get(0).tagName == 'INPUT'){
|
1024
|
+
criteria.selector = (eleType == 'checkbox' || eleType == 'radio') ? ':checked' : ':input';
|
1025
|
+
}else if (ele.get(0).tagName == 'SELECT'){
|
1026
|
+
criteria.selector = 'select';
|
1027
|
+
}
|
1028
|
+
}
|
1029
|
+
|
1030
|
+
if (!criteria.event){
|
1031
|
+
criteria.event = (eleType == 'checkbox' || eleType == 'radio') ? 'click' : 'change';
|
1032
|
+
}
|
1033
|
+
|
1034
|
+
return criteria;
|
1035
|
+
};
|
1036
|
+
|
1037
|
+
F.addCriteria = function(criterias){
|
1038
|
+
var self = this;
|
1039
|
+
|
1040
|
+
if(!criterias){ return false; }
|
1041
|
+
|
1042
|
+
if($.isArray(criterias)){
|
1043
|
+
$.each(criterias, function(){
|
1044
|
+
addFilterCriteria.call(self, this);
|
1045
|
+
});
|
1046
|
+
}else{
|
1047
|
+
addFilterCriteria.call(self, criterias);
|
1048
|
+
}
|
1049
|
+
|
1050
|
+
return true;
|
1051
|
+
};
|
1052
|
+
|
1053
|
+
// Add Filter criteria
|
1054
|
+
// criteria: { ele: '#name', event: 'check', field: 'name', type: 'range' }
|
1055
|
+
var addFilterCriteria = function(criteria){
|
1056
|
+
if(!criteria || !criteria.field || !criteria.ele){
|
1057
|
+
return false;
|
1058
|
+
}
|
1059
|
+
|
1060
|
+
criteria.$ele = $(criteria.ele);
|
1061
|
+
|
1062
|
+
if(!criteria.$ele.length){
|
1063
|
+
return false;
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
criteria = setDefaultCriteriaOpts(criteria);
|
1067
|
+
this.bindEvent(criteria.ele, criteria.event);
|
1068
|
+
|
1069
|
+
criteria._q = criteria.field + (criteria.type == 'range' ? '.$bt' : '')
|
1070
|
+
criteria.active = true;
|
1071
|
+
|
1072
|
+
this.criterias.push(criteria);
|
1073
|
+
|
1074
|
+
return true;
|
1075
|
+
};
|
1076
|
+
|
1077
|
+
F.removeCriteria = function(field){
|
1078
|
+
var self = this, criteria, index;
|
1079
|
+
|
1080
|
+
$.each(self.criterias, function(i){
|
1081
|
+
if(this.field == field){
|
1082
|
+
index = i;
|
1083
|
+
}
|
1084
|
+
});
|
1085
|
+
|
1086
|
+
if(index != null){
|
1087
|
+
criteria = this.criterias.splice(index, 1)[0];
|
1088
|
+
$('body').off(criteria.event, criteria.ele)
|
1089
|
+
}
|
1090
|
+
};
|
1091
|
+
|
1092
|
+
var changeCriteriaStatus = function(names, active){
|
1093
|
+
var self = this;
|
1094
|
+
|
1095
|
+
if(!names){ return; }
|
1096
|
+
|
1097
|
+
if(!$.isArray(names)){
|
1098
|
+
names = [names]
|
1099
|
+
}
|
1100
|
+
|
1101
|
+
$.each(names, function(){
|
1102
|
+
var name = this;
|
1103
|
+
|
1104
|
+
$.each(self.criterias, function(){
|
1105
|
+
if(this.field == name){
|
1106
|
+
this.active = active;
|
1107
|
+
}
|
1108
|
+
})
|
1109
|
+
});
|
1110
|
+
};
|
1111
|
+
|
1112
|
+
F.deactivateCriteria = function(names){
|
1113
|
+
changeCriteriaStatus.call(self, names, false);
|
1114
|
+
};
|
1115
|
+
|
1116
|
+
F.activateCriteria = function(names){
|
1117
|
+
changeCriteriaStatus.call(this, names, true);
|
1118
|
+
};
|
1119
|
+
|
1120
|
+
F.getSelectedValues = function(criteria, context){
|
1121
|
+
var vals = [];
|
1122
|
+
|
1123
|
+
criteria.$ele.filter(criteria.selector).each(function() {
|
1124
|
+
vals.push($(this).val());
|
1125
|
+
});
|
1126
|
+
|
1127
|
+
if($.isArray(vals[0])){
|
1128
|
+
vals = [].concat.apply([], vals);
|
1129
|
+
}
|
1130
|
+
|
1131
|
+
if(criteria.all && vals.indexOf(criteria.all) > -1){
|
1132
|
+
return;
|
1133
|
+
}
|
1134
|
+
|
1135
|
+
if(criteria.type == 'range'){
|
1136
|
+
vals = vals[0].split(criteria.delimiter || '-');
|
1137
|
+
}
|
1138
|
+
|
1139
|
+
vals = this.parseValues(criteria.field, vals);
|
1140
|
+
|
1141
|
+
return context.execCallback('onFilterSelect', {criteria: criteria, values: vals}) || vals;
|
1142
|
+
};
|
1143
|
+
|
1144
|
+
F.lastResult = function(){
|
1145
|
+
return (this.last_result || this.records);
|
1146
|
+
};
|
1147
|
+
|
1148
|
+
F.filter = function(){
|
1149
|
+
var query = {},
|
1150
|
+
vals, _q,
|
1151
|
+
count = 0,
|
1152
|
+
self = this,
|
1153
|
+
criteria;
|
1154
|
+
|
1155
|
+
$.each(this.criterias, function(){
|
1156
|
+
if(this.active){
|
1157
|
+
vals = self.getSelectedValues(this, self);
|
1158
|
+
|
1159
|
+
if(vals && vals.length){
|
1160
|
+
_q = ($.isArray(vals) && !this.type) ? (this._q + '.$in') : this._q;
|
1161
|
+
query[_q] = vals ;
|
1162
|
+
count = count + 1;
|
1163
|
+
}
|
1164
|
+
}
|
1165
|
+
});
|
1166
|
+
|
1167
|
+
this.anyFilterSelected = count > 0;
|
1168
|
+
criteria = count ? this.Model.where(query) : this.Model;
|
1169
|
+
this.execCallback('shortResult', criteria);
|
1170
|
+
this.last_result = criteria.all;
|
1171
|
+
|
1172
|
+
if(this.searchFilter(this.last_result)){
|
1173
|
+
return query;
|
1174
|
+
}
|
1175
|
+
|
1176
|
+
this.show(this.last_result);
|
1177
|
+
this.renderPagination(this.last_result.length);
|
1178
|
+
this.execCallback('afterFilter', this.last_result, JsonQuery.blankClone(this.Model, this.last_result));
|
1179
|
+
|
1180
|
+
return query;
|
1181
|
+
};
|
1182
|
+
|
1183
|
+
F.show = function(result, type){
|
1184
|
+
var i = 0, l = result.length;
|
1185
|
+
|
1186
|
+
if(this.has_pagination){
|
1187
|
+
|
1188
|
+
i = this.page.perPage *(this.page.currentPage - 1);
|
1189
|
+
l = i + this.page.perPage;
|
1190
|
+
|
1191
|
+
this.$container.html("");
|
1192
|
+
|
1193
|
+
for(i; i < l; i++){
|
1194
|
+
this.renderItem(result[i], i);
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
return;
|
1198
|
+
}
|
1199
|
+
|
1200
|
+
$('.fjs_item').hide();
|
1201
|
+
|
1202
|
+
for(i; i < l; i++){
|
1203
|
+
$('#fjs_' + result[i]._fid).show();
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
};
|
1207
|
+
|
1208
|
+
F.filterTimer = function(timeout){
|
1209
|
+
var self = this;
|
1210
|
+
|
1211
|
+
if (this.filterTimeoutId) {
|
1212
|
+
clearTimeout(this.filterTimeoutId);
|
1213
|
+
}
|
1214
|
+
|
1215
|
+
this.filterTimeoutId = setTimeout(function() {
|
1216
|
+
self.filter();
|
1217
|
+
}, timeout);
|
1218
|
+
};
|
1219
|
+
|
1220
|
+
F.bindEvent = function(ele, eventName){
|
1221
|
+
var self = this;
|
1222
|
+
|
1223
|
+
$(document).on(eventName, ele, function(e){
|
1224
|
+
self.filterTimer(self.opts.timeout || 35);
|
1225
|
+
});
|
1226
|
+
|
1227
|
+
};
|
1228
|
+
|
1229
|
+
F.initSearch = function(opts){
|
1230
|
+
if(!opts || !opts.ele){
|
1231
|
+
return;
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
if(!opts.start_length){
|
1235
|
+
this.opts.search.start_length = 2
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
this.$search_ele = $(this.opts.search.ele);
|
1239
|
+
|
1240
|
+
if(this.$search_ele.length){
|
1241
|
+
this.has_search = true;
|
1242
|
+
this.searchFn = this.buildSearchFn(opts.fields);
|
1243
|
+
this.bindEvent(opts.ele, 'keyup');
|
1244
|
+
}
|
1245
|
+
};
|
1246
|
+
|
1247
|
+
F.buildSearchFn = function(fields){
|
1248
|
+
var self = this, getterFns = [];
|
1249
|
+
|
1250
|
+
if(fields){
|
1251
|
+
$.each(fields, function(){
|
1252
|
+
getterFns.push(self.Model.getterFns[this]);
|
1253
|
+
})
|
1254
|
+
}else{
|
1255
|
+
$.each(self.Model.getterFns, function(i, fn){
|
1256
|
+
getterFns.push(fn);
|
1257
|
+
});
|
1258
|
+
}
|
1259
|
+
|
1260
|
+
return function(text, record){
|
1261
|
+
text = text.toLocaleUpperCase();
|
1262
|
+
|
1263
|
+
for(var i = 0, l = getterFns.length; i < l; i++){
|
1264
|
+
|
1265
|
+
if((getterFns[i](record) + '').toLocaleUpperCase().indexOf(text) > -1){
|
1266
|
+
return true;
|
1267
|
+
}
|
1268
|
+
|
1269
|
+
}
|
1270
|
+
return false;
|
1271
|
+
}
|
1272
|
+
};
|
1273
|
+
|
1274
|
+
F.lastSearchResult = function(){
|
1275
|
+
if (this.search_text.length > this.opts.search.start_length){
|
1276
|
+
return this.search_result;
|
1277
|
+
}else{
|
1278
|
+
return this.lastResult();
|
1279
|
+
}
|
1280
|
+
}
|
1281
|
+
|
1282
|
+
F.searchFilter = function(records) {
|
1283
|
+
if(!this.has_search){
|
1284
|
+
return;
|
1285
|
+
}
|
1286
|
+
|
1287
|
+
var result;
|
1288
|
+
this.search_text = $.trim(this.$search_ele.val());
|
1289
|
+
|
1290
|
+
if (this.search_text.length < this.opts.search.start_length){
|
1291
|
+
return false;
|
1292
|
+
}
|
1293
|
+
|
1294
|
+
result = this.search(this.search_text, records || this.lastResult());
|
1295
|
+
|
1296
|
+
this.search_result = result;
|
1297
|
+
this.show(result);
|
1298
|
+
this.renderPagination(result.length)
|
1299
|
+
this.execCallback('afterFilter', result, JsonQuery.blankClone(this.Model, result));
|
1300
|
+
|
1301
|
+
return true;
|
1302
|
+
};
|
1303
|
+
|
1304
|
+
F.search = function(text, records){
|
1305
|
+
text = text.toLocaleUpperCase();
|
1306
|
+
|
1307
|
+
var result = [];
|
1308
|
+
|
1309
|
+
for(var i = 0, l = records.length; i < l; i++){
|
1310
|
+
if(this.searchFn(text, records[i])){
|
1311
|
+
result.push(records[i]);
|
1312
|
+
}
|
1313
|
+
}
|
1314
|
+
|
1315
|
+
return result;
|
1316
|
+
};
|
1317
|
+
|
1318
|
+
//Streaming
|
1319
|
+
F.setStreaming = function(opts){
|
1320
|
+
if(!opts) {return;}
|
1321
|
+
|
1322
|
+
this.opts.streaming = opts;
|
1323
|
+
|
1324
|
+
if(opts.data_url){
|
1325
|
+
opts.stream_after = (opts.stream_after || 2)*1000;
|
1326
|
+
opts.batch_size = opts.batch_size || false;
|
1327
|
+
this.streamData(opts.stream_after);
|
1328
|
+
}
|
1329
|
+
|
1330
|
+
};
|
1331
|
+
|
1332
|
+
var fetchData = function(){
|
1333
|
+
var self = this,
|
1334
|
+
params = this.opts.params || {},
|
1335
|
+
opts = this.opts.streaming;
|
1336
|
+
|
1337
|
+
params.offset = this.recordsCount;
|
1338
|
+
|
1339
|
+
if (opts.batch_size) {
|
1340
|
+
params.limit = opts.batch_size;
|
1341
|
+
}
|
1342
|
+
|
1343
|
+
if (this.has_search){
|
1344
|
+
params['q'] = $.trim(this.$search_ele.val());
|
1345
|
+
}
|
1346
|
+
|
1347
|
+
$.getJSON(opts.data_url, params).done(function(records){
|
1348
|
+
if (params.limit != null && (!records || !records.length)){
|
1349
|
+
self.stopStreaming();
|
1350
|
+
}else{
|
1351
|
+
self.setStreamInterval();
|
1352
|
+
self.addRecords(records);
|
1353
|
+
}
|
1354
|
+
|
1355
|
+
}).fail(function(e){
|
1356
|
+
self.stopStreaming();
|
1357
|
+
});
|
1358
|
+
};
|
1359
|
+
|
1360
|
+
F.setStreamInterval = function(){
|
1361
|
+
var self = this;
|
1362
|
+
|
1363
|
+
if(self.opts.streaming.stop == true){ return; }
|
1364
|
+
|
1365
|
+
self.streamingTimer = setTimeout(function(){
|
1366
|
+
fetchData.call(self);
|
1367
|
+
}, self.opts.streaming.stream_after);
|
1368
|
+
};
|
1369
|
+
|
1370
|
+
F.stopStreaming = function(){
|
1371
|
+
this.opts.streaming.stop = true;
|
1372
|
+
|
1373
|
+
if (this.streamingTimer){
|
1374
|
+
clearTimeout(this.streamingTimer);
|
1375
|
+
}
|
1376
|
+
};
|
1377
|
+
|
1378
|
+
F.resumeStreaming = function(){
|
1379
|
+
this.opts.streaming.stop = false;
|
1380
|
+
this.streamData(this.opts.streaming.stream_after);
|
1381
|
+
};
|
1382
|
+
|
1383
|
+
F.streamData = function(time){
|
1384
|
+
this.setStreamInterval();
|
1385
|
+
|
1386
|
+
if(!this.opts.streaming.batch_size){
|
1387
|
+
this.stopStreaming();
|
1388
|
+
}
|
1389
|
+
};
|
1390
|
+
|
1391
|
+
F.clear = function(){
|
1392
|
+
if(this.opts.streaming){
|
1393
|
+
this.stopStreaming();
|
1394
|
+
}
|
1395
|
+
|
1396
|
+
$.each(this.criterias, function(){
|
1397
|
+
$(document).off(this.event, this.ele);
|
1398
|
+
})
|
1399
|
+
|
1400
|
+
if(this.opts.search){
|
1401
|
+
$(document).off('keyup', this.opts.search.ele);
|
1402
|
+
}
|
1403
|
+
|
1404
|
+
if (this.filterTimeoutId) {
|
1405
|
+
clearTimeout(this.filterTimeoutId);
|
1406
|
+
}
|
1407
|
+
}
|
1408
|
+
|
1409
|
+
F.initPagination = function(){
|
1410
|
+
var self = this,
|
1411
|
+
opts = this.opts.pagination;
|
1412
|
+
|
1413
|
+
if(!opts.perPage){
|
1414
|
+
opts.perPage = {}
|
1415
|
+
}
|
1416
|
+
|
1417
|
+
if(!opts.perPage.values){
|
1418
|
+
opts.perPage.values = [10, 20, 30];
|
1419
|
+
}
|
1420
|
+
|
1421
|
+
this.page = { currentPage: 1, perPage: opts.perPage.values };
|
1422
|
+
|
1423
|
+
this.paginator = new Paginator(this.lastResult().length, this.opts.pagination, function(currentPage, perPage){
|
1424
|
+
self.page = { currentPage: currentPage, perPage: perPage }
|
1425
|
+
|
1426
|
+
if(self.has_search){
|
1427
|
+
self.show(self.lastSearchResult())
|
1428
|
+
}else{
|
1429
|
+
self.show(self.lastResult())
|
1430
|
+
}
|
1431
|
+
})
|
1432
|
+
|
1433
|
+
this.filter();
|
1434
|
+
};
|
1435
|
+
|
1436
|
+
F.renderPagination = function(totalCount){
|
1437
|
+
if(this.has_pagination){
|
1438
|
+
this.paginator.setRecordCount(totalCount);
|
1439
|
+
}
|
1440
|
+
};
|
1441
|
+
|
1442
|
+
F.parseValues = function(field, values){
|
1443
|
+
var type = this.Model.schema[field];
|
1444
|
+
|
1445
|
+
if(type == 'Number'){
|
1446
|
+
return $.map(values, function(v){ return Number(v) });
|
1447
|
+
}else if(type == 'Boolean'){
|
1448
|
+
return $.map(values, function(v){ return (v == 'true' || v == true) });
|
1449
|
+
}else{
|
1450
|
+
return values;
|
1451
|
+
}
|
1452
|
+
};
|
1453
|
+
|
1454
|
+
F.setTemplate = function(template, rebuild) {
|
1455
|
+
this.templateFn = templateBuilder($(template).html());
|
1456
|
+
if(rebuild === true) {
|
1457
|
+
this.$container.empty();
|
1458
|
+
|
1459
|
+
this.render(this.records);
|
1460
|
+
this.filter();
|
1461
|
+
}
|
1462
|
+
};
|
1463
|
+
|
1464
|
+
|
1465
|
+
|
1466
|
+
var Paginator = function(recordsCount, opts, onPagination) {
|
1467
|
+
var paginationView;
|
1468
|
+
|
1469
|
+
this.recordsCount = recordsCount;;
|
1470
|
+
this.opts = opts;
|
1471
|
+
this.$container = $(this.opts.container);
|
1472
|
+
|
1473
|
+
if(this.opts.paginationView){
|
1474
|
+
paginationView = $(this.opts.paginationView).html();
|
1475
|
+
} else {
|
1476
|
+
paginationView = views.pagination;
|
1477
|
+
}
|
1478
|
+
|
1479
|
+
this.paginationTmpl = templateBuilder(paginationView);
|
1480
|
+
|
1481
|
+
this.currentPage = 1;
|
1482
|
+
this.onPagination = onPagination;
|
1483
|
+
this.initPerPage();
|
1484
|
+
this.render();
|
1485
|
+
this.bindEvents();
|
1486
|
+
};
|
1487
|
+
|
1488
|
+
var P = Paginator.prototype;
|
1489
|
+
|
1490
|
+
P.bindEvents = function(){
|
1491
|
+
var self = this;
|
1492
|
+
|
1493
|
+
$(this.opts.container).on('click', '[data-page]', function(e){
|
1494
|
+
self.setCurrentPage($(this).data('page'));
|
1495
|
+
e.preventDefault();
|
1496
|
+
});
|
1497
|
+
};
|
1498
|
+
|
1499
|
+
P.totalPages = function(){
|
1500
|
+
return Math.ceil(this.recordsCount/this.perPageCount);
|
1501
|
+
};
|
1502
|
+
|
1503
|
+
P.setCurrentPage = function(page){
|
1504
|
+
page = this.toPage(page)
|
1505
|
+
this.prevCurrentPage = this.currentPage;
|
1506
|
+
this.currentPage = page;
|
1507
|
+
this.paginate(page);
|
1508
|
+
};
|
1509
|
+
|
1510
|
+
P.setRecordCount = function(total){
|
1511
|
+
this.recordsCount = total;
|
1512
|
+
this.setCurrentPage(this.currentPage);
|
1513
|
+
}
|
1514
|
+
|
1515
|
+
P.toPage = function(page){
|
1516
|
+
if(page == 'first'){
|
1517
|
+
return 1;
|
1518
|
+
}
|
1519
|
+
|
1520
|
+
if(page == 'last'){
|
1521
|
+
return this.totalPages();
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
if(page == 'next'){
|
1525
|
+
var next_page = this.currentPage + 1;
|
1526
|
+
return (next_page > this.totalPages() ? this.currentPage : next_page);
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
if(page == 'prev'){
|
1530
|
+
var prev_page = this.currentPage - 1;
|
1531
|
+
return (prev_page <= 0 ? this.currentPage : prev_page);
|
1532
|
+
}
|
1533
|
+
|
1534
|
+
return parseInt(page);
|
1535
|
+
};
|
1536
|
+
|
1537
|
+
P.paginate = function(page){
|
1538
|
+
this.render();
|
1539
|
+
this.onPagination(this.currentPage, this.perPageCount);
|
1540
|
+
};
|
1541
|
+
|
1542
|
+
P.render = function(){
|
1543
|
+
var pages = this.getPages();
|
1544
|
+
|
1545
|
+
if(this.currentPage > pages.totalPages){
|
1546
|
+
this.currentPage = pages.totalPages;
|
1547
|
+
}
|
1548
|
+
|
1549
|
+
if(this.currentPage == 0){
|
1550
|
+
this.currentPage = 1;
|
1551
|
+
}
|
1552
|
+
|
1553
|
+
pages.currentPage = this.currentPage;
|
1554
|
+
this.$container.html(this.paginationTmpl(pages))
|
1555
|
+
};
|
1556
|
+
|
1557
|
+
function makePageArray(start, end){
|
1558
|
+
var i = start, pages = [];
|
1559
|
+
|
1560
|
+
for(i; i <= end; i++){
|
1561
|
+
pages.push(i);
|
1562
|
+
}
|
1563
|
+
|
1564
|
+
return pages;
|
1565
|
+
}
|
1566
|
+
|
1567
|
+
P.getPages = function () {
|
1568
|
+
var total = this.totalPages();
|
1569
|
+
|
1570
|
+
if(!this.opts.visiblePages){
|
1571
|
+
return { totalPages: total, pages: makePageArray(0, total), self: this };
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
var half = Math.floor(this.opts.visiblePages / 2);
|
1575
|
+
var start = this.currentPage - half + 1 - this.opts.visiblePages % 2;
|
1576
|
+
var end = this.currentPage + half;
|
1577
|
+
|
1578
|
+
// handle boundary case
|
1579
|
+
if (start <= 0) {
|
1580
|
+
start = 1;
|
1581
|
+
end = this.opts.visiblePages;
|
1582
|
+
}
|
1583
|
+
|
1584
|
+
if (end > total) {
|
1585
|
+
start = total - this.opts.visiblePages;
|
1586
|
+
|
1587
|
+
if(start <= 0){
|
1588
|
+
start = 1;
|
1589
|
+
}
|
1590
|
+
|
1591
|
+
end = total;
|
1592
|
+
}
|
1593
|
+
|
1594
|
+
return { currentPage: this.currentPage, totalPages: total, pages: makePageArray(start, end), self: this };
|
1595
|
+
},
|
1596
|
+
|
1597
|
+
P.initPerPage = function(){
|
1598
|
+
var opts = this.opts.perPage,
|
1599
|
+
template,
|
1600
|
+
html,
|
1601
|
+
ele,
|
1602
|
+
event_type,
|
1603
|
+
self = this;
|
1604
|
+
|
1605
|
+
this.perPageCount = opts.values[0];
|
1606
|
+
|
1607
|
+
template = opts.perPageView ? $(opts.perPageView).html() : views.per_page;
|
1608
|
+
html = templateBuilder(template)({ values: opts.values });
|
1609
|
+
$(opts.container).html(html);
|
1610
|
+
|
1611
|
+
ele = $(opts.container).find('[data-perpage]')
|
1612
|
+
event_type = ele.get(0).tagName == 'SELECT' ? 'change' : 'click';
|
1613
|
+
|
1614
|
+
$(opts.container).on(event_type, '[data-perpage]', function(e){
|
1615
|
+
var value = parseInt($(this).val() || $(this).data('value'));
|
1616
|
+
self.setPerPage(value)
|
1617
|
+
e.preventDefault();
|
1618
|
+
});
|
1619
|
+
};
|
1620
|
+
|
1621
|
+
P.setPerPage = function(value){
|
1622
|
+
this.perPageCount = value;
|
1623
|
+
this.setCurrentPage(this.currentPage);
|
1624
|
+
}
|
1625
|
+
|
1626
|
+
|
1627
|
+
$.fn.filterjs = function(records, options) {
|
1628
|
+
var $this = $(this);
|
1629
|
+
|
1630
|
+
if (!$this.data('fjs')){
|
1631
|
+
$this.data('fjs', FilterJS(records, $this, options));
|
1632
|
+
}
|
1633
|
+
};
|
1634
|
+
|
1635
|
+
|
1636
|
+
|
1637
|
+
|
1638
|
+
var list = [];
|
1639
|
+
var views = [];
|
1640
|
+
var FilterJS = function(records, container, options) {
|
1641
|
+
var fjs = new FJS(records, container, options);
|
1642
|
+
list.push(fjs);
|
1643
|
+
|
1644
|
+
return fjs;
|
1645
|
+
};
|
1646
|
+
|
1647
|
+
FilterJS.list = list;
|
1648
|
+
FilterJS.templateBuilder = templateBuilder;
|
1649
|
+
|
1650
|
+
window.FilterJS = FilterJS;
|
1651
|
+
|
1652
|
+
views['pagination'] = '<nav> <ul class="pagination"> <% if(currentPage > 1) { %> <li> <a href="#" data-page="first" aria-label="First"><span aria-hidden="true">First</span></a> </li> <li><a href="#" data-page="prev" aria-label="Previous"><span aria-hidden="true">← Previous</span></a></li> <% } %> <% for(var i = 0, l = pages.length; i < l; i++ ){ %> <li class="<%= pages[i] == currentPage ? \'active\' : \'\' %>"> <a href="#" data-page="<%= pages[i] %>"><%= pages[i] %></a> </li> <% } %> <% if( currentPage < totalPages ) { %> <li><a href="#" data-page="next" aria-label="Next"><span aria-hidden="true">Next →</span></a></li> <li><a href="#" data-page="last" aria-label="Last"><span aria-hidden="true">Last</span></a></li> <% } %> </ul></nav>';
|
1653
|
+
views['per_page'] = '<select size="1" name="per_page" data-perpage="true" class="per-page"> <% for(var i = 0; i < values.length; i++ ){ %> <option value="<%= values[i] %>"><%= values[i] %></option> <% } %></select>';
|
1654
|
+
|
1655
|
+
/*
|
1656
|
+
* Find html tag and parse options for filter
|
1657
|
+
*/
|
1658
|
+
function getElementWithOptions(name, hasMany){
|
1659
|
+
var attr = "fjs-"+ name;
|
1660
|
+
var $eles = $("[" + attr + "]");
|
1661
|
+
var options = [];
|
1662
|
+
|
1663
|
+
if(!$eles.length){
|
1664
|
+
return;
|
1665
|
+
}
|
1666
|
+
|
1667
|
+
$.each($eles, function(){
|
1668
|
+
var $ele = $(this);
|
1669
|
+
var option = { ele: $ele };
|
1670
|
+
var optionStr = $ele.attr(attr);
|
1671
|
+
|
1672
|
+
options.push(option);
|
1673
|
+
|
1674
|
+
if(!optionStr){
|
1675
|
+
return options;
|
1676
|
+
}
|
1677
|
+
|
1678
|
+
$.each(optionStr.split(','), function(i, opt){
|
1679
|
+
var kv = opt.split("=");
|
1680
|
+
option[kv[0]] = kv[1];
|
1681
|
+
})
|
1682
|
+
})
|
1683
|
+
|
1684
|
+
return hasMany ? options : options[0];
|
1685
|
+
};
|
1686
|
+
|
1687
|
+
FilterJS.auto = function(records, callbacks){
|
1688
|
+
var options = {};
|
1689
|
+
var container = getElementWithOptions("items");
|
1690
|
+
var fjs,
|
1691
|
+
search,
|
1692
|
+
template,
|
1693
|
+
criterias;
|
1694
|
+
|
1695
|
+
if(!container || !container.template){
|
1696
|
+
return;
|
1697
|
+
}
|
1698
|
+
|
1699
|
+
options.template = container.template
|
1700
|
+
search = getElementWithOptions("search");
|
1701
|
+
|
1702
|
+
if(search){
|
1703
|
+
if(search.fields){
|
1704
|
+
search.fields = search.fields.split(',');
|
1705
|
+
}
|
1706
|
+
options.search = search;
|
1707
|
+
}
|
1708
|
+
|
1709
|
+
if(callbacks){
|
1710
|
+
options.callbacks = callbacks;
|
1711
|
+
}
|
1712
|
+
|
1713
|
+
fjs = FilterJS(records, container.ele, options)
|
1714
|
+
|
1715
|
+
criterias = getElementWithOptions("criteria", true);
|
1716
|
+
|
1717
|
+
if(criterias){
|
1718
|
+
fjs.addCriteria(criterias);
|
1719
|
+
}
|
1720
|
+
|
1721
|
+
return fjs
|
1722
|
+
};
|
1723
|
+
|
1724
|
+
|
1725
|
+
|
1726
|
+
|
1727
|
+
})( jQuery, window , document );
|