Trello Copy

Trello 功能擴充

  1. // ==UserScript==
  2. // @name Trello Copy
  3. // @namespace 1207bd0a-0252-4c8d-9134-d40ac51e4248
  4. // @match https://trello.com/*
  5. // @grant none
  6. // @version 1.0.0
  7. // @author Rick0
  8. // @description Trello 功能擴充
  9. // @require https://unpkg.com/clipboard@2/dist/clipboard.min.js
  10. // ==/UserScript==
  11.  
  12. // == class ==
  13.  
  14. class Card {
  15. url = location.href.match(/(https?:\/\/.+)\//)[1]
  16. title () {
  17. return document.querySelector('.mod-card-back-title.js-card-detail-title-input').value
  18. }
  19. // description = document.querySelector('.description-title > .u-inline-block')
  20. // headerIcon = document.querySelector('.window-header-icon')
  21. // header = document.querySelector('.window-header')
  22. }
  23.  
  24. // == global function ==
  25.  
  26. function setCSS(src) {
  27. let stylesheet = createNode(`<link rel="stylesheet" type="text/css" href="${src}">`)
  28. document.head.appendChild(stylesheet)
  29. }
  30.  
  31. function setClipboardJS() {
  32. copyButton = createNode(`<button class="oneCopy"></button>`)
  33. document.body.appendChild(copyButton)
  34. new ClipboardJS('.oneCopy')
  35. }
  36.  
  37. function setClipboard (text) {
  38. copyButton.setAttribute('data-clipboard-text', text)
  39. copyButton.click()
  40. }
  41.  
  42. function createNode(html) {
  43. let template = document.createElement('template')
  44. template.innerHTML = html
  45. return template.content.firstChild
  46. }
  47.  
  48. function createButton (buttonName, eventName, callback) {
  49. let button = createNode(`<div><a class="button subtle" href="javascript:void(0)">${buttonName}</a></div>`)
  50. let link = button.querySelector('a')
  51.  
  52. link.addEventListener(eventName, callback)
  53.  
  54. return button
  55. }
  56.  
  57. function createCopyButton (buttonName, text) {
  58. return createButton(buttonName, 'click', function () {
  59. setClipboard(text)
  60. })
  61. }
  62.  
  63. // == global var ==
  64.  
  65.  
  66.  
  67. // == program start ==
  68.  
  69. // setCSS('https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.2/animate.css')
  70. setClipboardJS()
  71.  
  72. let observer = new MutationObserver(function () {
  73. let isCardDeatilMode = (location.pathname.slice(1, 2) === 'c')
  74. if (isCardDeatilMode) {
  75. let card = new Card()
  76.  
  77. let tagArea = document.querySelector('.window-main-col>.card-detail-data')
  78. let copyArea = createNode(`<div class="window-module-title window-module-title-no-divider description-title"><span class="icon-copy icon-lg window-module-title-icon"></span><h3 class="u-inline-block">複製</h3></div>`)
  79. let titleCopyButton = createButton('標題', 'click', function () {
  80. setClipboard(card.title())
  81. })
  82. let urlCopyButton = createCopyButton('網址', card.url)
  83. let recordCopyButton = createButton('專案紀錄', 'click', function () {
  84. setClipboard(`=HYPERLINK("${card.url}","${card.title().replace(/"/g, '\"\"')}")`)
  85. })
  86.  
  87. ;[
  88. titleCopyButton,
  89. urlCopyButton,
  90. recordCopyButton,
  91. ]
  92. .forEach(button => {
  93. copyArea.appendChild(button)
  94. })
  95. tagArea.insertAdjacentElement('afterend', copyArea)
  96. }
  97. })
  98. observer.observe(document.body, {
  99. attributeFilter: ['class'],
  100. })

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址