รับตำแหน่งเคอร์เซอร์ (เป็นตัวอักษร) ภายในช่องป้อนข้อความ


211

ฉันจะรับตำแหน่งคาเร็ตจากภายในช่องป้อนข้อมูลได้อย่างไร

ฉันพบบิตและชิ้นส่วนเล็ก ๆ ผ่าน Google แต่ไม่มีสิ่งใดที่สามารถพิสูจน์ได้

โดยทั่วไปบางอย่างเช่นปลั๊กอิน jQuery จะเหมาะที่สุดดังนั้นฉันสามารถทำได้

$("#myinput").caretPosition()

2
ลองค้นหา 'ตำแหน่งเคอร์เซอร์' ซึ่งจะทำให้คุณได้รับความนิยมมากขึ้นรวมถึงหัวข้อเกี่ยวกับเรื่องนี้ใน SO
อเล็กซ์

1
เป็นไปได้ที่ซ้ำกันของวิธีการรับตำแหน่งเคอร์เซอร์ใน textarea? . ดูเพิ่มเติมที่: ปลั๊กอิน FieldSelection
CMS

2
@CMS หาตำแหน่งในนั้นเป็นวิธีที่ง่ายกว่าการทำไว้ใน<input> <textarea>
Andrew Mao

1
@AndrewMao: และวิธีที่ยากขึ้นถ้าข้อความถูกเลื่อนและเครื่องหมายรูปหมวกเป็นsizeอักขระที่ผ่านมา
Dan Dascalescu

@alec: ฉันยอมรับการค้นหาเคอร์เซอร์แทนคาเร็ตอาจให้ผลลัพธ์มากกว่านี้ ตามที่ระบุไว้ที่อื่นฉันได้เรียนรู้ว่าเครื่องหมายรูปหมวกเป็นคำที่เหมาะสมกว่า เคอร์เซอร์แทนตำแหน่งอะไรในขณะที่ลูกศรแทนตำแหน่งเฉพาะในข้อความ
Suncat2000

คำตอบ:


247

ปรับปรุงง่ายขึ้น:

ใช้field.selectionStart ตัวอย่างในคำตอบนี้

ขอบคุณ @commonSenseCode สำหรับการชี้เรื่องนี้


คำตอบเก่า:

พบทางออกนี้ ไม่ใช่ jquery based แต่ไม่มีปัญหาในการรวมเข้ากับ jquery:

/*
** Returns the caret (cursor) position of the specified text field (oField).
** Return value range is 0-oField.value.length.
*/
function doGetCaretPosition (oField) {

  // Initialize
  var iCaretPos = 0;

  // IE Support
  if (document.selection) {

    // Set focus on the element
    oField.focus();

    // To get cursor position, get empty selection range
    var oSel = document.selection.createRange();

    // Move selection start to 0 position
    oSel.moveStart('character', -oField.value.length);

    // The caret position is selection length
    iCaretPos = oSel.text.length;
  }

  // Firefox support
  else if (oField.selectionStart || oField.selectionStart == '0')
    iCaretPos = oField.selectionDirection=='backward' ? oField.selectionStart : oField.selectionEnd;

  // Return results
  return iCaretPos;
}

9
else if (oField.selectionStart || oField.selectionStart == '0')อาจเป็นelse if (typeof oField.selectionStart==='number')
user2428118

แนวคิดของ "oField.focus ()" คืออะไร? มันใช้งานได้สำหรับฉันที่ไม่มีบรรทัดนี้ ระวังหากคุณใช้เหตุการณ์เบลอที่อินพุตและเรียกใช้ฟังก์ชันนั้นภายในการโทรกลับ
คิริลล์ Reznikov

คุณกำลังทดสอบสิ่งนั้นกับ IE หรือไม่? ทั้งหมดนั้นถ้าส่วนถูกดำเนินการบน IE เท่านั้น ใน IE มีการเลือกระดับโลกเท่านั้นนั่นเป็นสาเหตุว่าทำไมมันถึงdocument.selectionไม่ใช่field.selectionหรือมีบางอย่าง นอกจากนี้ยังเป็นไปได้ใน IE 7 (ไม่ทราบว่ายังคงเป็นไปได้ใน 8+) เพื่อเลือกบางอย่างแล้วกด TAB นอกสนามโดยไม่ต้องเสียการเลือก วิธีนี้เมื่อเลือกข้อความ แต่ไม่ได้เน้นฟิลด์document.selectionส่งคืนค่าการเลือกศูนย์ document.selectionนั่นเป็นเหตุผลที่เป็นวิธีแก้ปัญหาสำหรับข้อผิดพลาดนี้คุณจะต้องมุ่งเน้นองค์ประกอบก่อนที่จะอ่าน
bezmax

รับ 0 สำหรับโครเมี่ยมและ Firefox เสมอ
Kaushik Thanki

117

เยี่ยมมากขอบคุณมากสำหรับ Max

ฉันได้รวบรวมฟังก์ชั่นการใช้งานไว้ในคำตอบของเขาลงใน jQuery หากใครต้องการใช้งาน

(function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if ('selectionStart' in input) {
            // Standard-compliant browsers
            return input.selectionStart;
        } else if (document.selection) {
            // IE
            input.focus();
            var sel = document.selection.createRange();
            var selLen = document.selection.createRange().text.length;
            sel.moveStart('character', -input.value.length);
            return sel.text.length - selLen;
        }
    }
})(jQuery);

3
ไม่input = $(this).get(0)เหมือนกันinput = thisใช่ไหม
Mic

4
@ ไม่ใช่ฉันไม่ใช่ในปลั๊กอิน jQuery ในปลั๊กอินthisหมายถึงชุดที่ห่อเต็ม รหัสของเขายังคงไม่ถูกต้อง this.get(0)แต่มันก็ควรจะเป็น รหัสของเขาอาจยังใช้งานได้เพราะการห่อชุดที่ถูกห่อใหม่นั้นไม่ได้ทำอะไรเลย
Chev

1
สิ่งนี้ทำให้ฉันมีข้อมูลที่ไม่ถูกต้อง ฉันกำลังดูตำแหน่งเคอร์เซอร์เมื่อป้อนข้อความ ซอของฉันแสดงให้เห็นถึงสิ่งนี้คือ: jsfiddle.net/fallenreaper/TSwyk
Fallenreaper

1
Firefox สร้าง NS_ERROR_FAILURE ใน input.selectionStart เมื่ออินพุตเป็นชนิดตัวเลขห่อในลอง {} catch {}?
niall.campbell

จะดีสำหรับผึ้งใหม่ถ้าคุณเพิ่มการใช้งานสำหรับฟังก์ชั่น
Muhammad Omer Aslam

98

ง่ายมาก

อัปเดตคำตอบ

การใช้งานselectionStartก็เป็นที่เข้ากันได้กับเบราว์เซอร์ที่สำคัญทั้งหมด

document.getElementById('foobar').addEventListener('keyup', e => {
  console.log('Caret at: ', e.target.selectionStart)
})
<input id="foobar" />

อัปเดต: ใช้งานได้เฉพาะเมื่อไม่มีการกำหนดประเภทหรือtype="text"ในอินพุต


2
หากฉันเปลี่ยนตำแหน่งโดยใช้เมาส์แสดงว่าไม่ได้พิมพ์ในคอนโซล มีวิธีแก้ไขไหม
Eugene Barsky

3
@EugeneBarsky เพียงเพิ่มตัวฟังเหตุการณ์ใหม่สำหรับเหตุการณ์การคลิก คุณสามารถตรวจสอบ.selectionStartสถานที่ให้บริการได้ตลอดเวลา ( document.getElementById('foobar').selectionStart) มันไม่จำเป็นต้องอยู่ภายในฟังเหตุการณ์
JJJ

3
ยอดเยี่ยม แต่ไม่ทำงานใน Firefox หรือ Chrome เมื่อประเภทการป้อนข้อมูลเป็นตัวเลข
Adam R. Gray

26

มีวิธีการแก้ปัญหาที่ง่ายมาก ลองรหัสต่อไปนี้กับผลการตรวจสอบ -

<html>
<head>
<script>
    function f1(el) {
    var val = el.value;
    alert(val.slice(0, el.selectionStart).length);
}
</script>
</head>
<body>
<input type=text id=t1 value=abcd>
    <button onclick="f1(document.getElementById('t1'))">check position</button>
</body>
</html>

ฉันจะให้คุณfiddle_demo


13
sliceเป็นการดำเนินการที่ค่อนข้างแพงและไม่ได้เพิ่มสิ่งใดใน 'วิธีแก้ปัญหา' el.selectionStartนี้เท่ากับความยาวของส่วนของคุณ แค่คืนสิ่งนั้น นอกจากนี้เหตุผลที่การแก้ปัญหาอื่น ๆ ที่มีความซับซ้อนมากขึ้นเป็นเพราะพวกเขาจัดการกับเบราว์เซอร์อื่น ๆ selectionStartที่ไม่สนับสนุน
mpen

ฉันเลิกงานที่ฉันต้องทำงานกับรหัสที่มีชื่อตัวแปรเช่นนี้
Michael Scheper

@Michael Scheper - คุณหมายถึง 'el' สำหรับองค์ประกอบและ 'val' สำหรับความคุ้มค่าหรือไม่ นี่เป็นเรื่องธรรมดา ...
2782001

6
@ user2782001: ฉันสะกดผิด - ความกังวลหลักของฉันคือชื่อฟังก์ชั่น f1มีความหมายใกล้เคียงกับ 'user2782001' 😉
Michael Scheper

16

ตอนนี้มีปลั๊กอินที่ดีสำหรับสิ่งนี้: ปลั๊กอิน Caret

จากนั้นคุณสามารถรับตำแหน่งโดยใช้$("#myTextBox").caret()หรือตั้งค่าผ่าน$("#myTextBox").caret(position)


1
ปลั๊กอิน
คาเร็ต

4
ดีฉันได้มันทำงานกับ <input type = "text" id = "myTextBox" /> และใช้รหัสข้างต้น
Jens Mikkelsen

14
   (function($) {
    $.fn.getCursorPosition = function() {
        var input = this.get(0);
        if (!input) return; // No (input) element found
        if (document.selection) {
            // IE
           input.focus();
        }
        return 'selectionStart' in input ? input.selectionStart:'' || Math.abs(document.selection.createRange().moveStart('character', -input.value.length));
     }
   })(jQuery);

10

มีคำตอบที่ดีอยู่เล็กน้อยที่โพสต์ที่นี่ แต่ฉันคิดว่าคุณสามารถทำให้โค้ดของคุณง่ายขึ้นและข้ามการตรวจสอบเพื่อinputElement.selectionStartรับการสนับสนุน: ไม่รองรับเฉพาะ IE8 และเก่ากว่า(ดูเอกสารประกอบ ) ซึ่งแสดงถึงน้อยกว่า 1% ของการใช้เบราว์เซอร์ปัจจุบัน

var input = document.getElementById('myinput'); // or $('#myinput')[0]
var caretPos = input.selectionStart;

// and if you want to know if there is a selection or not inside your input:

if (input.selectionStart != input.selectionEnd)
{
    var selectionValue =
    input.value.substring(input.selectionStart, input.selectionEnd);
}

2

บางทีคุณอาจต้องเลือกช่วงนอกเหนือจากตำแหน่งเคอร์เซอร์ นี่คือฟังก์ชั่นที่เรียบง่ายคุณไม่จำเป็นต้องมี jQuery:

function caretPosition(input) {
    var start = input[0].selectionStart,
        end = input[0].selectionEnd,
        diff = end - start;

    if (start >= 0 && start == end) {
        // do cursor position actions, example:
        console.log('Cursor Position: ' + start);
    } else if (start >= 0) {
        // do ranged select actions, example:
        console.log('Cursor Position: ' + start + ' to ' + end + ' (' + diff + ' selected chars)');
    }
}

สมมติว่าคุณต้องการเรียกมันบนอินพุตเมื่อใดก็ตามที่มีการเปลี่ยนแปลงหรือเมาส์ย้ายตำแหน่งเคอร์เซอร์ (ในกรณีนี้เรากำลังใช้ jQuery .on()) สำหรับเหตุผลด้านประสิทธิภาพอาจเป็นความคิดที่ดีที่จะเพิ่มsetTimeout()หรือสิ่งที่คล้ายกับขีดเส้นใต้_debounce()ถ้ามีเหตุการณ์เกิดขึ้นใน:

$('input[type="text"]').on('keyup mouseup mouseleave', function() {
    caretPosition($(this));
});

นี่คือซอหากคุณต้องการลองใช้: https://jsfiddle.net/Dhaupin/91189tq7/


0

const inpT = document.getElementById("text-box");
const inpC = document.getElementById("text-box-content");
// swch gets  inputs .
var swch;
// swch  if corsur is active in inputs defaulte is false .
var isSelect = false;

var crnselect;
// on focus
function setSwitch(e) {
  swch = e;
  isSelect = true;
  console.log("set Switch: " + isSelect);
}
// on click ev
function setEmoji() {
  if (isSelect) {
    console.log("emoji added :)");
    swch.value += ":)";
    swch.setSelectionRange(2,2 );
    isSelect = true;
  }

}
// on not selected on input . 
function onout() {
  // الافنت  اون كي اب 
  crnselect = inpC.selectionStart;
  
  // return input select not active after 200 ms .
  var len = swch.value.length;
  setTimeout(() => {
   (len == swch.value.length)? isSelect = false:isSelect = true;
  }, 200);
}
<h1> Try it !</h1>
    
		<input type="text" onfocus = "setSwitch(this)" onfocusout = "onout()" id="text-box" size="20" value="title">
		<input type="text" onfocus = "setSwitch(this)"  onfocusout = "onout()"  id="text-box-content" size="20" value="content">
<button onclick="setEmoji()">emogi :) </button>

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.