is-loading
Version:
Small helper to give the user a visual feedback that something is happening
161 lines (140 loc) • 5.26 kB
JavaScript
import createElement from 'dom-create-element-query-selector';
export default (...params) => {
return new IsLoading(params);
};
const formElements = ['form', 'input', 'textarea', 'label', 'fieldset', 'select', 'button'];
const optionsDefault = {
'type': 'switch', // switch | replace | full-overlay | overlay
'text': 'loading', // Text to display in the loader
'disableSource': true, // true | false
'disableList': []
};
class IsLoading {
constructor (params) {
let options = {};
if (params.length === 0 || (params.length === 1 && !params[0].nodeType)) {
this._target = null;
options = {...params[0], type: 'full-overlay'};
} else {
this._target = params[0];
options = params[1];
}
this._options = {...optionsDefault, ...options};
this._fullOverlayId = 'is-loading-full-overlay';
}
loading () {
switch (this._options.type) {
case 'replace': this._onReplaceType(); break;
case 'full-overlay': this._onFullOverlayType(); break;
case 'overlay': this._onElementOverlayType(); break;
default: this._onSwitchType(); break;
}
}
get targetContent () {
if (this.isTargetValue) {
return this._target.value;
} else {
return this._target.textContent;
}
}
set targetContent (val) {
if (this.isTargetValue) {
this._target.value = val;
} else {
this._target.textContent = val;
}
}
get isTargetValue () {
const node = this._target.nodeName.toLowerCase();
const type = this._target.attributes.type;
return (node === 'input' && type && (type.value.toLowerCase() === 'button' || type.value.toLowerCase() === 'submit'));
}
restoreContent () {
const content = this._target.getAttribute('data-is-loading-content');
if (this.isTargetValue) {
this._target.value = content;
} else {
this._target.textContent = content;
}
}
_onSwitchType () {
this._toggleElements(false);
this._target.setAttribute('data-is-loading-content', this.targetContent);
this.targetContent = this._options.text;
}
_onReplaceType () {
this._toggleElements(false);
this._target.setAttribute('data-is-loading-content', this.targetContent);
this._target.innerHTML = '';
this._target.appendChild(createElement('span.is-loading.is-loading-target', this._options.text));
}
_onElementOverlayType () {
this._toggleElements(false);
const overlayWrapperClass = '.is-loading-element-overlay';
if (this._prop('position') === 'static') {
this._target.setAttribute('data-is-loading-position', 'static');
this._target.classList.add('is-loading-element-overlay-target');
}
if (!this._target.querySelector(overlayWrapperClass)) {
const overlay = createElement(overlayWrapperClass,
createElement('.is-loading-text-wrapper', this._options.text)
);
overlay.style.borderRadius = this._prop('border-radius');
this._target.appendChild(overlay);
}
}
_onFullOverlayType () {
this._toggleElements(false);
this._showFullOverlay();
}
_showFullOverlay () {
let overlay = document.querySelector(this._fullOverlayId);
if (!overlay) {
overlay = createElement(`#${this._fullOverlayId}`,
createElement('.is-loading-text-wrapper', this._options.text)
);
document.querySelector('body').appendChild(overlay);
}
}
_prop (prop) {
return window.getComputedStyle(this._target).getPropertyValue(prop);
}
_toggleElements (status = true) {
let list = [...this._options.disableList];
if (this._target && this._options.disableSource === true) {
list.unshift(this._target);
}
list.forEach(item => {
if (formElements.includes(item.tagName.toLowerCase())) {
if (status === true) {
item.removeAttribute('disabled');
} else {
item.setAttribute('disabled', 'disabled');
}
}
if (status === true) {
item.classList.remove('disabled');
} else {
item.classList.add('disabled');
}
});
}
remove () {
this._toggleElements(true);
if (this._options.type === 'switch') {
this.restoreContent();
}
if (this._target) {
this._target.removeAttribute('data-is-loading-content');
}
if (this._options.type === 'full-overlay') {
let overlay = document.getElementById(this._fullOverlayId);
if (overlay) {
document.querySelector('body').removeChild(overlay);
}
}
if (this._target && this._target.getAttribute('data-is-loading-position')) {
this._target.classList.remove('is-loading-element-overlay-target');
}
}
}