From mboxrd@z Thu Jan 1 00:00:00 1970 From: andy at warmcat.com (Andy Green) Date: Fri, 29 Jun 2018 09:40:24 +0800 Subject: [PATCH v6 2/7] cgit.js: line range highlight: introduce javascript In-Reply-To: <153023597876.27756.7476186508120329174.stgit@mail.warmcat.com> References: <153023597876.27756.7476186508120329174.stgit@mail.warmcat.com> Message-ID: <153023642446.27756.9543379934857131113.stgit@mail.warmcat.com> This adds a small css class, and a clientside js function plus event registrations in cgit.js, to interpret the # part of the URL on the client, and apply a highlight to filtered source. Unlike blame highlight boxes which use generated divs, this applies a computed absolutely-positioned, transparent div highlight over the affected line(s) on the client side. The # part of the URL is defined to not be passed to the server, so the highlight can't be rendered on the server side. However this has the advantage that the line range highlight can operate on /blame/ urls trivially, since it doesn't conflict with blame's generated div scheme. pointer-events: none is used on the highlight overlay div to allow the user to cut-and-paste in the highlit region and click on links underneath normally. The JS supports highlighting single lines as before like #n123 and also ranges of lines like #n123-135. Because the browser can no longer automatically scroll to the element in the second case, the JS also takes care of extracting the range start element and scrolling to it dynamically. Tested on Linux Firefox 60 + Linux Chrome 67 Signed-off-by: Andy Green --- cgit.css | 9 ++++++ cgit.js | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/cgit.css b/cgit.css index 1f581ec..45ba615 100644 --- a/cgit.css +++ b/cgit.css @@ -336,6 +336,7 @@ div#cgit table.ssdiff td.lineno a { color: gray; text-align: right; text-decoration: none; + transition: background-color 1.5s; } div#cgit table.blob td.linenumbers a:hover, @@ -376,6 +377,14 @@ div#cgit table.blame td.lines > div > pre { top: 0; } +div#cgit div.selected-lines { + position: absolute; + pointer-events: none; + z-index: 1; + background-color: rgba(255, 255, 0, 0); + transition: background-color 1.5s; +} + div#cgit table.bin-blob { margin-top: 0.5em; border: solid 1px black; diff --git a/cgit.js b/cgit.js index e69de29..7c034e3 100644 --- a/cgit.js +++ b/cgit.js @@ -0,0 +1,92 @@ +/* cgit.css: javacript functions for cgit + * + * Copyright (C) 2006-2018 cgit Development Team + * + * Licensed under GNU General Public License v2 + * (see COPYING for full license text) + */ + +(function () { + +function collect_offsetTop(e1) +{ + var t = 0; + + while (e1) { + if (e1.offsetTop) + t += e1.offsetTop; + e1 = e1.offsetParent; + } + + return t; +} + +function find_parent_of_type(e, type) +{ + while (e.tagName.toLowerCase() != type) + e = e.parentNode; + + return e; +} + +function line_range_highlight() +{ + var h = window.location.hash, l1 = 0, l2 = 0, e, t; + + l1 = parseInt(h.substring(2)); + if (!l1) + return; + + t = h.indexOf("-"); + l2 = l1; + if (t >= 1) + l2 = parseInt(h.substring(t + 1)); + + if (l2 < l1) + l2 = l1; + + var lh, etable, etr, de, n; + + e = document.getElementById('n' + l1); + if (!e) + return; + + de = document.createElement("DIV"); + + de.className = "selected-lines"; + de.style.bottom = e.style.bottom; + de.style.top = collect_offsetTop(e) + 'px'; + de.l1 = l1; + de.l2 = l2; + + /* we will tack the highlight div at the parent tr */ + etr = find_parent_of_type(e, "tr"); + + de.style.width = etr.offsetWidth + 'px'; + + /* the table is offset from the left, the highlight + * needs to follow it */ + etable = find_parent_of_type(etr, "table"); + + de.style.left = etable.offsetLeft + 'px'; + de.style.height = ((l2 - l1 + 1) * e.offsetHeight) + 'px'; + + etr.insertBefore(de, etr.firstChild); + + setTimeout(function() { + de.style.backgroundColor = "rgba(255, 255, 0, 0.2)"; + }, 1); + + n = l1; + while (n <= l2) + document.getElementById('n' + n++).style.backgroundColor = "yellow"; + + e.scrollIntoView(true); +} + +/* we have to use load, because header images can push the layout vertically */ +window.addEventListener("load", function() { + line_range_highlight(); +}, false); + +})();