-
Notifications
You must be signed in to change notification settings - Fork 7
/
selectize-ng.js
128 lines (110 loc) · 3.59 KB
/
selectize-ng.js
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
angular.module('selectize-ng', [])
.directive('selectize', function($timeout) {
'use strict';
return {
restrict: 'A',
require: 'ngModel',
scope: {
selectize: '&',
options: '&'
},
link: function(scope, element, attrs, ngModel) {
var changing, options, selectize, invalidValues = [];
// Default options
options = angular.extend({
delimiter: ',',
persist: true,
mode: (element[0].tagName === 'SELECT') ? 'single' : 'multi'
}, scope.selectize() || {});
// Activate the widget
selectize = element.selectize(options)[0].selectize;
selectize.on('change', function() {
setModelValue(selectize.getValue());
});
function setModelValue(value) {
if (changing) {
return;
}
scope.$parent.$apply(function() {
ngModel.$setViewValue(value);
});
if (options.mode === 'single') {
selectize.blur();
}
}
// Normalize the model value to an array
function parseValues(value) {
if (angular.isArray(value)) {
return value;
}
if ( ! value) {
return [];
}
return String(value).split(options.delimiter);
}
// Non-strict indexOf
function indexOfLike(arr, val) {
for (var i=0; i < arr.length; i++) {
if (arr[i] == val) {
return i;
}
}
return -1;
}
// Boolean wrapper to indexOfLike
function contains(arr, val) {
return indexOfLike(arr, val) !== -1;
}
// Store invalid items for late-loading options
function storeInvalidValues(values, resultValues) {
values.map(function(val) {
if ( ! (contains(resultValues, val) || contains(invalidValues, val))) {
invalidValues.push(val);
}
});
}
function restoreInvalidValues(newOptions, values) {
var i, index;
for (i=0; i < newOptions.length; i++) {
index = indexOfLike(invalidValues, newOptions[i][selectize.settings.valueField]);
if (index !== -1) {
values.push(newOptions[i][selectize.settings.valueField]);
invalidValues.splice(index, 1);
}
}
}
function setSelectizeValue(value) {
var values = parseValues(value);
if (changing || values === parseValues(selectize.getValue())) {
return;
}
changing = true;
setTimeout(function() {
selectize.setValue(values);
changing = false;
storeInvalidValues(values, parseValues(selectize.getValue()));
});
}
function setSelectizeOptions(newOptions) {
$timeout(function(){
// prevent digest problems
var values = parseValues(ngModel.$viewValue);
selectize.clearOptions();
selectize.addOption(newOptions);
selectize.refreshOptions(false);
if (options.mode === 'multi' && newOptions) {
restoreInvalidValues(newOptions, values);
}
setSelectizeValue(values);
});
}
scope.$parent.$watch(attrs.ngModel, setSelectizeValue);
if (attrs.options) {
scope.$parent.$watchCollection(attrs.options, setSelectizeOptions);
}
scope.$on('$destroy', function() {
selectize.destroy();
});
}
};
});