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

Define new "block-updated" event. #2221

Closed
krisnik opened this issue Dec 17, 2022 · 4 comments
Closed

Define new "block-updated" event. #2221

krisnik opened this issue Dec 17, 2022 · 4 comments

Comments

@krisnik
Copy link

krisnik commented Dec 17, 2022

The question.

How to differentiate Block Update (vs) Block insert / delete.

Why and how the question has come up.

When block is updated using block.update(id, BlockToolData) - EditorJS onChange api gets called twice. once with blocked-removed and later with block-added events.

block-removed and block-added events are also fired when the blocks are deleted / added to the EditorJS instance.

Hence, from the onChange response, it is not possible to differentiate if block's content is updated or a new block is added / existing block is removed.

@lijie1129
Copy link

lijie1129 commented Jan 7, 2023

I think this is because the update function is implemented by calling the insert function and specifying the replace parameter as true.

Therefore, there are two final actions:

  • delete the old block
  • insert the block holding the new data in the original location.

This is why an update causes the onChange API gets called twice.

This is the definition of the update function:

public update = (id: string, data: BlockToolData): void => {
const { BlockManager } = this.Editor;
const block = BlockManager.getBlockById(id);
if (!block) {
_.log('blocks.update(): Block with passed id was not found', 'warn');
return;
}
const blockIndex = BlockManager.getBlockIndex(block);
BlockManager.insert({
id: block.id,
tool: block.name,
data,
index: blockIndex,
replace: true,
tunes: block.tunes,
});
};

This is the definition of the insert function:

public insert({
id = undefined,
tool = this.config.defaultBlock,
data = {},
index,
needToFocus = true,
replace = false,
tunes = {},
}: {
id?: string;
tool?: string;
data?: BlockToolData;
index?: number;
needToFocus?: boolean;
replace?: boolean;
tunes?: {[name: string]: BlockTuneData};
} = {}): Block {
let newIndex = index;
if (newIndex === undefined) {
newIndex = this.currentBlockIndex + (replace ? 0 : 1);
}
const block = this.composeBlock({
id,
tool,
data,
tunes,
});
/**
* In case of block replacing (Converting OR from Toolbox or Shortcut on empty block OR on-paste to empty block)
* we need to dispatch the 'block-removing' event for the replacing block
*/
if (replace) {
this.blockDidMutated(BlockMutationType.Removed, this.getBlockByIndex(newIndex), {
index: newIndex,
});
}
this._blocks.insert(newIndex, block, replace);
/**
* Force call of didMutated event on Block insertion
*/
this.blockDidMutated(BlockMutationType.Added, block, {
index: newIndex,
});
if (needToFocus) {
this.currentBlockIndex = newIndex;
} else if (newIndex <= this.currentBlockIndex) {
this.currentBlockIndex++;
}
return block;
}

It seems that the simple way is:

  1. Provide a new function in the blockManager.ts file to update the block's data according to the specified block ID. (This function locates the correct block in this._blocks by ID and directly replace it.)
  2. Then, directly call the new function defined above in the update function of the api/blocks.ts file.
  3. Finally, trigger the onChange API once.

@lijie1129
Copy link

lijie1129 commented Jan 20, 2023

Why does it need to support a single event

Recently, I tried to make a binding between the YJS and EditorJS.

This is to realize an idea. Please refer to here.

First

Since the synchronization EditorJS changes to the data model (YJS doc) is triggered by onChange.

It is necessary to minimize unnecessary events and avoid performance waste.

Second

In the scenario of multi-person collaborative editing, directly removing and replacing the DOM of the entire block will cause the collaborator to lose the input focus, which will cause experience problems.

Therefore, it is a good way to delegate the work of updating a specific block content to a specific plug-in.

lijie1129 added a commit to lijie1129/editor.js that referenced this issue Jan 20, 2023
lijie1129 added a commit to lijie1129/editor.js that referenced this issue Feb 1, 2023
lijie1129 added a commit to lijie1129/editor.js that referenced this issue Feb 17, 2023
lijie1129 added a commit to lijie1129/editor.js that referenced this issue Feb 17, 2023
lijie1129 added a commit to lijie1129/editor.js that referenced this issue Feb 17, 2023
lijie1129 added a commit to lijie1129/editor.js that referenced this issue Mar 19, 2023
lijie1129 added a commit to lijie1129/editor.js that referenced this issue Mar 26, 2023
@lijie1129
Copy link

Why does it need to support a single event

Recently, I tried to make a binding between the YJS and EditorJS.

This is to realize an idea. Please refer to here.

First

Since the synchronization EditorJS changes to the data model (YJS doc) is triggered by onChange.

It is necessary to minimize unnecessary events and avoid performance waste.

Second

In the scenario of multi-person collaborative editing, directly removing and replacing the DOM of the entire block will cause the collaborator to lose the input focus, which will cause experience problems.

Therefore, it is a good way to delegate the work of updating a specific block content to a specific plug-in.

Good job! @neSpecc

This issue has been resolved.

So my work can be continue.

922dfd8

@krisnik krisnik closed this as completed Sep 15, 2023
@krisnik
Copy link
Author

krisnik commented Sep 15, 2023

Thank you for the fix @neSpecc . Marking as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants