content/static: add copy on click to unit page header
Adds copy on click code to unit page.
Change-Id: I2a7e350e002bfc5459cc9204d92690a245a4f32f
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/259201
Trust: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/content/static/css/unit_header.css b/content/static/css/unit_header.css
index 24de709..8a9247c 100644
--- a/content/static/css/unit_header.css
+++ b/content/static/css/unit_header.css
@@ -23,12 +23,13 @@
}
.UnitHeader-breadcrumbItem {
color: var(--gray-4);
+ display: inline-flex;
font-size: 0.875rem;
line-height: 1.5rem;
}
.UnitHeader-breadcrumbItem:not(:last-child)::after {
content: '>';
- padding: 0.5rem;
+ padding: 0 0.5rem;
}
.UnitHeader-heading {
display: flex;
diff --git a/content/static/html/helpers/_unit_header.tmpl b/content/static/html/helpers/_unit_header.tmpl
index 14bd702..7d429a6 100644
--- a/content/static/html/helpers/_unit_header.tmpl
+++ b/content/static/html/helpers/_unit_header.tmpl
@@ -19,7 +19,17 @@
<a href="{{.Href}}">{{.Body}}</a>
</span>
{{end}}
- <span class="UnitHeader-breadcrumbItem">{{.Current}}</span>
+ <span class="UnitHeader-breadcrumbItem">
+ {{.Current}}
+ {{if .CopyData}}
+ <button class="CopyToClipboardButton js-copyToClipboard"
+ title="Copy path to clipboard"
+ data-to-copy="{{.CopyData}}"
+ tabindex="-1">
+ <img class="CopyToClipboardButton-image" src="/static/img/copy-click.svg" alt="">
+ </button>
+ {{end}}
+ </span>
{{end}}
</div>
<div class="UnitHeader-heading">
diff --git a/content/static/js/unit_fixed_header.js b/content/static/js/unit_fixed_header.js
index a0b2ee1..b28691c 100644
--- a/content/static/js/unit_fixed_header.js
+++ b/content/static/js/unit_fixed_header.js
@@ -76,6 +76,73 @@
document.querySelector('.js-fixedHeader')
);
+/**
+ * This class decorates an element to copy arbitrary data attached via a data-
+ * attribute to the clipboard.
+ */
+class CopyToClipboardController {
+ /**
+ * The element that will trigger copying text to the clipboard. The text is
+ * expected to be within its data-to-copy attribute.
+ * @param {!Element} el
+ */
+ constructor(el) {
+ /**
+ * @type {!Element}
+ * @private
+ */
+ this._el = el;
+
+ /**
+ * The data to be copied to the clipboard.
+ * @type {string}
+ * @private
+ */
+ this._data = el.dataset['toCopy'];
+
+ el.addEventListener('click', e => this.handleCopyClick(/** @type {!Event} */ (e)));
+ }
+
+ /**
+ * Handles when the primary element is clicked.
+ * @param {!Event} e
+ * @private
+ */
+ handleCopyClick(e) {
+ e.preventDefault();
+ const TOOLTIP_SHOW_DURATION_MS = 1000;
+
+ // This API is not available on iOS.
+ if (!navigator.clipboard) {
+ this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);
+ return;
+ }
+ navigator.clipboard
+ .writeText(this._data)
+ .then(() => {
+ this.showTooltipText('Copied!', TOOLTIP_SHOW_DURATION_MS);
+ })
+ .catch(() => {
+ this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);
+ });
+ }
+
+ /**
+ * Shows the given text in a tooltip for a specified amount of time, in milliseconds.
+ * @param {string} text
+ * @param {number} durationMs
+ * @private
+ */
+ showTooltipText(text, durationMs) {
+ this._el.setAttribute('data-tooltip', text);
+ setTimeout(() => this._el.setAttribute('data-tooltip', ''), durationMs);
+ }
+}
+
+document.querySelectorAll('.js-copyToClipboard').forEach(el => {
+ new CopyToClipboardController(el);
+});
+
const overflowSelect = document.querySelector('.js-overflowSelect');
if (overflowSelect) {
overflowSelect.addEventListener('change', e => {