Skip to content

Commit

Permalink
Use clippie module to copy to clipboard (#23801)
Browse files Browse the repository at this point in the history
Externalize clipboard copying to the
[clippie](https://github.com/silverwind/clippie) module which I feel I
can maintain outside this repo for shared benefit with my other
projects.

The module is feature-equivalent to the previous code and has one
improvement where it sets `aria-hidden` on the fallback textarea,
preventing screen readers from picking it up. Also it support `Array` of
`content` as well to copy multiple items at once, in case it's ever
needed.
  • Loading branch information
silverwind authored Apr 2, 2023
1 parent fcb9ef8 commit f5593d0
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 45 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"add-asset-webpack-plugin": "2.0.1",
"ansi-to-html": "0.7.2",
"asciinema-player": "3.2.0",
"clippie": "3.1.4",
"css-loader": "6.7.3",
"dropzone": "6.0.0-beta.2",
"easymde": "2.18.0",
Expand Down
43 changes: 2 additions & 41 deletions web_src/js/features/clipboard.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,9 @@
import {showTemporaryTooltip} from '../modules/tippy.js';
import {toAbsoluteUrl} from '../utils.js';
import {clippie} from 'clippie';

const {copy_success, copy_error} = window.config.i18n;

export async function copyToClipboard(content) {
if (content instanceof Blob) {
const item = new ClipboardItem({[content.type]: content});
await navigator.clipboard.write([item]);
} else { // text
try {
await navigator.clipboard.writeText(content);
} catch {
return fallbackCopyToClipboard(content);
}
}
return true;
}

// Fallback to use if navigator.clipboard doesn't exist. Achieved via creating
// a temporary textarea element, selecting the text, and using document.execCommand
function fallbackCopyToClipboard(text) {
if (!document.execCommand) return false;

const tempTextArea = document.createElement('textarea');
tempTextArea.value = text;

// avoid scrolling
tempTextArea.style.top = 0;
tempTextArea.style.left = 0;
tempTextArea.style.position = 'fixed';

document.body.appendChild(tempTextArea);

tempTextArea.select();

// if unsecure (not https), there is no navigator.clipboard, but we can still
// use document.execCommand to copy to clipboard
const success = document.execCommand('copy');

document.body.removeChild(tempTextArea);

return success;
}

// For all DOM elements with [data-clipboard-target] or [data-clipboard-text],
// this copy-to-clipboard will work for them
export function initGlobalCopyToClipboardListener() {
Expand All @@ -61,7 +22,7 @@ export function initGlobalCopyToClipboardListener() {
e.preventDefault();

(async() => {
const success = await copyToClipboard(text);
const success = await clippie(text);
showTemporaryTooltip(target, success ? copy_success : copy_error);
})();

Expand Down
4 changes: 2 additions & 2 deletions web_src/js/features/copycontent.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {copyToClipboard} from './clipboard.js';
import {clippie} from 'clippie';
import {showTemporaryTooltip} from '../modules/tippy.js';
import {convertImage} from '../utils.js';

const {i18n} = window.config;

async function doCopy(content, btn) {
const success = await copyToClipboard(content);
const success = await clippie(content);
showTemporaryTooltip(btn, success ? i18n.copy_success : i18n.copy_error);
}

Expand Down
4 changes: 2 additions & 2 deletions web_src/js/features/repo-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import $ from 'jquery';
import {svg} from '../svg.js';
import {invertFileFolding} from './file-fold.js';
import {createTippy} from '../modules/tippy.js';
import {copyToClipboard} from './clipboard.js';
import {clippie} from 'clippie';
import {toAbsoluteUrl} from '../utils.js';

export const singleAnchorRegex = /^#(L|n)([1-9][0-9]*)$/;
Expand Down Expand Up @@ -190,7 +190,7 @@ export function initRepoCodeView() {
currentTarget.closest('tr').outerHTML = blob;
});
$(document).on('click', '.copy-line-permalink', async (e) => {
const success = await copyToClipboard(toAbsoluteUrl(e.currentTarget.getAttribute('data-url')));
const success = await clippie(toAbsoluteUrl(e.currentTarget.getAttribute('data-url')));
if (!success) return;
document.querySelector('.code-line-button')?._tippy?.hide();
});
Expand Down

0 comments on commit f5593d0

Please sign in to comment.