【问题标题】:Check if any text inside of ul is selected检查是否选择了 ul 内的任何文本
【发布时间】:2016-09-02 14:49:17
【问题描述】:

我正在编写一个日志消息框/与聊天相同的功能,一旦有人在聊天中选择文本(例如,如果用户想要粘贴某些内容),我想将我的 AutoScrollDown 布尔值设置为 false。

我用 ul 和 lis 实现了我的日志消息/聊天框,如下所示:

<ul id="1" class="logbox">
   <li class="debug"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.learn how to make a website. We offer free tutorials in all web development technologies.</li>
   <li class="error"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
   <li class="warning"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
   <li>blabla</li>
</ul>

我尝试了以下事件来检查是否选择了我的 ul 中的内容,但没有成功:

  $("#1").on("focus", function() {
    autoScrollEnabled = 0;
  });

  $("#1").off("focus", function() {
    autoScrollEnabled = 1;
  });

我的问题: 一旦有人在我的 ul 中选择/突出显示文本,我如何将 autoScrollEnabled 设置为 0,以及如何检查用户是否已停止选择/突出显示任何文本。

【问题讨论】:

  • @Omeed 不,我以前读过那个堆栈。
  • 我不确定你是否这样做了。它指出不可能有明确的“onHightlightEvent”。我相信答案解释了如何通过 mouseup 实现这一目标。这怎么不能回答你的问题?
  • 请理解我的用例,一个聊天/日志框,每秒/毫秒可能会有新消息+自动向下滚动,一旦选择了某些内容,我需要停止自动向下滚动,否则它会快速向下滚动,无法正确选择文本。我试图用 500 毫秒的新文本间隔来演示这个问题:streamable.com/67ay。如果会有更大的消息(比如 10 行左右,这会使粘贴非常不舒服)
  • 也许你需要更广泛的东西,比如当你的聊天框中有任何鼠标活动时?无论如何,对不起,祝你好运。

标签: javascript jquery html


【解决方案1】:

要检测用户是否在日志框中突出显示文本,您应该首先侦听mousedown 事件,然后在鼠标仍然按下时查看是否有任何mousemove 事件。您可以在鼠标按下或鼠标移动时将标志设置为 false,然后在 mouseup 事件中将其重置。

document.querySelector('#one').addEventListener('mousedown', function (event) {

  window.onmousemove = function (event) {
    console.log('the user is selecting text');
  }
  
  window.onmouseup = function (event) {
    console.log('the user mousedup');
    console.log(window.getSelection());
    autoScrollEnabled = 1;
    window.onmousemove = null;
    window.onmouseup = null;
  }
  
  console.log('user mouseddown in ' + event.target.nodeName);
  autoScrollEnabled = 0;
}, false);
<ul id="one" class="logbox">
   <li class="debug"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.learn how to make a website. We offer free tutorials in all web development technologies.</li>
   <li class="error"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
   <li class="warning"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
   <li>blabla</li>
</ul>

【讨论】:

    【解决方案2】:

    这段代码展示了:

    A.它可以检测带有或不带有表单输入的文本选择。

    B.将在 mouseup 事件上触发,并充分处理误报,例如点击了文本但没有突出显示。

    1. 委托整个文档侦听mouseup 事件。

    2. 接下来定义布尔状态:

      一个。条件1(必须为真):存在选择对象

      * 只要任何文本为event.target(即单击、鼠标向上、放屁等),选择就为真

      b.条件 2(不需要折叠):选择不只是单击文本(即没有突出显示)

      * 通过使用属性.isCollapsed,我们知道如果选择的起点与选择的终点相同,则.isCollapsed为真,因此不会突出显示文本。

    3. 由于从未解释过自动滚动,因此我将其简化为警报。

      一个。如果 autoScroll 被禁用,警报还将包含选定的文本。

    片段

    /*
    This Snippet demonstrates that:
       A. It can detect the selection of text with or without form inputs.
       B. Will trigger on mouseup event and adequately handle false positives like text clicked but nothing highlighted.
    */
    
    // Reference a selection object
    var selection = window.getSelection();
    
    /*
    1. Delegate the whole document to listen for a mouseup event.
    
    2. Next define the boolean state with:
    
      a. Condition 1 (needs to be true): That a selection object exists
      
         * selection is true as soon as any text is the event.target (i.e. clicked, mouseup, farted on, etc.)
      b. Condition 2 (needs to be not collapsed): That the selection is not just a single click on text (i.e. nothing highlighted)
      
         * By using the property .isCollapsed we know that if the starting point of a selection is the same as the ending point of a selection, then .isCollapsed is true and therefore no text was highlighted.
         
    3. Since autoscroll was never explained, I have simplified it as an alert.
    
       a. If autoScroll is disabled, the alert will also contain the text that's selected. 
    */
    
    $(document).on('mouseup', function(e) {
      var state = (selection && !selection.isCollapsed) ? alert('autoScroll is disabled {{' + selection + '}} is selected') : alert('autoScroll is still enabled');
      return state;
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <ul id="list1" class="logbox">
      <li class="debug"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.learn how to make a website. We offer free tutorials in all web development technologies.</li>
      <li class="error"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
      <li class="warning"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
      <li>blabla</li>
    </ul>

    参考文献

    【讨论】:

    • 请阅读 cmets(包括视频 sn-p)为什么这根本不能解决我的问题。
    • 查看我的 cmets 以回复您的解释。如果滚动太快,请改用mousedown。你的视频解释的不多。我所知道的是,如果一个事件被捕获,那么你的回调应该立即响应。你可以通过setTimeout(function(){..},0 来实现
    【解决方案3】:

    li 元素没有focus 事件,但可以欺骗。参见下面的 sn-p。

    var autoScrollOn = 1; //declare globally
    var timeoutHandle = 0; //for additional service
    $('#ul1').on('click', 'li', function() { //delegate click event
      clearTimeout(timeoutHandle); //clear timeout if any
      if ($(this).hasClass('selected')) { 
        //remove selection on the second click
        $('#ul1 li').removeClass('selected');
        autoScrollOn = 0;
      } else {
        //remove selection from siblings
        $('#ul1 li').removeClass('selected');
        //and add to the clicked element
        $(this).addClass('selected');
        autoScrollOn = 1;
        //restore autoscroll after 10s
        timeoutHandle = setTimeout(function() {
          $('#ul1 li').removeClass('selected');
          autoScrollOn = 0;
          console.log(autoScrollOn);
        }, 10000);
      }
      //do whatever you want with autoscroll
      console.log(autoScrollOn);
    });
    .debug {
      background: #aaf;
    }
    .error {
      background: #faa;
    }
    .warning {
      background: #ffa;
    }
    .selected {
      border: solid 1px #f00;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <ul id="ul1" class="logbox">
      <li class="debug"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.learn how to make a website. We offer free tutorials in all web development technologies.</li>
      <li class="error"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
      <li class="warning"><b>At</b> w3schools.com you will learn how to make a website. We offer free tutorials in all web development technologies.</li>
      <li>blabla</li>
    </ul>

    【讨论】:

    • 这根本不能解决我的问题(请检查包括流媒体在内的 cmets)。此外,您的 sn-p 无法按我的预期工作(例如,它是关于选择文本,而新文本一直在出现)。 console.log 仅在真正点击后发生(尝试选择文本)
    【解决方案4】:
    <script type="text/javascript">
        var mouseIsDown         = false,
            autoScrollEnabled   = 1;
            userSelection       = '';
    
        $.fn.doIt = function () {
            if (!window.getSelection().isCollapsed) {
                var range1 = window.getSelection().getRangeAt(0),
                    range2 = range1.cloneRange();
    
                range2.selectNodeContents(this[0]);
                range2.setStart(range1.startContainer, range1.startOffset);
                range2.setEnd(range1.endContainer, range1.endOffset);
                userSelection = range2.toString();
                console.log(userSelection);
    
                if (userSelection != '')
                    autoScrollEnabled = 0;
                else
                    autoScrollEnabled = 1;
            } else
                  autoScrollEnabled = 1;
        };
    
        $('.logbox').mousedown(function(event) {
            $(this).parent().delegate('ul.logbox', 'mousemove', function(event) {
                if (!mouseIsDown) return;
                $(this).doIt();
            });
            mouseIsDown = true;
        }).dblclick(function(event) {
            $(this).doIt();
        });
    
        $(window).mouseup(function(event) {
            mouseIsDown = false;
            $('.logbox').parent().undelegate('ul.logbox', 'mousemove');
        })
    </script>
    

    【讨论】:

      【解决方案5】:

      您需要将一些表单字段合并到您的日志消息应用程序中,这样您就可以使用 jQuery 方法,例如 on focus 和 on blur 并进行事件驱动编程。它们通常不适用于像 li 这样的原始文本。

      【讨论】:

      • 你能用一个代码例子来解释一下吗?那我应该用什么来代替 ul/li 呢?当我想到表单字段时,我想到的只有输入元素。
      猜你喜欢
      • 2013-03-17
      • 2013-12-29
      • 2012-02-22
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      相关资源
      最近更新 更多