Basecamp Keyword Highlighter

Highlights predefined list of keywords in the Basecamp task list at the beginning of task description

当前为 2017-02-14 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Basecamp Keyword Highlighter
  3. // @description Highlights predefined list of keywords in the Basecamp task list at the beginning of task description
  4. // @include https://*.basecamphq.com/projects/*/todo_lists
  5. // @grant none
  6. // @version 0.5.3
  7. // @namespace https://greasyfork.org/users/32141
  8. // ==/UserScript==
  9.  
  10. // Here you can add your own keywords:
  11. var keywordsColors = {
  12. // red
  13. 'bf0303': ['error', 'bug'],
  14.  
  15. // green
  16. '008c00': ['todo', 'feature'],
  17.  
  18. // purple
  19. '5a00b3': ['postponed'],
  20.  
  21. // pink
  22. 'cc00ba': ['high']
  23. };
  24.  
  25. function createKeywordStyles() {
  26. var color,
  27. style = document.createElement('style'),
  28. innerHtml = '.keyword {color: #fff; border-radius: 3px; padding: 0px 2px 0px 2px; }\n';
  29.  
  30. for (color in keywordsColors) {
  31. innerHtml += '.keyword-' + color + ' { background-color: #' + color + '; }\n';
  32. }
  33.  
  34. style.type = 'text/css';
  35. style.innerHTML = innerHtml;
  36.  
  37. document.getElementsByTagName('head')[0].appendChild(style);
  38. }
  39.  
  40. function processTodoLists(rootEl) {
  41. var el,
  42. child,
  43. color,
  44. regexps = {},
  45. keywords,
  46. tasksContent;
  47.  
  48. function getType(obj) {
  49. return Object.prototype.toString.call(obj).replace('[object ', '').replace(']', '').toLowerCase();
  50. }
  51.  
  52. function findElements(rootEl, tagName, param) {
  53. var result = [],
  54. elements = rootEl.getElementsByTagName(tagName),
  55. paramType = getType(param);
  56.  
  57. for (var i = 0; i < elements.length; i++) {
  58. if (paramType == 'string' && elements[i].id.indexOf(param) === 0) {
  59. result.push(elements[i]);
  60. } else if (paramType == 'regexp' && param.test(elements[i].id)) {
  61. result.push(elements[i]);
  62. }
  63. }
  64.  
  65. return result;
  66. }
  67.  
  68. function formatTask(el, color, word) {
  69. el.innerHTML = el.innerHTML.replace(word, '<span class="keyword keyword-' + color + '">' + word + '</span>');
  70. }
  71.  
  72. tasksContent = findElements(rootEl, 'span', /^item_wrap_/);
  73. for (var i = 0; i < tasksContent.length; i++) {
  74. el = tasksContent[i];
  75. child = el.firstChild;
  76.  
  77. if (child.nodeName && child.nodeName.toLowerCase() == 'span' &&
  78. child.classList && child.classList.contains('keyword')) {
  79. continue;
  80. }
  81.  
  82. var text = tasksContent[i].textContent;
  83. for (color in keywordsColors) {
  84. if (!keywordsColors.hasOwnProperty(color)) {
  85. continue;
  86. }
  87.  
  88. keywords = keywordsColors[color];
  89. if (!regexps[color]) {
  90. regexps[color] = new RegExp('^((?:' + keywords.join('|') + ')[^:^\s]*).*', 'i');
  91. }
  92.  
  93. var regexp = regexps[color];
  94. if (regexp.test(text)) {
  95. formatTask(tasksContent[i], color, regexp.exec(text)[1]);
  96. break;
  97. }
  98. }
  99. }
  100. }
  101.  
  102. createKeywordStyles();
  103.  
  104. document.observe("dom:modified", function(ev) {
  105. processTodoLists(ev.target);
  106. });
  107. processTodoLists(document);