Icons Buttosn RTE
This commit is contained in:
@@ -1 +1 @@
|
|||||||
1.1.54
|
1.1.55
|
||||||
@@ -502,6 +502,87 @@
|
|||||||
saveSelection();
|
saveSelection();
|
||||||
} catch {}
|
} catch {}
|
||||||
};
|
};
|
||||||
|
const selectionHasStyle = (range, styleProp, tags, styleMatch) => {
|
||||||
|
if (!range) return false;
|
||||||
|
try {
|
||||||
|
const fragment = range.cloneContents();
|
||||||
|
const walker = (node) => {
|
||||||
|
if (!node) return false;
|
||||||
|
if (node.nodeType === 1) {
|
||||||
|
const tag = node.tagName ? node.tagName.toUpperCase() : '';
|
||||||
|
if (tags && tags.includes(tag)) return true;
|
||||||
|
if (styleProp && node.style) {
|
||||||
|
if (styleMatch && styleMatch(node.style[styleProp] || '', node)) return true;
|
||||||
|
}
|
||||||
|
for (const child of Array.from(node.childNodes)) {
|
||||||
|
if (walker(child)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
for (const child of Array.from(fragment.childNodes)) {
|
||||||
|
if (walker(child)) return true;
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
const removeInlineStyle = (styleProp, tags, clearFn) => {
|
||||||
|
try {
|
||||||
|
content.focus();
|
||||||
|
restoreSelection();
|
||||||
|
const docRef = content.ownerDocument || document;
|
||||||
|
const range = getSelectionRange();
|
||||||
|
if (!range || range.collapsed) return;
|
||||||
|
const fragment = range.extractContents();
|
||||||
|
const unwrap = (node) => {
|
||||||
|
const parent = node.parentNode;
|
||||||
|
if (!parent) return;
|
||||||
|
while (node.firstChild) parent.insertBefore(node.firstChild, node);
|
||||||
|
parent.removeChild(node);
|
||||||
|
};
|
||||||
|
const strip = (node) => {
|
||||||
|
if (!node) return;
|
||||||
|
if (node.nodeType === 1) {
|
||||||
|
const tag = node.tagName ? node.tagName.toUpperCase() : '';
|
||||||
|
if (tags && tags.includes(tag)) {
|
||||||
|
const children = Array.from(node.childNodes);
|
||||||
|
children.forEach(strip);
|
||||||
|
unwrap(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (styleProp && node.style) {
|
||||||
|
if (typeof clearFn === 'function') {
|
||||||
|
clearFn(node.style);
|
||||||
|
} else {
|
||||||
|
node.style[styleProp] = '';
|
||||||
|
}
|
||||||
|
const styleAttr = node.getAttribute('style');
|
||||||
|
if (!styleAttr || !String(styleAttr).trim()) {
|
||||||
|
const children = Array.from(node.childNodes);
|
||||||
|
children.forEach(strip);
|
||||||
|
unwrap(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Array.from(node.childNodes).forEach(strip);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Array.from(fragment.childNodes).forEach(strip);
|
||||||
|
range.insertNode(fragment);
|
||||||
|
saveSelection();
|
||||||
|
} catch {}
|
||||||
|
};
|
||||||
|
const toggleInlineStyle = (cmd, styleProp, value, tags, styleMatch, clearFn) => {
|
||||||
|
const range = getSelectionRange();
|
||||||
|
if (!range || range.collapsed) return;
|
||||||
|
if (selectionHasStyle(range, styleProp, tags, styleMatch)) {
|
||||||
|
if (cmd) exec(cmd);
|
||||||
|
removeInlineStyle(styleProp, tags, clearFn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cmd) exec(cmd);
|
||||||
|
if (styleProp) applyInlineStyle(styleProp, value);
|
||||||
|
};
|
||||||
const removeInlineFormatting = () => {
|
const removeInlineFormatting = () => {
|
||||||
try {
|
try {
|
||||||
content.focus();
|
content.focus();
|
||||||
@@ -669,25 +750,52 @@
|
|||||||
if (!ui.overrideToolbar) {
|
if (!ui.overrideToolbar) {
|
||||||
const icon = (path) => `<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path d="${path}" fill="currentColor"/></svg>`;
|
const icon = (path) => `<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path d="${path}" fill="currentColor"/></svg>`;
|
||||||
addButton(
|
addButton(
|
||||||
icon('M6 4h5a3 3 0 0 1 0 6H6V4zm0 8h6a3 3 0 0 1 0 6H6v-6z'),
|
'<strong>B</strong>',
|
||||||
'Fett',
|
'Fett',
|
||||||
'bold',
|
'bold',
|
||||||
null,
|
null,
|
||||||
() => applyInlineStyle('fontWeight', '700')
|
() => toggleInlineStyle(
|
||||||
|
'bold',
|
||||||
|
'fontWeight',
|
||||||
|
'700',
|
||||||
|
['B', 'STRONG'],
|
||||||
|
(val) => {
|
||||||
|
const num = parseInt(String(val || '').replace(/[^0-9]/g, ''), 10);
|
||||||
|
return Number.isFinite(num) ? num >= 600 : /bold/i.test(String(val || ''));
|
||||||
|
},
|
||||||
|
(style) => { style.fontWeight = ''; }
|
||||||
|
)
|
||||||
);
|
);
|
||||||
addButton(
|
addButton(
|
||||||
icon('M10 4h8v2h-3l-4 12h3v2H6v-2h3l4-12h-3V4z'),
|
'<em>I</em>',
|
||||||
'Kursiv',
|
'Kursiv',
|
||||||
'italic',
|
'italic',
|
||||||
null,
|
null,
|
||||||
() => applyInlineStyle('fontStyle', 'italic')
|
() => toggleInlineStyle(
|
||||||
|
'italic',
|
||||||
|
'fontStyle',
|
||||||
|
'italic',
|
||||||
|
['I', 'EM'],
|
||||||
|
(val) => String(val || '').toLowerCase() === 'italic',
|
||||||
|
(style) => { style.fontStyle = ''; }
|
||||||
|
)
|
||||||
);
|
);
|
||||||
addButton(
|
addButton(
|
||||||
icon('M5 4h14v2h-6v3h4a4 4 0 0 1 0 8H7v-2h10a2 2 0 0 0 0-4h-4V6H5V4z'),
|
'<span style="text-decoration:underline;">U</span>',
|
||||||
'Unterstrichen',
|
'Unterstrichen',
|
||||||
'underline',
|
'underline',
|
||||||
null,
|
null,
|
||||||
() => applyInlineStyle('textDecoration', 'underline')
|
() => toggleInlineStyle(
|
||||||
|
'underline',
|
||||||
|
'textDecoration',
|
||||||
|
'underline',
|
||||||
|
['U'],
|
||||||
|
(val) => /underline/i.test(String(val || '')),
|
||||||
|
(style) => {
|
||||||
|
style.textDecoration = '';
|
||||||
|
style.textDecorationLine = '';
|
||||||
|
}
|
||||||
|
)
|
||||||
);
|
);
|
||||||
addButton(icon('M4 7h10v2H4zM4 11h16v2H4zM4 15h10v2H4z'), 'Liste (ungeordnet)', 'insertUnorderedList');
|
addButton(icon('M4 7h10v2H4zM4 11h16v2H4zM4 15h10v2H4z'), 'Liste (ungeordnet)', 'insertUnorderedList');
|
||||||
addButton(icon('M4 6h4v2H4V6zm0 4h4v2H4v-2zm0 4h4v2H4v-2zm6-8h10v2H10V6zm0 4h10v2H10v-2zm0 4h10v2H10v-2z'), 'Liste (geordnet)', 'insertOrderedList');
|
addButton(icon('M4 6h4v2H4V6zm0 4h4v2H4v-2zm0 4h4v2H4v-2zm6-8h10v2H10V6zm0 4h10v2H10v-2zm0 4h10v2H10v-2z'), 'Liste (geordnet)', 'insertOrderedList');
|
||||||
@@ -702,7 +810,7 @@
|
|||||||
addButton(icon('M7 4h4v4H7V4zm6 12h4v4h-4v-4zM7 10h10v2H7v-2z'), 'Einzug', 'indent');
|
addButton(icon('M7 4h4v4H7V4zm6 12h4v4h-4v-4zM7 10h10v2H7v-2z'), 'Einzug', 'indent');
|
||||||
addButton(icon('M13 4h4v4h-4V4zM7 16h4v4H7v-4zM7 10h10v2H7v-2z'), 'Ausruecken', 'outdent');
|
addButton(icon('M13 4h4v4h-4V4zM7 16h4v4H7v-4zM7 10h10v2H7v-2z'), 'Ausruecken', 'outdent');
|
||||||
addButton(
|
addButton(
|
||||||
icon('M5 5h14v2H5zM5 9h10v2H5zM5 13h14v2H5zM5 17h10v2H5z'),
|
'<span style="font-weight:600;">Tx</span>',
|
||||||
'Formatierung entfernen',
|
'Formatierung entfernen',
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@@ -776,7 +884,21 @@
|
|||||||
editorCss = editor && typeof editor.getCss === 'function' ? String(editor.getCss() || '') : '';
|
editorCss = editor && typeof editor.getCss === 'function' ? String(editor.getCss() || '') : '';
|
||||||
} catch {}
|
} catch {}
|
||||||
const frameCss = this.collectFrameCss(editor);
|
const frameCss = this.collectFrameCss(editor);
|
||||||
injectedStyle.textContent = `${fontCss}\n${editorCss}\n${frameCss}`.trim();
|
const rteUiCss = `
|
||||||
|
.bridge-rte-toolbar { gap: 8px; }
|
||||||
|
.bridge-rte-btn {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1;
|
||||||
|
min-height: 30px;
|
||||||
|
min-width: 30px;
|
||||||
|
color: #0f172a;
|
||||||
|
background: #f1f5f9;
|
||||||
|
}
|
||||||
|
.bridge-rte-btn:hover { background: #e2e8f0; }
|
||||||
|
.bridge-rte-btn:active { transform: translateY(1px); }
|
||||||
|
.bridge-rte-actions .bridge-rte-btn { min-width: 88px; }
|
||||||
|
`.trim();
|
||||||
|
injectedStyle.textContent = [fontCss, editorCss, frameCss, rteUiCss].filter(Boolean).join('\n');
|
||||||
if (injectedStyle.textContent) {
|
if (injectedStyle.textContent) {
|
||||||
container.appendChild(injectedStyle);
|
container.appendChild(injectedStyle);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user