-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathangular-checkboxes.js
More file actions
172 lines (126 loc) · 4.77 KB
/
Copy pathangular-checkboxes.js
File metadata and controls
172 lines (126 loc) · 4.77 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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
'use strict';
angular.module('msieurtoph.ngCheckboxes', [])
.directive('mtTo', ['$timeout', function($timeout){
return {
restrict: 'A',
controller: ['$parse', '$attrs', '$scope', function($parse, $attrs, $scope){
var getter = $parse($attrs.mtTo),
setter = getter.assign,
_this = this
;
this.get = function(){
return getter($scope) || [];
};
this.set = function(list){
return setter($scope, angular.copy(list));
};
this.indexOf = function(elt){
var list = _this.get();
for (var i=0, l=list.length; i<l; i++){
if (angular.equals(list[i], elt)) {
return i;
}
}
return -1;
};
this.add = function(elt){
$timeout(function(){
if (-1 === _this.indexOf(elt)){
var list = _this.get();
list.push(elt);
_this.set(list);
}
});
};
this.remove = function(elt){
$timeout(function(){
var index = _this.indexOf(elt);
if (-1 !== index){
var list = _this.get();
list.splice(index, 1);
_this.set(list);
}
});
};
}]
};
}])
.directive('mtCheckbox', [function () {
var internalCount = 0;
function uniqName(){
return 'mtCheckBox_' + (++internalCount);
}
return {
restrict: 'A',
require: ['mtCheckbox', '^mtTo', '?ngModel'],
controller: ['$attrs', '$parse', '$scope', function($attrs, $parse, $scope){
var getter = $parse($attrs.mtCheckbox),
setter = getter.assign
;
if ('' === $attrs.mtCheckbox) {
this.value = !!$attrs.name && '' !== $attrs.name ? $attrs.name : uniqName();
} else if (!angular.isFunction(setter)) {
this.value = getter($scope);
} else {
Object.defineProperty(this, 'value', {
enumerable: true,
get: function(){
return getter($scope);
},
set: function(val){
setter($scope, val);
}
});
}
// state is undefined until the first control;
this.state = undefined;
}],
link: {
pre: function(scope, element, attrs, ctrls){
var ctrl = ctrls[0],
destCtrl = ctrls[1],
ngModelCtrl = ctrls[2]
;
ctrl.hasNgModel = !! ngModelCtrl;
// watch changes on the element
// and then call set() ...
if (ctrl.hasNgModel) {
scope.$watch(attrs.ngModel, function(newVal, oldVal){
if (newVal !== oldVal){
ctrl.set(newVal);
}
});
} else {
element.on('change', function(){
ctrl.set(!ctrl.state);
});
}
// watch changes in the dest Model (= the array)
// and then call set() ...
scope.$watchCollection(function (){
return -1 !== destCtrl.indexOf(ctrl.value);
}, function(newV){
ctrl.set(newV);
});
// add method to the controller to check/uncheck the checkbox!
// init state, set local state/model and report to parent Model
ctrl.set = function(state){
// if ngModel does not have same state
// then change ngModel and abort, because the $viewValueListener will run again the set()
if (ctrl.hasNgModel && state !== ngModelCtrl.$modelValue) {
ngModelCtrl.$setViewValue(state);
return;
}
// abort if the ckeck/uncheck is already performed
if (ctrl.state === state || 'boolean' !== typeof state){
return;
}
// perform the check/uncheck
ctrl.state = !!state;
element[0].checked = ctrl.state;
destCtrl[ctrl.state ? 'add' : 'remove'](ctrl.value);
};
}
}
};
}]);