【问题标题】:How to keep highlighted text if another element has focus?如果另一个元素有焦点,如何保持突出显示的文本?
【发布时间】:2019-08-05 15:01:51
【问题描述】:

需要插入链接(替换高亮文本)

想法是 - 选择 lorem - 在输入中键入 href - 然后按 Enter - 设置链接。

问题 - 如果 inpa 具有焦点,则突出显示的文本不会突出显示。

有什么办法吗?

$('#inpa').on('keypress', function(e){
	if(e.keyCode == 13){
        let a = $('#inpa').val();
        let b = window.getSelection().toString();
        let ht = "<a href = '" + a + "' target = '_blank'>" + b + "</a>";
        document.execCommand('insertHTML', ht);
	}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class='story' id='story'>lorem ipsum</div>
<br>
<input type='text' class='inpa' id='inpa'>

【问题讨论】:

  • 不确定如何同时关注两件事...您最好记住选择而不是重新创建选择。
  • @epascarello,类似的功能存在于 SO,当创建一个内部有链接的帖子时
  • 是的,在元素获得焦点之前,您存储选择。完成后,您重新创建选择并运行您的代码。范围广泛的库使操作变得容易。
  • @qadenza 您引用的功能似乎是基于iframe,因为它是一个完全不同的选择上下文。我认为仅使用 JavaScript 是不可能的。一种选择可能是在blur 之后设置选择样式,然后在focus 上重新选择。如果这是您的选择,我可以尝试为此写一个答案。
  • @andrewgu,请尝试一下,听起来合乎逻辑,但问题可能是如果选择不在父级的末尾或顶部,而是在内部的某个地方

标签: javascript jquery


【解决方案1】:

如果您希望系统为您执行此操作,您所描述的内容是不可能的。但是,您可以使用很少的 JavaScript 轻松实现此目的。当用户选择文本时,使用JS 抓取它并使用CSS 突出显示它。我会将文本包装在spandiv 或其他东西中,并给它一个独特的ID,以便您以后可以访问它。您可以了解如何获取文本here。因此,当用户专注于输入时,文本看起来仍然突出显示,一旦用户设置链接,您可以以任何您喜欢的方式再次更新文本。

【讨论】:

    【解决方案2】:

    这是我在 cmets 中谈到的关于记住范围并重新创建范围的基本思想。

    // took this function getSelectionHtml from https://stackoverflow.com/questions/4652734/return-html-from-a-user-selected-text
    function getSelectionHtml() {
      var html = "";
      if (typeof window.getSelection != "undefined") {
        var sel = window.getSelection();
        if (sel.rangeCount) {
          var container = document.createElement("div");
          for (var i = 0, len = sel.rangeCount; i < len; ++i) {
            container.appendChild(sel.getRangeAt(i).cloneContents());
          }
          html = container.innerHTML;
        }
      } else if (typeof document.selection != "undefined") {
        if (document.selection.type == "Text") {
          html = document.selection.createRange().htmlText;
        }
      }
      return html;
    }
    
    
    // this gets the selection, and holds on to it. It returns a function if it has a range that will recreate the selection
    const selectionSaveRestore = () => {
      let range
      let sel
      if (window.getSelection) {
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
          range = sel.getRangeAt(0);
        }
      } else if (document.selection && document.selection.createRange) {
        range = document.selection.createRange();
      }
      if (range) {
        return () => {
          if (window.getSelection) {
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
          } else if (document.selection && range.select) {
            range.select();
          }
        }
      }
      return null;
    }
    
    let recreateRange
    const tb = document.querySelector("#test");
    tb.addEventListener("focus", () => {
      recreateRange = selectionSaveRestore()
    })
    
    tb.addEventListener("keypress", evt => {
      if (evt.which === 13 && recreateRange) {
        recreateRange()
        const a = evt.target.value;
        const b = getSelectionHtml()
        const ht = "<a href='" + a + "' target='_blank'>" + b + "</a>"
        document.execCommand('insertHTML', false, ht);
      }
    })
    <div id="foo" contenteditable="true">
      Bacon ipsum dolor amet leberkas spare ribs swine, tenderloin t-bone pork chop corned beef flank filet mignon rump beef sausage turducken. Pork chop kielbasa ground round, t-bone pork belly turducken brisket ribeye strip steak frankfurter pork loin pastrami
      filet mignon prosciutto bacon. Venison pork kielbasa, doner short ribs ball tip tri-tip porchetta boudin chuck salami shoulder shank shankle pastrami. Pig sirloin strip steak, frankfurter chicken beef ribs ribeye salami t-bone. Pork belly doner short
      loin ribeye burgdoggen ground round pork kielbasa frankfurter. Capicola spare ribs biltong kielbasa rump pork chop cow prosciutto shankle burgdoggen. Turkey shankle pancetta pig.
    </div>
    
    <input type="text" id="test" />

    【讨论】:

    • 非常感谢您的努力,如果这是唯一的方法(似乎如此),我很惊讶没有简单的方法来完成如此微不足道的任务。
    【解决方案3】:

    要达到预期效果,请使用以下选项

    1. 将选定文本分配给变量
    2. 用选定的文本形成标签
    3. 用第 2 步中的标签替换所选文本

    var text;
    
    $('#story').on('click', function(){
       text = ""
        if (window.getSelection) {
            text = window.getSelection().toString();
        } else if (document.selection && document.selection.type != "Control") {
            text = document.selection.createRange().text;
        }   
    });
    
    
        $('#inpa').on('keypress', function(e){
          console.log(text)
    	if(e.keyCode == 13){
            let a = $('#inpa').val();
            let ht = "<a href = '" + a + "' target = '_blank'>" + text + "</a>";
            let divText = $('#story').text();
            divText = divText.replace(text, ht);
        console.log(ht, text)
            $('#story').html(divText)
            
    	}
    });   
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class='story' id='story'>lorem ipsum</div>
    <br>
    <input type='text' class='inpa' id='inpa'>

    codepen - https://codepen.io/nagasai/pen/MxQXgJ

    【讨论】:

      猜你喜欢
      • 2017-04-18
      • 2013-03-14
      • 1970-01-01
      • 2016-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多