Google Docs Comment Toggler

Toggles comments (useful for word counts)

  1. // ==UserScript==
  2. // @name Google Docs Comment Toggler
  3. // @namespace www.arthaey.com
  4. // @description Toggles comments (useful for word counts)
  5. // @include https://docs.google.com/Doc?id=*
  6. // @include https://docs.google.com/Doc?docid=*
  7. //
  8. // Backed up from http://userscripts.org/scripts/review/36719
  9. // Last updated on 2009-08-17
  10. // @version 0.0.1.20140612212413
  11. // ==/UserScript==
  12.  
  13. window.addEventListener("load", function() {
  14.  
  15. // variables that are determined by Google (and thus may need to be updated)
  16. var EDITOR_FRAME_ID = "wys_frame";
  17. var toolbar = document.getElementById("editor-toolbar");
  18. var wordCountMenuItem = document.getElementById("m-wcount");
  19.  
  20. var BUTTON_CSS = "goog-toolbar-toggle-button goog-toolbar-button goog-inline-block";
  21. var BUTTON_OUTER_CSS = "goog-toolbar-button-outer-box goog-inline-block";
  22. var BUTTON_INNER_CSS = "goog-toolbar-button-inner-box goog-inline-block";
  23.  
  24. var BUTTON_SEPARATOR_HTML = "<div id=':t' class='goog-toolbar-separator goog-inline-block' style='-moz-user-select: none;' role='separator'> </div>";
  25.  
  26. var MENU_ITEM_CSS = "writely-menubar-item goog-menuitem";
  27. var MENU_CONTENT_CSS = "goog-menuitem-content";
  28.  
  29. var COMMENTS_ONLY_XPATH = "//span[@class='writely-comment']";
  30. var COMMENTS_H3_XPATH = "//span[@class='writely-comment'] | //h3 | //h4 | //h5";
  31. var COMMENTS_H2_XPATH = "//span[@class='writely-comment'] | //h2 | //h3 | //h4 | //h5";
  32.  
  33. // save references to toolbar buttons and menu items that will be created
  34. var BUTTONS = [];
  35. var MENU_ITEMS = [];
  36.  
  37. function toggleComments(xpath, triggerElement) {
  38. var editorFrame = document.getElementById(EDITOR_FRAME_ID);
  39. if (!editorFrame)
  40. return;
  41.  
  42. var editorDocument = editorFrame.contentDocument;
  43. if (!editorDocument)
  44. return;
  45.  
  46. var comments = editorDocument.evaluate(
  47. xpath,
  48. editorDocument,
  49. null,
  50. XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
  51. null
  52. );
  53.  
  54. var hidden = false;
  55. for (var i = 0; i < comments.snapshotLength; i++) {
  56. var comment = comments.snapshotItem(i);
  57.  
  58. if (comment.innerHTML) {
  59. if (!comment.title) // never clobber a non-empty title!
  60. comment.title = comment.innerHTML;
  61. comment.innerHTML = '';
  62. comment.style.display = "none";
  63. hidden = true;
  64. }
  65. else {
  66. comment.innerHTML = comment.title;
  67. comment.title = '';
  68. comment.style.display = "";
  69. }
  70. }
  71.  
  72. // rename toolbar buttons
  73. var button;
  74. for (var i = 0; i < BUTTONS.length; i++ ) {
  75. button = BUTTONS[i];
  76. if (hidden) {
  77. button.textContent = button.textContent.replace(/Hide/, "Show");
  78. }
  79. else {
  80. button.textContent = button.textContent.replace(/Show/, "Hide");
  81. }
  82. button.title = button.textContent;
  83. }
  84.  
  85. // rename menu items
  86. var menuItem;
  87. for (var i = 0; i < MENU_ITEMS.length; i++ ) {
  88. menuItem = MENU_ITEMS[i];
  89. if (hidden) {
  90. menuItem.textContent = menuItem.textContent.replace(/Hide/, "Show");
  91. }
  92. else {
  93. menuItem.textContent = menuItem.textContent.replace(/Show/, "Hide");
  94. }
  95. }
  96.  
  97. // toggle font weight of element
  98. var fontWeight = triggerElement.style.fontWeight;
  99. triggerElement.style.fontWeight = (fontWeight == "bold" ? "normal" : "bold");
  100. }
  101.  
  102. function insertAfter(anchorNode, newNode) {
  103. if (!anchorNode || !newNode) return;
  104. anchorNode.parentNode.insertBefore(newNode, anchorNode.nextSibling);
  105. }
  106.  
  107. function addGoogleDocsToolbarButtons() {
  108. var toolbar = document.getElementById("editor-toolbar");
  109. if (!toolbar) return;
  110.  
  111. var button = createGoogleDocsToolbarButton("Hide Comments", "toggleComments", COMMENTS_ONLY_XPATH);
  112. var buttonH3 = createGoogleDocsToolbarButton("+H3", "toggleCommentsH3", COMMENTS_H3_XPATH);
  113. var buttonH2 = createGoogleDocsToolbarButton("+H2", "toggleCommentsH2", COMMENTS_H2_XPATH);
  114.  
  115. insertAfter(toolbar.lastChild, button);
  116. insertAfter(toolbar.lastChild, buttonH3);
  117. insertAfter(toolbar.lastChild, buttonH2);
  118. }
  119.  
  120. function addGoogleDocsMenuItems() {
  121. var wordCountMenuItem = document.getElementById("m-wcount");
  122. if (!wordCountMenuItem) return;
  123.  
  124. var menuItem = createGoogleDocsMenuItem("Hide Comments", "m-togglecomments", COMMENTS_ONLY_XPATH);
  125. var menuItemH3 = createGoogleDocsMenuItem("Hide Comments + H3", "m-togglecomments-h3", COMMENTS_H3_XPATH);
  126. var menuItemH2 = createGoogleDocsMenuItem("Hide Comments + H2", "m-togglecomments-h2", COMMENTS_H2_XPATH);
  127.  
  128. MENU_ITEMS = [ menuItem, menuItemH3, menuItemH2 ];
  129.  
  130. insertAfter(wordCountMenuItem, menuItemH2);
  131. insertAfter(wordCountMenuItem, menuItemH3);
  132. insertAfter(wordCountMenuItem, menuItem);
  133. }
  134.  
  135. function createGoogleDocsToolbarButton(text, id, xpath) {
  136. // create all these elements DOM-wise because...
  137. var buttonDiv = document.createElement("div");
  138.  
  139. buttonDiv.id = id;
  140. buttonDiv.title = text;
  141. buttonDiv.className = BUTTON_CSS;
  142.  
  143. // attributes specific to Google Docs
  144. buttonDiv["aria-disabled"] = false;
  145. buttonDiv.role = "button";
  146.  
  147. var outerBox = document.createElement("div");
  148. outerBox.className = BUTTON_OUTER_CSS;
  149.  
  150. var innerBox = document.createElement("div");
  151. innerBox.className = BUTTON_INNER_CSS;
  152.  
  153. // ...we need to call addEventListener on the innermost div element
  154. var toggleButton = document.createElement("div");
  155. toggleButton.textContent = text;
  156. toggleButton.addEventListener("click", function() { toggleComments(xpath, toggleButton) }, true);
  157.  
  158. // add a separator to the end of the toolbar
  159. toolbar.innerHTML += BUTTON_SEPARATOR_HTML;
  160.  
  161. // compose and add the "Toggle Comments" button
  162. innerBox.appendChild(toggleButton);
  163. outerBox.appendChild(innerBox);
  164. buttonDiv.appendChild(outerBox);
  165.  
  166. BUTTONS.push(toggleButton);
  167. return buttonDiv;
  168. }
  169.  
  170. function createGoogleDocsMenuItem(text, id, xpath) {
  171. var toggleMenuItem = document.createElement("div");
  172.  
  173. toggleMenuItem.id = id;
  174. toggleMenuItem.className = MENU_ITEM_CSS;
  175.  
  176. var toggleContent = document.createElement("div");
  177. toggleContent.className = MENU_CONTENT_CSS;
  178.  
  179. toggleContent.appendChild(document.createTextNode(text));
  180. toggleMenuItem.appendChild(toggleContent);
  181.  
  182. // attributes specific to Google Docs
  183. toggleMenuItem.role = "menuitem";
  184. toggleMenuItem["aria-pressed"] = "false";
  185.  
  186. toggleMenuItem.addEventListener("click", function() { toggleComments(xpath, toggleContent) }, true);
  187.  
  188. MENU_ITEMS.push(toggleContent);
  189. return toggleMenuItem;
  190. }
  191.  
  192. function init() {
  193. addGoogleDocsToolbarButtons();
  194. addGoogleDocsMenuItems();
  195. }
  196.  
  197. init();
  198.  
  199. }, true);