1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | import MDCFoundation from '@material/base/foundation';
|
25 |
|
26 | import {MDCIconToggleAdapter, IconToggleEvent} from './adapter';
|
27 | import {cssClasses, strings} from './constants';
|
28 |
|
29 |
|
30 |
|
31 |
|
32 | class MDCIconToggleFoundation extends MDCFoundation {
|
33 | static get cssClasses() {
|
34 | return cssClasses;
|
35 | }
|
36 |
|
37 | static get strings() {
|
38 | return strings;
|
39 | }
|
40 |
|
41 | static get defaultAdapter() {
|
42 | return {
|
43 | addClass: (/* className: string */) => {},
|
44 | removeClass: (/* className: string */) => {},
|
45 | registerInteractionHandler: (/* type: string, handler: EventListener */) => {},
|
46 | deregisterInteractionHandler: (/* type: string, handler: EventListener */) => {},
|
47 | setText: (/* text: string */) => {},
|
48 | getTabIndex: () => 0,
|
49 | setTabIndex: (/* tabIndex: number */) => {},
|
50 | getAttr: (/* name: string */) => '',
|
51 | setAttr: (/* name: string, value: string */) => {},
|
52 | rmAttr: (/* name: string */) => {},
|
53 | notifyChange: (/* evtData: IconToggleEvent */) => {},
|
54 | };
|
55 | }
|
56 |
|
57 | constructor(adapter) {
|
58 | super(Object.assign(MDCIconToggleFoundation.defaultAdapter, adapter));
|
59 |
|
60 |
|
61 | this.on_ = false;
|
62 |
|
63 |
|
64 | this.disabled_ = false;
|
65 |
|
66 |
|
67 | this.savedTabIndex_ = -1;
|
68 |
|
69 |
|
70 | this.toggleOnData_ = null;
|
71 |
|
72 |
|
73 | this.toggleOffData_ = null;
|
74 |
|
75 | this.clickHandler_ = (
|
76 | () => this.toggleFromEvt_());
|
77 |
|
78 |
|
79 | this.isHandlingKeydown_ = false;
|
80 |
|
81 | this.keydownHandler_ = ((/** @type {!KeyboardKey} */ evt) => {
|
82 | if (isSpace(evt)) {
|
83 | this.isHandlingKeydown_ = true;
|
84 | return evt.preventDefault();
|
85 | }
|
86 | });
|
87 |
|
88 | this.keyupHandler_ = ((/** @type {!KeyboardKey} */ evt) => {
|
89 | if (isSpace(evt)) {
|
90 | this.isHandlingKeydown_ = false;
|
91 | this.toggleFromEvt_();
|
92 | }
|
93 | });
|
94 | }
|
95 |
|
96 | init() {
|
97 | this.refreshToggleData();
|
98 | this.savedTabIndex_ = this.adapter_.getTabIndex();
|
99 | this.adapter_.registerInteractionHandler('click', this.clickHandler_);
|
100 | this.adapter_.registerInteractionHandler('keydown', this.keydownHandler_);
|
101 | this.adapter_.registerInteractionHandler('keyup', this.keyupHandler_);
|
102 | }
|
103 |
|
104 | refreshToggleData() {
|
105 | const {DATA_TOGGLE_ON, DATA_TOGGLE_OFF} = MDCIconToggleFoundation.strings;
|
106 | this.toggleOnData_ = this.parseJsonDataAttr_(DATA_TOGGLE_ON);
|
107 | this.toggleOffData_ = this.parseJsonDataAttr_(DATA_TOGGLE_OFF);
|
108 | }
|
109 |
|
110 | destroy() {
|
111 | this.adapter_.deregisterInteractionHandler('click', this.clickHandler_);
|
112 | this.adapter_.deregisterInteractionHandler('keydown', this.keydownHandler_);
|
113 | this.adapter_.deregisterInteractionHandler('keyup', this.keyupHandler_);
|
114 | }
|
115 |
|
116 |
|
117 | toggleFromEvt_() {
|
118 | this.toggle();
|
119 | const {on_: isOn} = this;
|
120 | this.adapter_.notifyChange( ({isOn}));
|
121 | }
|
122 |
|
123 |
|
124 | isOn() {
|
125 | return this.on_;
|
126 | }
|
127 |
|
128 |
|
129 | toggle(isOn = !this.on_) {
|
130 | this.on_ = isOn;
|
131 |
|
132 | const {ARIA_LABEL, ARIA_PRESSED} = MDCIconToggleFoundation.strings;
|
133 |
|
134 | if (this.on_) {
|
135 | this.adapter_.setAttr(ARIA_PRESSED, 'true');
|
136 | } else {
|
137 | this.adapter_.setAttr(ARIA_PRESSED, 'false');
|
138 | }
|
139 |
|
140 | const {cssClass: classToRemove} =
|
141 | this.on_ ? this.toggleOffData_ : this.toggleOnData_;
|
142 |
|
143 | if (classToRemove) {
|
144 | this.adapter_.removeClass(classToRemove);
|
145 | }
|
146 |
|
147 | const {content, label, cssClass} = this.on_ ? this.toggleOnData_ : this.toggleOffData_;
|
148 |
|
149 | if (cssClass) {
|
150 | this.adapter_.addClass(cssClass);
|
151 | }
|
152 | if (content) {
|
153 | this.adapter_.setText(content);
|
154 | }
|
155 | if (label) {
|
156 | this.adapter_.setAttr(ARIA_LABEL, label);
|
157 | }
|
158 | }
|
159 |
|
160 | |
161 |
|
162 |
|
163 |
|
164 | parseJsonDataAttr_(dataAttr) {
|
165 | const val = this.adapter_.getAttr(dataAttr);
|
166 | if (!val) {
|
167 | return {};
|
168 | }
|
169 | return (JSON.parse(val));
|
170 | }
|
171 |
|
172 |
|
173 | isDisabled() {
|
174 | return this.disabled_;
|
175 | }
|
176 |
|
177 |
|
178 | setDisabled(isDisabled) {
|
179 | this.disabled_ = isDisabled;
|
180 |
|
181 | const {DISABLED} = MDCIconToggleFoundation.cssClasses;
|
182 | const {ARIA_DISABLED} = MDCIconToggleFoundation.strings;
|
183 |
|
184 | if (this.disabled_) {
|
185 | this.savedTabIndex_ = this.adapter_.getTabIndex();
|
186 | this.adapter_.setTabIndex(-1);
|
187 | this.adapter_.setAttr(ARIA_DISABLED, 'true');
|
188 | this.adapter_.addClass(DISABLED);
|
189 | } else {
|
190 | this.adapter_.setTabIndex(this.savedTabIndex_);
|
191 | this.adapter_.rmAttr(ARIA_DISABLED);
|
192 | this.adapter_.removeClass(DISABLED);
|
193 | }
|
194 | }
|
195 |
|
196 |
|
197 | isKeyboardActivated() {
|
198 | return this.isHandlingKeydown_;
|
199 | }
|
200 | }
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 |
|
208 | let KeyboardKey;
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 | function isSpace(keyboardKey) {
|
215 | return keyboardKey.key === 'Space' || keyboardKey.keyCode === 32;
|
216 | }
|
217 |
|
218 |
|
219 |
|
220 | class IconToggleState {}
|
221 |
|
222 |
|
223 |
|
224 |
|
225 |
|
226 | IconToggleState.prototype.label;
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 | IconToggleState.prototype.content;
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 | IconToggleState.prototype.cssClass;
|
239 |
|
240 | export default MDCIconToggleFoundation;
|