UNPKG

aurelia-binding

Version:

A modern databinding library for JavaScript and HTML.

185 lines (152 loc) 4.97 kB
import {subscriberCollection} from './subscriber-collection'; export class XLinkAttributeObserver { // xlink namespaced attributes require getAttributeNS/setAttributeNS // (even though the NS version doesn't work for other namespaces // in html5 documents) constructor(element, propertyName, attributeName) { this.element = element; this.propertyName = propertyName; this.attributeName = attributeName; } getValue() { return this.element.getAttributeNS('http://www.w3.org/1999/xlink', this.attributeName); } setValue(newValue) { return this.element.setAttributeNS('http://www.w3.org/1999/xlink', this.attributeName, newValue); } subscribe() { throw new Error(`Observation of a "${this.element.nodeName}" element\'s "${this.propertyName}" property is not supported.`); } } export const dataAttributeAccessor = { getValue: (obj, propertyName) => obj.getAttribute(propertyName), setValue: (value, obj, propertyName) => { if (value === null || value === undefined) { obj.removeAttribute(propertyName); } else { obj.setAttribute(propertyName, value); } } }; export class DataAttributeObserver { constructor(element, propertyName) { this.element = element; this.propertyName = propertyName; } getValue() { return this.element.getAttribute(this.propertyName); } setValue(newValue) { if (newValue === null || newValue === undefined) { return this.element.removeAttribute(this.propertyName); } return this.element.setAttribute(this.propertyName, newValue); } subscribe() { throw new Error(`Observation of a "${this.element.nodeName}" element\'s "${this.propertyName}" property is not supported.`); } } export class StyleObserver { constructor(element, propertyName) { this.element = element; this.propertyName = propertyName; this.styles = null; this.version = 0; } getValue() { return this.element.style.cssText; } _setProperty(style, value) { let priority = ''; if (value !== null && value !== undefined && typeof value.indexOf === 'function' && value.indexOf('!important') !== -1) { priority = 'important'; value = value.replace('!important', ''); } this.element.style.setProperty(style, value, priority); } setValue(newValue) { let styles = this.styles || {}; let style; let version = this.version; if (newValue !== null && newValue !== undefined) { if (newValue instanceof Object) { let value; for (style in newValue) { if (newValue.hasOwnProperty(style)) { value = newValue[style]; style = style.replace(/([A-Z])/g, m => '-' + m.toLowerCase()); styles[style] = version; this._setProperty(style, value); } } } else if (newValue.length) { let rx = /\s*([\w\-]+)\s*:\s*((?:(?:[\w\-]+\(\s*(?:"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|[\w\-]+\(\s*(?:^"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|[^\)]*)\),?|[^\)]*)\),?|"(?:\\"|[^"])*"|'(?:\\'|[^'])*'|[^;]*),?\s*)+);?/g; let pair; while ((pair = rx.exec(newValue)) !== null) { style = pair[1]; if ( !style ) { continue; } styles[style] = version; this._setProperty(style, pair[2]); } } } this.styles = styles; this.version += 1; if (version === 0) { return; } version -= 1; for (style in styles) { if (!styles.hasOwnProperty(style) || styles[style] !== version) { continue; } this.element.style.removeProperty(style); } } subscribe() { throw new Error(`Observation of a "${this.element.nodeName}" element\'s "${this.propertyName}" property is not supported.`); } } @subscriberCollection() export class ValueAttributeObserver { constructor(element, propertyName, handler) { this.element = element; this.propertyName = propertyName; this.handler = handler; if (propertyName === 'files') { // input.files cannot be assigned. this.setValue = () => {}; } } getValue() { return this.element[this.propertyName]; } setValue(newValue) { newValue = newValue === undefined || newValue === null ? '' : newValue; if (this.element[this.propertyName] !== newValue) { this.element[this.propertyName] = newValue; this.notify(); } } notify() { let oldValue = this.oldValue; let newValue = this.getValue(); this.callSubscribers(newValue, oldValue); this.oldValue = newValue; } handleEvent() { this.notify(); } subscribe(context, callable) { if (!this.hasSubscribers()) { this.oldValue = this.getValue(); this.handler.subscribe(this.element, this); } this.addSubscriber(context, callable); } unsubscribe(context, callable) { if (this.removeSubscriber(context, callable) && !this.hasSubscribers()) { this.handler.dispose(); } } }