jodit
Version:
Jodit is an awesome and useful wysiwyg editor with filebrowser
138 lines (137 loc) • 5.5 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 { pluginSystem } from "../../core/global.js";
import { splitArray, toArray } from "../../core/helpers/index.js";
import { flatButtonsSet, isButtonGroup } from "../../core/ui/helpers/buttons.js";
import "./config.js";
const isButtonSeparator = (item) => item === '|' || item === '---' || item === '\n';
/**
* Constrain a responsive breakpoint set (`buttonsMD/SM/XS`) to the buttons the
* user actually asked for via `buttons`. Those breakpoint defaults are
* group-based supersets, so a custom (smaller) `buttons` list would otherwise
* see *extra* buttons appear on resize when the toolbar switched to a breakpoint
* set — resizing must only ever drop buttons, never add ones outside `buttons`.
*
* When the breakpoint set introduces nothing outside `buttons` (the default
* case, where `buttons` is the full superset), the list is returned untouched so
* the standard grouped mobile layout — groups, separators and `dots` — is
* preserved. See #1389.
*/
function fitToButtons(list, editor) {
var _a;
const allowed = flatButtonsSet(splitArray(editor.o.buttons), editor);
const groups = editor.getRegisteredButtonGroups();
let changed = false;
let hadDots = false;
const flat = [];
for (const item of list) {
if (isButtonGroup(item)) {
const members = [...item.buttons, ...((_a = groups[item.group]) !== null && _a !== void 0 ? _a : [])];
const kept = members.filter(button => allowed.has(button));
if (kept.length !== members.length) {
changed = true;
}
flat.push(...kept);
}
else if (isButtonSeparator(item)) {
flat.push(item);
}
else if (item === 'dots') {
hadDots = true;
}
else if (allowed.has(item)) {
flat.push(item);
}
else {
changed = true;
}
}
if (!changed) {
return list;
}
// Drop separators left dangling once the buttons around them were removed.
const cleaned = [];
for (const item of flat) {
if (isButtonSeparator(item) &&
(cleaned.length === 0 ||
isButtonSeparator(cleaned[cleaned.length - 1]))) {
continue;
}
cleaned.push(item);
}
while (cleaned.length && isButtonSeparator(cleaned[cleaned.length - 1])) {
cleaned.pop();
}
// Keep the "show all" overflow button only if some requested button is still
// hidden at this breakpoint.
if (hadDots) {
const shown = flatButtonsSet(cleaned, editor);
if (toArray(allowed).some(button => !shown.has(button))) {
cleaned.push('dots');
}
}
return cleaned;
}
/**
* Rebuild toolbar in depends on editor's width
*/
export function mobile(editor) {
let timeout = 0, store = splitArray(editor.o.buttons);
if (editor.o.mobileTapTimeout) {
// Emulate double tap
editor.e.on('touchend', (e) => {
if (e.changedTouches && e.changedTouches.length) {
const now = new Date().getTime(), diff = now - timeout;
if (diff > editor.o.mobileTapTimeout) {
timeout = now;
if (diff < editor.o.mobileTapTimeout * 1.5) {
editor.s.insertCursorAtPoint(e.clientX, e.clientY);
}
}
}
});
}
editor.e.on('getDiffButtons.mobile', (toolbar) => {
if (toolbar === editor.toolbar) {
const buttons = flatButtonsSet(splitArray(editor.o.buttons), editor), flatStore = flatButtonsSet(store, editor);
return toArray(buttons).reduce((acc, item) => {
if (!flatStore.has(item)) {
acc.push(item);
}
return acc;
}, []);
}
});
if (editor.o.toolbarAdaptive) {
editor.e
.on('resize afterInit recalcAdaptive changePlace afterAddPlace', () => {
var _a, _b;
if (!editor.o.toolbar) {
return;
}
const width = ((_a = editor.container.parentElement) !== null && _a !== void 0 ? _a : editor.container).offsetWidth;
const newStore = (() => {
if (editor.isFullSize || width >= editor.o.sizeLG) {
return splitArray(editor.o.buttons);
}
if (width >= editor.o.sizeMD) {
return fitToButtons(splitArray(editor.o.buttonsMD), editor);
}
if (width >= editor.o.sizeSM) {
return fitToButtons(splitArray(editor.o.buttonsSM), editor);
}
return fitToButtons(splitArray(editor.o.buttonsXS), editor);
})();
if (newStore.toString() !== store.toString()) {
store = newStore;
editor.e.fire('closeAllPopups');
(_b = editor.toolbar) === null || _b === void 0 ? void 0 : _b.setRemoveButtons(editor.o.removeButtons).build(store.concat(editor.o.extraButtons));
}
})
.on(editor.ow, 'load resize', () => editor.e.fire('recalcAdaptive'));
}
}
pluginSystem.add('mobile', mobile);