-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathangular-query.js
More file actions
113 lines (103 loc) · 4.19 KB
/
angular-query.js
File metadata and controls
113 lines (103 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
angular.module('query', [])
.directive('query', function () {
return {
restrict: 'EA',
scope: {source: '=query', queryOptions: '=options', results: '='},
transclude: true,
template: "<dig ng-transclude></div>",
controller: ['$scope', function ($scope) {
/*Gets the value of an object's property.
Example: get({name: {first: "John", last: "Doe"}}, "name.first") returns "John"*/
var get = function (object, stringProperty) {
properties = stringProperty.split('.');
value = object;
for (var i = 0; i < properties.length; i++) {
value = value[properties[i]]
}
return value;
}
$scope.queryOptions.$stringify = function () {
return JSON.stringify(this);
}
var filter = function (value, option) {
if (typeof(option) != 'undefined') {
if (typeof(option) == 'string') { //Test for matching
if (!value) value = ""
return (new RegExp(option.toLowerCase())).test(value.toString().toLowerCase());
} else if (typeof(option) == 'number') { //Test for equality
return value == option;
} else if (typeof(option) == 'object') {
if (option.$gt) { //Greater than
return value > option.$gt;
} else if (option.$gte) { //Greater than or equal
return value >= option.$gte;
} else if (option.$lt) { //Less than
return value < option.$lt;
} else if (option.$lte) { //Less than or equal
return value <= option.$lte;
}
}
}
}
var exec = function () {
if (typeof($scope.source) != 'undefined' && $scope.source.constructor === Array &&
$scope.source.length && typeof($scope.queryOptions == 'object')) {
var dataSet = [];
for (var i = 0; i < $scope.source.length; i++) {
dataSet.push($scope.source[i]);
}
if (typeof($scope.queryOptions.$order) != 'undefined' && $scope.queryOptions.$order.by) {
//Apply order to source
orderBy = $scope.queryOptions.$order.by;
reverse = $scope.queryOptions.$order.reverse;
dataSet.sort(function(a, b) {
if(get(a, orderBy) < get(b, orderBy)) {
if (reverse) return 1;
else return -1;
}
if(get(a, orderBy) > get(b, orderBy)) {
if (reverse) return -1;
else return 1
}
return 0;
});
}
//Apply filters
var item, option, value = null;
$scope.results.length = 0;
for (var i = 0; i < dataSet.length; i++) {
item = dataSet[i];
include = true; //Indicates if the item must be included on the items array at the end of the filters
for (var key in $scope.queryOptions) {
if (key != '$order' && key != '$limit' && key != '$stringify') { //Ignore $order, $limit, and $stringify keys
option = get($scope.queryOptions, key);
if (option.constructor == Array) {
if (key == '$or' || key == '$and') { //Disjunction and Conjunction
for (var j = 0; j < option.length; j++) {
keys = Object.keys(option[j]);
value = get(item, keys[0]);
optn = option[j][keys[0]];
include = filter(value, optn);
if (include && key == '$or') break;
if (!include && key == '$and') break;
}
}
} else {
value = get(item, key);
include = filter(value, option);
}
}
if (!include) break;
}
if (include && ($scope.results.length < $scope.queryOptions.$limit || !$scope.queryOptions.$limit))
$scope.results.push(item);
}
}
}
//Watch for $scope.source changes
$scope.$watch('source', exec, true);
//Watch for $scope.queryOptions changes
$scope.$watch('queryOptions.$stringify()', exec);
}]
}
});