Skip to content
quarry Artifact [eb4139fb7b]
Login

Artifact [eb4139fb7b]

Artifact eb4139fb7b54b3b075ef7c77726f69d09990034488a9beb0fdb72c19422faa73:


// chat.js — the channel's own enhancements. First-party, dependency-free.
// Datastar carries the signals and the stream; this carries the two
// things that need a real statement or two of script.
//
// 1. Following a reference to a message ALREADY ON THE PAGE scrolls to
//    it and flashes it — no reload, nothing below it disappears, the
//    conversation stays exactly where it was. A reference to a message
//    not on the page falls through to the link, which opens the channel
//    in a window around it.
// 2. Nothing else yet. Keep it that way until something earns a place.
(function () {
  "use strict";
  var log = document.getElementById("chatlog");
  if (!log) return;
  var repo = document.body.dataset.refRepo || "";
  var here = "/r/" + encodeURIComponent(repo) + "/chat/";

  function seqOf(a) {
    // Only this channel's own permalinks: a cross-repository reference
    // has another repo in its path and must navigate.
    var href = a.getAttribute("href") || "";
    if (href.indexOf(here) !== 0) return 0;
    var rest = href.slice(here.length).split(/[?#]/)[0];
    return /^\d+$/.test(rest) ? Number(rest) : 0;
  }

  document.addEventListener("click", function (ev) {
    var a = ev.target.closest && ev.target.closest("a[href]");
    if (!a) return;
    var seq = seqOf(a);
    if (!seq) return;
    var row = log.querySelector('.chatmsg[data-seq="' + seq + '"]');
    if (!row) return; // not on this page: let the link do its job
    ev.preventDefault();
    row.scrollIntoView({ block: "center", behavior: "smooth" });
    // Restart the flash even if the same row is hit twice.
    row.classList.remove("chat-found");
    void row.offsetWidth;
    row.classList.add("chat-found");
    row.addEventListener("animationend", function () {
      row.classList.remove("chat-found");
    }, { once: true });
  });
})();