Show link on hover for headings and anchors in documentation

For supporting users it is often useful to send them links to a
certain section in the documentation. The Gerrit documenation contains
a lot of anchors, but they are not easily accessible. If the section
is linked from the TOC the link to the section can be gained by
clicking on the link in the TOC. To link to other elements it is often
needed to check the HTML source code to find out the link target.

Make the links to section headings and anchors easier accessible by
displaying a link icon when the mouse is hovered over the heading or
anchor. By clicking on the link icon the page anchor is set and the
link can be copied from the address bar of the browser.

Having this functionality for anchors is especially useful for linking
to certain configuration parameters in the config-gerrit.html page.

The link icon is taken from the 'Freebie: Application Icon Set' [1]
which is licensed under the Creative Commons Attribution 3.0 Unported
License [2].

[1] http://tympanus.net/codrops/2012/10/02/freebie-application-icon-set-png-psd-csh/
[2] http://creativecommons.org/licenses/by/3.0/deed.en_US

Change-Id: I4377ea23ad76143fd4caa78afc30b82690e533ff
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
(cherry picked from commit a92861fb01)
This commit is contained in:
Edwin Kempin
2014-11-04 17:48:10 +01:00
committed by David Pursehouse
parent c57cc47865
commit 93a17f6e1c
5 changed files with 120 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -80,6 +80,114 @@ document.getElementById("docSearch").onkeypress = function(e) {
""" """
LINK_SCRIPT = """
++++
<script type="text/javascript">
decorate(document.getElementsByTagName('h1'));
decorate(document.getElementsByTagName('h2'));
decorate(document.getElementsByTagName('h3'));
var divs = document.getElementsByTagName('div');
var arr = new Array();
var excluded = getExcludedIds();
for(var i = 0; i < divs.length; i++) {
var d = divs[i];
var id = d.getAttribute('id');
if (id != null && !(id in excluded)) {
arr[arr.length] = d;
}
}
decorate(arr);
var anchors = document.getElementsByTagName('a');
arr = new Array();
for(var i = 0; i < anchors.length; i++) {
var a = anchors[i];
// if the anchor has no id there is no target to
// which we can link
if (a.getAttribute('id') != null) {
// if the anchor is empty there is no content which
// can receive the mouseover event, an empty anchor
// applies to the element that follows, move the
// element that follows into the anchor so that there
// is content which can receive the mouseover event
if (a.firstChild == null) {
var next = a.nextSibling;
if (next != null) {
next.parentNode.removeChild(next);
a.appendChild(next);
}
}
arr[arr.length] = a;
}
}
decorate(arr);
function decorate(e) {
for(var i = 0; i < e.length; i++) {
e[i].onmouseover = function (evt) {
var element = this;
// do nothing if the link icon is currently showing
var a = element.firstChild;
if (a != null && a instanceof Element
&& a.getAttribute('id') == 'LINK') {
return;
}
// if there is no id there is no target to link to
var id = element.getAttribute('id');
if (id == null) {
return;
}
// create and show a link icon that links to this element
a = document.createElement('a');
a.setAttribute('id', 'LINK');
a.setAttribute('href', '#' + id);
a.setAttribute('style', 'position: absolute;'
+ ' left: ' + (element.offsetLeft - 16 - 2 * 4) + 'px;'
+ ' padding-left: 4px; padding-right: 4px; padding-top:4px;');
var img = document.createElement('img');
img.setAttribute('src', 'images/link.png');
img.setAttribute('style', 'background-color: #FFFFFF;');
a.appendChild(img);
element.insertBefore(a, element.firstChild);
// remove the link icon when the mouse is moved away,
// but keep it shown if the mouse is over the element, the link or the icon
hide = function(evt) {
if (document.elementFromPoint(evt.clientX, evt.clientY) != element
&& document.elementFromPoint(evt.clientX, evt.clientY) != a
&& document.elementFromPoint(evt.clientX, evt.clientY) != img
&& element.contains(a)) {
element.removeChild(a);
}
}
element.onmouseout = hide;
a.onmouseout = hide;
img.onmouseout = hide;
}
}
}
function getExcludedIds() {
var excluded = {};
excluded['header'] = true;
excluded['toc'] = true;
excluded['toctitle'] = true;
excluded['content'] = true;
excluded['preamble'] = true;
excluded['footer'] = true;
excluded['footer-text'] = true;
return excluded;
}
</script>
++++
"""
opts = OptionParser() opts = OptionParser()
opts.add_option('-o', '--out', help='output file') opts.add_option('-o', '--out', help='output file')
opts.add_option('-s', '--src', help='source file') opts.add_option('-s', '--src', help='source file')
@@ -127,6 +235,7 @@ try:
out_file.write(last_line) out_file.write(last_line)
last_line = line last_line = line
out_file.write(last_line) out_file.write(last_line)
out_file.write(LINK_SCRIPT)
out_file.close() out_file.close()
except IOError as err: except IOError as err:
sys.stderr.write( sys.stderr.write(

View File

@@ -68,6 +68,7 @@ gwt_module(
resources = glob(['src/main/java/**/*'], excludes = DIFFY), resources = glob(['src/main/java/**/*'], excludes = DIFFY),
deps = [ deps = [
':diffy_logo', ':diffy_logo',
':freebie_application_icon_set',
'//gerrit-gwtexpui:Clippy', '//gerrit-gwtexpui:Clippy',
'//gerrit-gwtexpui:GlobalKey', '//gerrit-gwtexpui:GlobalKey',
'//gerrit-gwtexpui:Progress', '//gerrit-gwtexpui:Progress',
@@ -102,6 +103,14 @@ prebuilt_jar(
], ],
) )
java_library(
name = 'freebie_application_icon_set',
deps = [
'//lib:LICENSE-freebie_application_icon_set',
'//lib:LICENSE-CC-BY3.0',
],
)
genrule( genrule(
name = 'diffy_image_files_ln', name = 'diffy_image_files_ln',
cmd = 'ln -s $(location :diffy_image_files) $OUT', cmd = 'ln -s $(location :diffy_image_files) $OUT',

View File

@@ -12,6 +12,7 @@ define_license(name = 'bouncycastle')
define_license(name = 'clippy') define_license(name = 'clippy')
define_license(name = 'codemirror') define_license(name = 'codemirror')
define_license(name = 'diffy') define_license(name = 'diffy')
define_license(name = 'freebie_application_icon_set')
define_license(name = 'h2') define_license(name = 'h2')
define_license(name = 'jgit') define_license(name = 'jgit')
define_license(name = 'jsch') define_license(name = 'jsch')

View File

@@ -0,0 +1 @@
link:http://creativecommons.org/licenses/by/3.0/us/[CC-BY 3.0] (c) Matt Gentile, link:http://tympanus.net/codrops/2012/10/02/freebie-application-icon-set-png-psd-csh/[Freebie: Application Icon Set]