jodit
Version:
Jodit is an awesome and useful wysiwyg editor with filebrowser
160 lines (159 loc) • 6.2 kB
JavaScript
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
*/
import { INVISIBLE_SPACE, MODE_WYSIWYG } from "../../core/constants.js";
import { Dom } from "../../core/dom/index.js";
import { pluginSystem } from "../../core/global.js";
import { trim } from "../../core/helpers/string/trim.js";
import { attr } from "../../core/helpers/utils/attr.js";
import { getXPathByElement } from "../../core/helpers/utils/selector.js";
import { Plugin } from "../../core/plugin/index.js";
import { ContextMenu } from "../../modules/context-menu/context-menu.js";
import { makeButton } from "../../modules/toolbar/factory.js";
import "./config.js";
/**
* Show a path to a current element in status bar
*/
class xpath extends Plugin {
constructor() {
super(...arguments);
this.onContext = (bindElement, event) => {
if (!this.menu) {
this.menu = new ContextMenu(this.j);
}
this.menu.show(event.clientX, event.clientY, [
{
icon: 'bin',
title: bindElement === this.j.editor ? 'Clear' : 'Remove',
exec: () => {
if (bindElement !== this.j.editor) {
Dom.safeRemove(bindElement);
}
else {
this.j.value = '';
}
this.j.synchronizeValues();
}
},
{
icon: 'select-all',
title: 'Select',
exec: () => {
this.j.s.select(bindElement);
}
}
]);
return false;
};
this.onSelectPath = (bindElement, event) => {
this.j.s.focus();
const path = attr(event.target, '-path') || '/';
if (path === '/') {
this.j.execCommand('selectall');
return false;
}
try {
const elm = this.j.ed
.evaluate(path, this.j.editor, null, XPathResult.ANY_TYPE, null)
.iterateNext();
if (elm) {
this.j.s.select(elm);
return false;
}
}
catch (_a) { }
this.j.s.select(bindElement);
return false;
};
this.tpl = (bindElement, path, name, title) => {
const item = this.j.c.fromHTML(`<span class="jodit-xpath__item"><a role="button" data-path="${path}" title="${title}" tabindex="-1"'>${trim(name)}</a></span>`);
const a = item.firstChild;
this.j.e
.on(a, 'click', this.onSelectPath.bind(this, bindElement))
.on(a, 'contextmenu', this.onContext.bind(this, bindElement));
return item;
};
this.removeSelectAll = () => {
if (this.selectAllButton) {
this.selectAllButton.destruct();
delete this.selectAllButton;
}
};
this.appendSelectAll = () => {
this.removeSelectAll();
this.selectAllButton = makeButton(this.j, {
name: 'selectall',
...this.j.o.controls.selectall
});
this.selectAllButton.state.size = 'tiny';
this.container &&
this.container.insertBefore(this.selectAllButton.container, this.container.firstChild);
};
this.calcPathImd = () => {
if (this.isDestructed) {
return;
}
const current = this.j.s.current();
if (this.container) {
this.container.innerHTML = INVISIBLE_SPACE;
}
if (current) {
let name, xpth, li;
Dom.up(current, (elm) => {
if (elm &&
this.j.editor !== elm &&
!Dom.isText(elm) &&
!Dom.isComment(elm)) {
name = elm.nodeName.toLowerCase();
xpth = getXPathByElement(elm, this.j.editor).replace(/^\//, '');
li = this.tpl(elm, xpth, name, this.j.i18n('Select %s', name));
this.container &&
this.container.insertBefore(li, this.container.firstChild);
}
}, this.j.editor);
}
this.appendSelectAll();
};
this.calcPath = this.j.async.debounce(this.calcPathImd, this.j.defaultTimeout * 2, true);
}
afterInit() {
if (this.j.o.showXPathInStatusbar) {
this.container = this.j.c.div('jodit-xpath');
attr(this.container, 'role', 'list');
const init = () => {
if (!this.j.o.showXPathInStatusbar || !this.container) {
return;
}
this.j.statusbar.append(this.container);
if (this.j.getRealMode() === MODE_WYSIWYG) {
this.calcPath();
}
else {
if (this.container) {
this.container.innerHTML = INVISIBLE_SPACE;
}
this.appendSelectAll();
}
};
this.j.e
.off('.xpath')
.on('pointerup.xpath change.xpath keydown.xpath changeSelection.xpath', this.calcPath)
.on('afterSetMode.xpath afterInit.xpath changePlace.xpath', init);
init();
this.calcPath();
}
}
beforeDestruct() {
if (this.j && this.j.events) {
this.j.e.off('.xpath');
}
this.removeSelectAll();
this.menu && this.menu.destruct();
Dom.safeRemove(this.container);
delete this.menu;
delete this.container;
}
}
pluginSystem.add('xpath', xpath);