Hacker News - Folding Subtrees

Fold and unfold arbitrary comment subtrees.

当前为 2015-09-17 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Hacker News - Folding Subtrees
  3. // @namespace thoughtnoise.net
  4. // @description Fold and unfold arbitrary comment subtrees.
  5. // @include https://news.ycombinator.com/item*
  6. // @version 1.0
  7. // @grant none
  8. // ==/UserScript==
  9.  
  10. (function () {
  11. var nesting_width = 40;
  12. var post_selector = '.athing';
  13. var indent_selector = '.ind';
  14. var header_selector = '.default div:nth-child(1)';
  15. var votebox_selector = 'tr td:nth-child(2)';
  16. var style_r90 = ".rotate90 { transform: rotate(90deg); }";
  17. var style_r270 = ".rotate270 { transform: rotate(270deg); }";
  18. var style_foldunfold = ".foldunfoldbtn { position: relative; top: -1px; }";
  19. var style_fold = '.foldbtn { opacity: 0.5; }';
  20. var style_unfold = '.unfoldbtn { opacity: 0.7; }';
  21. var style_ctlbox = '.foldctlbox { position: absolute; padding-left: 0.5em; }';
  22. var style_list = [style_r90, style_r270, style_foldunfold, style_fold, style_unfold, style_ctlbox];
  23. var extra_style_sheet = document.createElement('style');
  24. extra_style_sheet.type = 'text/css';
  25. extra_style_sheet.appendChild(document.createTextNode(style_list.join("\n")));
  26. var head = document.querySelector('head');
  27. head.appendChild(extra_style_sheet);
  28. var foldified_count = 0;
  29. function hide (el) {
  30. el.style.display = 'none';
  31. }
  32.  
  33. function show_element (el, mode) {
  34. if (el) {
  35. el.style.display = mode;
  36. }
  37. }
  38.  
  39. function show_block (el) { show_element(el, 'block' ); }
  40. function show_inline (el) { show_element(el, 'inline' ); }
  41. function show_inline_block (el) { show_element(el, 'inline-block'); }
  42.  
  43. function set_toggle_button_fold (btn) {
  44. btn.classList.add('foldbtn');
  45. btn.classList.add('rotate90');
  46. btn.classList.remove('unfoldbtn');
  47. btn.classList.remove('rotate270');
  48. }
  49. function set_toggle_button_unfold (btn) {
  50. btn.classList.remove('foldbtn');
  51. btn.classList.remove('rotate90');
  52. btn.classList.add('unfoldbtn');
  53. btn.classList.add('rotate270');
  54. }
  55.  
  56. function make_toggle_button (btn_type, rotation_class) {
  57. var btn = document.createElement('div');
  58. btn.classList.add('votearrow');
  59. btn.classList.add('foldunfoldbtn');
  60. set_toggle_button_fold(btn);
  61. show_inline_block(btn);
  62. return btn;
  63. }
  64. function each_subtree_post (post, func) {
  65. if (!post.hasOwnProperty('indent_width')) { return; }
  66.  
  67. var width = post.indent_width || 0;
  68. post = post.nextElementSibling;
  69.  
  70. while (post && post.hasOwnProperty('indent_width') && (post.indent_width > width)) {
  71. func(post);
  72. post = post.nextElementSibling;
  73. }
  74. }
  75.  
  76. function foldify_post(post_el, idx) {
  77. var ind_el = post_el.querySelector(indent_selector);
  78. if (!ind_el) { return; }
  79.  
  80. var spacer_img = ind_el.firstChild;
  81. if (!spacer_img) { return; }
  82. post_el.indent_width = spacer_img.width;
  83. var header_el = post_el.querySelector(header_selector);
  84. var votebox_el = post_el.querySelector(votebox_selector);
  85. var votepad_el = null;
  86. var body_br_el = null;
  87. var body_comment_el = null;
  88. var body_pad_el = null;
  89. if (header_el) {
  90. votepad_el = document.createElement('span');
  91. votepad_el.style.display = 'none';
  92.  
  93. body_pad_el = document.createElement('div');
  94. body_pad_el.classList.add('comment');
  95.  
  96. if (votebox_el) {
  97. var icon_width = votebox_el.clientWidth;
  98. votepad_el.style.width = icon_width;
  99. body_pad_el.style.width = '' + (header_el.clientWidth + icon_width) + 'px';
  100. }
  101. header_el.insertBefore(votepad_el, header_el.firstChild);
  102.  
  103. body_br_el = header_el.parentElement.children[1];
  104. body_comment_el = header_el.parentElement.children[2];
  105. header_el.parentElement.appendChild(body_pad_el);
  106. }
  107. var toggle_btn = make_toggle_button();
  108. post_el.fold_self = function () {
  109. post_el.is_folded = true;
  110.  
  111. set_toggle_button_unfold(toggle_btn);
  112. hide(votebox_el);
  113. show_inline_block(votepad_el);
  114. hide(body_br_el);
  115. hide(body_comment_el);
  116. show_block(body_pad_el);
  117. };
  118. post_el.unfold_self = function () {
  119. post_el.is_folded = false;
  120.  
  121. set_toggle_button_fold(toggle_btn);
  122. show_block(votebox_el);
  123. hide(votepad_el);
  124. show_inline(body_br_el);
  125. show_block(body_comment_el);
  126. hide(body_pad_el);
  127. };
  128. post_el.fold_subtree = function () {
  129. each_subtree_post(post_el, function (post) { post.fold_self(); });
  130. };
  131. post_el.unfold_subtree = function () {
  132. each_subtree_post(post_el, function (post) { post.unfold_self(); });
  133. };
  134.  
  135. post_el.fold = function () {
  136. post_el.fold_self();
  137. post_el.fold_subtree();
  138. };
  139. post_el.unfold = function () {
  140. post_el.unfold_self();
  141. post_el.unfold_subtree();
  142. };
  143. post_el.is_folded = false;
  144. post_el.toggle_fold = function () {
  145. if (post_el.is_folded) {
  146. post_el.unfold();
  147. } else {
  148. post_el.fold();
  149. }
  150. };
  151.  
  152. var toggle_event = function (event) {
  153. post_el.toggle_fold();
  154. };
  155. toggle_btn.addEventListener('click', toggle_event, false);
  156.  
  157. var ctl_box = document.createElement('div');
  158. ctl_box.classList.add('foldctlbox');
  159. ctl_box.appendChild(toggle_btn);
  160. show_inline_block(ctl_box);
  161. header_el.appendChild(ctl_box);
  162. foldified_count = foldified_count + 1;
  163. }
  164. function setup_posts () {
  165. var posts = document.querySelectorAll(post_selector);
  166. /*console.log('found ' + posts.length + ' posts');*/
  167. if (posts) {
  168. Array.prototype.forEach.call(posts, foldify_post);
  169. }
  170. }
  171. setup_posts();
  172. /*console.log("foldified " + foldified_count + ' posts');*/
  173. })();