वर्तमान कर्सर स्थिति में टेक्स्टारिया में टेक्स्ट कैसे डालें?


124

मैं एक साधारण फ़ंक्शन बनाना चाहता हूं जो टेक्स्ट को उपयोगकर्ता के कर्सर स्थान पर एक पाठ क्षेत्र में जोड़ता है। इसे एक स्वच्छ कार्य करने की आवश्यकता है। बस मूल बातें हैं। मैं बाकी का पता लगा सकता हूं।



2
पहले से ही पोस्ट किए गए इस उत्तर पर एक नज़र डालें: stackoverflow.com/questions/4456545/…
जॉन कुलविनर



यदि आप पूर्ववत समर्थन के साथ एक सरल मॉड्यूल की तलाश कर रहे हैं, तो सम्मिलित-पाठ-टेक्स्टारिया का प्रयास करें । यदि आपको IE8 + समर्थन की आवश्यकता है, तो सम्मिलित-पाठ-पर-कर्सर पैकेज का प्रयास करें।
फ्रीगर्ल

जवाबों:


115
function insertAtCursor(myField, myValue) {
    //IE support
    if (document.selection) {
        myField.focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    //MOZILLA and others
    else if (myField.selectionStart || myField.selectionStart == '0') {
        var startPos = myField.selectionStart;
        var endPos = myField.selectionEnd;
        myField.value = myField.value.substring(0, startPos)
            + myValue
            + myField.value.substring(endPos, myField.value.length);
    } else {
        myField.value += myValue;
    }
}

19
" } else { myField.selectionStart = startPos + myValue.length; myField.selectionEnd = startPos + myValue.length;
लॉस्ट

10
जवाब के लिए धन्यवाद रब और फिक्स के लिए @ user340140। यहाँ एक काम करने का उदाहरण है
ज़्नर्कस

@ user340140, आपका "खो कैरेट पॉटिशन" ठीक है, केवल तभी काम करता है जब मैं आपके द्वारा सुझाई गई लाइनों से ठीक पहले इनपुट पर ध्यान देता हूं। गैर-केंद्रित क्षेत्र पर चयन को बदलना असंभव प्रतीत होता है, कम से कम क्रोम में (वर्तमान संस्करण 62.0)
Jette

इस कोड के साथ एक छोटी सी समस्या है: selectionStartएक संख्यात्मक मान है, और इस तरह इसकी तुलना की जानी चाहिए 0और नहीं '0', और शायद इसका उपयोग करना चाहिए===
हेरोहार्ट

82

यह स्निपेट jQuery 1.9+: http://jsfiddle.net/4MBUG/2/ की कुछ पंक्तियों में आपकी मदद कर सकता है।

$('input[type=button]').on('click', function() {
    var cursorPos = $('#text').prop('selectionStart');
    var v = $('#text').val();
    var textBefore = v.substring(0,  cursorPos);
    var textAfter  = v.substring(cursorPos, v.length);

    $('#text').val(textBefore + $(this).val() + textAfter);
});

महान! मामूली संशोधनों के साथ 1.6 के साथ भी काम करता है।
रबन घीया

1
लेकिन यह चयनित पाठ की जगह नहीं ले सकता
सर्गेई गोलाइन

@mparkuk: यह अभी भी उपयोगकर्ता के द्वारा वर्णित "लूज़ कैरट पोज़िशन" से ग्रस्त है। (क्षमा करें, मुझे इसे ठीक करना चाहिए, लेकिन मैं समय से बाहर भाग गया।)
jbobbins

4
धन्यवाद एक काम कर रहे बेला प्रदान करते हैं। मैंने इसे कैरट पोजिशन को रीसेट करने के लिए अपडेट किया है और इसे jquery प्लगइन बनाया है: jsfiddle.net/70gqn153
स्वतंत्रता-एम

यह काम करता है लेकिन कर्सर गलत स्थान पर समाप्त होता है।
AndroidDev

36

उचित जावास्क्रिप्ट के लिए

HTMLTextAreaElement.prototype.insertAtCaret = function (text) {
  text = text || '';
  if (document.selection) {
    // IE
    this.focus();
    var sel = document.selection.createRange();
    sel.text = text;
  } else if (this.selectionStart || this.selectionStart === 0) {
    // Others
    var startPos = this.selectionStart;
    var endPos = this.selectionEnd;
    this.value = this.value.substring(0, startPos) +
      text +
      this.value.substring(endPos, this.value.length);
    this.selectionStart = startPos + text.length;
    this.selectionEnd = startPos + text.length;
  } else {
    this.value += text;
  }
};

बहुत अच्छा विस्तार! उम्मीद के मुताबिक काम करता है। धन्यवाद!
मार्टिन जोहानसन

सबसे अच्छा उपाय! धन्यवाद
Dima Melnik

4
यह उन वस्तुओं के प्रोटोटाइप का विस्तार करने के लिए एक अच्छा विचार नहीं है जो आपके पास नहीं हैं। बस इसे एक नियमित कार्य करें और यह बस के रूप में अच्छी तरह से काम करता है।
फ्रीगर्ल

यह सेटिंग के बाद संपादन तत्व के लिए पूर्ववत बफ़र को साफ़ करता है this.value = ...। क्या इसे संरक्षित करने का कोई तरीका है?
c00000fd

18

नया उत्तर:

https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setRangeText

मैं हालांकि इसके लिए ब्राउज़र समर्थन के बारे में निश्चित नहीं हूं।

Chrome 81 में परीक्षण किया गया।

function typeInTextarea(newText, el = document.activeElement) {
  const [start, end] = [el.selectionStart, el.selectionEnd];
  el.setRangeText(newText, start, end, 'select');
}

document.getElementById("input").onkeydown = e => {
  if (e.key === "Enter") typeInTextarea("lol");
}
<input id="input" />
<br/><br/>
<div>Press Enter to insert "lol" at caret.</div>
<div>It'll replace a selection with the given text.</div>

पुराना उत्तर:

एरिक पुक्किंनिस का शुद्ध जेएस संशोधन:

function typeInTextarea(newText, el = document.activeElement) {
  const start = el.selectionStart
  const end = el.selectionEnd
  const text = el.value
  const before = text.substring(0, start)
  const after  = text.substring(end, text.length)
  el.value = (before + newText + after)
  el.selectionStart = el.selectionEnd = start + newText.length
  el.focus()
}

document.getElementById("input").onkeydown = e => {
  if (e.key === "Enter") typeInTextarea("lol");
}
<input id="input" />
<br/><br/>
<div>Press Enter to insert "lol" at caret.</div>

Chrome 47, 81 और फ़ायरफ़ॉक्स 76 में परीक्षण किया गया।

यदि आप एक ही क्षेत्र में (स्वतः पूर्ण या समान प्रभाव के लिए) टाइप करते समय वर्तमान में चयनित पाठ का मान बदलना चाहते हैं, document.activeElementतो पहले पैरामीटर के रूप में पास करें ।

यह ऐसा करने का सबसे सुरुचिपूर्ण तरीका नहीं है, लेकिन यह बहुत सरल है।

उदाहरण usages:

typeInTextarea('hello');
typeInTextarea('haha', document.getElementById('some-id'));

आपने >> के साथ लाइन को बंद नहीं किया; <<
फीनिक्स

4
जावास्क्रिप्ट में @Phoenix सेमीकोलन वैकल्पिक हैं। उनके बिना भी काम करता है। हालाँकि, यदि आप चाहें तो आप अर्धविराम में संपादित कर सकते हैं। कोई बड़ाई नहीं।
जयंत भावल

3
मैंने JSFiddle पर एक डेमो बनाया। यह भी काम करता है Version 54.0.2813.0 canary (64-bit), जो मूल रूप से क्रोम कैनरी 54.0.2813.0 है। अंत में, यदि आप चाहते हैं कि यह आईडी द्वारा टेक्स्ट बॉक्स में डाला जाए, तो फ़ंक्शन के document.getElementById('insertyourIDhere')स्थान पर उपयोग करें el
हयकम

मेरे जवाब का कौन सा हिस्सा "शुद्ध" जेएस नहीं है? क्या मैं वहां कुछ C ++ भूल गया?
एरिक एगर

2
हे @ErikAigner! मेरा बुरा, इस सवाल का एहसास दो एरिक द्वारा जवाब नहीं था। मेरा मतलब था Erik Pukinskis। मैं बेहतर ढंग से प्रतिबिंबित करने के लिए उत्तर को अपडेट करूंगा।
जयंत भावल

15

एक सरल समाधान जो फ़ायरफ़ॉक्स, क्रोम, ओपेरा, सफारी और किनारे पर काम करता है लेकिन शायद पुराने IE ब्राउज़रों पर काम नहीं करेगा।

  var target = document.getElementById("mytextarea_id")

  if (target.setRangeText) {
     //if setRangeText function is supported by current browser
     target.setRangeText(data)
  } else {
    target.focus()
    document.execCommand('insertText', false /*no UI*/, data);
  }
}

setRangeTextफ़ंक्शन आपको दिए गए पाठ के साथ वर्तमान चयन को बदलने की अनुमति देता है या यदि कोई चयन नहीं होता है तो कर्सर स्थिति पर पाठ डालें। यह केवल फ़ायरफ़ॉक्स द्वारा समर्थित है जहाँ तक मुझे पता है।

अन्य ब्राउज़रों के लिए "इंसर्टटेक्स्ट" कमांड है जो केवल वर्तमान में केंद्रित html तत्व को प्रभावित करता है और जैसा व्यवहार करता है setRangeText

इससे आंशिक रूप से प्रेरित लेख


यह लगभग सही तरीका है। आपके द्वारा जोड़ा गया लेख, पैकेज के रूप में एक पूर्ण समाधान प्रदान करता है: सम्मिलित-पाठ-पर-कर्सर । हालाँकि, मैं पसंद execCommandकरता हूँ क्योंकि यह सम्मिलित-पाठ-textarea का समर्थन करता है undoऔर बनाया है । कोई IE समर्थन नहीं बल्कि छोटा है
19 '

1
दुर्भाग्य से, execCommandएमडीएन द्वारा अप्रचलित माना जाता है: developer.mozilla.org/en-US/docs/Web/API/Document/execCommand मुझे पता नहीं क्यों, यह वास्तव में उपयोगी लगता है!
रिचर्ड

1
हां, execCommand का उपयोग अन्य ब्राउज़रों के लिए किया जाता है, फ़ायरफ़ॉक्स के लिए फ़ंक्शन setRangeText का उपयोग इसके बजाय किया जाता है।
रामस्त

रामस्त, वह नहीं जो आपका कोड करता है। यह किसी भी ब्राउज़र को परिभाषित करने वाले (सबसे) को निष्पादित करने के बजाए setRangeText का उपयोग करेगा। आपके द्वारा वर्णित व्यवहार के लिए, आपको पहले document.execCommand पर कॉल करने की आवश्यकता है, फिर रिटर्न वैल्यू जांचें। यदि यह गलत है, तो target.setRangeText का उपयोग करें।
जूल

@Jools अगर setRangeText का समर्थन किया जाता है, तो इसे निष्पादित करने के बजाय इसका उपयोग क्यों नहीं किया जाता है? मुझे पहले निष्पादित करने की आवश्यकता क्यों है?
रामस्त

10

रब का जवाब बहुत अच्छा काम करता है, लेकिन माइक्रोसॉफ्ट एज के लिए नहीं, इसलिए मैंने एज के लिए एक छोटा सा अनुकूलन जोड़ा:

https://jsfiddle.net/et9borp4/

function insertAtCursor(myField, myValue) {
    //IE support
    if (document.selection) {
        myField.focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    // Microsoft Edge
    else if(window.navigator.userAgent.indexOf("Edge") > -1) {
      var startPos = myField.selectionStart; 
      var endPos = myField.selectionEnd; 

      myField.value = myField.value.substring(0, startPos)+ myValue 
             + myField.value.substring(endPos, myField.value.length); 

      var pos = startPos + myValue.length;
      myField.focus();
      myField.setSelectionRange(pos, pos);
    }
    //MOZILLA and others
    else if (myField.selectionStart || myField.selectionStart == '0') {
        var startPos = myField.selectionStart;
        var endPos = myField.selectionEnd;
        myField.value = myField.value.substring(0, startPos)
            + myValue
            + myField.value.substring(endPos, myField.value.length);
    } else {
        myField.value += myValue;
    }
}

9

मुझे सरल जावास्क्रिप्ट पसंद है, और मेरे पास आमतौर पर jQuery है। यहाँ मैं क्या देख रहा हूँ, जो कि मपरुख का है :

function typeInTextarea(el, newText) {
  var start = el.prop("selectionStart")
  var end = el.prop("selectionEnd")
  var text = el.val()
  var before = text.substring(0, start)
  var after  = text.substring(end, text.length)
  el.val(before + newText + after)
  el[0].selectionStart = el[0].selectionEnd = start + newText.length
  el.focus()
}

$("button").on("click", function() {
  typeInTextarea($("textarea"), "some text")
  return false
})

यहाँ एक डेमो है: http://codepen.io/erikpukinskis/pen/EjaaMY?editors=101


6

function insertAtCaret(text) {
  const textarea = document.querySelector('textarea')
  textarea.setRangeText(
    text,
    textarea.selectionStart,
    textarea.selectionEnd,
    'end'
  )
}

setInterval(() => insertAtCaret('Hello'), 3000)
<textarea cols="60">Stack Overflow Stack Exchange Starbucks Coffee</textarea>

4

यदि पाठ सम्मिलित किए जाने के बाद उपयोगकर्ता इनपुट को स्पर्श नहीं करता है, तो 'इनपुट' ईवेंट को कभी ट्रिगर नहीं किया जाता है, और मान विशेषता परिवर्तन को प्रतिबिंबित नहीं करेगा। इसलिए प्रोग्राम को पाठ सम्मिलित करने के बाद इनपुट इवेंट को ट्रिगर करना महत्वपूर्ण है। मैदान पर ध्यान केंद्रित करना पर्याप्त नहीं है।

निम्नलिखित में एक इनपुट ट्रिगर के साथ स्नोरवर्ग के उत्तर की एक प्रति है :

function insertAtCursor(myField, myValue) {
    //IE support
    if (document.selection) {
        myField.focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    // Microsoft Edge
    else if(window.navigator.userAgent.indexOf("Edge") > -1) {
      var startPos = myField.selectionStart; 
      var endPos = myField.selectionEnd; 

      myField.value = myField.value.substring(0, startPos)+ myValue 
             + myField.value.substring(endPos, myField.value.length); 

      var pos = startPos + myValue.length;
      myField.focus();
      myField.setSelectionRange(pos, pos);
    }
    //MOZILLA and others
    else if (myField.selectionStart || myField.selectionStart == '0') {
        var startPos = myField.selectionStart;
        var endPos = myField.selectionEnd;
        myField.value = myField.value.substring(0, startPos)
            + myValue
            + myField.value.substring(endPos, myField.value.length);
    } else {
        myField.value += myValue;
    }
    triggerEvent(myField,'input');
}

function triggerEvent(el, type){
  if ('createEvent' in document) {
    // modern browsers, IE9+
    var e = document.createEvent('HTMLEvents');
    e.initEvent(type, false, true);
    el.dispatchEvent(e);
  } else {
    // IE 8
    var e = document.createEventObject();
    e.eventType = type;
    el.fireEvent('on'+e.eventType, e);
  }
}

ट्रिगर फ़ंक्शन के लिए plainjs.com को क्रेडिट

पर घटना oninput के बारे में अधिक w3schools.com

मुझे चैट के लिए इमोजी-पिकर बनाते समय यह पता चला। यदि उपयोगकर्ता केवल कुछ इमोजी का चयन करता है और "भेजें" बटन को हिट करता है, तो इनपुट फ़ील्ड को उपयोगकर्ता द्वारा कभी नहीं छुआ जाता है। मूल्य विशेषता की जांच करते समय यह हमेशा खाली था, भले ही इनपुट फ़ील्ड में सम्मिलित इमोजी यूनिकोड दिखाई दे रहे थे। यह बताता है कि यदि उपयोगकर्ता फ़ील्ड को स्पर्श नहीं करता है, तो 'इनपुट' ईवेंट कभी फ़ॉर नहीं होता है और समाधान को इस तरह ट्रिगर करना होता है। यह पता लगाने में काफी समय लग गया ... उम्मीद है कि यह किसी को कुछ समय बचाएगा।


0

स्वयं के संदर्भ के लिए संशोधित फ़ंक्शन पोस्ट करना। यह उदाहरण <select>ऑब्जेक्ट से चयनित आइटम सम्मिलित करता है और टैग के बीच कैरेट डालता है:

//Inserts a choicebox selected element into target by id
function insertTag(choicebox,id) {
    var ta=document.getElementById(id)
    ta.focus()
    var ss=ta.selectionStart
    var se=ta.selectionEnd
    ta.value=ta.value.substring(0,ss)+'<'+choicebox.value+'>'+'</'+choicebox.value+'>'+ta.value.substring(se,ta.value.length)
    ta.setSelectionRange(ss+choicebox.value.length+2,ss+choicebox.value.length+2)
}

0
 /**
 * Usage "foo baz".insertInside(4, 0, "bar ") ==> "foo bar baz"
 */
String.prototype.insertInside = function(start, delCount, newSubStr) {
    return this.slice(0, start) + newSubStr + this.slice(start + Math.abs(delCount));
};


 $('textarea').bind("keydown keypress", function (event) {
   var val = $(this).val();
   var indexOf = $(this).prop('selectionStart');
   if(event.which === 13) {
       val = val.insertInside(indexOf, 0,  "<br>\n");
       $(this).val(val);
       $(this).focus();
    }
})

हालांकि यह प्रश्न का उत्तर दे सकता है, उत्तर के आवश्यक भागों की व्याख्या करना बेहतर है और संभवतः ओपी कोड के साथ समस्या क्या थी।
पिरहो

0

नीचे दिया गया कोड दिमित्री कुबिसकिन द्वारा पैकेज https://github.com/grassator/insert-text-at-cursor का टाइपस्क्रिप्ट रूपांतरण है ।


/**
 * Inserts the given text at the cursor. If the element contains a selection, the selection
 * will be replaced by the text.
 */
export function insertText(input: HTMLTextAreaElement | HTMLInputElement, text: string) {
  // Most of the used APIs only work with the field selected
  input.focus();

  // IE 8-10
  if ((document as any).selection) {
    const ieRange = (document as any).selection.createRange();
    ieRange.text = text;

    // Move cursor after the inserted text
    ieRange.collapse(false /* to the end */);
    ieRange.select();

    return;
  }

  // Webkit + Edge
  const isSuccess = document.execCommand("insertText", false, text);
  if (!isSuccess) {
    const start = input.selectionStart;
    const end = input.selectionEnd;
    // Firefox (non-standard method)
    if (typeof (input as any).setRangeText === "function") {
      (input as any).setRangeText(text);
    } else {
      if (canManipulateViaTextNodes(input)) {
        const textNode = document.createTextNode(text);
        let node = input.firstChild;

        // If textarea is empty, just insert the text
        if (!node) {
          input.appendChild(textNode);
        } else {
          // Otherwise we need to find a nodes for start and end
          let offset = 0;
          let startNode = null;
          let endNode = null;

          // To make a change we just need a Range, not a Selection
          const range = document.createRange();

          while (node && (startNode === null || endNode === null)) {
            const nodeLength = node.nodeValue.length;

            // if start of the selection falls into current node
            if (start >= offset && start <= offset + nodeLength) {
              range.setStart((startNode = node), start - offset);
            }

            // if end of the selection falls into current node
            if (end >= offset && end <= offset + nodeLength) {
              range.setEnd((endNode = node), end - offset);
            }

            offset += nodeLength;
            node = node.nextSibling;
          }

          // If there is some text selected, remove it as we should replace it
          if (start !== end) {
            range.deleteContents();
          }

          // Finally insert a new node. The browser will automatically
          // split start and end nodes into two if necessary
          range.insertNode(textNode);
        }
      } else {
        // For the text input the only way is to replace the whole value :(
        const value = input.value;
        input.value = value.slice(0, start) + text + value.slice(end);
      }
    }

    // Correct the cursor position to be at the end of the insertion
    input.setSelectionRange(start + text.length, start + text.length);

    // Notify any possible listeners of the change
    const e = document.createEvent("UIEvent");
    e.initEvent("input", true, false);
    input.dispatchEvent(e);
  }
}

function canManipulateViaTextNodes(input: HTMLTextAreaElement | HTMLInputElement) {
  if (input.nodeName !== "TEXTAREA") {
    return false;
  }
  let browserSupportsTextareaTextNodes;
  if (typeof browserSupportsTextareaTextNodes === "undefined") {
    const textarea = document.createElement("textarea");
    textarea.value = "1";
    browserSupportsTextareaTextNodes = !!textarea.firstChild;
  }
  return browserSupportsTextareaTextNodes;
}

-1

इसे getElementById (myField) में बदल दिया

 function insertAtCursor(myField, myValue) {
    //IE support
    if (document.selection) {
        document.getElementById(myField).focus();
        sel = document.selection.createRange();
        sel.text = myValue;
    }
    //MOZILLA and others
    else if (document.getElementById(myField).selectionStart || document.getElementById(myField).selectionStart == '0') {
        var startPos = document.getElementById(myField).selectionStart;
        var endPos = document.getElementById(myField).selectionEnd;
        document.getElementById(myField).value = document.getElementById(myField).value.substring(0, startPos)
            + myValue
            + document.getElementById(myField).value.substring(endPos, document.getElementById(myField).value.length);
    } else {
        document.getElementById(myField).value += myValue;
    }
}

3
आप की जरूरत से ज्यादा डोम रास्ता हिट करने के लिए जा रहा है .. myfieldएक स्थानीय के रूप में भंडारण प्रदर्शन के लिए बहुत बेहतर है
टीएमएएन

2
वाह, वास्तव में बहुत ज्यादा दोहराव का रास्ता document.getElementById(myField)! शीर्ष पर एक बार करें और एक चर नाम का उपयोग करें। एक पंक्ति में कितनी बार आप एक ही तत्व को अनावश्यक रूप से देखने का इरादा रखते हैं?
dgg65536
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.