-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpicker.js
138 lines (111 loc) · 3.37 KB
/
picker.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
129
130
131
132
133
134
135
136
137
138
export class Picker {
constructor(root) {
let args = {
// Root element for picker
el: null,
// Selector for children
children: '*',
// Class to add to picked children
class: 'picker-selected'
};
if (_.isUndefined(root))
console.log('Must pass argument to Picker constructor');
if (_.isObject(root))
args = _.defaults(_.clone(root), args);
else
args.el = root;
if (_.isString(args.el)) {
args.el = document.querySelector(args.el);
} else if (!_.isElement(args.el)) {
console.log('Must pass string or element to picker');
}
// copy properties to this
_.extend(this, args);
this._assignHandlers();
}
_assignHandlers() {
var children = this.el.querySelectorAll(this.children);
for (var child of children) {
child.addEventListener('click', this._clickHandler.bind(this));
}
}
_clickHandler(mouseEvt) {
this.clear();
let elem = mouseEvt.currentTarget;
elem.classList.add(this.class);
}
clear() {
for (let child of this.el.querySelectorAll(this.children)) {
child.classList.remove(this.class);
}
}
};
/**
* @class LockedPicker
*
* Applies classes to elements depending on rules
*
* Rules are specified as an object, where the key is a selector for a child
* which, when clicked, applies the ruleset to the other children
*
* For example:
* {
* ".play": {
* enable: [".pause", ".stop"],
* disable: [".play"]
* },
* ".pause": {
* enable: [".play", ".stop"],
* disable: [".pause"]
* }
* }
*
* @param {Object} args Argument object
*/
export class LockedPicker extends Picker {
constructor(args) {
super(args);
this.enableClass = args.enableClass || 'enable';
this.disableClass = args.disableClass || 'disable';
this.rules = args.rules || {};
};
_clickHandler(evt) {
// try to identify which selector matches the clicked element
let sels = Object.keys(this.rules),
target = evt.currentTarget,
targetSel = null;
// Check if target is disabled, bail if it is
if (target.classList.contains(this.disableClass))
return;
for (let sel of sels) {
let candidates = this.el.querySelectorAll(sel);
if (Array.prototype.some.call(candidates, (el) => el === target)) {
targetSel = sel;
break;
}
}
if (targetSel) {
this.clear();
this.applyRule(this.rules[targetSel]);
}
}
applyRule(rule) {
for (let toEnable of rule.enable) {
Array.prototype.forEach.call(
this.el.querySelectorAll(toEnable),
(el) => el.classList.add(this.enableClass)
);
}
for (let toDisable of rule.disable) {
Array.prototype.forEach.call(
this.el.querySelectorAll(toDisable),
(el) => el.classList.add(this.disableClass)
);
}
}
clear() {
for (let child of this.el.querySelectorAll(this.children)) {
child.classList.remove(this.enableClass, this.disableClass);
}
}
};