1
|
/**
|
2
|
* Angucomplete
|
3
|
* Autocomplete directive for AngularJS
|
4
|
* By Daryl Rowland
|
5
|
*/
|
6
|
|
7
|
angular.module('angucomplete', [] )
|
8
|
.directive('angucomplete', function ($parse, $http, $sce, $timeout) {
|
9
|
return {
|
10
|
restrict: 'EA',
|
11
|
scope: {
|
12
|
"id": "@id",
|
13
|
"placeholder": "@placeholder",
|
14
|
"selectedObject": "=selectedobject",
|
15
|
"url": "@url",
|
16
|
"dataField": "@datafield",
|
17
|
"titleField": "@titlefield",
|
18
|
"descriptionField": "@descriptionfield",
|
19
|
"imageField": "@imagefield",
|
20
|
"imageUri": "@imageuri",
|
21
|
"inputClass": "@inputclass",
|
22
|
"userPause": "@pause",
|
23
|
"localData": "=localdata",
|
24
|
"searchFields": "@searchfields",
|
25
|
"minLengthUser": "@minlength",
|
26
|
"matchClass": "@matchclass"
|
27
|
},
|
28
|
template: '<div class="angucomplete-holder"><input id="{{id}}_value" ng-model="searchStr" type="text" placeholder="{{placeholder}}" class="{{inputClass}}" onmouseup="this.select();" ng-focus="resetHideResults()" ng-blur="hideResults()" /><div id="{{id}}_dropdown" class="angucomplete-dropdown" ng-if="showDropdown"><div class="angucomplete-searching" ng-show="searching">Searching...</div><div class="angucomplete-searching" ng-show="!searching && (!results || results.length == 0)">No results found</div><div class="angucomplete-row" ng-repeat="result in results" ng-mousedown="selectResult(result)" ng-mouseover="hoverRow()" ng-class="{\'angucomplete-selected-row\': $index == currentIndex}"><div ng-if="imageField" class="angucomplete-image-holder"><img ng-if="result.image && result.image != \'\'" ng-src="{{result.image}}" class="angucomplete-image"/><div ng-if="!result.image && result.image != \'\'" class="angucomplete-image-default"></div></div><div class="angucomplete-title" ng-if="matchClass" ng-bind-html="result.title"></div><div class="angucomplete-title" ng-if="!matchClass">{{ result.title }}</div><div ng-if="result.description && result.description != \'\'" class="angucomplete-description">{{result.description}}</div></div></div></div>',
|
29
|
|
30
|
link: function($scope, elem, attrs) {
|
31
|
$scope.lastSearchTerm = null;
|
32
|
$scope.currentIndex = null;
|
33
|
$scope.justChanged = false;
|
34
|
$scope.searchTimer = null;
|
35
|
$scope.hideTimer = null;
|
36
|
$scope.searching = false;
|
37
|
$scope.pause = 500;
|
38
|
$scope.minLength = 3;
|
39
|
$scope.searchStr = null;
|
40
|
|
41
|
if ($scope.minLengthUser && $scope.minLengthUser != "") {
|
42
|
$scope.minLength = $scope.minLengthUser;
|
43
|
}
|
44
|
|
45
|
if ($scope.userPause) {
|
46
|
$scope.pause = $scope.userPause;
|
47
|
}
|
48
|
|
49
|
isNewSearchNeeded = function(newTerm, oldTerm) {
|
50
|
return newTerm.length >= $scope.minLength && newTerm != oldTerm
|
51
|
}
|
52
|
|
53
|
$scope.processResults = function(responseData, str) {
|
54
|
if (responseData && responseData.length > 0) {
|
55
|
$scope.results = [];
|
56
|
|
57
|
var titleFields = [];
|
58
|
if ($scope.titleField && $scope.titleField != "") {
|
59
|
titleFields = $scope.titleField.split(",");
|
60
|
}
|
61
|
|
62
|
for (var i = 0; i < responseData.length; i++) {
|
63
|
// Get title variables
|
64
|
var titleCode = [];
|
65
|
|
66
|
for (var t = 0; t < titleFields.length; t++) {
|
67
|
titleCode.push(responseData[i][titleFields[t]]);
|
68
|
}
|
69
|
|
70
|
var description = "";
|
71
|
if ($scope.descriptionField) {
|
72
|
description = responseData[i][$scope.descriptionField];
|
73
|
}
|
74
|
|
75
|
var imageUri = "";
|
76
|
if ($scope.imageUri) {
|
77
|
imageUri = $scope.imageUri;
|
78
|
}
|
79
|
|
80
|
var image = "";
|
81
|
if ($scope.imageField) {
|
82
|
image = imageUri + responseData[i][$scope.imageField];
|
83
|
}
|
84
|
|
85
|
var text = titleCode.join(' ');
|
86
|
if ($scope.matchClass) {
|
87
|
var re = new RegExp(str, 'i');
|
88
|
var strPart = text.match(re)[0];
|
89
|
text = $sce.trustAsHtml(text.replace(re, '<span class="'+ $scope.matchClass +'">'+ strPart +'</span>'));
|
90
|
}
|
91
|
|
92
|
var resultRow = {
|
93
|
title: text,
|
94
|
description: description,
|
95
|
image: image,
|
96
|
originalObject: responseData[i]
|
97
|
}
|
98
|
|
99
|
$scope.results[$scope.results.length] = resultRow;
|
100
|
}
|
101
|
|
102
|
|
103
|
} else {
|
104
|
$scope.results = [];
|
105
|
}
|
106
|
}
|
107
|
|
108
|
$scope.searchTimerComplete = function(str) {
|
109
|
// Begin the search
|
110
|
|
111
|
if (str.length >= $scope.minLength) {
|
112
|
if ($scope.localData) {
|
113
|
var searchFields = $scope.searchFields.split(",");
|
114
|
|
115
|
var matches = [];
|
116
|
|
117
|
for (var i = 0; i < $scope.localData.length; i++) {
|
118
|
var match = false;
|
119
|
|
120
|
for (var s = 0; s < searchFields.length; s++) {
|
121
|
match = match || (typeof $scope.localData[i][searchFields[s]] === 'string' && typeof str === 'string' && $scope.localData[i][searchFields[s]].toLowerCase().indexOf(str.toLowerCase()) >= 0);
|
122
|
}
|
123
|
|
124
|
if (match) {
|
125
|
matches[matches.length] = $scope.localData[i];
|
126
|
}
|
127
|
}
|
128
|
|
129
|
$scope.searching = false;
|
130
|
$scope.processResults(matches, str);
|
131
|
|
132
|
} else {
|
133
|
$http.get($scope.url + str, {}).
|
134
|
success(function(responseData, status, headers, config) {
|
135
|
$scope.searching = false;
|
136
|
$scope.processResults((($scope.dataField) ? responseData[$scope.dataField] : responseData ), str);
|
137
|
}).
|
138
|
error(function(data, status, headers, config) {
|
139
|
console.log("error");
|
140
|
});
|
141
|
}
|
142
|
}
|
143
|
}
|
144
|
|
145
|
$scope.hideResults = function() {
|
146
|
$scope.hideTimer = $timeout(function() {
|
147
|
$scope.showDropdown = false;
|
148
|
}, $scope.pause);
|
149
|
};
|
150
|
|
151
|
$scope.resetHideResults = function() {
|
152
|
if($scope.hideTimer) {
|
153
|
$timeout.cancel($scope.hideTimer);
|
154
|
};
|
155
|
};
|
156
|
|
157
|
$scope.hoverRow = function(index) {
|
158
|
$scope.currentIndex = index;
|
159
|
}
|
160
|
|
161
|
$scope.keyPressed = function(event) {
|
162
|
if (!(event.which == 38 || event.which == 40 || event.which == 13)) {
|
163
|
if (!$scope.searchStr || $scope.searchStr == "") {
|
164
|
$scope.showDropdown = false;
|
165
|
$scope.lastSearchTerm = null
|
166
|
} else if (isNewSearchNeeded($scope.searchStr, $scope.lastSearchTerm)) {
|
167
|
$scope.lastSearchTerm = $scope.searchStr
|
168
|
$scope.showDropdown = true;
|
169
|
$scope.currentIndex = -1;
|
170
|
$scope.results = [];
|
171
|
|
172
|
if ($scope.searchTimer) {
|
173
|
$timeout.cancel($scope.searchTimer);
|
174
|
}
|
175
|
|
176
|
$scope.searching = true;
|
177
|
|
178
|
$scope.searchTimer = $timeout(function() {
|
179
|
$scope.searchTimerComplete($scope.searchStr);
|
180
|
}, $scope.pause);
|
181
|
}
|
182
|
} else {
|
183
|
event.preventDefault();
|
184
|
}
|
185
|
}
|
186
|
|
187
|
$scope.selectResult = function(result) {
|
188
|
if ($scope.matchClass) {
|
189
|
result.title = result.title.toString().replace(/(<([^>]+)>)/ig, '');
|
190
|
}
|
191
|
$scope.searchStr = $scope.lastSearchTerm = result.title;
|
192
|
$scope.selectedObject = result;
|
193
|
$scope.showDropdown = false;
|
194
|
$scope.results = [];
|
195
|
//$scope.$apply();
|
196
|
}
|
197
|
|
198
|
var inputField = elem.find('input');
|
199
|
|
200
|
inputField.on('keyup', $scope.keyPressed);
|
201
|
|
202
|
elem.on("keyup", function (event) {
|
203
|
if(event.which === 40) {
|
204
|
if ($scope.results && ($scope.currentIndex + 1) < $scope.results.length) {
|
205
|
$scope.currentIndex ++;
|
206
|
$scope.$apply();
|
207
|
event.preventDefault;
|
208
|
event.stopPropagation();
|
209
|
}
|
210
|
|
211
|
$scope.$apply();
|
212
|
} else if(event.which == 38) {
|
213
|
if ($scope.currentIndex >= 1) {
|
214
|
$scope.currentIndex --;
|
215
|
$scope.$apply();
|
216
|
event.preventDefault;
|
217
|
event.stopPropagation();
|
218
|
}
|
219
|
|
220
|
} else if (event.which == 13) {
|
221
|
if ($scope.results && $scope.currentIndex >= 0 && $scope.currentIndex < $scope.results.length) {
|
222
|
$scope.selectResult($scope.results[$scope.currentIndex]);
|
223
|
$scope.$apply();
|
224
|
event.preventDefault;
|
225
|
event.stopPropagation();
|
226
|
} else {
|
227
|
$scope.results = [];
|
228
|
$scope.$apply();
|
229
|
event.preventDefault;
|
230
|
event.stopPropagation();
|
231
|
}
|
232
|
|
233
|
} else if (event.which == 27) {
|
234
|
$scope.results = [];
|
235
|
$scope.showDropdown = false;
|
236
|
$scope.$apply();
|
237
|
} else if (event.which == 8) {
|
238
|
$scope.selectedObject = null;
|
239
|
$scope.$apply();
|
240
|
}
|
241
|
});
|
242
|
|
243
|
}
|
244
|
};
|
245
|
});
|
246
|
|