Как переместить курсор вверх, вниз, влево, вправо в текстовой области при нажатии кнопки с помощью jQuery? - PullRequest
1 голос
/ 11 ноября 2019

Как сделать кнопки для перемещения курсора вверх, вниз, влево или вправо в текстовой области с помощью 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>

Также, как мы можем выделить текст с помощью кнопок вверх / вниз?

Если selPressed истинно, тогда перемещение курсоравыберет текст. В противном случае он просто перемещает курсор.

Вырезать / Копировать / Вставить с использованием массива будет сложно, я думаю.

Придется ли мне использовать внешнюю библиотеку, например clipboard.js, или это можно сделать без нее?

Ответы [ 2 ]

1 голос
/ 11 ноября 2019

Пожалуйста, ознакомьтесь с моим кодом, для демонстрации в реальном времени 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>
1 голос
/ 11 ноября 2019

Сначала вам нужно получить текущую позицию курсора, как я делал в функции getInputSelection()

Я немного исследовал перемещение позиции курсора внутри текстовой области, благодаря трюкам css Я нашел способ переместить его в конец текстовой области. Я адаптировал эту функцию для ваших нужд. Магия случается в moveCursor = function(pos). Вы можете передать желаемое положение курсора к функции. Левый и правый работают совершенно нормально. Вверх и вниз сложно, потому что количество символов в каждой строке меняется от строки к строке.

Я решил установить статическое значение 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>
...