javascript – 从contenteditable div中的可拖动内容中删除默认样式

我正在尝试创建简单的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));
});

它就像一个魅力:

《javascript – 从contenteditable div中的可拖动内容中删除默认样式》

但是通过拖放它不会像预期的那样工作.
我在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)));
});

结果如下:

《javascript – 从contenteditable div中的可拖动内容中删除默认样式》

另外,我尝试按照documentation执行此操作,但这完全删除了旧元素内容.
码:

$mainInput.bind('drop', function (e) {
    event.target.textContent = e.originalEvent.dataTransfer.getData("text/plain");
    event.preventDefault();
});

例:

《javascript – 从contenteditable div中的可拖动内容中删除默认样式》

有人可以帮助我,或者给出一些如何处理的建议.

此当前状态在此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);
}
点赞