258 lines
8.1 KiB
JavaScript
258 lines
8.1 KiB
JavaScript
(() => {
|
|
|
|
class NavItem extends HTMLElement {
|
|
constructor() {
|
|
super()
|
|
if (!this.hasAttribute('tabindex')) {
|
|
this.setAttribute('tabindex', '0');
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
class VInput extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
let self = this;
|
|
self.id = self.id || VUtils.tempId();
|
|
let val = self.innerHTML;
|
|
self.innerHTML = '';
|
|
let input = self.input = self.createNew('input', {id: self.id})
|
|
let label = self.createNew('label', {content: self.dataset.label});
|
|
self.createNew('span', {classes: 'error', content: self.dataset.error});
|
|
label.setAttribute('for', self.id);
|
|
input.type = self.getAttribute('type') || 'text';
|
|
input.value = val.trim();
|
|
input.required = self.hasAttribute('required');
|
|
input.name = self.getAttribute('name');
|
|
input.addMultiListener('change input', self.cb.bind(self));
|
|
}
|
|
|
|
get value() {
|
|
return this.input.value;
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.cb({currentTarget: this.input}, true);
|
|
}
|
|
|
|
cb(e, noInvalid) {
|
|
let el = e.currentTarget
|
|
let errorMessage = $('.error-message', el.find('form'));
|
|
if (errorMessage) {
|
|
errorMessage.classList.add('hide')
|
|
}
|
|
let cl = this.classList;
|
|
if (el.value === "") {
|
|
cl.remove('focus')
|
|
} else {
|
|
cl.add('focus')
|
|
}
|
|
if (el.checkValidity()) {
|
|
cl.add('valid');
|
|
cl.remove('invalid');
|
|
} else {
|
|
if (!noInvalid) {
|
|
cl.remove('valid');
|
|
cl.add('invalid');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class VSwitch extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
const id = this.dataset.id || VUtils.tempId();
|
|
$('input', this).id = id;
|
|
$('label', this).setAttribute('for', id);
|
|
}
|
|
}
|
|
|
|
class VSlider extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.input = $('input', this);
|
|
this.input.id = this.dataset.id || VUtils.tempId();
|
|
this.input.addEventListener('input', this.changeValue.bind(this));
|
|
this.cur = $('.current', this);
|
|
this.cur.addEventListener('input', this.onChange.bind(this));
|
|
this.cur.addEventListener('keypress', this.onKey.bind(this));
|
|
this.cur.addEventListener('focusout', this.onChange.bind(this));
|
|
this.checkStepSize();
|
|
this.minLabel = $('.min', this);
|
|
this.maxLabel = $('.max', this);
|
|
}
|
|
|
|
checkStepSize() {
|
|
const stepSize = this.input.getAttribute('step');
|
|
const max = parseFloat(this.input.getAttribute('max'));
|
|
const min = parseFloat(this.input.getAttribute('min'));
|
|
if (stepSize === "" && max - min <= 1) {
|
|
this.input.setAttribute('step', "0.05");
|
|
}
|
|
}
|
|
|
|
set value(value) {
|
|
this.input.value = value;
|
|
this.changeValue();
|
|
this.dispatchEvent(new Event('input'));
|
|
}
|
|
|
|
get value() {
|
|
return this.input.value;
|
|
}
|
|
|
|
set max(value) {
|
|
this.input.max = value;
|
|
this.maxLabel.innerHTML = value;
|
|
}
|
|
|
|
get max() {
|
|
return this.input.max;
|
|
}
|
|
|
|
set min(value) {
|
|
this.input.min = value;
|
|
this.minLabel.innerHTML = value;
|
|
}
|
|
|
|
get min() {
|
|
return this.input.min;
|
|
}
|
|
|
|
onKey(evt) {
|
|
const code = evt.keyCode;
|
|
if (code === 44 || code === 46) return;
|
|
if (code < 48 || code > 57 || code === 13) evt.preventDefault();
|
|
}
|
|
|
|
changeValue() {
|
|
this.cur.innerText = this.input.value;
|
|
}
|
|
|
|
onChange(e) {
|
|
if (e.type === 'focusout') {
|
|
this.cur.innerText = this.input.value;
|
|
return;
|
|
}
|
|
try {
|
|
const text = this.cur.innerText.trim();
|
|
if (text === '') {
|
|
this.cur.innerText = 0;
|
|
}
|
|
let val = parseFloat(text.replace(",", "."));
|
|
let min = parseFloat(this.input.getAttribute('min'));
|
|
let max = parseFloat(this.input.getAttribute('max'));
|
|
if (val < min) val = min;
|
|
if (val > max) val = max;
|
|
if (isNaN(val)) {
|
|
val = this.input.value;
|
|
}
|
|
let step = this.input.step || 1;
|
|
if (Math.floor(step) === step) {
|
|
val = Math.round(val);
|
|
}
|
|
this.input.value = val;
|
|
} catch (err) {
|
|
this.cur.innerText = this.input.value;
|
|
PrettyConsole.error(VSlider, err);
|
|
}
|
|
}
|
|
}
|
|
|
|
class VColor extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.input = $('input', this);
|
|
this.blob = $('.colorBlob', this);
|
|
this.addEventListener('input', this.onChange.bind(this));
|
|
}
|
|
|
|
onChange() {
|
|
requestAnimationFrame(() => {
|
|
this.blob.style.backgroundColor = this.input.value;
|
|
});
|
|
}
|
|
|
|
set value(value) {
|
|
this.input.value = value;
|
|
this.onChange();
|
|
this.dispatchEvent(new Event('input'));
|
|
}
|
|
|
|
get value() {
|
|
return this.input.value;
|
|
}
|
|
}
|
|
|
|
class VCollapseHead extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
if (!$('.btn-ripple', this)) {
|
|
this.createNew('div', {
|
|
classes: ['ripple']
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
class GUIItem extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
connectedCallback() {
|
|
requestAnimationFrame(() => {
|
|
this.update();
|
|
})
|
|
}
|
|
|
|
update() {
|
|
let bindItem = $('[data-bind]', this);
|
|
if (bindItem && bindItem.dataset.bind && bindItem.dataset.bind.trim() !== '') {
|
|
let bind = bindItem.dataset.bind;
|
|
if (bindItem.nodeName === 'INPUT' && bindItem.type === 'checkbox') {
|
|
bindItem.checked = config.get(bind, bindItem.checked);
|
|
} else if (bindItem.nodeName === 'V-SELECT') {
|
|
this.initVSelect(bindItem, bind);
|
|
} else {
|
|
bindItem.value = config.get(bind, bindItem.value);
|
|
}
|
|
if (!bindItem._hasEvent) {
|
|
bindItem.addEventListener('input', () => {
|
|
if (bindItem.nodeName === 'INPUT' && bindItem.type === 'checkbox') {
|
|
config.set(bind, bindItem.checked);
|
|
} else if (bindItem.nodeName === 'V-SELECT') {
|
|
config.set(bind, bindItem.rawValue);
|
|
} else {
|
|
config.set(bind, bindItem.value);
|
|
}
|
|
bindItem._hasEvent = true;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
initVSelect(bindItem, bind) {
|
|
let value = config.get(bind, bindItem.rawValue).toString().split(", ");
|
|
bindItem.options.forEach(item => {
|
|
if (value.indexOf(item.value) === -1) {
|
|
item.removeAttribute('selected');
|
|
} else {
|
|
item.setAttribute('selected', value.indexOf(item.value) !== -1);
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
customElements.define("v-input", VInput);
|
|
customElements.define("v-switch", VSwitch);
|
|
customElements.define("v-slider", VSlider);
|
|
customElements.define("v-color", VColor);
|
|
customElements.define("nav-item", NavItem);
|
|
customElements.define("v-gui-item", GUIItem);
|
|
customElements.define("v-collapse-head", VCollapseHead);
|
|
})();
|