diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java index 248fac6cc72..21bd17c1a58 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SearchWriter.java @@ -89,8 +89,9 @@ public class SearchWriter extends HtmlDocletWriter { */ protected void addSearchFileContents(Content contentTree) { - String copyText = resources.getText("doclet.Copy_url_to_clipboard"); - String copiedText = resources.getText("doclet.Copied_url_to_clipboard"); + String copyText = resources.getText("doclet.Copy_to_clipboard"); + String copiedText = resources.getText("doclet.Copied_to_clipboard"); + String copyUrlText = resources.getText("doclet.Copy_url_to_clipboard"); Content helpSection = Text.EMPTY; // Suppress link to help page if no help page is generated or a custom help page is used. HtmlOptions options = configuration.getOptions(); @@ -117,10 +118,11 @@ public class SearchWriter extends HtmlDocletWriter { .add(new HtmlTree(TagName.BUTTON) .add(new HtmlTree(TagName.IMG) .put(HtmlAttr.SRC, pathToRoot.resolve(DocPaths.CLIPBOARD_SVG).getPath()) - .put(HtmlAttr.ALT, copyText)) + .put(HtmlAttr.ALT, copyUrlText)) .add(HtmlTree.SPAN(Text.of(copyText)) .put(HtmlAttr.DATA_COPIED, copiedText)) .addStyle(HtmlStyle.copy) + .put(HtmlAttr.ARIA_LABEL, copyUrlText) .setId(HtmlId.of("page-search-copy"))) .add(HtmlTree.P(HtmlTree.INPUT("checkbox", HtmlId.of("search-redirect"))) .add(HtmlTree.LABEL("search-redirect", diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java index 455f7f2c3a3..dc3f51eb9a6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -711,17 +711,19 @@ public class TagletWriterImpl extends TagletWriter { code.add(c); } }); - String copyText = resources.getText("doclet.Copy_snippet_to_clipboard"); - String copiedText = resources.getText("doclet.Copied_snippet_to_clipboard"); + String copyText = resources.getText("doclet.Copy_to_clipboard"); + String copiedText = resources.getText("doclet.Copied_to_clipboard"); + String copySnippetText = resources.getText("doclet.Copy_snippet_to_clipboard"); var snippetContainer = HtmlTree.DIV(HtmlStyle.snippetContainer, 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.ALT, copyText)) + .put(HtmlAttr.ALT, copySnippetText)) .addStyle(HtmlStyle.copy) .addStyle(HtmlStyle.snippetCopy) + .put(HtmlAttr.ARIA_LABEL, copySnippetText) .put(HtmlAttr.ONCLICK, "copySnippet(this)")); return snippetContainer.add(pre.add(code)); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search-page.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search-page.js index cf43bbc3b9d..613d3948cb2 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search-page.js +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search-page.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,23 +39,8 @@ $(function() { copy[0].onmouseenter(); } function copyLink(e) { - var textarea = document.createElement("textarea"); - textarea.style.height = 0; - document.body.appendChild(textarea); - textarea.value = this.previousSibling.innerText; - textarea.select(); - document.execCommand("copy"); - document.body.removeChild(textarea); - var span = this.lastElementChild; - var copied = span.getAttribute("data-copied"); - if (span.innerHTML !== copied) { - var initialLabel = span.innerHTML; - span.innerHTML = copied; - var parent = this.parentElement.parentElement; - parent.onmouseleave = parent.ontouchend = copy[0].onmouseenter = function() { - span.innerHTML = initialLabel; - }; - } + copyToClipboard(this.previousSibling.innerText); + switchCopyLabel(this, this.lastElementChild); } copy.click(copyLink); copy[0].onmouseenter = function() {}; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template index 9c823b7bbc8..81e9a8a1a38 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,8 +31,9 @@ const messages = { loading: "##REPLACE:doclet.search.loading##", searching: "##REPLACE:doclet.search.searching##", redirecting: "##REPLACE:doclet.search.redirecting##", - copyUrl: "##REPLACE:doclet.Copy_url_to_clipboard##", - urlCopied: "##REPLACE:doclet.Copied_url_to_clipboard##" + copyToClipboard: "##REPLACE:doclet.Copy_to_clipboard##", + copyUrlToClipboard: "##REPLACE:doclet.Copy_url_to_clipboard##", + copiedToClipboard: "##REPLACE:doclet.Copied_to_clipboard##" } const categories = { modules: "##REPLACE:doclet.search.modules##", @@ -407,16 +408,17 @@ $(function() { $("ul.sub-nav-list-small li a").click(collapse); $("input#search-input").focus(collapse); $("main").click(collapse); - $("section[id] > :header, :header[id], :header:has(a[id])").hover( - function () { - $(this).append($("")); - }, - function () { - $(this).find("button:last").remove(); + $("section[id] > :header, :header[id], :header:has(a[id])").each(function(idx, el) { + // Create copy-to-clipboard buttons for headers with an associated id attribute + var hdr = $(el); + var id = hdr.attr("id") || hdr.parent("section").attr("id") || hdr.children("a").attr("id"); + if (id) { + hdr.append($("")); } - ); + }); $(window).on("orientationchange", collapse).on("resize", function(e) { if (expanded && windowWidth !== window.innerWidth) collapse(); }); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index 375fb39c8ce..b93303022e2 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -55,10 +55,10 @@ doclet.File_not_found=File not found: {0} doclet.snippet_file_not_found=file not found on source path or snippet path: {0} doclet.Copy_Overwrite_warning=File {0} not copied to {1} due to existing file with same name... doclet.Copy_Ignored_warning=File {0} not copied: invalid name +doclet.Copy_to_clipboard=Copy +doclet.Copied_to_clipboard=Copied! doclet.Copy_url_to_clipboard=Copy URL -doclet.Copied_url_to_clipboard=Copied! -doclet.Copy_snippet_to_clipboard=Copy -doclet.Copied_snippet_to_clipboard=Copied! +doclet.Copy_snippet_to_clipboard=Copy snippet doclet.Copying_File_0_To_Dir_1=Copying file {0} to directory {1}... doclet.Copying_File_0_To_File_1=Copying file {0} to file {1}... doclet.No_Public_Classes_To_Document=No public or protected classes found to document. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js index 324dbca2896..bbccddde5f2 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/script.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -202,7 +202,7 @@ function indexFilesLoaded() { // Copy the contents of the local snippet to the clipboard function copySnippet(button) { copyToClipboard(button.nextElementSibling.innerText); - switchCopyLabel(button.firstElementChild, button.parentElement); + switchCopyLabel(button, button.firstElementChild); } // Copy the link to the adjacent header to the clipboard function copyUrl(button) { @@ -221,7 +221,7 @@ function copyUrl(button) { url = url.substring(0, url.indexOf("#")); } copyToClipboard(url + "#" + id); - switchCopyLabel(button.lastElementChild, button.parentElement); + switchCopyLabel(button, button.lastElementChild); } function copyToClipboard(content) { var textarea = document.createElement("textarea"); @@ -232,15 +232,19 @@ function copyToClipboard(content) { document.execCommand("copy"); document.body.removeChild(textarea); } -function switchCopyLabel(span, parent) { +function switchCopyLabel(button, span) { var copied = span.getAttribute("data-copied"); - if (span.innerHTML !== copied) { - var initialLabel = span.innerHTML; - span.innerHTML = copied; - parent.onmouseleave = parent.ontouchend = function() { - span.innerHTML = initialLabel; - }; - } + button.classList.add("visible"); + var initialLabel = span.innerHTML; + span.innerHTML = copied; + setTimeout(function() { + button.classList.remove("visible"); + setTimeout(function() { + if (initialLabel !== copied) { + span.innerHTML = initialLabel; + } + }, 100); + }, 1900); } // Workaround for scroll position not being included in browser history (8249133) document.addEventListener("DOMContentLoaded", function(e) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css index 5f389596eef..f47a6fede6a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css @@ -915,16 +915,21 @@ main a[href*="://"]:focus::after { * Styles for copy-to-clipboard buttons */ button.copy { - opacity: 80%; + opacity: 70%; border: none; border-radius: 3px; position: relative; background:none; - transition: opacity 0.2s; + transition: opacity 0.3s; cursor: pointer; } +:hover > button.copy { + opacity: 80%; +} button.copy:hover, -button.copy:active { +button.copy:active, +button.copy:focus-visible, +button.copy.visible { opacity: 100%; } button.copy img { @@ -942,12 +947,19 @@ button.copy span { transition: all 0.1s; font-size: 0.76rem; line-height: 1.2em; + opacity: 0; +} +button.copy:hover span, +button.copy:focus-visible span, +button.copy.visible span { + opacity: 100%; } /* header/section copy button */ button.copy-header { margin: 0 0.2em; padding: 0 4px; height: 1.16em; + opacity: 0; } button.copy-header img { height: 0.88em; @@ -967,15 +979,12 @@ button#page-search-copy img { } button#page-search-copy span { color: var(--body-text-color); - content: attr(aria-label); line-height: 1.2em; padding: 0.2em; top: -0.18em; - opacity: 0; } -div.page-search-info:hover button#page-search-copy, div.page-search-info:hover button#page-search-copy span { - opacity: 90%; + opacity: 100%; } /* snippet copy button */ button.snippet-copy { @@ -983,7 +992,6 @@ button.snippet-copy { top: 6px; right: 6px; height: 1.7em; - opacity: 50%; padding: 2px; } button.snippet-copy img { @@ -992,20 +1000,12 @@ button.snippet-copy img { padding: 0.05em 0; } button.snippet-copy span { - content: attr(aria-label); line-height: 1.2em; padding: 0.2em; position: relative; top: -0.5em; - display: none; } div.snippet-container:hover button.snippet-copy span { - display: inline; -} -div.snippet-container:hover button.snippet-copy { - opacity: 80%; -} -div.snippet-container button.snippet-copy:hover { opacity: 100%; } /* diff --git a/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java b/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java index 5ec8284244f..7c3858e39ba 100644 --- a/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java +++ b/test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,7 +129,7 @@ public class CheckStylesheetClasses { // or if they are unused and therefore candidates to be deleted. // false positives: file extensions and URL components - removeAll(styleSheetNames, "css", "png", "w3"); + removeAll(styleSheetNames, "css", "png", "w3", "org"); // for doc-comment authors; maybe worthy of inclusion in HtmlStyle, just to be documented removeAll(styleSheetNames, "borderless", "plain", "striped"); @@ -138,7 +138,8 @@ public class CheckStylesheetClasses { removeAll(styleSheetNames, "result-highlight", "result-item", "copy-header", "search-tag-desc-result", "search-tag-holder-result", "page-search-header", "ui-autocomplete", "ui-autocomplete-category", "ui-state-active", "expanded", - "search-result-link", "two-column-search-results", "ui-static-link"); + "search-result-link", "two-column-search-results", "ui-static-link", + "sort-asc", "sort-desc", "visible"); // very JDK specific styleSheetNames.remove("module-graph"); @@ -203,7 +204,7 @@ public class CheckStylesheetClasses { throw new AssertionError("Cannot find or access resource " + resource); } String s = new String(in.readAllBytes()); - Pattern p = Pattern.compile("(?i)(\\s|([a-z][a-z0-9-]*))\\.(?[a-z][a-z0-9-]+)\\b"); + Pattern p = Pattern.compile("(?i)\\.(?[a-z][a-z0-9-]+)\\b"); Matcher m = p.matcher(s); while (m.find()) { names.add(m.group("name")); diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java index 98bb8a7f705..0436fa894fb 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/SnippetTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,8 +119,9 @@ public class SnippetTester extends JavadocTester { var idString = id.isEmpty() ? "" : " id=\"%s\"".formatted(id.get()); var langString = lang.isEmpty() ? "" : " class=\"language-%s\"".formatted(lang.get()); return """ -
+
%s
""".formatted(svgString, idString, langString, content); } diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetUnnamedPackage.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetUnnamedPackage.java index 4bebe817d67..4f5c3e32223 100644 --- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetUnnamedPackage.java +++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetUnnamedPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Optional; public class TestSnippetUnnamedPackage extends SnippetTester { @@ -87,11 +88,9 @@ public class TestSnippetUnnamedPackage extends SnippetTester { """ Before. \s -
-
public class S { }
-
+ %s - After."""); + After.""".formatted(getSnippetHtmlRepresentation("C.html", + "public class S { }", Optional.of("java")))); } }