1 | import extend from 'extend';
|
2 | import Emitter from '../core/emitter';
|
3 | import BaseTheme, { BaseTooltip } from './base';
|
4 | import { Range } from '../core/selection';
|
5 | import icons from '../ui/icons';
|
6 |
|
7 |
|
8 | const TOOLBAR_CONFIG = [
|
9 | ['bold', 'italic', 'link'],
|
10 | [{ header: 1 }, { header: 2 }, 'blockquote']
|
11 | ];
|
12 |
|
13 | class BubbleTheme extends BaseTheme {
|
14 | constructor(quill, options) {
|
15 | if (options.modules.toolbar != null && options.modules.toolbar.container == null) {
|
16 | options.modules.toolbar.container = TOOLBAR_CONFIG;
|
17 | }
|
18 | super(quill, options);
|
19 | this.quill.container.classList.add('ql-bubble');
|
20 | }
|
21 |
|
22 | extendToolbar(toolbar) {
|
23 | this.tooltip = new BubbleTooltip(this.quill, this.options.bounds);
|
24 | this.tooltip.root.appendChild(toolbar.container);
|
25 | this.buildButtons([].slice.call(toolbar.container.querySelectorAll('button')), icons);
|
26 | this.buildPickers([].slice.call(toolbar.container.querySelectorAll('select')), icons);
|
27 | }
|
28 | }
|
29 | BubbleTheme.DEFAULTS = extend(true, {}, BaseTheme.DEFAULTS, {
|
30 | modules: {
|
31 | toolbar: {
|
32 | handlers: {
|
33 | link: function(value) {
|
34 | if (!value) {
|
35 | this.quill.format('link', false);
|
36 | } else {
|
37 | this.quill.theme.tooltip.edit();
|
38 | }
|
39 | }
|
40 | }
|
41 | }
|
42 | }
|
43 | });
|
44 |
|
45 |
|
46 | class BubbleTooltip extends BaseTooltip {
|
47 | constructor(quill, bounds) {
|
48 | super(quill, bounds);
|
49 | this.quill.on(Emitter.events.EDITOR_CHANGE, (type, range, oldRange, source) => {
|
50 | if (type !== Emitter.events.SELECTION_CHANGE) return;
|
51 | if (range != null && range.length > 0 && source === Emitter.sources.USER) {
|
52 | this.show();
|
53 |
|
54 | this.root.style.left = '0px';
|
55 | this.root.style.width = '';
|
56 | this.root.style.width = this.root.offsetWidth + 'px';
|
57 | let lines = this.quill.getLines(range.index, range.length);
|
58 | if (lines.length === 1) {
|
59 | this.position(this.quill.getBounds(range));
|
60 | } else {
|
61 | let lastLine = lines[lines.length - 1];
|
62 | let index = this.quill.getIndex(lastLine);
|
63 | let length = Math.min(lastLine.length() - 1, range.index + range.length - index);
|
64 | let bounds = this.quill.getBounds(new Range(index, length));
|
65 | this.position(bounds);
|
66 | }
|
67 | } else if (document.activeElement !== this.textbox && this.quill.hasFocus()) {
|
68 | this.hide();
|
69 | }
|
70 | });
|
71 | }
|
72 |
|
73 | listen() {
|
74 | super.listen();
|
75 | this.root.querySelector('.ql-close').addEventListener('click', () => {
|
76 | this.root.classList.remove('ql-editing');
|
77 | });
|
78 | this.quill.on(Emitter.events.SCROLL_OPTIMIZE, () => {
|
79 |
|
80 | setTimeout(() => {
|
81 | if (this.root.classList.contains('ql-hidden')) return;
|
82 | let range = this.quill.getSelection();
|
83 | if (range != null) {
|
84 | this.position(this.quill.getBounds(range));
|
85 | }
|
86 | }, 1);
|
87 | });
|
88 | }
|
89 |
|
90 | cancel() {
|
91 | this.show();
|
92 | }
|
93 |
|
94 | position(reference) {
|
95 | let shift = super.position(reference);
|
96 | let arrow = this.root.querySelector('.ql-tooltip-arrow');
|
97 | arrow.style.marginLeft = '';
|
98 | if (shift === 0) return shift;
|
99 | arrow.style.marginLeft = (-1*shift - arrow.offsetWidth/2) + 'px';
|
100 | }
|
101 | }
|
102 | BubbleTooltip.TEMPLATE = [
|
103 | '<span class="ql-tooltip-arrow"></span>',
|
104 | '<div class="ql-tooltip-editor">',
|
105 | '<input type="text" data-formula="e=mc^2" data-link="https://quilljs.com" data-video="Embed URL">',
|
106 | '<a class="ql-close"></a>',
|
107 | '</div>'
|
108 | ].join('');
|
109 |
|
110 |
|
111 | export { BubbleTooltip, BubbleTheme as default };
|