Skip to content

Commit 384cd1a

Browse files
authored
issue-705: Leaf BlockSettings and InlineTools via keyboard (#723)
* Do not start multi-block selection on UI elements (#662) * Do not start multi-block selection on UI elements * Do not prevent mousedown event on inline toolbar actions * Remove log * Add comment * Add link to issue closes #646 * Fix loss of pointer (#666) * Fix loss of pointer when click is outside of the editor but selection is inside * Remove log * Update shortcuts module (#685) * Fixed possible grammatical typo (#681) Thanks * Update shortcuts module * update changelog * update * Remove margin top for inline-link icon (#690) * Remove margin top for inline-link icon resolves #674 * Update CHANGELOG.md * Remove unused style * Pull fresh tools * Remove changelog contents from readme (#700) * #665 API to open and close inline-toolbar (#711) * API to open and close inline-toolbar * Fixed documentation * renamed inline -> inline-toolbar * removed dist * reset editor.js * added editor.js bundle * Fixed build error * Null checks on toolbar/inline@open * updated bundle * Improve some comments * Updatd api.md CHANGELOG.md * Change feature to new instead of improvement * leaf buttons: initial * leaf inline toolbar buttons * Allow holderId work with ref on dom element (#710) * done * update types * attempt to simplify code * remove useless helper * revert holderId logic and add holder property * Apply suggestions from code review Co-Authored-By: dimensi <[email protected]> * update holder type on string | HTMLElement * fix typo * add deprecated notice and fix typos * fix wrong compare * fix comments * swap console.log on _.log * update types for editor config * update examples * update docs * update build * leaf inline tools and drop index after click * leaf toolbox and clear active button after activation * debugging blockSettings * Activating Open Collective (#736) Hi, I'm making updates for Open Collective. Either you or a supporter signed this repo up for Open Collective. This pull request adds backers and sponsors from your Open Collective https://opencollective.com/editorjs❤️ It adds two badges at the top to show the latest number of backers and sponsors. It also adds placeholders so that the avatar/logo of new backers/sponsors can automatically be shown without having to update your README.md. [more info](https://github.com/opencollective/opencollective/wiki/Github-banner). See how it looks on this [repo](https://github.com/apex/apex#backers). You can also add a postinstall script to let people know after npm|yarn install that you are welcoming donations (optional). [More info](https://github.com/OpenCollective/opencollective-cli) You can also add a "Donate" button to your website and automatically show your backers and sponsors there with our widgets. Have a look here: https://opencollective.com/widgets P.S: As with any pull request, feel free to comment or suggest changes. The only thing "required" are the placeholders on the README because we believe it's important to acknowledge the people in your community that are contributing (financially or with code!). Thank you for your great contribution to the open source community. You are awesome! 🙌 And welcome to the open collective community! 😊 Come chat with us in the #opensource channel on https://slack.opencollective.com - great place to ask questions and share best practices with other open source sustainers! * Do not install editor.js as dev-dependency (#731) Resolves #730 * Move codex-notifier to dependencies for typescript declarations (#728) * Close inline toolbar after creating new link by pressing ENTER (#722) * Method to clear current selection and close inline toolbar * clearSelection with optional collapsed range * refactored selection.ts * removed experimental function * Update src/components/selection.ts Co-Authored-By: tanmayv <[email protected]> * update version, add changelog * Link Logo Image to homepage (#738) * Update README.md (#744) * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md * Update README.md Co-Authored-By: neSpecc <[email protected]> * Config minHeight option that allows to customize bottom zone (#745) * issue-739: allow Block's editable element selection (#747) * issue-739: allow Block's input selection * little improvements * update Changelog and cache inputs * small fix * delete map file * fix inputs.count condition * Fix typo in example paragraph (#749) * Fix typo * Update example-dev.html * minor release * done * requested changes * production build * update package.json * some improvements * ready for testing * update * ready * requested changes * updates * use setToBlock instead of focus * active -> focused * update * refactor types * fix inline tools flipping * inhancements * rm check for focus at the handleShowingEvent * fix IT closing after second enter * add animation to settings buttons * Click animation * Add changelog * do not patch version
1 parent 5a443b2 commit 384cd1a

File tree

11 files changed

+421
-90
lines changed

11 files changed

+421
-90
lines changed

dist/editor.js

+9-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
### 2.14
55

66
- `Fix` *Config* — User config now has higher priority than internal settings
7+
- `New` — Ability to work with Block Actions and Inline Toolbar from the keyboard by Tab.
78

89
### 2.13
910

src/components/dom.ts

+74
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,80 @@ export default class Dom {
520520
}
521521

522522
/**
523+
* Leafs nodes inside the target list from active element
524+
*
525+
* @param {HTMLElement[]} nodeList - target list of nodes
526+
* @param {number} activeIndex — index of active node. By default it must be -1
527+
* @param {string} direction - leaf direction. Can be 'left' or 'right'
528+
* @param {string} activeCSSClass - css class that will be added
529+
*
530+
* @return {Number} index of active node
531+
*/
532+
public static leafNodesAndReturnIndex(nodeList: HTMLElement[], activeIndex: number, direction: string, activeCSSClass: string): number {
533+
/**
534+
* If activeButtonIndex === -1 then we have no chosen Tool in Toolbox
535+
*/
536+
if (activeIndex === -1) {
537+
/**
538+
* Normalize "previous" Tool index depending on direction.
539+
* We need to do this to highlight "first" Tool correctly
540+
*
541+
* Order of Tools: [0] [1] ... [n - 1]
542+
* [0 = n] because of: n % n = 0 % n
543+
*
544+
* Direction 'right': for [0] the [n - 1] is a previous index
545+
* [n - 1] -> [0]
546+
*
547+
* Direction 'left': for [n - 1] the [0] is a previous index
548+
* [n - 1] <- [0]
549+
*
550+
* @type {number}
551+
*/
552+
activeIndex = direction === 'right' ? -1 : 0;
553+
} else {
554+
/**
555+
* If we have chosen Tool then remove highlighting
556+
*/
557+
nodeList[activeIndex].classList.remove(activeCSSClass);
558+
}
559+
560+
/**
561+
* Count index for next Tool
562+
*/
563+
if (direction === 'right') {
564+
/**
565+
* If we go right then choose next (+1) Tool
566+
* @type {number}
567+
*/
568+
activeIndex = (activeIndex + 1) % nodeList.length;
569+
} else {
570+
/**
571+
* If we go left then choose previous (-1) Tool
572+
* Before counting module we need to add length before because of "The JavaScript Modulo Bug"
573+
* @type {number}
574+
*/
575+
activeIndex = (nodeList.length + activeIndex - 1) % nodeList.length;
576+
}
577+
578+
if (Dom.isNativeInput(nodeList[activeIndex])) {
579+
/**
580+
* Focus input
581+
*/
582+
nodeList[activeIndex].focus();
583+
}
584+
585+
/**
586+
* Highlight new chosen Tool
587+
*/
588+
nodeList[activeIndex].classList.add(activeCSSClass);
589+
590+
/**
591+
* Return Active index
592+
*/
593+
return activeIndex;
594+
}
595+
596+
/*
523597
* Helper for get holder from {string} or return HTMLElement
524598
* @param element
525599
*/

src/components/modules/blockEvents.ts

+92-15
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
*/
44
import Module from '../__module';
55
import _ from '../utils';
6+
import SelectionUtils from '../selection';
67

78
export default class BlockEvents extends Module {
9+
810
/**
911
* All keydowns on Block
1012
* @param {KeyboardEvent} event - keydown
@@ -62,7 +64,12 @@ export default class BlockEvents extends Module {
6264
return;
6365
}
6466

65-
this.Editor.Toolbar.close();
67+
/**
68+
* Close Toolbar on any keypress except TAB, because TAB leafs Tools
69+
*/
70+
if (event.keyCode !== _.keyCodes.TAB) {
71+
this.Editor.Toolbar.close();
72+
}
6673

6774
const cmdKey = event.ctrlKey || event.metaKey;
6875
const altKey = event.altKey;
@@ -110,6 +117,10 @@ export default class BlockEvents extends Module {
110117

111118
const {currentBlock} = this.Editor.BlockManager;
112119

120+
if (!currentBlock) {
121+
return;
122+
}
123+
113124
/** Prevent Default behaviour */
114125
event.preventDefault();
115126
event.stopPropagation();
@@ -119,31 +130,77 @@ export default class BlockEvents extends Module {
119130
direction = shiftKey ? 'left' : 'right';
120131

121132
/**
122-
* Don't show Plus and Toolbox near not-inital Tools
133+
* For empty Blocks we show Plus button via Toobox only for initial Blocks
123134
*/
124-
if (!this.Editor.Tools.isInitial(currentBlock.tool)) {
125-
return;
126-
}
127-
128-
if (currentBlock.isEmpty) {
135+
if (this.Editor.Tools.isInitial(currentBlock.tool) && currentBlock.isEmpty) {
136+
/**
137+
* Work with Toolbox
138+
* ------------------
139+
*
140+
* If Toolbox is not open, then just open it and show plus button
141+
* Next Tab press will leaf Toolbox Tools
142+
*/
129143
if (!this.Editor.Toolbar.opened) {
130144
this.Editor.Toolbar.open(false , false);
131145
this.Editor.Toolbar.plusButton.show();
146+
} else {
147+
this.Editor.Toolbox.leaf(direction);
132148
}
133149

134150
this.Editor.Toolbox.open();
135-
}
151+
} else if (!currentBlock.isEmpty && !SelectionUtils.isCollapsed) {
152+
/**
153+
* Work with Inline Tools
154+
* -----------------------
155+
*
156+
* If InlineToolbar is not open, just open it and focus first button
157+
* Next Tab press will leaf InlineToolbar Tools
158+
*/
159+
if (this.Editor.InlineToolbar.opened) {
160+
this.Editor.InlineToolbar.leaf(direction);
161+
}
162+
} else {
163+
/**
164+
* Open Toolbar and show BlockSettings
165+
*/
166+
if (!this.Editor.Toolbar.opened) {
167+
this.Editor.BlockManager.currentBlock.focused = true;
168+
this.Editor.Toolbar.open(true, false);
169+
this.Editor.Toolbar.plusButton.hide();
170+
}
136171

137-
if (this.Editor.Toolbox.opened) {
138-
this.Editor.Toolbox.leaf(direction);
172+
/**
173+
* Work with Block Tunes
174+
* ----------------------
175+
*
176+
* If BlockSettings is not open, then open BlockSettings
177+
* Next Tab press will leaf Settings Buttons
178+
*/
179+
if (!this.Editor.BlockSettings.opened) {
180+
this.Editor.BlockSettings.open();
181+
}
182+
183+
this.Editor.BlockSettings.leaf(direction);
139184
}
140185
}
141186

142187
/**
143188
* Escape pressed
144-
* @param event
189+
* If some of Toolbar components are opened, then close it otherwise close Toolbar
190+
*
191+
* @param {Event} event
145192
*/
146-
public escapePressed(event): void { }
193+
public escapePressed(event): void {
194+
if (this.Editor.Toolbox.opened) {
195+
this.Editor.Toolbox.close();
196+
} else if (this.Editor.BlockSettings.opened) {
197+
this.Editor.BlockSettings.close();
198+
} else if (this.Editor.InlineToolbar.opened) {
199+
this.Editor.InlineToolbar.close();
200+
} else {
201+
this.Editor.Toolbar.close();
202+
}
203+
}
147204

148205
/**
149206
* Add drop target styles
@@ -231,18 +288,31 @@ export default class BlockEvents extends Module {
231288
* Don't handle Enter keydowns when Tool sets enableLineBreaks to true.
232289
* Uses for Tools like <code> where line breaks should be handled by default behaviour.
233290
*/
234-
if (tool && tool[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS]) {
291+
if (tool
292+
&& tool[this.Editor.Tools.apiSettings.IS_ENABLED_LINE_BREAKS]
293+
&& !this.Editor.BlockSettings.opened
294+
&& !this.Editor.InlineToolbar.opened) {
235295
return;
236296
}
237297

238298
if (this.Editor.Toolbox.opened && this.Editor.Toolbox.getActiveTool) {
239299
event.preventDefault();
240300
event.stopPropagation();
241301
event.stopImmediatePropagation();
302+
242303
this.Editor.Toolbox.toolButtonActivate(event, this.Editor.Toolbox.getActiveTool);
243304
return;
244305
}
245306

307+
if (this.Editor.InlineToolbar.opened && this.Editor.InlineToolbar.focusedButton) {
308+
event.preventDefault();
309+
event.stopPropagation();
310+
event.stopImmediatePropagation();
311+
312+
this.Editor.InlineToolbar.focusedButton.click();
313+
return;
314+
}
315+
246316
/**
247317
* Allow to create linebreaks by Shift+Enter
248318
*/
@@ -441,8 +511,15 @@ export default class BlockEvents extends Module {
441511
*/
442512
private needToolbarClosing(event) {
443513
const toolboxItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.Toolbox.opened),
444-
flippingToolboxItems = event.keyCode === _.keyCodes.TAB;
514+
blockSettingsItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.BlockSettings.opened),
515+
flippingToolbarItems = event.keyCode === _.keyCodes.TAB;
445516

446-
return !(event.shiftKey || flippingToolboxItems || toolboxItemSelected);
517+
/**
518+
* Do not close Toolbar in cases:
519+
* 1. ShiftKey pressed (or combination with shiftKey)
520+
* 2. When Toolbar is opened and Tab leafs its Tools
521+
* 3. When Toolbar's component is opened and some its item selected
522+
*/
523+
return !(event.shiftKey || flippingToolbarItems || toolboxItemSelected || blockSettingsItemSelected);
447524
}
448525
}

0 commit comments

Comments
 (0)