我正在尝试创建简单的WYSIWYG编辑器,我遇到了以下问题.
当用户在contenteditable div中复制或拖动文本时.
根据Google提供的信息,我添加了以下代码进行复制/粘贴:
var $mainInput = $('#main-input');
$mainInput.on('paste', function(e) {
e.preventDefault();
var text = e.originalEvent.clipboardData.getData("text/plain");
lastCaretIndex.insertNode(document.createTextNode(text));
});
它就像一个魅力:
但是通过拖放它不会像预期的那样工作.
我在Stackoverflow上发现了类似的帖子:
1)This one uses jQuery UI which is irrelevant for my case
2)Event described here doesn’t provide ability to customize draggable text, only target
还有其他一些,所以我得到了以下代码:
$mainInput.on('dragend', function(e) {
window.getSelection().getRangeAt(0).insertNode(document.createTextNode(strip(t)));
});
结果如下:
另外,我尝试按照documentation执行此操作,但这完全删除了旧元素内容.
码:
$mainInput.bind('drop', function (e) {
event.target.textContent = e.originalEvent.dataTransfer.getData("text/plain");
event.preventDefault();
});
例:
有人可以帮助我,或者给出一些如何处理的建议.
此当前状态在此fiddle中可用
================= PS ===============
这解决了.适用于大多数浏览器的版本 – fiddle
最佳答案 删除文本时,丢弃点处的跨度将分为两个,并在其间插入新的跨度.我没有看到拖放的选项来防止这种行为.避免它的一种方法是替换默认的传输机制.
在放置事件处理程序中,如果发现它将以不同的跨度结束,则可以手动移动文本.目标范围可以通过createCollapsedRangeFromPoint
找到,这是Tim Down提供的功能.然后可以将范围与原始选择范围进行比较.
以下代码可在this jsfiddle中测试.它适用于Chrome和Firefox,但不适用于IE11.如果不支持自定义拖放行为,则使用默认的拖放行为.
var $mainInput = $('#main-input');
var draggedText;
var dragStartContainer;
var dragEndContainer;
var dragStartOffset;
var dragEndOffset;
$mainInput.on('dragstart', function(e) {
var dragRange = getSelectionRange();
dragStartContainer = dragRange.startContainer;
dragEndContainer = dragRange.endContainer;
dragStartOffset = dragRange.startOffset;
dragEndOffset = dragRange.endOffset;
draggedText = e.originalEvent.dataTransfer.getData("text");
});
$mainInput.on('drop', function(e) {
// Get caret at mouse cursor position
var range = createCollapsedRangeFromPoint(e.clientX, e.clientY);
var container = range.startContainer;
// If text is moved to another container, do it manually
if (container && (container !== dragStartContainer || container !== dragEndContainer)) {
e.preventDefault();
// Insert dragged text at caret position
var startOffset = range.startOffset;
var str = container.textContent;
var strPrepend = str.substr(0, range.startOffset);
var strAppend = str.substr(range.startOffset);
container.textContent = strPrepend + draggedText + strAppend;
// Delete text at original position
var spaceCount = getSpaceCountAtStart(container);
setSelectionRange(dragStartContainer, dragEndContainer, dragStartOffset, dragEndOffset);
document.execCommand("delete", false);
var spaceCountCorrection = getSpaceCountAtStart(container) - spaceCount;
// Select text at new position
var startRemoved = (dragEndContainer === container ? dragEndOffset - 1 : 0);
var startOffset = Math.max(0, startOffset + spaceCountCorrection - startRemoved);
var endOffset = startOffset + draggedText.length;
setSelectionRange(container, container, startOffset, endOffset);
}
});
// Get the number of spaces at start of container
// After moving text, that number may change
// and screw up range position calculations
function getSpaceCountAtStart(container) {
var innerHTML = container.parentNode.innerHTML;
var count = 0;
for (var i = 0; i < innerHTML.length; i++) {
if (innerHTML[i] === ' ') {
count += 1;
} else {
break;
}
}
return count;
}
// Function provided by Tim Down at https://stackoverflow.com/a/28275304/1009922
function createCollapsedRangeFromPoint(x, y) {
var doc = document;
var position, range = null;
if (typeof doc.caretPositionFromPoint != "undefined") {
position = doc.caretPositionFromPoint(x, y);
range = doc.createRange();
range.setStart(position.offsetNode, position.offset);
range.collapse(true);
} else if (typeof doc.caretRangeFromPoint != "undefined") {
range = doc.caretRangeFromPoint(x, y);
} else if (typeof doc.body.createTextRange != "undefined") {
range = doc.body.createTextRange();
range.moveToPoint(x, y);
}
return range;
}
function getSelectionRange() {
var sel;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
return sel.getRangeAt(0);
}
} else if (document.selection) {
return document.createRange();
}
return null;
}
function setSelectionRange(startContainer, endContainer, startOffset, endOffset) {
var sel = window.getSelection();
sel.removeAllRanges();
var range = document.createRange();
range.setStart(startContainer, startOffset);
range.setEnd(endContainer, endOffset);
sel.addRange(range);
}