UNPKG

@web-atoms/core

Version:
559 lines (558 loc) • 19.4 kB
System.register(["tslib", "../App", "../core/types", "../di/Inject", "./AtomDisposableList", "./AtomWatcher", "./Bind", "./Hacks", "./InheritedProperty", "./PropertyMap", "./XNode"], function (_export, _context) { "use strict"; var __decorate, __metadata, __param, App, ArrayHelper, CancelToken, ignoreValue, Inject, AtomDisposableList, AtomWatcher, bindSymbol, visitDescendents, watchProperty, InheritedProperty, PropertyMap, isControl, isFactorySymbol, xnodeSymbol, PropertyBinding, _a, _b, localBindSymbol, localXNodeSymbol, AtomComponent; _export("PropertyBinding", void 0); return { setters: [function (_tslib) { __decorate = _tslib.__decorate; __metadata = _tslib.__metadata; __param = _tslib.__param; }, function (_App) { App = _App.App; }, function (_coreTypes) { ArrayHelper = _coreTypes.ArrayHelper; CancelToken = _coreTypes.CancelToken; ignoreValue = _coreTypes.ignoreValue; }, function (_diInject) { Inject = _diInject.Inject; }, function (_AtomDisposableList) { AtomDisposableList = _AtomDisposableList.AtomDisposableList; }, function (_AtomWatcher) { AtomWatcher = _AtomWatcher.AtomWatcher; }, function (_Bind) { bindSymbol = _Bind.bindSymbol; }, function (_Hacks) { visitDescendents = _Hacks.visitDescendents; watchProperty = _Hacks.watchProperty; }, function (_InheritedProperty) { InheritedProperty = _InheritedProperty.InheritedProperty; }, function (_PropertyMap) { PropertyMap = _PropertyMap.PropertyMap; }, function (_XNode) { isControl = _XNode.isControl; isFactorySymbol = _XNode.isFactorySymbol; xnodeSymbol = _XNode.xnodeSymbol; }], execute: function () { localBindSymbol = bindSymbol; localXNodeSymbol = xnodeSymbol; _export("AtomComponent", AtomComponent = class AtomComponent { get vsProps() { return undefined; } constructor(app, element = null) { this.app = app; this.mInvalidated = 0; this.mPendingPromises = {}; this.disposables = new AtomDisposableList(); this.bindings = []; this.eventHandlers = []; this.element = element; this.element.atomControl = this; const a = this.beginEdit(); this.preCreate(); this.create(); app.callLater(() => a.dispose()); } bind(element, name, path, twoWays, valueFunc, source) { const binding = new PropertyBinding(this, element, name, path, twoWays, valueFunc, source); this.bindings.push(binding); return { dispose: () => { binding.dispose(); ArrayHelper.remove(this.bindings, x => x === binding); } }; } unbind(element, name) { const toDelete = this.bindings.filter(x => x.element === element && (!name || x.name === name)); for (const iterator of toDelete) { iterator.dispose(); ArrayHelper.remove(this.bindings, x => x === iterator); } } bindEvent(element, name, method, key, capture) { if (!element) { return; } if (!method) { return; } const be = { element, name, handler: method }; if (key) { be.key = key; } const handler = e => { var _c; try { let r = method(e); e.executed = true; if (r) { const originalReturn = r; r = r.then ? r : Promise.resolve(r); e.promise = e.promise ? e.promise.then(() => r) : r; if (originalReturn.catch) { return originalReturn.catch(c => { var _c; if (CancelToken.isCancelled(c !== null && c !== void 0 ? c : "Unknown error")) { return; } alert((_c = c.stack) !== null && _c !== void 0 ? _c : c); }); } return r; } } catch (error) { if (CancelToken.isCancelled(error)) { return; } alert((_c = error.stack) !== null && _c !== void 0 ? _c : error); } }; element.addEventListener(name, handler, capture); be.disposable = { dispose: () => { element.removeEventListener(name, handler, capture); be.disposable.dispose = () => undefined; } }; this.eventHandlers.push(be); return { dispose: () => { be.disposable.dispose(); ArrayHelper.remove(this.eventHandlers, e => e.disposable === be.disposable); } }; } unbindEvent(element, name, method, key) { const deleted = []; for (const be of this.eventHandlers) { if (element && be.element !== element) { return; } if (key && be.key !== key) { return; } if (name && be.name !== name) { return; } if (method && be.handler !== method) { return; } be.disposable.dispose(); be.handler = null; be.element = null; be.name = null; be.key = null; deleted.push(() => this.eventHandlers.remove(be)); } for (const iterator of deleted) { iterator(); } } hasProperty(name) { if (/^(data|viewModel|localViewModel|element)$/.test(name)) { return true; } const map = PropertyMap.from(this); if (map.map[name]) { return true; } if (this[name] !== undefined) { return true; } return false; } setPrimitiveValue(element, name, value) { const p = value; if (p && p.then && p.catch) { console.warn(`Do not bind promises, instead use Bind.oneWayAsync`); this.mPendingPromises[name] = p; p.then(r => { if (this.mPendingPromises[name] !== p) { return; } this.mPendingPromises[name] = null; this.setPrimitiveValue(element, name, r); }).catch(e => { if (this.mPendingPromises[name] !== p) { return; } this.mPendingPromises[name] = null; console.error(e); }); return; } if (/^(viewModel|localViewModel)$/.test(name)) { this[name] = value; return; } if ((!element || element === this.element) && this.hasProperty(name)) { this.runAfterInit(() => { this[name] = value; }); } else { this.setElementValue(element, name, value); } } setLocalValue(element, name, value) { const p = value; if (p && p.then && p.catch) { console.warn(`Do not bind promises, instead use Bind.oneWayAsync`); this.mPendingPromises[name] = p; p.then(r => { if (this.mPendingPromises[name] !== p) { return; } this.mPendingPromises[name] = null; this.setLocalValue(element, name, r); }).catch(e => { if (this.mPendingPromises[name] !== p) { return; } this.mPendingPromises[name] = null; console.error(e); }); return; } if ((!element || element === this.element) && Reflect.has(this, name)) { this[name] = value; } else { this.setElementValue(element, name, value); } } dispose(e) { if (this.mInvalidated) { clearTimeout(this.mInvalidated); this.mInvalidated = 0; } visitDescendents(e || this.element, (ex, ac) => { if (ac) { ac.dispose(); return false; } return true; }); if (!e) { this.unbindEvent(null, null, null); for (const binding of this.bindings) { binding.dispose(); } this.bindings.length = 0; this.bindings = null; const e1 = this.element; if (typeof e1.dispose === "function") { e1.dispose(); } this.element = null; const lvm = this.localViewModel; if (lvm && lvm.dispose) { lvm.dispose(); this.localViewModel = null; } const vm = this.viewModel; if (vm && vm.dispose) { vm.dispose(); this.viewModel = null; } this.disposables.dispose(); this.pendingInits = null; } } onPropertyChanged(name) {} beginEdit() { this.pendingInits = []; const a = this.pendingInits; return { dispose: () => { if (this.pendingInits == null) { return; } this.pendingInits = null; if (a) { for (const iterator of a) { iterator(); } } this.invalidate(); } }; } invalidate() { if (this.mInvalidated) { clearTimeout(this.mInvalidated); } this.mInvalidated = setTimeout(() => { this.mInvalidated = 0; this.app.callLater(() => { this.onUpdateUI(); }); }, 5); } onUpdateUI() {} runAfterInit(f) { if (this.pendingInits) { this.pendingInits.push(f); } else { f(); } } registerDisposable(d) { return this.disposables.add(d); } render(node, e = this.element, creator = this.creator || this) { const app = this.app; const attr = node.attributes; if (attr) { for (const key in attr) { if (attr.hasOwnProperty(key)) { const item = attr[key]; const isObject = typeof item === "object"; if (isObject && item !== null) { const localSymbol = item[localBindSymbol]; if (localSymbol) { localSymbol(key, this, e, creator); continue; } const localXNode = item[localXNodeSymbol]; if (localXNode) { if (item.isTemplate) { this.setLocalValue(e, key, this.toTemplate(app, item, creator)); continue; } this.setLocalValue(e, key, this.createNode(app, null, item, creator)); continue; } } this.setLocalValue(e, key, item); } } } const children = node.children; if (children === void 0) { return; } for (const iterator of children) { if (!iterator) { continue; } if (!iterator[localXNodeSymbol]) { e.appendChild(document.createTextNode(iterator.toString())); continue; } if (iterator.isProperty) { if (iterator.isTemplate) { this.setLocalValue(e, iterator.name, this.toTemplate(app, iterator.children[0], creator)); continue; } this.createNode(app, e, iterator, creator); continue; } const t = iterator.attributes && iterator.attributes.template; if (t) { console.warn(`This path is deprecated, check who is calling it.`); this.setLocalValue(e, t, this.toTemplate(app, iterator, creator)); continue; } this.createNode(app, e, iterator, creator); } } extractControlProperties(x, name = "div") { const a = x.attributes; const extracted = {}; if (typeof x.name === "function" && this instanceof x.name) { x.name = name; } if (a) { for (const key in a) { if (Object.prototype.hasOwnProperty.call(a, key)) { if (Reflect.has(this, key)) { const element = a[key]; extracted[key] = element; delete a[key]; } } } } return extracted; } create() {} preCreate() {} setElementValue(element, name, value) { element[name] = value; } resolve(c, selfName) { const result = this.app.resolve(c, true); if (selfName) { if (typeof selfName === "function") { this.runAfterInit(() => { const v = selfName(); if (v) { for (const key in v) { if (v.hasOwnProperty(key)) { const element = v[key]; result[key] = element; } } } }); } else { result[selfName] = this; } } return result; } pushInit() { this.runAfterInit(() => { var _c, _d, _e; (_e = (_d = (_c = this).init) === null || _d === void 0 ? void 0 : _d.call(_c)) === null || _e === void 0 ? void 0 : _e.catch(error => CancelToken.isCancelled(error) ? void 0 : console.error(error)); }); } }); _a = isControl; _b = isFactorySymbol; AtomComponent[_a] = true; AtomComponent[_b] = true; __decorate([InheritedProperty, __metadata("design:type", Object)], AtomComponent.prototype, "data", void 0); __decorate([InheritedProperty, __metadata("design:type", Object)], AtomComponent.prototype, "viewModel", void 0); __decorate([InheritedProperty, __metadata("design:type", Object)], AtomComponent.prototype, "localViewModel", void 0); _export("AtomComponent", AtomComponent = __decorate([__param(0, Inject), __metadata("design:paramtypes", [App, Object])], AtomComponent)); _export("PropertyBinding", PropertyBinding = class PropertyBinding { constructor(target, element, name, path, twoWays, valueFunc, source) { this.target = target; this.element = element; this.name = name; this.twoWays = twoWays; this.source = source; this.isTwoWaySetup = false; this.name = name; this.twoWays = twoWays; this.target = target; this.element = element; this.isRunning = false; if (valueFunc) { if (typeof valueFunc !== "function") { this.fromSourceToTarget = valueFunc.fromSource; this.fromTargetToSource = valueFunc.fromTarget; } else { this.fromSourceToTarget = valueFunc; } } this.watcher = new AtomWatcher(target, path, (...v) => { if (this.isRunning) { return; } if (this.disposed) { return; } for (const iterator of v) { if (iterator === undefined) { return; } } const cv = this.fromSourceToTarget ? this.fromSourceToTarget.apply(this, v) : v[0]; if (cv === ignoreValue) { return; } this.isRunning = true; try { if (this.target instanceof AtomComponent) { this.target.setLocalValue(this.element, this.name, cv); } else { this.target[name] = cv; } } finally { this.isRunning = false; } }, source); this.path = this.watcher.path; if (this.target instanceof AtomComponent) { this.target.runAfterInit(() => { if (!this.watcher) { return; } this.watcher.init(true); if (twoWays) { this.setupTwoWayBinding(); } }); } else { this.watcher.init(true); if (twoWays) { this.setupTwoWayBinding(); } } } setupTwoWayBinding() { if (this.target instanceof AtomComponent) { if (this.element && (this.element !== this.target.element || !this.target.hasProperty(this.name))) { let events = []; if (typeof this.twoWays !== "boolean") { events = this.twoWays; } this.twoWaysDisposable = watchProperty(this.element, this.name, events, v => { this.setInverseValue(v); }); return; } } const watcher = new AtomWatcher(this.target, [[this.name]], (...values) => { if (this.isTwoWaySetup) { this.setInverseValue(values[0]); } }); watcher.init(true); this.isTwoWaySetup = true; this.twoWaysDisposable = watcher; } setInverseValue(value) { if (!this.twoWays) { throw new Error("This Binding is not two ways."); } if (this.disposed) { return; } if (this.isRunning) { return; } this.isRunning = true; try { const first = this.path[0]; const length = first.length; let v = this.target; let i = 0; let name; for (i = 0; i < length - 1; i++) { name = first[i].name; if (name === "this") { v = this.source || this.target; } else { v = v[name]; } if (!v) { return; } } name = first[i].name; v[name] = this.fromTargetToSource ? this.fromTargetToSource.call(this, value) : value; } finally { this.isRunning = false; } } dispose() { var _c; (_c = this.twoWaysDisposable) === null || _c === void 0 ? void 0 : _c.dispose(); this.twoWaysDisposable = undefined; this.watcher.dispose(); this.disposed = true; this.watcher = null; } }); } }; }); //# sourceMappingURL=AtomComponent.js.map