Greasy Fork is available in English.

Laravel docs sidebar

Move the table of contents in laravel docs to a sidebar!

  1. // ==UserScript==
  2. // @name Laravel docs sidebar
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.1
  5. // @description Move the table of contents in laravel docs to a sidebar!
  6. // @author unoqaz
  7. // @match https://laravel.com/docs/*
  8. // @icon https://www.google.com/s2/favicons?domain=laravel.com
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. const ele= document.createElement('style');
  16. ele.type = 'text/css';
  17. ele.innerHTML = `
  18. @media only screen and (min-width: 1265px) {
  19. #main-content > ul { position: fixed; top: 33px; right: 15px; height: calc(100vh - 33px); overflow: auto; padding-right: 10px; width: 15vw; z-index: 999}
  20. ::-webkit-scrollbar { width: 10px; } ::-webkit-scrollbar-track { background: #f1f1f1; } ::-webkit-scrollbar-thumb { background: #888; } ::-webkit-scrollbar-thumb:hover { background: #555; }
  21. }
  22. html {
  23. scroll-behavior: smooth;
  24. }
  25. `;
  26. document.head.appendChild(ele);
  27.  
  28. // https://css-tricks.com/sticky-table-of-contents-with-scrolling-active-states/
  29. const observer = new IntersectionObserver(entries => {
  30. entries.some((entry, index, entries) => { //using some so that itteration can be stopped in the case that this IntersectionObserver callback is called when document has just rendered
  31. const id = entry.target.getAttribute('id');
  32. const sectionArray = [...document.querySelectorAll('h2[id],h3[id]')]
  33. const indexOfEntry = sectionArray.indexOf(entry.target)
  34.  
  35. const highlightMenuItem = function (id){
  36.  
  37. const menuItem = document.querySelector(`#main-content li a[href="#${id}"]`)
  38.  
  39. menuItem.style.setProperty('color', "rgba(255,124,117)", 'important')
  40.  
  41. if(menuItem.getBoundingClientRect().bottom > document.defaultView.innerHeight || (menuItem.getBoundingClientRect().y < 35)){
  42. var timer = null;
  43. const scrollMenuInView = function() {
  44. if(timer !== null) {
  45. clearTimeout(timer);
  46. }
  47. timer = setTimeout(function() {
  48. window.removeEventListener('scroll', scrollMenuInView)
  49. menuItem.scrollIntoView({behavior: "smooth", block: "center"})
  50. }, 111);
  51. }
  52. window.addEventListener('scroll', scrollMenuInView);
  53. }
  54. }
  55.  
  56. if (entry.isIntersecting){
  57. if (entry.boundingClientRect.top >= entry.rootBounds.top){// entry moving upward
  58. [...document.querySelectorAll('#main-content>ul li a[style]:not([style=""])')].forEach(item => {
  59. item.style.removeProperty('color')
  60. })
  61. }
  62.  
  63. highlightMenuItem(id)
  64. } else {
  65. if (entry.boundingClientRect.bottom >= entry.rootBounds.bottom){
  66. const idToHighlight = sectionArray[indexOfEntry - 1].id;
  67. [...document.querySelectorAll('#main-content>ul li a[style]:not([style=""])')].forEach(item => {
  68. item.style.removeProperty('color')
  69. })
  70. highlightMenuItem(idToHighlight)
  71. }
  72. if (entries.length === sectionArray.length) return true; // document just rendered so quit itteration.
  73. }
  74.  
  75. });
  76. }, {rootMargin: "-144px 0px -55% 0px"});
  77.  
  78. document.querySelectorAll('h2[id],h3[id]').forEach((section) => {
  79. const id = section?.id
  80. if (id && document.querySelector(`#main-content li a[href="#${id}"]`)) {
  81. observer.observe(section);
  82. }
  83. });
  84.  
  85. })();