WikiIndent

Four visual improvements for Wikipedia (and other wikis): Indents sub-sections to make the layout clearer. Hides the sidebar (toggle by clicking the header). Floats the Table of Contents for access when scrolled. Converts heading underlines to overlines.

当前为 2016-11-20 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WikiIndent
  3. // @namespace joeytwiddle
  4. // @description Four visual improvements for Wikipedia (and other wikis): Indents sub-sections to make the layout clearer. Hides the sidebar (toggle by clicking the header). Floats the Table of Contents for access when scrolled. Converts heading underlines to overlines.
  5. // @downstreamURL http://userscripts.org/scripts/source/60832.user.js
  6. // @version 1.3.0
  7. // @include *wiki*
  8. // @include http://www.buzztard.com/*
  9. // @include http://encyclopediadramatica.com/*
  10. // @include http://www.wormus.com/leakytap/*
  11. // @include http://theinfosphere.org/*
  12. // @include http://rosettacode.org/mw/*
  13. // @grant GM_setValue
  14. // @grant GM_addStyle
  15. // @grant GM_getValue
  16. // @grant GM_log
  17. // ==/UserScript==
  18.  
  19. // Without this function wrapper, Mozilla Firefox rejects the whole script, because it sees the top-level 'return;' as invalid syntax!
  20.  
  21. (function(){
  22.  
  23. // Feature #1 : Make the sidebar collapsible so the page content can fill the whole width.
  24.  
  25. var toggleSidebar = true;
  26.  
  27. // Feature #2 : Float the TOC on the top-right of the screen, so it can still be used after scrolling down the page.
  28.  
  29. var makeTableOfContentsFloat = true;
  30.  
  31. // Feature #3 : Indent the blocks so their tree-like structure is visible.
  32.  
  33. var indentSubBlocks = true;
  34.  
  35. // Feature #4 : Change underlined headings to overlined headings. (So the lines separate the heading from the previous section, rather than separating the heading from its content.)
  36.  
  37. var fixUnderlinesToOverlines = true;
  38.  
  39.  
  40.  
  41. // var minimisedSidebarSize = 6; // Small
  42. var minimisedSidebarSize = 16;
  43.  
  44. // When opening the sidebar again, the transition displays the sidebar contents
  45. // before there is space for it, causing brief ugly overlap! So we delay
  46. // unhiding to look prettier.
  47. // CONSIDER: Perhaps this could look even smoother if the text appeared/disappeared using opacity.
  48. var delayHide = 0;
  49. var delayUnhide = ( document.getElementById("mw-panel") ? 250 : 0 );
  50.  
  51. var debug = false;
  52.  
  53.  
  54.  
  55. /* CONSIDER: As we scroll the page, light up the "current" section in the TOC.
  56. *
  57. * FIXED: One occasional problem with the TOC is when it is taller than the
  58. * window! (I usually work around this by zooming out (reducing font
  59. * size), but perhaps we can use CSS overflow to solve it properly.)
  60. *
  61. * TODO: Indentation was not working well in edit preview on Hwiki(MW).
  62. */
  63.  
  64. /* Changelog
  65. * 5/ 2/2012 - Better (though more fragile) click-to-toggle areas.
  66. * 3/ 1/2012 - Fixed Chrome compatibility so it works! Doh.
  67. * 23/ 3/2011 - Added Chrome compatibility.
  68. */
  69.  
  70. // Recent versions do not play nice together, so just in case we run WI twice:
  71. if (unsafeWindow.WikiIndent_loaded) {
  72. return;
  73. } else {
  74. unsafeWindow.WikiIndent_loaded = true;
  75. }
  76.  
  77. function log(x) {
  78. x = "[WI] "+x;
  79. if (this.GM_log) {
  80. this.GM_log(x);
  81. } else if (this.console && console.log) {
  82. console.log(x);
  83. } else {
  84. window.status = ""+x;
  85. // alert(x);
  86. }
  87. }
  88.  
  89. // For bookmarklets:
  90. if (typeof GM_addStyle == "undefined") {
  91. GM_addStyle = function(css) {
  92. var head, style;
  93. head = document.getElementsByTagName("head")[0];
  94. if (!head) { return; }
  95. style = document.createElement("style");
  96. style.type = "text/css";
  97. style.innerHTML = css;
  98. head.appendChild(style);
  99. };
  100. }
  101.  
  102. if (typeof GM_setValue == 'undefined' || window.navigator.vendor.match(/Google/)) {
  103. GM_log("WikiIndent: Adding fallback implementation of GM_set/getValue");
  104.  
  105. if (typeof localStorage == 'undefined') {
  106.  
  107. GM_getValue = function(name, defaultValue) {
  108. return defaultValue;
  109. };
  110.  
  111. } else {
  112.  
  113. GM_setValue = function(name, value) {
  114. value = (typeof value)[0] + value;
  115. localStorage.setItem(name, value);
  116. };
  117.  
  118. GM_getValue = function(name, defaultValue) {
  119. var value = localStorage.getItem(name);
  120. if (!value)
  121. return defaultValue;
  122. var type = value[0];
  123. value = value.substring(1);
  124. switch (type) {
  125. case 'b':
  126. return value == 'true';
  127. case 'n':
  128. return Number(value);
  129. default:
  130. return value;
  131. }
  132. };
  133.  
  134. }
  135.  
  136. }
  137.  
  138.  
  139.  
  140. // The following block is mirrored in table_of_contents_everyw.user.js
  141.  
  142. // See also: resetProps
  143. function clearStyle(elem) {
  144. // We set some crucial defaults, so we don't inherit CSS from the page:
  145. elem.style.display = 'inline';
  146. elem.style.position = 'static';
  147. elem.style.top = 'auto';
  148. elem.style.right = 'auto';
  149. elem.style.bottom = 'auto';
  150. elem.style.left = 'auto';
  151. //elem.style.color = 'black';
  152. //elem.style.backgroundColor = 'white';
  153. return elem;
  154. }
  155.  
  156. function newNode(tag,data) {
  157. var elem = document.createElement(tag);
  158. if (data) {
  159. for (var prop in data) {
  160. elem[prop] = data[prop];
  161. }
  162. }
  163. return elem;
  164. }
  165.  
  166. function newSpan(text) {
  167. return clearStyle(newNode("span",{textContent:text}));
  168. }
  169.  
  170. /*
  171. function addCloseButtonTo(where, toc) {
  172. var closeButton = newSpan("[X]");
  173. // closeButton.style.float = 'right';
  174. // closeButton.style.cssFloat = 'right'; // Firefox
  175. // closeButton.style.styleFloat = 'right'; // IE7
  176. closeButton.style.cursor = 'pointer';
  177. closeButton.style.paddingLeft = '5px';
  178. closeButton.onclick = function() { toc.parentNode.removeChild(toc); };
  179. closeButton.id = "closeTOC";
  180. where.appendChild(closeButton);
  181. }
  182. */
  183.  
  184. function addCloseButtonTo(where, toc) {
  185. var closeSpan = newNode("span");
  186. var closeLink = newNode("a",{textContent:"close"});
  187. closeLink.onclick = function() { toc.parentNode.removeChild(toc); };
  188. closeLink.id = "closeTOC";
  189. closeLink.style.cursor = 'pointer';
  190. closeSpan.appendChild(document.createTextNode("["));
  191. closeSpan.appendChild(closeLink);
  192. closeSpan.appendChild(document.createTextNode("]"));
  193. //closeSpan.style.paddingLeft = '5px';
  194. where.appendChild(closeSpan);
  195. }
  196.  
  197. function addHideButtonTo(toc, tocInner) {
  198. var rollupButton = newSpan("[hide]");
  199. // rollupButton.style.float = 'right';
  200. // rollupButton.style.cssFloat = 'right'; // Firefox
  201. // rollupButton.style.styleFloat = 'right'; // IE7
  202. rollupButton.style.cursor = 'pointer';
  203. rollupButton.style.paddingLeft = '10px';
  204. function toggleRollUp() {
  205. if (tocInner.style.display == 'none') {
  206. tocInner.style.display = '';
  207. rollupButton.textContent = "[hide]";
  208. } else {
  209. tocInner.style.display = 'none';
  210. rollupButton.textContent = "[show]";
  211. }
  212. setTimeout(function(){
  213. GM_setValue("WI_toc_rolledUp", tocInner.style.display=='none');
  214. },5);
  215. }
  216. rollupButton.onclick = toggleRollUp;
  217. rollupButton.id = "togglelink";
  218. toc.appendChild(rollupButton);
  219. if (GM_getValue("WI_toc_rolledUp",false)) {
  220. toggleRollUp();
  221. }
  222. }
  223.  
  224. function addButtonsConditionally(toc) {
  225.  
  226. function verbosely(fn) {
  227. return function() {
  228. // GM_log("[WI] Calling: "+fn+" with ",arguments);
  229. return fn.apply(this,arguments);
  230. };
  231. };
  232.  
  233. // Provide a hide/show toggle button if the TOC does not already have one.
  234.  
  235. // Wikimedia's toc element is actually a table. We must put the
  236. // buttons in the title div, if we can find it!
  237.  
  238. var tocTitle = document.getElementById("toctitle"); // Wikipedia
  239. tocTitle = tocTitle || toc.getElementsByTagName("h2")[0]; // Mozdev
  240. // tocTitle = tocTitle || toc.getElementsByTagName("div")[0]; // Fingers crossed for general
  241. tocTitle = tocTitle || toc.firstChild; // Fingers crossed for general
  242.  
  243. // Sometimes Wikimedia does not add a hide/show button (if the TOC is small).
  244. // We cannot test this immediately, because it gets loaded in later!
  245. function addButtonsNow() {
  246.  
  247. var hideShowButton = document.getElementById("togglelink");
  248. if (!hideShowButton) {
  249. var tocInner = toc.getElementsByTagName("ol")[0]; // Mozdev (can't get them all!)
  250. tocInner = tocInner || toc.getElementsByTagName("ul")[0]; // Wikipedia
  251. tocInner = tocInner || toc.getElementsByTagName("div")[0]; // Our own
  252. if (tocInner) {
  253. verbosely(addHideButtonTo)(tocTitle || toc, tocInner);
  254. }
  255. }
  256.  
  257. // We do this later, to ensure it appears on the right of
  258. // any existing [hide/show] button.
  259. if (document.getElementById("closeTOC") == null) {
  260. verbosely(addCloseButtonTo)(tocTitle || toc, toc);
  261. }
  262.  
  263. }
  264.  
  265. // Sometimes Wikimedia does not add a hide/show button (if the TOC is small).
  266. // We cannot test this immediately, because it gets loaded in later!
  267. if (document.location.href.indexOf("wiki") >= 0) {
  268. setTimeout(addButtonsNow,2000);
  269. } else {
  270. addButtonsNow();
  271. }
  272.  
  273. }
  274.  
  275. // End mirror.
  276.  
  277.  
  278.  
  279. // == Main == //
  280.  
  281. function doIt() {
  282.  
  283.  
  284.  
  285. //// Feature #1 : Hide the sidebar. Fullsize the content.
  286.  
  287. // Toggle the sidebar by clicking the "page background" (empty space outside
  288. // the main content). Sometimes clicking the content background is enough.
  289.  
  290. if (toggleSidebar) {
  291.  
  292. var content = document.getElementById("content")
  293. || document.getElementById("column-content");
  294. var sideBar = document.getElementById("column-one")
  295. || document.getElementById("panel")
  296. || /* WikiMedia: */ document.getElementById("mw-panel")
  297. || /* forgot: */ document.getElementById("jq-interiorNavigation")
  298. || /* pmwiki: */ document.getElementById('wikileft');
  299. var toToggle = [ document.getElementById("page-base"), document.getElementById("siteNotice"), document.getElementById("head") ];
  300. var cac = document.getElementById("p-cactions");
  301. var cacOldHome = ( cac ? cac.parentNode : null );
  302.  
  303. function toggleWikipediaSidebar(evt) {
  304.  
  305. // We don't want to act on all clicked body elements (notably not the WP
  306. // image). I detected two types of tag we wanted to click.
  307. /*if (!evt || evt.target.tagName == "UL" || evt.target.tagName == "DIV") {*/
  308.  
  309. // That was still activating on divs in the content! (Gaps between paragraphs.)
  310. // This only acts on the header area.
  311. var thisElementTogglesSidebar;
  312. var inStartup = (evt == null);
  313. if (inStartup) {
  314. thisElementTogglesSidebar = true;
  315. } else {
  316. var elem = evt.target;
  317. var clickedHeader = (elem.id == 'mw-head');
  318. // For wikia.com:
  319. clickedHeader |= (elem.id=="WikiHeader");
  320. // For Wikimedia:
  321. var clickedPanelBackground = elem.id == 'mw-panel' || elem.className.indexOf('portal')>=0;
  322. clickedPanelBackground |= elem.id == 'column-content'; // for beebwiki (old mediawiki?)
  323. // Hopefully for sites in general. Allow one level below body. Needed for Wikia's UL.
  324. var clickedAreaBelowSidebar = (elem.tagName == 'HTML' || elem.tagName == 'BODY');
  325. var clickedBackground = (elem.parentNode && elem.parentNode.tagName == "BODY");
  326. thisElementTogglesSidebar = clickedHeader || clickedPanelBackground || clickedAreaBelowSidebar || clickedBackground;
  327. }
  328. if (thisElementTogglesSidebar) {
  329.  
  330. if (evt)
  331. evt.preventDefault();
  332. if (debug) { GM_log("evt=",evt); }
  333. // if (evt) GM_log("evt.target.tagName="+evt.target.tagName);
  334. /* We put the GM_setValue calls on timers, so they won't slow down the rendering. */
  335. // Make the change animate smoothly:
  336. content.style.transition = 'all 150ms ease-in-out';
  337. if (sideBar) {
  338. if (sideBar.style.display == '') {
  339. // Wikipedia's column-one contains a lot of things we want to hide
  340. sideBar.style.display = 'none';
  341. if (content) {
  342. content.oldMarginLeft = content.style.marginLeft;
  343. content.style.marginLeft = minimisedSidebarSize+'px';
  344. }
  345. for (var i in toToggle) {
  346. if (toToggle[i]) { toToggle[i].style.display = 'none'; }
  347. }
  348. // but one of them we want to preserve
  349. // (the row of tools across the top):
  350. if (cac)
  351. sideBar.parentNode.insertBefore(cac,sideBar.nextSibling);
  352. setTimeout(function(){
  353. GM_setValue("sidebarVisible",false);
  354. },200);
  355. } else {
  356. function unhide() {
  357. sideBar.style.display = '';
  358. }
  359. setTimeout(unhide,delayUnhide);
  360. if (content) {
  361. content.style.marginLeft = content.oldMarginLeft;
  362. }
  363. for (var i in toToggle) {
  364. if (toToggle[i]) { toToggle[i].style.display = ''; }
  365. }
  366. if (cac && cacOldHome)
  367. cacOldHome.appendChild(cac); // almost back where it was :P
  368. setTimeout(function(){
  369. GM_setValue("sidebarVisible",true);
  370. },200);
  371. }
  372. }
  373.  
  374. }
  375. }
  376.  
  377. // log("sideBar="+sideBar+" and content="+content);
  378. if (sideBar) {
  379. // We need to watch window for clicks below sidebar (Chrome).
  380. document.documentElement.addEventListener('click',toggleWikipediaSidebar,false);
  381. } else {
  382. log("Did not have sideBar "+sideBar+" or content "+content); // @todo Better to warn or error?
  383. }
  384.  
  385. if (!GM_getValue("sidebarVisible",true)) {
  386. toggleWikipediaSidebar();
  387. }
  388.  
  389. // TODO: Make a toggle button for it!
  390.  
  391. // Fix for docs.jquery.com:
  392. /*
  393. var j = document.getElementById("jq-primaryContent");
  394. if (j) {
  395. j.style.setAttribute('display', 'block');
  396. j.style.setAttribute('float', 'none');
  397. j.style.setAttribute('width', '100%');
  398. }
  399. */
  400. GM_addStyle("#jq-primaryContent { display: block; float: none; width: 100%; }");
  401.  
  402. }
  403.  
  404.  
  405.  
  406. //// Feature #2: Make Table of Contents float
  407.  
  408. if (makeTableOfContentsFloat) {
  409.  
  410. /* @consider If the TOC has a "Hide/Show" link ("button") then we could
  411. * fire that instead of changing opacity.
  412. */
  413.  
  414. // document.getElementById('column-one').appendChild(document.getElementById('toc'));
  415.  
  416. // createFader basically worked but was a little bit buggy. (Unless the bugs were caused by conflict with other TOC script.)
  417. // Anyway createFader() has now been deprecated in favour of CSS :hover.
  418.  
  419. function createFader(toc) {
  420.  
  421. var timer = null;
  422.  
  423. // BUG: this didn't stop the two fades from conflicting when the user wiggles the mouse to start both!
  424. function resetTimeout(fn,ms) {
  425. if (timer) {
  426. clearTimeout(timer);
  427. }
  428. setTimeout(fn,ms);
  429. }
  430.  
  431. function fadeElement(elem,start,stop,speed,current) {
  432. if (current == null)
  433. current = start;
  434. if (speed == null)
  435. speed = (stop - start) / 8;
  436. if (Math.abs(current+speed-stop) > Math.abs(current-stop))
  437. current = stop;
  438. else
  439. current = current + speed;
  440. elem.style.opacity = current;
  441. if (current != stop)
  442. resetTimeout(function(){fadeElement(elem,start,stop,speed,current);},50);
  443. }
  444.  
  445. toc.style.opacity = 0.3;
  446. var listenElement = toc;
  447. // var listenElement = toc.getElementsByTagName('TD')[0];
  448. var focused = false;
  449. var visible = false;
  450. listenElement.addEventListener('mouseover',function(){
  451. if (!visible)
  452. setTimeout(function(){ if (focused) { visible=true; fadeElement(toc,0.4,1.0,0.2); } },10);
  453. focused = true;
  454. },false);
  455. listenElement.addEventListener('mouseout',function(){
  456. if (visible)
  457. setTimeout(function(){ if (!focused) { visible=false; fadeElement(toc,1.0,0.2,-0.1); } },10);
  458. focused = false;
  459. },false);
  460.  
  461. }
  462.  
  463.  
  464. function tryTOC() {
  465.  
  466. // Find the table of contents element:
  467. var toc = document.getElementById("toc") /* MediaWiki */
  468. || document.getElementsByClassName("table-of-contents")[0] /* BashFAQ */
  469. || document.getElementsByClassName("toc")[0] /* LeakyTap */
  470. || document.getElementsByClassName("wt-toc")[0]; /* Wikitravel */
  471.  
  472. if (toc) {
  473.  
  474. addButtonsConditionally(toc);
  475.  
  476. // toc.style.backgroundColor = '#eeeeee';
  477. // alert("doing it!");
  478. toc.style.position = 'fixed';
  479. toc.style.right = '16px';
  480. // toc.style.top = '16px';
  481. // A healthy gap from the top allows the user to access things fixed in the top right of the page, if they can scroll finely enough.
  482. // toc.style.top = '24px';
  483. //toc.style.right = '4%';
  484. //toc.style.top = '10%';
  485. toc.style.right = '4px';
  486. toc.style.top = '84px'; // We want to be below the search box!
  487. // toc.style.left = '';
  488. // toc.style.bottom = '';
  489. toc.style.zIndex = '5000';
  490. // fadeElement(toc,1.0,0.4);
  491. // This might work for a simple toc div
  492. toc.style.maxHeight = "80%";
  493. toc.style.maxWidth = "32%";
  494.  
  495. /*
  496. * Sometimes specifying max-height: 80% does not work, the toc won't shrink.
  497. * This may be when it's a table and not a div. Then we must set max-height on the content. (Maybe we don't actually need to set pixels if we find the right element.)
  498. */
  499. toc.id = "toc";
  500. var maxHeight = window.innerHeight * 0.8 | 0;
  501. var maxWidth = window.innerWidth * 0.4 | 0;
  502.  
  503. /*
  504. * WikiMedia tree looks like this: <table id="toc" class="toc"><tbody><tr><td><div id="toctitle"><h2>Contents</h2>...</div> <ul> <li class="toclevel-1 tocsection-1">
  505. Here is a long TOC: http://mewiki.project357.com/wiki/X264_Settings#Input.2FOutput
  506. */
  507. // GM_addStyle("#toc ul { overflow: auto; max-width: "+maxWidth+"px; max-height: "+maxHeight+"px; }");
  508. var rootUL = toc.getElementsByTagName("UL")[0];
  509. if (!rootUL)
  510. rootUL = toc;
  511. // DONE: If we can cleanly separate them, we might want to put a scrollbar on the content element, leaving the title outside it.
  512. rootUL.style.overflow = "auto";
  513. rootUL.style.maxWidth = maxWidth+'px';
  514. rootUL.style.maxHeight = maxHeight+'px';
  515.  
  516. // But if calc and vh are available, then we can make it adaptive
  517. // Of this 132px, 84px comes from the 'top', and the rest comes from the toc title and padding.
  518. rootUL.style.maxHeight = "calc(100vh - 132px)";
  519.  
  520. /*
  521. createFader(toc);
  522. */
  523. //// Alternative rules from table_of_contents_everywhere script:
  524. toc.id = "toc";
  525. // GM_addStyle("#toc { position: fixed; top: 10%; right: 4%; background-color: white; color: black; font-weight: normal; padding: 5px; border: 1px solid grey; z-index: 5555; max-height: 80%; overflow: auto; }");
  526. GM_addStyle("#toc { opacity: 0.2; }");
  527. GM_addStyle("#toc:hover { opacity: 1.0; }");
  528.  
  529. var tocID = "toc";
  530. var resetProps = "";
  531. // This is a clone of the code in table_of_contents_everyw.user.js
  532. GM_addStyle("#"+tocID+" { position: fixed; top: 84px; right: 4px; background-color: #f4f4f4; color: black; font-weight: normal; padding: 5px; border: 1px solid grey; z-index: 9999999; "+resetProps+" }" // max-height: 80%; max-width: 32%; overflow: auto;
  533. + "#"+tocID+" { opacity: 0.3; }"
  534. + "#"+tocID+":hover { box-shadow: 0px 2px 10px 1px rgba(0,0,0,0.3); }"
  535. + "#"+tocID+":hover { -webkit-box-shadow: 0px 1px 4px 0px rgba(0,0,0,0.3); }"
  536. + "#"+tocID+":hover { opacity: 1.0; }"
  537. + "#"+tocID+" > * > * { opacity: 0.0; }"
  538. + "#"+tocID+":hover > * > * { opacity: 1.0; }"
  539. + "#"+tocID+" , #"+tocID+" > * > * { transition: opacity; transition-duration: 400ms; }"
  540. + "#"+tocID+" , #"+tocID+" > * > * { -webkit-transition: opacity; -webkit-transition-duration: 400ms; }"
  541. + "#"+tocID+" { padding: 0; }"
  542. + "#"+tocID+" > div { padding: 4px 12px; }"
  543. + "#"+tocID+" > ul { padding: 0px 12px 2px 12px; margin-top: 0; }"
  544. );
  545.  
  546. // For Wikia (tested in Chrome):
  547. if (getComputedStyle(toc)["background-color"] == "rgba(0, 0, 0, 0)") {
  548. toc.style.backgroundColor = 'white';
  549. }
  550.  
  551. return true;
  552.  
  553. }
  554.  
  555. return false;
  556.  
  557. }
  558.  
  559. // Ideally we want to act before # anchor position occurs, but we may
  560. // need to wait for the toc if it is not added to the DOM until later.
  561. if (!tryTOC()) {
  562. setTimeout(tryTOC,400);
  563. }
  564.  
  565. }
  566.  
  567.  
  568.  
  569. // In case you have * in your includes, only continue for pages which have
  570. // "wiki" before "?" in the URL, or who have both toc and content elements.
  571. var isWikiPage = document.location.href.split("?")[0].match("wiki")
  572. || ( document.getElementById("toc") && document.getElementById("content") );
  573.  
  574. if (!isWikiPage)
  575. return;
  576.  
  577.  
  578.  
  579. // Delay. Feature 3 and 4 can run a bit later, without *too* much page
  580. // change, but with significant processor saving!
  581. setTimeout(function(){
  582.  
  583.  
  584.  
  585. //// Feature #3 : Indent the blocks so their tree-like structure is visible
  586.  
  587. // Oct 2012: Disabled - was making a right mess of the header/nav on Wikia
  588. if (document.location.host.match(/wikia.com/)) {
  589. indentSubBlocks = false;
  590. }
  591.  
  592. if (indentSubBlocks) {
  593.  
  594. function indent(tag) {
  595. // By targetting search we avoid indenting any blocks in left-hand-column (sidebar).
  596. var whereToSearch = document.getElementById('bodyContent') || document.getElementById('content') || document.getElementById('WikiaMainContent') || document.body;
  597. var elems = whereToSearch.getElementsByTagName(tag);
  598. if (elems.length == 1)
  599. return;
  600. // for (var i=0;i<elems.length;i++) {
  601. for (var i=elems.length;i-->0;) {
  602. var elem = elems[i];
  603. /* Don't fiddle with main heading, siteSub, or TOC. */
  604. if (elem.className == 'firstHeading')
  605. continue;
  606. if (elem.id == 'siteSub')
  607. continue;
  608. if (elem.textContent == 'Contents')
  609. continue;
  610.  
  611. // We have found a "heading" element. Every sibling after this
  612. // element should be indented a bit.
  613.  
  614. //// Current method of indenting: Create a UL and put everything
  615. //// inside that.
  616. // var newChild = document.createElement('blockquote');
  617. //// Unfortunately blockquotes tend to indent too much!
  618. // var newChild = document.createElement('DIV');
  619. //var newChild = document.createElement('UL'); // UL works better with my Folding script, but we must not do this to the TOC!
  620. var newChild = document.createElement('div'); // <ul>s look wrong on bitbucket wikis (indent too much). And since I haven't used my folding script recently, I am switching back to a nice <div>.
  621. newChild.style.marginLeft = '1.0em';
  622. var toAdd = elem.nextSibling;
  623. while (toAdd && toAdd.tagName != tag) {
  624. // That last condition means a h3 might swallow an h2 if they
  625. // are on the same level! But it *should* swallow an h4.
  626. // TODO: We should break if we encounter any marker with level
  627. // above or equal to our own, otherwise continue to swallow.
  628. var next = toAdd.nextSibling;
  629. newChild.appendChild(toAdd);
  630. toAdd = next;
  631. }
  632. elem.parentNode.insertBefore(newChild,elem.nextSibling);
  633.  
  634. // CONSIDER: Alternative: Do not swallow at all, do not create
  635. // newChild and change the page's tree. Just modify
  636. // style.marginLeft, resetting it if an incompatible element style
  637. // already exists there, updating it if we have already indented
  638. // this element!
  639.  
  640. // GM_log("Placed "+newChild+" after "+elem);
  641. }
  642. }
  643.  
  644. indent("H1"); indent("H2"); indent("H3"); indent("H4"); indent("H5"); indent("H6");
  645.  
  646. }
  647.  
  648.  
  649.  
  650. //// Feature #4: Change underlined headings to overlined headings.
  651.  
  652. if (fixUnderlinesToOverlines) {
  653.  
  654. // Hide any existing underlines
  655. // I made this !important to defeat the more specific `.markdown-body h*` rules on GitHub wikis.
  656. GM_addStyle("h1, h2, h3, h4, h5, h6 { border-bottom: 0 !important; }");
  657.  
  658. // Add our own overlines instead
  659. GM_addStyle("h1, h2, h3, h4, h5, h6 { border-top: 1px solid #AAAAAA; }");
  660.  
  661. // Do not use `text-decoration: underline;`. It will only appear as wide as the text (not filling the page width) and will make the text look like a hyperlink!
  662.  
  663. }
  664.  
  665.  
  666.  
  667. },1000);
  668.  
  669.  
  670.  
  671.  
  672. } // end doIt
  673.  
  674.  
  675. // setTimeout(doIt,2000);
  676. doIt();
  677.  
  678. })();
  679.