content: move clipboard.js code to content/ts
Migrates CopyToClipboardController to TypeScript
and adds a unit test.
For golang/go#43359
For golang/go#43361
Change-Id: I2e1179aa7cecb0e280a57d420ee2f885c4d6db3c
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/280893
Reviewed-by: Julie Qiu <julie@golang.org>
Trust: Jamal Carvalho <jamal@golang.org>
diff --git a/content/lib/ts/clipboard.test.ts b/content/lib/ts/clipboard.test.ts
new file mode 100644
index 0000000..28ef5ad
--- /dev/null
+++ b/content/lib/ts/clipboard.test.ts
@@ -0,0 +1,42 @@
+/*!
+ * @license
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+import { CopyToClipboardController } from './clipboard';
+
+describe('CopyToClipboardController', () => {
+ let button: HTMLButtonElement;
+ let controller: CopyToClipboardController;
+ const dataToCopy = 'Hello, world!';
+
+ beforeEach(() => {
+ document.body.innerHTML = `
+ <div>
+ <button class="js-copyToClipboard" data-to-copy="${dataToCopy}"></button>
+ </div>
+ `;
+ button = document.querySelector<HTMLButtonElement>('.js-copyToClipboard');
+ controller = new CopyToClipboardController(button);
+ });
+
+ afterEach(() => {
+ document.body.innerHTML = '';
+ });
+
+ it('copys text when clicked', () => {
+ Object.assign(navigator, { clipboard: { writeText: () => Promise.resolve() } });
+ jest.spyOn(navigator.clipboard, 'writeText');
+ button.click();
+ expect(navigator.clipboard.writeText).toHaveBeenCalledWith(dataToCopy);
+ });
+
+ it('shows error when clicked if clipboard is undefined', () => {
+ Object.assign(navigator, { clipboard: undefined });
+ jest.spyOn(controller, 'showTooltipText');
+ button.click();
+ expect(controller.showTooltipText).toHaveBeenCalledWith('Unable to copy', 1000);
+ });
+});
diff --git a/content/lib/ts/clipboard.ts b/content/lib/ts/clipboard.ts
new file mode 100644
index 0000000..51a43e6
--- /dev/null
+++ b/content/lib/ts/clipboard.ts
@@ -0,0 +1,58 @@
+/*!
+ * @license
+ * Copyright 2020 The Go Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+/**
+ * This class decorates an element to copy arbitrary data attached via a data-
+ * attribute to the clipboard.
+ */
+export class CopyToClipboardController {
+ private _el: HTMLButtonElement;
+ /**
+ * The data to be copied to the clipboard.
+ */
+ private _data: string;
+
+ /**
+ * @param el The element that will trigger copying text to the clipboard. The text is
+ * expected to be within its data-to-copy attribute.
+ */
+ constructor(el: HTMLButtonElement) {
+ this._el = el;
+ this._data = el.dataset['toCopy'] ?? '';
+ el.addEventListener('click', e => this.handleCopyClick(e));
+ }
+
+ /**
+ * Handles when the primary element is clicked.
+ */
+ handleCopyClick(e: MouseEvent): void {
+ 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.
+ */
+ showTooltipText(text: string, durationMs: number): void {
+ this._el.setAttribute('data-tooltip', text);
+ setTimeout(() => this._el.setAttribute('data-tooltip', ''), durationMs);
+ }
+}
diff --git a/content/static/js/clipboard.js b/content/static/js/clipboard.js
index c9b7e35..0773009 100644
--- a/content/static/js/clipboard.js
+++ b/content/static/js/clipboard.js
@@ -1,47 +1,18 @@
-/**
+/*!
* @license
- * Copyright 2019-2020 The Go Authors. All rights reserved.
+ * Copyright 2020 The Go Authors. All rights reserved.
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
-
-/**
- * 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
- */
+export class CopyToClipboardController {
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)));
+ this._data = el.dataset['toCopy'] ?? '';
+ el.addEventListener('click', e => this.handleCopyClick(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;
@@ -55,15 +26,9 @@
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);
}
}
+//# sourceMappingURL=clipboard.js.map
diff --git a/content/static/js/clipboard.js.map b/content/static/js/clipboard.js.map
new file mode 100644
index 0000000..245c951
--- /dev/null
+++ b/content/static/js/clipboard.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../lib/ts/clipboard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,OAAO,yBAAyB;IAWpC,YAAY,EAAqB;QAC/B,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;QACd,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACxC,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IAKD,eAAe,CAAC,CAAa;QAC3B,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,MAAM,wBAAwB,GAAG,IAAI,CAAC;QAGtC,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE;YACxB,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;YACjE,OAAO;SACR;QACD,SAAS,CAAC,SAAS;aAChB,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;aACrB,IAAI,CAAC,GAAG,EAAE;YACT,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;QAC5D,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,IAAI,CAAC,eAAe,CAAC,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;IACP,CAAC;IAKD,eAAe,CAAC,IAAY,EAAE,UAAkB;QAC9C,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QAC5C,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,cAAc,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IAC1E,CAAC;CACF"}
\ No newline at end of file
diff --git a/content/static/js/unit.js b/content/static/js/unit.js
index 23cdcd5..492f27a 100644
--- a/content/static/js/unit.js
+++ b/content/static/js/unit.js
@@ -6,6 +6,7 @@
*/
import { AccordionController } from './accordion.js';
+import { CopyToClipboardController } from './clipboard.js';
import './toggle-tip.js';
/**
@@ -18,6 +19,14 @@
}
/**
+ * Instantiates CopyToClipboardController controller copy buttons
+ * on the unit page.
+ */
+document.querySelectorAll('.js-copyToClipboard').forEach(el => {
+ new CopyToClipboardController(el);
+});
+
+/**
* Event handlers for expanding and collapsing the readme section.
*/
const readme = document.querySelector('.js-readme');
diff --git a/content/static/js/unit_fixed_header.js b/content/static/js/unit_fixed_header.js
index b28691c..a0b2ee1 100644
--- a/content/static/js/unit_fixed_header.js
+++ b/content/static/js/unit_fixed_header.js
@@ -76,73 +76,6 @@
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 => {