如何将光标移动到可信实体的末尾 [英] How to move cursor to end of contenteditable entity
问题描述
我需要将插入符号移到 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屋!