// meld.js — draws what a conflicting landing's three panes cannot draw
// for themselves: the bands joining each marked block in ours or theirs
// to its place in the result, the overview strip down the right edge,
// and stepping from one conflict to the next. The panes are complete
// without it; the server already marked every block (meld.go).
(function () {
"use strict";
var colour = { cf: "var(--meld-cf)", chg: "var(--meld-chg)", ins: "var(--meld-ins)" };
function kindOf(el) {
if (el.classList.contains("cf")) { return "cf"; }
if (el.classList.contains("chg")) { return "chg"; }
if (el.classList.contains("ins")) { return "ins"; }
return "";
}
function mount(m) {
var file = m.closest(".meld-file");
var pane = function (p) { return m.querySelector('[data-pane="' + p + '"]'); };
var seg = function (p, id) { return pane(p).querySelector('.seg[data-id="' + id + '"]'); };
var conflicts = Array.prototype.slice.call(pane("M").querySelectorAll(".seg.cf"));
var cur = -1;
function bands() {
["L", "R"].forEach(function (side) {
var g = m.querySelector('[data-gut="' + side + '"]'), svg = g.querySelector("svg");
if (getComputedStyle(g).display === "none") { svg.innerHTML = ""; return; }
var gr = g.getBoundingClientRect(), w = gr.width, h = w / 2, out = "";
pane(side).querySelectorAll(".seg.cf, .seg.chg, .seg.ins").forEach(function (a) {
var mid = seg("M", a.dataset.id);
if (!mid) { return; }
var ar = a.getBoundingClientRect(), mr = mid.getBoundingClientRect();
var x0 = side === "L" ? 0 : w, x1 = side === "L" ? w : 0;
var ya = ar.top - gr.top, yb = Math.max(ar.bottom - gr.top, ya + 1);
var ma = mr.top - gr.top, mb = Math.max(mr.bottom - gr.top, ma + 1);
var c = colour[kindOf(a)];
out += '<path d="M' + x0 + "," + ya + " C" + h + "," + ya + " " + h + "," + ma + " " + x1 + "," + ma +
" L" + x1 + "," + mb + " C" + h + "," + mb + " " + h + "," + yb + " " + x0 + "," + yb +
' Z" fill="' + c + '" fill-opacity=".28" stroke="' + c + '" stroke-opacity=".7"/>';
});
svg.innerHTML = out;
});
overview();
}
// The strip maps the whole result: each marked block at its place,
// the current conflict outlined; a mark jumps there.
function overview() {
var o = m.querySelector(".ovr");
if (!o || getComputedStyle(o).display === "none") { return; }
o.innerHTML = "";
var inner = pane("M").querySelector(".inner"), ir = inner.getBoundingClientRect();
var head = pane("M").querySelector(".phead").getBoundingClientRect().height;
var span = o.getBoundingClientRect().height - head;
if (ir.height <= 0 || span <= 0) { return; }
pane("M").querySelectorAll(".seg.cf, .seg.chg, .seg.ins").forEach(function (s) {
var r = s.getBoundingClientRect(), i = document.createElement("i");
i.style.top = (head + (r.top - ir.top) / ir.height * span) + "px";
i.style.height = Math.max(3, r.height / ir.height * span) + "px";
i.style.background = colour[kindOf(s)];
if (conflicts[cur] === s) { i.className = "cur"; }
i.title = kindOf(s) === "cf" ? "conflict" : "change";
i.addEventListener("click", function () {
var k = conflicts.indexOf(s);
if (k >= 0) { go(k); } else { s.scrollIntoView({ block: "center", behavior: "smooth" }); }
});
o.appendChild(i);
});
}
function go(k) {
if (!conflicts.length) { return; }
cur = (k + conflicts.length) % conflicts.length;
conflicts.forEach(function (c, i) { c.classList.toggle("cur", i === cur); });
var pos = file.querySelector("[data-meld-pos]");
if (pos) { pos.textContent = "conflict " + (cur + 1) + " of " + conflicts.length; }
conflicts[cur].scrollIntoView({ block: "center", behavior: "smooth" });
overview();
}
file.querySelectorAll("[data-meld-step]").forEach(function (b) {
b.addEventListener("click", function () { go(cur < 0 ? (b.dataset.meldStep > 0 ? 0 : -1) : cur + Number(b.dataset.meldStep)); });
});
// A long line scrolls its own pane sideways; the conflict label
// stays as wide as the pane it sits in.
function fit() {
var w = pane("M").clientWidth;
pane("M").querySelectorAll(".tagline").forEach(function (t) { t.style.width = w + "px"; });
bands();
}
["L", "M", "R"].forEach(function (p) { pane(p).addEventListener("scroll", bands, { passive: true }); });
window.addEventListener("resize", fit);
if (document.fonts && document.fonts.ready) { document.fonts.ready.then(fit); }
fit();
}
document.querySelectorAll("[data-meld]").forEach(mount);
})();