forked from zicloud/bigscreen_admin
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
3.2 KiB
JavaScript
95 lines
3.2 KiB
JavaScript
import { ParentBlot } from 'parchment';
|
|
import Module from '../core/module.js';
|
|
import Quill from '../core/quill.js';
|
|
const isMac = /Mac/i.test(navigator.platform);
|
|
|
|
// Export for testing
|
|
export const TTL_FOR_VALID_SELECTION_CHANGE = 100;
|
|
|
|
// A loose check to determine if the shortcut can move the caret before a UI node:
|
|
// <ANY_PARENT>[CARET]<div class="ql-ui"></div>[CONTENT]</ANY_PARENT>
|
|
const canMoveCaretBeforeUINode = event => {
|
|
if (event.key === 'ArrowLeft' || event.key === 'ArrowRight' ||
|
|
// RTL scripts or moving from the end of the previous line
|
|
event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Home') {
|
|
return true;
|
|
}
|
|
if (isMac && event.key === 'a' && event.ctrlKey === true) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
class UINode extends Module {
|
|
isListening = false;
|
|
selectionChangeDeadline = 0;
|
|
constructor(quill, options) {
|
|
super(quill, options);
|
|
this.handleArrowKeys();
|
|
this.handleNavigationShortcuts();
|
|
}
|
|
handleArrowKeys() {
|
|
this.quill.keyboard.addBinding({
|
|
key: ['ArrowLeft', 'ArrowRight'],
|
|
offset: 0,
|
|
shiftKey: null,
|
|
handler(range, _ref) {
|
|
let {
|
|
line,
|
|
event
|
|
} = _ref;
|
|
if (!(line instanceof ParentBlot) || !line.uiNode) {
|
|
return true;
|
|
}
|
|
const isRTL = getComputedStyle(line.domNode)['direction'] === 'rtl';
|
|
if (isRTL && event.key !== 'ArrowRight' || !isRTL && event.key !== 'ArrowLeft') {
|
|
return true;
|
|
}
|
|
this.quill.setSelection(range.index - 1, range.length + (event.shiftKey ? 1 : 0), Quill.sources.USER);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
handleNavigationShortcuts() {
|
|
this.quill.root.addEventListener('keydown', event => {
|
|
if (!event.defaultPrevented && canMoveCaretBeforeUINode(event)) {
|
|
this.ensureListeningToSelectionChange();
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* We only listen to the `selectionchange` event when
|
|
* there is an intention of moving the caret to the beginning using shortcuts.
|
|
* This is primarily implemented to prevent infinite loops, as we are changing
|
|
* the selection within the handler of a `selectionchange` event.
|
|
*/
|
|
ensureListeningToSelectionChange() {
|
|
this.selectionChangeDeadline = Date.now() + TTL_FOR_VALID_SELECTION_CHANGE;
|
|
if (this.isListening) return;
|
|
this.isListening = true;
|
|
const listener = () => {
|
|
this.isListening = false;
|
|
if (Date.now() <= this.selectionChangeDeadline) {
|
|
this.handleSelectionChange();
|
|
}
|
|
};
|
|
document.addEventListener('selectionchange', listener, {
|
|
once: true
|
|
});
|
|
}
|
|
handleSelectionChange() {
|
|
const selection = document.getSelection();
|
|
if (!selection) return;
|
|
const range = selection.getRangeAt(0);
|
|
if (range.collapsed !== true || range.startOffset !== 0) return;
|
|
const line = this.quill.scroll.find(range.startContainer);
|
|
if (!(line instanceof ParentBlot) || !line.uiNode) return;
|
|
const newRange = document.createRange();
|
|
newRange.setStartAfter(line.uiNode);
|
|
newRange.setEndAfter(line.uiNode);
|
|
selection.removeAllRanges();
|
|
selection.addRange(newRange);
|
|
}
|
|
}
|
|
export default UINode;
|
|
//# sourceMappingURL=uiNode.js.map
|