Buttons RTE
This commit is contained in:
@@ -1 +1 @@
|
|||||||
1.1.55
|
1.1.56
|
||||||
@@ -480,6 +480,17 @@
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const findLinkAtSelection = () => {
|
||||||
|
const range = getSelectionRange();
|
||||||
|
if (!range) return null;
|
||||||
|
let node = range.commonAncestorContainer;
|
||||||
|
if (node && node.nodeType === 3) node = node.parentNode;
|
||||||
|
while (node && node !== content) {
|
||||||
|
if (node.tagName && node.tagName.toUpperCase() === 'A') return node;
|
||||||
|
node = node.parentNode;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
const applyInlineStyle = (styleProp, value) => {
|
const applyInlineStyle = (styleProp, value) => {
|
||||||
try {
|
try {
|
||||||
content.focus();
|
content.focus();
|
||||||
@@ -523,6 +534,22 @@
|
|||||||
for (const child of Array.from(fragment.childNodes)) {
|
for (const child of Array.from(fragment.childNodes)) {
|
||||||
if (walker(child)) return true;
|
if (walker(child)) return true;
|
||||||
}
|
}
|
||||||
|
const checkAncestors = (node) => {
|
||||||
|
let cur = node;
|
||||||
|
while (cur && cur !== content) {
|
||||||
|
if (cur.nodeType === 1) {
|
||||||
|
const tag = cur.tagName ? cur.tagName.toUpperCase() : '';
|
||||||
|
if (tags && tags.includes(tag)) return true;
|
||||||
|
if (styleProp && cur.style) {
|
||||||
|
if (styleMatch && styleMatch(cur.style[styleProp] || '', cur)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cur = cur.parentNode;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if (checkAncestors(range.startContainer)) return true;
|
||||||
|
if (checkAncestors(range.endContainer)) return true;
|
||||||
} catch {}
|
} catch {}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -655,7 +682,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const value = typeof valueGetter === 'function' ? valueGetter() : valueGetter;
|
const value = typeof valueGetter === 'function' ? valueGetter() : valueGetter;
|
||||||
if (value === null || value === undefined) return;
|
const hasValue = typeof valueGetter !== 'undefined';
|
||||||
|
if (hasValue && (value === null || value === undefined)) return;
|
||||||
if (cmd === 'createLink' && !value) return;
|
if (cmd === 'createLink' && !value) return;
|
||||||
exec(cmd, value);
|
exec(cmd, value);
|
||||||
});
|
});
|
||||||
@@ -803,8 +831,103 @@
|
|||||||
addButton(icon('M5 7h14v2H5zM4 11h16v2H4zM5 15h14v2H5z'), 'Zentriert', 'justifyCenter');
|
addButton(icon('M5 7h14v2H5zM4 11h16v2H4zM5 15h14v2H5z'), 'Zentriert', 'justifyCenter');
|
||||||
addButton(icon('M10 7h10v2H10zM4 11h16v2H4zM8 15h12v2H8z'), 'Rechtsbuendig', 'justifyRight');
|
addButton(icon('M10 7h10v2H10zM4 11h16v2H4zM8 15h12v2H8z'), 'Rechtsbuendig', 'justifyRight');
|
||||||
addButton(icon('M4 7h16v2H4zM4 11h16v2H4zM4 15h16v2H4z'), 'Blocksatz', 'justifyFull');
|
addButton(icon('M4 7h16v2H4zM4 11h16v2H4zM4 15h16v2H4z'), 'Blocksatz', 'justifyFull');
|
||||||
addButton(icon('M7 7h10l-1.5 1.5-3-3-5.5 5.5v5h5l5.5-5.5-3-3L17 7z'), 'Link einfuegen', 'createLink', () => prompt('Link-URL eingeben', 'https://'));
|
const linkPanel = doc.createElement('div');
|
||||||
addButton(icon('M7 7h4v2H7v4H5V9a2 2 0 0 1 2-2zm10 0a2 2 0 0 1 2 2v4h-2V9h-4V7h4zm0 10h-4v-2h4v-4h2v4a2 2 0 0 1-2 2zm-10 0a2 2 0 0 1-2-2v-4h2v4h4v2H7z'), 'Link entfernen', 'unlink');
|
linkPanel.style.display = 'none';
|
||||||
|
linkPanel.style.alignItems = 'center';
|
||||||
|
linkPanel.style.gap = '6px';
|
||||||
|
linkPanel.style.padding = '6px';
|
||||||
|
linkPanel.style.border = '1px solid #cbd5f5';
|
||||||
|
linkPanel.style.borderRadius = '6px';
|
||||||
|
linkPanel.style.background = '#ffffff';
|
||||||
|
linkPanel.style.boxShadow = '0 2px 10px rgba(15,23,42,0.08)';
|
||||||
|
linkPanel.className = 'bridge-rte-link-panel';
|
||||||
|
linkPanel.setAttribute('data-bridge-rte', 'link-panel');
|
||||||
|
|
||||||
|
const linkInput = doc.createElement('input');
|
||||||
|
linkInput.type = 'text';
|
||||||
|
linkInput.placeholder = 'https://...';
|
||||||
|
linkInput.style.flex = '1';
|
||||||
|
linkInput.style.minWidth = '220px';
|
||||||
|
linkInput.style.padding = '6px 8px';
|
||||||
|
linkInput.style.border = '1px solid #cbd5f5';
|
||||||
|
linkInput.style.borderRadius = '4px';
|
||||||
|
linkInput.style.fontSize = '14px';
|
||||||
|
|
||||||
|
const linkApply = doc.createElement('button');
|
||||||
|
linkApply.type = 'button';
|
||||||
|
linkApply.textContent = 'OK';
|
||||||
|
linkApply.className = 'bridge-rte-btn';
|
||||||
|
linkApply.style.padding = '6px 10px';
|
||||||
|
|
||||||
|
const linkRemove = doc.createElement('button');
|
||||||
|
linkRemove.type = 'button';
|
||||||
|
linkRemove.textContent = 'Entfernen';
|
||||||
|
linkRemove.className = 'bridge-rte-btn';
|
||||||
|
linkRemove.style.padding = '6px 10px';
|
||||||
|
|
||||||
|
const linkCancel = doc.createElement('button');
|
||||||
|
linkCancel.type = 'button';
|
||||||
|
linkCancel.textContent = 'Abbrechen';
|
||||||
|
linkCancel.className = 'bridge-rte-btn';
|
||||||
|
linkCancel.style.padding = '6px 10px';
|
||||||
|
|
||||||
|
linkPanel.appendChild(linkInput);
|
||||||
|
linkPanel.appendChild(linkApply);
|
||||||
|
linkPanel.appendChild(linkRemove);
|
||||||
|
linkPanel.appendChild(linkCancel);
|
||||||
|
toolbar.appendChild(linkPanel);
|
||||||
|
|
||||||
|
const hideLinkPanel = () => {
|
||||||
|
linkPanel.style.display = 'none';
|
||||||
|
};
|
||||||
|
const showLinkPanel = () => {
|
||||||
|
const linkEl = findLinkAtSelection();
|
||||||
|
linkInput.value = linkEl && linkEl.getAttribute ? (linkEl.getAttribute('href') || '') : '';
|
||||||
|
linkPanel.style.display = 'flex';
|
||||||
|
linkInput.focus();
|
||||||
|
linkInput.select();
|
||||||
|
};
|
||||||
|
|
||||||
|
addButton(
|
||||||
|
icon('M7 7h10l-1.5 1.5-3-3-5.5 5.5v5h5l5.5-5.5-3-3L17 7z'),
|
||||||
|
'Link einfuegen/bearbeiten',
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
() => {
|
||||||
|
saveSelection();
|
||||||
|
showLinkPanel();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
linkApply.addEventListener('click', () => {
|
||||||
|
const url = String(linkInput.value || '').trim();
|
||||||
|
if (!url) {
|
||||||
|
exec('unlink');
|
||||||
|
hideLinkPanel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const linkEl = findLinkAtSelection();
|
||||||
|
if (linkEl) {
|
||||||
|
const docRef = content.ownerDocument || document;
|
||||||
|
const sel = docRef.getSelection();
|
||||||
|
if (sel && docRef.createRange) {
|
||||||
|
const range = docRef.createRange();
|
||||||
|
range.selectNodeContents(linkEl);
|
||||||
|
sel.removeAllRanges();
|
||||||
|
sel.addRange(range);
|
||||||
|
saveSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
exec('createLink', url);
|
||||||
|
hideLinkPanel();
|
||||||
|
});
|
||||||
|
linkRemove.addEventListener('click', () => {
|
||||||
|
exec('unlink');
|
||||||
|
hideLinkPanel();
|
||||||
|
});
|
||||||
|
linkCancel.addEventListener('click', hideLinkPanel);
|
||||||
addButton(icon('M7 6h10v2H7zM9 10h6v2H9zM10 14h4v2h-4z'), 'Tiefgestellt', 'subscript');
|
addButton(icon('M7 6h10v2H7zM9 10h6v2H9zM10 14h4v2h-4z'), 'Tiefgestellt', 'subscript');
|
||||||
addButton(icon('M7 6h10v2H7zM9 10h6v2H9zM8 14h8v2H8z'), 'Hochgestellt', 'superscript');
|
addButton(icon('M7 6h10v2H7zM9 10h6v2H9zM8 14h8v2H8z'), 'Hochgestellt', 'superscript');
|
||||||
addButton(icon('M7 4h4v4H7V4zm6 12h4v4h-4v-4zM7 10h10v2H7v-2z'), 'Einzug', 'indent');
|
addButton(icon('M7 4h4v4H7V4zm6 12h4v4h-4v-4zM7 10h10v2H7v-2z'), 'Einzug', 'indent');
|
||||||
|
|||||||
Reference in New Issue
Block a user