如何将光标移动到可信实体的末尾 [英] How to move cursor to end of contenteditable entity

查看:148
本文介绍了如何将光标移动到可信实体的末尾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将插入符号移到 contenteditable 节点的末尾,就像在Gmail备注小部件上一样。

I need to move caret to end of contenteditable node like on Gmail notes widget.

我读过线程在StackOverflow上,但这些解决方案基于使用输入,它们不适用于 contenteditable 元素。

I read threads on StackOverflow, but those solutions are based on using inputs and they doesn't work with contenteditable elements.

推荐答案

还有另一个问题。

Nico Burns 的解决方案如果 contenteditable div不包含其他多线元素。

The Nico Burns's solution works if the contenteditable div doesn't contain other multilined elements.

例如,如果一个div包含其他div,而这些其他div包含其他内容,可能会出现一些问题。

For instance, if a div contains other divs, and these other divs contain other stuff inside, could occur some problems.

为了解决它们,我'我们安排了以下解决方案,这是对 Nico 的改进:

In order to solve them, I've arranged the following solution, that is an improvement of the Nico's one:

//Namespace management idea from http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/
(function( cursorManager ) {

    //From: http://www.w3.org/TR/html-markup/syntax.html#syntax-elements
    var voidNodeTags = ['AREA', 'BASE', 'BR', 'COL', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR', 'BASEFONT', 'BGSOUND', 'FRAME', 'ISINDEX'];

    //From: https://stackoverflow.com/questions/237104/array-containsobj-in-javascript
    Array.prototype.contains = function(obj) {
        var i = this.length;
        while (i--) {
            if (this[i] === obj) {
                return true;
            }
        }
        return false;
    }

    //Basic idea from: https://stackoverflow.com/questions/19790442/test-if-an-element-can-contain-text
    function canContainText(node) {
        if(node.nodeType == 1) { //is an element node
            return !voidNodeTags.contains(node.nodeName);
        } else { //is not an element node
            return false;
        }
    };

    function getLastChildElement(el){
        var lc = el.lastChild;
        while(lc && lc.nodeType != 1) {
            if(lc.previousSibling)
                lc = lc.previousSibling;
            else
                break;
        }
        return lc;
    }

    //Based on Nico Burns's answer
    cursorManager.setEndOfContenteditable = function(contentEditableElement)
    {

        while(getLastChildElement(contentEditableElement) &&
              canContainText(getLastChildElement(contentEditableElement))) {
            contentEditableElement = getLastChildElement(contentEditableElement);
        }

        var range,selection;
        if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+
        {    
            range = document.createRange();//Create a range (a range is a like the selection but invisible)
            range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range
            range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
            selection = window.getSelection();//get the selection object (allows you to change selection)
            selection.removeAllRanges();//remove any selections already made
            selection.addRange(range);//make the range you have just created the visible selection
        }
        else if(document.selection)//IE 8 and lower
        { 
            range = document.body.createTextRange();//Create a range (a range is a like the selection but invisible)
            range.moveToElementText(contentEditableElement);//Select the entire contents of the element with the range
            range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start
            range.select();//Select the range (make it the visible selection
        }
    }

}( window.cursorManager = window.cursorManager || {}));

用法:

var editableDiv = document.getElementById("my_contentEditableDiv");
cursorManager.setEndOfContenteditable(editableDiv);

这样,光标肯定位于最后一个元素的末尾,最终嵌套。

In this way, the cursor is surely positioned at the end of the last element, eventually nested.

编辑#1 :为了更通用,while语句还应考虑所有其他不能包含文本的标记。这些元素名为 void elements ,并且在这个问题中有一些方法可以测试元素是否为空。因此,假设存在一个名为的函数canContainText ,如果参数不是void元素,则返回 true ,以下行代码:

EDIT #1: In order to be more generic, the while statement should consider also all the other tags which cannot contain text. These elements are named void elements, and in this question there are some methods on how to test if an element is void. So, assuming that exists a function called canContainText that returns true if the argument is not a void element, the following line of code:

contentEditableElement.lastChild.tagName.toLowerCase() != 'br'

应替换为:

canContainText(getLastChildElement(contentEditableElement))

编辑#2 :上面的代码是完全更新,描述和讨论的每个更改

EDIT #2: The above code is fully updated, with every changes described and discussed

这篇关于如何将光标移动到可信实体的末尾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆