-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathangular-ui-tree-filter.js
More file actions
129 lines (117 loc) · 4.58 KB
/
angular-ui-tree-filter.js
File metadata and controls
129 lines (117 loc) · 4.58 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
(function (angular) {
'use strict';
angular.module('ui.tree-filter', [])
/**
* @ngdoc object
* @name ui.tree-filter.provider:uiTreeFilterSettings
*/
.provider('uiTreeFilterSettings', function () {
var uiTreeFilterSettings = this;
this.addresses = ['title'];
this.regexFlags = 'gi';
this.descendantCollection = 'items';
this.$get = function () {
return {
addresses: uiTreeFilterSettings.addresses,
regexFlags: uiTreeFilterSettings.regexFlags,
descendantCollection: uiTreeFilterSettings.descendantCollection,
};
};
})
/**
* @ngdoc function
* @name ui.tree-filter.factory:uiTreeFilter
*/
.filter('uiTreeFilter', ["uiTreeFilterSettings", function (uiTreeFilterSettings) {
/**
* Iterates through given collection if flag is not true and sets a flag to true on first match.
*
* @param {Array} collection
* @param {string} pattern
* @param {string} address
*
* @returns {boolean}
*/
function visit(collection, pattern, address) {
collection = collection || [];
var foundSoFar = false;
collection.forEach(function (collectionItem) {
foundSoFar = foundSoFar || testForField(collectionItem, pattern, address);
});
return foundSoFar;
}
/**
* Resolves object value from dot-delimited address.
*
* @param object
* @param path
* @returns {*}
*/
function resolveAddress(object, path) {
var parts = path.split('.');
if (object === undefined) {
return;
}
return parts.length < 2 ? object[parts[0]] : resolveAddress(object[parts[0]], parts.slice(1).join('.'));
}
/**
* Checks if object or its children matches a pattern on a given field
*
* First it resolves the property address and gets the value.
* If the value is a string it matches it against provided pattern.
* If item matches because its property matches it's children are not checked.
* Otherwise all item descendants are checked as well
*
* @param {Object} item
* @param {string} pattern
* @param {string} address property name or dot-delimited path to property.
*
* @returns {boolean}
*/
function testForField(item, pattern, address) {
var value = resolveAddress(item, address);
var found;
if (typeof value === 'string') {
found = !!value.match(new RegExp(pattern, uiTreeFilterSettings.regexFlags));
} else if (Array.isArray(value)) {
found = searchStringInArray(new RegExp(pattern, uiTreeFilterSettings.regexFlags), value);
} else {
found = false;
}
return found || visit(item[uiTreeFilterSettings.descendantCollection], pattern, address);
}
/**
* Checks if pattern matches any of the strings in an array
*
* @param {string} str
* @param {array} strArray
*
* @returns {boolean}
*/
function searchStringInArray(str, strArray) {
var found = false;
if (strArray) {
strArray.forEach(function (item) {
if (item.match(str)) {
found = true;
}
});
return found;
}
}
/**
* Checks if pattern matches any of addresses
*
* @param {object} item
* @param {string} pattern
*
* @returns {boolean}
*/
return function (item, pattern, addresses) {
addresses = addresses || uiTreeFilterSettings.addresses;
return pattern === undefined || addresses.reduce(function (foundSoFar, fieldName) {
return foundSoFar || testForField(item, pattern, fieldName);
}, false);
};
}]);
})(angular);