Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: errors caused by events fired while editor is not initialized yet #2532

Merged
merged 2 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- `Fix` — When the focusing Block is out of the viewport, the page will be scrolled.
- `Fix` — `blocks.render()` won't lead the `onChange` call in Safari
- `Fix` — Editor wrapper element growing on the Inline Toolbar close
- `Fix` — Fix errors thrown by clicks on a document when the editor is being initialized

### 2.28.2

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@editorjs/editorjs",
"version": "2.29.0-rc.5",
"version": "2.29.0-rc.6",
"description": "Editor.js — Native JS, based on API and Open Source",
"main": "dist/editorjs.umd.js",
"module": "dist/editorjs.mjs",
Expand Down
6 changes: 5 additions & 1 deletion src/components/modules/blockManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,11 @@ export default class BlockManager extends Module {
* @param {Node} childNode - node to get Block by
* @returns {Block}
*/
public getBlockByChildNode(childNode: Node): Block {
public getBlockByChildNode(childNode: Node): Block | undefined {
if (!childNode || childNode instanceof Node === false) {
return undefined;
}

/**
* If node is Text TextNode
*/
Expand Down
7 changes: 7 additions & 0 deletions src/components/modules/crossBlockSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ export default class CrossBlockSelection extends Module {
private onMouseOver = (event: MouseEvent): void => {
const { BlockManager, BlockSelection } = this.Editor;

/**
* Probably, editor is not initialized yet
*/
if (event.relatedTarget === null && event.target === null) {
return;
}

const relatedBlock = BlockManager.getBlockByChildNode(event.relatedTarget as Node) || this.lastSelectedBlock;
const targetBlock = BlockManager.getBlockByChildNode(event.target as Node);

Expand Down
5 changes: 4 additions & 1 deletion src/components/modules/toolbar/blockSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import Popover, { PopoverEvent } from '../../utils/popover';
* HTML Elements that used for BlockSettings
*/
interface BlockSettingsNodes {
wrapper: HTMLElement;
/**
* Block Settings wrapper. Undefined when before "make" method called
*/
wrapper: HTMLElement | undefined;
}

/**
Expand Down
12 changes: 6 additions & 6 deletions src/components/modules/toolbar/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ import { BlockHovered } from '../../events/BlockHovered';
* HTML Elements used for Toolbar UI
*/
interface ToolbarNodes {
wrapper: HTMLElement;
content: HTMLElement;
actions: HTMLElement;
wrapper: HTMLElement | undefined;
content: HTMLElement | undefined;
actions: HTMLElement | undefined;

plusButton: HTMLElement;
settingsToggler: HTMLElement;
plusButton: HTMLElement | undefined;
settingsToggler: HTMLElement | undefined;
}
/**
*
Expand Down Expand Up @@ -316,7 +316,7 @@ export default class Toolbar extends Module<ToolbarNodes> {
return;
}

this.nodes.wrapper.classList.remove(this.CSS.toolbarOpened);
this.nodes.wrapper?.classList.remove(this.CSS.toolbarOpened);

/** Close components */
this.blockActions.hide();
Expand Down
16 changes: 10 additions & 6 deletions src/components/modules/toolbar/inline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ import { IconChevronDown } from '@codexteam/icons';
* Inline Toolbar elements
*/
interface InlineToolbarNodes {
wrapper: HTMLElement;
togglerAndButtonsWrapper: HTMLElement;
buttons: HTMLElement;
conversionToggler: HTMLElement;
conversionTogglerContent: HTMLElement;
wrapper: HTMLElement | undefined;
togglerAndButtonsWrapper: HTMLElement | undefined;
buttons: HTMLElement | undefined;
conversionToggler: HTMLElement | undefined;
conversionTogglerContent: HTMLElement | undefined;
/**
* Zone below the buttons where Tools can create additional actions by 'renderActions()' method
* For example, input for the 'link' tool or textarea for the 'comment' tool
*/
actions: HTMLElement;
actions: HTMLElement | undefined;
}

/**
Expand Down Expand Up @@ -238,6 +238,10 @@ export default class InlineToolbar extends Module<InlineToolbarNodes> {
* @param {Node} node — node to check
*/
public containsNode(node: Node): boolean {
if (this.nodes.wrapper === undefined) {
return false;
}

return this.nodes.wrapper.contains(node);
}

Expand Down
18 changes: 13 additions & 5 deletions src/components/modules/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,20 @@ export default class UI extends Module<UINodes> {
*/
if (!readOnlyEnabled) {
/**
* Unbind all events
* Postpone events binding to the next tick to make sure all ui elements are ready
*/
this.enableModuleBindings();
window.requestIdleCallback(() => {
/**
* Bind events for the UI elements
*/
this.enableModuleBindings();
}, {
timeout: 2000,
});
} else {
/**
* Bind events for the UI elements
* Unbind all events
*
*/
this.disableModuleBindings();
}
Expand Down Expand Up @@ -633,8 +641,8 @@ export default class UI extends Module<UINodes> {
* But allow clicking inside Block Settings.
* Also, do not process clicks on the Block Settings Toggler, because it has own click listener
*/
const isClickedInsideBlockSettings = this.Editor.BlockSettings.nodes.wrapper.contains(target);
const isClickedInsideBlockSettingsToggler = this.Editor.Toolbar.nodes.settingsToggler.contains(target);
const isClickedInsideBlockSettings = this.Editor.BlockSettings.nodes.wrapper?.contains(target);
const isClickedInsideBlockSettingsToggler = this.Editor.Toolbar.nodes.settingsToggler?.contains(target);
const doNotProcess = isClickedInsideBlockSettings || isClickedInsideBlockSettingsToggler;

if (this.Editor.BlockSettings.opened && !doNotProcess) {
Expand Down