[ModificationObserver]: Use Native MutationObserver instead of DomModification listener (#556)

* Use native Mutation Observer

* use debounce on mutations

* bump version

* code descriptions

* upd
This commit is contained in:
Murod Khaydarov 2018-12-07 11:33:43 +03:00 committed by GitHub
parent 3d512d66ff
commit d5d77c60cb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 8 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{
"name": "codex.editor",
"version": "2.7.8",
"version": "2.7.9",
"description": "Codex Editor. Native JS, based on API and Open Source",
"main": "dist/codex-editor.js",
"types": "./types/index.d.ts",

View file

@ -7,6 +7,7 @@
import Module from '../__module';
import _ from '../utils';
import Block from '../block';
export default class ModificationsObserver extends Module {
@ -16,6 +17,11 @@ export default class ModificationsObserver extends Module {
*/
public static readonly DebounceTimer = 450;
/**
* MutationObserver instance
*/
private observer: MutationObserver;
/**
* Used to prevent several mutation callback execution
* @type {Function}
@ -29,6 +35,8 @@ export default class ModificationsObserver extends Module {
*/
public destroy() {
this.mutationDebouncer = null;
this.observer.disconnect();
this.observer = null;
}
/**
@ -51,13 +59,59 @@ export default class ModificationsObserver extends Module {
* so that User can handle outside from API
*/
private setObserver(): void {
const {Listeners, UI} = this.Editor;
const {UI} = this.Editor;
const observerOptions = {
childList: true,
attributes: true,
subtree: true,
characterData: true,
characterDataOldValue: true,
};
this.observer = new MutationObserver((mutationList, observer) => {
this.mutationHandler(mutationList, observer);
});
this.observer.observe(UI.nodes.redactor, observerOptions);
}
/**
* MutationObserver events handler
* @param mutationList
* @param observer
*/
private mutationHandler(mutationList, observer) {
/**
* Set Listener to the Editor <div> element that holds only Blocks
* We divide two Mutation types:
* 1) mutations that concerns client changes. For example, settings changes, symbol added, deletion, insertions and so on
* 2) functional changes. On each client actions we set functional identifiers to interact with user
*/
Listeners.on(UI.nodes.redactor, 'DOMSubtreeModified', () => {
let contentMutated = false;
mutationList.forEach((mutation) => {
switch (mutation.type) {
case 'childList':
case 'subtree':
case 'characterData':
case 'characterDataOldValue':
contentMutated = true;
break;
case 'attributes':
const mutatedTarget = mutation.target as Element;
/**
* Changes on Element.ce-block usually is functional
*/
if (!mutatedTarget.classList.contains(Block.CSS.wrapper)) {
contentMutated = true;
return;
}
break;
}
});
/** call once */
if (contentMutated) {
this.mutationDebouncer();
}, false);
}
}
}