在html文本框中设置键盘插入符的位置


186

有人知道如何将文本框中的键盘插入符移动到特定位置吗?

例如,如果一个文本框(例如,输入元素,而不是文本区域)中包含50个字符,而我想将插入号放在字符20之前,我该如何处理?

这与以下问题有所不同:jQuery在Text Area中设置光标位置,这需要jQuery。

Answers:


210

摘自Josh Stodola的使用Javascript在Textbox或TextArea中设置键盘插入符号的位置

泛型函数,可让您将插入符号插入所需的文本框或文本区域的任何位置:

function setCaretPosition(elemId, caretPos) {
    var elem = document.getElementById(elemId);

    if(elem != null) {
        if(elem.createTextRange) {
            var range = elem.createTextRange();
            range.move('character', caretPos);
            range.select();
        }
        else {
            if(elem.selectionStart) {
                elem.focus();
                elem.setSelectionRange(caretPos, caretPos);
            }
            else
                elem.focus();
        }
    }
}

第一个预期参数是您希望插入键盘插入符号的元素的ID。如果找不到该元素,则不会发生任何事情(显然)。第二个参数是插入号位置索引。零将把键盘插入符号放在开头。如果您传递的数字大于elements值中的字符数,它将把键盘插入符号放在最后。

在IE6及更高版本,Firefox 2,Opera 8,Netscape 9,SeaMonkey和Safari上进行了测试。不幸的是,在Safari上,它无法与onfocus事件结合使用。

使用上述功能强制键盘插入符号在获得焦点时跳至页面上所有文本区域的末尾的示例:

function addLoadEvent(func) {
    if(typeof window.onload != 'function') {
        window.onload = func;
    }
    else {
        if(func) {
            var oldLoad = window.onload;

            window.onload = function() {
                if(oldLoad)
                        oldLoad();

                func();
            }
        }
    }
}

// The setCaretPosition function belongs right here!

function setTextAreasOnFocus() {
/***
 * This function will force the keyboard caret to be positioned
 * at the end of all textareas when they receive focus.
 */
    var textAreas = document.getElementsByTagName('textarea');

    for(var i = 0; i < textAreas.length; i++) {
        textAreas[i].onfocus = function() {
            setCaretPosition(this.id, this.value.length);
        }
    }

    textAreas = null;
}

addLoadEvent(setTextAreasOnFocus);

4
if(elem.selectionStart)正如jhnns的答案所指出的,当selectionStart为0时中断。
mpartel 2012年

1
这对我不起作用。当我单击实际的文本框时,我希望插入符号的位置在开头。看看我的小提琴jsfiddle.net/khx2w
elad.chen 2013年

setCaretPosition函数可以正常工作。但是,您的addActionHandler函数不会。但是即使没有这些,我也无法使光标移到焦点上。这很可能是因为浏览器会根据点击位置自行设置光标位置。据我所知,似乎没有办法解决它,但我可能完全错了。
2013年

适用于IE9,FF25,但不适用于Chrome30。总比没有强!
Umber Ferrule,2013年

我有elem.value = elem.value.replace(/^9/g,'+79')代码。在OperaMINI光标之后+。此功能
无济于事

53

答案中的链接已断开,该链接应该可用(所有功劳都归blog.vishalon.net):

http://snipplr.com/view/5144/getset-cursor-in-html-textarea/

万一代码再次丢失,这是两个主要功能:

function doGetCaretPosition(ctrl)
{
 var CaretPos = 0;

 if (ctrl.selectionStart || ctrl.selectionStart == 0)
 {// Standard.
  CaretPos = ctrl.selectionStart;
 }
 else if (document.selection)
 {// Legacy IE
  ctrl.focus ();
  var Sel = document.selection.createRange ();
  Sel.moveStart ('character', -ctrl.value.length);
  CaretPos = Sel.text.length;
 }

 return (CaretPos);
}


function setCaretPosition(ctrl,pos)
{
 if (ctrl.setSelectionRange)
 {
  ctrl.focus();
  ctrl.setSelectionRange(pos,pos);
 }
 else if (ctrl.createTextRange)
 {
  var range = ctrl.createTextRange();
  range.collapse(true);
  range.moveEnd('character', pos);
  range.moveStart('character', pos);
  range.select();
 }
}

1
基本功能为+1,尽管必须进行一些调整。使用范围方法时,必须从“ pos”中减去行数。
罗布W

37

由于我实际上确实需要此解决方案,并且典型的基准解决方案(集中输入-然后将值设置为等于自身无法跨浏览器工作,因此我花了一些时间进行调整和编辑,以使其正常运行。基于@ kd7的代码,这就是我提出的。

请享用!适用于IE6 +,Firefox,Chrome,Safari,Opera

跨浏览器插入符的定位技术(例如:将光标移动到END)

// ** USEAGE ** (returns a boolean true/false if it worked or not)
// Parameters ( Id_of_element, caretPosition_you_want)

setCaretPosition('IDHERE', 10); // example

肉类和土豆基本上是@ kd7的setCaretPosition,最大的调整是if (el.selectionStart || el.selectionStart === 0),在firefox中,selectionStart从0开始,在布尔值中它当然变成了False,所以它在那里中断了。

在chrome中,最大的问题是仅仅给出它.focus()是不够的(它一直选择所有文本!)因此,el.value = el.value;在调用函数之前,我们将自身的值设置为自身,现在它对输入以使用selectionStart

function setCaretPosition(elemId, caretPos) {
    var el = document.getElementById(elemId);

    el.value = el.value;
    // ^ this is used to not only get "focus", but
    // to make sure we don't have it everything -selected-
    // (it causes an issue in chrome, and having it doesn't hurt any other browser)

    if (el !== null) {

        if (el.createTextRange) {
            var range = el.createTextRange();
            range.move('character', caretPos);
            range.select();
            return true;
        }

        else {
            // (el.selectionStart === 0 added for Firefox bug)
            if (el.selectionStart || el.selectionStart === 0) {
                el.focus();
                el.setSelectionRange(caretPos, caretPos);
                return true;
            }

            else  { // fail city, fortunately this never happens (as far as I've tested) :)
                el.focus();
                return false;
            }
        }
    }
}

@mcpDESIGNS当我将重点放在文本输入上时,我正在尝试使用此功能,但是我无处可寻,请使用纯JavaScript来帮助您应用此功能吗?
elad.chen 2013年

@ elad.chen您是否在尝试将它们放在文本框的末尾时将其放置在文本框的末尾?
Mark Pieszak-Trilon.io,2013年

@mcpDESIGNS我想在元素被聚焦后立即将光标放在字段的开头。看到小提琴:jsfiddle.net/KuLTU/3
elad.chen

@ elad.chen抱歉,您的疯狂回复!只是,事件更改.onclick,而不是.onfocus你的search_field_focus函数内
马克Pieszak - Trilon.io

2
el.value = el.value; [...] if(el !== null)-我会交换这两行。如果el为null,el.value = el.value则将失败,因此该行应位于内if
BackSlash

21

我已经稍微调整了kd7的答案,因为当selectionStart偶然为0时elem.selectionStart的评估结果为false。

function setCaretPosition(elem, caretPos) {
    var range;

    if (elem.createTextRange) {
        range = elem.createTextRange();
        range.move('character', caretPos);
        range.select();
    } else {
        elem.focus();
        if (elem.selectionStart !== undefined) {
            elem.setSelectionRange(caretPos, caretPos);
        }
    }
}

8

我找到了解决此问题的简便方法,并在IE和Chrome中进行了测试:

function setCaret(elemId, caret)
 {
   var elem = document.getElementById(elemId);
   elem.setSelectionRange(caret, caret);
 }

将文本框ID和插入位置传递给此函数。


3

如果您需要关注某个文本框,而唯一的问题是整个文本都被突出显示,而您希望插入符号位于末尾,那么在这种特定情况下,您可以使用以下技巧在聚焦后将文本框值设置为其自身:

$("#myinputfield").focus().val($("#myinputfield").val());

2
<!DOCTYPE html>
<html>
<head>
<title>set caret position</title>
<script type="application/javascript">
//<![CDATA[
window.onload = function ()
{
 setCaret(document.getElementById('input1'), 13, 13)
}

function setCaret(el, st, end)
{
 if (el.setSelectionRange)
 {
  el.focus();
  el.setSelectionRange(st, end);
 }
 else
 {
  if (el.createTextRange)
  {
   range = el.createTextRange();
   range.collapse(true);
   range.moveEnd('character', end);
   range.moveStart('character', st);
   range.select();
  }
 }
}
//]]>
</script>
</head>
<body>

<textarea id="input1" name="input1" rows="10" cols="30">Happy kittens dancing</textarea>

<p>&nbsp;</p>

</body>
</html>

2
function SetCaretEnd(tID) {
    tID += "";
    if (!tID.startsWith("#")) { tID = "#" + tID; }
    $(tID).focus();
    var t = $(tID).val();
    if (t.length == 0) { return; }
    $(tID).val("");
    $(tID).val(t);
    $(tID).scrollTop($(tID)[0].scrollHeight); }

未捕获的类型错误:对象[对象HTMLInputElement]无方法“startsWith”
bobpaul

1
@bobpaul:tID应该是元素的ID,而不是元素对象本身。如果要传递元素对象,则只需在此方法中删除前两行即可,它将起作用。
敬畏

2

我将修复以下条件:

function setCaretPosition(elemId, caretPos)
{
 var elem = document.getElementById(elemId);
 if (elem)
 {
  if (typeof elem.createTextRange != 'undefined')
  {
   var range = elem.createTextRange();
   range.move('character', caretPos);
   range.select();
  }
  else
  {
   if (typeof elem.selectionStart != 'undefined')
    elem.selectionStart = caretPos;
   elem.focus();
  }
 }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.