Fake background when selection is reseted by input field on toolbar (#560)

* Fake selection works

* some styles

* Refactoring fake background

* transition in SelectionUtils

* explanation

* refactoring

* fix

* build
This commit is contained in:
horoyami 2018-12-17 19:51:16 +03:00 committed by GitHub
parent 78e922ae1d
commit 518866a575
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 77 additions and 18 deletions

12
dist/codex-editor.js vendored

File diff suppressed because one or more lines are too long

View file

@ -4,6 +4,7 @@ import $ from '../dom';
import _ from '../utils';
import {API, InlineTool, SanitizerConfig} from '../../../types';
import {Notifier, Toolbar} from '../../../types/api';
/**
* Link Tool
*
@ -137,7 +138,14 @@ export default class LinkInlineTool implements InlineTool {
/**
* Save selection before change focus to the input
*/
this.selection.save();
if (!this.inputOpened) {
/** Create blue background instead of selection */
this.selection.setFakeBackground();
this.selection.save();
} else {
this.selection.restore();
this.selection.removeFakeBackground();
}
const parentAnchor = this.selection.findParentTag('A');
/**
@ -222,6 +230,16 @@ export default class LinkInlineTool implements InlineTool {
* on toggle-clicks on the icon of opened Toolbar
*/
private closeActions(clearSavedSelection: boolean = true): void {
// if actions is broken by other selection We need to save new selection
const currentSelection = new SelectionUtils();
currentSelection.save();
this.selection.restore();
this.selection.removeFakeBackground();
// and recover new selection after removing fake background
currentSelection.restore();
this.nodes.input.classList.remove(this.CSS.inputShowed);
this.nodes.input.value = '';
if (clearSavedSelection) {
@ -258,6 +276,8 @@ export default class LinkInlineTool implements InlineTool {
value = this.prepareLink(value);
this.selection.restore();
this.selection.removeFakeBackground();
this.insertLink(value);
/**

View file

@ -37,10 +37,10 @@ export default class SelectionUtils {
* Editor styles
* @return {{editorWrapper: string, editorZone: string}}
*/
static get CSS(): {editorWrapper: string, editorZone: string} {
static get CSS(): { editorWrapper: string, editorZone: string } {
return {
editorWrapper : 'codex-editor',
editorZone : 'codex-editor__redactor',
editorWrapper: 'codex-editor',
editorZone: 'codex-editor__redactor',
};
}
@ -49,7 +49,7 @@ export default class SelectionUtils {
* {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorNode}
* @return {Node|null}
*/
static get anchorNode(): Node|null {
static get anchorNode(): Node | null {
const selection = window.getSelection();
return selection ? selection.anchorNode : null;
@ -60,7 +60,7 @@ export default class SelectionUtils {
* {@link https://developer.mozilla.org/ru/docs/Web/API/Selection/anchorOffset}
* @return {Number|null}
*/
static get anchorOffset(): number|null {
static get anchorOffset(): number | null {
const selection = window.getSelection();
return selection ? selection.anchorOffset : null;
@ -70,7 +70,7 @@ export default class SelectionUtils {
* Is current selection range collapsed
* @return {boolean|null}
*/
static get isCollapsed(): boolean|null {
static get isCollapsed(): boolean | null {
const selection = window.getSelection();
return selection ? selection.isCollapsed : null;
@ -117,9 +117,9 @@ export default class SelectionUtils {
* Calculates position and size of selected text
* @return {{x, y, width, height, top?, left?, bottom?, right?}}
*/
static get rect(): DOMRect|ClientRect {
let sel: Selection|MSSelection = (document as Document).selection,
range: TextRange|Range;
static get rect(): DOMRect | ClientRect {
let sel: Selection | MSSelection = (document as Document).selection,
range: TextRange | Range;
let rect = {
x: 0,
@ -163,7 +163,7 @@ export default class SelectionUtils {
if (span.getBoundingClientRect) {
// Ensure span has dimensions and position by
// adding a zero-width space character
span.appendChild( document.createTextNode('\u200b') );
span.appendChild(document.createTextNode('\u200b'));
range.insertNode(span);
rect = span.getBoundingClientRect() as DOMRect;
@ -205,6 +205,45 @@ export default class SelectionUtils {
*/
public savedSelectionRange: Range = null;
/**
* Fake background is active
*
* @return {boolean}
*/
private fakeBackground = false;
/**
* Native Document's commands for fake background
*/
private readonly commandBackground: string = 'backColor';
private readonly commandRemoveFormat: string = 'removeFormat';
/**
* Removes fake background
*/
public removeFakeBackground() {
if (!this.fakeBackground) {
return;
}
const fakeBack = this.findParentTag('SPAN');
fakeBack.style.paddingTop = '';
this.fakeBackground = false;
document.execCommand(this.commandRemoveFormat);
}
/**
* Sets fake background
*/
public setFakeBackground() {
document.execCommand(this.commandBackground, false, '#a8d6ff');
const fakeBack = this.findParentTag('SPAN');
// The matched value to be slightly compared with the actual height of the selection
fakeBack.style.paddingTop = '0.30em';
this.fakeBackground = true;
}
/**
* Save SelectionUtils's range
*/
@ -241,7 +280,7 @@ export default class SelectionUtils {
* @param {Number} [searchDepth] - count of tags that can be included. For better performance.
* @return {HTMLElement|null}
*/
public findParentTag(tagName: string, className?: string, searchDepth = 10): HTMLElement|null {
public findParentTag(tagName: string, className?: string, searchDepth = 10): HTMLElement | null {
const selection = window.getSelection();
let parentTag = null;