当我使用JavaScript更新文本时,光标移动到文本开头

4
我正在使用contenteditable允许用户编辑网页上的信息,但某些字段有长度要求,我希望他们知道何时达到了该要求,因此当他们按回车键时,我会将将被截断的文本更改为红色。
问题在于,当使用JavaScript更改文本时,浏览器会将光标移动到字符串的前面。有人知道我如何防止这种行为吗?据我所知,这是所有浏览器中的问题。
这里是一个JSFiddle链接
$(element).keypress(function (event) {
    if ($(element).text().trim().length > maxChars) {
        $(element).html($(element).text().trim().substr(0, maxChars) +
            "<span class=red>" + $(element).text().trim().substr(maxChars) + "</span>");
    }
});

1
也许这会有所帮助https://dev59.com/92Qo5IYBdhLWcg3wOdFZ - Harsha Venkataramu
哇,显然我在寻找答案方面没有想象中的那么好。谢谢! - Josh Sherick
没问题,我很高兴能帮到你! - Harsha Venkataramu
2
https://dev59.com/CGYr5IYBdhLWcg3wG2pI#13950376 可以更普遍地工作,所以插入符号保持在同一位置,而不是总是移动到结尾(如果您正在输入文本,则不是您想要的中间位置)。演示:http://jsfiddle.net/TeXG6/5/ - Tim Down
@TimDown 这就是我过去一天一直在尝试让它做的事情,谢谢!由于某种原因,在JSFiddle中这对我不起作用(在文本中间输入可以工作,但在末尾输入会使光标跳到前面),但在我的实际应用程序中它可以工作,所以没问题。然而,在Firefox中仍然存在一个问题,即空格会从末尾删除...我稍后会检查一下看出了什么问题。 - Josh Sherick
@JoshSherick:在换行和可能存在多个空格的情况下,会出现问题。这是一个难以完全解决的问题。 - Tim Down
2个回答

2
感谢Harsha和Tim Down的帮助,最终我解决了问题,也修复了Firefox不允许空格的问题,并且它运行得非常好。唯一意外的行为是它会破坏浏览器的撤销历史记录,但除此之外它还是很好用的。
我已经在每个浏览器中进行了测试,但是IE除外,但我不知道为什么在新版本的IE中不工作。它需要使用输入事件,因此在旧版浏览器中无法工作。我也不知道它如何处理换行符,因为在我的应用程序中我去掉了它们。
首先,您需要在文件中某个地方使用Tim Down编写的这段代码:written by Tim Down
var saveSelection, restoreSelection;
var endSpaceIndex = -1;

if (window.getSelection && document.createRange) {
    saveSelection = function(containerEl) {
        var range = window.getSelection().getRangeAt(0);
        var preSelectionRange = range.cloneRange();
        preSelectionRange.selectNodeContents(containerEl);
        preSelectionRange.setEnd(range.startContainer, range.startOffset);
        var start = preSelectionRange.toString().length;

        return {
            start: start,
            end: start + range.toString().length
        }
    };

    restoreSelection = function(containerEl, savedSel) {
        var charIndex = 0, range = document.createRange();
        range.setStart(containerEl, 0);
        range.collapse(true);
        var nodeStack = [containerEl], node, foundStart = false, stop = false;

        while (!stop && (node = nodeStack.pop())) {
            if (node.nodeType == 3) {
                var nextCharIndex = charIndex + node.length;
                if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
                    range.setStart(node, savedSel.start - charIndex);
                    foundStart = true;
                }
                if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
                    range.setEnd(node, savedSel.end - charIndex);
                    stop = true;
                }
                charIndex = nextCharIndex;
            } else {
                var i = node.childNodes.length;
                while (i--) {
                    nodeStack.push(node.childNodes[i]);
                }
            }
        }

        var sel = window.getSelection();
        sel.removeAllRanges();
        sel.addRange(range);
    }
} else if (document.selection) {
    saveSelection = function(containerEl) {
        var selectedTextRange = document.selection.createRange();
        var preSelectionTextRange = document.body.createTextRange();
        preSelectionTextRange.moveToElementText(containerEl);
        preSelectionTextRange.setEndPoint("EndToStart", selectedTextRange);
        var start = preSelectionTextRange.text.length;

        return {
            start: start,
            end: start + selectedTextRange.text.length
        }
    };

    restoreSelection = function(containerEl, savedSel) {
        var textRange = document.body.createTextRange();
        textRange.moveToElementText(containerEl);
        textRange.collapse(true);
        textRange.moveEnd("character", savedSel.end);
        textRange.moveStart("character", savedSel.start);
        textRange.select();
    };
}

在某些情况下,您需要以下代码。它使用jQuery,所以如果您没有jQuery,则必须从下面的示例中删除jQuery。这需要绑定到input事件,因为Firefox在何时调用keyupkeypress上非常不一致。这是解决Firefox不允许空格的问题的方法。它相当混乱。但是,显然contenteditable的浏览器支持也是如此。

// Provided `element` is the element that you want to modify while the user changes it.
$(element).bind('input', function() {
    var savedSel = saveSelection(element);
    if (endSpaceIndex > -1 && $(element).text().substr(endSpaceIndex) != " " 
        && savedSel.end == $(element).text().length && savedSel.end == savedSel.start) {
            $(element).html($(element).text().substr(0, endSpaceIndex) + " " + $(element).text().substr(endSpaceIndex));
            endSpaceIndex = -1;
            savedSel.end = savedSel.start = $(element).text().length;
    }

    // Here, change the element however you want to. 
    // For example, I add a 'red' class around the text that will be chopped off

    restoreSelection(element, savedSel);
    var fullText = $(element).text();
    if (fullText.substr(fullText.length - 1) == " ") {
        endSpaceIndex = fullText.length - 1;
    }
}

另外,我最初标记它为重复,但我不再认为它是重复的,因为它修复了Firefox不允许空格的问题。希望这能帮助其他人!


0

问题是关于contenteditable元素,而不是输入框或文本区域。 - Tim Down

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接