Всплывающая подсказка браузера по умолчанию не отображается из-за отказов RxJS

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

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

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

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

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

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

Всего 1 ответ


Ну, я думаю, вы можете попытаться вызвать событие mousemove в коде, используя метод Element.dispatchEvent() . Я попытался сделать что-то в качестве примера в этой демонстрации стекаблиц (да, это угловой, но я не использую энди угловую функцию за пределами разделения интересов markup-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
    })
  );
}


Есть идеи?

10000