copy-button.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. /**
  2. * Set up copy/paste for code blocks
  3. */
  4. const copySVG = `<svg aria-labelledby="title" aria-hidden="true" data-prefix="far" data-icon="copy" class="svg-inline--fa fa-copy fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
  5. <title id="title" lang="en">Copy code</title>
  6. <path fill="#777" d="M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"></path>
  7. </svg>`
  8. const clipboardButton = id =>
  9. `<a id="copy-button-${id}" class="btn copybtn o-tooltip--left" data-tooltip="Copy" data-clipboard-target="#${id}">
  10. ${copySVG}
  11. </a>`
  12. // Clears selected text since ClipboardJS will select the text when copying
  13. const clearSelection = () => {
  14. if (window.getSelection) {
  15. window.getSelection().removeAllRanges()
  16. } else if (document.selection) {
  17. document.selection.empty()
  18. }
  19. }
  20. // Changes tooltip text for two seconds, then changes it back
  21. const temporarilyChangeTooltip = (el, newText) => {
  22. const oldText = el.getAttribute('data-tooltip')
  23. el.setAttribute('data-tooltip', newText)
  24. setTimeout(() => el.setAttribute('data-tooltip', oldText), 2000)
  25. }
  26. const addCopyButtonToCodeCells = () => {
  27. // If ClipboardJS hasn't loaded, wait a bit and try again. This
  28. // happens because we load ClipboardJS asynchronously.
  29. if (window.ClipboardJS === undefined) {
  30. setTimeout(addCopyButtonToCodeCells, 250)
  31. return
  32. }
  33. pageElements['codeCells'].forEach((codeCell) => {
  34. const id = codeCell.getAttribute('id')
  35. if (document.getElementById("copy-button" + id) == null) {
  36. codeCell.insertAdjacentHTML('afterend', clipboardButton(id));
  37. }
  38. })
  39. const clipboard = new ClipboardJS('.copybtn')
  40. clipboard.on('success', event => {
  41. clearSelection()
  42. temporarilyChangeTooltip(event.trigger, 'Copied!')
  43. })
  44. clipboard.on('error', event => {
  45. temporarilyChangeTooltip(event.trigger, 'Failed to copy')
  46. })
  47. // Get rid of clipboard before the next page visit to avoid memory leak
  48. document.addEventListener('turbolinks:before-visit', () =>
  49. clipboard.destroy()
  50. )
  51. }
  52. initFunction(addCopyButtonToCodeCells);