On Wed, Mar 22, 2017 at 11:37:32AM +0100, Denis Laxalde wrote: > # HG changeset patch > # User Denis Laxalde <denis.laxa...@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@mercurial-scm.org > https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel _______________________________________________ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel