🏠 Home 

Basecamp Keyword Highlighter

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


Install this script?
  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. // Here you can add your own keywords:
  10. var keywordsColors = {
  11. // red
  12. 'bf0303': ['error', 'bug'],
  13. // green
  14. '008c00': ['todo', 'feature'],
  15. // purple
  16. '5a00b3': ['postponed'],
  17. // pink
  18. 'cc00ba': ['high']
  19. };
  20. function createKeywordStyles() {
  21. var color,
  22. style = document.createElement('style'),
  23. innerHtml = '.keyword {color: #fff; border-radius: 3px; padding: 0px 2px 0px 2px; }\n';
  24. for (color in keywordsColors) {
  25. innerHtml += '.keyword-' + color + ' { background-color: #' + color + '; }\n';
  26. }
  27. style.type = 'text/css';
  28. style.innerHTML = innerHtml;
  29. document.getElementsByTagName('head')[0].appendChild(style);
  30. }
  31. function processTodoLists(rootEl) {
  32. var el,
  33. child,
  34. color,
  35. regexps = {},
  36. keywords,
  37. tasksContent;
  38. function getType(obj) {
  39. return Object.prototype.toString.call(obj).replace('[object ', '').replace(']', '').toLowerCase();
  40. }
  41. function findElements(rootEl, tagName, param) {
  42. var r###lt = [],
  43. elements = rootEl.getElementsByTagName(tagName),
  44. paramType = getType(param);
  45. for (var i = 0; i < elements.length; i++) {
  46. if (paramType == 'string' && elements[i].id.indexOf(param) === 0) {
  47. r###lt.push(elements[i]);
  48. } else if (paramType == 'regexp' && param.test(elements[i].id)) {
  49. r###lt.push(elements[i]);
  50. }
  51. }
  52. return r###lt;
  53. }
  54. function formatTask(el, color, word) {
  55. el.innerHTML = el.innerHTML.replace(word, '<span class="keyword keyword-' + color + '">' + word + '</span>');
  56. }
  57. tasksContent = findElements(rootEl, 'span', /^item_wrap_/);
  58. for (var i = 0; i < tasksContent.length; i++) {
  59. el = tasksContent[i];
  60. child = el.firstChild;
  61. if (child.nodeName && child.nodeName.toLowerCase() == 'span' &&
  62. child.classList && child.classList.contains('keyword')) {
  63. continue;
  64. }
  65. var text = tasksContent[i].textContent;
  66. for (color in keywordsColors) {
  67. if (!keywordsColors.hasOwnProperty(color)) {
  68. continue;
  69. }
  70. keywords = keywordsColors[color];
  71. if (!regexps[color]) {
  72. regexps[color] = new RegExp('^((?:' + keywords.join('|') + ')[^:^\s]*).*', 'i');
  73. }
  74. var regexp = regexps[color];
  75. if (regexp.test(text)) {
  76. formatTask(tasksContent[i], color, regexp.exec(text)[1]);
  77. break;
  78. }
  79. }
  80. }
  81. }
  82. createKeywordStyles();
  83. document.observe("dom:modified", function(ev) {
  84. processTodoLists(ev.target);
  85. });
  86. processTodoLists(document);