GitHub Toggle Expanders

A userscript that toggles all expanders when one expander is shift-clicked

  1. // ==UserScript==
  2. // @name GitHub Toggle Expanders
  3. // @version 2.1.0
  4. // @description A userscript that toggles all expanders when one expander is shift-clicked
  5. // @license MIT
  6. // @author Rob Garrison
  7. // @namespace https://github.com/Mottie
  8. // @match https://github.com/*
  9. // @run-at document-idle
  10. // @require https://greasyfork.org/scripts/398877-utils-js/code/utilsjs.js?version=1079637
  11. // @icon https://github.githubassets.com/pinned-octocat.svg
  12. // @supportURL https://github.com/Mottie/GitHub-userscripts/issues
  13. // ==/UserScript==
  14.  
  15. (() => {
  16. /* global $ $$ on */
  17. "use strict";
  18.  
  19. // Commit history toggle
  20. // https://github.com/torvalds/linux/commits/master
  21. function toggleButton(el, modKey) {
  22. const stateNode = el.closest(".js-details-container");
  23. const state = stateNode && (
  24. // Resolved expander
  25. stateNode.classList.contains("open") ||
  26. // compare detail expander
  27. stateNode.classList.contains("Details--on")
  28. );
  29. const parentNode = stateNode && stateNode.closest(modKey
  30. // shift+ctrl+click = expand all on page
  31. ?
  32. ".repository-content"
  33. // shift+click = expand all in date
  34. :
  35. ".Box--condensed"
  36. );
  37.  
  38. if (parentNode) {
  39. const containers = parentNode.querySelectorAll(".js-details-container");
  40. [...containers].forEach(node => {
  41. node.classList.toggle("open", state);
  42. node.classList.toggle("Details--on", state);
  43. });
  44. }
  45. }
  46.  
  47. // Toggle resolved/outdated comments
  48. // https://github.com/PowerShell/PowerShell/pull/18210
  49. function toggleDetails(el, modKey) {
  50. // clicked button has the previous state
  51. const state = el && el.classList.contains("Details-content--closed");
  52. const parentNode = el.closest(modKey
  53. // shift+ctrl+click = expand all on page
  54. ?
  55. ".js-discussion"
  56. // shift+click = expand all in date
  57. :
  58. ".js-timeline-item"
  59. );
  60.  
  61. if (parentNode) {
  62. $$("turbo-frame", parentNode).forEach(node => {
  63. const details = $("details", node);
  64. if (state) {
  65. details.setAttribute("open", state);
  66. } else {
  67. details.removeAttribute("open");
  68. }
  69. });
  70. }
  71. }
  72.  
  73. on($("body"), "click", event => {
  74. const target = event.target;
  75. const mod = event.ctrlKey ||
  76. event.metaKey ||
  77. window.location.pathname.includes("/compare/");
  78.  
  79. if (target && event.getModifierState("Shift")) {
  80. // give GitHub time to update the elements
  81. setTimeout(() => {
  82. if (target.matches(".js-details-target")) {
  83. toggleButton(target, mod);
  84. } else if (
  85. target.matches(".Details-content--closed, .Details-content--open")
  86. ) {
  87. toggleDetails(target, mod);
  88. }
  89. }, 100);
  90. }
  91. });
  92.  
  93. })();