Workflowy computable values

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

当前为 2016-08-18 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/22313/142557/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. setTimeout(itemOpenedOrClosed, 1000)
  26. }
  27. })
  28.  
  29. window.addEventListener('hashchange', function (e) {
  30. setTimeout(itemOpenedOrClosed, 1000)
  31. })
  32.  
  33. itemOpenedOrClosed()
  34. }
  35.  
  36. function itemOpenedOrClosed () {
  37. for (let i = 0; i < funcs.length; i++) {
  38. let script = funcs[i]
  39. execScript(script)
  40. }
  41. }
  42.  
  43. function execScript ({script, selector, id, color}) {
  44. let items = findItems(selector)
  45. for (let i = 0; i < items.length; i++) {
  46. let item = items[i]
  47. execForItem(item, script, id, color)
  48. }
  49. }
  50.  
  51. function execForItem (item, fun, id, color) {
  52. var children = []
  53. let par = item.querySelector('.children')
  54. for (let p = 0; p < par.children.length; p++) {
  55. if (par.children[p].classList.contains('project')) {
  56. children.push(par.children[p])
  57. }
  58. }
  59.  
  60. var args = []
  61. for (let i = 0; i < children.length; i++) {
  62. let child = children[i]
  63. arg = nodeToArg(child)
  64. args.push(arg)
  65. }
  66.  
  67. var result = item.querySelector('.result.script-' + id)
  68. if (!result) {
  69. let content = item.querySelector('.name .content')
  70. result = document.createElement('span')
  71. result.className = 'result script-' + id
  72. result.title = id
  73. result.style.color = color
  74. content.parentNode.insertBefore(result, content.nextSibling)
  75. }
  76. let resultvalue = fun(args, nodeToArg(item))
  77. result.innerHTML = (resultvalue || '').toString()
  78. }
  79.  
  80. function nodeToArg (node) {
  81. let name = node.querySelector('.name .content').innerText.trim()
  82. let note = node.querySelector('.notes').innerText.trim()
  83.  
  84. var arg = {name, note}
  85.  
  86. let results = node.querySelector('.name').querySelectorAll('.result')
  87. for (let r = 0; r < results.length; r++) {
  88. let result = results[r]
  89. arg[result.classList.item(1)] = result.innerText.trim()
  90. }
  91.  
  92. return arg
  93. }
  94.  
  95. function findItems (selector) {
  96. let parsed = parseSelector(selector)
  97. var items = null
  98. for (let l = 0; l < parsed.length; l++) {
  99. let layer = parsed[l]
  100. items = select(layer, items)
  101. }
  102. return items || []
  103. }
  104.  
  105. function select (layer, base) {
  106. if (!base) {
  107. base = document.querySelectorAll('.mainTreeRoot')
  108. }
  109.  
  110. let [connector, selector] = layer
  111. return getChildren(base, selector, connector === 'directchild')
  112. }
  113.  
  114. function getChildren (base, selector, onlydirect=false) {
  115. var filter
  116. switch (selector.type) {
  117. case 'id':
  118. filter = node =>
  119. node.getAttribute('projectid') === selector.val ||
  120. node.querySelector('.bullet').href.split('#/')[1] === selector.val
  121. break
  122. case 'regex':
  123. filter = node =>
  124. node.querySelector('.name .content').innerText.search(selector.val) !== -1
  125. break
  126. case 'name':
  127. filter = node =>
  128. node.querySelector('.name .content').innerText.trim() === selector.val
  129. break
  130. case 'any':
  131. filter = () => true
  132. break
  133. default:
  134. throw new Error('INVALID SELECTOR: ', selector)
  135. }
  136.  
  137. var children = []
  138. for (let i = 0; i < base.length; i++) {
  139. if (onlydirect) {
  140. let par = base[i].querySelector('.children')
  141. for (let p = 0; p < par.children.length; p++) {
  142. if (par.children[p].classList.contains('project') && par.children[p].classList.contains('open')) {
  143. children.push(par.children[p])
  144. }
  145. }
  146. } else {
  147. let all = base[i].querySelectorAll('.children > .project.open')
  148. for (let i = 0; i < all.length; i++) {
  149. children.push(all[i])
  150. }
  151. }
  152. }
  153.  
  154. return children.filter(filter)
  155. }
  156.  
  157. function registerScript (s) {
  158. funcs.push(s)
  159. }
  160.  
  161. function waitFor (selector, callback) {
  162. let res = document.querySelector(selector)
  163. if (res) return callback()
  164.  
  165. setTimeout(() => {
  166. waitFor(selector, callback)
  167. }, 1000)
  168. }

QingJ © 2025

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