[PATCH 1/3] ui-shared: introduce line range highlight javascript
Andy Green
andy at warmcat.com
Thu Jun 21 07:42:50 CEST 2018
This adds a small css class and a function in ui-shared that
emits canned javascript 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
applied a computed absolute, transparent 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
Examples:
https://warmcat.com/git/cgit/tree/ui-shared.c#n1146
https://warmcat.com/git/cgit/tree/ui-shared.c#n1146-1164
https://warmcat.com/git/cgit/blame/ui-shared.c#n1146-1164
Signed-off-by: Andy Green <andy at warmcat.com>
---
cgit.css | 8 ++++++++
ui-shared.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
ui-shared.h | 1 +
3 files changed, 61 insertions(+)
diff --git a/cgit.css b/cgit.css
index 61bbd49..7cb0fd6 100644
--- a/cgit.css
+++ b/cgit.css
@@ -368,6 +368,14 @@ div#cgit table.blame td.lines > div > pre {
top: 0;
}
+div#cgit div.line_range {
+ position: absolute;
+ pointer-events: none;
+ left: 0px;
+ z-index: 1;
+ background-color: rgba(255, 255, 0, 0.2);
+}
+
div#cgit table.bin-blob {
margin-top: 0.5em;
border: solid 1px black;
diff --git a/ui-shared.c b/ui-shared.c
index 082a6f1..c8f4d8f 100644
--- a/ui-shared.c
+++ b/ui-shared.c
@@ -1237,3 +1237,55 @@ void cgit_set_title_from_path(const char *path)
strcat(new_title, ctx.page.title);
ctx.page.title = new_title;
}
+
+void cgit_emit_line_range_highlight_script(int parent_level)
+{
+ html("<script>\n"
+ "function cgit_line_range_highlight()\n"
+ "{\n"
+ " var h = window.location.hash, l1 = 0, l2 = 0, e, t;\n"
+ "\n"
+ " l1 = parseInt(h.substring(2));\n"
+ " t = h.indexOf(\"-\");\n"
+ " if (t >= 1)\n"
+ " l2 = parseInt(h.substring(t + 1));\n"
+ " else\n"
+ " l2 = l1;\n"
+ "\n"
+ " if (l1) {\n"
+ " var lh, t = 0, e1, de;\n"
+ "\n"
+ " e1 = e = document.getElementById('n' + l1);\n"
+ " if (e) {\n"
+ "\n"
+ " while (e1) { if (e1.offsetTop) t += e1.offsetTop; e1 = e1.offsetParent; } \n"
+ "\n"
+ " de = document.createElement(\"DIV\");"
+ "\n"
+ " de.className = \"line_range\";\n"
+ " de.style.bottom = e.style.bottom;\n"
+ " de.style.top = t + 'px';\n");
+ if (!parent_level)
+ html(" de.style.width = e.parentElement.parentElement.parentNode.offsetWidth + 'px';\n");
+ else
+ html(" de.style.width = e.parentElement.parentElement.parentNode.parentNode.offsetWidth + 'px';\n");
+ html(" de.style.height = ((l2 - l1 + 1) * e.offsetHeight) + 'px';\n"
+ "\n"
+ " e.parentElement.parentElement.insertBefore(de, e.parentElement.parentElement.firstChild);\n"
+ "\n"
+ " while (l1 <= l2) {\n"
+ " var e1;\n"
+ " e1 = document.getElementById('n' + l1++);\n"
+ " e1.style.backgroundColor = \"yellow\";\n"
+ " }\n"
+ "\n"
+ " e.scrollIntoView(true);\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "document.addEventListener(\"DOMContentLoaded\", function() {"
+ " cgit_line_range_highlight();\n"
+ "}, false);\n"
+ "</script>\n");
+}
diff --git a/ui-shared.h b/ui-shared.h
index e78b5fd..8b0cddc 100644
--- a/ui-shared.h
+++ b/ui-shared.h
@@ -89,4 +89,5 @@ extern void cgit_add_hidden_formfields(int incl_head, int incl_search,
const char *page);
extern void cgit_set_title_from_path(const char *path);
+extern void cgit_emit_line_range_highlight_script(int parent_level);
#endif /* UI_SHARED_H */
More information about the CGit
mailing list