Greasy Fork is available in English.

Workflowy computable values

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

بۇ قوليازمىنى بىۋاسىتە قاچىلاشقا بولمايدۇ. بۇ باشقا قوليازمىلارنىڭ ئىشلىتىشى ئۈچۈن تەمىنلەنگەن ئامبار بولۇپ، ئىشلىتىش ئۈچۈن مېتا كۆرسەتمىسىگە قىستۇرىدىغان كود: // @require https://update.greatest.deepsurf.us/scripts/22313/143441/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: 27px;
  13. }
  14.  
  15. .project .result {
  16. display: inline;
  17. color: blue;
  18. margin-left: 10px;
  19. }
  20. .project .result:first-child {
  21. margin-left: 0;
  22. }
  23. `)
  24.  
  25.  
  26. document.body.addEventListener('click', function (e) {
  27. if (e.target.id === 'expandButton') {
  28. setTimeout(itemOpenedOrClosed, 1000)
  29. }
  30. })
  31.  
  32. window.addEventListener('hashchange', throttle(itemOpenedOrClosed, 2000))
  33.  
  34. itemOpenedOrClosed()
  35. }
  36.  
  37. function throttle (callback, limit) {
  38. var wait = false
  39. return function () {
  40. if (!wait) {
  41. wait = true
  42. setTimeout(function () {
  43. callback.call()
  44. wait = false
  45. }, limit)
  46. }
  47. }
  48. }
  49.  
  50. function itemOpenedOrClosed () {
  51. for (let i = 0; i < funcs.length; i++) {
  52. let script = funcs[i]
  53. execScript(script)
  54. }
  55. }
  56.  
  57. function execScript ({script, selector, id, color}) {
  58. let items = findItems(selector)
  59. for (let i = 0; i < items.length; i++) {
  60. let item = items[i]
  61. execForItem(item, script, id, color)
  62. }
  63. }
  64.  
  65. function execForItem (item, fun, id, color) {
  66. var children = []
  67. let par = item.querySelector('.children')
  68. for (let p = 0; p < par.children.length; p++) {
  69. if (par.children[p].classList.contains('project')) {
  70. children.push(par.children[p])
  71. }
  72. }
  73.  
  74. var args = []
  75. for (let i = 0; i < children.length; i++) {
  76. let child = children[i]
  77. arg = nodeToArg(child)
  78. args.push(arg)
  79. }
  80.  
  81. var result = item.querySelector('.result.script-' + id)
  82. if (!result) {
  83. let content = item.querySelector('.name .content')
  84. result = document.createElement('span')
  85. result.className = 'result script-' + id
  86. result.title = id
  87. result.style.color = color
  88. content.parentNode.insertBefore(result, content.nextSibling)
  89. }
  90. let resultvalue = fun(args, nodeToArg(item))
  91. result.innerHTML = (resultvalue || '').toString()
  92. }
  93.  
  94. function nodeToArg (node) {
  95. let name = node.querySelector('.name .content').innerText.trim()
  96. let note = node.querySelector('.notes').innerText.trim()
  97.  
  98. var arg = {name, note}
  99.  
  100. let results = node.querySelector('.name').querySelectorAll('.result')
  101. for (let r = 0; r < results.length; r++) {
  102. let result = results[r]
  103. arg[result.classList.item(1)] = result.innerText.trim()
  104. }
  105.  
  106. return arg
  107. }
  108.  
  109. function findItems (selector) {
  110. let parsed = parseSelector(selector)
  111. var items = null
  112. for (let l = 0; l < parsed.length; l++) {
  113. let layer = parsed[l]
  114. items = select(layer, items)
  115. }
  116. return items || []
  117. }
  118.  
  119. function select (layer, base) {
  120. if (!base) {
  121. base = document.querySelectorAll('.mainTreeRoot')
  122. }
  123.  
  124. let [connector, selector] = layer
  125. return getChildren(base, selector, connector === 'directchild')
  126. }
  127.  
  128. function getChildren (base, selector, onlydirect=false) {
  129. var filter
  130. switch (selector.type) {
  131. case 'id':
  132. filter = node =>
  133. node.getAttribute('projectid') === selector.val ||
  134. node.querySelector('.bullet').href.split('#/')[1] === selector.val
  135. break
  136. case 'regex':
  137. filter = node =>
  138. node.querySelector('.name .content').innerText.search(selector.val) !== -1
  139. break
  140. case 'name':
  141. filter = node =>
  142. node.querySelector('.name .content').innerText.trim() === selector.val
  143. break
  144. case 'any':
  145. filter = () => true
  146. break
  147. default:
  148. throw new Error('INVALID SELECTOR: ', selector)
  149. }
  150.  
  151. var children = []
  152. for (let i = 0; i < base.length; i++) {
  153. if (onlydirect) {
  154. let par = base[i].querySelector('.children')
  155. for (let p = 0; p < par.children.length; p++) {
  156. if (par.children[p].classList.contains('project') && par.children[p].classList.contains('open')) {
  157. children.push(par.children[p])
  158. }
  159. }
  160. } else {
  161. let all = base[i].querySelectorAll('.children > .project.open')
  162. for (let i = 0; i < all.length; i++) {
  163. children.push(all[i])
  164. }
  165. }
  166. }
  167.  
  168. return children.filter(filter)
  169. }
  170.  
  171. function registerScript (s) {
  172. funcs.push(s)
  173. }
  174.  
  175. function waitFor (selector, callback) {
  176. let res = document.querySelector(selector)
  177. if (res) return callback()
  178.  
  179. setTimeout(() => {
  180. waitFor(selector, callback)
  181. }, 1000)
  182. }