var ngSearchProvider = function ($scope, grid, $filter) {
var self = this,
searchConditions = [];
self.extFilter = grid.config.filterOptions.useExternalFilter;
$scope.showFilter = grid.config.showFilter;
$scope.filterText = '';
self.fieldMap = {};
self.evalFilter = function () {
var filterFunc = function(item) {
for (var x = 0, len = searchConditions.length; x < len; x++) {
var condition = searchConditions[x];
//Search entire row
var result;
if (!condition.column) {
for (var prop in item) {
if (item.hasOwnProperty(prop)) {
var c = self.fieldMap[prop];
if (!c)
continue;
var f = null,
s = null;
if (c && c.cellFilter) {
s = c.cellFilter.split(':');
f = $filter(s[0]);
}
var pVal = item[prop];
if (pVal != null) {
if (typeof f == 'function') {
var filterRes = f(typeof pVal === 'object' ? evalObject(pVal, c.field) : pVal, s[1]).toString();
result = condition.regex.test(filterRes);
} else {
result = condition.regex.test(typeof pVal === 'object' ? evalObject(pVal, c.field).toString() : pVal.toString());
}
if (pVal && result) {
return true;
}
}
}
}
return false;
}
//Search by column.
var col = self.fieldMap[condition.columnDisplay];
if (!col) {
return false;
}
var sp = col.cellFilter.split(':');
var filter = col.cellFilter ? $filter(sp[0]) : null;
var value = item[condition.column] || item[col.field.split('.')[0]];
if (value == null)
return false;
if (typeof filter == 'function') {
var filterResults = filter(typeof value === 'object' ? evalObject(value, col.field) : value, sp[1]).toString();
result = condition.regex.test(filterResults);
} else {
result = condition.regex.test(typeof value === 'object' ? evalObject(value, col.field).toString() : value.toString());
}
if (!value || !result) {
return false;
}
}
return true;
};
if (searchConditions.length === 0) {
grid.filteredRows = grid.rowCache;
} else {
grid.filteredRows = grid.rowCache.filter(function(row) {
return filterFunc(row.entity);
});
}
for (var i = 0; i < grid.filteredRows.length; i++)
{
grid.filteredRows[i].rowIndex = i;
}
grid.rowFactory.filteredRowsChanged();
};
//Traversing through the object to find the value that we want. If fail, then return the original object.
var evalObject = function (obj, columnName) {
if (typeof obj != 'object' || typeof columnName != 'string')
return obj;
var args = columnName.split('.');
var cObj = obj;
if (args.length > 1) {
for (var i = 1, len = args.length; i < len; i++) {
cObj = cObj[args[i]];
if (!cObj)
return obj;
}
return cObj;
}
return obj;
};
var getRegExp = function (str, modifiers) {
try {
return new RegExp(str, modifiers);
} catch (err) {
//Escape all RegExp metacharacters.
return new RegExp(str.replace(/(\^|\$|\(|\)|\<|\>|\[|\]|\{|\}|\\|\||\.|\*|\+|\?)/g, '\\$1'));
}
};
var buildSearchConditions = function (a) {
//reset.
searchConditions = [];
var qStr;
if (!(qStr = $.trim(a))) {
return;
}
var columnFilters = qStr.split(";");
for (var i = 0; i < columnFilters.length; i++) {
var args = columnFilters[i].split(':');
if (args.length > 1) {
var columnName = $.trim(args[0]);
var columnValue = $.trim(args[1]);
if (columnName && columnValue) {
searchConditions.push({
column: columnName,
columnDisplay: columnName.replace(/\s+/g, '').toLowerCase(),
regex: getRegExp(columnValue, 'i')
});
}
} else {
var val = $.trim(args[0]);
if (val) {
searchConditions.push({
column: '',
regex: getRegExp(val, 'i')
});
}
}
};
};
$scope.$watch(function() {
return grid.config.filterOptions.filterText;
}, function(a){
$scope.filterText = a;
});
$scope.$watch('filterText', function(a){
if(!self.extFilter){
$scope.$emit('ngGridEventFilter', a);
buildSearchConditions(a);
self.evalFilter();
}
});
if (!self.extFilter) {
$scope.$watch('columns', function (cs) {
for (var i = 0; i < cs.length; i++) {
var col = cs[i];
if(col.field)
self.fieldMap[col.field.split('.')[0]] = col;
if(col.displayName)
self.fieldMap[col.displayName.toLowerCase().replace(/\s+/g, '')] = col;
};
});
}
};