【问题标题】:How to detect the deselection of a before selected text?如何检测之前选择的文本的取消选择?
【发布时间】:2022-02-04 19:05:47
【问题描述】:

这可能是一个愚蠢的问题,但我在任何地方都没有找到任何有关此的信息...

<input type="text" onselect="javascript: sel1 = true" placeholder="Suche nach etwas" id="browser1">

我有这条线,onselect 的 var sel1 为真。现在这就是问题所在:我不知道如何做相反的事情。我想知道当我取消选择输入时如何将 var sel1 设置为 false。

【问题讨论】:

  • 你试过 onblur="sel1=false" 吗?我希望这会有所帮助。
  • 这能回答你的问题吗? Call a function after leaving input field
  • 只是为了注意...blur 事件类型与select 事件类型并不相反。由于后者在每次选择文本时为text 类型的输入字段和文本区域分派,因此相反的是取消选择此类文本而不是元素本身的散焦(可能在丢失元素时选择了文本焦点)。
  • @Jan ... 这样说。首先处理select 事件的目的是什么?
  • @Jan ...关于提供的答案/解决方案/方法还有什么问题吗?

标签: javascript dom event-handling textselection custom-events


【解决方案1】:

方法如下...

  • WeakMap 实例用作基于文本元素的存储,用于文本元素的最新文本选择状态

  • 启用文本元素取消选择检测 ...

    • ...通过跟踪此类元素的'select'事件选择状态 .. .
    • ... 并关注其他事件,例如'keyup''mouseup''focusout',其中总是需要对照最近的选择状态检查当前选择状态
  • 在验证取消选择的情况下创建并发送custom event。因此,现在可以直接监听和处理与文本元素相关的'deselect' 事件

// gather all text control related selection data and put it
// into an object based (here the element reference) storage.
function putTextSelectionState(textControl) {
  const { value, selectionStart, selectionEnd } = textControl;

  const isSelected = (selectionEnd - selectionStart >= 1);
  const selection = value.substring(selectionStart, selectionEnd);

  textSelectionStorage.set(textControl, {
    isSelected,
    selection,
    selectionStart,
    selectionEnd,
    value,
  });
}
// the object based storage.
const textSelectionStorage = new WeakMap;

// detect whether custom 'deselect' event handling has to take place.
function handleDeselectText(evt) {
  const textControl = evt.currentTarget;
  const { selectionStart, selectionEnd } = textControl;

  // console.log({ type: evt.type, selectionStart, selectionEnd });

  const recentState = { ...textSelectionStorage.get(textControl) };
  putTextSelectionState(textControl);
  const currentState = { ...textSelectionStorage.get(textControl) };

  if (
    (selectionEnd - selectionStart === 0)
    && recentState.isSelected
  ) {
    // console.log('deselect');

    // a custom event will be created and dispatched in case ...
    // - there is nothing currently selected ... and ...
    // - there was a recent slection right before.
    textControl
      .dispatchEvent(
        new CustomEvent('deselect', {
          detail: {
            recentState,
            currentState,
          },
        })
      );
  }  
}
// update text control related selection data.
function handleSelectText({ currentTarget }) {
  putTextSelectionState(currentTarget);
}

// enable text related, custom 'deselect' event handling.
function initializeHandleDeselectText(textControl) {
  const nodeName = textControl.nodeName.toLowerCase();
  const textType = ((nodeName === 'textarea') && 'text')
    || ((nodeName === 'input') && textControl.type)
    || null;

  if (
    (textType === 'text') ||
    (textType === 'search') // ... or some more ...
  ) {
    putTextSelectionState(textControl);

    textControl.addEventListener('select', handleSelectText);

    textControl.addEventListener('input', handleDeselectText);
    textControl.addEventListener('keyup', handleDeselectText);
    textControl.addEventListener('mouseup', handleDeselectText);
    textControl.addEventListener('focusout', handleDeselectText); 
  }
}


// custom 'deselect' event handling.
function logTextDeselection(evt) {
  const { type, detail, currentTarget } = evt;

  console.log({ type, detail, currentTarget });
}
// native 'select' event handling.
function logTextSelection(evt) {
  const textControl = evt.currentTarget;

  const { value, selectionStart, selectionEnd } = textControl;
  const selection = value.substring(selectionStart, selectionEnd);

  console.log({ type: evt.type, selection });
}

function main() {
  const textControl = document.querySelector('#browser1');

  // enable text related, custom 'deselect' event handling.
  initializeHandleDeselectText(textControl);

  // native 'select' event handling.
  textControl.addEventListener('select', logTextSelection);

  // custom 'deselect' event handling.
  textControl.addEventListener('deselect', logTextDeselection);

  // default selected initial value.
  textControl.focus();
  textControl.value = 'The quick brown fox jumps over the lazy dog.';

  textControl.selectionStart = 12;
  textControl.selectionEnd = 19;

  // handle display of all available text selection states.
  document
    .querySelector('button')
    .addEventListener('click', () => console.log([
      ...document
      .querySelectorAll('textarea, input[type="text"], input[type="search"]')
    ].map(elmNode => ({
      elmNode,
      isSelected: textSelectionStorage.get(elmNode).isSelected
    }))));
}
main();
body { margin: 0; }
button { width: 27%; }
[type="search"] { width: 72%; }
.as-console-wrapper { min-height: 85%; }
<input id="browser1" type="search" placeholder="Search something ..."/>
<button>show select states</button>

【讨论】:

    【解决方案2】:

    我建议创建一个函数来清除您绑定到输入的每个变量。在每个输入的单击事件处理程序中,您可以调用此函数来清除之前可能已设置的任何变量。调用函数后,设置该元素对应的变量。

    类似的东西

    function clearFlags() {
    sel1 = false, sel2 = false, sel3 = false; // etc
    }
    

    然后你的内联事件处理程序可能是

    <input type="text" onselect="javascript: clearFlags(); sel1 = true" placeholder="Suche nach etwas" id="browser1">
    

    【讨论】:

      【解决方案3】:

      您可以使用onblur。如果您退出输入,则会调用此方法。输入时使用onfocus 而不是onselect(这是用于输入字段中的文本选择)。

      let sel1, last = 0;
         
      setInterval(() => {
          if (sel1 === last) return;
          console.log(sel1);
          last = sel1;
      }, 200);
      &lt;input type="text" onfocus="javascript: sel1 = true" onblur="javascript: sel1 = false" placeholder="Suche nach etwas" id="browser1"&gt;

      【讨论】:

      • select 的反面是 deselect 并且不会失去焦点。 OP 处理文本输入的文本选择事件。因此处理blur 很可能不是正确的解决方案。
      • @PeterSeliger deselect 不是 available
      • 我知道,这就是为什么必须通过处理许多其他事件来检测它,甚至可能创建自定义/人工 文本相关 deselect 事件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-25
      • 1970-01-01
      • 2017-07-16
      • 2012-12-27
      • 1970-01-01
      相关资源
      最近更新 更多