blob: 52747890bc0df4276013b23341799a6a30894eef [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001'use strict';
2
3var _stringUtils = require('../utils/string-utils');
4
5var _constants = require('../utils/constants');
6
7/**
8 * @license
9 * Copyright 2016 Leif Olsen. All Rights Reserved.
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 *
23 * This code is built with Google Material Design Lite,
24 * which is Licensed under the Apache License, Version 2.0
25 */
26
27/*
28 * Copied/Modified from https://github.com/google/material-design-lite/tree/master/src/textfield
29 */
30
31(function () {
32 'use strict';
33
34 var LABEL = 'mdlext-selectfield__label';
35 var INPUT = 'mdlext-selectfield__select';
36
37 /**
38 * Class constructor for Selectfield MDLEXT component.
39 * Implements MDL component design pattern defined at:
40 * https://github.com/jasonmayes/mdl-component-design-pattern
41 *
42 * @constructor
43 * @param {HTMLElement} element The element that will be upgraded.
44 */
45 var MaterialExtSelectfield = function MaterialExtSelectfield(element) {
46 this.element_ = element;
47 this.init(); // Initialize instance.
48 };
49
50 window['MaterialExtSelectfield'] = MaterialExtSelectfield;
51
52 /**
53 * Handle focus.
54 *
55 * @param {Event} event The event that fired.
56 * @private
57 */
58 /*eslint no-unused-vars: 0*/
59 MaterialExtSelectfield.prototype.onFocus_ = function () /*event*/{
60 this.element_.classList.add(_constants.IS_FOCUSED);
61 };
62
63 /**
64 * Handle lost focus.
65 *
66 * @param {Event} event The event that fired.
67 * @private
68 */
69 /*eslint no-unused-vars: 0*/
70 MaterialExtSelectfield.prototype.onBlur_ = function () /*event*/{
71 this.element_.classList.remove(_constants.IS_FOCUSED);
72 };
73
74 /**
75 * Handle reset event from out side.
76 *
77 * @param {Event} event The event that fired.
78 * @private
79 */
80 MaterialExtSelectfield.prototype.onReset_ = function () /*event*/{
81 this.updateClasses_();
82 };
83
84 /**
85 * Handle class updates.
86 *
87 * @private
88 */
89 MaterialExtSelectfield.prototype.updateClasses_ = function () {
90 this.checkDisabled();
91 this.checkValidity();
92 this.checkDirty();
93 this.checkFocus();
94 };
95
96 // Public methods.
97
98 /**
99 * Check the disabled state and update field accordingly.
100 *
101 * @public
102 */
103 MaterialExtSelectfield.prototype.checkDisabled = function () {
104 if (this.select_.disabled) {
105 this.element_.classList.add(_constants.IS_DISABLED);
106 } else {
107 this.element_.classList.remove(_constants.IS_DISABLED);
108 }
109 };
110 MaterialExtSelectfield.prototype['checkDisabled'] = MaterialExtSelectfield.prototype.checkDisabled;
111
112 /**
113 * Check the focus state and update field accordingly.
114 *
115 * @public
116 */
117 MaterialExtSelectfield.prototype.checkFocus = function () {
118 // Note: element.querySelector(':focus') always return null in JsDom, even if select element has focus
119 /*eslint no-extra-boolean-cast: 0*/
120 if (Boolean(this.element_.querySelector(':focus'))) {
121 this.element_.classList.add(_constants.IS_FOCUSED);
122 } else {
123 this.element_.classList.remove(_constants.IS_FOCUSED);
124 }
125 };
126
127 MaterialExtSelectfield.prototype['checkFocus'] = MaterialExtSelectfield.prototype.checkFocus;
128
129 /**
130 * Check the validity state and update field accordingly.
131 *
132 * @public
133 */
134 MaterialExtSelectfield.prototype.checkValidity = function () {
135
136 /* Don't think it makes any sense to check validity.
137 Tests I've done, so far, indicates that setting an illegal value via JS returns selectedIndex=0
138 if (this.select_.validity) {
139 if (this.select_.validity.valid) {
140 this.element_.classList.remove(this.CssClasses_.IS_INVALID);
141 } else {
142 this.element_.classList.add(this.CssClasses_.IS_INVALID);
143 }
144 }
145 */
146 };
147
148 MaterialExtSelectfield.prototype['checkValidity'] = MaterialExtSelectfield.prototype.checkValidity;
149
150 /**
151 * Check the dirty state and update field accordingly.
152 *
153 * @public
154 */
155 MaterialExtSelectfield.prototype.checkDirty = function () {
156 if (this.select_.value && this.select_.value.length > 0) {
157 this.element_.classList.add(_constants.IS_DIRTY);
158 } else {
159 this.element_.classList.remove(_constants.IS_DIRTY);
160 }
161 };
162
163 MaterialExtSelectfield.prototype['checkDirty'] = MaterialExtSelectfield.prototype.checkDirty;
164
165 /**
166 * Disable select field.
167 *
168 * @public
169 */
170 MaterialExtSelectfield.prototype.disable = function () {
171 this.select_.disabled = true;
172 this.updateClasses_();
173 };
174
175 MaterialExtSelectfield.prototype['disable'] = MaterialExtSelectfield.prototype.disable;
176
177 /**
178 * Enable select field.
179 *
180 * @public
181 */
182 MaterialExtSelectfield.prototype.enable = function () {
183 this.select_.disabled = false;
184 this.updateClasses_();
185 };
186
187 MaterialExtSelectfield.prototype['enable'] = MaterialExtSelectfield.prototype.enable;
188
189 /**
190 * Update select field value.
191 *
192 * @param {string} value The value to which to set the control (optional).
193 * @public
194 */
195 MaterialExtSelectfield.prototype.change = function (value) {
196 this.select_.value = value || '';
197 this.updateClasses_();
198 };
199 MaterialExtSelectfield.prototype['change'] = MaterialExtSelectfield.prototype.change;
200
201 /**
202 * Initialize element.
203 */
204 MaterialExtSelectfield.prototype.init = function () {
205 if (this.element_) {
206 this.label_ = this.element_.querySelector('.' + LABEL);
207 this.select_ = this.element_.querySelector('.' + INPUT);
208
209 if (this.select_) {
210 // Remove listeners, just in case ...
211 this.select_.removeEventListener('change', this.updateClasses_);
212 this.select_.removeEventListener('focus', this.onFocus_);
213 this.select_.removeEventListener('blur', this.onBlur_);
214 this.select_.removeEventListener('reset', this.onReset_);
215
216 this.select_.addEventListener('change', this.updateClasses_.bind(this));
217 this.select_.addEventListener('focus', this.onFocus_.bind(this));
218 this.select_.addEventListener('blur', this.onBlur_.bind(this));
219 this.select_.addEventListener('reset', this.onReset_.bind(this));
220
221 if (this.label_) {
222 var id = void 0;
223 if (!this.select_.hasAttribute('id')) {
224 id = 'select-' + (0, _stringUtils.randomString)();
225 this.select_.id = id;
226 } else {
227 id = this.select_.id;
228 }
229
230 if (!this.label_.hasAttribute('for')) {
231 this.label_.setAttribute('for', id);
232 }
233 }
234
235 var invalid = this.element_.classList.contains(_constants.IS_INVALID);
236 this.updateClasses_();
237 this.element_.classList.add(_constants.IS_UPGRADED);
238
239 if (invalid) {
240 this.element_.classList.add(_constants.IS_INVALID);
241 }
242 if (this.select_.hasAttribute('autofocus')) {
243 this.element_.focus();
244 this.checkFocus();
245 }
246 }
247 }
248 };
249
250 /**
251 * Downgrade component
252 * E.g remove listeners and clean up resources
253 *
254 * Nothing to downgrade
255 *
256 MaterialExtSelectfield.prototype.mdlDowngrade_ = function() {
257 'use strict';
258 console.log('***** MaterialExtSelectfield.mdlDowngrade ');
259 };
260 */
261
262 // The component registers itself. It can assume componentHandler is available
263 // in the global scope.
264 /*eslint no-undef: 0*/
265 componentHandler.register({
266 constructor: MaterialExtSelectfield,
267 classAsString: 'MaterialExtSelectfield',
268 cssClass: 'mdlext-js-selectfield',
269 widget: true
270 });
271})();