如何在使用 jQuery 按下按钮时在文本区域中向上、向下、向左、向右移动光标?

How to move cursor up, down, left, right in textarea on button press using jQuery?

如何使用 jQuery 使按钮在文本区域中向上、向下、向左或向右移动光标?

$(document).ready(function() {
  var clpBrd;
  $("textarea")[0].focus(); /*To show to cursor at the end of text*/
  
  $("#cpBtn").click(function(){
    clpBrd = $("txtOutput").text();
    console.log("COPIED: "+clpBrd);
  });
  
  $("#ltBtn").click(function(){
    var txtVal = $("textarea").val();
    var txtLen = txtVal.length;
    $("textarea")[0].focus(txtLen - 1);
  });
  
  $("#rtBtn").click(function(){
    var txtVal = $("textarea").val();
    var txtLen = txtVal.length;
    $("textarea")[0].focus(txtLen + 1);
  });
  
  $("#upBtn").click(function(){
    var txtVal = $("textarea").val();
    var txtLen = txtVal.length;
    $("textarea")[0].focus( /*??*/ );
  });
  
  $("#dnBtn").click(function(){
    var txtVal = $("textarea").val();
    var txtLen = txtVal.length;
    $("textarea")[0].focus(/*??*/);
  });
  
  var selPressed = false;
  $("#selBtn").click(function(){
    selPressed = !selPressed;
  });
  
});
* {
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh
}

textarea,
#btnWrap button {
  display: flex;
  flex-grow: 1;
}

textarea::selection{
    color:white; background: black
}

#btnWrap {
  height: 50px;
  display: flex;
  flex-direction: row;
}

#btnWrap button {
  align-items: center;
  justify-content: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea id="txtOutput">
  Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book.</textarea>
<div id="btnWrap">
  <button id="slBtn">Select</button>
  <button id="upBtn">▲</button>
  <button id="ltBtn">◀</button>
  <button id="rtBtn">▶</button>
  <button id="dnBtn">▼</button>
  <button id="ctBtn">Cut</button>
  <button id="psBtn">Paste</button>
  <button id="cpBtn">Copy</button>
</div>

另外,我们如何使用 up/down 按钮 select 文本?

如果 selPressed 为真,则移动光标将 select 文本。否则它只是移动光标。

Cut/Copy/Paste 我觉得使用数组会比较困难。

我是否必须使用像 clipboard.js 这样的外部库,或者没有它也能做到这一点?

你需要像我在函数getInputSelection()

中所做的那样先获取你当前的光标位置

我研究了一点有关在文本区域内移动光标位置的问题,感谢 css tricks,我找到了一种将其移动到文本区域末尾的方法。我根据您的需要调整了此功能。奇迹发生在 moveCursor = function(pos)。您可以将所需的光标位置传递给 fct。左右都工作得很好。 向上和向下是棘手的,因为每行中的字符数量会随着行的不同而变化。

我决定输入 100 个字符的静态值。光标向上或向下移动,但位置不是 100% 准确。

我很确定通过一些研究,您可以找到一种计算每行字符数并优化此功能的方法。

$(document).ready(function() {
  var clpBrd;
  $("textarea")[0].focus(); /*To show to cursor at the end of text*/
  
  $("#cpBtn").click(function(){
    clpBrd = $("txtOutput").text();
    console.log("COPIED: "+clpBrd);
  });
  
  $("#ltBtn").click(function(){
     var sel = getInputSelection($("textarea"));
     $("textarea").moveCursor(sel-1);
  });
  
  $("#rtBtn").click(function(){
     var sel = getInputSelection($("textarea"));
     $("textarea").moveCursor(sel+1);
  });
  
  $("#upBtn").click(function(){
     var sel = getInputSelection($("textarea"));
     $("textarea").moveCursor(sel-100);
  });
  
  $("#dnBtn").click(function(){
     var sel = getInputSelection($("textarea"));
     $("textarea").moveCursor(sel+100);
  });
  
  var selPressed = false;
  $("#selBtn").click(function(){
    selPressed = !selPressed;
  });

  
});

jQuery.fn.moveCursor = function(pos) {

  return this.each(function() {
    
    // Cache references
    var $el = $(this),
        el = this;

    // Only focus if input isn't already
    if (!$el.is(":focus")) {
     $el.focus();
    }

    // If this function exists... (IE 9+)
    if (el.setSelectionRange) {

      // Timeout seems to be required for Blink
      setTimeout(function() {
        el.setSelectionRange(pos, pos);
      }, 1);
    
    } else {
      
      // As a fallback, replace the contents with itself
      // Doesn't work in Chrome, but Chrome supports setSelectionRange
      $el.val(pos);
      
    }

    // Scroll to the bottom, in case we're in a tall textarea
    // (Necessary for Firefox and Chrome)
    this.scrollTop = 999999;

  });

};

function getInputSelection(elem){
 if(typeof elem != "undefined"){
  var s=elem[0].selectionStart;
  return s;
 }else{
  return '';
 }
}
* {
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh
}

textarea,
#btnWrap button {
  display: flex;
  flex-grow: 1;
}

textarea::selection{
    color:white; background: black
}

#btnWrap {
  height: 50px;
  display: flex;
  flex-direction: row;
}

#btnWrap button {
  align-items: center;
  justify-content: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea id="txtOutput">
  Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book.</textarea>
<div id="btnWrap">
  <button id="slBtn">Select</button>
  <button id="upBtn">▲</button>
  <button id="ltBtn">◀</button>
  <button id="rtBtn">▶</button>
  <button id="dnBtn">▼</button>
  <button id="ctBtn">Cut</button>
  <button id="psBtn">Paste</button>
  <button id="cpBtn">Copy</button>
</div>

请参考我的代码,用于现场演示https://codepen.io/libin-prasanth/pen/dyyjJbG

window.onload = function() {
  var selPressed = false;
  var length = 0;
  var sStart = 0;
  var target = document.getElementById('txtOutput');
  var clipBoard = '';
  // Select click event  
  document.getElementById('selBtn').addEventListener('click', function(e) {
    length = target.selectionStart;
    sStart = target.selectionStart;
    target.focus();
    selPressed = true;
  });

  // right button
  document.getElementById('rtBtn').addEventListener('click', function(e) {
    var textLength = target.value.length;
    if (!selPressed) return;
    length++;
    length = (length <= textLength) ? length : textLength;
    target.focus();
    target.setSelectionRange(sStart, length);
  });
  // left button 
  document.getElementById('ltBtn').addEventListener('click', function(e) {
    var textLength = target.value.length;
    if (!selPressed) return;
    length--;
    length = (length >= 0) ? length : 0;
    target.focus();
    target.setSelectionRange(sStart, length);
  });

  // down button 
  document.getElementById('dnBtn').addEventListener('click', function(e) {
    var textLength = target.value.length;
    if (!selPressed) return;
    target.focus();
    length = length + getCharacterPerLine(target);
    length = (length > textLength) ? textLength : length;
    target.setSelectionRange(sStart, length);
  });

  // up button
  document.getElementById('upBtn').addEventListener('click', function(e) {
    if (!selPressed) return;
    target.focus();
    length = length - getCharacterPerLine(target);
    length = (length <= 0) ? 0 : length;
    target.setSelectionRange(sStart, length);
  });

  // copy event 
  document.getElementById('cpBtn').addEventListener('click', function(e) {
    var text = target.value
    if (!selPressed) return;
    target.focus();
    target.setSelectionRange(sStart, length);
    document.execCommand("copy");
    clipBoard = target.value.substr(sStart, length);
    length = 0;
    sStart = 0;
  });

  // copy cut 
  document.getElementById('ctBtn').addEventListener('click', function(e) {
    var text = target.value
    if (!selPressed) return;
    target.focus();
    target.setSelectionRange(sStart, length);
    clipBoard = target.value.substr(sStart, length);
    document.execCommand("cut");
    length = 0;
    sStart = 0;
  });
  // paste cut 
  document.getElementById('psBtn').addEventListener('click', function(e) {
    if (!selPressed) return;
    insertAtCursor(target, clipBoard);
    length = 0;
    sStart = 0;
  });

  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;
    }
    myField.focus();
  }

  function getCharacterPerLine(target) {
    var w = target.clientWidth;
    var fSize = window.getComputedStyle(target, null).getPropertyValue('font-size');
    fSize = parseFloat(fSize);
    return (w / fSize) * 2;
  }

}
* {
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100vh;
}

textarea,
#btnWrap button {
  display: flex;
  flex-grow: 1;
}

textarea::selection {
  color: white;
  background: black;
}

#btnWrap {
  height: 50px;
  display: flex;
  flex-direction: row;
}

#btnWrap button {
  align-items: center;
  justify-content: center;
}
<textarea id="txtOutput">
Lorem ipsum, or lipsum as it is sometimes known, is dummy text used in laying out print, graphic or web designs. The passage is attributed to an unknown typesetter in the 15th century who is thought to have scrambled parts of Cicero's De Finibus Bonorum et Malorum for use in a type specimen book.</textarea>
<div id="btnWrap">
  <button id="selBtn">Select</button>
  <button id="upBtn">▲</button>
  <button id="ltBtn">◀</button>
  <button id="rtBtn">▶</button>
  <button id="dnBtn">▼</button>
  <button id="ctBtn">Cut</button>
  <button id="psBtn">Paste</button>
  <button id="cpBtn">Copy</button>
</div>