8276768: Snippet copy feature should use button instead of link
Reviewed-by: prappo
This commit is contained in:
parent
d8b0dee65e
commit
0395e4ef8c
@ -447,13 +447,14 @@ public class TagletWriterImpl extends TagletWriter {
|
|||||||
String copyText = resources.getText("doclet.Copy_snippet_to_clipboard");
|
String copyText = resources.getText("doclet.Copy_snippet_to_clipboard");
|
||||||
String copiedText = resources.getText("doclet.Copied_snippet_to_clipboard");
|
String copiedText = resources.getText("doclet.Copied_snippet_to_clipboard");
|
||||||
HtmlTree snippetContainer = HtmlTree.DIV(HtmlStyle.snippetContainer,
|
HtmlTree snippetContainer = HtmlTree.DIV(HtmlStyle.snippetContainer,
|
||||||
HtmlTree.A("#", new HtmlTree(TagName.IMG)
|
new HtmlTree(TagName.BUTTON)
|
||||||
|
.add(HtmlTree.SPAN(Text.of(copyText))
|
||||||
|
.put(HtmlAttr.DATA_COPIED, copiedText))
|
||||||
|
.add(new HtmlTree(TagName.IMG)
|
||||||
.put(HtmlAttr.SRC, htmlWriter.pathToRoot.resolve(DocPaths.CLIPBOARD_SVG).getPath())
|
.put(HtmlAttr.SRC, htmlWriter.pathToRoot.resolve(DocPaths.CLIPBOARD_SVG).getPath())
|
||||||
.put(HtmlAttr.ALT, copyText))
|
.put(HtmlAttr.ALT, copyText))
|
||||||
.addStyle(HtmlStyle.snippetCopy)
|
.addStyle(HtmlStyle.snippetCopy)
|
||||||
.put(HtmlAttr.ONCLICK, "copySnippet(this)")
|
.put(HtmlAttr.ONCLICK, "copySnippet(this)"));
|
||||||
.put(HtmlAttr.ARIA_LABEL, copyText)
|
|
||||||
.put(HtmlAttr.DATA_COPIED, copiedText));
|
|
||||||
return snippetContainer.add(pre.add(code));
|
return snippetContainer.add(pre.add(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,19 +106,24 @@ function indexFilesLoaded() {
|
|||||||
&& tagSearchIndex;
|
&& tagSearchIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
function copySnippet(link) {
|
function copySnippet(button) {
|
||||||
var textarea = document.createElement("textarea");
|
var textarea = document.createElement("textarea");
|
||||||
textarea.style.height = 0;
|
textarea.style.height = 0;
|
||||||
document.body.appendChild(textarea);
|
document.body.appendChild(textarea);
|
||||||
textarea.value = link.nextElementSibling.innerText;
|
textarea.value = button.nextElementSibling.innerText;
|
||||||
textarea.select();
|
textarea.select();
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
document.body.removeChild(textarea);
|
document.body.removeChild(textarea);
|
||||||
link.classList.add("copied");
|
var span = button.firstElementChild;
|
||||||
var parent = link.parentElement;
|
var copied = span.getAttribute("data-copied");
|
||||||
parent.onmouseleave = parent.ontouchend = function() {
|
if (span.innerHTML !== copied) {
|
||||||
link.classList.remove("copied");
|
var initialLabel = span.innerHTML;
|
||||||
};
|
span.innerHTML = copied;
|
||||||
|
var parent = button.parentElement;
|
||||||
|
parent.onmouseleave = parent.ontouchend = function() {
|
||||||
|
span.innerHTML = initialLabel;
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround for scroll position not being included in browser history (8249133)
|
// Workaround for scroll position not being included in browser history (8249133)
|
||||||
|
@ -936,62 +936,56 @@ pre.snippet {
|
|||||||
div.snippet-container {
|
div.snippet-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
a.snippet-copy {
|
button.snippet-copy {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 6px;
|
||||||
right: 8px;
|
right: 6px;
|
||||||
|
height: 1.7em;
|
||||||
|
opacity: 50%;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
padding: 2px;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
background: none;
|
||||||
}
|
}
|
||||||
a.snippet-copy img {
|
button.snippet-copy img {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
padding: 0.05em 0;
|
padding: 0.05em 0;
|
||||||
opacity: 50%;
|
background: none;
|
||||||
transition: opacity 0.2s;
|
|
||||||
}
|
}
|
||||||
div.snippet-container:hover a.snippet-copy img {
|
div.snippet-container:hover button.snippet-copy {
|
||||||
opacity: 80%;
|
opacity: 80%;
|
||||||
}
|
}
|
||||||
div.snippet-container a.snippet-copy:hover img {
|
div.snippet-container button.snippet-copy:hover {
|
||||||
opacity: 100%;
|
opacity: 100%;
|
||||||
}
|
}
|
||||||
a.snippet-copy:active img {
|
button.snippet-copy span {
|
||||||
background: #d3d3d3;
|
|
||||||
opacity: 100%;
|
|
||||||
}
|
|
||||||
a.snippet-copy::before {
|
|
||||||
color: #3d3d3d;
|
color: #3d3d3d;
|
||||||
content: attr(aria-label);
|
content: attr(aria-label);
|
||||||
font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
|
font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
|
||||||
font-size: 85%;
|
font-size: 85%;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
padding: 0.2em;
|
padding: 0.2em;
|
||||||
position: absolute;
|
position: relative;
|
||||||
opacity: 80%;
|
|
||||||
transition: opacity 0.2s;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
top: -0.01em;
|
top: -0.5em;
|
||||||
right: 1.5em;
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
div.snippet-container:hover a.snippet-copy::before {
|
div.snippet-container:hover button.snippet-copy span {
|
||||||
display: inherit;
|
display: inline;
|
||||||
}
|
}
|
||||||
div.snippet-container a.snippet-copy:hover::before {
|
button.snippet-copy:active {
|
||||||
|
background: #d3d3d3;
|
||||||
opacity: 100%;
|
opacity: 100%;
|
||||||
}
|
}
|
||||||
a.snippet-copy.copied::before {
|
|
||||||
content: attr(data-copied);
|
|
||||||
}
|
|
||||||
a.snippet-copy:active::before {
|
|
||||||
background-color: #dadada;
|
|
||||||
}
|
|
||||||
@media screen and (max-width: 800px) {
|
@media screen and (max-width: 800px) {
|
||||||
pre.snippet {
|
pre.snippet {
|
||||||
padding-top: 26px;
|
padding-top: 26px;
|
||||||
}
|
}
|
||||||
a.snippet-copy {
|
button.snippet-copy {
|
||||||
top: 6px;
|
top: 4px;
|
||||||
right: 6px;
|
right: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pre.snippet .italic {
|
pre.snippet .italic {
|
||||||
|
@ -224,9 +224,9 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
<span class="element-name">case%s</span>()</div>
|
<span class="element-name">case%s</span>()</div>
|
||||||
<div class="block">A method.
|
<div class="block">A method.
|
||||||
\s
|
\s
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="cop\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySni\
|
||||||
ySnippet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.sv\
|
ppet(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" al\
|
||||||
g" alt="Copy"></a>
|
t="Copy"></button>
|
||||||
<pre class="snippet"%s><code%s> Hello, Snippet!
|
<pre class="snippet"%s><code%s> Hello, Snippet!
|
||||||
</code></pre>
|
</code></pre>
|
||||||
</div>
|
</div>
|
||||||
@ -948,9 +948,9 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
"""
|
"""
|
||||||
<span class="element-name">case%s</span>()</div>
|
<span class="element-name">case%s</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="cop\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySni\
|
||||||
ySnippet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.sv\
|
ppet(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" al\
|
||||||
g" alt="Copy"></a>
|
t="Copy"></button>
|
||||||
<pre class="snippet"><code>%s</code></pre>
|
<pre class="snippet"><code>%s</code></pre>
|
||||||
</div>""".formatted(id, t.expectedOutput()));
|
</div>""".formatted(id, t.expectedOutput()));
|
||||||
});
|
});
|
||||||
@ -1044,9 +1044,9 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
"""
|
"""
|
||||||
<span class="element-name">case%s</span>()</div>
|
<span class="element-name">case%s</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="cop\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySni\
|
||||||
ySnippet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.sv\
|
ppet(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" al\
|
||||||
g" alt="Copy"></a>
|
t="Copy"></button>
|
||||||
<pre class="snippet"><code>%s</code></pre>
|
<pre class="snippet"><code>%s</code></pre>
|
||||||
</div>""".formatted(index, expectedOutput));
|
</div>""".formatted(index, expectedOutput));
|
||||||
});
|
});
|
||||||
@ -1605,9 +1605,9 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
"""
|
"""
|
||||||
<span class="element-name">case%s</span>()</div>
|
<span class="element-name">case%s</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="cop\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySni\
|
||||||
ySnippet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.sv\
|
ppet(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" al\
|
||||||
g" alt="Copy"></a>
|
t="Copy"></button>
|
||||||
<pre class="snippet"><code>%s</code></pre>
|
<pre class="snippet"><code>%s</code></pre>
|
||||||
</div>""".formatted(index, t.expectedOutput()));
|
</div>""".formatted(index, t.expectedOutput()));
|
||||||
});
|
});
|
||||||
@ -1722,18 +1722,18 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
"""
|
"""
|
||||||
<span class="element-name">case0</span>()</div>
|
<span class="element-name">case0</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="copySni\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySnippet\
|
||||||
ppet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.svg" alt="\
|
(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" alt="Copy"\
|
||||||
Copy"></a>
|
></button>
|
||||||
<pre class="snippet"><code></code></pre>
|
<pre class="snippet"><code></code></pre>
|
||||||
</div>""");
|
</div>""");
|
||||||
checkOutput("pkg/A.html", true,
|
checkOutput("pkg/A.html", true,
|
||||||
"""
|
"""
|
||||||
<span class="element-name">case1</span>()</div>
|
<span class="element-name">case1</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="copySni\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySnippet\
|
||||||
ppet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.svg" alt="\
|
(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" alt="Copy"\
|
||||||
Copy"></a>
|
></button>
|
||||||
<pre class="snippet"><code></code></pre>
|
<pre class="snippet"><code></code></pre>
|
||||||
</div>""");
|
</div>""");
|
||||||
}
|
}
|
||||||
@ -1832,9 +1832,9 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
"""
|
"""
|
||||||
<span class="element-name">case%s</span>()</div>
|
<span class="element-name">case%s</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="cop\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySni\
|
||||||
ySnippet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.sv\
|
ppet(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" al\
|
||||||
g" alt="Copy"></a>
|
t="Copy"></button>
|
||||||
<pre class="snippet"><code>2</code></pre>
|
<pre class="snippet"><code>2</code></pre>
|
||||||
</div>
|
</div>
|
||||||
""".formatted(j));
|
""".formatted(j));
|
||||||
@ -1916,9 +1916,9 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
"""
|
"""
|
||||||
<span class="element-name">case%s</span>()</div>
|
<span class="element-name">case%s</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="cop\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySni\
|
||||||
ySnippet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.sv\
|
ppet(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" al\
|
||||||
g" alt="Copy"></a>
|
t="Copy"></button>
|
||||||
<pre class="snippet"><code>%s</code></pre>
|
<pre class="snippet"><code>%s</code></pre>
|
||||||
</div>""".formatted(index, t.expectedOutput()));
|
</div>""".formatted(index, t.expectedOutput()));
|
||||||
});
|
});
|
||||||
@ -2248,9 +2248,9 @@ public class TestSnippetTag extends JavadocTester {
|
|||||||
"""
|
"""
|
||||||
<span class="element-name">case%s</span>()</div>
|
<span class="element-name">case%s</span>()</div>
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<div class="snippet-container"><a href="#" class="snippet-copy" onclick="cop\
|
<div class="snippet-container"><button class="snippet-copy" onclick="copySni\
|
||||||
ySnippet(this)" aria-label="Copy" data-copied="Copied!"><img src="../copy.sv\
|
ppet(this)"><span data-copied="Copied!">Copy</span><img src="../copy.svg" al\
|
||||||
g" alt="Copy"></a>
|
t="Copy"></button>
|
||||||
<pre class="snippet"><code>%s</code></pre>
|
<pre class="snippet"><code>%s</code></pre>
|
||||||
</div>""".formatted(index, t.expectedOutput()));
|
</div>""".formatted(index, t.expectedOutput()));
|
||||||
});
|
});
|
||||||
|
@ -351,7 +351,7 @@ public class LinkChecker extends HtmlChecker {
|
|||||||
|
|
||||||
void addReference(String name, Path from, int line) {
|
void addReference(String name, Path from, int line) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
if (name != null && !name.isEmpty()) {
|
if (name != null) {
|
||||||
ID id = map.get(name);
|
ID id = map.get(name);
|
||||||
if (id == null || !id.declared) {
|
if (id == null || !id.declared) {
|
||||||
error(from, line, "id not found: " + this.name + "#" + name);
|
error(from, line, "id not found: " + this.name + "#" + name);
|
||||||
@ -368,7 +368,7 @@ public class LinkChecker extends HtmlChecker {
|
|||||||
|
|
||||||
void check() {
|
void check() {
|
||||||
map.forEach((name, id) -> {
|
map.forEach((name, id) -> {
|
||||||
if (name != null && !name.isEmpty() && !id.declared) {
|
if (name != null && !id.declared) {
|
||||||
//log.error(currFile, 0, "id not declared: " + name);
|
//log.error(currFile, 0, "id not declared: " + name);
|
||||||
for (Position ref : id.references) {
|
for (Position ref : id.references) {
|
||||||
error(ref.path, ref.line, "id not found: " + this.name + "#" + name);
|
error(ref.path, ref.line, "id not found: " + this.name + "#" + name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user