I am after a definitive, cross-browser solution to set the cursor/caret position to the last known position when a contentEditable='on' <div> regains focus. It appears default functionality of a content editable div is to move the caret/cursor to the beginning of the text in the div each time you click on it, which is undesirable.

我相信当光标离开div的焦点时,我必须将当前光标位置存储在一个变量中,然后在它们再次获得焦点时重新设置该位置,但我还无法组合在一起或找到工作的代码示例.

如果任何人有任何 idea 、工作代码片段或示例,我都很乐意看到.

我实际上还没有任何代码,但下面是我拥有的代码:

<script type="text/javascript">
// jQuery
$(document).ready(function() {
   $('#area').focus(function() { .. }  // focus I would imagine I need.
}
</script>
<div id="area" contentEditable="true"></div>

PS. I have tried this resource but it appears it does not work for a <div>. Perhaps only for textarea (How to move cursor to end of contenteditable entity)

推荐答案

这与基于标准的浏览器兼容,但在IE中可能会失败.我将它作为一个起点提供.IE不支持DOM范围.

var editable = document.getElementById('editable'),
    selection, range;

// Populates selection and range variables
var captureSelection = function(e) {
    // Don't capture selection outside editable region
    var isOrContainsAnchor = false,
        isOrContainsFocus = false,
        sel = window.getSelection(),
        parentAnchor = sel.anchorNode,
        parentFocus = sel.focusNode;

    while(parentAnchor && parentAnchor != document.documentElement) {
        if(parentAnchor == editable) {
            isOrContainsAnchor = true;
        }
        parentAnchor = parentAnchor.parentNode;
    }

    while(parentFocus && parentFocus != document.documentElement) {
        if(parentFocus == editable) {
            isOrContainsFocus = true;
        }
        parentFocus = parentFocus.parentNode;
    }

    if(!isOrContainsAnchor || !isOrContainsFocus) {
        return;
    }

    selection = window.getSelection();

    // Get range (standards)
    if(selection.getRangeAt !== undefined) {
        range = selection.getRangeAt(0);

    // Get range (Safari 2)
    } else if(
        document.createRange &&
        selection.anchorNode &&
        selection.anchorOffset &&
        selection.focusNode &&
        selection.focusOffset
    ) {
        range = document.createRange();
        range.setStart(selection.anchorNode, selection.anchorOffset);
        range.setEnd(selection.focusNode, selection.focusOffset);
    } else {
        // Failure here, not handled by the rest of the script.
        // Probably IE or some older browser
    }
};

// Recalculate selection while typing
editable.onkeyup = captureSelection;

// Recalculate selection after clicking/drag-selecting
editable.onmousedown = function(e) {
    editable.className = editable.className + ' selecting';
};
document.onmouseup = function(e) {
    if(editable.className.match(/\sselecting(\s|$)/)) {
        editable.className = editable.className.replace(/ selecting(\s|$)/, '');
        captureSelection();
    }
};

editable.onblur = function(e) {
    var cursorStart = document.createElement('span'),
        collapsed = !!range.collapsed;

    cursorStart.id = 'cursorStart';
    cursorStart.appendChild(document.createTextNode('—'));

    // Insert beginning cursor marker
    range.insertNode(cursorStart);

    // Insert end cursor marker if any text is selected
    if(!collapsed) {
        var cursorEnd = document.createElement('span');
        cursorEnd.id = 'cursorEnd';
        range.collapse();
        range.insertNode(cursorEnd);
    }
};

// Add callbacks to afterFocus to be called after cursor is replaced
// if you like, this would be useful for styling buttons and so on
var afterFocus = [];
editable.onfocus = function(e) {
    // Slight delay will avoid the initial selection
    // (at start or of contents depending on browser) being mistaken
    setTimeout(function() {
        var cursorStart = document.getElementById('cursorStart'),
            cursorEnd = document.getElementById('cursorEnd');

        // Don't do anything if user is creating a new selection
        if(editable.className.match(/\sselecting(\s|$)/)) {
            if(cursorStart) {
                cursorStart.parentNode.removeChild(cursorStart);
            }
            if(cursorEnd) {
                cursorEnd.parentNode.removeChild(cursorEnd);
            }
        } else if(cursorStart) {
            captureSelection();
            var range = document.createRange();

            if(cursorEnd) {
                range.setStartAfter(cursorStart);
                range.setEndBefore(cursorEnd);

                // Delete cursor markers
                cursorStart.parentNode.removeChild(cursorStart);
                cursorEnd.parentNode.removeChild(cursorEnd);

                // Select range
                selection.removeAllRanges();
                selection.addRange(range);
            } else {
                range.selectNode(cursorStart);

                // Select range
                selection.removeAllRanges();
                selection.addRange(range);

                // Delete cursor marker
                document.execCommand('delete', false, null);
            }
        }

        // Call callbacks here
        for(var i = 0; i < afterFocus.length; i++) {
            afterFocus[i]();
        }
        afterFocus = [];

        // Register selection again
        captureSelection();
    }, 10);
};

Html相关问答推荐

如何增加行背景的宽度而不影响上面的内容?""' HTML CSS

如何将grid—template—column应用于元素中的子元素

当表头包含特殊字符时,R Quarto发布的HTML表中不必要的大列宽

当在双引号|Angular .html文件中使用时,Pretier会将单引号字符替换为&;Quot;

如何使用css为动态用户输入矩阵添加背景色?

仅向上扩展并以最大高度滚动的Div

角化、剪裁、边缘,但仅在底部2和平滑包装上

SVG';COLOR&39;属性不优先于通用css';COLOR&39;属性

列表项文本在占据剩余空间之前在标记下换行

如何使用*ngFor将模板从父级传递到子级

如何使VS代码支持以模仿嵌套的方式对已经包含注释的HTML进行注释?

为什么字体大小而不是 colored颜色 属性适用于元素?

我如何使用 html 在表格的单元格内实现下面显示的背景 colored颜色 加载器(请判断设计参考的图像链接)

Sass 混合动画未正确应用

我正在使用 NVDA 并多次读取关闭按钮,但它的读取非常完美

输入框不是全宽

不同屏幕尺寸的显示问题

如何在 svelte 中对静态 html 文件使用href=

font awesome 的 CDN/CSS 如何工作?

使用模板循环每行列出 3 个 bootstrap 卡