UNPKG

@akala/core

Version:
365 lines 13.1 kB
"use strict"; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; result["default"] = mod; return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const parser_1 = require("./parser"); const events_1 = require("events"); const promiseHelpers_1 = require("./promiseHelpers"); const formatters = __importStar(require("./formatters")); const eachAsync_1 = require("./eachAsync"); const each_1 = require("./each"); class Binding extends events_1.EventEmitter { constructor(_expression, _target, register = true) { super(); this._expression = _expression; this._target = _target; this.evaluator = parser_1.Parser.evalAsFunction(this.expression); this.registeredBindings = []; this.formatter = formatters.identity; if (register) this.register(); else this.setMaxListeners(0); } static defineProperty(target, property, value) { var binding = new Binding(property.toString(), target); Object.defineProperty(target, property, { get() { return value; }, set(value) { binding.setValue(value, binding); } }); return binding; } static unbindify(element) { return each_1.map(element, function (value, key) { if (typeof (value) == 'object') { if (value instanceof Binding) return value.getValue(); else return Binding.unbindify(value); } else return value; }); } get expression() { return this._expression; } get target() { return this._target; } set target(value) { this._target = value; this.register(); } onChanging(handler) { this.on(Binding.ChangingFieldEventName, handler); } onChanged(handler, doNotTriggerHandler) { this.on(Binding.ChangedFieldEventName, handler); if (!doNotTriggerHandler) handler({ target: this.target, eventArgs: { fieldName: this.expression, value: this.getValue() }, source: null }); } onError(handler) { this.on(Binding.ErrorEventName, handler); } pipe(binding) { if (this.registeredBindings.indexOf(binding) > -1) return; this.registeredBindings.push(binding); var watcher = this; watcher.onChanging(function (a) { if (a.source == binding || a.source === null) return; var args = [Binding.ChangingFieldEventName, a]; //@ts-ignore TS2345 binding.emit.apply(binding, args); }); watcher.onChanged(function (a) { if (a.source == binding || a.source === null) return; var args = [Binding.ChangedFieldEventName, { source: a.source, target: a.target, eventArgs: { fieldName: a.eventArgs.fieldName, value: binding.getValue() } }]; //@ts-ignore TS2345 binding.emit.apply(binding, args); }); watcher.onError(function (a) { if (a.source == binding || a.source === null) return; var args = [Binding.ChangedFieldEventName, a]; //@ts-ignore TS2345 binding.emit.apply(binding, args); }); } //defined in constructor getValue() { return this.formatter(this.evaluator(this.target, false)); } register() { var target = this.target; var parts = parser_1.Parser.parseBindable(this.expression); var self = this; while (parts.length > 0) { var part = parts.shift(); if (target !== null && target !== undefined && typeof (target) == 'object') { if (!target.hasOwnProperty('$$watchers')) { try { Object.defineProperty(target, '$$watchers', { enumerable: false, writable: false, value: {}, configurable: true }); } catch (e) { console.error('could not register watcher on ', target, 'this could lead to performance issues'); } } var watcher = target.$$watchers && target.$$watchers[part]; if (!watcher) { if (promiseHelpers_1.isPromiseLike(target)) { var subParts = part; if (parts.length > 0) subParts += '.' + parts.join('.'); watcher = new PromiseBinding(subParts, target); } else if (target instanceof ObservableArray) { let initHandled = false; target.on('collectionChanged', function (args) { if (args.action == 'init') { if (initHandled) return; initHandled = true; } var subParts = part; if (parts.length > 0) subParts += '.' + parts.join('.'); for (var i in args.newItems) { new Binding(subParts, args.newItems[i]).pipe(this); } }); target.init(); return; } else watcher = new Binding(part, target, false); if (target.$$watchers) target.$$watchers[part] = watcher; } watcher.pipe(this); if (watcher instanceof PromiseBinding) return; target = watcher.getValue(); } } } apply(elements, doNotRegisterEvents) { } /*apply(elements, doNotRegisterEvents) { var val = this.getValue(); var inputs = elements.filter(':input').val(val) var binding = this; if (!doNotRegisterEvents) inputs.change(function () { binding.setValue($(this).val(), this); }); elements.filter(':not(:input))').text(val); }*/ static getSetter(target, expression) { var parts = parser_1.Parser.parseBindable(expression); return function (value, source, doNotTriggerEvents) { while (parts.length > 1) { if (!target && target !== '') return; target = target[parts.shift()]; } var watcher = target.$$watchers[parts[0]]; var setter = parser_1.Parser.getSetter(parts[0], target); if (setter === null) return; var promise = new Promise((resolve, reject) => { try { if (doNotTriggerEvents) return resolve(value); if (watcher) { var listeners = watcher.listeners(Binding.ChangingFieldEventName); eachAsync_1.array(listeners, function (listener, i, next) { promiseHelpers_1.Promisify(listener({ target: target, fieldName: setter.expression, source: source, })).then(function () { next(); }, reject); }, function () { resolve(value); }); } else resolve(value); } catch (ex) { watcher.emit(Binding.ErrorEventName, { target: target, field: setter.expression, Exception: ex, source: source }); reject(ex); } }); promise.then(function resolve(value) { setter.set(value); if (watcher && !doNotTriggerEvents) watcher.emit(Binding.ChangedFieldEventName, { target: target, eventArgs: { fieldName: setter.expression, value: value }, source: source }); }, function (ex) { if (watcher) watcher.emit(Binding.ErrorEventName, { target: target, field: setter.expression, Exception: ex, source: source }); }); return promise; }; } setValue(value, source, doNotTriggerEvents) { var target = this.target; var setter = Binding.getSetter(this.target, this.expression); if (setter != null) setter(value, source || this, doNotTriggerEvents); } ; } exports.Binding = Binding; Binding.ChangingFieldEventName = "fieldChanging"; Binding.ChangedFieldEventName = "fieldChanged"; Binding.ErrorEventName = "bindingError"; class PromiseBinding extends Binding { constructor(expression, target) { super(expression, null, false); var self = this; var binding = new Binding(expression, null); binding.pipe(self); var callback = function (value) { if (promiseHelpers_1.isPromiseLike(value)) { value.then(callback); return; } binding.formatter = self.formatter; binding.target = value; self.emit(Binding.ChangedFieldEventName, { target: value, eventArgs: { fieldName: self.expression, value: self.getValue() }, source: binding }); }; target.then(callback); } } exports.PromiseBinding = PromiseBinding; if (typeof (Array.prototype['replace']) == 'undefined') Object.defineProperty(Array.prototype, 'replace', { value: function (index, item) { this[index] = item; }, configurable: true, writable: true, enumerable: false }); class ObservableArray extends events_1.EventEmitter { constructor(array) { super(); this.array = array; this.unshift = function (item) { this.array.unshift(item); this.emit('collectionChanged', { action: 'unshift', newItems: [item] }); }; } get length() { return this.array.length; } push(...items) { this.array.push.apply(this.array, items); this.emit('collectionChanged', { action: 'push', newItems: items }); } ; shift() { var item = this.array.shift(); this.emit('collectionChanged', { action: 'shift', oldItems: [item] }); } ; pop() { var item = this.array.pop(); this.emit('collectionChanged', { action: 'pop', oldItems: [item] }); } ; replace(index, item) { var oldItem = this.array[index]; this.array['replace'](index, item); this.emit('collectionChanged', { action: 'replace', newItems: [item], oldItems: [oldItem] }); } ; init() { this.emit('collectionChanged', { action: 'init', newItems: this.array.slice(0) }); } indexOf() { //@ts-ignore TS2345 return this.array.indexOf.apply(this.array, arguments); } toString() { return this.array.toString(); } ; } exports.ObservableArray = ObservableArray; ; class WatchBinding extends Binding { constructor(expression, target, interval) { super(expression, target, true); setInterval(this.check.bind(this), interval); } check() { var newValue = this.getValue(); if (this.lastValue !== newValue) { this.lastValue = newValue; this.emit(Binding.ChangedFieldEventName, { target: this.target, eventArgs: { fieldName: this.expression, value: newValue }, source: this }); } } } exports.WatchBinding = WatchBinding; //# sourceMappingURL=binder.js.map