-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck-allindex.js
More file actions
101 lines (101 loc) · 3.92 KB
/
check-allindex.js
File metadata and controls
101 lines (101 loc) · 3.92 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
export default function subscribe(container) {
let shiftKey = false;
let lastCheckbox = null;
container.addEventListener('mousedown', onMouseDown);
container.addEventListener('change', onChange);
function setChecked(target, input, checked, indeterminate = false) {
if (!(input instanceof HTMLInputElement))
return;
input.indeterminate = indeterminate;
if (input.checked !== checked) {
input.checked = checked;
setTimeout(() => {
const event = new CustomEvent('change', {
bubbles: true,
cancelable: false,
detail: { relatedTarget: target }
});
input.dispatchEvent(event);
});
}
}
function onChange(event) {
const target = event.target;
if (!(target instanceof Element))
return;
if (target.hasAttribute('data-check-all')) {
onCheckAll(event);
}
else if (target.hasAttribute('data-check-all-item')) {
onCheckAllItem(event);
}
}
function onCheckAll(event) {
if (event instanceof CustomEvent && event.detail) {
const { relatedTarget } = event.detail;
if (relatedTarget && relatedTarget.hasAttribute('data-check-all-item')) {
return;
}
}
const target = event.target;
if (!(target instanceof HTMLInputElement))
return;
lastCheckbox = null;
for (const input of container.querySelectorAll('[data-check-all-item]')) {
setChecked(target, input, target.checked);
}
target.indeterminate = false;
updateCount();
}
function onMouseDown(event) {
if (!(event.target instanceof Element))
return;
const target = event.target instanceof HTMLLabelElement ? event.target.control || event.target : event.target;
if (target.hasAttribute('data-check-all-item')) {
shiftKey = event.shiftKey;
}
}
function onCheckAllItem(event) {
if (event instanceof CustomEvent && event.detail) {
const { relatedTarget } = event.detail;
if (relatedTarget &&
(relatedTarget.hasAttribute('data-check-all') || relatedTarget.hasAttribute('data-check-all-item'))) {
return;
}
}
const target = event.target;
if (!(target instanceof HTMLInputElement))
return;
const itemCheckboxes = Array.from(container.querySelectorAll('[data-check-all-item]'));
if (shiftKey && lastCheckbox) {
const [start, end] = [itemCheckboxes.indexOf(lastCheckbox), itemCheckboxes.indexOf(target)].sort();
for (const input of itemCheckboxes.slice(start, +end + 1 || 9e9)) {
setChecked(target, input, target.checked);
}
}
shiftKey = false;
lastCheckbox = target;
const allCheckbox = container.querySelector('[data-check-all]');
if (allCheckbox) {
const total = itemCheckboxes.length;
const count = itemCheckboxes.filter(checkbox => checkbox instanceof HTMLInputElement && checkbox.checked).length;
const checked = count === total;
const indeterminate = total > count && count > 0;
setChecked(target, allCheckbox, checked, indeterminate);
}
updateCount();
}
function updateCount() {
const countContainer = container.querySelector('[data-check-all-count]');
if (countContainer) {
const count = container.querySelectorAll('[data-check-all-item]:checked').length;
countContainer.textContent = count.toString();
}
}
return {
unsubscribe: () => {
container.removeEventListener('mousedown', onMouseDown);
container.removeEventListener('change', onChange);
}
};
}