[PATCH 2 of 3] hgweb: parameterize the tag name of elements holding followlines selection

Denis Laxalde denis at laxalde.org
Thu Jun 22 10:40:11 EDT 2017


# HG changeset patch
# User Denis Laxalde <denis.laxalde at logilab.fr>
# Date 1498057671 -7200
#      Wed Jun 21 17:07:51 2017 +0200
# Node ID d568b7b353ea6d8ba9c30b1c2d976a88f2962245
# Parent  a67c2d37caf130131d7a5c659c9ec1428ee75451
# Available At http://hg.logilab.org/users/dlaxalde/hg
#              hg pull http://hg.logilab.org/users/dlaxalde/hg -r d568b7b353ea
hgweb: parameterize the tag name of elements holding followlines selection

While plugging followlines.js into "annotate" view, we'll need to walk a
different DOM structure from that of "filerevision" view. In particular, the
selectable source line element is a <tr> in annotate view (in contrast with a
<span> in filerevision view). So make this tag name a parameter of
followlines.js script by passing its value as a "selectabletag" data attribute
of <pre class="sourcelines"> element.

As <pre class="sourcelines"> tags are getting quite long in templates, rewrite
them on several lines.

diff --git a/mercurial/templates/gitweb/filerevision.tmpl b/mercurial/templates/gitweb/filerevision.tmpl
--- a/mercurial/templates/gitweb/filerevision.tmpl
+++ b/mercurial/templates/gitweb/filerevision.tmpl
@@ -66,7 +66,12 @@ file |
 </div>
 
 <div class="page_body">
-<pre class="sourcelines stripes" data-logurl="{url|urlescape}log/{symrev}/{file|urlescape}" data-ishead="{ishead}">{text%fileline}</pre>
+<pre class="sourcelines stripes"
+     data-logurl="{url|urlescape}log/{symrev}/{file|urlescape}"
+     data-selectabletag="SPAN"
+     data-ishead="{ishead}">
+{text%fileline}
+</pre>
 </div>
 
 <script type="text/javascript" src="{staticurl|urlescape}followlines.js"></script>
diff --git a/mercurial/templates/paper/filerevision.tmpl b/mercurial/templates/paper/filerevision.tmpl
--- a/mercurial/templates/paper/filerevision.tmpl
+++ b/mercurial/templates/paper/filerevision.tmpl
@@ -67,7 +67,12 @@
 <div class="overflow">
 <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
 <div class="sourcefirst"> line source</div>
-<pre class="sourcelines stripes4 wrap bottomline" data-logurl="{url|urlescape}log/{symrev}/{file|urlescape}" data-ishead="{ishead}">{text%fileline}</pre>
+<pre class="sourcelines stripes4 wrap bottomline"
+     data-logurl="{url|urlescape}log/{symrev}/{file|urlescape}"
+     data-selectabletag="SPAN"
+     data-ishead="{ishead}">
+{text%fileline}
+</pre>
 </div>
 
 <script type="text/javascript" src="{staticurl|urlescape}followlines.js"></script>
diff --git a/mercurial/templates/static/followlines.js b/mercurial/templates/static/followlines.js
--- a/mercurial/templates/static/followlines.js
+++ b/mercurial/templates/static/followlines.js
@@ -17,6 +17,13 @@ document.addEventListener('DOMContentLoa
         return;
     }
 
+    // Tag of children of "sourcelines" element on which to add "line
+    // selection" style.
+    var selectableTag = sourcelines.dataset.selectabletag;
+    if (typeof selectableTag === 'undefined') {
+        return;
+    }
+
     var isHead = parseInt(sourcelines.dataset.ishead || "0");
 
     // tooltip to invite on lines selection
@@ -52,22 +59,23 @@ document.addEventListener('DOMContentLoa
     // on mousemove, show tooltip close to cursor position
     sourcelines.addEventListener('mousemove', moveAndShowTooltip);
 
-    // retrieve all direct <span> children of <pre class="sourcelines">
-    var spans = Array.prototype.filter.call(
+    // retrieve all direct *selectable* children of class="sourcelines"
+    // element
+    var selectableElements = Array.prototype.filter.call(
         sourcelines.children,
-        function(x) { return x.tagName === 'SPAN' });
+        function(x) { return x.tagName === selectableTag });
 
     // add a "followlines-select" class to change cursor type in CSS
-    for (var i = 0; i < spans.length; i++) {
-        spans[i].classList.add('followlines-select');
+    for (var i = 0; i < selectableElements.length; i++) {
+        selectableElements[i].classList.add('followlines-select');
     }
 
     var lineSelectedCSSClass = 'followlines-selected';
 
-    //** add CSS class on <span> element in `from`-`to` line range */
+    //** add CSS class on selectable elements in `from`-`to` line range */
     function addSelectedCSSClass(from, to) {
         for (var i = from; i <= to; i++) {
-            spans[i].classList.add(lineSelectedCSSClass);
+            selectableElements[i].classList.add(lineSelectedCSSClass);
         }
     }
 
@@ -80,24 +88,24 @@ document.addEventListener('DOMContentLoa
         }
     }
 
-    // ** return the <span> element parent of `element` */
-    function findParentSpan(element) {
+    // ** return the element of type "selectableTag" parent of `element` */
+    function selectableParent(element) {
         var parent = element.parentElement;
         if (parent === null) {
             return null;
         }
-        if (element.tagName == 'SPAN' && parent.isSameNode(sourcelines)) {
+        if (element.tagName == selectableTag && parent.isSameNode(sourcelines)) {
             return element;
         }
-        return findParentSpan(parent);
+        return selectableParent(parent);
     }
 
     //** event handler for "click" on the first line of a block */
     function lineSelectStart(e) {
-        var startElement = findParentSpan(e.target);
+        var startElement = selectableParent(e.target);
         if (startElement === null) {
-            // not a <span> (maybe <a>): abort, keeping event listener
-            // registered for other click with <span> target
+            // not a "selectable" element (maybe <a>): abort, keeping event
+            // listener registered for other click with a "selectable" target
             return;
         }
 
@@ -112,7 +120,7 @@ document.addEventListener('DOMContentLoa
 
         //** event handler for "click" on the last line of the block */
         function lineSelectEnd(e) {
-            var endElement = findParentSpan(e.target);
+            var endElement = selectableParent(e.target);
             if (endElement === null) {
                 // not a <span> (maybe <a>): abort, keeping event listener
                 // registered for other click with <span> target
diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t
--- a/tests/test-hgweb-commands.t
+++ b/tests/test-hgweb-commands.t
@@ -1347,8 +1347,13 @@ File-related
   <div class="overflow">
   <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
   <div class="sourcefirst"> line source</div>
-  <pre class="sourcelines stripes4 wrap bottomline" data-logurl="/log/1/foo" data-ishead="0">
-  <span id="l1">foo</span><a href="#l1"></a></pre>
+  <pre class="sourcelines stripes4 wrap bottomline"
+       data-logurl="/log/1/foo"
+       data-selectabletag="SPAN"
+       data-ishead="0">
+  
+  <span id="l1">foo</span><a href="#l1"></a>
+  </pre>
   </div>
   
   <script type="text/javascript" src="/static/followlines.js"></script>
@@ -1476,8 +1481,13 @@ File-related
   <div class="overflow">
   <div class="sourcefirst linewraptoggle">line wrap: <a class="linewraplink" href="javascript:toggleLinewrap()">on</a></div>
   <div class="sourcefirst"> line source</div>
-  <pre class="sourcelines stripes4 wrap bottomline" data-logurl="/log/2/foo" data-ishead="1">
-  <span id="l1">another</span><a href="#l1"></a></pre>
+  <pre class="sourcelines stripes4 wrap bottomline"
+       data-logurl="/log/2/foo"
+       data-selectabletag="SPAN"
+       data-ishead="1">
+  
+  <span id="l1">another</span><a href="#l1"></a>
+  </pre>
   </div>
   
   <script type="text/javascript" src="/static/followlines.js"></script>


More information about the Mercurial-devel mailing list