Greasy Fork镜像 还支持 简体中文。

Workflowy computable values

Compute things with sublists and display values on an item name.

目前為 2016-08-18 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/22313/142428/Workflowy%20computable%20values.js

  1. var parseSelector = window.Parser.parse
  2.  
  3. window.funcs = []
  4. window.nodeCache = {}
  5. var observer
  6.  
  7. // observe dom mutations to make it run every time an item is opened / closed
  8. function start () {
  9. GM_addStyle(`
  10. .project .content {
  11. display: inline-block !important;
  12. padding-right: 10px;
  13. }
  14.  
  15. .project .result {
  16. display: inline;
  17. color: blue;
  18. margin-left: 10px;
  19. }
  20. `)
  21.  
  22.  
  23. document.body.addEventListener('click', function (e) {
  24. if (e.target.id === 'expandButton') {
  25. let restrictTo = e.target.parentNode.parentNode.parentNode.getAttribute('projectid')
  26. setTimeout(function () {
  27. itemOpenedOrClosed(restrictTo)
  28. }, 1000)
  29. }
  30. })
  31.  
  32. itemOpenedOrClosed()
  33. }
  34.  
  35. function itemOpenedOrClosed (restrictTo) {
  36. for (let i = 0; i < funcs.length; i++) {
  37. let script = funcs[i]
  38. execScript(script, restrictTo)
  39. }
  40. }
  41.  
  42. function execScript ({script, selector, id, color}, restrictTo) {
  43. let items = findItems(selector)
  44. for (let i = 0; i < items.length; i++) {
  45. let item = items[i]
  46. if (restrictTo && item.getAttribute('projectid') !== restrictTo) {
  47. continue
  48. }
  49. execForItem(item, script, id, color)
  50. }
  51. }
  52.  
  53. function execForItem (item, fun, id, color) {
  54. var children = []
  55. let par = item.querySelector('.children')
  56. for (let p = 0; p < par.children.length; p++) {
  57. if (par.children[p].classList.contains('project')) {
  58. children.push(par.children[p])
  59. }
  60. }
  61.  
  62. var args = []
  63. for (let i = 0; i < children.length; i++) {
  64. let child = children[i]
  65. arg = nodeToArg(child)
  66. args.push(arg)
  67. }
  68.  
  69. var result = item.querySelector('.result.script-' + id)
  70. if (!result) {
  71. let content = item.querySelector('.name .content')
  72. result = document.createElement('span')
  73. result.className = 'result script-' + id
  74. result.title = id
  75. result.style.color = color
  76. content.parentNode.insertBefore(result, content.nextSibling)
  77. }
  78. let resultvalue = fun(args, nodeToArg(item))
  79. result.innerHTML = (resultvalue || '').toString()
  80. }
  81.  
  82. function nodeToArg (node) {
  83. let name = node.querySelector('.name .content').innerText.trim()
  84. let note = node.querySelector('.notes').innerText.trim()
  85.  
  86. var arg = {name, note}
  87.  
  88. let results = node.querySelector('.name').querySelectorAll('.result')
  89. for (let r = 0; r < results.length; r++) {
  90. let result = results[r]
  91. arg[result.classList.item(1)] = result.innerText.trim()
  92. }
  93.  
  94. return arg
  95. }
  96.  
  97. function findItems (selector) {
  98. let parsed = parseSelector(selector)
  99. var items = null
  100. for (let l = 0; l < parsed.length; l++) {
  101. let layer = parsed[l]
  102. items = select(layer, items)
  103. }
  104. return items || []
  105. }
  106.  
  107. function select (layer, base) {
  108. if (!base) {
  109. base = document.querySelectorAll('.mainTreeRoot')
  110. }
  111.  
  112. let [connector, selector] = layer
  113. return getChildren(base, selector, connector === 'directchild')
  114. }
  115.  
  116. function getChildren (base, selector, onlydirect=false) {
  117. var filter
  118. switch (selector.type) {
  119. case 'id':
  120. filter = node =>
  121. node.getAttribute('projectid') === selector.val ||
  122. node.querySelector('.bullet').href.split('#/')[1] === selector.val
  123. break
  124. case 'regex':
  125. filter = node =>
  126. node.querySelector('.name .content').innerText.search(selector.val) !== -1
  127. break
  128. case 'name':
  129. filter = node =>
  130. node.querySelector('.name .content').innerText.trim() === selector.val
  131. break
  132. case 'any':
  133. filter = () => true
  134. break
  135. default:
  136. throw new Error('INVALID SELECTOR: ', selector)
  137. }
  138.  
  139. var children = []
  140. for (let i = 0; i < base.length; i++) {
  141. if (onlydirect) {
  142. let par = base[i].querySelector('.children')
  143. for (let p = 0; p < par.children.length; p++) {
  144. if (par.children[p].classList.contains('project') && par.children[p].classList.contains('open')) {
  145. children.push(par.children[p])
  146. }
  147. }
  148. } else {
  149. let all = base[i].querySelectorAll('.children > .project.open')
  150. for (let i = 0; i < all.length; i++) {
  151. children.push(all[i])
  152. }
  153. }
  154. }
  155.  
  156. return children.filter(filter)
  157. }
  158.  
  159. function registerScript (s) {
  160. funcs.push(s)
  161. }
  162.  
  163. function waitFor (selector, callback) {
  164. let res = document.querySelector(selector)
  165. if (res) return callback()
  166.  
  167. setTimeout(() => {
  168. waitFor(selector, callback)
  169. }, 1000)
  170. }

QingJ © 2025

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