ajsfw
Version:
Ajs Framework
1,035 lines • 50.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var logger = require("ajsfw/dbg/logger");
var utils = require("ajsfw/utils");
var exceptions = require("./exceptions");
var ViewComponent = (function () {
function ViewComponent(navigator, router, documentManager, templateManager, viewManager, viewComponentManager, id, componentViewId, parentComponent, visualComponent, state, parentComponentInitStateNotify) {
if (visualComponent === null) {
throw new exceptions.VisualComponentNotRegisteredException(null);
}
logger.log(logger.LogType.Constructor, 0, "ajs.mvvm.viewmodel", this);
this._componentViewId = componentViewId;
this.ajs = {
stylesheetsApplied: false,
initialized: false,
id: id,
navigator: navigator,
router: router,
documentManager: documentManager,
templateManager: templateManager,
viewComponentManager: viewComponentManager,
viewManager: viewManager,
parentComponent: parentComponent,
visualComponent: visualComponent,
templateElement: visualComponent.component,
stateToApply: state,
parentComponentInitStateNotify: parentComponentInitStateNotify,
key: null,
stateChanged: false,
stateKeys: [],
stateChangePrevented: false,
stateQueue: [],
processingStateQueue: false,
hasVisualStateTransition: false,
visualStateTransitionRunning: false,
visualStateTransitionBeginHandler: null,
transitionNewElement: null,
transitionOldElement: null,
attributeProcessors: {
__default: this.__attrDefault,
component: this.__attrComponent,
if: this.__attrIf,
onclick: this.__attrEventHandler,
onmousedown: this.__attrEventHandler,
onmouseup: this.__attrEventHandler,
onkeydown: this.__attrEventHandler,
onkeyup: this.__attrEventHandler,
onkeypress: this.__attrEventHandler,
onchange: this.__attrEventHandler,
oninput: this.__attrEventHandler,
ontouchmove_ajs: this.__attrEventHandler,
onanimationend: this.__attrEventHandler,
onstatetransitionbegin: this.__attrTransitionBeginHanler
}
};
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
}
Object.defineProperty(ViewComponent.prototype, "componentViewId", {
get: function () { return this._componentViewId; },
enumerable: true,
configurable: true
});
;
ViewComponent.prototype.configure = function () {
var services = [];
for (var _i = 0; _i < arguments.length; _i++) {
services[_i] = arguments[_i];
}
return this._onConfigure.apply(this, services);
};
ViewComponent.prototype.initialize = function () {
return __awaiter(this, void 0, void 0, function () {
var newState;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
if (!(this.ajs.stateToApply && this.ajs.stateToApply !== null)) return [3, 2];
newState = utils.DeepMerge.merge(this._onDefaultState(), this.ajs.stateToApply);
utils.Obj.assign(this.ajs.stateToApply, newState);
return [4, this.__applyState({
component: this,
stateChangeRoot: this.ajs.parentComponentInitStateNotify,
state: this.ajs.stateToApply
})];
case 1:
_a.sent();
return [3, 4];
case 2: return [4, this.__applyState({
component: this,
stateChangeRoot: this.ajs.parentComponentInitStateNotify || null,
state: this._onDefaultState()
})];
case 3:
_a.sent();
_a.label = 4;
case 4:
this.ajs.parentComponentInitStateNotify = undefined;
this.ajs.stateToApply = undefined;
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2, this.__initialize()];
}
});
});
};
ViewComponent.prototype.destroy = function () {
return this.__destroy();
};
;
ViewComponent.prototype.setState = function (state, stateChangeRootComponent) {
if (stateChangeRootComponent === void 0) { stateChangeRootComponent = null; }
return this.__setState(state, stateChangeRootComponent);
};
ViewComponent.prototype.clearState = function (render) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
this.__clearState(render);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
ViewComponent.prototype.render = function (parentElement, clearStateChangeOnly, attributes) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
var element = this.__render(parentElement, clearStateChangeOnly, attributes);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return element;
};
ViewComponent.prototype.ajsVisualStateTransitionBegin = function (newElement) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
this._ajsVisualStateTransitionBegin(newElement);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
ViewComponent.prototype.insertChildComponent = function (viewComponentName, id, state, placeholder, index) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
this.__insertChildComponent(viewComponentName, id, state, placeholder, index);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
ViewComponent.prototype.removeChildComponent = function (placeholder, id) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
this.__removeChildComponent(placeholder, id);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
Object.defineProperty(ViewComponent.prototype, "preventStateChange", {
set: function (value) {
this._setPreventStateChange(value);
},
enumerable: true,
configurable: true
});
ViewComponent.prototype._onDefaultState = function () {
return {};
};
ViewComponent.prototype._onConfigure = function () {
var params = [];
for (var _i = 0; _i < arguments.length; _i++) {
params[_i] = arguments[_i];
}
return Promise.resolve();
};
ViewComponent.prototype._onInitialize = function () {
return Promise.resolve();
};
ViewComponent.prototype._onFinalize = function () {
return;
};
ViewComponent.prototype._filterState = function (state) {
return state;
};
ViewComponent.prototype._filterStateKey = function (key, value) {
return {
filterApplied: false,
key: null,
state: null
};
};
ViewComponent.prototype._filterStateArrayItem = function (key, index, length, state) {
return {
filterApplied: false,
key: null,
state: null
};
};
ViewComponent.prototype._setPreventStateChange = function (value) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
logger.log(logger.LogType.Info, 0, "ajs.mvvm.viewmodel", this, "Setting prevent state change to " + value +
" (" + utils.getClassName(this) + ", id: " + this.ajs.id, ", viewId: " + this.componentViewId + ")");
this.ajs.stateChangePrevented = value;
var children = this.ajs.viewComponentManager.getChildrenComponentInstances(this);
for (var i = 0; i < children.length; i++) {
children[i].preventStateChange = value;
}
if (!value) {
this.__processStateQueue();
}
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
ViewComponent.prototype._ajsVisualStateTransitionBegin = function (newElement) {
return __awaiter(this, void 0, void 0, function () {
var transitionType;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
if (this.ajs.visualStateTransitionRunning) {
this._ajsVisualStateTransitionCancel();
}
this.ajs.visualStateTransitionRunning = true;
this.ajs.transitionNewElement = newElement;
if (!(typeof this.ajs.visualStateTransitionBeginHandler === "function")) return [3, 2];
return [4, this.ajs.visualStateTransitionBeginHandler.call(this)];
case 1:
transitionType = _a.sent();
if (transitionType !== null) {
this.__ajsVisualStateTransitionStart(transitionType);
}
else {
this._ajsVisualStateTransitionEnd();
}
return [3, 3];
case 2:
this._ajsVisualStateTransitionEnd();
_a.label = 3;
case 3:
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
});
});
};
ViewComponent.prototype._ajsVisualStateTransitionCancel = function () {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
if (this.ajs.transitionNewElement) {
this._ajsVisualStateTransitionEnd();
}
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
ViewComponent.prototype._ajsVisualStateTransitionEnd = function () {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
if (this.ajs.visualStateTransitionRunning &&
this.ajs.transitionOldElement instanceof HTMLElement &&
this.__childElementExists(this.ajs.transitionOldElement.parentElement, this.ajs.transitionOldElement)) {
this.ajs.transitionOldElement.removeAttribute("statetransitiontypeold");
this.ajs.transitionNewElement.removeAttribute("statetransitiontypenew");
}
this.ajs.documentManager.removeNode(this.ajs.transitionOldElement);
this.ajs.transitionOldElement = null;
this.ajs.transitionNewElement = null;
this.ajs.visualStateTransitionRunning = false;
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
ViewComponent.prototype.__initialize = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
return [4, this.__applyTemplateStylesheets()];
case 1:
_a.sent();
return [4, this._onInitialize()];
case 2:
_a.sent();
this.ajs.stateChanged = true;
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
});
});
};
ViewComponent.prototype.__destroy = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
this.clearState(false);
return [4, this._onFinalize()];
case 1:
_a.sent();
this.ajs.documentManager.removeNodeByUniqueId(this.componentViewId);
this.ajs.viewComponentManager.removeComponentInstance(this);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
});
});
};
ViewComponent.prototype.__applyTemplateStylesheets = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
return [4, this.ajs.documentManager.applyStyleSheetsFromTemplate(this.ajs.visualComponent.template)];
case 1:
_a.sent();
this.ajs.stylesheetsApplied = true;
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
});
});
};
ViewComponent.prototype.__setState = function (state, stateChangeRootComponent) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
logger.log(logger.LogType.Info, 0, "ajs.mvvm.viewmodel", this, "Setting component state: " + utils.getClassName(this) + ", id: " + this.ajs.id, ", viewId: " + this.componentViewId, state);
if (this.ajs.visualStateTransitionRunning) {
this._ajsVisualStateTransitionCancel();
}
this.ajs.stateQueue.push({
component: this,
stateChangeRoot: stateChangeRootComponent,
state: state
});
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2, this.__processStateQueue()];
});
});
};
ViewComponent.prototype.__processStateQueue = function () {
return __awaiter(this, void 0, void 0, function () {
var stateInfo, node;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
if (this.ajs.stateQueue.length === 0) {
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
if (this.ajs.processingStateQueue) {
logger.log(logger.LogType.Warning, 0, "ajs.mvvm.viewmodel", this, "Processing state already running!");
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
if (this.ajs.stateChangePrevented) {
logger.log(logger.LogType.Warning, 0, "ajs.mvvm.viewmodel", this, "State change is prevented: " +
utils.getClassName(this) + ", id: " + this.ajs.id, ", viewId: " + this.componentViewId);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
this.ajs.processingStateQueue = true;
logger.log(logger.LogType.Info, 0, "ajs.mvvm.viewmodel", this, "Processing state queue: " +
utils.getClassName(this) + ", id: " + this.ajs.id, ", viewId: " + this.componentViewId + ", " +
this.ajs.stateQueue.length + " state changes queued");
_a.label = 1;
case 1:
if (!(this.ajs.stateQueue.length > 0)) return [3, 3];
if (this.ajs.stateChangePrevented) {
logger.log(logger.LogType.Warning, 0, "ajs.mvvm.viewmodel", this, "State change is prevented: " +
utils.getClassName(this) + ", id: " + this.ajs.id, ", viewId: " + this.componentViewId);
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
stateInfo = this.ajs.stateQueue.shift();
logger.log(logger.LogType.Info, 0, "ajs.mvvm.viewmodel", this, "Setting component state: " +
utils.getClassName(this) + ", id: " + this.ajs.id, ", viewId: " + this.componentViewId + ", " +
this.ajs.stateQueue.length + " state changes queued", stateInfo.state);
if (this.ajs.hasVisualStateTransition) {
node = this.ajs.documentManager.getTargetNodeByUniqueId(this.componentViewId);
this.ajs.transitionOldElement = node.cloneNode(true);
}
this.ajs.viewManager.stateChangeBegin(stateInfo);
return [4, this.__applyState(stateInfo)];
case 2:
_a.sent();
this.ajs.viewManager.stateChangeEnd(stateInfo);
return [3, 1];
case 3:
this.ajs.processingStateQueue = false;
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
});
});
};
ViewComponent.prototype.__clearState = function (render) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
var schi = {
component: this,
stateChangeRoot: null,
state: null
};
if (render) {
this.ajs.viewManager.stateChangeBegin(schi);
}
while (this.ajs.stateKeys.length > 0) {
if (this[this.ajs.stateKeys[0]] instanceof ViewComponent) {
this[this.ajs.stateKeys[0]].destroy();
}
if (this[this.ajs.stateKeys[0]] instanceof Array) {
for (var i = 0; i < this[this.ajs.stateKeys[0]].length; i++) {
if (this[this.ajs.stateKeys[0]][i] instanceof ViewComponent) {
this[this.ajs.stateKeys[0]][i].destroy();
}
}
}
delete (this[this.ajs.stateKeys[0]]);
this.ajs.stateKeys.splice(0, 1);
}
if (render) {
this.ajs.stateChanged = true;
this.ajs.viewManager.stateChangeEnd(schi);
}
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
};
ViewComponent.prototype.__applyState = function (stateChangeInfo) {
return __awaiter(this, void 0, void 0, function () {
var state, _a, _b, _i, key, filteredKey, filteredState;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
state = stateChangeInfo.state;
if (state === undefined || state === null) {
return [2];
}
state = this._filterState(state);
if (state === undefined || state === null) {
return [2];
}
_a = [];
for (_b in state)
_a.push(_b);
_i = 0;
_c.label = 1;
case 1:
if (!(_i < _a.length)) return [3, 6];
key = _a[_i];
if (!state.hasOwnProperty(key)) {
return [3, 5];
}
filteredKey = key;
filteredState = this._filterStateKey(filteredKey, state[filteredKey]);
if (filteredState.filterApplied) {
if (filteredState.key !== key) {
filteredKey = filteredState.key;
delete state[key];
}
state[filteredKey] = filteredState.state;
}
if (!this.hasOwnProperty(filteredKey)) return [3, 3];
return [4, this.__updateExistingStateKey(filteredKey, {
component: stateChangeInfo.component,
stateChangeRoot: stateChangeInfo.stateChangeRoot,
state: state
})];
case 2:
_c.sent();
return [3, 5];
case 3: return [4, this.__createNewStateKey(filteredKey, {
component: stateChangeInfo.component,
stateChangeRoot: stateChangeInfo.stateChangeRoot,
state: state
})];
case 4:
_c.sent();
_c.label = 5;
case 5:
_i++;
return [3, 1];
case 6:
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return [2];
}
});
});
};
ViewComponent.prototype.__createNewStateKey = function (key, stateChangeInfo) {
return __awaiter(this, void 0, void 0, function () {
var state, _a, _b, filteredStates, i, filteredState, filteredState, i, j, c;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
state = stateChangeInfo.state;
if (!this.ajs.visualComponent.children.hasOwnProperty(key)) return [3, 5];
if (!(state[key] instanceof Array)) return [3, 2];
return [4, this.__createComponentsArray(key, stateChangeInfo)];
case 1:
_c.sent();
return [3, 4];
case 2:
_a = this;
_b = key;
return [4, this.__createViewComponent(key, this.ajs.visualComponent.children[key], state[key])];
case 3:
_a[_b] = _c.sent();
this.ajs.stateKeys.push(key);
_c.label = 4;
case 4: return [2];
case 5:
filteredStates = [];
if (state[key] instanceof Array) {
for (i = 0; i < state[key].length; i++) {
filteredState = this._filterStateArrayItem(key, i, state[key].length, state[key][i]);
if (filteredState.filterApplied) {
if (filteredState.key !== key) {
filteredStates.push(filteredState);
}
}
}
}
if (!(filteredStates.length > 0)) return [3, 7];
filteredState = {};
for (i = 0; i < filteredStates.length; i++) {
if (filteredState[filteredStates[i].key] === undefined) {
filteredState[filteredStates[i].key] = [];
}
if (filteredStates[i].state instanceof Array) {
for (j = 0; j < filteredStates[i].state.length; j++) {
filteredState[filteredStates[i].key].push(filteredStates[i].state[j]);
}
}
else {
filteredState[filteredStates[i].key].push(filteredStates[i].state);
}
}
return [4, this.__applyState(filteredState)];
case 6:
_c.sent();
return [2];
case 7:
this[key] = state[key];
this.ajs.stateKeys.push(key);
this.ajs.stateChanged = true;
if (stateChangeInfo.stateChangeRoot !== null) {
c = this;
while (c !== stateChangeInfo.stateChangeRoot) {
c = c.ajs.parentComponent;
c.ajs.stateChanged = true;
}
}
return [2];
}
});
});
};
ViewComponent.prototype.__createComponentsArray = function (key, stateChangeInfo) {
return __awaiter(this, void 0, void 0, function () {
var state, i, filteredState, newViewComponent, j, newViewComponent;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
state = stateChangeInfo.state;
this.ajs.stateKeys.push(key);
this[key] = [];
i = 0;
_a.label = 1;
case 1:
if (!(i < state[key].length)) return [3, 7];
filteredState = this._filterStateArrayItem(key, i, state[key].length, state[key][i]);
if (!(!filteredState.filterApplied || !(filteredState.state instanceof Array))) return [3, 3];
newViewComponent = void 0;
return [4, this.__createViewComponent(key, this.ajs.visualComponent.children[key], filteredState.filterApplied && filteredState.key === key ? filteredState.state : state[key][i])];
case 2:
newViewComponent = _a.sent();
this[key][i] = newViewComponent;
return [3, 6];
case 3:
j = 0;
_a.label = 4;
case 4:
if (!(j < filteredState.state.length)) return [3, 6];
newViewComponent = void 0;
return [4, this.__createViewComponent(key, this.ajs.visualComponent.children[key], filteredState.state[j])];
case 5:
newViewComponent = _a.sent();
if (j === 0) {
this[key][i] = newViewComponent;
return [3, 4];
}
if (i < state[key].length - 1) {
this[key].splice(i + 1, 0, newViewComponent);
}
else {
this[key].push(newViewComponent);
}
i++;
j++;
return [3, 4];
case 6:
i++;
return [3, 1];
case 7: return [2];
}
});
});
};
ViewComponent.prototype.__updateExistingStateKey = function (key, stateChangeInfo) {
return __awaiter(this, void 0, void 0, function () {
var state, c;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
state = stateChangeInfo.state;
if (!(this[key] instanceof ViewComponent)) return [3, 2];
return [4, this[key].setState(state[key], stateChangeInfo.stateChangeRoot !== null ? stateChangeInfo.stateChangeRoot : this)];
case 1:
_a.sent();
return [2];
case 2:
if (!(state[key] instanceof Array &&
this.ajs.visualComponent.children.hasOwnProperty(key) &&
this[key] instanceof Array)) return [3, 4];
return [4, this.__updateArrayState(key, stateChangeInfo)];
case 3:
_a.sent();
return [2];
case 4:
if (this.ajs.stateKeys.indexOf(key) === -1) {
this.ajs.stateKeys.push(key);
}
if (this[key] !== state[key]) {
this[key] = state[key];
this.ajs.stateChanged = true;
if (stateChangeInfo.stateChangeRoot !== null) {
c = this;
while (c !== stateChangeInfo.stateChangeRoot) {
c = c.ajs.parentComponent;
c.ajs.stateChanged = true;
}
}
}
return [2];
}
});
});
};
ViewComponent.prototype.__updateArrayState = function (key, stateChangeInfo) {
return __awaiter(this, void 0, void 0, function () {
var state, i, del, j, c, newViewComponent;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
state = stateChangeInfo.state;
i = 0;
while (i < this[key].length) {
del = true;
for (j = 0; j < state[key].length; j++) {
if (this[key][i].key === state[key][j].key) {
del = false;
break;
}
}
if (!del) {
i++;
continue;
}
this[key][i].destroy();
if (stateChangeInfo.stateChangeRoot !== null) {
c = this;
while (c !== stateChangeInfo.stateChangeRoot) {
c = c.ajs.parentComponent;
c.ajs.stateChanged = true;
}
}
this[key].splice(i, 1);
if (this[key].length === 0) {
this.ajs.stateKeys.splice(this.ajs.stateKeys.indexOf(key), 1);
}
}
if (this.ajs.stateKeys.indexOf(key) === -1) {
this.ajs.stateKeys.push(key);
}
i = 0;
_a.label = 1;
case 1:
if (!(i < state[key].length)) return [3, 6];
if (!(this[key].length > i && this[key][i].key === state[key][i].key)) return [3, 3];
return [4, this[key][i].setState(state[key][i], stateChangeInfo.stateChangeRoot !== null ? stateChangeInfo.stateChangeRoot : this)];
case 2:
_a.sent();
return [3, 5];
case 3: return [4, this.__createViewComponent(key, this.ajs.visualComponent.children[key], state[key][i])];
case 4:
newViewComponent = _a.sent();
this[key].splice(i, 0, newViewComponent);
_a.label = 5;
case 5:
i++;
return [3, 1];
case 6: return [2];
}
});
});
};
ViewComponent.prototype.__createViewComponent = function (id, viewComponentInfo, state) {
var name = viewComponentInfo.tagName;
if (name === "COMPONENT" && viewComponentInfo.nameAttribute) {
name = viewComponentInfo.nameAttribute;
}
return this.ajs.viewComponentManager.createViewComponent(name, id, this, state, this);
};
ViewComponent.prototype.__render = function (parentElement, clearStateChangeOnly, attributes) {
logger.log(logger.LogType.Enter, 0, "ajs.mvvm.viewmodel", this);
var node;
node = this.__renderTree(this.ajs.visualComponent.component, parentElement, clearStateChangeOnly, attributes);
this.ajs.stateChanged = false;
if (clearStateChangeOnly) {
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return null;
}
if (!(node instanceof HTMLElement)) {
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return null;
}
var componentNode = node;
componentNode.ajsData = componentNode.ajsData || {};
componentNode.ajsData.component = this;
componentNode.ajsData.ownerComponent = this;
logger.log(logger.LogType.Exit, 0, "ajs.mvvm.viewmodel", this);
return node;
};
ViewComponent.prototype.__renderTree = function (sourceNode, targetNode, clearStateChangeOnly, attributes) {
var id = null;
if (sourceNode.nodeType === Node.ELEMENT_NODE) {
id = sourceNode.getAttribute("id");
}
if (id !== null && this[id] !== undefined && (this[id] instanceof ViewComponent || this[id] instanceof Array)) {
if (this[id] instanceof ViewComponent) {
this[id].render(targetNode, clearStateChangeOnly, sourceNode.attributes);
}
else {
if (this[id] instanceof Array) {
for (var i = 0; i < this[id].length; i++) {
if (this[id][i] instanceof ViewComponent) {
this[id][i].render(targetNode, clearStateChangeOnly, sourceNode.attributes);
}
}
}
}
}
else {
var addedNode = void 0;
if (clearStateChangeOnly) {
addedNode = null;
}
else {
addedNode = this.__renderNode(sourceNode, targetNode, attributes);
}
var skip = sourceNode === this.ajs.visualComponent.component && !this.ajs.stateChanged;
if (addedNode !== null && skip) {
addedNode.ajsData = addedNode.ajsData || {};
addedNode.ajsData.skipUpdate = true;
}
if (addedNode !== null && !skip) {
for (var i = 0; i < sourceNode.childNodes.length; i++) {
this.__renderTree(sourceNode.childNodes.item(i), addedNode, false);
}
}
else {
for (var i = 0; i < sourceNode.childNodes.length; i++) {
this.__renderTree(sourceNode.childNodes.item(i), null, true);
}
}
return addedNode;
}
};
ViewComponent.prototype.__renderNode = function (sourceNode, targetNode, attributes) {
var clonedNode = sourceNode.cloneNode(false);
var adoptedNode = targetNode.ownerDocument.adoptNode(clonedNode);
if (attributes) {
this.__mergeAttributes(adoptedNode, attributes);
}
var processedNode = this.__processNode(adoptedNode);
if (processedNode && processedNode !== null) {
if (processedNode instanceof HTMLElement) {
processedNode.ajsData = processedNode.ajsData || {};
processedNode.ajsData.ownerComponent = this;
}
targetNode.appendChild(processedNode);
}
return processedNode;
};
ViewComponent.prototype.__mergeAttributes = function (targetNode, attributes) {
if (!(targetNode instanceof Element)) {
return;
}
for (var i = 0; i < attributes.length; i++) {
switch (attributes[i].nodeName.toLowerCase()) {
case "class":
if (targetNode.hasAttribute("class")) {
if (targetNode.getAttribute("class").indexOf(attributes[i].nodeValue) === -1) {
targetNode.setAttribute(attributes[i].nodeName, targetNode.getAttribute("class") + " " + attributes[i].nodeValue);
}
}
else {
targetNode.setAttribute(attributes[i].nodeName, attributes[i].nodeValue);
}
break;
case "id":
break;
default:
targetNode.setAttribute(attributes[i].nodeName, attributes[i].nodeValue);
break;
}
}
};
ViewComponent.prototype.__processNode = function (node) {
switch (node.nodeType) {
case Node.ELEMENT_NODE:
return this.__processElement(node);
case Node.TEXT_NODE:
return this.__processText(node);
default:
return null;
}
};
ViewComponent.prototype.__processText = function (node) {
var props = node.nodeValue.match(/{(.*?)}/g);
if (props !== null) {
for (var i = 0; i < props.length; i++) {
var propName = props[i].substring(1, props[i].length - 1);
if (this[propName] !== undefined && this[propName] !== null) {
node.nodeValue = node.nodeValue.replace(props[i], this[propName]);
}
else {
node.nodeValue = node.nodeValue.replace(props[i], "");
}
}
}
if (node.nodeValue.substr(0, 8) === "#ASHTML:") {
var asHtml = document.createElement("ashtml");
asHtml.innerHTML = node.nodeValue.substr(8);
node = asHtml;
var ahrefs = asHtml.getElementsByTagName("a");
for (var i = 0; i < ahrefs.length; i++) {
this.__processElement(ahrefs.item(i));
}
}
return node;
};
ViewComponent.prototype.__linkMouseDown = function (e) {
e.returnValue = this.ajs.navigator.linkClicked(e);
if (!e.returnValue) {
e.cancelBubble = true;
e.preventDefault();
e.stopPropagation();
}
};
ViewComponent.prototype.__processElement = function (element) {
var _this = this;
element = this.__processAttributes(element);
if (element instanceof HTMLAnchorElement) {
if (element.hasAttribute("href")) {
var href = element.getAttribute("href");
if (href.substr(0, 4) !== "http") {
var domEventListenerInfo = {
source: this.ajs.templateElement,
eventType: "mousedown",
eventListener: function (e) { _this.__linkMouseDown(e); }
};
var node = element;
node.ajsData = node.ajsData || {};
if (!(node.ajsData.eventListeners instanceof Array)) {
node.ajsData.eventListeners = [];
}
node.ajsData.eventListeners.push(domEventListenerInfo);
domEventListenerInfo = {
source: this.ajs.templateElement,
eventType: "click",
eventListener: function (e) {
e.returnValue = false;
e.cancelBubble = true;
e.preventDefault();
e.stopPropagation();
}
};
node.ajsData.eventListeners.push(domEventListenerInfo);
}
}
}
return element;
};
ViewComponent.prototype.__processAttributes = function (element) {
var toRemove = [];
for (var i = 0; i < element.attributes.length; i++) {
if (this.ajs.attributeProcessors[element.attributes[i].nodeName] !== undefined) {
if (!this.ajs.attributeProcessors[element.attributes[i].nodeName].call(this, toRemove, element.attributes[i])) {
return null;
}
}
else {
if (!this.ajs.attributeProcessors.__default.call(this, toRemove, element.attributes[i])) {
return null;
}
}
}
for (var i = 0; i < toRemove.length; i++) {
element.removeAttribute(toRemove[i]);
if (element.hasOwnProperty(toRemove[i])) {
element[toRemove[i]] = null;
}
}
return element;
};
ViewComponent.prototype.__attrComponent = function (toRemove, attr) {
toRemove.push(attr.nodeName);
return true;
};
ViewComponent.prototype.__attrIf = function (toRemove, attr) {
var condition = attr.nodeValue;
try {
if (!eval(condition)) {
return false;
}
}
catch (e) {
throw new exceptions.InvalidAttributeIfValueException(e);
}
toRemove.push(attr.nodeName);
return true;
};
ViewComponent.prototype.__attrDefault = function (toRemove, attr) {
var props = attr.nodeValue.match(/{(.*?)}/);
if (props !== null) {
var propName = props[1];
if (this[propName] !== undefined && this[propName] !== null) {
attr.nodeValue = attr.nodeValue.replace(props[0], this[propName]);
}
else {
toRemove.push(attr.nodeName);
}
}
return true;
};
ViewComponent.prototype.__attrEventHandler = function (toRemove, attr) {
var _this = this;
toRemove.push(attr.nodeName);
if ((this[attr.nodeValue] !== undefined && typeof this[attr.nodeValue] === "function") ||
(this["_" + attr.nodeValue] !== undefined && typeof this["_" + attr.nodeValue] === "function") ||
(this["__" + attr.nodeValue] !== undefined && typeof this["__" + attr.nodeValue] === "function")) {
var eventType = attr.nodeName.substring(2);
if (eventType.indexOf("_ajs") !== -1) {
eventType = eventType.substr(0, eventType.indexOf("_ajs"));
}
var eventHandlerName_1 = attr.nodeValue;
if (!(this[attr.nodeValue] !== undefined && typeof this[attr.nodeValue] === "function")) {
if ((this["_" + attr.nodeValue] !== undefined && typeof this["_" + attr.nodeValue] === "function")) {
eventHandlerName_1 = "_" + eventHandlerName_1;
}
else {
eventHandlerName_1 = "__" + eventHandlerName_1;
}
}
var listener = function (e) {
_this[eventHandlerName_1](e);
};
var domEventListenerInfo = {
source: this.ajs.templateElement,
eventType: eventType,
eventListener: listener
};
var node = attr.ownerElement;
node.ajsData = node.ajsData || {};
if (!(node.ajsData.eventListeners instanceof Array)) {
node.ajsData.eventListeners = [];
}
node.ajsData.eventListeners.push(domEventListenerInfo);
}
return true;
};
ViewComponent.prototype.__attrTransitionBeginHanler = function (toRemove, attr) {
if (this[attr.nodeValue] !== undefined && typeof this[attr.nodeValue] === "function") {
this.ajs.hasVisualStateTransition = true;
this.ajs.visualStateTransitionBeginHandler = this[attr.nodeValue];
}
toRemove.push(attr.nodeName);
return true;
};
ViewComponent.prototype.__insertChildComponent = function (viewComponentName, id, state, placeholder, index) {
if (state === null) {
state = {};
}
var visualComponent;
visualComponent = this.ajs.templateManager.getVisualComponent(viewComponentName);
if (visualComponent === null) {
throw new exceptions.VisualComponentNotRegisteredException(viewComponentName);
}
this.__visualComponentInsertChild(placeholder, viewComponentName, id, index);
var thisState = {};
thisState[id] = state;
this.setState(thisState, this);
};
ViewComponent.prototype.__removeChildComponent = function (placeholder, id) {
if (this.hasOwnProperty(id) && this[id] instanceof ViewComponent) {
this.__visualComponentRemoveChild(placeholder, id);
this[id]._destroy();
delete this[id];
var i = this.ajs.stateKeys.indexOf(id);
if (i !== -1) {
this.ajs.stateKeys.splice(i, 1);
}
}
};
ViewComponent.prototype.__visualComponentInsertChild = function (placeholder, componentName, id, index) {
if (this.ajs.visualComponent.placeholders.hasOwnProperty(placeholder)) {
var ph = this.ajs.visualComponent.placeholders[placeholder].placeholder;
var vc = ph.ownerDocument.createElement(componentName);
vc.setAttribute("id", id);
if (index !== undefined) {
}
else {
ph.appendChild(vc);
}
this.ajs.visualComponent.children[id] = {
tagName: componentName,
nameAttribute: null
};
}
};
ViewComponent.prototype.__visualComponentRemoveChild = function (placeholder, id) {
if (this.ajs.visualComponent.placeholders.hasOwnProperty(placeholder)) {
var ph = this.ajs.visualComponent.placeholders[placeholder].placeholder;
var vc = null;
for (var i = 0; i < ph.childElementCount; i++) {
if (ph.children.item(i).hasAttribute("id") && ph.children.item(i).getAttribute("id") === id) {
vc = ph.children.item(i);
break;
}
}
if (vc !== null) {
ph.removeChild(vc);
delete this.ajs.visualComponent.children[id];
}
}
};
ViewComponent.prototype.__ajsVisualStateTransitionStart = function (transitionType) {
if (this.ajs.transitionOldElement instanceof HTMLElement &&
this.ajs.transitionNewElement instanceof HTMLElement) {
this.ajs.transitionNewElement.parentElement.insertBefore(this.ajs.transitionOldElement, this.ajs.transitionNewElement);
this.ajs.transitionOldElement.setAttribute("statetransitiontypeold", transitionType.oldComponent);
this.ajs.transitionNewElement.setAttribute("statetransitiontypenew", transitionType.newComponent);
}
};
ViewComponent.prototype.__childElementExists = function (