index.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import deselectCurrent from './toggle-selection';
  2. const clipboardToIE11Formatting = {
  3. 'text/plain': 'Text',
  4. 'text/html': 'Url',
  5. default: 'Text'
  6. };
  7. const defaultMessage = 'Copy to clipboard: #{key}, Enter';
  8. function format(message) {
  9. const copyKey = (/mac os x/i.test(navigator.userAgent) ? '⌘' : 'Ctrl') + '+C';
  10. return message.replace(/#{\s*key\s*}/g, copyKey);
  11. }
  12. function copy(text, options) {
  13. let message,
  14. reselectPrevious,
  15. range,
  16. selection,
  17. mark,
  18. success = false;
  19. if (!options) {
  20. options = {};
  21. }
  22. const debug = options.debug || false;
  23. try {
  24. reselectPrevious = deselectCurrent();
  25. range = document.createRange();
  26. selection = document.getSelection();
  27. mark = document.createElement('span');
  28. mark.textContent = text;
  29. // reset user styles for span element
  30. mark.style.all = 'unset';
  31. // prevents scrolling to the end of the page
  32. mark.style.position = 'fixed';
  33. mark.style.top = 0;
  34. mark.style.clip = 'rect(0, 0, 0, 0)';
  35. // used to preserve spaces and line breaks
  36. mark.style.whiteSpace = 'pre';
  37. // do not inherit user-select (it may be `none`)
  38. mark.style.webkitUserSelect = 'text';
  39. mark.style.MozUserSelect = 'text';
  40. mark.style.msUserSelect = 'text';
  41. mark.style.userSelect = 'text';
  42. mark.addEventListener('copy', function (e) {
  43. e.stopPropagation();
  44. if (options.format) {
  45. e.preventDefault();
  46. if (typeof e.clipboardData === 'undefined') {
  47. // IE 11
  48. debug && console.warn('unable to use e.clipboardData');
  49. debug && console.warn('trying IE specific stuff');
  50. window.clipboardData.clearData();
  51. const format = clipboardToIE11Formatting[options.format] || clipboardToIE11Formatting['default'];
  52. window.clipboardData.setData(format, text);
  53. } else {
  54. // all other browsers
  55. e.clipboardData.clearData();
  56. e.clipboardData.setData(options.format, text);
  57. }
  58. }
  59. if (options.onCopy) {
  60. e.preventDefault();
  61. options.onCopy(e.clipboardData);
  62. }
  63. });
  64. document.body.appendChild(mark);
  65. range.selectNodeContents(mark);
  66. selection.addRange(range);
  67. const successful = document.execCommand('copy');
  68. if (!successful) {
  69. throw new Error('copy command was unsuccessful');
  70. }
  71. success = true;
  72. } catch (err) {
  73. debug && console.error('unable to copy using execCommand: ', err);
  74. debug && console.warn('trying IE specific stuff');
  75. try {
  76. window.clipboardData.setData(options.format || 'text', text);
  77. options.onCopy && options.onCopy(window.clipboardData);
  78. success = true;
  79. } catch (err) {
  80. debug && console.error('unable to copy using clipboardData: ', err);
  81. debug && console.error('falling back to prompt');
  82. message = format('message' in options ? options.message : defaultMessage);
  83. window.prompt(message, text);
  84. }
  85. } finally {
  86. if (selection) {
  87. if (typeof selection.removeRange == 'function') {
  88. selection.removeRange(range);
  89. } else {
  90. selection.removeAllRanges();
  91. }
  92. }
  93. if (mark) {
  94. document.body.removeChild(mark);
  95. }
  96. reselectPrevious();
  97. }
  98. return success;
  99. }
  100. export default copy;