mirror of
https://github.com/codex-team/editor.js
synced 2024-05-19 06:47:16 +02:00
ac93017c70
* 2.16.0 * [Refactor] Separate internal and external settings (#845) * Enable flipping tools via standalone class (#830) * Enable flipping tools via standalone class * use flipper to refactor (#842) * use flipper to refactor * save changes * update * fix flipper on inline toolbar * ready for testing * requested changes * update doc * updates * destroy flippers * some requested changes * update * update * ready * update * last changes * update docs * Hghl active button of CT, simplify activate/deactivate * separate dom iterator * unhardcode directions * fixed a link in readme.md (#856) * Fix Block selection via CMD+A (#829) * Fix Block selection via CMD+A * Delete editor.js.map * update * update * Update CHANGELOG.md * Improve style of selected blocks (#858) * Cross-block-selection style improved * Update CHANGELOG.md * Fix case when property 'observer' in modificationObserver is not defined (#866) * Bump lodash.template from 4.4.0 to 4.5.0 (#885) Bumps [lodash.template](https://github.com/lodash/lodash) from 4.4.0 to 4.5.0. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.4.0...4.5.0) Signed-off-by: dependabot[bot] <support@github.com> * Bump eslint-utils from 1.3.1 to 1.4.2 (#886) Bumps [eslint-utils](https://github.com/mysticatea/eslint-utils) from 1.3.1 to 1.4.2. - [Release notes](https://github.com/mysticatea/eslint-utils/releases) - [Commits](https://github.com/mysticatea/eslint-utils/compare/v1.3.1...v1.4.2) Signed-off-by: dependabot[bot] <support@github.com> * Bump mixin-deep from 1.3.1 to 1.3.2 (#887) Bumps [mixin-deep](https://github.com/jonschlinkert/mixin-deep) from 1.3.1 to 1.3.2. - [Release notes](https://github.com/jonschlinkert/mixin-deep/releases) - [Commits](https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2) Signed-off-by: dependabot[bot] <support@github.com> * update bundle and readme * Update README.md * upd codeowners, fix funding * Minor Docs Fix according to main Readme (#916) * Inline Toolbar now contains Conversion Toolbar (#932) * Block lifecycle hooks (#906) * [Fix] Arrow selection (#964) * Fix arrow selection * Add docs * [issue-926]: fix dom iterator leafing when items are empty (#958) * [issue-926]: fix dom iterator leafing when items are empty * update Changelog * Issue 869 (#963) * Fix issue 943 (#965) * [Draft] Feature/tooltip enhancements (#907) * initial * update * make module standalone * use tooltips as external module * update * build via prod mode * add tooltips as external module * add declaration file and options param * add api tooltip * update * removed submodule * removed due to the incorrect setip * setup tooltips again * wip * update tooltip module * toolbox, inline toolbar * Tooltips in block tunes not uses shorthand * shorthand in a plus and block settings * fix doc * Update tools-inline.md * Delete tooltip.css * Update CHANGELOG.md * Update codex.tooltips * Update api.md * [issue-779]: Grammarly conflicts (#956) * grammarly conflicts * update * upd bundle * Submodule Header now on master * Submodule Marker now on master * Submodule Paragraph now on master * Submodule InlineCode now on master * Submodule Simple Image now on master * [issue-868]: Deleting multiple blocks triggers back button in Firefox (#967) * Deleting multiple blocks triggers back button in Firefox @evgenusov * Update editor.js * Update CHANGELOG.md * pass options on removeEventListener (#904) * pass options on removeEventListener by removeAll * rebuild * Merge branch 'release/2.16' into pr/904 * Update CHANGELOG.md * Update inline.ts * [Fix] Selection rangecount (#968) * Fix #952 (#969) * Update codex.tooltips * Selection bugfix (#970) * Selection bugfix * fix cross block selection * close inline toolbar when blocks selected via shift * remove inline toolbar closing on cross block selection mouse up due to the bug (#972) * [Feature] Log levels (#971) * Decrease margins (#973) * Decrease margins * Update editor.licenses.txt * Update src/components/domIterator.ts Co-Authored-By: Murod Khaydarov <murod.haydarov@gmail.com> * [Fix] Fix delete blocks api method (#974) * Update docs/usage.md Co-Authored-By: Murod Khaydarov <murod.haydarov@gmail.com> * rm unused * Update yarn.lock file * upd bundle, changelog
171 lines
4.1 KiB
TypeScript
171 lines
4.1 KiB
TypeScript
/**
|
|
* @module ModificationsObserver
|
|
*
|
|
* Handles any mutations
|
|
* and gives opportunity to handle outside
|
|
*/
|
|
|
|
import Module from '../__module';
|
|
import * as _ from '../utils';
|
|
import Block from '../block';
|
|
|
|
export default class ModificationsObserver extends Module {
|
|
|
|
/**
|
|
* Debounce Timer
|
|
* @type {number}
|
|
*/
|
|
public static readonly DebounceTimer = 450;
|
|
|
|
/**
|
|
* MutationObserver instance
|
|
*/
|
|
private observer: MutationObserver;
|
|
|
|
/**
|
|
* Allows to temporary disable mutations handling
|
|
*/
|
|
private disabled: boolean;
|
|
|
|
/**
|
|
* Used to prevent several mutation callback execution
|
|
* @type {Function}
|
|
*/
|
|
private mutationDebouncer = _.debounce( () => {
|
|
this.updateNativeInputs();
|
|
this.config.onChange();
|
|
}, ModificationsObserver.DebounceTimer);
|
|
|
|
/**
|
|
* Array of native inputs in Blocks.
|
|
* Changes in native inputs are not handled by modification observer, so we need to set change event listeners on them
|
|
*/
|
|
private nativeInputs: HTMLElement[] = [];
|
|
|
|
/**
|
|
* Clear timeout and set null to mutationDebouncer property
|
|
*/
|
|
public destroy() {
|
|
this.mutationDebouncer = null;
|
|
if (this.observer) {
|
|
this.observer.disconnect();
|
|
}
|
|
this.observer = null;
|
|
this.nativeInputs.forEach((input) => this.Editor.Listeners.off(input, 'input', this.mutationDebouncer));
|
|
}
|
|
|
|
/**
|
|
* Preparation method
|
|
* @return {Promise<void>}
|
|
*/
|
|
public async prepare(): Promise<void> {
|
|
/**
|
|
* wait till Browser render Editor's Blocks
|
|
*/
|
|
window.setTimeout( () => {
|
|
this.setObserver();
|
|
}, 1000);
|
|
}
|
|
|
|
/**
|
|
* Allows to disable observer,
|
|
* for example when Editor wants to stealthy mutate DOM
|
|
*/
|
|
public disable() {
|
|
this.disabled = true;
|
|
}
|
|
|
|
/**
|
|
* Enables mutation handling
|
|
* Should be called after .disable()
|
|
*/
|
|
public enable() {
|
|
this.disabled = false;
|
|
}
|
|
|
|
/**
|
|
* setObserver
|
|
*
|
|
* sets 'DOMSubtreeModified' listener on Editor's UI.nodes.redactor
|
|
* so that User can handle outside from API
|
|
*/
|
|
private setObserver(): void {
|
|
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) {
|
|
/**
|
|
* Skip mutations in stealth mode
|
|
*/
|
|
if (this.disabled) {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* We divide two Mutation types:
|
|
* 1) mutations that concerns client changes: settings changes, symbol added, deletion, insertions and so on
|
|
* 2) functional changes. On each client actions we set functional identifiers to interact with user
|
|
*/
|
|
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();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets native inputs and set oninput event handler
|
|
*/
|
|
private updateNativeInputs(): void {
|
|
if (this.nativeInputs) {
|
|
this.nativeInputs.forEach((input) => {
|
|
this.Editor.Listeners.off(input, 'input');
|
|
});
|
|
}
|
|
|
|
this.nativeInputs = Array.from(this.Editor.UI.nodes.redactor.querySelectorAll('textarea, input, select'));
|
|
|
|
this.nativeInputs.forEach((input) => this.Editor.Listeners.on(input, 'input', this.mutationDebouncer));
|
|
}
|
|
}
|