满意的文本选择不起作用 [英] contenteditable selection of text not working

查看:57
本文介绍了满意的文本选择不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我面临以下问题:当我尝试在 contenteditable 元素中选择文本并且选择的结尾是元素内容的开头时,则没有选择事件被解雇,没有选择范围对象。



有人可以告诉我为什么会出现这种情况或者我如何防止这种情况?



负责获取选择范围的代码:



  $('div [contenteditable =true]')。bind(mouseup keyup touchend, function(){lastCaretIndex = getSelectionRange();}); function getSelectionRange(){var sel; if(window.getSelection){sel = window.getSelection();的console.log(SEL); //这不会打印任何事件空字符串if(sel.rangeCount){return sel.getRangeAt(0); } else if(document.selection){return document.createRange(); } return null;}  

 < div id =main -inputcontenteditable =true> Hello world!< / div>< script type =text / javascriptsrc =https://code.jquery.com/jquery-2.2.4.min.js >< / script>  



解决方案

问题在于您只在 contenteditable 元素上发生特定事件时记录选择更改。更具体地说,你有

  $('div [contenteditable =true]')。bind(mouseup keyup touchend ,// ... 

特别是 mouseup 事件通常会在选择更改时触发。除非它没有。当你在可编辑的 div 之外释放鼠标时(你在你的例子中做了! ),然后 div 永远不会收到 mouseup 事件,因此永远不会记录选择。



有两种解决方法:


  1. 监听整个上的事件正文。缺点是您收到的更多事件不会影响选择,并且仍然可以在页面外获得 mouseup 事件。

  2. 收听 selectionchange event。

  document.addEventListener('selectionchange',function(event){console.log(event.type);});  

 < div contenteditable =true> Hello world!< / div>  



您当然可以像现在一样进行选择此事件处理程序。每次选择更改时都会触发此事件,因此您可能需要 throttle 它。



完全实现可以在下面找到。



  function handler(){//在这里做你想做的任何事情//这显示了选择,它包含了var sel = window.getSelection()的所有范围,ranges = Array(sel.rangeCount).fill(0).map((_,i)=> sel.getRangeAt(i)); ranges = ranges.map((r)=>`$ {r.startOffset}  -  $ {r.endOffset}`)。join(';'); console.log(`Selection [$ {ranges}:$ {sel.toString()}]`);} function throttle(func){var timeoutId = false,called = false,wrap = function(){if( !叫){clearInterval(timeoutId); timeoutId = false; } else {func(); } called = false; }; return function(){if(timeoutId === false){func(); timeoutId = setInterval(wrap,500); } else {called = true; document.addEventListener('selectionchange',throttle(handler));  

 < div contenteditable =true> Hello world!< / div>  


I am faced with following: when I try to select text in a contenteditable element and the end of the selection is the start of the element content, then no select event is fired and there are no Selection and Range objects.

Could somebody please give me any advice on why this might occur or how I can prevent this?

Code responsible for getting selection range:

$('div[contenteditable="true"]').bind("mouseup keyup touchend", function() {
  lastCaretIndex = getSelectionRange();
});

function getSelectionRange() {
  var sel;
  if (window.getSelection) {
    sel = window.getSelection();

    console.log(sel); // this doesn't print anything event empty string

    if (sel.rangeCount) {
      return sel.getRangeAt(0);
    }
  } else if (document.selection) {
    return document.createRange();
  }

  return null;
}

<div id="main-input" contenteditable="true">Hello world!</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.4.min.js"></script>

JSFiddle (open your browser console to make sure that selection doesn't get logged).

解决方案

The issue is that you only log selection changes when specific events occur on the contenteditable element. More specifically, you have

$('div[contenteditable="true"]').bind("mouseup keyup touchend", // ...

In particular the mouseup event will normally be triggered when the selection changes. Except when it doesn't. When you release the mouse outside of the editable div (which you do in your example!), then the div will never receive a mouseup event and thus never log the selection.

There are two ways around this:

  1. Listen for events on the entire body. Downsides are that you receive more events that do not influence the selection and that it is still possible to get mouseup events outside of the page.
  2. Listen for the selectionchange event.

document.addEventListener('selectionchange', function(event) {
  console.log(event.type);
});

<div contenteditable="true">Hello world!</div>

You can of course still access the selection as you currently do inside this event handler. This event is triggered every time the selection changes, so you may want to throttle it.

Full implementation of that can be found below.

function handler() {
  // do whatever you want here
  // this shows the selection and all ranges it consists of
  var sel = window.getSelection(),
      ranges = Array(sel.rangeCount).fill(0).map((_, i) => sel.getRangeAt(i));
  ranges = ranges.map((r) => `${r.startOffset}-${r.endOffset}`).join(';');
  console.log(`Selection [${ranges}:"${sel.toString()}"]`);
}

function throttle(func) {
  var timeoutId = false,
      called = false,
      wrap = function() {
        if (!called) {
          clearInterval(timeoutId);
          timeoutId = false;
        } else {
          func();
        }
        called = false;
      };
  return function() {
    if (timeoutId === false) {
      func();
      timeoutId = setInterval(wrap, 500);
    } else {
      called = true;
    }
  };
}

document.addEventListener('selectionchange', throttle(handler));

<div contenteditable="true">Hello world!</div>

这篇关于满意的文本选择不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆