More or less cosmetic
This commit is contained in:
parent
92fa548109
commit
666a3daac3
|
@ -76,12 +76,12 @@ export function spawnWindowEventFactory(ds: Ref) {
|
||||||
const facet = Turn.activeFacet;
|
const facet = Turn.activeFacet;
|
||||||
facet.preventInertCheck();
|
facet.preventInertCheck();
|
||||||
|
|
||||||
let handler = function (event: Event) {
|
let handler = (event: Event) => {
|
||||||
facet.turn(() => {
|
facet.turn(() => {
|
||||||
send message P.WindowEvent(eventType, embed(create ({ data: event })));
|
send message P.WindowEvent(eventType, embed(create ({ data: event })));
|
||||||
});
|
});
|
||||||
return dealWithPreventDefault(eventType, event);
|
return dealWithPreventDefault(eventType, event);
|
||||||
}
|
};
|
||||||
|
|
||||||
function updateEventListeners(install: boolean) {
|
function updateEventListeners(install: boolean) {
|
||||||
if (install) {
|
if (install) {
|
||||||
|
@ -116,108 +116,109 @@ function spawnUIFragmentFactory(ds: Ref) {
|
||||||
|
|
||||||
spawn named 'UIFragmentFactory' {
|
spawn named 'UIFragmentFactory' {
|
||||||
at ds {
|
at ds {
|
||||||
during P.UIFragment($fragmentId0, _, _, _) => spawn named ['UIFragment', fragmentId0] {
|
during P.UIFragment($fragmentId0, _, _, _) =>
|
||||||
if (!isFragmentId(fragmentId0)) return;
|
spawn named ['UIFragment', fragmentId0] {
|
||||||
const fragmentId = fragmentId0;
|
if (!isFragmentId(fragmentId0)) return;
|
||||||
|
const fragmentId = fragmentId0;
|
||||||
|
|
||||||
field version: number = 0;
|
field version: number = 0;
|
||||||
assert P.UIFragmentVersion(fragmentId, version.value) when (version.value > 0);
|
assert P.UIFragmentVersion(fragmentId, version.value) when (version.value > 0);
|
||||||
|
|
||||||
let selector: string;
|
let selector: string;
|
||||||
let html: Array<ChildNode>;
|
let html: Array<ChildNode>;
|
||||||
let orderBy: NodeOrderKey;
|
let orderBy: NodeOrderKey;
|
||||||
let anchorNodes: Array<Element> = [];
|
let anchorNodes: Array<Element> = [];
|
||||||
let eventRegistrations =
|
let eventRegistrations =
|
||||||
new FlexMap<RegistrationKey, HandlerClosure>(JSON.stringify);
|
new FlexMap<RegistrationKey, HandlerClosure>(JSON.stringify);
|
||||||
|
|
||||||
on stop removeNodes();
|
on stop removeNodes();
|
||||||
|
|
||||||
during Observe({
|
during Observe({
|
||||||
"pattern": :pattern P.UIEvent(fragmentId,
|
"pattern": :pattern P.UIEvent(fragmentId,
|
||||||
\Q.lit($selector: string),
|
\Q.lit($selector: string),
|
||||||
\Q.lit($eventType: string),
|
\Q.lit($eventType: string),
|
||||||
\_)
|
\_)
|
||||||
}) => {
|
}) => {
|
||||||
updateEventListeners([ selector, eventType ], true);
|
updateEventListeners([ selector, eventType ], true);
|
||||||
on stop updateEventListeners([ selector, eventType ], false);
|
on stop updateEventListeners([ selector, eventType ], false);
|
||||||
}
|
|
||||||
|
|
||||||
on asserted P.UIFragment(fragmentId, $newSelector: string, $newHtml, $newOrderBy) => {
|
|
||||||
if (!isNodeOrderKey(newOrderBy)) return;
|
|
||||||
|
|
||||||
removeNodes();
|
|
||||||
|
|
||||||
selector = newSelector;
|
|
||||||
html = (newHtml as Embedded<Ref>).embeddedValue.target.data as ChildNode[];
|
|
||||||
orderBy = newOrderBy;
|
|
||||||
anchorNodes = (selector !== null) ? selectorMatch(document.body, selector) : [];
|
|
||||||
|
|
||||||
if (anchorNodes.length === 0) {
|
|
||||||
console.warn('UIFragment found no parent nodes matching selector', selector, fragmentId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
anchorNodes.forEach(anchorNode => {
|
on asserted P.UIFragment(fragmentId, $newSelector: string, $newHtml, $newOrderBy) => {
|
||||||
let insertionPoint = findInsertionPoint(anchorNode, orderBy, fragmentId);
|
if (!isNodeOrderKey(newOrderBy)) return;
|
||||||
html.forEach(newNode => {
|
|
||||||
setSortKey(newNode, orderBy, fragmentId);
|
|
||||||
anchorNode.insertBefore(newNode, insertionPoint);
|
|
||||||
configureNode(newNode);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// (re)install event listeners
|
removeNodes();
|
||||||
eventRegistrations.forEach((_handler, key) => updateEventListeners(key, true));
|
|
||||||
|
|
||||||
version.value++;
|
selector = newSelector;
|
||||||
}
|
html = (newHtml as Embedded<Ref>).embeddedValue.target.data as ChildNode[];
|
||||||
|
orderBy = newOrderBy;
|
||||||
|
anchorNodes = (selector !== null) ? selectorMatch(document.body, selector) : [];
|
||||||
|
|
||||||
function removeNodes() {
|
if (anchorNodes.length === 0) {
|
||||||
anchorNodes.forEach(anchorNode => {
|
console.warn('UIFragment found no parent nodes matching selector', selector, fragmentId);
|
||||||
let insertionPoint = findInsertionPoint(anchorNode, orderBy, fragmentId);
|
|
||||||
while (true) {
|
|
||||||
let n = insertionPoint ? insertionPoint.previousSibling : anchorNode.lastChild;
|
|
||||||
if (!(n && hasSortKey(n, orderBy, fragmentId))) break;
|
|
||||||
n.parentNode?.removeChild(n); // auto-updates previousSibling/lastChild
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateEventListeners(key: RegistrationKey, install: boolean) {
|
anchorNodes.forEach(anchorNode => {
|
||||||
const [selector, eventType] = key;
|
let insertionPoint = findInsertionPoint(anchorNode, orderBy, fragmentId);
|
||||||
|
html.forEach(newNode => {
|
||||||
let handlerClosure: HandlerClosure;
|
setSortKey(newNode, orderBy, fragmentId);
|
||||||
if (!eventRegistrations.has(key)) {
|
anchorNode.insertBefore(newNode, insertionPoint);
|
||||||
const facet = Turn.activeFacet;
|
configureNode(newNode);
|
||||||
function handler(event: Event) {
|
|
||||||
facet.turn(() => {
|
|
||||||
send message P.UIEvent(fragmentId, selector, eventType, embed(create ({ data: event })));
|
|
||||||
});
|
});
|
||||||
return dealWithPreventDefault(eventType, event);
|
});
|
||||||
}
|
|
||||||
eventRegistrations.set(key, handler);
|
// (re)install event listeners
|
||||||
handlerClosure = handler;
|
eventRegistrations.forEach((_handler, key) => updateEventListeners(key, true));
|
||||||
} else {
|
|
||||||
handlerClosure = eventRegistrations.get(key)!;
|
version.value++;
|
||||||
}
|
}
|
||||||
|
|
||||||
anchorNodes.forEach(anchorNode => {
|
function removeNodes() {
|
||||||
let insertionPoint = findInsertionPoint(anchorNode, orderBy, fragmentId);
|
anchorNodes.forEach(anchorNode => {
|
||||||
while (true) {
|
let insertionPoint = findInsertionPoint(anchorNode, orderBy, fragmentId);
|
||||||
let uiNode = insertionPoint ? insertionPoint.previousSibling : anchorNode.lastChild;
|
while (true) {
|
||||||
if (!(uiNode && hasSortKey(uiNode, orderBy, fragmentId))) break;
|
let n = insertionPoint ? insertionPoint.previousSibling : anchorNode.lastChild;
|
||||||
if (isQueryableNode(uiNode)) {
|
if (!(n && hasSortKey(n, orderBy, fragmentId))) break;
|
||||||
selectorMatch(uiNode, selector).forEach(
|
n.parentNode?.removeChild(n); // auto-updates previousSibling/lastChild
|
||||||
eventUpdater(cleanEventType(eventType), handlerClosure, install));
|
|
||||||
}
|
}
|
||||||
insertionPoint = uiNode;
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (!install) {
|
function updateEventListeners(key: RegistrationKey, install: boolean) {
|
||||||
eventRegistrations.delete(key);
|
const [selector, eventType] = key;
|
||||||
|
|
||||||
|
let handlerClosure: HandlerClosure;
|
||||||
|
if (!eventRegistrations.has(key)) {
|
||||||
|
const facet = Turn.activeFacet;
|
||||||
|
function handler(event: Event) {
|
||||||
|
facet.turn(() => {
|
||||||
|
send message P.UIEvent(fragmentId, selector, eventType, embed(create ({ data: event })));
|
||||||
|
});
|
||||||
|
return dealWithPreventDefault(eventType, event);
|
||||||
|
}
|
||||||
|
eventRegistrations.set(key, handler);
|
||||||
|
handlerClosure = handler;
|
||||||
|
} else {
|
||||||
|
handlerClosure = eventRegistrations.get(key)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
anchorNodes.forEach(anchorNode => {
|
||||||
|
let insertionPoint = findInsertionPoint(anchorNode, orderBy, fragmentId);
|
||||||
|
while (true) {
|
||||||
|
let uiNode = insertionPoint ? insertionPoint.previousSibling : anchorNode.lastChild;
|
||||||
|
if (!(uiNode && hasSortKey(uiNode, orderBy, fragmentId))) break;
|
||||||
|
if (isQueryableNode(uiNode)) {
|
||||||
|
selectorMatch(uiNode, selector).forEach(
|
||||||
|
eventUpdater(cleanEventType(eventType), handlerClosure, install));
|
||||||
|
}
|
||||||
|
insertionPoint = uiNode;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!install) {
|
||||||
|
eventRegistrations.delete(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -309,7 +310,7 @@ function configureNode(n: ChildNode) {
|
||||||
// Runs post-insertion configuration of nodes.
|
// Runs post-insertion configuration of nodes.
|
||||||
// TODO: review this design.
|
// TODO: review this design.
|
||||||
selectorMatch(n, '.-syndicate-focus').forEach(
|
selectorMatch(n, '.-syndicate-focus').forEach(
|
||||||
function (n: Element | HTMLTextAreaElement | HTMLInputElement) {
|
(n: Element | HTMLTextAreaElement | HTMLInputElement) => {
|
||||||
if ('focus' in n && 'setSelectionRange' in n) {
|
if ('focus' in n && 'setSelectionRange' in n) {
|
||||||
n.focus();
|
n.focus();
|
||||||
n.setSelectionRange(n.value.length, n.value.length);
|
n.setSelectionRange(n.value.length, n.value.length);
|
||||||
|
@ -573,7 +574,7 @@ function selectorMatch(n: Element | Node, selector: string): Array<Element> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function eventUpdater(eventType: string, handlerClosure: (event: Event) => void, install: boolean) {
|
function eventUpdater(eventType: string, handlerClosure: (event: Event) => void, install: boolean) {
|
||||||
return function (n: EventTarget) {
|
return (n: EventTarget) => {
|
||||||
// addEventListener and removeEventListener are idempotent.
|
// addEventListener and removeEventListener are idempotent.
|
||||||
if (install) {
|
if (install) {
|
||||||
n.addEventListener(eventType, handlerClosure);
|
n.addEventListener(eventType, handlerClosure);
|
||||||
|
|
Loading…
Reference in New Issue