web-atoms-core
Version:
500 lines • 20.7 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "../App", "../core/AtomBridge", "../core/PropertyBinding", "../core/PropertyMap", "../core/types", "../di/Inject", "./AtomDisposableList", "./Bind", "./XNode"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var App_1 = require("../App");
var AtomBridge_1 = require("../core/AtomBridge");
var PropertyBinding_1 = require("../core/PropertyBinding");
var PropertyMap_1 = require("../core/PropertyMap");
// tslint:disable-next-line:import-spacing
var types_1 = require("../core/types");
var Inject_1 = require("../di/Inject");
var AtomDisposableList_1 = require("./AtomDisposableList");
var Bind_1 = require("./Bind");
var XNode_1 = require("./XNode");
var AtomComponent = /** @class */ (function () {
function AtomComponent(app, element) {
if (element === void 0) { element = null; }
this.app = app;
this.mInvalidated = 0;
this.mPendingPromises = {};
this.mData = undefined;
this.mViewModel = undefined;
this.mLocalViewModel = undefined;
this.disposables = new AtomDisposableList_1.AtomDisposableList();
this.bindings = [];
this.eventHandlers = [];
this.element = element;
AtomBridge_1.AtomBridge.instance.attachControl(this.element, this);
var a = this.beginEdit();
this.preCreate();
this.create();
app.callLater(function () { return a.dispose(); });
}
Object.defineProperty(AtomComponent.prototype, "data", {
get: function () {
if (this.mData !== undefined) {
return this.mData;
}
var parent = this.parent;
if (parent) {
return parent.data;
}
return undefined;
},
set: function (v) {
this.mData = v;
AtomBridge_1.AtomBridge.refreshInherited(this, "data");
},
enumerable: true,
configurable: true
});
Object.defineProperty(AtomComponent.prototype, "viewModel", {
get: function () {
if (this.mViewModel !== undefined) {
return this.mViewModel;
}
var parent = this.parent;
if (parent) {
return parent.viewModel;
}
return undefined;
},
set: function (v) {
var old = this.mViewModel;
if (old && old.dispose) {
old.dispose();
}
this.mViewModel = v;
AtomBridge_1.AtomBridge.refreshInherited(this, "viewModel");
},
enumerable: true,
configurable: true
});
Object.defineProperty(AtomComponent.prototype, "localViewModel", {
get: function () {
if (this.mLocalViewModel !== undefined) {
return this.mLocalViewModel;
}
var parent = this.parent;
if (parent) {
return parent.localViewModel;
}
return undefined;
},
set: function (v) {
var old = this.mLocalViewModel;
if (old && old.dispose) {
old.dispose();
}
this.mLocalViewModel = v;
AtomBridge_1.AtomBridge.refreshInherited(this, "localViewModel");
},
enumerable: true,
configurable: true
});
Object.defineProperty(AtomComponent.prototype, "vsProps", {
/** Do not ever use, only available as intellisense feature for
* vs code editor.
*/
get: function () {
return undefined;
},
enumerable: true,
configurable: true
});
AtomComponent.prototype.bind = function (element, name, path, twoWays, valueFunc, source) {
var _this = this;
// remove existing binding if any
var binding = this.bindings.find(function (x) { return x.name === name && (element ? x.element === element : true); });
if (binding) {
binding.dispose();
types_1.ArrayHelper.remove(this.bindings, function (x) { return x === binding; });
}
binding = new PropertyBinding_1.PropertyBinding(this, element, name, path, twoWays, valueFunc, source);
this.bindings.push(binding);
return {
dispose: function () {
binding.dispose();
types_1.ArrayHelper.remove(_this.bindings, function (x) { return x === binding; });
}
};
};
/**
* Remove all bindings associated with given element and optional name
* @param element T
* @param name string
*/
AtomComponent.prototype.unbind = function (element, name) {
var toDelete = this.bindings.filter(function (x) { return x.element === element && (!name || (x.name === name)); });
var _loop_1 = function (iterator) {
iterator.dispose();
types_1.ArrayHelper.remove(this_1.bindings, function (x) { return x === iterator; });
};
var this_1 = this;
for (var _i = 0, toDelete_1 = toDelete; _i < toDelete_1.length; _i++) {
var iterator = toDelete_1[_i];
_loop_1(iterator);
}
};
AtomComponent.prototype.bindEvent = function (element, name, method, key) {
var _this = this;
if (!element) {
return;
}
if (!method) {
return;
}
var be = {
element: element,
name: name,
handler: method
};
if (key) {
be.key = key;
}
be.disposable = AtomBridge_1.AtomBridge.instance.addEventHandler(element, name, method, false);
this.eventHandlers.push(be);
return {
dispose: function () {
be.disposable.dispose();
types_1.ArrayHelper.remove(_this.eventHandlers, function (e) { return e.disposable === be.disposable; });
}
};
};
AtomComponent.prototype.unbindEvent = function (element, name, method, key) {
var _this = this;
var deleted = [];
var _loop_2 = function (be) {
if (element && be.element !== element) {
return { value: void 0 };
}
if (key && be.key !== key) {
return { value: void 0 };
}
if (name && be.name !== name) {
return { value: void 0 };
}
if (method && be.handler !== method) {
return { value: void 0 };
}
be.disposable.dispose();
be.handler = null;
be.element = null;
be.name = null;
be.key = null;
deleted.push(function () { return _this.eventHandlers.remove(be); });
};
for (var _i = 0, _a = this.eventHandlers; _i < _a.length; _i++) {
var be = _a[_i];
var state_1 = _loop_2(be);
if (typeof state_1 === "object")
return state_1.value;
}
for (var _b = 0, deleted_1 = deleted; _b < deleted_1.length; _b++) {
var iterator = deleted_1[_b];
iterator();
}
};
AtomComponent.prototype.hasProperty = function (name) {
if (this[name] !== undefined) {
return true;
}
var map = PropertyMap_1.PropertyMap.from(this);
return map.map[name];
};
/**
* Use this method if you want to set attribute on HTMLElement immediately but
* defer atom control property
* @param element HTMLElement
* @param name string
* @param value any
*/
AtomComponent.prototype.setPrimitiveValue = function (element, name, value) {
var _this = this;
var p = value;
if (p && p.then && p.catch) {
this.mPendingPromises[name] = p;
p.then(function (r) {
if (_this.mPendingPromises[name] !== p) {
return;
}
_this.mPendingPromises[name] = null;
_this.setPrimitiveValue(element, name, r);
}).catch(function (e) {
if (_this.mPendingPromises[name] !== p) {
return;
}
_this.mPendingPromises[name] = null;
// tslint:disable-next-line:no-console
console.error(e);
});
return;
}
if (/^(viewModel|localViewModel)$/.test(name)) {
this[name] = value;
return;
}
if ((!element || element === this.element) && this.hasProperty(name)) {
this.runAfterInit(function () {
_this[name] = value;
});
}
else {
this.setElementValue(element, name, value);
}
};
AtomComponent.prototype.setLocalValue = function (element, name, value) {
var _this = this;
// if value is a promise
var p = value;
if (p && p.then && p.catch) {
this.mPendingPromises[name] = p;
p.then(function (r) {
if (_this.mPendingPromises[name] !== p) {
return;
}
_this.mPendingPromises[name] = null;
_this.setLocalValue(element, name, r);
}).catch(function (e) {
if (_this.mPendingPromises[name] !== p) {
return;
}
_this.mPendingPromises[name] = null;
// tslint:disable-next-line:no-console
console.error(e);
});
return;
}
if ((!element || element === this.element) && this.hasProperty(name)) {
this[name] = value;
}
else {
this.setElementValue(element, name, value);
}
};
AtomComponent.prototype.dispose = function (e) {
if (this.mInvalidated) {
clearTimeout(this.mInvalidated);
this.mInvalidated = 0;
}
AtomBridge_1.AtomBridge.instance.visitDescendents(e || this.element, function (ex, ac) {
if (ac) {
ac.dispose();
return false;
}
return true;
});
if (!e) {
this.unbindEvent(null, null, null);
for (var _i = 0, _a = this.bindings; _i < _a.length; _i++) {
var binding = _a[_i];
binding.dispose();
}
this.bindings.length = 0;
this.bindings = null;
AtomBridge_1.AtomBridge.instance.dispose(this.element);
this.element = null;
var lvm = this.mLocalViewModel;
if (lvm && lvm.dispose) {
lvm.dispose();
this.mLocalViewModel = null;
}
var vm = this.mViewModel;
if (vm && vm.dispose) {
vm.dispose();
this.mViewModel = null;
}
this.disposables.dispose();
this.pendingInits = null;
}
};
// tslint:disable-next-line:no-empty
AtomComponent.prototype.onPropertyChanged = function (name) {
};
AtomComponent.prototype.beginEdit = function () {
var _this = this;
this.pendingInits = [];
var a = this.pendingInits;
return {
dispose: function () {
if (_this.pendingInits == null) {
// case where current control is disposed...
return;
}
_this.pendingInits = null;
if (a) {
for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
var iterator = a_1[_i];
iterator();
}
}
_this.invalidate();
}
};
};
AtomComponent.prototype.invalidate = function () {
var _this = this;
if (this.mInvalidated) {
clearTimeout(this.mInvalidated);
}
this.mInvalidated = setTimeout(function () {
_this.mInvalidated = 0;
_this.app.callLater(function () {
_this.onUpdateUI();
});
}, 5);
};
AtomComponent.prototype.onUpdateUI = function () {
// for implementors..
};
AtomComponent.prototype.runAfterInit = function (f) {
if (this.pendingInits) {
this.pendingInits.push(f);
}
else {
f();
}
};
AtomComponent.prototype.registerDisposable = function (d) {
return this.disposables.add(d);
};
AtomComponent.prototype.render = function (node, e, creator) {
creator = creator || this;
var bridge = AtomBridge_1.AtomBridge.instance;
var app = this.app;
var renderFirst = AtomBridge_1.AtomBridge.platform === "xf";
e = e || this.element;
var attr = node.attributes;
if (attr) {
for (var key in attr) {
if (attr.hasOwnProperty(key)) {
var item = attr[key];
if (item instanceof Bind_1.default) {
item.setupFunction(key, item, this, e, creator);
}
else if (item instanceof XNode_1.default) {
// this is template..
if (item.isTemplate) {
this.setLocalValue(e, key, AtomBridge_1.AtomBridge.toTemplate(app, item, creator));
}
else {
var child = AtomBridge_1.AtomBridge.createNode(item, app);
this.setLocalValue(e, key, child.element);
}
}
else {
this.setLocalValue(e, key, item);
}
}
}
}
for (var _i = 0, _a = node.children; _i < _a.length; _i++) {
var iterator = _a[_i];
if (typeof iterator === "string") {
e.appendChild(document.createTextNode(iterator));
continue;
}
if (iterator.isTemplate) {
if (iterator.isProperty) {
this.setLocalValue(e, iterator.name, AtomBridge_1.AtomBridge.toTemplate(app, iterator.children[0], creator));
}
else {
e.appendChild(AtomBridge_1.AtomBridge.toTemplate(app, iterator, creator));
}
continue;
}
if (iterator.isProperty) {
for (var _b = 0, _c = iterator.children; _b < _c.length; _b++) {
var child = _c[_b];
var pc = AtomBridge_1.AtomBridge.createNode(child, app);
(pc.control || this).render(child, pc.element, creator);
// in Xamarin.Forms certain properties are required to be
// set in advance, so we append the element after setting
// all children properties
bridge.append(e, iterator.name, pc.element);
}
continue;
}
var t = iterator.attributes && iterator.attributes.template;
if (t) {
this.setLocalValue(e, t, AtomBridge_1.AtomBridge.toTemplate(app, iterator, creator));
continue;
}
var c = AtomBridge_1.AtomBridge.createNode(iterator, app);
if (renderFirst) {
(c.control || this).render(iterator, c.element, creator);
}
if (this.element === e) {
this.append(c.control || c.element);
}
else {
e.appendChild(c.element);
}
if (!renderFirst) {
(c.control || this).render(iterator, c.element, creator);
}
}
};
// tslint:disable-next-line:no-empty
AtomComponent.prototype.create = function () {
};
// tslint:disable-next-line:no-empty
AtomComponent.prototype.preCreate = function () {
};
AtomComponent.prototype.setElementValue = function (element, name, value) {
AtomBridge_1.AtomBridge.instance.setValue(element, name, value);
};
AtomComponent.prototype.resolve = function (c, selfName) {
var result = this.app.resolve(c, true);
if (selfName) {
if (typeof selfName === "function") {
// this is required as parent is not available
// in items control so binding becomes difficult
this.runAfterInit(function () {
var v = selfName();
if (v) {
for (var key in v) {
if (v.hasOwnProperty(key)) {
var element = v[key];
result[key] = element;
}
}
}
});
}
else {
result[selfName] = this;
}
}
return result;
};
AtomComponent.isControl = true;
AtomComponent = __decorate([
__param(0, Inject_1.Inject),
__metadata("design:paramtypes", [App_1.App, Object])
], AtomComponent);
return AtomComponent;
}());
exports.AtomComponent = AtomComponent;
});
//# sourceMappingURL=AtomComponent.js.map