class NodeResizer {
protected context: EditorUiContext;
- protected dom: HTMLElement|null = null;
+ protected resizerDOM: HTMLElement|null = null;
+ protected targetDOM: HTMLElement|null = null;
protected scrollContainer: HTMLElement;
protected mouseTracker: MouseDragTracker|null = null;
protected activeSelection: string = '';
+ protected loadAbortController = new AbortController();
constructor(context: EditorUiContext) {
this.context = context;
this.scrollContainer = context.scrollDOM;
this.onSelectionChange = this.onSelectionChange.bind(this);
+ this.onTargetDOMLoad = this.onTargetDOMLoad.bind(this);
+
context.manager.onSelectionChange(this.onSelectionChange);
}
}
}
+ onTargetDOMLoad(): void {
+ this.updateResizerPosition();
+ }
+
teardown() {
this.context.manager.offSelectionChange(this.onSelectionChange);
this.hide();
}
- protected showForNode(node: NodeHasSize&LexicalNode, dom: HTMLElement) {
- this.dom = this.buildDOM();
+ protected showForNode(node: NodeHasSize&LexicalNode, targetDOM: HTMLElement) {
+ this.resizerDOM = this.buildDOM();
+ this.targetDOM = targetDOM;
let ghost = el('span', {class: 'editor-node-resizer-ghost'});
if ($isImageNode(node)) {
- ghost = el('img', {src: dom.getAttribute('src'), class: 'editor-node-resizer-ghost'});
+ ghost = el('img', {src: targetDOM.getAttribute('src'), class: 'editor-node-resizer-ghost'});
}
- this.dom.append(ghost);
+ this.resizerDOM.append(ghost);
- this.context.scrollDOM.append(this.dom);
- this.updateDOMPosition(dom);
+ this.context.scrollDOM.append(this.resizerDOM);
+ this.updateResizerPosition();
- this.mouseTracker = this.setupTracker(this.dom, node, dom);
+ this.mouseTracker = this.setupTracker(this.resizerDOM, node, targetDOM);
this.activeSelection = node.getKey();
+
+ if (targetDOM.matches('img, embed, iframe, object')) {
+ this.loadAbortController = new AbortController();
+ targetDOM.addEventListener('load', this.onTargetDOMLoad, { signal: this.loadAbortController.signal });
+ }
}
- protected updateDOMPosition(nodeDOM: HTMLElement) {
- if (!this.dom) {
+ protected updateResizerPosition() {
+ if (!this.resizerDOM || !this.targetDOM) {
return;
}
const scrollAreaRect = this.scrollContainer.getBoundingClientRect();
- const nodeRect = nodeDOM.getBoundingClientRect();
+ const nodeRect = this.targetDOM.getBoundingClientRect();
const top = nodeRect.top - (scrollAreaRect.top - this.scrollContainer.scrollTop);
const left = nodeRect.left - scrollAreaRect.left;
- this.dom.style.top = `${top}px`;
- this.dom.style.left = `${left}px`;
- this.dom.style.width = nodeRect.width + 'px';
- this.dom.style.height = nodeRect.height + 'px';
+ this.resizerDOM.style.top = `${top}px`;
+ this.resizerDOM.style.left = `${left}px`;
+ this.resizerDOM.style.width = nodeRect.width + 'px';
+ this.resizerDOM.style.height = nodeRect.height + 'px';
}
protected updateDOMSize(width: number, height: number): void {
- if (!this.dom) {
+ if (!this.resizerDOM) {
return;
}
- this.dom.style.width = width + 'px';
- this.dom.style.height = height + 'px';
+ this.resizerDOM.style.width = width + 'px';
+ this.resizerDOM.style.height = height + 'px';
}
protected hide() {
this.mouseTracker?.teardown();
- this.dom?.remove();
+ this.resizerDOM?.remove();
+ this.targetDOM = null;
this.activeSelection = '';
+ this.loadAbortController.abort();
}
protected buildDOM() {
return new MouseDragTracker(container, '.editor-node-resizer-handle', {
down(event: MouseEvent, handle: HTMLElement) {
- _this.dom?.classList.add('active');
+ _this.resizerDOM?.classList.add('active');
_this.context.editor.getEditorState().read(() => {
const domRect = nodeDOM.getBoundingClientRect();
startingWidth = node.getWidth() || domRect.width;
node.setHeight(hasHeight ? size.height : 0);
_this.context.manager.triggerLayoutUpdate();
requestAnimationFrame(() => {
- _this.updateDOMPosition(nodeDOM);
+ _this.updateResizerPosition();
})
});
- _this.dom?.classList.remove('active');
+ _this.resizerDOM?.classList.remove('active');
}
});
}