বর্তমান কার্সার অবস্থানে পাঠ্যকে পাঠ্য কীভাবে প্রবেশ করবেন?


124

আমি একটি সাধারণ ফাংশন তৈরি করতে চাই যা ব্যবহারকারীর কার্সারের অবস্থানে একটি পাঠ্য অঞ্চলে পাঠ্য যুক্ত করে। এটি একটি পরিষ্কার ফাংশন হওয়া প্রয়োজন। শুধু বেসিক। বাকিটা আমি বুঝতে পারি



2
এই উত্তরটি কটাক্ষপাত ইতিমধ্যে পোস্ট নিন: stackoverflow.com/questions/4456545/...
জন Culviner



যদি আপনি পূর্বাবস্থায় সমর্থন সহ একটি সাধারণ মডিউল খুঁজছেন, সারণি-পাঠ্য-পাঠ্য চেষ্টা করুন । আপনার যদি আই 8 + সমর্থন প্রয়োজন হয় তবে সন্নিবেশ-পাঠ্য-এ-কার্সার প্যাকেজটি চেষ্টা করুন।
fregante

উত্তর:


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
উত্তরের জন্য রব এবং @ ব্যবহারকারী340140 সমাধানের জন্য ধন্যবাদ। এখানে একটি কাজের উদাহরণ
Znarkus

@ ব্যবহারকারী340140, আপনার "ক্যারেট পোটিশন হারা" ফিক্সটি কেবলমাত্র তখনই কাজ করে যদি আমি আপনার প্রস্তাবিত লাইনের ঠিক আগে ইনপুটটিতে ফোকাস দিই। কমপক্ষে ক্রোমে (বর্তমান সংস্করণ .0২.০) অ - কেন্দ্রীভূত ক্ষেত্রে নির্বাচন পরিবর্তন করা অসম্ভব বলে মনে হচ্ছে
জেটে

এই কোডটিতে একটি ছোটখাটো সমস্যা রয়েছে: 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
তবে এটি নির্বাচিত পাঠ্যটি প্রতিস্থাপন করতে পারে না
সের্গেই গোলিনে

@ এমপার্কুক: এটি এখনও ব্যবহারকারী340140 দ্বারা উল্লিখিত "হারানো কেরেটের অবস্থান" ইস্যুতে ভুগছে। (দুঃখিত, আমার এটি ঠিক করা উচিত, তবে আমার সময় শেষ হয়ে গেল।)
জবববিন্স

4
আপনাকে একটি কাজের ভারসাম্য সরবরাহ করার জন্য ধন্যবাদ। আমি কেরেটের
স্বাধীনতা-এম

এটি কাজ করে তবে কার্সারটি ভুল জায়গায় শেষ হয়।
অ্যান্ড্রয়েডদেভ

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;
  }
};

খুব সুন্দর এক্সটেনশন! প্রত্যাশার মতোই কাজ করে। ধন্যবাদ!
মার্টিন জোহানসন

সব থেকে ভালো সমাধান! আপনাকে ধন্যবাদ
দিমা মেল্নিক

4
নিজের মালিকানাযুক্ত জিনিসগুলির প্রোটোটাইপ বাড়ানো ভাল ধারণা নয়। এটি কেবল একটি নিয়মিত ফাংশন করুন এবং এটি ঠিক পাশাপাশি কাজ করে।
ফ্রেংতে

এটি সেটিংসের পরে সম্পাদনা উপাদানটির পূর্বাবস্থায় ফিরে আসা সাফ করে this.value = ...। এটি সংরক্ষণ করার কোনও উপায় আছে?
c00000fd

18

নতুন উত্তর:

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

যদিও আমি এটির জন্য ব্রাউজার সমর্থন সম্পর্কে নিশ্চিত নই।

ক্রোম ৮১-এ পরীক্ষিত।

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>

ক্রোম 47, 81 এবং ফায়ারফক্স 76 এ পরীক্ষিত।

আপনি যদি একই ক্ষেত্রটিতে টাইপ করার সময় আপনি বর্তমানে নির্বাচিত পাঠ্যের মান পরিবর্তন করতে চান (স্বতঃপূরণ বা অনুরূপ প্রভাবের জন্য), পাস করুন document.activeElement প্রথম প্যারামিটার হিসাবে ।

এটি করার জন্য এটি সবচেয়ে মার্জিত উপায় নয়, তবে এটি বেশ সহজ।

ব্যবহারের উদাহরণ:

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

আপনি >> এর সাথে লাইনটি বন্ধ করেননি; <<
ফিনিক্স

4
জাভা স্ক্রিপ্টে @ ফিনিক্স সেমিকোলনগুলি alচ্ছিক। তাদের ছাড়াও কাজ করে। যদিও আপনি চাইলে আপনি সেমিকোলনে সম্পাদনা করতে পারেন। কোনও বিগি নেই।
জয়ন্ত ভাওয়াল

3
আমি জেএসফিডেলে একটি ডেমো তৈরি করেছি। এটি ব্যবহার করেও কাজ করে Version 54.0.2813.0 canary (64-bit)যা মূলত ক্রোম ক্যানারি 54.0.2813.0। অবশেষে, আপনি যদি এটি আইডি দিয়ে পাঠ্য বাক্সে প্রবেশ করতে চান তবে ফাংশনটির document.getElementById('insertyourIDhere')জায়গায় ব্যবহার করুন el
হাইকমাম

আমার উত্তরের কোন অংশটি "খাঁটি" জেএস নয়? আমি কি কিছু সি ++ ভুলে গেছি?
এরিক অাইগনার

2
আরে @ এরিকআগনার! আমার খারাপ, এই প্রশ্নের দুটি এরিকের উত্তর পেয়েও বুঝতে পারিনি। আমি বলতে চাইছি 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ফাংশন আপনাকে প্রদত্ত পাঠ্যের সাথে বর্তমান নির্বাচন প্রতিস্থাপন করতে অনুমতি দেয় বা কোনও নির্বাচন না করে পাঠ্যটি কার্সার অবস্থানে সন্নিবেশ করায়। আমি যতদূর জানি এটি কেবল ফায়ারফক্স দ্বারা সমর্থিত।

অন্যান্য ব্রাউজারগুলির জন্য "ইনসার্টটেক্সট" কমান্ড রয়েছে যা কেবলমাত্র বর্তমানে নিবদ্ধ এইচটিএমএল উপাদানকেই প্রভাবিত করে এবং এর মতো আচরণ করে setRangeText

এই নিবন্ধ দ্বারা আংশিক অনুপ্রাণিত


এটি প্রায় সঠিক উপায়। আপনি যে নিবন্ধটি লিঙ্ক করেছেন, এটি প্যাকেজ হিসাবে একটি সম্পূর্ণ সমাধান সরবরাহ করে: সন্নিবেশ-পাঠ্য-এ-কার্সার । তবে আমি পছন্দ করি execCommandকারণ এটি সন্নিবেশ-পাঠ্য-পাঠ্যundo তৈরি করে । কোনও আইই সমর্থন নয়, ছোট
ফ্রেগান্ট

1
দুর্ভাগ্যক্রমে, execCommandMDN দ্বারা অপ্রচলিত হিসাবে বিবেচিত: developer.mozilla.org/en-US/docs/Web/API/Docament/execCommand কেন জানি না, এটি সত্যিই দরকারী বলে মনে হচ্ছে!
রিচার্ড

1
হ্যাঁ, এক্সিকিউন্ড কম্যান্ড অন্য ব্রাউজারগুলির জন্য ব্যবহৃত হয়, ফায়ারফক্সের জন্য ফাংশন সেট রেঞ্জ টেক্সট পরিবর্তে ব্যবহৃত হয়।
রামাষ্ট

রামস্ট, আপনার কোড এটি করে না। এটি যে কোনও ব্রাউজার (এটি সর্বাধিক) সংজ্ঞায়িত করে তার জন্য এক্সিকিউন্ড কমন্ডের চেয়ে সেটরেঞ্জটেক্সট ব্যবহার করবে। আপনি যে আচরণটি বর্ণনা করেছেন তার জন্য আপনাকে প্রথমে ডকুমেন্ট.এক্সেকমন্ডল কল করতে হবে, তারপরে ফেরতের মানটি পরীক্ষা করতে হবে। যদি এটি মিথ্যা হয় তবে টার্গেট.সেটর্যাংটেক্সট ব্যবহার করুন।
Jools

@ জুলস যদি সেটরেঞ্জটেক্সট সমর্থিত হয় তবে এক্সিকিউন্ডের পরিবর্তে কেন এটি ব্যবহার করবেন না? আমাকে প্রথমে এক্সিকিউমন্ড চেষ্টা করার দরকার কেন?
রামাষ্ট

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 triggerEvent ফাংশন জন্য

এ ইভেন্টটির 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();
    }
})

যদিও এটি প্রশ্নের উত্তর দিতে পারে, উত্তরের প্রয়োজনীয় অংশগুলি এবং সম্ভবত ওপিএস কোডটিতে কী সমস্যা ছিল তা ব্যাখ্যা করা ভাল।
pirho

0

নীচের কোডটি দিমিত্রি কুবিশকিনের প্যাকেজ https://github.com/grassator/insert-text-at-cursor এর একটি টাইপস্ক্রিপ্ট অভিযোজন is


/**
 * 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

এটি এলেমেন্টবিআইআইডি (মাইফিল্ড) এ পরিবর্তন করা হয়েছে

 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)! এটি একবারে শীর্ষে করুন এবং একটি পরিবর্তনশীল নাম ব্যবহার করুন। আপনি একপর্যায়ে কতবার একই উপাদানটিকে পুনরুদ্ধার করে অনুসন্ধান করার মনস্থ করেন?
doug65536
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.