hgweb: parameterize the tag name of elements holding followlines selection
authorDenis Laxalde <denis.laxalde@logilab.fr>
Wed, 21 Jun 2017 17:07:51 +0200
changeset 32995 7c82bfd55d47
parent 32994 9fda810cd0db
child 32996 1c97df5e3b46
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.
mercurial/templates/gitweb/filerevision.tmpl
mercurial/templates/paper/filerevision.tmpl
mercurial/templates/static/followlines.js
tests/test-hgweb-commands.t
tests/test-highlight.t
--- a/mercurial/templates/gitweb/filerevision.tmpl	Wed Jun 21 17:02:21 2017 +0200
+++ b/mercurial/templates/gitweb/filerevision.tmpl	Wed Jun 21 17:07:51 2017 +0200
@@ -66,7 +66,12 @@
 </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>
--- a/mercurial/templates/paper/filerevision.tmpl	Wed Jun 21 17:02:21 2017 +0200
+++ b/mercurial/templates/paper/filerevision.tmpl	Wed Jun 21 17:07:51 2017 +0200
@@ -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>
--- a/mercurial/templates/static/followlines.js	Wed Jun 21 17:02:21 2017 +0200
+++ b/mercurial/templates/static/followlines.js	Wed Jun 21 17:07:51 2017 +0200
@@ -17,6 +17,13 @@
         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 @@
     // 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 @@
         }
     }
 
-    // ** 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 @@
 
         //** 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
--- a/tests/test-hgweb-commands.t	Wed Jun 21 17:02:21 2017 +0200
+++ b/tests/test-hgweb-commands.t	Wed Jun 21 17:07:51 2017 +0200
@@ -1347,8 +1347,13 @@
   <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 @@
   <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>
--- a/tests/test-highlight.t	Wed Jun 21 17:02:21 2017 +0200
+++ b/tests/test-highlight.t	Wed Jun 21 17:07:51 2017 +0200
@@ -148,7 +148,11 @@
   <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/tip/primes.py" data-ishead="1">
+  <pre class="sourcelines stripes4 wrap bottomline"
+       data-logurl="/log/tip/primes.py"
+       data-selectabletag="SPAN"
+       data-ishead="1">
+  
   <span id="l1"><span class="sd">&quot;&quot;&quot;Fun with generators. Corresponding Haskell implementation:</span></span><a href="#l1"></a>
   <span id="l2"></span><a href="#l2"></a>
   <span id="l3"><span class="sd">primes = 2 : sieve [3, 5..]</span></span><a href="#l3"></a>
@@ -179,7 +183,8 @@
   <span id="l28">        <span class="n">n</span> <span class="o">=</span> <span class="mi">10</span></span><a href="#l28"></a>
   <span id="l29">    <span class="n">p</span> <span class="o">=</span> <span class="n">primes</span><span class="p">()</span></span><a href="#l29"></a>
   <span id="l30">    <span class="kn">print</span> <span class="s">&quot;The first </span><span class="si">%d</span><span class="s"> primes: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">islice</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">n</span><span class="p">)))</span></span><a href="#l30"></a>
-  <span id="l31"></span><a href="#l31"></a></pre>
+  <span id="l31"></span><a href="#l31"></a>
+  </pre>
   </div>
   
   <script type="text/javascript" src="/static/followlines.js"></script>