การแทรกข้อความที่เคอร์เซอร์กำลังใช้ Javascript / jquery


167

ฉันมีหน้าเว็บที่มีกล่องข้อความจำนวนมาก เมื่อมีคนคลิกลิงค์ฉันต้องการแทรกคำหรือสองตำแหน่งที่เคอร์เซอร์อยู่หรือผนวกเข้ากับกล่องข้อความที่มีโฟกัส

ตัวอย่างเช่นหากเคอร์เซอร์ / โฟกัสอยู่ในกล่องข้อความที่บอกว่า 'apple' และเขาคลิกลิงก์ที่บอกว่า '[อีเมล]' ดังนั้นฉันต้องการให้กล่องข้อความพูดว่า 'apple bob@example.com'

ฉันจะทำสิ่งนี้ได้อย่างไร สิ่งนี้อาจเป็นไปได้เพราะจะเกิดอะไรขึ้นหากการโฟกัสอยู่บนองค์ประกอบของวิทยุ / ดรอปดาวน์ / ไม่ใช่กล่องข้อความ? สามารถจดจำกล่องข้อความที่เน้นข้อความล่าสุดได้หรือไม่?


ฉันคิดว่ามันเป็นไปได้เพราะมันเป็นพื้นฐานของบรรณาธิการ WYSISYG วิธีการทำฉันไม่รู้
เอียนเอลเลียต


ขอบคุณที่ถามคำถามนี้ ... ตอนนี้ฉันสามารถแทรก "[รุ่น]" ที่เคอร์เซอร์ด้วยส่วนขยาย Chrome ของฉัน!
haykam

หากคุณกำลังมองหาโมดูลที่เรียบง่ายด้วยการยกเลิกการสนับสนุนลองแทรกข้อความ textarea หากคุณต้องการการสนับสนุน IE8 + ลองแพ็คเกจแทรกข้อความ - เคอร์เซอร์
Fregante

คำตอบ:


241

ใช้สิ่งนี้จากที่นี่ :

function insertAtCaret(areaId, text) {
  var txtarea = document.getElementById(areaId);
  if (!txtarea) {
    return;
  }

  var scrollPos = txtarea.scrollTop;
  var strPos = 0;
  var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ?
    "ff" : (document.selection ? "ie" : false));
  if (br == "ie") {
    txtarea.focus();
    var range = document.selection.createRange();
    range.moveStart('character', -txtarea.value.length);
    strPos = range.text.length;
  } else if (br == "ff") {
    strPos = txtarea.selectionStart;
  }

  var front = (txtarea.value).substring(0, strPos);
  var back = (txtarea.value).substring(strPos, txtarea.value.length);
  txtarea.value = front + text + back;
  strPos = strPos + text.length;
  if (br == "ie") {
    txtarea.focus();
    var ieRange = document.selection.createRange();
    ieRange.moveStart('character', -txtarea.value.length);
    ieRange.moveStart('character', strPos);
    ieRange.moveEnd('character', 0);
    ieRange.select();
  } else if (br == "ff") {
    txtarea.selectionStart = strPos;
    txtarea.selectionEnd = strPos;
    txtarea.focus();
  }

  txtarea.scrollTop = scrollPos;
}
<textarea id="textareaid"></textarea>
<a href="#" onclick="insertAtCaret('textareaid', 'text to insert');return false;">Click Here to Insert</a>


7
สิ่งนี้ใช้งานได้ดี แต่ไม่สามารถแทนที่ข้อความที่เลือกได้เช่นเดียวกับโปรแกรมแก้ไขข้อความทั้งหมด สิ่งนี้อาจไม่จำเป็นสำหรับคำถามดั้งเดิมของผู้โพสต์ แต่ถ้าคุณต้องการคุณสามารถแทนที่ 'strPos' ด้วย 'txtArea.selectionEnd' คำตอบของฉันด้านล่างแสดงสิ่งนี้พร้อมกับลบรหัสตรวจจับเบราว์เซอร์หากคุณไม่ต้องการสนับสนุน IE เวอร์ชันเก่า
Jeffrey Harmon

มีวิธีการเลือกองค์ประกอบทั้งหมดด้วยareaIdหรือไม่?
haykam

1
คุณสามารถบรรลุข้อความอัตโนมัติที่เลือกโดยการแทรกฟังก์ชั่นเช่นนี้ function deleteTxt() { var ele = document.getElementById('yourTextarea'); var text = ele.value; text = text.slice(0, ele.selectionStart) + text.slice(ele.selectionEnd); ele.value = text; return text; }
NSTuttle

วิธีแทรกข้อความที่ตำแหน่งของเมาส์
Thamarai T

คุณดีที่สุด!
Ecko Santoso

156

อาจเป็นรุ่นที่สั้นกว่านี้จะเข้าใจได้ง่ายขึ้นหรือไม่

    jQuery("#btn").on('click', function() {
        var $txt = jQuery("#txt");
        var caretPos = $txt[0].selectionStart;
        var textAreaTxt = $txt.val();
        var txtToAdd = "stuff";
        $txt.val(textAreaTxt.substring(0, caretPos) + txtToAdd + textAreaTxt.substring(caretPos) );
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<textarea id="txt" rows="15" cols="70">There is some text here.</textarea>
<input type="button" id="btn" value="OK" />

ฉันเขียนสิ่งนี้เพื่อตอบสนองต่อวิธีการเพิ่มข้อความไปยังกล่องข้อความจากตำแหน่งปัจจุบันของตัวชี้ด้วย jquery?


11
document.getElementById("txt").selectionStart = caretPos + txtToAdd.lengthนอกจากนี้คุณยังสามารถเรียกคืนตำแหน่งเครื่องหมายหลังจากการเปลี่ยนค่าด้วย:
Bludwarf

1
ทำงานให้ฉันขอบคุณ FYI คุณสมบัติ "selectionStart" ไม่มีอยู่ผ่านตัวเลือก jquery $ ("#") คุณต้องผ่าน document.getElementById ()
เลโก้

1
jsfiddle.net/NaHTw/802เป็นวิธีการแก้ปัญหาของคุณด้วยการเพิ่มพิเศษเล็กน้อยเพื่อแทนที่พื้นที่ที่เลือกด้วยสิ่งที่วางไว้
patrick

3
ดีถ้าคุณกำลังจะไปที่ไกลลบ jQuery คุณเช่นกันอาจจะลบมันทั้งหมด ; ^)
รัฟฟิน

8
เพื่อช่วยนี่คือโซลูชันที่สมบูรณ์ด้วยการคืนค่าตำแหน่งลูกศรและแทนที่พื้นที่ที่เลือกด้วยเนื้อหาที่วาง: jsfiddle.net/NaHTw/1028
AlfaTeK

41

คำตอบที่ได้รับอนุมัติจาก George Claghorn ใช้งานได้ดีสำหรับการแทรกข้อความที่ตำแหน่งเคอร์เซอร์ หากผู้ใช้เลือกข้อความและคุณต้องการแทนที่ข้อความนั้น (ประสบการณ์เริ่มต้นด้วยข้อความส่วนใหญ่) คุณจะต้องทำการเปลี่ยนแปลงเล็กน้อยเมื่อตั้งค่าตัวแปร 'ย้อนกลับ'

นอกจากนี้หากคุณไม่จำเป็นต้องรองรับ IE เวอร์ชันเก่ารุ่นทันสมัยรองรับ textarea.selectionStart ดังนั้นคุณสามารถทำการตรวจจับเบราว์เซอร์ทั้งหมดและรหัสเฉพาะ IE ได้

นี่คือเวอร์ชันที่เรียบง่ายที่ใช้งานได้กับ Chrome และ IE11 เป็นอย่างน้อยและจัดการการแทนที่ข้อความที่เลือก

function insertAtCaret(areaId, text) {
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var caretPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0, caretPos);
    var back = (txtarea.value).substring(txtarea.selectionEnd, txtarea.value.length);
    txtarea.value = front + text + back;
    caretPos = caretPos + text.length;
    txtarea.selectionStart = caretPos;
    txtarea.selectionEnd = caretPos;
    txtarea.focus();
    txtarea.scrollTop = scrollPos;
}

นี่เป็นสิ่งที่ดี แต่ไม่คำนึงถึงองค์ประกอบmaxlengthดังนั้นค่าผลลัพธ์ที่ได้หลังจากการแทรกอาจนานกว่าค่าสูงสุด
mbomb007

22

รหัสด้านบนใช้ไม่ได้กับฉันใน IE นี่คือโค้ดบางส่วนจากคำตอบนี้

ฉันหยิบออกมาgetElementByIdเพื่อที่ฉันจะได้อ้างอิงองค์ประกอบในวิธีที่ต่างออกไป

function insertAtCaret(element, text) {
  if (document.selection) {
    element.focus();
    var sel = document.selection.createRange();
    sel.text = text;
    element.focus();
  } else if (element.selectionStart || element.selectionStart === 0) {
    var startPos = element.selectionStart;
    var endPos = element.selectionEnd;
    var scrollTop = element.scrollTop;
    element.value = element.value.substring(0, startPos) +
      text + element.value.substring(endPos, element.value.length);
    element.focus();
    element.selectionStart = startPos + text.length;
    element.selectionEnd = startPos + text.length;
    element.scrollTop = scrollTop;
  } else {
    element.value += text;
    element.focus();
  }
}
input{width:100px}
label{display:block;margin:10px 0}
<label for="in2copy">Copy text from: <input id="in2copy" type="text" value="x"></label>
<label for="in2ins">Element to insert: <input id="in2ins" type="text" value="1,2,3" autofocus></label>
<button onclick="insertAtCaret(document.getElementById('in2ins'),document.getElementById('in2copy').value)">Insert</button>

แก้ไข: เพิ่มข้อมูลโค้ดทำงานjQuery ไม่ได้ถูกใช้


องค์ประกอบเป็นวัตถุ jquery หรือไม่? element.value และ element.focus () ไม่สามารถทำงานทั้ง ...
สกอตต์ฟอร์ด

7
element.focus()เป็นวิธี JavaScript ที่ถูกต้องตามกฎหมายใน DOMElements: w3schools.com/jsref/met_html_focus.asp
oliverseal

1
ความคิดที่ดีที่สุดคือการลดความเข้ากันได้ของ IE
ar2015

2
ใช่ฉันเขียนคำตอบนี้ 7 ปีที่ผ่านมา ณ จุดนี้ IE 11 เป็นรุ่นที่ได้รับการสนับสนุนขั้นต่ำที่ดีและรหัสด้านบนใช้ได้กับมัน
Collin Anderson

6

ใช้คำตอบ @quick_sliv:

function insertAtCaret(el, text) {
    var caretPos = el.selectionStart;
    var textAreaTxt = el.value;
    el.value = textAreaTxt.substring(0, caretPos) + text + textAreaTxt.substring(caretPos);
};

4

วิธีแทรกข้อความไปยังตำแหน่งเคอร์เซอร์ปัจจุบันของกล่องข้อความผ่าน JQuery และ JavaScript

กระบวนการ

  1. ค้นหาตำแหน่งเคอร์เซอร์ปัจจุบัน
  2. รับข้อความที่จะคัดลอก
  3. ตั้งค่าข้อความไว้ที่นั่น
  4. อัปเดตตำแหน่งเคอร์เซอร์

ที่นี่ฉันมี 2 กล่องข้อความและปุ่ม ฉันต้องคลิกที่ตำแหน่งใดตำแหน่งหนึ่งบนกล่องข้อความจากนั้นคลิกที่ปุ่มเพื่อวางข้อความจากกล่องข้อความอื่นไปยังตำแหน่งของกล่องข้อความก่อนหน้า

ปัญหาหลักที่นี่คือการรับตำแหน่งเคอร์เซอร์ปัจจุบันที่เราจะวางข้อความ

//Textbox on which to be pasted
<input type="text" id="txtOnWhichToBePasted" />

//Textbox from where to be pasted
<input type="text" id="txtFromWhichToBePasted" />


//Button on which click the text to be pasted
<input type="button" id="btnInsert" value="Insert"/>


<script type="text/javascript">

$(document).ready(function () {
    $('#btnInsert').bind('click', function () {
            var TextToBePasted = $('#txtFromWhichToBePasted').value;
            var ControlOnWhichToBePasted = $('#txtOnWhichToBePasted');

            //Paste the Text
            PasteTag(ControlOnWhichToBePasted, TextToBePasted);
        });
    });

//Function Pasting The Text
function PasteTag(ControlOnWhichToBePasted,TextToBePasted) {
    //Get the position where to be paste

    var CaretPos = 0;
    // IE Support
    if (document.selection) {

        ControlOnWhichToBePasted.focus();
        var Sel = document.selection.createRange();

        Sel.moveStart('character', -ctrl.value.length);

        CaretPos = Sel.text.length;
    }
    // Firefox support
    else if (ControlOnWhichToBePasted.selectionStart || ControlOnWhichToBePasted.selectionStart == '0')
        CaretPos = ControlOnWhichToBePasted.selectionStart;

    //paste the text
    var WholeString = ControlOnWhichToBePasted.value;
    var txt1 = WholeString.substring(0, CaretPos);
    var txt2 = WholeString.substring(CaretPos, WholeString.length);
    WholeString = txt1 + TextToBePasted + txt2;
    var CaretPos = txt1.length + TextToBePasted.length;
    ControlOnWhichToBePasted.value = WholeString;

    //update The cursor position 
    setCaretPosition(ControlOnWhichToBePasted, CaretPos);
}

function setCaretPosition(ControlOnWhichToBePasted, pos) {

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

</script>

3

การเพิ่มข้อความไปยังตำแหน่งเคอร์เซอร์ปัจจุบันมีสองขั้นตอน:

  1. การเพิ่มข้อความที่ตำแหน่งเคอร์เซอร์ปัจจุบัน
  2. การอัปเดตตำแหน่งเคอร์เซอร์ปัจจุบัน

การสาธิต: https://codepen.io/anon/pen/qZXmgN

ทดสอบใน Chrome 48, Firefox 45, IE 11 และ Edge 25

JS:

function addTextAtCaret(textAreaId, text) {
    var textArea = document.getElementById(textAreaId);
    var cursorPosition = textArea.selectionStart;
    addTextAtCursorPosition(textArea, cursorPosition, text);
    updateCursorPosition(cursorPosition, text, textArea);
}
function addTextAtCursorPosition(textArea, cursorPosition, text) {
    var front = (textArea.value).substring(0, cursorPosition);
    var back = (textArea.value).substring(cursorPosition, textArea.value.length);
    textArea.value = front + text + back;
}
function updateCursorPosition(cursorPosition, text, textArea) {
    cursorPosition = cursorPosition + text.length;
    textArea.selectionStart = cursorPosition;
    textArea.selectionEnd = cursorPosition;
    textArea.focus();    
}

HTML:

<div>
    <button type="button" onclick="addTextAtCaret('textArea','Apple')">Insert Apple!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Mango')">Insert Mango!</button>
    <button type="button" onclick="addTextAtCaret('textArea','Orange')">Insert Orange!</button>
</div>
<textarea id="textArea" rows="20" cols="50"></textarea>

2

ฉันคิดว่าคุณสามารถใช้ JavaScript ต่อไปนี้เพื่อติดตามกล่องข้อความที่มุ่งเน้นไปที่ล่าสุด:

<script>
var holdFocus;

function updateFocus(x)
{
    holdFocus = x;
}

function appendTextToLastFocus(text)
{
    holdFocus.value += text;
}
</script>

การใช้งาน:

<input type="textbox" onfocus="updateFocus(this)" />
<a href="#" onclick="appendTextToLastFocus('textToAppend')" />

วิธีแก้ปัญหาก่อนหน้า (อุปกรณ์ประกอบฉากถึง gclaghorn) ใช้ textarea และคำนวณตำแหน่งของเคอร์เซอร์ด้วยดังนั้นมันอาจจะดีกว่าสำหรับสิ่งที่คุณต้องการ ในทางกลับกันอันนี้จะเบาขึ้นถ้านั่นคือสิ่งที่คุณกำลังมองหา


ความคิดที่ดี. ฉันใช้ jQuery เพื่อให้แต่ละกล่องข้อความที่มีบางคลาสมีเหตุการณ์นี้นำไปใช้กับพวกเขาแทนที่จะต้องใส่ "onfocus = ... " ใน html ของแต่ละกล่องข้อความ แต่แนวทางที่ดี :)
คลิกโหวต

1

คำตอบที่ยอมรับนั้นใช้ไม่ได้กับฉันใน Internet Explorer 9 ฉันตรวจสอบแล้วและการตรวจหาเบราว์เซอร์ทำงานไม่ถูกต้องตรวจพบff (firefox) เมื่อฉันอยู่ที่ Internet Explorer

ฉันเพิ่งทำการเปลี่ยนแปลงนี้:

if ($.browser.msie) 

แทน:

if (br == "ie") { 

รหัสผลลัพธ์คือรหัสนี้:

function insertAtCaret(areaId,text) {
    var txtarea = document.getElementById(areaId);
    var scrollPos = txtarea.scrollTop;
    var strPos = 0;
    var br = ((txtarea.selectionStart || txtarea.selectionStart == '0') ? 
        "ff" : (document.selection ? "ie" : false ) );

    if ($.browser.msie) { 
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        strPos = range.text.length;
    }
    else if (br == "ff") strPos = txtarea.selectionStart;

    var front = (txtarea.value).substring(0,strPos);  
    var back = (txtarea.value).substring(strPos,txtarea.value.length); 
    txtarea.value=front+text+back;
    strPos = strPos + text.length;
    if (br == "ie") { 
        txtarea.focus();
        var range = document.selection.createRange();
        range.moveStart ('character', -txtarea.value.length);
        range.moveStart ('character', strPos);
        range.moveEnd ('character', 0);
        range.select();
    }
    else if (br == "ff") {
        txtarea.selectionStart = strPos;
        txtarea.selectionEnd = strPos;
        txtarea.focus();
    }
    txtarea.scrollTop = scrollPos;
}


0

คุณสามารถมุ่งเน้นช่องข้อความที่จำเป็นและแทรกข้อความที่นั่น ไม่มีวิธีใดที่จะค้นหาว่า AFAIK โฟกัสอยู่ที่ใด (อาจมีการเชื่อมต่อกับโหนด DOM ทั้งหมดหรือไม่)

ตรวจสอบ stackoverflow - มันมีทางออกสำหรับคุณ: ฉันจะรู้ได้อย่างไรว่าองค์ประกอบ DOM ใดที่มีโฟกัส?


0

เนื้อหาที่สามารถแก้ไขได้ HTML หรือการเลือกองค์ประกอบ DOM อื่น ๆ

หากคุณพยายามแทรกที่คาเร็ตบน a สิ่ง<div contenteditable="true">นี้จะกลายเป็นเรื่องยากมากขึ้นโดยเฉพาะหากมีเด็กอยู่ในคอนเทนเนอร์ที่แก้ไขได้

ฉันโชคดีจริงๆที่ใช้ห้องสมุดRangy :

มันมีคุณสมบัติที่ยอดเยี่ยมมากมายเช่น:

  • บันทึกตำแหน่งหรือส่วนที่เลือก
  • จากนั้นในภายหลังให้คืนค่าตำแหน่งหรือส่วนที่เลือก
  • รับการเลือก HTML หรือข้อความธรรมดา
  • ท่ามกลางคนอื่น ๆ

การสาธิตออนไลน์ไม่ทำงานครั้งสุดท้ายที่ฉันตรวจสอบ แต่ repo มีการสาธิตการทำงาน ในการเริ่มต้นให้ดาวน์โหลด Repo จาก Git หรือ NPM ง่าย ๆ จากนั้นเปิด. / rangy/demos/index.html

มันทำให้การทำงานกับคาเร็ต pos และการเลือกข้อความเป็นเรื่องง่าย!


0

คำตอบของคำถามนี้ถูกโพสต์เมื่อนานมาแล้วและฉันก็สะดุดเมื่อค้นหาผ่าน Google HTML5 จัดเตรียมHTMLInputElement APIที่มีเมธอด setRangeText ()ซึ่งจะแทนที่ช่วงของข้อความในองค์ประกอบ<input>หรือ<textarea>องค์ประกอบด้วยสตริงใหม่:

element.setRangeText('abc');

ดังกล่าวข้างต้นจะเข้ามาแทนที่การเลือกทำภายในกับelement abcคุณยังสามารถระบุได้ว่าส่วนใดของค่าอินพุตที่จะแทนที่:

element.setRangeText('abc', 3, 5);

ดังกล่าวข้างต้นจะเข้ามาแทนที่ที่ 4 จนถึงตัวอักษรที่ 6 abcของมูลค่าการป้อนข้อมูลด้วย คุณยังสามารถระบุวิธีการตั้งค่าการเลือกหลังจากที่ข้อความถูกแทนที่โดยการจัดเตรียมหนึ่งในสตริงต่อไปนี้เป็นพารามิเตอร์ที่ 4:

  • 'preserve'พยายามคงการเลือกไว้ นี่คือค่าเริ่มต้น
  • 'select' เลือกข้อความที่แทรกใหม่
  • 'start' ย้ายส่วนที่เลือกไปก่อนข้อความที่แทรก
  • 'end' ย้ายส่วนที่เลือกไปหลังข้อความที่แทรก

ความเข้ากันได้ของเบราว์เซอร์

หน้า MDN สำหรับsetRangeTextไม่ได้ให้ข้อมูลความเข้ากันได้ของเบราว์เซอร์ แต่ฉันเดาว่ามันจะเหมือนกับHTMLInputElement.setSelectionRange ()ซึ่งโดยทั่วไปคือเบราว์เซอร์สมัยใหม่ทั้งหมด IE 9 ขึ้นไป Edge 12 และสูงกว่า

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