diff --git a/core/quill.js b/core/quill.js index 9a3b91b049..7e7ea80ce8 100644 --- a/core/quill.js +++ b/core/quill.js @@ -45,7 +45,7 @@ class Quill { let html = this.container.innerHTML; this.container.classList.add('ql-container'); this.container.innerHTML = ''; - this.controls = {}; + this.controls = {}; // TODO make into API this.modules = {}; // TODO scroll will reset innerHTML as well, do not do twice this.root = this.addContainer('ql-editor'); @@ -117,16 +117,17 @@ class Quill { this.selection.focus(); } - formatCursor(name, value, source = Emitter.sources.API) { + format(name, value, source = Emitter.sources.API) { let range = this.getSelection(); if (range == null) return; if (Parchment.query(name, Parchment.Scope.BLOCK)) { this.formatLine(range, name, value, source); } else if (range.length === 0) { - this.selection.format(name, value); + return this.selection.format(name, value); } else { this.formatText(range, name, value, source); } + this.setSelection(range, Emitter.sources.SILENT); } formatLine(index, length, name, value, source) { @@ -181,6 +182,10 @@ class Quill { return this.editor.getText(index, length); } + hasFocus() { + return this.selection.hasFocus(); + } + insertEmbed(index, embed, value, source) { this.editor.insertEmbed(index, embed, value, source); } diff --git a/core/selection.js b/core/selection.js index 8a8949d3d3..c8f91ed3a8 100644 --- a/core/selection.js +++ b/core/selection.js @@ -38,12 +38,8 @@ class Selection { this.update(Emitter.sources.SILENT); } - checkFocus() { - return document.activeElement === this.root; - } - focus() { - if (this.checkFocus()) return; + if (this.hasFocus()) return; this.root.focus(); this.setRange(this.savedRange); } @@ -155,7 +151,7 @@ class Selection { } getRange() { - if (!this.checkFocus()) return [null, null]; + if (!this.hasFocus()) return [null, null]; let range = this.getNativeRange(); if (range == null) return [null, null]; let positions = [[range.start.node, range.start.offset]]; @@ -178,6 +174,10 @@ class Selection { return [new Range(start, end-start), range]; } + hasFocus() { + return document.activeElement === this.root; + } + scrollIntoView() { if (this.lastRange == null) return; let startBounds = this.getBounds(this.lastRange.start); @@ -197,7 +197,7 @@ class Selection { let selection = document.getSelection(); if (selection == null) return; if (startNode != null) { - if (!this.checkFocus()) this.root.focus(); + if (!this.hasFocus()) this.root.focus(); let nativeRange = this.getNativeRange(); if (nativeRange == null || startNode !== nativeRange.start.node || startOffset !== nativeRange.start.offset || diff --git a/modules/keyboard.js b/modules/keyboard.js index 97544576e2..7c0f73f75f 100644 --- a/modules/keyboard.js +++ b/modules/keyboard.js @@ -52,9 +52,9 @@ class Keyboard extends Module { onDelete(backspace, range) { if (range.length > 0) { - this.quill.deleteText(range, Quill.sources.USER); + this.quill.deleteText(range, Emitter.sources.USER); } else if (!backspace) { - this.quill.deleteText(range.index, 1, Quill.sources.USER); + this.quill.deleteText(range.index, 1, Emitter.sources.USER); } else { let [line, offset] = this.quill.scroll.descendant(Block, range.index); let formats = this.quill.getFormat(range); @@ -65,11 +65,11 @@ class Keyboard extends Module { line.format('list', false); } } else { - this.quill.deleteText(range.index - 1, 1, Quill.sources.USER); + this.quill.deleteText(range.index - 1, 1, Emitter.sources.USER); range = new Range(Math.max(0, range.index - 1)); } } - this.quill.setSelection(range.index, Quill.sources.SILENT); + this.quill.setSelection(range.index, Emitter.sources.SILENT); } onEnter(range) { @@ -84,8 +84,8 @@ class Keyboard extends Module { .retain(range.index) .insert('\n', lineFormats) .delete(range.length); - this.quill.updateContents(delta, Quill.sources.USER); - this.quill.setSelection(range.index + 1, Quill.sources.SILENT); + this.quill.updateContents(delta, Emitter.sources.USER); + this.quill.setSelection(range.index + 1, Emitter.sources.SILENT); Object.keys(formats).forEach((name) => { if (lineFormats[name] == null) { this.quill.formatCursor(name, formats[name]); @@ -95,16 +95,13 @@ class Keyboard extends Module { onFormat(format, range) { let formats = this.quill.getFormat(range); - this.quill.formatCursor(format, !formats[format], Quill.sources.USER); - if (range.length !== 0) { - this.quill.setSelection(range, Quill.sources.SILENT); - } + this.quill.format(format, formats[format], Emitter.sources.USER); } onTab(range, evt) { if (range.length === 0) { let delta = new Delta().retain(range.index).insert('\t').delete(range.length); - this.quill.updateContents(delta, Quill.sources.USER); + this.quill.updateContents(delta, Emitter.sources.USER); this.quill.setSelection(range.index + 1, Emitter.sources.SILENT); } else { let modifier = evt.shiftKey ? -1 : 1; @@ -113,7 +110,7 @@ class Keyboard extends Module { let indent = parseInt(format['indent'] || 0); line.format('indent', Math.max(0, indent + modifier)); }); - this.quill.update(Quill.sources.USER); + this.quill.update(Emitter.sources.USER); this.quill.setSelection(range, Emitter.sources.SILENT); } } diff --git a/modules/toolbar.js b/modules/toolbar.js index 7880b0874d..ea1f8cbe09 100644 --- a/modules/toolbar.js +++ b/modules/toolbar.js @@ -1,4 +1,5 @@ import extend from 'extend'; +import Emitter from '../core/emitter'; import Parchment from 'parchment'; import Module from '../core/module'; import logger from '../core/logger'; @@ -41,34 +42,23 @@ class Toolbar extends Module { // if (this.quill.options.formats.indexOf(format) < 0) return; // TODO enable let eventName = input.tagName === 'SELECT' ? 'change' : 'click'; input.addEventListener(eventName, () => { - let range = this.quill.getSelection(true); - if (range == null) return false; + this.quill.focus(); let value; if (input.tagName === 'SELECT') { value = input.options[input.selectedIndex].value || false; } else { value = input.classList.contains('ql-active') ? false : input.getAttribute('data-value') || true; } - let handler = this.quill.controls[format] || this.handle.bind(this); - handler(range, format, value); - this.update(); + if (this.quill.controls[format]) { + this.quill.controls[format](format, value); + } else { + this.quill.format(format, value, Emitter.sources.USER); + } }); // TODO use weakmap this.controls.push([format, input]); } - handle(range, format, value) { - if (Parchment.query(format, Parchment.Scope.BLOCK)) { - this.quill.formatLine(range, format, value, Quill.sources.USER); - } else if (range.length === 0) { - this.quill.formatCursor(format, value, Quill.sources.USER); - return; - } else { - this.quill.formatText(range, format, value, Quill.sources.USER); - } - this.quill.setSelection(range, Quill.sources.SILENT); - } - update() { let range = this.quill.getSelection(); if (range == null) return; diff --git a/test/unit/selection.js b/test/unit/selection.js index ae01385c2f..a6e20db68e 100644 --- a/test/unit/selection.js +++ b/test/unit/selection.js @@ -21,9 +21,9 @@ describe('Selection', function() { }); it('initial focus', function() { - expect(this.selection.checkFocus()).toBe(false); + expect(this.selection.hasFocus()).toBe(false); this.selection.focus(); - expect(this.selection.checkFocus()).toBe(true); + expect(this.selection.hasFocus()).toBe(true); }); it('restore last range', function() { @@ -31,9 +31,9 @@ describe('Selection', function() { this.selection.setRange(range); this.textarea.focus(); this.textarea.select(); - expect(this.selection.checkFocus()).toBe(false); + expect(this.selection.hasFocus()).toBe(false); this.selection.focus(); - expect(this.selection.checkFocus()).toBe(true); + expect(this.selection.hasFocus()).toBe(true); expect(this.selection.getRange()[0]).toEqual(range); }); }); @@ -162,7 +162,7 @@ describe('Selection', function() { selection.setRange(expected); let [range, ] = selection.getRange(); expect(range).toEqual(expected); - expect(selection.checkFocus()).toBe(true); + expect(selection.hasFocus()).toBe(true); }); it('empty lines', function() { @@ -176,7 +176,7 @@ describe('Selection', function() { selection.setRange(expected); let [range, ] = selection.getRange(); expect(range).toEqual(range); - expect(selection.checkFocus()).toBe(true); + expect(selection.hasFocus()).toBe(true); }); it('nested text node', function() { @@ -190,7 +190,7 @@ describe('Selection', function() { selection.setRange(expected); let [range, ] = selection.getRange(); expect(range).toEqual(expected); - expect(selection.checkFocus()).toBe(true); + expect(selection.hasFocus()).toBe(true); }); it('between inlines', function() { @@ -199,7 +199,7 @@ describe('Selection', function() { selection.setRange(expected); let [range, ] = selection.getRange(); expect(range).toEqual(expected); - expect(selection.checkFocus()).toBe(true); + expect(selection.hasFocus()).toBe(true); }); it('between embeds', function() { @@ -219,7 +219,7 @@ describe('Selection', function() { selection.setRange(expected); let [range, ] = selection.getRange(); expect(range).toEqual(expected); - expect(selection.checkFocus()).toBe(true); + expect(selection.hasFocus()).toBe(true); }); it('null', function() { @@ -230,7 +230,7 @@ describe('Selection', function() { selection.setRange(null); [range, ] = selection.getRange(); expect(range).toEqual(null); - expect(selection.checkFocus()).toBe(false); + expect(selection.hasFocus()).toBe(false); }); });