suneditor
Version:
Vanilla JavaScript based WYSIWYG web editor
111 lines (99 loc) • 3.28 kB
JavaScript
import { dom } from '../../../helper';
/**
* @description Manages editor focus and blur behavior across frames and controllers.
*/
export default class FocusManager {
#kernel;
#$;
#store;
#options;
#frameContext;
#frameOptions;
/**
* @constructor
* @param {SunEditor.Kernel} kernel
*/
constructor(kernel) {
this.#kernel = kernel;
this.#$ = kernel.$;
this.#store = kernel.store;
this.#options = this.#$.options;
this.#frameContext = this.#$.frameContext;
this.#frameOptions = this.#$.frameOptions;
}
/**
* @description Focus to wysiwyg area
* @param {*} [rootKey] Root frame key.
*/
focus(rootKey) {
if (rootKey) this.#$.facade.changeFrameContext(rootKey);
if (this.#frameContext.get('wysiwygFrame').style.display === 'none') return;
this.#store.set('_preventBlur', false);
if (this.#frameOptions.get('iframe') || !this.#frameContext.get('wysiwyg').contains(this.#$.selection.getNode())) {
this.nativeFocus();
} else {
try {
const range = this.#$.selection.getRange();
if (range.startContainer === range.endContainer && dom.check.isWysiwygFrame(range.startContainer)) {
const currentNode = /** @type {HTMLElement} */ (range.commonAncestorContainer).children[range.startOffset];
if (!this.#$.format.isLine(currentNode) && !this.#$.component.is(currentNode)) {
const br = dom.utils.createElement('BR');
const format = dom.utils.createElement(this.#options.get('defaultLine'), null, br);
this.#frameContext.get('wysiwyg').insertBefore(format, currentNode);
this.#$.selection.setRange(br, 0, br, 0);
return;
}
}
this.#$.selection.setRange(range.startContainer, range.startOffset, range.endContainer, range.endOffset);
} catch (e) {
console.warn('[SUNEDITOR.focus.warn] ', e);
this.nativeFocus();
}
}
if (this.#store.mode.isBalloon) this.#kernel._eventOrchestrator._toggleToolbarBalloon();
}
/**
* @description If `focusEl` is a component, then that component is selected; if it is a format element, the last text is selected
* - If `focusEl` is `null`, then selected last element
* @param {?Node} [focusEl] Focus element
*/
focusEdge(focusEl) {
this.#store.set('_preventBlur', false);
focusEl ||= this.#frameContext.get('wysiwyg').lastElementChild;
const fileComponentInfo = this.#$.component.get(focusEl);
if (fileComponentInfo) {
this.#$.component.select(fileComponentInfo.target, fileComponentInfo.pluginName);
} else if (focusEl) {
if (focusEl.nodeType !== 3) {
focusEl = dom.query.getEdgeChild(
focusEl,
function (current) {
return current.childNodes.length === 0 || current.nodeType === 3;
},
true,
);
}
if (!focusEl) this.nativeFocus();
else this.#$.selection.setRange(focusEl, focusEl.textContent.length, focusEl, focusEl.textContent.length);
} else {
this.focus();
}
}
/**
* @description Focus to wysiwyg area using native focus function
*/
nativeFocus() {
this.#$.selection.__focus();
this.#$.selection.init();
}
/**
* @description Focusout to wysiwyg area (.blur())
*/
blur() {
if (this.#frameOptions.get('iframe')) {
this.#frameContext.get('wysiwygFrame').blur();
} else {
this.#frameContext.get('wysiwyg').blur();
}
}
}