RTE Link editor
This commit is contained in:
@@ -1 +1 @@
|
|||||||
1.1.58
|
1.1.59
|
||||||
@@ -376,6 +376,7 @@
|
|||||||
container.style.gap = '10px';
|
container.style.gap = '10px';
|
||||||
container.style.height = '100%';
|
container.style.height = '100%';
|
||||||
container.style.minHeight = '360px';
|
container.style.minHeight = '360px';
|
||||||
|
container.style.position = 'relative';
|
||||||
container.className = 'bridge-rte-container';
|
container.className = 'bridge-rte-container';
|
||||||
container.setAttribute('data-bridge-rte', 'container');
|
container.setAttribute('data-bridge-rte', 'container');
|
||||||
|
|
||||||
@@ -847,28 +848,46 @@
|
|||||||
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');
|
||||||
|
const linkModal = doc.createElement('div');
|
||||||
|
linkModal.style.display = 'none';
|
||||||
|
linkModal.style.position = 'absolute';
|
||||||
|
linkModal.style.inset = '0';
|
||||||
|
linkModal.style.background = 'rgba(15,23,42,0.35)';
|
||||||
|
linkModal.style.alignItems = 'center';
|
||||||
|
linkModal.style.justifyContent = 'center';
|
||||||
|
linkModal.style.zIndex = '20';
|
||||||
|
linkModal.className = 'bridge-rte-link-modal';
|
||||||
|
linkModal.setAttribute('data-bridge-rte', 'link-modal');
|
||||||
|
|
||||||
const linkPanel = doc.createElement('div');
|
const linkPanel = doc.createElement('div');
|
||||||
linkPanel.style.display = 'none';
|
linkPanel.style.display = 'flex';
|
||||||
linkPanel.style.alignItems = 'center';
|
linkPanel.style.flexDirection = 'column';
|
||||||
linkPanel.style.gap = '6px';
|
linkPanel.style.gap = '10px';
|
||||||
linkPanel.style.padding = '6px';
|
linkPanel.style.padding = '12px';
|
||||||
linkPanel.style.border = '1px solid #cbd5f5';
|
linkPanel.style.border = '1px solid #cbd5f5';
|
||||||
linkPanel.style.borderRadius = '6px';
|
linkPanel.style.borderRadius = '8px';
|
||||||
linkPanel.style.background = '#ffffff';
|
linkPanel.style.background = '#ffffff';
|
||||||
linkPanel.style.boxShadow = '0 2px 10px rgba(15,23,42,0.08)';
|
linkPanel.style.boxShadow = '0 6px 24px rgba(15,23,42,0.2)';
|
||||||
linkPanel.className = 'bridge-rte-link-panel';
|
linkPanel.style.minWidth = '320px';
|
||||||
linkPanel.setAttribute('data-bridge-rte', 'link-panel');
|
|
||||||
|
const linkTitle = doc.createElement('div');
|
||||||
|
linkTitle.textContent = 'Link einfuegen';
|
||||||
|
linkTitle.style.fontWeight = '600';
|
||||||
|
linkTitle.style.fontSize = '14px';
|
||||||
|
|
||||||
const linkInput = doc.createElement('input');
|
const linkInput = doc.createElement('input');
|
||||||
linkInput.type = 'text';
|
linkInput.type = 'text';
|
||||||
linkInput.placeholder = 'https://...';
|
linkInput.placeholder = 'https://...';
|
||||||
linkInput.style.flex = '1';
|
|
||||||
linkInput.style.minWidth = '220px';
|
|
||||||
linkInput.style.padding = '6px 8px';
|
linkInput.style.padding = '6px 8px';
|
||||||
linkInput.style.border = '1px solid #cbd5f5';
|
linkInput.style.border = '1px solid #cbd5f5';
|
||||||
linkInput.style.borderRadius = '4px';
|
linkInput.style.borderRadius = '4px';
|
||||||
linkInput.style.fontSize = '14px';
|
linkInput.style.fontSize = '14px';
|
||||||
|
|
||||||
|
const linkActions = doc.createElement('div');
|
||||||
|
linkActions.style.display = 'flex';
|
||||||
|
linkActions.style.justifyContent = 'flex-end';
|
||||||
|
linkActions.style.gap = '8px';
|
||||||
|
|
||||||
const linkApply = doc.createElement('button');
|
const linkApply = doc.createElement('button');
|
||||||
linkApply.type = 'button';
|
linkApply.type = 'button';
|
||||||
linkApply.textContent = 'OK';
|
linkApply.textContent = 'OK';
|
||||||
@@ -887,19 +906,24 @@
|
|||||||
linkCancel.className = 'bridge-rte-btn';
|
linkCancel.className = 'bridge-rte-btn';
|
||||||
linkCancel.style.padding = '6px 10px';
|
linkCancel.style.padding = '6px 10px';
|
||||||
|
|
||||||
|
linkActions.appendChild(linkCancel);
|
||||||
|
linkActions.appendChild(linkRemove);
|
||||||
|
linkActions.appendChild(linkApply);
|
||||||
|
|
||||||
|
linkPanel.appendChild(linkTitle);
|
||||||
linkPanel.appendChild(linkInput);
|
linkPanel.appendChild(linkInput);
|
||||||
linkPanel.appendChild(linkApply);
|
linkPanel.appendChild(linkActions);
|
||||||
linkPanel.appendChild(linkRemove);
|
linkModal.appendChild(linkPanel);
|
||||||
linkPanel.appendChild(linkCancel);
|
container.appendChild(linkModal);
|
||||||
toolbar.appendChild(linkPanel);
|
|
||||||
|
|
||||||
const hideLinkPanel = () => {
|
const hideLinkPanel = () => {
|
||||||
linkPanel.style.display = 'none';
|
linkModal.style.display = 'none';
|
||||||
};
|
};
|
||||||
const showLinkPanel = () => {
|
const showLinkPanel = () => {
|
||||||
|
saveSelection();
|
||||||
const linkEl = findLinkAtSelection();
|
const linkEl = findLinkAtSelection();
|
||||||
linkInput.value = linkEl && linkEl.getAttribute ? (linkEl.getAttribute('href') || '') : '';
|
linkInput.value = linkEl && linkEl.getAttribute ? (linkEl.getAttribute('href') || '') : '';
|
||||||
linkPanel.style.display = 'flex';
|
linkModal.style.display = 'flex';
|
||||||
linkInput.focus();
|
linkInput.focus();
|
||||||
linkInput.select();
|
linkInput.select();
|
||||||
};
|
};
|
||||||
@@ -910,7 +934,6 @@
|
|||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
() => {
|
() => {
|
||||||
saveSelection();
|
|
||||||
showLinkPanel();
|
showLinkPanel();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -918,7 +941,7 @@
|
|||||||
linkApply.addEventListener('click', () => {
|
linkApply.addEventListener('click', () => {
|
||||||
const url = String(linkInput.value || '').trim();
|
const url = String(linkInput.value || '').trim();
|
||||||
if (!url) {
|
if (!url) {
|
||||||
linkRemove.click();
|
hideLinkPanel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@@ -929,13 +952,24 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
const range = getSelectionRange();
|
const range = savedRange ? savedRange.cloneRange() : getSelectionRange();
|
||||||
if (!range || range.collapsed) {
|
if (!range || range.collapsed) {
|
||||||
hideLinkPanel();
|
hideLinkPanel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const docRef = content.ownerDocument || document;
|
||||||
|
const anchor = docRef.createElement('a');
|
||||||
|
anchor.setAttribute('href', url);
|
||||||
|
anchor.setAttribute('target', '_blank');
|
||||||
|
anchor.setAttribute('rel', 'noopener');
|
||||||
|
const fragment = range.extractContents();
|
||||||
|
anchor.appendChild(fragment);
|
||||||
|
range.insertNode(anchor);
|
||||||
|
} catch {
|
||||||
restoreSelection();
|
restoreSelection();
|
||||||
exec('createLink', url);
|
exec('createLink', url);
|
||||||
|
}
|
||||||
hideLinkPanel();
|
hideLinkPanel();
|
||||||
});
|
});
|
||||||
linkRemove.addEventListener('click', () => {
|
linkRemove.addEventListener('click', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user