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
256 lines
5.9 KiB
TypeScript
256 lines
5.9 KiB
TypeScript
import DomIterator from './domIterator';
|
|
import * as _ from './utils';
|
|
|
|
/**
|
|
* Flipper construction options
|
|
*/
|
|
export interface FlipperOptions {
|
|
/**
|
|
* CSS-modifier for focused item
|
|
*/
|
|
focusedItemClass?: string;
|
|
|
|
/**
|
|
* If flipping items are the same for all Block (for ex. Toolbox), ypu can pass it on constructing
|
|
*/
|
|
items?: HTMLElement[];
|
|
|
|
/**
|
|
* Defines arrows usage. By default Flipper leafs items also via RIGHT/LEFT.
|
|
*
|
|
* true by default
|
|
*
|
|
* Pass 'false' if you don't need this behaviour
|
|
* (for example, Inline Toolbar should be closed by arrows,
|
|
* because it means caret moving with selection clearing)
|
|
*/
|
|
allowArrows?: boolean;
|
|
|
|
/**
|
|
* Optional callback for button click
|
|
*/
|
|
activateCallback?: () => void;
|
|
}
|
|
|
|
/**
|
|
* Flipper is a component that iterates passed items array by TAB or Arrows and clicks it by ENTER
|
|
*/
|
|
export default class Flipper {
|
|
|
|
/**
|
|
* Instance of flipper iterator
|
|
* @type {DomIterator|null}
|
|
*/
|
|
private readonly iterator: DomIterator = null;
|
|
|
|
/**
|
|
* Flag that defines activation status
|
|
* @type {boolean}
|
|
*/
|
|
private activated: boolean = false;
|
|
|
|
/**
|
|
* Flag that allows arrows usage to flip items
|
|
* @type {boolean}
|
|
*/
|
|
private readonly allowArrows: boolean = true;
|
|
|
|
/**
|
|
* Call back for button click/enter
|
|
*/
|
|
private readonly activateCallback: () => void;
|
|
|
|
/**
|
|
* @constructor
|
|
*
|
|
* @param {FlipperOptions} options - different constructing settings
|
|
* @
|
|
*/
|
|
constructor(options: FlipperOptions) {
|
|
this.allowArrows = typeof options.allowArrows === 'boolean' ? options.allowArrows : true;
|
|
this.iterator = new DomIterator(options.items, options.focusedItemClass);
|
|
this.activateCallback = options.activateCallback;
|
|
|
|
/**
|
|
* Listening all keydowns on document and react on TAB/Enter press
|
|
* TAB will leaf iterator items
|
|
* ENTER will click the focused item
|
|
*/
|
|
document.addEventListener('keydown', (event) => {
|
|
const isReady = this.isEventReadyForHandling(event);
|
|
|
|
if (!isReady) {
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* Prevent only used keys default behaviour
|
|
* (allows to navigate by ARROW DOWN, for example)
|
|
*/
|
|
if (Flipper.usedKeys.includes(event.keyCode)) {
|
|
event.preventDefault();
|
|
}
|
|
|
|
switch (event.keyCode) {
|
|
case _.keyCodes.TAB:
|
|
this.handleTabPress(event);
|
|
break;
|
|
case _.keyCodes.LEFT:
|
|
case _.keyCodes.UP:
|
|
this.flipLeft();
|
|
break;
|
|
case _.keyCodes.RIGHT:
|
|
case _.keyCodes.DOWN:
|
|
this.flipRight();
|
|
break;
|
|
case _.keyCodes.ENTER:
|
|
this.handleEnterPress(event);
|
|
break;
|
|
}
|
|
}, false);
|
|
}
|
|
|
|
/**
|
|
* Array of keys (codes) that is handled by Flipper
|
|
* Used to:
|
|
* - preventDefault only for this keys, not all keywdowns (@see constructor)
|
|
* - to skip external behaviours only for these keys, when filler is activated (@see BlockEvents@arrowRightAndDown)
|
|
*/
|
|
public static get usedKeys(): number[] {
|
|
return [
|
|
_.keyCodes.TAB,
|
|
_.keyCodes.LEFT,
|
|
_.keyCodes.RIGHT,
|
|
_.keyCodes.ENTER,
|
|
_.keyCodes.UP,
|
|
_.keyCodes.DOWN,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Active tab/arrows handling by flipper
|
|
* @param {HTMLElement[]} items - Some modules (like, InlineToolbar, BlockSettings) might refresh buttons dynamically
|
|
*/
|
|
public activate(items?: HTMLElement[]): void {
|
|
this.activated = true;
|
|
|
|
if (items) {
|
|
this.iterator.setItems(items);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Disable tab/arrows handling by flipper
|
|
*/
|
|
public deactivate(): void {
|
|
this.activated = false;
|
|
this.dropCursor();
|
|
}
|
|
|
|
/**
|
|
* Return current focused button
|
|
* @return {HTMLElement|null}
|
|
*/
|
|
public get currentItem(): HTMLElement|null {
|
|
return this.iterator.currentItem;
|
|
}
|
|
|
|
/**
|
|
* Focus first item
|
|
*/
|
|
public focusFirst(): void {
|
|
this.dropCursor();
|
|
this.flipRight();
|
|
}
|
|
|
|
/**
|
|
* Drops flipper's iterator cursor
|
|
* @see DomIterator#dropCursor
|
|
*/
|
|
private dropCursor(): void {
|
|
this.iterator.dropCursor();
|
|
}
|
|
|
|
/**
|
|
* This function is fired before handling flipper keycodes
|
|
* The result of this function defines if it is need to be handled or not
|
|
* @param {KeyboardEvent} event
|
|
* @return {boolean}
|
|
*/
|
|
private isEventReadyForHandling(event: KeyboardEvent): boolean {
|
|
const handlingKeyCodeList = [
|
|
_.keyCodes.TAB,
|
|
_.keyCodes.ENTER,
|
|
];
|
|
|
|
if (this.allowArrows) {
|
|
handlingKeyCodeList.push(
|
|
_.keyCodes.LEFT,
|
|
_.keyCodes.RIGHT,
|
|
_.keyCodes.UP,
|
|
_.keyCodes.DOWN,
|
|
);
|
|
}
|
|
|
|
if (!this.activated || handlingKeyCodeList.indexOf(event.keyCode) === -1) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* When flipper is activated tab press will leaf the items
|
|
* @param {KeyboardEvent} event
|
|
*/
|
|
private handleTabPress(event: KeyboardEvent): void {
|
|
/** this property defines leaf direction */
|
|
const shiftKey = event.shiftKey,
|
|
direction = shiftKey ? DomIterator.directions.LEFT : DomIterator.directions.RIGHT;
|
|
|
|
switch (direction) {
|
|
case DomIterator.directions.RIGHT:
|
|
this.flipRight();
|
|
break;
|
|
case DomIterator.directions.LEFT:
|
|
this.flipLeft();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Focuses previous flipper iterator item
|
|
*/
|
|
private flipLeft(): void {
|
|
this.iterator.previous();
|
|
}
|
|
|
|
/**
|
|
* Focuses next flipper iterator item
|
|
*/
|
|
private flipRight(): void {
|
|
this.iterator.next();
|
|
}
|
|
|
|
/**
|
|
* Enter press will click current item if flipper is activated
|
|
* @param {KeyboardEvent} event
|
|
*/
|
|
private handleEnterPress(event: KeyboardEvent): void {
|
|
if (!this.activated) {
|
|
return;
|
|
}
|
|
|
|
if (this.iterator.currentItem) {
|
|
this.iterator.currentItem.click();
|
|
}
|
|
|
|
if (typeof this.activateCallback === 'function') {
|
|
this.activateCallback();
|
|
}
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
}
|