[PATCH 7 of 7 V3] hgweb: expose a followlines UI in filerevision view (RFC)

Augie Fackler raf at durin42.com
Thu Mar 23 11:55:53 EDT 2017


On Wed, Mar 22, 2017 at 11:37:32AM +0100, Denis Laxalde wrote:
> # HG changeset patch
> # User Denis Laxalde <denis.laxalde at logilab.fr>
> # Date 1489594320 -3600
> #      Wed Mar 15 17:12:00 2017 +0100
> # Node ID cb742fcfe0edb2d393b59674c4eebcf8775ecfe1
> # Parent  9e3ae74c1ca558f0584067c62835bec82034c245
> # Available At http://hg.logilab.org/users/dlaxalde/hg
> #              hg pull http://hg.logilab.org/users/dlaxalde/hg -r cb742fcfe0ed
> hgweb: expose a followlines UI in filerevision view (RFC)

Neat idea.

>
> In filerevision view (/file/<rev>/<fname>) we add some event listeners on
> mouse selection of <span> elements in the <pre class="sourcelines"> block.
> Those listeners will capture the range of mouse-selected lines and, upon mouse
> release, a box inviting to follow the history of selected lines will show up.
> This action is advertised by a :after pseudo-element on file lines that shows
> up on hover and invite to "select a block of lines to follow its history".
>
> This is proposal implementation, comments welcome on any aspects.

It's a neat idea. I think I like it...

>
> 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
> @@ -73,6 +73,11 @@
>  <div class="sourcefirst"> line source</div>
>  <pre class="sourcelines stripes4 wrap bottomline">{text%fileline}</pre>
>  </div>
> +
> +<script type="text/javascript"{if(nonce, ' nonce="{nonce}"')}>
> +    installLineSelect("{url|urlescape}log/{symrev}/{file|urlescape}");
> +</script>

I suspect you can't do this inline javascript because of our Content-Security-Policy support. Greg?

(Maybe the nonce makes this okay. I don't really understand modern JS yet...)

> +
>  </div>
>  </div>
>
> diff --git a/mercurial/templates/static/mercurial.js b/mercurial/templates/static/mercurial.js
> --- a/mercurial/templates/static/mercurial.js
> +++ b/mercurial/templates/static/mercurial.js
> @@ -434,6 +434,81 @@ function ajaxScrollInit(urlFormat,
>      scrollHandler();
>  }
>
> +//** install mouse event listeners on <pre class="sourcelines"> */
> +function installLineSelect(targetUri) {
> +    var sourcelines = document.getElementsByClassName('sourcelines')[0];
> +    if (typeof sourcelines === 'undefined') {
> +        return;
> +    }
> +    // add event listener to the whole <pre class="sourcelines"> block to have
> +    // it available in all children <span>
> +    sourcelines.addEventListener('mousedown', lineSelectStart);
> +
> +    //** event handler for "mousedown" */
> +    function lineSelectStart(e) {
> +        var startElement = e.target;
> +        if (startElement.tagName !== 'SPAN') {
> +            // we may be on a <a>
> +            return;
> +        }
> +        // retarget "mouseup" to sourcelines element so that if this event
> +        // occurs outside the <pre> we don't miss it
> +        sourcelines.setCapture();
> +        // drop any prior <div id="followlines">
> +        var previousInvite = document.getElementById('followlines');
> +        if (previousInvite !== null) {
> +            previousInvite.parentNode.removeChild(previousInvite);
> +        }
> +
> +        var startId = parseInt(startElement.id.slice(1));
> +
> +        //** event handler for "mouseup" */
> +        function lineSelectEnd(e) {
> +            // remove "mouseup" listener
> +            sourcelines.removeEventListener('mouseup', lineSelectEnd);
> +
> +            var endElement = e.target;
> +            if (endElement.tagName !== 'SPAN') {
> +                // not on <span>, probably outside <pre class="sourcelines">,
> +                // we cannot compute endId
> +                return;
> +            }
> +
> +            // compute line range (startId, endId) and insert the
> +            // "followlines" element
> +            var endId = parseInt(endElement.id.slice(1));
> +            if (endId == startId) {
> +                return;
> +            }
> +            var inviteElement = endElement;
> +            if (endId < startId) {
> +                var tmp = endId;
> +                endId = startId;
> +                startId = tmp;
> +                inviteElement = startElement;
> +            }
> +            var div = followlinesBox(startId, endId);
> +            inviteElement.appendChild(div);
> +        }
> +
> +        sourcelines.addEventListener('mouseup', lineSelectEnd);
> +
> +    }
> +
> +    //** return a <div id="followlines"> with a link for followlines action */
> +    function followlinesBox(startId, endId) {
> +        var div = document.createElement('div');
> +        div.id = 'followlines';
> +        var a = document.createElement('a');
> +        var url = targetUri + '?patch=&linerange=' + startId + ':' + endId;
> +        a.setAttribute('href', url);
> +        a.textContent = 'follow lines ' + startId + ':' + endId;
> +        div.appendChild(a);
> +        return div;
> +    }
> +
> +}
> +
>  document.addEventListener('DOMContentLoaded', function() {
>     process_dates();
>  }, false);
> diff --git a/mercurial/templates/static/style-paper.css b/mercurial/templates/static/style-paper.css
> --- a/mercurial/templates/static/style-paper.css
> +++ b/mercurial/templates/static/style-paper.css
> @@ -276,10 +276,28 @@ td.annotate:hover div.annotate-info { di
>    float: left;
>  }
>
> +div.overflow pre.sourcelines > span:hover:after {
> +  content: "select a block of lines to follow its history";
> +  display: inline;
> +  float: right;
> +  line-height: 1em;
> +  background-color: #FFFFFF;
> +  color: #001199;
> +}
> +
>  .sourcelines > span:target, tr:target td {
>    background-color: #bfdfff;
>  }
>
> +div#followlines {
> +  display: inline;
> +  position: absolute;
> +  background-color: #FFFFFF;
> +  border: 1px solid #999;
> +  color: #000000;
> +  padding: 2px;
> +}
> +
>  .sourcelines > a {
>      display: inline-block;
>      position: absolute;
> 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
> @@ -1346,6 +1346,11 @@ File-related
>    <pre class="sourcelines stripes4 wrap bottomline">
>    <span id="l1">foo</span><a href="#l1"></a></pre>
>    </div>
> +
> +  <script type="text/javascript">
> +      installLineSelect("/log/1/foo");
> +  </script>
> +
>    </div>
>    </div>
>
> @@ -1471,6 +1476,11 @@ File-related
>    <pre class="sourcelines stripes4 wrap bottomline">
>    <span id="l1">another</span><a href="#l1"></a></pre>
>    </div>
> +
> +  <script type="text/javascript">
> +      installLineSelect("/log/2/foo");
> +  </script>
> +
>    </div>
>    </div>
>
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


More information about the Mercurial-devel mailing list