Enable editor autofocus (#581)

This commit is contained in:
George Berezhnoy 2019-01-12 03:44:43 +03:00 committed by GitHub
parent e8d43c8fc7
commit da9255a98d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 60 additions and 32 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,9 @@
# Changelog # Changelog
### 2.2.25 changelog
- `New` *Autofocus — Now you can set focus at Editor after page has been loaded
### 2.2.24 changelog ### 2.2.24 changelog
- `Improvements` *Paste handling — minor paste handling improvements - `Improvements` *Paste handling — minor paste handling improvements

View file

@ -56,3 +56,17 @@ var editor = CodexEditor({
}); });
``` ```
## Autofocus
If you want to focus Editor after page has been loaded, you can enable autofocus by passing `autofocus` to the initial config
```js
var editor = CodexEditor({
//...
autofocus: true
//...
});
```

View file

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

View file

@ -78,6 +78,12 @@ export default class Core {
_.log('I\'m ready! (ノ◕ヮ◕)ノ*:・゚✧', 'log', '', 'color: #E24A75'); _.log('I\'m ready! (ノ◕ヮ◕)ノ*:・゚✧', 'log', '', 'color: #E24A75');
setTimeout(() => { setTimeout(() => {
if ((this.configuration as EditorConfig).autofocus) {
const {BlockManager, Caret} = this.moduleInstances;
Caret.setToBlock(BlockManager.blocks[0], Caret.positions.START);
}
/** /**
* Remove loader, show content * Remove loader, show content
*/ */

View file

@ -3,7 +3,6 @@
*/ */
import Module from '../__module'; import Module from '../__module';
import _ from '../utils'; import _ from '../utils';
import CaretClass from './caret';
export default class BlockEvents extends Module { export default class BlockEvents extends Module {
/** /**
@ -217,7 +216,7 @@ export default class BlockEvents extends Module {
BlockManager.removeAllBlocks(); BlockManager.removeAllBlocks();
} else { } else {
BlockManager.removeBlock(); BlockManager.removeBlock();
Caret.setToBlock(BlockManager.insert(), CaretClass.positions.START); Caret.setToBlock(BlockManager.insert(), Caret.positions.START);
} }
/** Clear selection */ /** Clear selection */
@ -331,7 +330,7 @@ export default class BlockEvents extends Module {
BlockManager.insert(); BlockManager.insert();
} }
Caret.setToBlock(BlockManager.currentBlock, CaretClass.positions.END); Caret.setToBlock(BlockManager.currentBlock, Caret.positions.END);
} }
/** Close Toolbar */ /** Close Toolbar */

View file

@ -12,7 +12,6 @@ import $ from '../dom';
import _ from '../utils'; import _ from '../utils';
import Blocks from '../blocks'; import Blocks from '../blocks';
import {BlockTool, BlockToolConstructable, BlockToolData, PasteEvent, ToolConfig} from '../../../types'; import {BlockTool, BlockToolConstructable, BlockToolData, PasteEvent, ToolConfig} from '../../../types';
import Caret from './caret';
/** /**
* @typedef {BlockManager} BlockManager * @typedef {BlockManager} BlockManager
@ -412,7 +411,10 @@ export default class BlockManager extends Module {
* @param {string} caretPosition - position where to set caret * @param {string} caretPosition - position where to set caret
* @throws Error - when passed Node is not included at the Block * @throws Error - when passed Node is not included at the Block
*/ */
public setCurrentBlockByChildNode(childNode: Node, caretPosition: string = Caret.positions.DEFAULT): void { public setCurrentBlockByChildNode(
childNode: Node,
caretPosition: string = this.Editor.Caret.positions.DEFAULT,
): void {
/** /**
* If node is Text TextNode * If node is Text TextNode
*/ */

View file

@ -26,7 +26,7 @@ export default class Caret extends Module {
* @static * @static
* @returns {{START: string, END: string, DEFAULT: string}} * @returns {{START: string, END: string, DEFAULT: string}}
*/ */
public static get positions(): {START: string, END: string, DEFAULT: string} { public get positions(): {START: string, END: string, DEFAULT: string} {
return { return {
START: 'start', START: 'start',
END: 'end', END: 'end',
@ -161,15 +161,15 @@ export default class Caret extends Module {
* If default - leave default behaviour and apply offset if it's passed * If default - leave default behaviour and apply offset if it's passed
* @param {Number} offset - caret offset regarding to the text node * @param {Number} offset - caret offset regarding to the text node
*/ */
public setToBlock(block: Block, position: string = Caret.positions.DEFAULT, offset: number = 0): void { public setToBlock(block: Block, position: string = this.positions.DEFAULT, offset: number = 0): void {
const {BlockManager} = this.Editor; const {BlockManager} = this.Editor;
let element; let element;
switch (position) { switch (position) {
case Caret.positions.START: case this.positions.START:
element = block.firstInput; element = block.firstInput;
break; break;
case Caret.positions.END: case this.positions.END:
element = block.lastInput; element = block.lastInput;
break; break;
default: default:
@ -180,14 +180,14 @@ export default class Caret extends Module {
return; return;
} }
const nodeToSet = $.getDeepestNode(element, position === Caret.positions.END); const nodeToSet = $.getDeepestNode(element, position === this.positions.END);
const contentLength = $.getContentLength(nodeToSet); const contentLength = $.getContentLength(nodeToSet);
switch (true) { switch (true) {
case position === Caret.positions.START: case position === this.positions.START:
offset = 0; offset = 0;
break; break;
case position === Caret.positions.END: case position === this.positions.END:
case offset > contentLength: case offset > contentLength:
offset = contentLength; offset = contentLength;
break; break;
@ -212,16 +212,16 @@ export default class Caret extends Module {
* If default - leave default behaviour and apply offset if it's passed * If default - leave default behaviour and apply offset if it's passed
* @param {number} offset - caret offset regarding to the text node * @param {number} offset - caret offset regarding to the text node
*/ */
public setToInput(input: HTMLElement, position: string = Caret.positions.DEFAULT, offset: number = 0): void { public setToInput(input: HTMLElement, position: string = this.positions.DEFAULT, offset: number = 0): void {
const {currentBlock} = this.Editor.BlockManager; const {currentBlock} = this.Editor.BlockManager;
const nodeToSet = $.getDeepestNode(input); const nodeToSet = $.getDeepestNode(input);
switch (position) { switch (position) {
case Caret.positions.START: case this.positions.START:
this.set(nodeToSet as HTMLElement, 0); this.set(nodeToSet as HTMLElement, 0);
break; break;
case Caret.positions.END: case this.positions.END:
const contentLength = $.getContentLength(nodeToSet); const contentLength = $.getContentLength(nodeToSet);
this.set(nodeToSet as HTMLElement, contentLength); this.set(nodeToSet as HTMLElement, contentLength);
@ -333,16 +333,16 @@ export default class Caret extends Module {
} }
if (force) { if (force) {
this.setToBlock(nextContentfulBlock, Caret.positions.START); this.setToBlock(nextContentfulBlock, this.positions.START);
return true; return true;
} }
if (this.isAtEnd) { if (this.isAtEnd) {
/** If next Tool`s input exists, focus on it. Otherwise set caret to the next Block */ /** If next Tool`s input exists, focus on it. Otherwise set caret to the next Block */
if (!nextInput) { if (!nextInput) {
this.setToBlock(nextContentfulBlock, Caret.positions.START); this.setToBlock(nextContentfulBlock, this.positions.START);
} else { } else {
this.setToInput(nextInput, Caret.positions.START); this.setToInput(nextInput, this.positions.START);
} }
return true; return true;
@ -374,16 +374,16 @@ export default class Caret extends Module {
} }
if (force) { if (force) {
this.setToBlock( previousContentfulBlock, Caret.positions.END ); this.setToBlock( previousContentfulBlock, this.positions.END );
return true; return true;
} }
if (this.isAtStart) { if (this.isAtStart) {
/** If previous Tool`s input exists, focus on it. Otherwise set caret to the previous Block */ /** If previous Tool`s input exists, focus on it. Otherwise set caret to the previous Block */
if (!previousInput) { if (!previousInput) {
this.setToBlock( previousContentfulBlock, Caret.positions.END ); this.setToBlock( previousContentfulBlock, this.positions.END );
} else { } else {
this.setToInput(previousInput, Caret.positions.END); this.setToInput(previousInput, this.positions.END);
} }
return true; return true;
} }

View file

@ -1,8 +1,6 @@
import SelectionUtils from '../selection'; import SelectionUtils from '../selection';
import Module from '../__module'; import Module from '../__module';
import Caret from './caret';
export default class DragNDrop extends Module { export default class DragNDrop extends Module {
/** /**
@ -50,6 +48,7 @@ export default class DragNDrop extends Module {
private processDrop = async (dropEvent: DragEvent): Promise<void> => { private processDrop = async (dropEvent: DragEvent): Promise<void> => {
const { const {
BlockManager, BlockManager,
Caret,
Paste, Paste,
} = this.Editor; } = this.Editor;

View file

@ -1,4 +1,3 @@
import CaretClass from './caret';
import Module from '../__module'; import Module from '../__module';
import $ from '../dom'; import $ from '../dom';
import _ from '../utils'; import _ from '../utils';
@ -448,7 +447,7 @@ export default class Paste extends Module {
async (content, i) => await this.insertBlock(content, i === 0 && needToReplaceCurrentBlock), async (content, i) => await this.insertBlock(content, i === 0 && needToReplaceCurrentBlock),
)); ));
Caret.setToBlock(BlockManager.currentBlock, CaretClass.positions.END); Caret.setToBlock(BlockManager.currentBlock, Caret.positions.END);
} }
/** /**
@ -585,7 +584,7 @@ export default class Paste extends Module {
insertedBlock = BlockManager.paste(blockData.tool, blockData.event, needToReplaceCurrentBlock); insertedBlock = BlockManager.paste(blockData.tool, blockData.event, needToReplaceCurrentBlock);
Caret.setToBlock(insertedBlock, CaretClass.positions.END); Caret.setToBlock(insertedBlock, Caret.positions.END);
return; return;
} }
} }
@ -645,13 +644,13 @@ export default class Paste extends Module {
if (canReplaceCurrentBlock && currentBlock && currentBlock.isEmpty) { if (canReplaceCurrentBlock && currentBlock && currentBlock.isEmpty) {
block = BlockManager.paste(data.tool, data.event, true); block = BlockManager.paste(data.tool, data.event, true);
Caret.setToBlock(block, CaretClass.positions.END); Caret.setToBlock(block, Caret.positions.END);
return; return;
} }
block = BlockManager.paste(data.tool, data.event); block = BlockManager.paste(data.tool, data.event);
Caret.setToBlock(block, CaretClass.positions.END); Caret.setToBlock(block, Caret.positions.END);
} }
/** /**

View file

@ -8,6 +8,11 @@ export interface EditorConfig {
*/ */
holderId?: string; holderId?: string;
/**
* If true, set caret at the first Block after Editor is ready
*/
autofocus?: boolean;
/** /**
* This Tool will be used as default * This Tool will be used as default
* Name should be equal to one of Tool`s keys of passed tools * Name should be equal to one of Tool`s keys of passed tools