UNPKG

@ribajs/core

Version:

Core module of Riba.js

108 lines (92 loc) 2.76 kB
import { Binder } from "../binder.js"; import { getInputValue, getString, setAttribute } from "@ribajs/utils"; const DEFAULT_EVENTS = "change input paste blur focus"; /** * Sets the element's value. Also sets the model property when the input changes * (two-way binder). */ export class ValueBinder extends Binder<any, HTMLElement> { static key = "value"; publishes = true; priority = 3000; event?: string; getData(el: HTMLElement) { const data = { type: (el as HTMLInputElement).type, tagName: el.tagName, contenteditable: el.getAttribute("contenteditable") ? true : false, isRadio: false, isOption: false, }; data.isRadio = data.tagName === "INPUT" && data.type === "radio"; data.isOption = data.tagName === "OPTION"; return data; } onChange = this.publish.bind(this); bind(el: HTMLElement) { if (el.tagName === "OPTION") { return; } const data = this.getData(el); if (!data.isRadio) { this.event = el.getAttribute("event-name") || DEFAULT_EVENTS; const events = this.event.split(" "); for (const event of events) { el.addEventListener(event.trim(), this.onChange, false); } } } unbind(el: HTMLUnknownElement) { if (this.event) { const events = this.event.split(" "); for (const event in events) { el.removeEventListener(event.trim(), this.onChange); } } } routine( el: HTMLElement | HTMLSelectElement, newValue?: number | string | string[], ) { let oldValue = this.getValue(el); if (!Array.isArray(newValue)) { if (newValue != null) { newValue = getString(newValue); } else { newValue = ""; } } if (!Array.isArray(oldValue)) { if (oldValue != null) { oldValue = getString(oldValue); } else { oldValue = ""; } } if (oldValue === newValue) { // nothing changed return; } const data = this.getData(el); if (data.isRadio || data.isOption) { return setAttribute(el, "value", newValue); } if ((el as HTMLSelectElement).type === "select-multiple") { if (Array.isArray(newValue)) { for (let i = 0; i < (el as HTMLSelectElement).options.length; i++) { const option = (el as HTMLSelectElement).options[ i ] as HTMLOptionElement; option.selected = newValue.indexOf(option.value) > -1; } } } else if (el.getAttribute("contenteditable")) { el.innerHTML = newValue as string; // TODO write test for contenteditable } else { (el as HTMLInputElement).value = newValue as string; } } getValue(el: HTMLElement) { return getInputValue(el); } }