Всплывающая подсказка браузера по умолчанию не отображается из-за отказов - PullRequest
0 голосов
/ 23 марта 2020

По сути, я хочу добиться прослушивания события mousemove, прикрепленного к документу, и, когда я наведу указатель мыши на элемент, я проверяю, не переполнен ли он текстом, и, если это так, обрезаю его и добавляю атрибут title к целевому элементу с полным текст, так что когда пользователь наводит на него курсор, браузер отображает всплывающую подсказку по умолчанию с этим текстом.

Этот лог c отлично работает сам по себе, но имеет большой недостаток. Это убивает производительность моего приложения, потому что я использую внутри него getComputedStyle ().

Чтобы решить эту проблему, я попытался использовать Rx JS debounce, и он прекрасно работает. Но если пользователь быстро перемещает мышь, а затем останавливается, так что для этого элемента генерируется только 1 событие, тогда подсказка добавляется в DOM, но не отображается.

Как я понимаю, что происходит с точки зрения браузера, все работает нормально, потому что когда пользователь наведен на элемент, заголовка еще не было, и как только он был добавлен, пользователь больше не перемещал мышь, поэтому всплывающая подсказка не отображается.

fromEvent(document, 'mouseenter')
.pipe(
  debounceTime(20),
  tap(($event: Event) => {
    this.addTooltip($event);
  })
)
.subscribe();

Вопрос в том, знает ли кто-нибудь, как обойти эту проблему

1 Ответ

0 голосов
/ 24 марта 2020

Ну, я думаю, вы можете попытаться вызвать событие mousemove в коде, используя метод Element.dispatchEvent(). Я попытался сделать что-то в качестве примера в этой демонстрации stackblitz (да, это angular, но я не использую функцию andy angular за пределами разметки разделения проблем - javascript - css => все остальное просто javascript). В основном то, что я сделал, было:

<p title="house">
  Start editing to see some magic happen :)
</p>
// track the html elements that currently have a title modified
// this avoids additional unnecessary listeners on a single HTML element
private elementWithListenerAdded = new Set();

...

fromEvent(document, "mousemove")
  .pipe(
    debounceTime(20),
    tap(($event: MouseEvent) => {
      this.addTooltip($event);
    })
  )
  .subscribe();

...

addTooltip(evt: MouseEvent) {
  const $tag = evt.target;

  // I'm assuming that you don't want any tooltip on
  // header, HTML or body tags
  if (
    ($tag as any).tagName === "HEADER" ||
    ($tag as any).tagName === "HTML" ||
    ($tag as any).tagName === "BODY" ||
    this.elementWithListenerAdded.has($tag)
  ) {
    return;
  }

  const elementWithListenerAdded = this.elementWithListenerAdded;

  elementWithListenerAdded.add($tag);

  // remove the event listener when the mouse leave the element
  // and restore the original title
  const originalTitle = ($tag as any).getAttribute("title");
  function removeEventListener() {
    $tag.removeEventListener("mouseleave", this);
    elementWithListenerAdded.delete($tag);
    ($tag as any).setAttribute("title", originalTitle);
  }

  $tag.addEventListener("mouseleave", removeEventListener);

  ($tag as any).setAttribute("title", "just a test");

  ($tag as any).dispatchEvent(
    new MouseEvent("mousemove", {
      bubbles: true,
      cancelable: true,
      view: window
    })
  );
}

...