@dooboostore/dom-render
Version:
html view template engine
477 lines • 24.1 kB
JavaScript
var _a;
import { ScriptUtils } from '@dooboostore/core-web/script/ScriptUtils';
import { DomUtils } from '@dooboostore/core-web/dom/DomUtils';
import { Range } from '../iterators/Range';
import { DomRenderFinalProxy } from '../types/Types';
export class EventManager {
constructor() {
this.eventNames = [
'click', 'mousedown', 'mouseup', 'dblclick', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'contextmenu',
'keyup', 'keydown', 'keypress', 'toggle',
'change', 'input', 'submit', 'resize', 'focus', 'blur',
'close', 'cancel' // dialog cancel 이벤트는 close 이벤트의 하위 이벤트로, ESC 키나 취소 버튼으로 닫힐 때만 발생. (close// 추가 로직 (예: 닫힘 후 처리))
/*
close 이벤트: <dialog>가 닫힐 때 발생. 사용자가 취소 버튼, 확인 버튼, 또는 dialog.close() 메서드로 닫을 때 모두 트리거됩니다.
cancel 이벤트: <dialog>가 ESC 키나 취소 버튼으로 닫힐 때 발생. close 이벤트의 하위 이벤트로 볼 수 있습니다.
*/
];
this.bindScript = `
const ${_a.VALUE_VARNAME} = this.__render.value;
const ${_a.SCRIPTS_VARNAME} = this.__render.scripts;
const ${_a.RANGE_VARNAME} = this.__render.range;
const ${_a.ROUTER_VARNAME} = this.__render.router;
const ${_a.ATTRIBUTE_VARNAME} = this.__render.attribute;
const ${_a.ELEMENT_VARNAME} = this.__render.element;
const ${_a.COMPONENT_VARNAME} = this.__render.element.component;
const ${_a.TARGET_VARNAME} = this.__render.target;
const ${_a.EVENT_VARNAME} = this.__render.event;
`;
this.eventNames.forEach(it => {
_a.attrNames.push(_a.attrPrefix + 'event-' + it);
});
_a.attrNames.push(_a.onRenderedInitAttrName);
if (typeof window !== 'undefined') {
_a.WINDOW_EVENTS.forEach(eventName => {
window === null || window === void 0 ? void 0 : window.addEventListener(eventName, (event) => {
const targetAttr = `dr-window-event-${eventName}`;
document.querySelectorAll(`[${targetAttr}]`).forEach(it => {
var _b;
const script = it.getAttribute(targetAttr);
if (script) {
const obj = it.obj;
const config = (_b = obj === null || obj === void 0 ? void 0 : obj._DomRender_proxy) === null || _b === void 0 ? void 0 : _b.config;
ScriptUtils.eval(`${this.bindScript} ${script} `, Object.assign(obj, {
__render: Object.freeze({
target: DomRenderFinalProxy.final(event.target),
element: it,
event: event,
range: Range.range,
scripts: _a.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj)
// ...EventManager.eventVariables
})
}));
}
});
});
});
}
}
// // 순환참조때문에 우선 여기에 뺴놓는다.
// public DomrenderProxyFinal(obj: any) {
// (obj as any)._DomRender_isFinal = true;
// return obj;
// }
// 중요 이벤트에 대상이될 Elements를 찾는다.
findAttrElements(fragment, config) {
var _b, _c;
// const datas: {name: string, value: string | null, element: Element}[] = [];
const elements = new Set();
const addAttributes = (_c = (_b = config === null || config === void 0 ? void 0 : config.applyEvents) === null || _b === void 0 ? void 0 : _b.map(it => it.attrName)) !== null && _c !== void 0 ? _c : [];
addAttributes.concat([..._a.attrNames]).forEach(attrName => {
fragment === null || fragment === void 0 ? void 0 : fragment.querySelectorAll(`[${attrName}]`).forEach(it => {
elements.add(it);
});
});
return elements;
}
// 중요 처음 이벤트 처리
// eslint-disable-next-line no-undef
applyEvent(obj, childNodes, config) {
// console.log('eventManager applyEvent==>', obj, childNodes, config)
// Node.ELEMENT_NODE = 1
// event
// childNodes.forEach(it => {
// if (it instanceof Element) {
// it.setAttribute('dr-thieVariableName', 'this')
// }
// })
// 중요 이벤트 걸어줌
this.eventNames.forEach(it => {
this.addDrEvents(obj, it, childNodes, config);
});
this.addDrEventPram(obj, _a.eventParam, childNodes, config);
// value
this.procAttr(childNodes, _a.valueAttrName, (it, attribute) => {
const script = attribute;
if (script) {
const data = ScriptUtils.evalReturn(script, obj);
if (it.value !== data) {
it.value = data;
}
}
});
// normal-attr-map
this.procAttr(childNodes, _a.normalAttrMapAttrName, (it, attribute) => {
const map = new Map(JSON.parse(attribute));
map.forEach((v, k) => {
const data = ScriptUtils.eval(`const $element = this.element; return ${v} `, Object.assign(obj, {
__render: Object.freeze({
element: it,
attribute: DomUtils.getAttributeToObject(it)
})
}));
// console.log('-------normalAttribute---datadatadata',data)
if (data === null) {
it.removeAttribute(k);
}
else {
it.setAttribute(k, data);
}
});
});
// window event
_a.WINDOW_EVENTS.forEach(it => {
this.procAttr(childNodes, _a.attrPrefix + 'window-event-' + it, (it, attribute) => {
it.obj = obj;
});
});
// value-link event
_a.linkAttrs.forEach(linkInfo => {
this.procAttr(childNodes, linkInfo.name, (it, varName) => {
if (varName) {
const ownerVariablePathName = it.getAttribute(_a.ownerVariablePathAttrName);
const mapScript = it.getAttribute(`${linkInfo.name}:map`);
// const inMapScript = it.getAttribute(`${valueLinkAttrName}:in-map`);
let bindObj = obj;
if (ownerVariablePathName) {
bindObj = ScriptUtils.evalReturn(ownerVariablePathName, obj);
}
const getValue = this.getValue(obj, varName, bindObj);
// TODO: 아래 나중에 리팩토링 필요함
if (typeof getValue === 'function' && getValue) {
let setValue = it[linkInfo.property];
if (mapScript) {
setValue = ScriptUtils.eval(`${this.getBindScript(config)} return ${mapScript}`, Object.assign(bindObj, { __render: Object.freeze(Object.assign({ element: it, target: bindObj, range: Range.range, value: setValue, scripts: _a.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj) }, config === null || config === void 0 ? void 0 : config.eventVariables)) }));
}
getValue(setValue);
}
else if (getValue) {
let setValue = getValue;
if (mapScript) {
setValue = ScriptUtils.eval(`${this.getBindScript(config)} return ${mapScript}`, Object.assign(bindObj, { __render: Object.freeze(Object.assign({ element: it, target: bindObj, range: Range.range, value: setValue, scripts: _a.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj) }, config === null || config === void 0 ? void 0 : config.eventVariables)) }));
}
// console.log('------->',it.value, setValue)
if (setValue === null) {
it.removeAttribute(linkInfo.property);
}
else {
// console.log('-----------',it, setValue)
it[linkInfo.property] = setValue;
}
// 여기서 value가 먼저냐 value-link가 먼저냐 선을 정해야되는거네..-> 라고해서 undefined일때에는 element값을 먼저셋팅해준다.
}
else if (getValue === undefined) {
this.setValue(obj, varName, it[linkInfo.property]);
}
it.addEventListener(linkInfo.event, (event) => {
let value = it[linkInfo.property];
if (mapScript) {
value = ScriptUtils.eval(`${this.getBindScript(config)} return ${mapScript}`, Object.assign(bindObj, {
__render: Object.freeze(Object.assign({ event, element: it, attribute: DomUtils.getAttributeToObject(it), target: event.target, range: Range.range, scripts: _a.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj) }, config === null || config === void 0 ? void 0 : config.eventVariables))
}));
}
if (typeof this.getValue(obj, varName, bindObj) === 'function') {
this.getValue(obj, varName, bindObj)(value, event);
}
else {
this.setValue(obj, varName, value);
}
});
}
});
});
// on-init event
this.procAttr(childNodes, _a.onInitAttrName, (it, attribute) => {
// it.removeAttribute(EventManager.onInitAttrName);
let script = attribute;
if (script) {
script = 'return ' + script;
}
if (script) {
ScriptUtils.eval(`${this.getBindScript(config)}; ${script} `, Object.assign(obj, {
__render: Object.freeze(Object.assign({ element: it, attribute: DomUtils.getAttributeToObject(it) }, config === null || config === void 0 ? void 0 : config.eventVariables))
}));
}
});
this.onRenderedEvent(obj, childNodes, config);
this.changeVar(obj, childNodes, undefined, config);
// console.log('eventManager-applyEvent-->', config?.applyEvents)
const elements = Array.from(childNodes).filter(it => it.nodeType === 1).map(it => it);
elements.forEach(it => {
var _b;
(_b = config === null || config === void 0 ? void 0 : config.applyEvents) === null || _b === void 0 ? void 0 : _b.filter(ta => it.getAttribute(ta.attrName) !== null).forEach(ta => ta.callBack(it, it.getAttribute(ta.attrName), obj));
});
}
// RawSet에서 replaceBody이후에 호출
onRenderedEvent(obj, childNodes, config) {
// console.log('--------onRenderedEvent', obj, childNodes);
// console.log(document.querySelectorAll(`[${EventManager.onRenderedInitAttrName}]`))
this.procAttr(childNodes, _a.onRenderedInitAttrName, (it, attribute) => {
// it.removeAttribute(EventManager.onRenderedInitAttrName);
if (!it.isConnected) {
return;
}
let script = attribute;
if (script) {
script = 'return ' + script;
}
// console.log('onRendered!!')
if (script) {
ScriptUtils.eval(`${this.getBindScript(config)}; ${script} `, Object.assign(obj, {
__render: Object.freeze(Object.assign({ element: it, attribute: DomUtils.getAttributeToObject(it) }, config === null || config === void 0 ? void 0 : config.eventVariables))
}));
}
});
}
// eslint-disable-next-line no-undef
changeVar(obj, elements, varName, config) {
// style
this.procAttr(elements, _a.styleAttrName, (it, attribute) => {
let script = attribute;
if (script) {
script = 'return ' + script;
}
if (_a.isUsingThisVar(script, varName) || varName === undefined) {
const data = ScriptUtils.eval(`const $element = this.__render.element; ${script} `, Object.assign(obj, {
__render: Object.freeze({
element: it,
attribute: DomUtils.getAttributeToObject(it)
})
}));
if (typeof data === 'string') {
it.setAttribute('style', data);
}
else if (Array.isArray(data)) {
it.setAttribute('style', data.join(';'));
}
else {
for (const [key, value] of Object.entries(data)) {
if (it instanceof HTMLElement) {
it.style[key] = String(value);
}
}
}
}
});
// class
this.procAttr(elements, _a.classAttrName, (it, attribute) => {
let script = attribute;
if (script) {
script = 'return ' + script;
}
if (_a.isUsingThisVar(script, varName) || varName === undefined) {
const data = ScriptUtils.eval(`const $element = this.element; ${script} `, Object.assign(obj, {
__render: Object.freeze({
element: it,
attribute: DomUtils.getAttributeToObject(it)
})
}));
if (typeof data === 'string') {
it.setAttribute('class', data);
}
else if (Array.isArray(data)) {
it.setAttribute('class', data.join(' '));
}
else {
for (const [key, value] of Object.entries(data)) {
if (it instanceof HTMLElement) {
if (value) {
it.classList.add(key);
}
else {
it.classList.remove(key);
}
}
}
}
}
});
// this.onRenderedEvent(obj,elements, config);
}
addDrEvents(obj, eventName, elements, config) {
// console.log('-------?', config?.router)
const attr = _a.attrPrefix + 'event-' + eventName;
this.procAttr(elements, attr, (it, attribute) => {
const script = attribute;
const hasDispatch = it.hasAttribute(`${attr}:dispatch`);
// console.log('hasDispatch',hasDispatch, attr, it);
it.addEventListener(eventName, (event) => {
let filter = true;
const filterScript = it.getAttribute(`${attr}:filter`);
const thisTarget = Object.assign(obj, {
__render: Object.freeze(Object.assign({ event, element: it, target: event.target, range: Range.range, attribute: DomUtils.getAttributeToObject(it), router: config === null || config === void 0 ? void 0 : config.router, scripts: _a.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj) }, config === null || config === void 0 ? void 0 : config.eventVariables))
});
if (filterScript) {
filter = ScriptUtils.eval(`${this.getBindScript(config)} return ${filterScript}`, thisTarget);
}
if (filter) {
ScriptUtils.eval(`${this.getBindScript(config)} ${script} `, thisTarget);
}
});
if (hasDispatch) {
it.dispatchEvent(new Event(eventName));
}
});
}
// eslint-disable-next-line no-undef
addDrEventPram(obj, attr, elements, config) {
this.procAttr(elements, attr, (it, attribute, attributes) => {
const bind = attributes[attr + ':bind'];
if (bind) {
const script = attribute;
const params = {};
const prefix = attr + ':';
Object.entries(attributes).filter(([k, v]) => k.startsWith(prefix)).forEach(([k, v]) => {
params[k.slice(prefix.length)] = v;
});
bind.split(',').forEach(eventName => {
it.addEventListener(eventName.trim(), (event) => {
ScriptUtils.eval(`const $params = this.__render.params; ${this.getBindScript(config)} ${script} `, Object.assign(obj, {
__render: Object.freeze(Object.assign({ event, element: it, attribute: DomUtils.getAttributeToObject(it), target: event.target, range: Range.range, scripts: _a.setBindProperty(config === null || config === void 0 ? void 0 : config.scripts, obj), params }, config === null || config === void 0 ? void 0 : config.eventVariables))
}));
});
});
}
});
}
// eslint-disable-next-line no-undef
procAttr(elements = new Set(), attrName, callBack) {
const sets = new Set();
elements.forEach(it => {
// console.log('--->type', it, it.nodeType)
if (!it) {
return;
}
// Node.ELEMENT_NODE = 1
if (it.nodeType === 1) {
const e = it;
sets.add(e);
e.querySelectorAll(`[${attrName}]`).forEach(it => {
sets.add(it);
});
}
});
// console.log('---setr',sets);
sets.forEach(it => {
const attr = it.getAttribute(attrName);
const attrs = DomUtils.getAttributeToObject(it);
if (attr) {
callBack(it, attr, attrs);
}
});
}
getValue(obj, name, bindObj) {
// let r = obj[name];
let r = ScriptUtils.evalReturn(name, obj);
if (typeof r === 'function') {
r = r.bind(bindObj !== null && bindObj !== void 0 ? bindObj : obj);
}
return r;
}
setValue(obj, name, value) {
name = name.replaceAll('this.', 'this.this.');
ScriptUtils.eval(`${name} = this.value;`, {
this: obj,
value: value
});
}
static isUsingThisVar(raws, varName) {
// console.log('isUsingV', raws)
// console.log('isUsingV', raws, varName, ScriptUtils.getVariablePaths(raws ?? ''))
if (varName && raws) {
if (varName.startsWith('this.')) {
varName = varName.replace(/this\./, '');
}
_a.VARNAMES.forEach(it => {
// raws = raws!.replace(RegExp(it.replace('$', '\\$'), 'g'), `this?.___${it}`);
raws = raws.replace(RegExp(it.replace('$', '\\$'), 'g'), `this.___${it}`);
});
const variablePaths = ScriptUtils.getVariablePaths(raws !== null && raws !== void 0 ? raws : '');
return variablePaths.has(varName);
}
return false;
}
static setBindProperty(scripts, obj) {
if (scripts) {
// const newScripts = Object.assign({}, scripts)
const newScripts = Object.assign({}, scripts);
for (const [key, value] of Object.entries(newScripts)) {
if (typeof value === 'function') {
newScripts[key] = value.bind(obj);
}
}
return newScripts;
}
}
getBindScript(config) {
if (config === null || config === void 0 ? void 0 : config.eventVariables) {
const bindScript = Object.entries(config.eventVariables).filter(([key, value]) => !this.bindScript.includes(`const ${key}`)).map(([key, value]) => {
return `const ${key} = this.__render.${key};`;
}).join(';');
return this.bindScript + '' + bindScript;
}
else {
return this.bindScript;
}
}
}
_a = EventManager;
EventManager.attrPrefix = 'dr-';
EventManager.ownerVariablePathAttrName = _a.attrPrefix + 'owner-variable-path';
EventManager.eventParam = _a.attrPrefix + 'event';
EventManager.onInitAttrName = _a.attrPrefix + 'on-init';
EventManager.valueAttrName = _a.attrPrefix + 'value';
EventManager.linkAttrs = [
{ name: _a.attrPrefix + 'value-link', property: 'value', event: 'input' },
{ name: _a.attrPrefix + 'hidden-link', property: 'value', event: 'input' },
{ name: _a.attrPrefix + 'required-link', property: 'value', event: 'input' },
{ name: _a.attrPrefix + 'checked-link', property: 'checked', event: 'change' },
{ name: _a.attrPrefix + 'open-link', property: 'open', event: 'toggle' },
];
EventManager.linkTargetMapAttrName = _a.attrPrefix + 'link-variables';
EventManager.onRenderedInitAttrName = _a.attrPrefix + 'on-rendered-init';
EventManager.attrAttrName = _a.attrPrefix + 'attr';
EventManager.normalAttrMapAttrName = _a.attrPrefix + 'normal-attr-map';
EventManager.styleAttrName = _a.attrPrefix + 'style';
EventManager.classAttrName = _a.attrPrefix + 'class';
EventManager.VALUE_VARNAME = '$value';
EventManager.SCRIPTS_VARNAME = '$scripts';
EventManager.FAG_VARNAME = '$fag';
EventManager.RAWSET_VARNAME = '$rawSet';
EventManager.RENDER_VARNAME = '$render';
EventManager.NEAR_THIS_VARNAME = '$nearThis';
EventManager.PARENT_THIS_VARNAME = '$parentThis';
EventManager.ROOT_OBJECT_VARNAME = '$rootObject';
EventManager.SCRIPT_UTILS_VARNAME = '$scriptUtils';
EventManager.RANGE_VARNAME = '$range';
EventManager.ROUTER_VARNAME = '$router';
EventManager.INNER_HTML_VARNAME = '$innerHTML';
EventManager.ELEMENT_VARNAME = '$element';
EventManager.TARGET_VARNAME = '$target';
EventManager.EVENT_VARNAME = '$event';
EventManager.COMPONENT_VARNAME = '$component';
EventManager.INNERHTML_VARNAME = '$innerHTML';
EventManager.ATTRIBUTE_VARNAME = '$attribute';
EventManager.CREATOR_META_DATA_VARNAME = '$creatorMetaData';
EventManager.PARENT_THIS_PATH_VARNAME = '$parentPath';
EventManager.CURRENT_THIS_VARNAME = '$currentThis';
EventManager.CURRENT_THIS_PATH_VARNAME = '$currentThisPath';
EventManager.NEAR_THIS_PATH_VARNAME = '$nearThisPath';
EventManager.VARNAMES = [_a.SCRIPTS_VARNAME, _a.FAG_VARNAME, _a.RAWSET_VARNAME, _a.RANGE_VARNAME, _a.ROUTER_VARNAME, _a.ELEMENT_VARNAME, _a.TARGET_VARNAME, _a.EVENT_VARNAME, _a.COMPONENT_VARNAME, _a.INNERHTML_VARNAME, _a.ATTRIBUTE_VARNAME, _a.ATTRIBUTE_VARNAME, _a.CREATOR_META_DATA_VARNAME, _a.PARENT_THIS_PATH_VARNAME, _a.PARENT_THIS_VARNAME, _a.attrAttrName];
EventManager.WINDOW_EVENT_POPSTATE = 'popstate';
EventManager.WINDOW_EVENT_RESIZE = 'resize';
EventManager.WINDOW_EVENTS = [_a.WINDOW_EVENT_POPSTATE, _a.WINDOW_EVENT_RESIZE];
EventManager.attrNames = [
_a.valueAttrName,
_a.attrAttrName,
_a.normalAttrMapAttrName,
_a.styleAttrName,
_a.classAttrName,
_a.attrPrefix + 'window-event-' + _a.WINDOW_EVENT_POPSTATE,
_a.attrPrefix + 'window-event-' + _a.WINDOW_EVENT_RESIZE,
_a.onInitAttrName,
..._a.linkAttrs.map(it => it.name),
_a.eventParam
];
export const eventManager = new EventManager();
//# sourceMappingURL=EventManager.js.map