Как отредактировать ссылку в contentEditable div
-
20-09-2019 - |
Вопрос
Есть ли у кого-нибудь какие-либо предложения о том, как отредактировать ссылку в contentEditable div?Было бы идеально, если бы после щелчка мышью по ссылке или наведения курсора на ссылку появлялось небольшое приглашение, позволяющее пользователю изменить свойство href ссылки.Проблема не в подсказке, но как можно определить, что ссылка была нажата или что курсор перешел на ссылку?onfocus, похоже, не работает в contentEditable div в Firefox и Safari.Есть какие-нибудь идеи?
Решение
Я почти уверен, что это то, что вы искали, однако я использовал jQuery просто для того, чтобы немного упростить высмеивание концепции. jsbin ( джсбин ) предварительный просмотр доступен, так что идите и посмотрите на него.Если кто-нибудь может преобразовать это в чистый JS ради ответа, я сделал это вики-сайтом сообщества.
Это работает путем привязки к событиям нажатия клавиши / click в редактируемом div, затем проверки наличия узла, на который помещается курсор пользователя, используя window.getSelection()
для Стандартов, или document.selection
для тех, кто работает с IE.Остальная часть кода обрабатывает появление / обработку изменений.
Методы jQuery:
function getSelectionStartNode(){
var node,selection;
if (window.getSelection) { // FF3.6, Safari4, Chrome5 (DOM Standards)
selection = getSelection();
node = selection.anchorNode;
}
if (!node && document.selection) { // IE
selection = document.selection
var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
node = range.commonAncestorContainer ? range.commonAncestorContainer :
range.parentElement ? range.parentElement() : range.item(0);
}
if (node) {
return (node.nodeName == "#text" ? node.parentNode : node);
}
}
$(function() {
$("#editLink").hide();
$("#myEditable").bind('keyup click', function(e) {
var $node = $(getSelectionStartNode());
if ($node.is('a')) {
$("#editLink").css({
top: $node.offset().top - $('#editLink').height() - 5,
left: $node.offset().left
}).show().data('node', $node);
$("#linktext").val($node.text());
$("#linkhref").val($node.attr('href'));
$("#linkpreview").attr('href', $node.attr('href'));
} else {
$("#editLink").hide();
}
});
$("#linktext").bind('keyup change', function() {
var $node = $("#editLink").data('node');
$node.text($(this).val());
});
$("#linkhref").bind('keyup change', function() {
var $node = $("#editLink").data('node');
$node.attr('href', $(this).val());
$node.and('#linkpreview').attr('href',$(this).val());
});
});
Другие советы
Я тестировал это только на Chrome
стиль кнопки
button.cmd {
...
}
кнопка на панели инструментов
<button type="button" id="linkEditor" class="cmd">link</button>
модальный диалог -> редактор ссылок
<div id="optionDialog" class="modal">
<div class="modal-content">
<div id="linkOption">
<p>
<label>Indirizzo link</label><br />
<input type="text" id="linkUrl" value="" placeholder="http://www..." />
</p>
<p>
<label>Testo link</label><br />
<input type="text" id="linkData" value="" placeholder="link label" />
</p>
<p>
<button type="button" id="linkDone">apply</button>
<button type="button" id="cancel">cancel</button>
</p>
</div>
</div>
</div>
javascript, jquery
var cur_range;
var cur_dialog;
$(document).ready(function() {
$('.editor').focus();
//on toolbar button mousedown keep current range
$('.cmd').mousedown(function(event) {
event.preventDefault();
try {
cur_range = document.getSelection().getRangeAt(0);
}
catch(error) {
console.log(error);
}
});
$('#linkEditor').click(function() {
event.preventDefault();
//if user select edit link, else insert link
if (!cur_range.collapsed) {
//if selection is a link set edit values
if (cur_range.commonAncestorContainer.parentNode.nodeName.toLowerCase() == 'a') {
$('#linkUrl').val(cur_range.commonAncestorContainer.parentNode.href);
$('#linkData').val(cur_range.commonAncestorContainer.data);
}
else {
//alert here
return false;
}
}
else {
$('#linkUrl').val('');
$('#linkData').val('');
}
//open link editor dialog
$('#optionDialog').show();
$('#linkOption').show();
//store current dialog section (link, table, header)
cur_dialog = $('#linkOption');
});
$('#linkDone').click(function() {
event.preventDefault();
if (cur_range.collapsed) {
//insert link at caret position
var node = '<a href="' + $('#linkUrl').val() + '" target="_blank">' + $('#linkData').val() + '</a>';
cur_range.insertNode(cur_range.createContextualFragment(node));
}
else {
//replace existing link values
cur_node = cur_range.commonAncestorContainer.parentNode;
cur_node.href = $('#linkUrl').val();
cur_node.innerText = $('#linkData').val();
}
//update range
document.getSelection().removeAllRanges();
document.getSelection().addRange(cur_range);
document.getSelection().collapseToEnd();
$('.modal-close').click();
//if you don't use observer some code is nedeed
//save_history(1);
});
//When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
optionDialog = document.getElementById('optionDialog');
if (event.target == optionDialog) {
$('#optionDialog').hide();
cur_dialog.hide();
cur_dialog = null;
}
}
});