ui: use slot name as target
This commit is contained in:
parent
9f4852bd38
commit
8b568ee027
2 changed files with 18 additions and 121 deletions
|
|
@ -9,7 +9,6 @@ import FocusManager from './FocusManager';
|
||||||
import SelectionManager from './SelectionManager';
|
import SelectionManager from './SelectionManager';
|
||||||
import {
|
import {
|
||||||
StyleElement,
|
StyleElement,
|
||||||
VSpriteMap,
|
|
||||||
OnloadStyleSheet,
|
OnloadStyleSheet,
|
||||||
VDocument,
|
VDocument,
|
||||||
VElement,
|
VElement,
|
||||||
|
|
@ -55,14 +54,12 @@ export default class DOMManager extends ListWalker<Message> {
|
||||||
*/
|
*/
|
||||||
private olStyleSheets: Map<number, OnloadStyleSheet> = new Map();
|
private olStyleSheets: Map<number, OnloadStyleSheet> = new Map();
|
||||||
/** @depreacted since tracker 4.0.2 Mapping by nodeID */
|
/** @depreacted since tracker 4.0.2 Mapping by nodeID */
|
||||||
private olStyleSheetsDeprecated: Map<number, OnloadStyleSheet> = new Map();
|
|
||||||
private upperBodyId: number = -1;
|
private upperBodyId: number = -1;
|
||||||
private nodeScrollManagers: Map<number, ListWalker<SetNodeScroll>> =
|
private nodeScrollManagers: Map<number, ListWalker<SetNodeScroll>> =
|
||||||
new Map();
|
new Map();
|
||||||
private stylesManager: StylesManager;
|
private stylesManager: StylesManager;
|
||||||
private focusManager: FocusManager = new FocusManager(this.vElements);
|
private focusManager: FocusManager = new FocusManager(this.vElements);
|
||||||
private selectionManager: SelectionManager;
|
private selectionManager: SelectionManager;
|
||||||
private nodeSlots: Map<number, { slotID: number; host: any }> = new Map();
|
|
||||||
private readonly screen: Screen;
|
private readonly screen: Screen;
|
||||||
private readonly isMobile: boolean;
|
private readonly isMobile: boolean;
|
||||||
private readonly stringDict: Record<number, string>;
|
private readonly stringDict: Record<number, string>;
|
||||||
|
|
@ -72,7 +69,7 @@ export default class DOMManager extends ListWalker<Message> {
|
||||||
};
|
};
|
||||||
public readonly time: number;
|
public readonly time: number;
|
||||||
private virtualMode = false;
|
private virtualMode = false;
|
||||||
private hasSlots = false
|
private hasSlots = false;
|
||||||
private showVModeBadge?: () => void;
|
private showVModeBadge?: () => void;
|
||||||
|
|
||||||
constructor(params: {
|
constructor(params: {
|
||||||
|
|
@ -286,42 +283,26 @@ export default class DOMManager extends ListWalker<Message> {
|
||||||
logger.error('SetNodeSlot: Node not found', msg);
|
logger.error('SetNodeSlot: Node not found', msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.slotID > 0) {
|
if (msg.slotID > 0) {
|
||||||
const slotElem = this.vElements.get(msg.slotID);
|
const slotElem = this.vElements.get(msg.slotID);
|
||||||
if (!(slotElem instanceof VSlot)) {
|
if (!(slotElem instanceof VSlot)) {
|
||||||
logger.error('SetNodeSlot: Slot not found', msg);
|
logger.error('SetNodeSlot: Slot not found', msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const host = vChild.parentNode;
|
|
||||||
if (host && (vChild as any).assignedSlot !== slotElem) {
|
if (vChild instanceof VElement) {
|
||||||
if (vChild.node.parentNode === (host as any).node) {
|
const slotName = (slotElem.node as HTMLSlotElement).name;
|
||||||
host.node.removeChild(vChild.node);
|
if (slotName && slotName !== 'default') {
|
||||||
|
vChild.setAttribute('slot', slotName);
|
||||||
|
} else {
|
||||||
|
// if el goes to default slot, we don't need attr
|
||||||
|
vChild.removeAttribute('slot');
|
||||||
}
|
}
|
||||||
(host as any).notMontedChildren?.delete(vChild);
|
|
||||||
slotElem.addAssigned(vChild);
|
|
||||||
(vChild as any).assignedSlot = slotElem;
|
|
||||||
this.nodeSlots.set(msg.id, { slotID: msg.slotID, host });
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (vChild.assignedSlot) {
|
if (vChild instanceof VElement) {
|
||||||
const slotElem = vChild.assignedSlot as VSlot;
|
vChild.removeAttribute('slot');
|
||||||
slotElem.removeAssigned(vChild);
|
|
||||||
if (vChild.parentNode) {
|
|
||||||
const host = vChild.parentNode;
|
|
||||||
const siblings = host['children'] as any[];
|
|
||||||
const index = siblings.indexOf(vChild);
|
|
||||||
let next: Node | null = null;
|
|
||||||
for (let i = index + 1; i < siblings.length; i++) {
|
|
||||||
const sib = siblings[i];
|
|
||||||
if (!sib.assignedSlot) {
|
|
||||||
next = sib.node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
host.node.insertBefore(vChild.node, next);
|
|
||||||
}
|
|
||||||
vChild.assignedSlot = null;
|
|
||||||
this.nodeSlots.delete(msg.id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ export abstract class VNode<T extends Node = Node> {
|
||||||
public abstract applyChanges(): void;
|
public abstract applyChanges(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type VChild = VElement | VText | VSpriteMap;
|
type VChild = VElement | VText;
|
||||||
abstract class VParent<T extends Node = Node> extends VNode<T> {
|
abstract class VParent<T extends Node = Node> extends VNode<T> {
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
@ -163,46 +163,6 @@ export class VShadowRoot extends VParent<ShadowRoot> {
|
||||||
|
|
||||||
export type VRoot = VDocument | VShadowRoot;
|
export type VRoot = VDocument | VShadowRoot;
|
||||||
|
|
||||||
export class VSpriteMap extends VParent<Element> {
|
|
||||||
parentNode: VParent | null =
|
|
||||||
null; /** Should be modified only by he parent itself */
|
|
||||||
|
|
||||||
private newAttributes: Map<string, string | false> = new Map();
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
readonly tagName: string,
|
|
||||||
readonly isSVG = true,
|
|
||||||
public readonly index: number,
|
|
||||||
private readonly nodeId: number,
|
|
||||||
) {
|
|
||||||
super();
|
|
||||||
this.createNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected createNode() {
|
|
||||||
try {
|
|
||||||
const element = document.createElementNS(
|
|
||||||
'http://www.w3.org/2000/svg',
|
|
||||||
this.tagName,
|
|
||||||
);
|
|
||||||
element.dataset.openreplayId = this.nodeId.toString();
|
|
||||||
return element;
|
|
||||||
} catch (e) {
|
|
||||||
console.error(
|
|
||||||
'Openreplay: Player received invalid html tag',
|
|
||||||
this.tagName,
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
return document.createElement(this.tagName.replace(/[^a-z]/gi, ''));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyChanges() {
|
|
||||||
// this is a hack to prevent the sprite map from being removed from the DOM
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class VElement extends VParent<Element> {
|
export class VElement extends VParent<Element> {
|
||||||
parentNode: VParent | null =
|
parentNode: VParent | null =
|
||||||
null; /** Should be modified only by he parent itself */
|
null; /** Should be modified only by he parent itself */
|
||||||
|
|
@ -298,58 +258,14 @@ export class VElement extends VParent<Element> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VSlot extends VElement {
|
export class VSlot extends VElement {
|
||||||
assignedNodes: VChild[] = [];
|
protected createNode() {
|
||||||
|
const element = super.createNode() as HTMLSlotElement;
|
||||||
addAssigned(child: VChild) {
|
return element;
|
||||||
if (this.assignedNodes.indexOf(child) === -1) {
|
|
||||||
this.assignedNodes.push(child);
|
|
||||||
this.notMontedChildren.add(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeAssigned(child: VChild) {
|
|
||||||
this.assignedNodes = this.assignedNodes.filter((c) => c !== child);
|
|
||||||
this.notMontedChildren.delete(child);
|
|
||||||
}
|
|
||||||
|
|
||||||
private mountAssigned() {
|
|
||||||
let nextMounted: VChild | null = null;
|
|
||||||
for (let i = this.assignedNodes.length - 1; i >= 0; i--) {
|
|
||||||
const child = this.assignedNodes[i];
|
|
||||||
if (this.notMontedChildren.has(child)) {
|
|
||||||
this.node.insertBefore(
|
|
||||||
child.node,
|
|
||||||
nextMounted ? nextMounted.node : null,
|
|
||||||
);
|
|
||||||
this.notMontedChildren.delete(child);
|
|
||||||
}
|
|
||||||
if (!this.notMontedChildren.has(child)) {
|
|
||||||
nextMounted = child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
applyChanges() {
|
applyChanges() {
|
||||||
if (this.assignedNodes.length > 0) {
|
super.applyChanges();
|
||||||
this.assignedNodes.forEach((c) => c.applyChanges());
|
// todo safety checks here ?
|
||||||
this.mountAssigned();
|
|
||||||
const { node } = this;
|
|
||||||
const realChildren = node.childNodes;
|
|
||||||
if (realChildren.length > 0) {
|
|
||||||
for (let j = 0; j < this.assignedNodes.length; j++) {
|
|
||||||
while (realChildren[j] !== this.assignedNodes[j].node) {
|
|
||||||
if (isNode(realChildren[j])) {
|
|
||||||
node.removeChild(realChildren[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (realChildren.length > this.assignedNodes.length) {
|
|
||||||
node.removeChild(node.lastChild as Node);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
super.applyChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue