blob: 459f0b8f28e6f332d348fc4c3326fc1d2c067ba6 [file] [log] [blame]
/**
* @license
* Copyright 2016 Leif Olsen. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This code is built with Google Material Design Lite,
* which is Licensed under the Apache License, Version 2.0
*/
/*
* Copied/Modified from https://github.com/google/material-design-lite/tree/master/src/textfield
*/
import { randomString } from '../utils/string-utils';
import {
IS_DIRTY,
IS_FOCUSED,
IS_DISABLED,
IS_INVALID,
IS_UPGRADED
} from '../utils/constants';
(function() {
'use strict';
const LABEL = 'mdlext-selectfield__label';
const INPUT = 'mdlext-selectfield__select';
/**
* Class constructor for Selectfield MDLEXT component.
* Implements MDL component design pattern defined at:
* https://github.com/jasonmayes/mdl-component-design-pattern
*
* @constructor
* @param {HTMLElement} element The element that will be upgraded.
*/
const MaterialExtSelectfield = function MaterialExtSelectfield(element) {
this.element_ = element;
this.init(); // Initialize instance.
};
window['MaterialExtSelectfield'] = MaterialExtSelectfield;
/**
* Handle focus.
*
* @param {Event} event The event that fired.
* @private
*/
/*eslint no-unused-vars: 0*/
MaterialExtSelectfield.prototype.onFocus_ = function( /*event*/ ) {
this.element_.classList.add(IS_FOCUSED);
};
/**
* Handle lost focus.
*
* @param {Event} event The event that fired.
* @private
*/
/*eslint no-unused-vars: 0*/
MaterialExtSelectfield.prototype.onBlur_ = function( /*event*/ ) {
this.element_.classList.remove(IS_FOCUSED);
};
/**
* Handle reset event from out side.
*
* @param {Event} event The event that fired.
* @private
*/
MaterialExtSelectfield.prototype.onReset_ = function( /*event*/ ) {
this.updateClasses_();
};
/**
* Handle class updates.
*
* @private
*/
MaterialExtSelectfield.prototype.updateClasses_ = function() {
this.checkDisabled();
this.checkValidity();
this.checkDirty();
this.checkFocus();
};
// Public methods.
/**
* Check the disabled state and update field accordingly.
*
* @public
*/
MaterialExtSelectfield.prototype.checkDisabled = function() {
if (this.select_.disabled) {
this.element_.classList.add(IS_DISABLED);
} else {
this.element_.classList.remove(IS_DISABLED);
}
};
MaterialExtSelectfield.prototype['checkDisabled'] = MaterialExtSelectfield.prototype.checkDisabled;
/**
* Check the focus state and update field accordingly.
*
* @public
*/
MaterialExtSelectfield.prototype.checkFocus = function() {
// Note: element.querySelector(':focus') always return null in JsDom, even if select element has focus
/*eslint no-extra-boolean-cast: 0*/
if (Boolean(this.element_.querySelector(':focus'))) {
this.element_.classList.add(IS_FOCUSED);
} else {
this.element_.classList.remove(IS_FOCUSED);
}
};
MaterialExtSelectfield.prototype['checkFocus'] = MaterialExtSelectfield.prototype.checkFocus;
/**
* Check the validity state and update field accordingly.
*
* @public
*/
MaterialExtSelectfield.prototype.checkValidity = function() {
/* Don't think it makes any sense to check validity.
Tests I've done, so far, indicates that setting an illegal value via JS returns selectedIndex=0
if (this.select_.validity) {
if (this.select_.validity.valid) {
this.element_.classList.remove(this.CssClasses_.IS_INVALID);
} else {
this.element_.classList.add(this.CssClasses_.IS_INVALID);
}
}
*/
};
MaterialExtSelectfield.prototype['checkValidity'] = MaterialExtSelectfield.prototype.checkValidity;
/**
* Check the dirty state and update field accordingly.
*
* @public
*/
MaterialExtSelectfield.prototype.checkDirty = function() {
if (this.select_.value && this.select_.value.length > 0) {
this.element_.classList.add(IS_DIRTY);
} else {
this.element_.classList.remove(IS_DIRTY);
}
};
MaterialExtSelectfield.prototype['checkDirty'] = MaterialExtSelectfield.prototype.checkDirty;
/**
* Disable select field.
*
* @public
*/
MaterialExtSelectfield.prototype.disable = function() {
this.select_.disabled = true;
this.updateClasses_();
};
MaterialExtSelectfield.prototype['disable'] = MaterialExtSelectfield.prototype.disable;
/**
* Enable select field.
*
* @public
*/
MaterialExtSelectfield.prototype.enable = function() {
this.select_.disabled = false;
this.updateClasses_();
};
MaterialExtSelectfield.prototype['enable'] = MaterialExtSelectfield.prototype.enable;
/**
* Update select field value.
*
* @param {string} value The value to which to set the control (optional).
* @public
*/
MaterialExtSelectfield.prototype.change = function(value) {
this.select_.value = value || '';
this.updateClasses_();
};
MaterialExtSelectfield.prototype['change'] = MaterialExtSelectfield.prototype.change;
/**
* Initialize element.
*/
MaterialExtSelectfield.prototype.init = function() {
if (this.element_) {
this.label_ = this.element_.querySelector(`.${LABEL}`);
this.select_ = this.element_.querySelector(`.${INPUT}`);
if (this.select_) {
// Remove listeners, just in case ...
this.select_.removeEventListener('change', this.updateClasses_);
this.select_.removeEventListener('focus', this.onFocus_);
this.select_.removeEventListener('blur', this.onBlur_);
this.select_.removeEventListener('reset', this.onReset_);
this.select_.addEventListener('change', this.updateClasses_.bind(this));
this.select_.addEventListener('focus', this.onFocus_.bind(this));
this.select_.addEventListener('blur', this.onBlur_.bind(this));
this.select_.addEventListener('reset', this.onReset_.bind(this));
if(this.label_) {
let id;
if(!this.select_.hasAttribute('id')) {
id = `select-${randomString()}`;
this.select_.id = id;
}
else {
id = this.select_.id;
}
if(!this.label_.hasAttribute('for')) {
this.label_.setAttribute('for', id);
}
}
const invalid = this.element_.classList.contains(IS_INVALID);
this.updateClasses_();
this.element_.classList.add(IS_UPGRADED);
if (invalid) {
this.element_.classList.add(IS_INVALID);
}
if (this.select_.hasAttribute('autofocus')) {
this.element_.focus();
this.checkFocus();
}
}
}
};
/**
* Downgrade component
* E.g remove listeners and clean up resources
*
* Nothing to downgrade
*
MaterialExtSelectfield.prototype.mdlDowngrade_ = function() {
'use strict';
console.log('***** MaterialExtSelectfield.mdlDowngrade ');
};
*/
// The component registers itself. It can assume componentHandler is available
// in the global scope.
/*eslint no-undef: 0*/
componentHandler.register({
constructor: MaterialExtSelectfield,
classAsString: 'MaterialExtSelectfield',
cssClass: 'mdlext-js-selectfield',
widget: true
});
})();