debian-mirror-gitlab/app/assets/javascripts/behaviors/copy_to_clipboard.js

112 lines
3.4 KiB
JavaScript
Raw Normal View History

2022-03-02 08:16:31 +05:30
import ClipboardJS from 'clipboard';
2021-03-11 19:13:27 +05:30
import $ from 'jquery';
2022-03-02 08:16:31 +05:30
import { parseBoolean } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
import { fixTitle, add, show, hide, once } from '~/tooltips';
const CLIPBOARD_SUCCESS_EVENT = 'clipboard-success';
const CLIPBOARD_ERROR_EVENT = 'clipboard-error';
const I18N_ERROR_MESSAGE = __('Copy failed. Please manually copy the value.');
2018-03-17 18:26:18 +05:30
function showTooltip(target, title) {
2021-04-17 20:07:23 +05:30
const { title: originalTitle } = target.dataset;
once('hidden', (tooltip) => {
if (tooltip.target === target) {
2021-01-03 14:25:43 +05:30
target.setAttribute('title', originalTitle);
2022-03-02 08:16:31 +05:30
target.setAttribute('aria-label', originalTitle);
2021-01-03 14:25:43 +05:30
fixTitle(target);
2021-04-17 20:07:23 +05:30
}
});
2021-01-03 14:25:43 +05:30
target.setAttribute('title', title);
2022-03-02 08:16:31 +05:30
target.setAttribute('aria-label', title);
2021-01-03 14:25:43 +05:30
fixTitle(target);
show(target);
2022-03-02 08:16:31 +05:30
setTimeout(() => {
hide(target);
}, 1000);
2018-03-17 18:26:18 +05:30
}
function genericSuccess(e) {
2022-03-02 08:16:31 +05:30
// Clear the selection
2018-03-17 18:26:18 +05:30
e.clearSelection();
2022-03-02 08:16:31 +05:30
e.trigger.focus();
e.trigger.dispatchEvent(new Event(CLIPBOARD_SUCCESS_EVENT));
const { clipboardHandleTooltip = true } = e.trigger.dataset;
if (parseBoolean(clipboardHandleTooltip)) {
// Update tooltip
showTooltip(e.trigger, __('Copied'));
}
2018-03-17 18:26:18 +05:30
}
/**
* Safari > 10 doesn't support `execCommand`, so instead we inform the user to copy manually.
* See http://clipboardjs.com/#browser-support
*/
function genericError(e) {
2022-03-02 08:16:31 +05:30
e.trigger.dispatchEvent(new Event(CLIPBOARD_ERROR_EVENT));
const { clipboardHandleTooltip = true } = e.trigger.dataset;
if (parseBoolean(clipboardHandleTooltip)) {
showTooltip(e.trigger, I18N_ERROR_MESSAGE);
2018-03-17 18:26:18 +05:30
}
}
export default function initCopyToClipboard() {
2022-03-02 08:16:31 +05:30
const clipboard = new ClipboardJS('[data-clipboard-target], [data-clipboard-text]');
2018-03-17 18:26:18 +05:30
clipboard.on('success', genericSuccess);
clipboard.on('error', genericError);
/**
* This a workaround around ClipboardJS limitations to allow the context-specific copy/pasting
* of plain text or GFM. The Ruby `clipboard_button` helper sneaks a JSON hash with `text` and
* `gfm` keys into the `data-clipboard-text` attribute that ClipboardJS reads from.
* When ClipboardJS creates a new `textarea` (directly inside `body`, with a `readonly`
* attribute`), sets its value to the value of this data attribute, focusses on it, and finally
* programmatically issues the 'Copy' command, this code intercepts the copy command/event at
* the last minute to deconstruct this JSON hash and set the `text/plain` and `text/x-gfm` copy
* data types to the intended values.
*/
2021-03-08 18:12:59 +05:30
$(document).on('copy', 'body > textarea[readonly]', (e) => {
2018-11-08 19:23:39 +05:30
const { clipboardData } = e.originalEvent;
2018-03-17 18:26:18 +05:30
if (!clipboardData) return;
const text = e.target.value;
let json;
try {
json = JSON.parse(text);
} catch (ex) {
return;
}
if (!json.text || !json.gfm) return;
e.preventDefault();
clipboardData.setData('text/plain', json.text);
clipboardData.setData('text/x-gfm', json.gfm);
});
2022-03-02 08:16:31 +05:30
return clipboard;
2018-03-17 18:26:18 +05:30
}
2021-01-29 00:20:46 +05:30
/**
* Programmatically triggers a click event on a
* "copy to clipboard" button, causing its
* contents to be copied. Handles some of the messiniess
* around managing the button's tooltip.
* @param {HTMLElement} btnElement
*/
export function clickCopyToClipboardButton(btnElement) {
// Ensure the button has already been tooltip'd.
2021-04-17 20:07:23 +05:30
add([btnElement], { show: true });
2021-01-29 00:20:46 +05:30
btnElement.click();
}
2022-03-02 08:16:31 +05:30
export { CLIPBOARD_SUCCESS_EVENT, CLIPBOARD_ERROR_EVENT, I18N_ERROR_MESSAGE };