-
Notifications
You must be signed in to change notification settings - Fork 6
/
jquery.qubit.js
100 lines (99 loc) · 3.09 KB
/
jquery.qubit.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
(function(factory){
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports === 'object') {
factory(require('jquery'));
} else {
factory(jQuery);
}
}(function($) {
$.fn.qubit = function(options) {
return this.each(function() {
new Qubit(this, options);
});
};
var Qubit = function(el) {
var self = this;
this.scope = $(el);
var handler = function(e) {
if (!self.suspendListeners) {
self.process(e.target);
}
};
this.scope.on('change', 'input[type=checkbox]', handler);
// workaround for IE<10
if (document.documentMode && document.documentMode <= 9) {
this.scope.on('click', 'input[type=checkbox]:indeterminate', handler);
}
this.processParents();
};
Qubit.prototype = {
itemSelector: 'li',
process: function(checkbox) {
checkbox = $(checkbox);
var parentItems = checkbox.parentsUntil(this.scope, this.itemSelector);
var self = this;
try {
this.suspendListeners = true;
// all children inherit my state
parentItems.eq(0).find('input[type=checkbox]').not(':disabled')
.filter(checkbox.prop('checked') ? ':not(:checked)' : ':checked')
.each(function() {
if (!$(this).parent().hasClass('hidden')) {
self.setChecked($(this), checkbox.prop('checked'));
}
});
this.processParents();
} finally {
this.suspendListeners = false;
}
},
processParents: function() {
var self = this, changed = false;
this.scope.find('input[type=checkbox]').not(':disabled').each(function() {
var $this = $(this);
var parent = $this.closest(self.itemSelector);
var children = parent.find('input[type=checkbox]').not(':disabled').not($this);
var numChecked = children.filter(function() {
return $(this).prop('checked') || $(this).prop('indeterminate');
}).length;
if (children.length) {
if (numChecked === 0) {
self.setChecked($this, false) && (changed = true);
}
else if (numChecked == children.length) {
self.setChecked($this, true) && (changed = true);
}
else {
self.setIndeterminate($this, true) && (changed = true);
}
}
else {
self.setIndeterminate($this, false) && (changed = true);
}
});
if (changed) this.processParents();
},
setChecked: function(checkbox, value, event) {
var changed = false;
if (checkbox.prop('indeterminate')) {
checkbox.prop('indeterminate', false);
changed = true;
}
if (checkbox.prop('checked') != value) {
checkbox.prop('checked', value).trigger('change');
changed = true;
}
return changed;
},
setIndeterminate: function(checkbox, value) {
if (value) {
checkbox.prop('checked', false);
}
if (checkbox.prop('indeterminate') != value) {
checkbox.prop('indeterminate', value);
return true;
}
}
};
}));