Tooltip browser default tidak ditampilkan karena debounce RxJS

Pada dasarnya apa yang ingin saya capai adalah mendengarkan acara 'mousemove' yang dilampirkan ke dokumen dan setelah saya mengarahkan kursor ke elemen, saya memeriksa apakah teksnya meluap, dan jika ya, saya memotongnya dan menambahkan atribut judul ke elemen target dengan teks lengkap sehingga ketika pengguna mengarahkannya, browser menampilkan tooltip default dengan teks ini.

Logika ini berfungsi dengan baik tetapi memiliki kelemahan besar. Itu mematikan kinerja aplikasi saya karena saya menggunakan getComputedStyle() di dalamnya.

Untuk mengatasi ini saya mencoba menggunakan debounce RxJS dan berfungsi dengan baik. Namun jika pengguna menggerakkan mouse dengan cepat lalu berhenti sehingga hanya ada 1 event untuk elemen tersebut yang dikeluarkan, maka tooltip ditambahkan ke DOM tetapi tidak ditampilkan.

Seperti yang saya pahami apa yang terjadi dari perspektif browser semuanya berfungsi dengan baik karena ketika pengguna mengarahkan elemen belum ada judul dan setelah ditambahkan pengguna tidak lagi menggerakkan mouse sehingga tooltip tidak ditampilkan.

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

Pertanyaannya adalah adakah yang tahu bagaimana cara mengatasi masalah ini?


person Mykola    schedule 23.03.2020    source sumber


Jawaban (1)


Baiklah, saya rasa Anda dapat mencoba memicu peristiwa mousemove pada kode menggunakan metode Element.dispatchEvent(). Saya sudah mencoba melakukan sesuatu sebagai contoh di demo stackblitz (ya, ini bersudut, tapi saya tidak menggunakan fitur sudut andy di luar pemisahan kekhawatiran markup-javascript-css => yang lainnya hanyalah javascript murni). Pada dasarnya apa yang saya lakukan adalah:

<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
    })
  );
}

person julianobrasil    schedule 24.03.2020