javascript - 如何使用 Ctrl+Z 事件将文本替换为星号?

标签 javascript jquery css

我有一个场景,我需要用文本区域中的星号替换文本。替换文本后,默认事件 (Ctrl+Z) 不起作用。

JavaScript:

$(document).ready(function () {
    closePopUp();
    var newpost = $('#newpost');
    $('#mytextarea').on('select', function (e) {
        var txtarea = document.getElementById("mytextarea");
        var start = txtarea.selectionStart;
        var finish = txtarea.selectionEnd;
        newpost.offset(getCursorXY(txtarea, start, 20)).show();
        newpost.find('div').text('replace with stars');
    });
});

const getCursorXY = (input, selectionPoint, offset) => {
    const {
        offsetLeft: inputX,
        offsetTop: inputY,
        } = input
    // create a dummy element that will be a clone of our input
    const div = document.createElement('div')
    // get the computed style of the input and clone it onto the dummy element
    const copyStyle = getComputedStyle(input)
    for (const prop of copyStyle) {
        div.style[prop] = copyStyle[prop]
    }
    // we need a character that will replace whitespace when filling our dummy element 
    // if it's a single line <input/>
    const swap = '.'
    const inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value
    // set the div content to that of the textarea up until selection
    const textContent = inputValue.substr(0, selectionPoint)
    // set the text content of the dummy element div
    div.textContent = textContent
    if (input.tagName === 'TEXTAREA') div.style.height = 'auto'
    // if a single line input then the div needs to be single line and not break out like a text area
    if (input.tagName === 'INPUT') div.style.width = 'auto'
    // create a marker element to obtain caret position
    const span = document.createElement('span')
    // give the span the textContent of remaining content so that the recreated dummy element 
    // is as close as possible
    span.textContent = inputValue.substr(selectionPoint) || '.'
    // append the span marker to the div
    div.appendChild(span)
    // append the dummy element to the body
    document.body.appendChild(div)
    // get the marker position, this is the caret position top and left relative to the input
    const { offsetLeft: spanX,offsetTop: spanY } = span
    // lastly, remove that dummy element
    // NOTE:: can comment this out for debugging purposes if you want to see where that span is rendered
    document.body.removeChild(div)
    // return an object with the x and y of the caret. account for input positioning 
    // so that you don't need to wrap the input
    return {
        left: inputX + spanX,
        top: inputY + spanY + offset,
    }
}

这是我的 Plunker

我需要在执行“Ctrl+Z”时获取之前的文本。

提前致谢。

最佳答案

试试这个。它将保存最后一次替换并在 Ctrl+Z 上撤消它。

但是,如果要保存多个替换,则需要更复杂的逻辑。

var selection = {};

function undo(e) {
      var evtobj = window.event? window.event : e;
      if (evtobj.keyCode == 90 && evtobj.ctrlKey && selection.text) {
          evtobj.preventDefault();
          var txtarea = document.getElementById("mytextarea");
          var allText = txtarea.value;
          var newText = allText.substring(0, selection.start) + selection.text + allText.substring(selection.finish, allText.length);
          txtarea.value = newText;
      }
}

function getSel() {
    // obtain the object reference for the textarea>
    var txtarea = document.getElementById("mytextarea");
    // obtain the index of the first selected character
    var start = txtarea.selectionStart;
    // obtain the index of the last selected character
    var finish = txtarea.selectionEnd;
    //obtain all Text
    var allText = txtarea.value;
    
    selection.text = allText.substring(start, finish);
    selection.start = start;
    selection.finish = finish;

    // obtain the selected text
    var sel = Array(finish - start + 1).join("*");
    //append te text;
    var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
    txtarea.value = newText;
    
    $('#newpost').offset({top: 0, left: 0}).hide();
}
function closePopUp() {
    $('#newpost').offset({top: 0, left: 0}).hide();
}

$(document).ready(function () {
    closePopUp();
    var newpost = $('#newpost');
    $('#mytextarea').on('select', function (e) {
        var txtarea = document.getElementById("mytextarea");
        var start = txtarea.selectionStart;
        var finish = txtarea.selectionEnd;
        newpost.offset(getCursorXY(txtarea, start, 20)).show();
        newpost.find('div').text(Array(finish - start + 1).join("*"));
    }).on('input', () => selection.text = null);
    document.onkeydown = undo;
});

const getCursorXY = (input, selectionPoint, offset) => {
  const {
    offsetLeft: inputX,
    offsetTop: inputY,
  } = input
  // create a dummy element that will be a clone of our input
  const div = document.createElement('div')
  // get the computed style of the input and clone it onto the dummy element
  const copyStyle = getComputedStyle(input)
  for (const prop of copyStyle) {
    div.style[prop] = copyStyle[prop]
  }
  // we need a character that will replace whitespace when filling our dummy element 
  // if it's a single line <input/>
  const swap = '.'
  const inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value
  // set the div content to that of the textarea up until selection
  const textContent = inputValue.substr(0, selectionPoint)
  // set the text content of the dummy element div
  div.textContent = textContent
  if (input.tagName === 'TEXTAREA') div.style.height = 'auto'
  // if a single line input then the div needs to be single line and not break out like a text area
  if (input.tagName === 'INPUT') div.style.width = 'auto'
  // create a marker element to obtain caret position
  const span = document.createElement('span')
  // give the span the textContent of remaining content so that the recreated dummy element 
  // is as close as possible
  span.textContent = inputValue.substr(selectionPoint) || '.'
  // append the span marker to the div
  div.appendChild(span)
  // append the dummy element to the body
  document.body.appendChild(div)
  // get the marker position, this is the caret position top and left relative to the input
  const { offsetLeft: spanX, offsetTop: spanY } = span
  // lastly, remove that dummy element
  // NOTE:: can comment this out for debugging purposes if you want to see where that span is rendered
  document.body.removeChild(div)
  // return an object with the x and y of the caret. account for input positioning 
  // so that you don't need to wrap the input
  return {
    left: inputX + spanX,
    top: inputY + spanY + offset,
  }
}
#mytextarea {width: 600px; height: 200px; overflow:hidden; position:fixed}
#newpost {
    position:absolute;
    background-color:#ffffdc;
    border:1px solid #DCDCDC;
    border-radius:10px;
    padding-right:5px; 
    width: auto;
    height: 30px;
}
#newpost span {
    cursor:pointer;
    position: absolute;
    top: 0;
    right: 5px;
    font-size: 22px;
}
#newpost div {
    color:#0000ff;
    padding:10px;
    margin-right:10px;
    width: auto;
    cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
  <head>
  </head>
 <body>
    <textArea id="mytextarea"></textArea>
    <div id="newpost">
        <span onclick="closePopUp();">&#735;</span>
        <div onclick="getSel()"></div>
    </div>
</body>

</html>

关于javascript - 如何使用 Ctrl+Z 事件将文本替换为星号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48499220/

相关文章:

javascript - 响应式工具提示 Css

javascript - EmberJS + Handlebars : Re-Use rendered views

javascript - 如何在VueJs中上传不同字段的多张图片?

javascript - 在特定图层上设置事件监听器(谷歌​​ map )

javascript - 如何在用户输入关键字时触发onclick函数? jQuery

css - 带省略号和换行的多行截断

php - 需要一些解决办法。 jquery 中的点击事件中未调用 Javascript 函数

javascript - JQuery 行破坏了我的页面

html - 垂直对齐 Div 与绝对位置

javascript - 当鼠标悬停在 iframe 上时隐藏自定义光标