mirror of
https://github.com/bodyrep/DemoApp.git
synced 2026-01-25 14:43:00 +00:00
405 lines
13 KiB
JavaScript
405 lines
13 KiB
JavaScript
/*
|
|
* Filter.js
|
|
* version: 1.3.2 (4/11/2012)
|
|
*
|
|
* Licensed under the MIT:
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
*
|
|
* Copyright 2011 Jiren Patel[ joshsoftware.com ]
|
|
*
|
|
* Dependency:
|
|
* jQuery(v1.6 >=)
|
|
*/
|
|
|
|
(function(window) {
|
|
|
|
var _filterJS = function(dataModel, parentNode, view, settings) {
|
|
this.dataModel = dataModel;
|
|
this.view = view;
|
|
this.parentNode = parentNode;
|
|
this.settings = settings || {};
|
|
//this.last_result = null;
|
|
|
|
if (this.dataModel.constructor == Object){
|
|
this.dataModel = [this.dataModel];
|
|
}
|
|
|
|
for (name in this.dataModel[0]) {
|
|
this.settings.root = name;
|
|
}
|
|
|
|
this.render();
|
|
this.buildCategoryMap();
|
|
this.bindEvents();
|
|
|
|
if(this.settings.exec_callbacks_on_init && this.settings.callbacks){
|
|
this.execCallBacks(this.settings.all_objects);
|
|
}
|
|
|
|
if(!this.settings.filter_types){
|
|
this.settings.filter_types = {};
|
|
}
|
|
|
|
if(!this.settings.filter_types['range']){
|
|
this.settings.filter_types['range'] = this.rangeFilter;
|
|
}
|
|
|
|
};
|
|
|
|
var FilterJS = function(dataModel, parentNode, view, settings) {
|
|
return new _filterJS(dataModel, parentNode, view, settings);
|
|
};
|
|
|
|
FilterJS.VERSION = '1.3.2';
|
|
|
|
//Register new html tag
|
|
FilterJS.registerHtmlElement = function(tag_name){
|
|
_filterJS.prototype[tag_name] = function(attrs, content){
|
|
return _filterJS.prototype.content_tag(tag_name, attrs, content);
|
|
};
|
|
};
|
|
|
|
_filterJS.prototype = {
|
|
/**
|
|
* Tag to make html elements.
|
|
* i.e this.content_tag('span', {class: 'logo_text'}, "Logo Text")
|
|
* First argument is tag name
|
|
* Second argument is attributes class,title,id etc.
|
|
* Last argument is array of html elements or text.
|
|
**/
|
|
content_tag: function(tag, attrs, content) {
|
|
var el = document.createElement(tag);
|
|
|
|
if (attrs) $(el).attr(attrs);
|
|
if (content) {
|
|
if (content.constructor == Array) {
|
|
content.forEach(function(c) {
|
|
if (c) $(el).append(c.constructor == String ? c : $(c));
|
|
});
|
|
}
|
|
else {
|
|
$(el).html(content);
|
|
}
|
|
}
|
|
return el;
|
|
},
|
|
|
|
/**
|
|
* Link Tag:
|
|
* i.e. this.link('/test/1' ,{'title': 'title'}, 'link text')
|
|
**/
|
|
link: function(url, attrs, content) {
|
|
attrs = attrs || {};
|
|
attrs['href'] = url;
|
|
return this.content_tag('a', attrs, content)
|
|
},
|
|
|
|
/**
|
|
* Image Tag:
|
|
* i.e. this.image('/test.png', {class: 'image'})
|
|
**/
|
|
image: function(url, attrs) {
|
|
attrs = attrs || {};
|
|
attrs['src'] = url;
|
|
return this.content_tag('img', attrs)
|
|
},
|
|
|
|
//Render Html using JSON data
|
|
render: function(parentNode) {
|
|
var base = this;
|
|
var node = $(this.parentNode);
|
|
|
|
if (!this.parentNode || !this.view) return;
|
|
|
|
this.dataModel.forEach(function(dm) {
|
|
dm = dm[base.settings.root];
|
|
var el = $(base.view(dm));
|
|
el.attr({'id': base.settings.root + '_' + dm.id, 'data-fjs': true});
|
|
node.append(el);
|
|
});
|
|
},
|
|
|
|
//Bind Events to filter html elements
|
|
bindEvents: function() {
|
|
var base = this;
|
|
base.settings.selector.forEach(function(selector, index) {
|
|
$(selector.element).live(selector.events, function(e) {
|
|
base.filter();
|
|
});
|
|
})
|
|
|
|
if(base.settings.search){
|
|
$(base.settings.search.input).live('keyup', function(e){
|
|
//var search_result = base.search(this, base.last_result || base.settings.all_objects);
|
|
//base.hideShow(search_result);
|
|
base.filter();
|
|
});
|
|
}
|
|
},
|
|
|
|
//Unbind fileter events
|
|
unbindEvents: function() {
|
|
var base = this;
|
|
base.settings.selector.forEach(function(selector, index) {
|
|
$(selector.element).die(selector.events);
|
|
})
|
|
},
|
|
|
|
|
|
//Find elements accroding to selection criteria.
|
|
filter: function() {
|
|
var base = this;
|
|
var filter_out = base.settings.all_objects.slice();
|
|
var selected_count = 0;
|
|
var select_none = false; //Zero Selection for any category
|
|
|
|
base.settings.selector.forEach(function(s) {
|
|
var out = $(s.element).filter(s.select).map(function() {
|
|
return $(this).val();
|
|
});
|
|
selected_count += out.length;
|
|
|
|
if (out.length) {
|
|
filter_out = base.grep(filter_out, base.findObjects(s.name, out, s.type));
|
|
}
|
|
else{
|
|
select_none = true;
|
|
}
|
|
|
|
});
|
|
|
|
if(select_none && base.settings.and_filter_on) filter_out = [];
|
|
|
|
//Search
|
|
if(base.settings.search){
|
|
filter_out = base.search(base.settings.search, filter_out);
|
|
}
|
|
base.hideShow(filter_out);
|
|
|
|
//Callbacks
|
|
base.execCallBacks(filter_out);
|
|
|
|
//base.last_result = filter_out;
|
|
},
|
|
|
|
//Compare and collect objects
|
|
findObjects: function(filter_name, categories, filter_type) {
|
|
var base = this;
|
|
var out = [];
|
|
var category_map = base.settings.object_map[filter_name];
|
|
var filter_type_function = base.settings.filter_types[filter_type];
|
|
|
|
$.each(categories, function(index, category_value) {
|
|
var cat;
|
|
|
|
if(filter_type){
|
|
cat = $.map(category_map, function(n,v){
|
|
if(filter_type_function(category_value, v)){
|
|
return category_map[v];
|
|
}
|
|
});
|
|
} else {
|
|
cat = category_map[category_value];
|
|
}
|
|
|
|
if(cat) {
|
|
out = out.concat(cat);
|
|
}
|
|
});
|
|
|
|
return out;
|
|
},
|
|
|
|
rangeFilter: function(category_value, v){
|
|
var range = category_value.split('-');
|
|
if(range.length == 2){
|
|
if (range[0] == 'below') range[0] = -Infinity;
|
|
if (range[1] == 'above') range[1] = Infinity;
|
|
if (Number(v) >= range[0] && Number(v) <= range[1]){
|
|
return true;
|
|
}
|
|
}
|
|
},
|
|
|
|
//Find objects in array
|
|
grep: function(filter_out, value) {
|
|
return jQuery.grep(filter_out,
|
|
function(p, i) {
|
|
return (jQuery.inArray(p, value) != -1);
|
|
});
|
|
},
|
|
|
|
//Make eval expresssion to collect object from the json data.
|
|
makeEvalString: function(field_map, root) {
|
|
var fields = field_map.split('.ARRAY.');
|
|
var eval_out_str = root + '.' + fields[0];
|
|
|
|
for (i = 1; i < fields.length; i++) {
|
|
eval_out_str += ".filter_collect('" + fields[i] + "')";
|
|
}
|
|
|
|
return eval_out_str;
|
|
},
|
|
|
|
//Create map accroding to selection criteria.
|
|
buildObjectMap: function() {
|
|
var base = this;
|
|
var filter_criteria = this.settings.filter_criteria;
|
|
var object_map = {};
|
|
base.settings.selector = [];
|
|
|
|
for (name in filter_criteria) {
|
|
var selector = {};
|
|
|
|
selector.element = filter_criteria[name][0].split(/.EVENT.|.SELECT.|.TYPE./)[0];
|
|
selector.events = (filter_criteria[name][0].match(/.EVENT.(\S*)/) || [])[1];
|
|
selector.select = (filter_criteria[name][0].match(/.SELECT.(\S*)/) || [])[1]
|
|
selector.type = (filter_criteria[name][0].match(/.TYPE.(\S*)/) || [])[1];
|
|
selector.name = name;
|
|
|
|
base.settings.selector.push(selector);
|
|
|
|
filter_criteria[name].push(base.makeEvalString(filter_criteria[name][1], base.settings.root));
|
|
object_map[name] = {};
|
|
}
|
|
|
|
return object_map;
|
|
},
|
|
|
|
buildCategoryMap: function() {
|
|
var filter_criteria = this.settings.filter_criteria;
|
|
var object_map = this.buildObjectMap();
|
|
var settings = this.settings;
|
|
settings.all_objects = [];
|
|
|
|
this.dataModel.forEach(function(dm) {
|
|
settings.all_objects.push(dm[settings.root].id);
|
|
for (name in filter_criteria) {
|
|
var eval_out = eval('dm.' + filter_criteria[name][2]);
|
|
var obj = object_map[name];
|
|
|
|
if (eval_out && eval_out.constructor == Array) {
|
|
eval_out.forEach(function(x) {
|
|
if (obj[x]) {
|
|
obj[x].push(dm[settings.root].id);
|
|
} else {
|
|
obj[x] = [dm[settings.root].id];
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
if (obj[eval_out]) {
|
|
obj[eval_out].push(dm[settings.root].id);
|
|
} else {
|
|
obj[eval_out] = [dm[settings.root].id];
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
settings.object_map = object_map;
|
|
|
|
return object_map;
|
|
},
|
|
|
|
hideShow: function(id_arr) {
|
|
var id_str = "#" + this.settings.root + '_';
|
|
$(this.parentNode + " > *[data-fjs]").hide();
|
|
|
|
id_arr.forEach(function(id) {
|
|
$(id_str + id).show();
|
|
});
|
|
},
|
|
|
|
search: function(search_config, filter_result){
|
|
var val = $.trim($(search_config.input).val());
|
|
|
|
if(!val.length) return filter_result;
|
|
|
|
var base = this;
|
|
var id_str = "#" + base.settings.root + '_';
|
|
|
|
return $.map(filter_result, function(id){
|
|
var $item = $(id_str + id);
|
|
if(search_config.field_selector){
|
|
$item = $item.find(search_config.field_selector)
|
|
}
|
|
|
|
if($item.text().toUpperCase().indexOf(val.toUpperCase()) >= 0){
|
|
return id;
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
execCallBacks: function(result){
|
|
var base = this;
|
|
if(!base.settings.callbacks) return;
|
|
|
|
filtered_objects = [];
|
|
$.each(base.dataModel, function(i, v){
|
|
if(v && result.indexOf(v[base.settings.root].id) != -1){
|
|
filtered_objects.push(v[base.settings.root]);
|
|
}
|
|
});
|
|
|
|
$.each(base.settings.callbacks, function(name, callback){
|
|
callback.call(base, filtered_objects);
|
|
}
|
|
);
|
|
}
|
|
|
|
};
|
|
|
|
window.FilterJS = FilterJS;
|
|
|
|
//Register html tags
|
|
FilterJS.registerHtmlElement('div');
|
|
FilterJS.registerHtmlElement('span');
|
|
FilterJS.registerHtmlElement('li');
|
|
FilterJS.registerHtmlElement('ul');
|
|
FilterJS.registerHtmlElement('p');
|
|
|
|
})(this);
|
|
|
|
/**
|
|
* Recursive method to collect object from json object.
|
|
* i.e. test = [ {"deal": {"id": 1 }}, {"deal": {"id": 2}}]
|
|
* - to collect id from the json data
|
|
* test.filter_collect('deal').filter_collect('id')
|
|
* this will return [1,2]
|
|
*/
|
|
Array.prototype.filter_collect = function(field, out_arr) {
|
|
var out_arr = out_arr || [];
|
|
this.forEach(function(obj) {
|
|
if (obj.constructor == Array) {
|
|
obj.filter_collect(field, out_arr);
|
|
}
|
|
else {
|
|
out_arr.push(obj[field]);
|
|
}
|
|
});
|
|
return out_arr;
|
|
};
|
|
|
|
//In IE forEach mathod not define so added manually if not define.
|
|
if(!Array.prototype.forEach) {
|
|
Array.prototype.forEach = function(action, that) {
|
|
for (var i = 0, n = this.length; i < n; i++)
|
|
if (i in this) action.call(that, this[i], i, this);
|
|
};
|
|
}
|
|
|
|
//In IE indexOf method not define.
|
|
if (!Array.prototype.indexOf) {
|
|
Array.prototype.indexOf = function(obj, start) {
|
|
for (var i = (start || 0), j = this.length; i < j; i++) {
|
|
if (this[i] === obj) { return i; }
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
|