Last active
August 19, 2025 18:21
-
-
Save jhauga/7e3af6f91cc931f492d0615367612627 to your computer and use it in GitHub Desktop.
Bookmarklet - use this bookmarklet for searching long documentation pages by headings (default), showing following elements that are not headings. If no default elements are found, select the are to be searched manually (a prompt will appear). Click and drag to adjust top position (range of 40px to 150px).. Ensure to copy/paste the top condensed…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// *********************************************************** /// | |
| // ****************** BROWSER BOOKMARKLET GIST ***************** // | |
| // ************************************************************* // | |
| // // | |
| // LICENSE ///////////////////////////////////////////////////// | |
| // ******* // | |
| // The code in this gist is public domain. // | |
| // Licensed as Public Domain CC0 // | |
| ////////////////////////////////////////////////////////////////// | |
| // | |
| // COPY / PAST BELOW LINE TO USE | |
| javascript: (function () { /* Config variables. */ /* Set search area, where 1 = use default selection, 0 = custom element. */ var autoSelectSearchPage = 1; /* For switch condition defines searchElementsSearchPage (0 = default). */ var searchTagsSearchPage = 0; /* 0 = default */ /******************************* var searchTagsSearchPage = 1 = h1 to h4 ||*loop siblings and show hide accordingly 2 = all elements with class || 3 = all p elements || 4 = all div with p elements || 5 >= ADD PER HTML SEMANTICS || default = all p, ul, ol *loop siblings and show hide accordingly ********************************//* Specify where to insert search elements relative to search area, using insertAdjacentElements first property. */var insertWhereSearchPage = "beforebegin"; /* Config DOM Selector variables */ var querySelectorsSearchPage = /* loop and check if page has querySelectors */ [".container", ".container-fluid", "#main", "main", ".main"]; /* Config DOM Custom Selector variables. */ var customSelectorSearchPage = /* loop and check if page has querySelectors */ ["CHANGE"]; /* Auto-configuration variables. */ /* use switch below and var searchTagsSearchPage to specify nested items to search in. */ var searchElementsSearchPage; /* Define nested elements to search based on searchTagsSearchPage above. */ switch(searchTagsSearchPage) { case 1: searchElementsSearchPage = "h1,h2,h3,h4"; /* use nested headings */ break; case 2: searchElementsSearchPage = "*[class]"; /* all elements class */ break; case 3: searchElementsSearchPage = "p"; /* all p elements nested in area */ break; case 4: searchElementsSearchPage = "div p"; /* div nested in search area */ break; default: searchElementsSearchPage = /* all p or span in area */ "p, ul, ol"; } var selectHierarchySearchPage = /* config based on config variables */ (searchElementsSearchPage.search(/h[1-9]/g) > -1) ? 1 : 0; /* hierarchy or all elements */ /* Global variables -defined later. */ var markersSearchPage; /* select all elements with head tag in parSearchPage */ var parSearchPage; /* parent to recurse over */ var inputSearchPage; /* search input element */ var addedSearchPage; /* switch variable */ var parSelectedSearchPage = 0; /* swithch if user selects */ /************************************* SUPPORT FUNCTIONS *************************************/ /* Loop and check if page has query selector. */ const checkSelectorSearchPage = () => { let qArr; /* use query selectors pending autoSelectSearchPage value */ /* select which query selector array */ if (autoSelectSearchPage == 1) { qArr = querySelectorsSearchPage; } else { qArr = customSelectorSearchPage; } let qArrLen = qArr.length; /* used to compare length of found elements */ let compLen = 0; /* check if page has element and use first */ for (i = 0; i < qArrLen; i++) { let curCheck = document.querySelectorAll(qArr[i]); if (curCheck[0]) { /* use element with most children */ for (l = 0; l < curCheck.length; l++) { if (curCheck[l].querySelectorAll("*").length > compLen) { compLen = curCheck[l].querySelectorAll("*").length; parSearchPage = curCheck[l]; } } break; } else { continue; } } }; /* Allow user to selecct the area to search. */ const selectParSearchPage = () => { let selectedElement, lastHover; /* temp store last style to restore */ let resLastOutline = "", resLastCursor = "", resLastBorder = ""; /* add temp event */ let highlight = (el) => { /* remove old highlight */ if (lastHover) { lastHover.style.cursor = resLastCursor; lastHover.style.border = resLastBorder; } /* store prior styles */ if (el.style.border && el.style.border != "10px solid dodgerblue") resLastOutline = el.style.border; if (el.style.cursor && el.style.cursor != "pointer") resLastCursor = el.style.cursor; lastHover = el; /* redefine */ /* stylish highlight */ el.style.border = "10px solid dodgerblue"; el.style.cursor = "pointer"; }; /* mouse over possible search area */ let handleMouseOver = (el) => { el.stopPropagation(); highlight(el.target); }; /* use clicked element as search element */ let handleClick = (el) => { /* dont' do any predefined behavior */ el.preventDefault(); /* no action other than clicked element */ el.stopPropagation(); /* define and clean selection */ selectedElement = el.target; selectedElement.style.cursor = resLastCursor; /* define global for search */ parSearchPage = selectedElement; /* continue main function */ hasParSearchPage = 1; parSelectedSearchPage = 1; cleanup(); /* stop listening once selected */ }; /* remove temp events */ let cleanup = () => { document.removeEventListener("mouseover", handleMouseOver, true); document.removeEventListener("click", handleClick, true); /* remove mouse effect */ if (lastHover) { lastHover.style.border = resLastBorder; lastHover.style.cursor = resLastCursor; } }; /* Activate selection mode */ document.addEventListener("mouseover", handleMouseOver, true); document.addEventListener("click", handleClick, true); }; /* Check if parSearchPage, else start manual selection process. */ var hasParSearchPage = 0; /* 1 if parSearchPage is found */ var initAlertSearchPage = 0; /* prevent alert from repeating */ const checkParSearchPage = () => { if (parSearchPage) { hasParSearchPage = 1; /* query found element */ parSelectedSearchPage = 1; /* continue main function */ } else { if (initAlertSearchPage == 0) { alert( ` SELECT MANUALLY: \n\n The default or custom selectors were not found on page. \n Hover, and select the area to be searched manually. `); initAlertSearchPage = 1; /* turn off alert */ } /* user select search parent */ selectParSearchPage(); } }; /* Add search input box to top of page. */ const addSearchPage = () => { if (hasParSearchPage == 1) { /* ensure par was found */ /* prevent duplicate search boxes */ let prevDup = /* use class name added on first run */ document.getElementsByClassName("bookmarkletDOMSearchSearchPage"); if (!prevDup[0]) { let par = document.createElement("div"); /* hold all search elements */ let sPar = document.createElement("div"); /* hold searc and clear */ let inp = document.createElement("input"); /* search */ let sh = document.createElement("span"); /* show hide search */ let clr = document.createElement("span"); /* clear search field */ /* set parent of search style */ par.style.zIndex = "100"; /* topmost - can be hidden, not too intrusive */ par.style.background = "white"; par.style.position = "fixed"; par.style.top = "90px"; par.style.padding = "10px"; par.style.width = "200px"; par.style.height = "50px"; par.style.border = "1px solid #9b9b9b"; par.style.borderRadius = "6px"; /* allow par top position to be adjusted. */ par.addEventListener("mousedown", (el) => { let startY, startTop; startY = el.clientY; /* current y position */ startTop = /* current style */ parseInt(window.getComputedStyle(par).top, 10); let onMouseMove = (el) => { let newTop = startTop + (el.clientY - startY); /* between 40 and 150 */ newTop = Math.max(40, Math.min(150, newTop)); par.style.top = newTop + "px"; }; /* remove events */ let onMouseUp = () => { document.removeEventListener("mousemove", onMouseMove); document.removeEventListener("mouseup", onMouseUp); }; /* add temp events */ document.addEventListener("mousemove", onMouseMove); document.addEventListener("mouseup", onMouseUp); }); /* prevent duplicate search boxes */ par.setAttribute("class", "bookmarkletDOMSearchSearchPage"); /* set input attributes and style */ inp.type = "text"; inp.placeholder = "Search Page"; inp.style.display = "block"; inp.style.position = "fixed"; inp.style.width = "160px"; inp.style.marginBottom = "10px"; inp.style.marginLeft = "20px"; /* data-id to select if parent needs to be reselected */ inp.setAttribute("data-id", "bookmarkletDOMSearchSearchPage"); /* style clear button */ clr.style.zIndex = "1"; clr.style.position = "fixed"; clr.style.cursor = "pointer"; clr.style.marginLeft = "164px"; clr.style.marginTop = "1px"; clr.style.padding = "4px"; clr.style.background = "#d3d3d350"; clr.innerText = "-"; /* clear mouse effects */ clr.addEventListener("mouseover", () => { clr.style.background = "#d3d3d3"; }); clr.addEventListener("mouseout", () => { clr.style.background = "#d3d3d350"; }); /* clear search */ clr.addEventListener("click", ()=> { clr.previousElementSibling.value = ""; setTimeout(function() { /* delay a bit */ performSearchPage(); /* manual show all */ }, 100); }); /* set close button attributes and style */ sh.style.position = "fixed"; sh.style.cursor = "pointer"; sh.style.border = "1px solid black"; sh.style.padding = "3px"; sh.innerText = " x "; /* show/hide effects */ sh.addEventListener("mouseover", () => { sh.style.backgroundColor = "dodgerblue"; sh.style.color = "white"; }); sh.addEventListener("mouseout", () => { sh.style.backgroundColor = ""; sh.style.color = ""; }); /* click event */ sh.addEventListener("click", () => { if (!sPar) return; /* something unexpected */ if (sPar.style.display === "none") { sh.innerText = " x "; /* indicate click will hide */ par.style.width = "200px"; /* parent width */ sPar.style.display = ""; /* show search */ } else { sh.innerText = " o "; /* indicate click will show */ par.style.width = "37px"; /* parent width */ sPar.style.display = "none"; /* hide search */ } }); /* insert search before area to be searched */ /* config var, par created */ parSearchPage.insertAdjacentElement(insertWhereSearchPage, par); par.prepend(sh); /* show hide button */ sh.insertAdjacentElement("afterend", sPar); /* search and clear search parent */ sPar.prepend(inp); /* search input element */ inp.insertAdjacentElement("afterend", clr);/* clears search */ /* set focus on search box */ inp.focus(); } /* define heading elemnets from parSearchPage */ markersSearchPage = Array.from(parSearchPage.querySelectorAll(searchElementsSearchPage)); /* define search box from created input */ inputSearchPage = /* use data-id attribute added */ document.querySelector("[data-id='bookmarkletDOMSearchSearchPage'"); /* turn on condition to continue in main function */ addedSearchPage = 1; } else { addedSearchPage = 0; } }; /* Perform search on page. */ const performSearchPage = () => { let curVal = /* current search value formatted */ inputSearchPage.value.trim().toLowerCase(); /* loop over ids and see if siblings match */ let j = 0; /* increments heading markers */ let sibID = 0; /* switch - if sibling has less heading */ let firstIter = 0; /* ensure hVal gets defined */ let hFirstIter = 0; /* ensure hRank gets defined */ let hVal; /* declare variable to check heading values */ let lVal; /* store last h tag value */ let hRank; /* compare hiarchy of h tags */ let cRank; /* current h tag */ markersSearchPage.forEach((e, n) => { if (e.nextElementSibling && e.nextElementSibling.tagName.toLowerCase() == "nav") { return; } let defHRank = () => { let tH = 0; /* temp heading variable */ if (e.tagName.toLowerCase().search(/h[1-9]/g) > -1) tH = Number(e.tagName.substr(1,)); return tH; }; let curRank = () => { let tRank = 0; /* temp rank */ /* rank current h tags */ if (selectHierarchySearchPage == 1) { tRank = defHRank(); /* inline function for heading # */ } /* final return for variable */ return tRank }; cRank = curRank(); /* set cRank */ /* ensure last h tag is ranked */ if (hFirstIter == 0) { hFirstIter = 1; hRank = curRank(); /* store heading to check against next */ } /* define whether value matches search */ if (firstIter == 0 || sibID == 0) { if (firstIter == 1) { lVal = hVal; } hVal = /* get value formatted of heading and check search */ e.innerText.toLowerCase().includes(curVal); if (firstIter == 0) { firstIter = 1; lVal = hVal; } } j = /* next element with heading tag name attribute */ markersSearchPage[n + 1] || null; /* get the elements following heading */ let el = e.nextElementSibling; /* check if next element has id, skip if so */ if (cRank < hRank) { hRank = curRank(); /* store heading to check against next */ sibID = 1; } else { /* h tags equal and use h hierarchy */ if (cRank == hRank && selectHierarchySearchPage == 1) { hRank = curRank(); /* store heading to check against next */ sibID = 1; } else { sibID = 0; } /* show or hide pending search */ e.style.display = hVal ? "" : "none"; /* loop following elements and show/hide according to search */ if (selectHierarchySearchPage == 1 || searchTagsSearchPage == 0) { while (el && el != j) { /* exists and not next heading */ el.style.display = hVal ? "" : "none"; el = el.nextElementSibling; } } } }); }; /* Run time out with function as parameter. */ const runSupportSearchPage = (cur) => { setTimeout(function() { cur(); }, 100); }; /********************************************************************************************* MAIN FUNCTION *********************************************************************************************/ /* Run each support function and add event listener. */ var stopRecurSearchPage = 0; /* stop recursing after 20-ish seconds */ function domSearchPage() { if (parSelectedSearchPage == 0) { /* check parent with elements for search */ runSupportSearchPage(checkSelectorSearchPage); } /* if parent for search continue, manual select */ runSupportSearchPage(checkParSearchPage); /* create search input box above parent */ runSupportSearchPage(addSearchPage); setTimeout( function() { /* Check if found and input field, then continue */ if (addedSearchPage == 1) { /* add event to search page */ inputSearchPage .addEventListener("input", performSearchPage); } else { stopRecurSearchPage++; if (stopRecurSearchPage < 20) { domSearchPage(); /* recurse - probably selecting */ } else { let skip; /* do nothing */ } } }, 1000); } /* Call main function. */ domSearchPage();})(); | |
| // MAKE ANY EDITS AS NEEDED | |
| // ************************************************************* | |
| // Use the JS Formatted Bookmarklet below to see if any changes | |
| // need to be made in accordance to the page you want to use | |
| // it for. After making needed changes ensure that the revised | |
| // bookmarklet is condensed before using it in your browser. | |
| // For more info on this bookmarklet visit: | |
| // https://github.com/isocialPractice/bookmarklets | |
| // ************************************************************* | |
| // ************************************************************* | |
| // ************************JS-FORMATTED************************* | |
| javascript: (function () { | |
| /* Config variables. */ | |
| /* Set search area, where 1 = use default selection, 0 = custom element. */ | |
| var autoSelectSearchPage = 1; | |
| /* For switch condition defines searchElementsSearchPage (0 = default). */ | |
| var searchTagsSearchPage = 0; /* 0 = default */ | |
| /******************************* | |
| var searchTagsSearchPage = | |
| 1 = h1 to h4 ||*loop siblings and show hide accordingly | |
| 2 = all elements with class || | |
| 3 = all p elements || | |
| 4 = all div with p elements || | |
| 5 >= ADD PER HTML SEMANTICS || | |
| default = all p, ul, ol *loop siblings and show hide accordingly | |
| ********************************/ | |
| /* Specify where to insert search elements relative to search area, using | |
| insertAdjacentElements first property. */ | |
| var insertWhereSearchPage = "beforebegin"; | |
| /* Config DOM Selector variables */ | |
| var querySelectorsSearchPage = /* loop and check if page has querySelectors */ | |
| [".container", ".container-fluid", "#main", "main", ".main"]; | |
| /* Config DOM Custom Selector variables. */ | |
| var customSelectorSearchPage = /* loop and check if page has querySelectors */ | |
| ["CHANGE"]; | |
| /* Auto-configuration variables. */ | |
| /* use switch below and var searchTagsSearchPage to specify nested items to search in. */ | |
| var searchElementsSearchPage; | |
| /* Define nested elements to search based on searchTagsSearchPage above. */ | |
| switch(searchTagsSearchPage) { | |
| case 1: | |
| searchElementsSearchPage = "h1,h2,h3,h4"; /* use nested headings */ | |
| break; | |
| case 2: | |
| searchElementsSearchPage = "*[class]"; /* all elements class */ | |
| break; | |
| case 3: | |
| searchElementsSearchPage = "p"; /* all p elements nested in area */ | |
| break; | |
| case 4: | |
| searchElementsSearchPage = "div p"; /* div nested in search area */ | |
| break; | |
| default: | |
| searchElementsSearchPage = /* all p or span in area */ | |
| "p, ul, ol"; | |
| } | |
| var selectHierarchySearchPage = /* config based on config variables */ | |
| (searchElementsSearchPage.search(/h[1-9]/g) > -1) ? 1 : 0; /* hierarchy or all elements */ | |
| /* Global variables -defined later. */ | |
| var markersSearchPage; /* select all elements with head tag in parSearchPage */ | |
| var parSearchPage; /* parent to recurse over */ | |
| var inputSearchPage; /* search input element */ | |
| var addedSearchPage; /* switch variable */ | |
| var parSelectedSearchPage = 0; /* swithch if user selects */ | |
| /************************************* SUPPORT FUNCTIONS *************************************/ | |
| /* Loop and check if page has query selector. */ | |
| const checkSelectorSearchPage = () => { | |
| let qArr; /* use query selectors pending autoSelectSearchPage value */ | |
| /* select which query selector array */ | |
| if (autoSelectSearchPage == 1) { | |
| qArr = querySelectorsSearchPage; | |
| } else { | |
| qArr = customSelectorSearchPage; | |
| } | |
| let qArrLen = qArr.length; | |
| /* used to compare length of found elements */ | |
| let compLen = 0; | |
| /* check if page has element and use first */ | |
| for (i = 0; i < qArrLen; i++) { | |
| let curCheck = document.querySelectorAll(qArr[i]); | |
| if (curCheck[0]) { | |
| /* use element with most children */ | |
| for (l = 0; l < curCheck.length; l++) { | |
| if (curCheck[l].querySelectorAll("*").length > compLen) { | |
| compLen = curCheck[l].querySelectorAll("*").length; | |
| parSearchPage = curCheck[l]; | |
| } | |
| } | |
| break; | |
| } else { | |
| continue; | |
| } | |
| } | |
| }; | |
| /* Allow user to selecct the area to search. */ | |
| const selectParSearchPage = () => { | |
| let selectedElement, lastHover; | |
| /* temp store last style to restore */ | |
| let resLastOutline = "", resLastCursor = "", resLastBorder = ""; | |
| /* add temp event */ | |
| let highlight = (el) => { | |
| /* remove old highlight */ | |
| if (lastHover) { | |
| lastHover.style.cursor = resLastCursor; | |
| lastHover.style.border = resLastBorder; | |
| } | |
| /* store prior styles */ | |
| if (el.style.border && el.style.border != "10px solid dodgerblue") | |
| resLastOutline = el.style.border; | |
| if (el.style.cursor && el.style.cursor != "pointer") | |
| resLastCursor = el.style.cursor; | |
| lastHover = el; /* redefine */ | |
| /* stylish highlight */ | |
| el.style.border = "10px solid dodgerblue"; | |
| el.style.cursor = "pointer"; | |
| }; | |
| /* mouse over possible search area */ | |
| let handleMouseOver = (el) => { | |
| el.stopPropagation(); | |
| highlight(el.target); | |
| }; | |
| /* use clicked element as search element */ | |
| let handleClick = (el) => { | |
| /* dont' do any predefined behavior */ | |
| el.preventDefault(); | |
| /* no action other than clicked element */ | |
| el.stopPropagation(); | |
| /* define and clean selection */ | |
| selectedElement = el.target; | |
| selectedElement.style.cursor = resLastCursor; | |
| /* define global for search */ | |
| parSearchPage = selectedElement; | |
| /* continue main function */ | |
| hasParSearchPage = 1; | |
| parSelectedSearchPage = 1; | |
| cleanup(); /* stop listening once selected */ | |
| }; | |
| /* remove temp events */ | |
| let cleanup = () => { | |
| document.removeEventListener("mouseover", handleMouseOver, true); | |
| document.removeEventListener("click", handleClick, true); | |
| /* remove mouse effect */ | |
| if (lastHover) { | |
| lastHover.style.border = resLastBorder; | |
| lastHover.style.cursor = resLastCursor; | |
| } | |
| }; | |
| /* Activate selection mode */ | |
| document.addEventListener("mouseover", handleMouseOver, true); | |
| document.addEventListener("click", handleClick, true); | |
| }; | |
| /* Check if parSearchPage, else start manual selection process. */ | |
| var hasParSearchPage = 0; /* 1 if parSearchPage is found */ | |
| var initAlertSearchPage = 0; /* prevent alert from repeating */ | |
| const checkParSearchPage = () => { | |
| if (parSearchPage) { | |
| hasParSearchPage = 1; /* query found element */ | |
| parSelectedSearchPage = 1; /* continue main function */ | |
| } else { | |
| if (initAlertSearchPage == 0) { | |
| alert(` | |
| SELECT MANUALLY: | |
| \n\n | |
| The default or custom selectors were not found on page. | |
| \n | |
| Hover, and select the area to be searched manually. | |
| `); | |
| initAlertSearchPage = 1; /* turn off alert */ | |
| } | |
| /* user select search parent */ | |
| selectParSearchPage(); | |
| } | |
| }; | |
| /* Add search input box to top of page. */ | |
| const addSearchPage = () => { | |
| if (hasParSearchPage == 1) { /* ensure par was found */ | |
| /* prevent duplicate search boxes */ | |
| let prevDup = /* use class name added on first run */ | |
| document.getElementsByClassName("bookmarkletDOMSearchSearchPage"); | |
| if (!prevDup[0]) { | |
| let par = document.createElement("div"); /* hold all search elements */ | |
| let sPar = document.createElement("div"); /* hold searc and clear */ | |
| let inp = document.createElement("input"); /* search */ | |
| let sh = document.createElement("span"); /* show hide search */ | |
| let clr = document.createElement("span"); /* clear search field */ | |
| /* set parent of search style */ | |
| par.style.zIndex = "100"; /* topmost - can be hidden, not too intrusive */ | |
| par.style.background = "white"; | |
| par.style.position = "fixed"; | |
| par.style.top = "90px"; | |
| par.style.padding = "10px"; | |
| par.style.width = "200px"; | |
| par.style.height = "50px"; | |
| par.style.border = "1px solid #9b9b9b"; | |
| par.style.borderRadius = "6px"; | |
| /* allow par top position to be adjusted. */ | |
| par.addEventListener("mousedown", (el) => { | |
| let startY, startTop; | |
| startY = el.clientY; /* current y position */ | |
| startTop = /* current style */ | |
| parseInt(window.getComputedStyle(par).top, 10); | |
| let onMouseMove = (el) => { | |
| let newTop = startTop + (el.clientY - startY); | |
| /* between 40 and 150 */ | |
| newTop = Math.max(40, Math.min(150, newTop)); | |
| par.style.top = newTop + "px"; | |
| }; | |
| /* remove events */ | |
| let onMouseUp = () => { | |
| document.removeEventListener("mousemove", onMouseMove); | |
| document.removeEventListener("mouseup", onMouseUp); | |
| }; | |
| /* add temp events */ | |
| document.addEventListener("mousemove", onMouseMove); | |
| document.addEventListener("mouseup", onMouseUp); | |
| }); | |
| /* prevent duplicate search boxes */ | |
| par.setAttribute("class", "bookmarkletDOMSearchSearchPage"); | |
| /* set input attributes and style */ | |
| inp.type = "text"; | |
| inp.placeholder = "Search Page"; | |
| inp.style.display = "block"; | |
| inp.style.position = "fixed"; | |
| inp.style.width = "160px"; | |
| inp.style.marginBottom = "10px"; | |
| inp.style.marginLeft = "20px"; | |
| /* data-id to select if parent needs to be reselected */ | |
| inp.setAttribute("data-id", "bookmarkletDOMSearchSearchPage"); | |
| /* style clear button */ | |
| clr.style.zIndex = "1"; | |
| clr.style.position = "fixed"; | |
| clr.style.cursor = "pointer"; | |
| clr.style.marginLeft = "164px"; | |
| clr.style.marginTop = "1px"; | |
| clr.style.padding = "4px"; | |
| clr.style.background = "#d3d3d350"; | |
| clr.innerText = "-"; | |
| /* clear mouse effects */ | |
| clr.addEventListener("mouseover", () => { | |
| clr.style.background = "#d3d3d3"; | |
| }); | |
| clr.addEventListener("mouseout", () => { | |
| clr.style.background = "#d3d3d350"; | |
| }); | |
| /* clear search */ | |
| clr.addEventListener("click", ()=> { | |
| clr.previousElementSibling.value = ""; | |
| setTimeout(function() { /* delay a bit */ | |
| performSearchPage(); /* manual show all */ | |
| }, 100); | |
| }); | |
| /* set close button attributes and style */ | |
| sh.style.position = "fixed"; | |
| sh.style.cursor = "pointer"; | |
| sh.style.border = "1px solid black"; | |
| sh.style.padding = "3px"; | |
| sh.innerText = " x "; | |
| /* show/hide effects */ | |
| sh.addEventListener("mouseover", () => { | |
| sh.style.backgroundColor = "dodgerblue"; | |
| sh.style.color = "white"; | |
| }); | |
| sh.addEventListener("mouseout", () => { | |
| sh.style.backgroundColor = ""; | |
| sh.style.color = ""; | |
| }); | |
| /* click event */ | |
| sh.addEventListener("click", () => { | |
| if (!sPar) return; /* something unexpected */ | |
| if (sPar.style.display === "none") { | |
| sh.innerText = " x "; /* indicate click will hide */ | |
| par.style.width = "200px"; /* parent width */ | |
| sPar.style.display = ""; /* show search */ | |
| } else { | |
| sh.innerText = " o "; /* indicate click will show */ | |
| par.style.width = "37px"; /* parent width */ | |
| sPar.style.display = "none"; /* hide search */ | |
| } | |
| }); | |
| /* insert search before area to be searched */ | |
| /* config var, par created */ | |
| parSearchPage.insertAdjacentElement(insertWhereSearchPage, par); | |
| par.prepend(sh); /* show hide button */ | |
| sh.insertAdjacentElement("afterend", sPar); /* search and clear search parent */ | |
| sPar.prepend(inp); /* search input element */ | |
| inp.insertAdjacentElement("afterend", clr);/* clears search */ | |
| /* set focus on search box */ | |
| inp.focus(); | |
| } | |
| /* define heading elemnets from parSearchPage */ | |
| markersSearchPage = | |
| Array.from(parSearchPage.querySelectorAll(searchElementsSearchPage)); | |
| /* define search box from created input */ | |
| inputSearchPage = /* use data-id attribute added */ | |
| document.querySelector("[data-id='bookmarkletDOMSearchSearchPage'"); | |
| /* turn on condition to continue in main function */ | |
| addedSearchPage = 1; | |
| } else { | |
| addedSearchPage = 0; | |
| } | |
| }; | |
| /* Perform search on page. */ | |
| const performSearchPage = () => { | |
| let curVal = /* current search value formatted */ | |
| inputSearchPage.value.trim().toLowerCase(); | |
| /* loop over ids and see if siblings match */ | |
| let j = 0; /* increments heading markers */ | |
| let sibID = 0; /* switch - if sibling has less heading */ | |
| let firstIter = 0; /* ensure hVal gets defined */ | |
| let hFirstIter = 0; /* ensure hRank gets defined */ | |
| let hVal; /* declare variable to check heading values */ | |
| let lVal; /* store last h tag value */ | |
| let hRank; /* compare hiarchy of h tags */ | |
| let cRank; /* current h tag */ | |
| markersSearchPage.forEach((e, n) => { | |
| if (e.nextElementSibling && | |
| e.nextElementSibling.tagName.toLowerCase() == "nav") { | |
| return; | |
| } | |
| let defHRank = () => { | |
| let tH = 0; /* temp heading variable */ | |
| if (e.tagName.toLowerCase().search(/h[1-9]/g) > -1) | |
| tH = Number(e.tagName.substr(1,)); | |
| return tH; | |
| }; | |
| let curRank = () => { | |
| let tRank = 0; /* temp rank */ | |
| /* rank current h tags */ | |
| if (selectHierarchySearchPage == 1) { | |
| tRank = defHRank(); /* inline function for heading # */ | |
| } | |
| /* final return for variable */ | |
| return tRank | |
| }; | |
| cRank = curRank(); /* set cRank */ | |
| /* ensure last h tag is ranked */ | |
| if (hFirstIter == 0) { | |
| hFirstIter = 1; | |
| hRank = curRank(); /* store heading to check against next */ | |
| } | |
| /* define whether value matches search */ | |
| if (firstIter == 0 || sibID == 0) { | |
| if (firstIter == 1) { | |
| lVal = hVal; | |
| } | |
| hVal = /* get value formatted of heading and check search */ | |
| e.innerText.toLowerCase().includes(curVal); | |
| if (firstIter == 0) { | |
| firstIter = 1; | |
| lVal = hVal; | |
| } | |
| } | |
| j = /* next element with heading tag name attribute */ | |
| markersSearchPage[n + 1] || null; | |
| /* get the elements following heading */ | |
| let el = e.nextElementSibling; | |
| /* check if next element has id, skip if so */ | |
| if (cRank < hRank) { | |
| hRank = curRank(); /* store heading to check against next */ | |
| sibID = 1; | |
| } else { | |
| /* h tags equal and use h hierarchy */ | |
| if (cRank == hRank && selectHierarchySearchPage == 1) { | |
| hRank = curRank(); /* store heading to check against next */ | |
| sibID = 1; | |
| } else { | |
| sibID = 0; | |
| } | |
| /* show or hide pending search */ | |
| e.style.display = hVal ? "" : "none"; | |
| /* loop following elements and show/hide according to search */ | |
| if (selectHierarchySearchPage == 1 || searchTagsSearchPage == 0) { | |
| while (el && el != j) { /* exists and not next heading */ | |
| el.style.display = hVal ? "" : "none"; | |
| el = el.nextElementSibling; | |
| } | |
| } | |
| } | |
| }); | |
| }; | |
| /* Run time out with function as parameter. */ | |
| const runSupportSearchPage = (cur) => { | |
| setTimeout(function() { | |
| cur(); | |
| }, 100); | |
| }; | |
| /********************************************************************************************* | |
| MAIN FUNCTION | |
| *********************************************************************************************/ | |
| /* Run each support function and add event listener. */ | |
| var stopRecurSearchPage = 0; /* stop recursing after 20-ish seconds */ | |
| function domSearchPage() { | |
| if (parSelectedSearchPage == 0) { | |
| /* check parent with elements for search */ | |
| runSupportSearchPage(checkSelectorSearchPage); | |
| } | |
| /* if parent for search continue, manual select */ | |
| runSupportSearchPage(checkParSearchPage); | |
| /* create search input box above parent */ | |
| runSupportSearchPage(addSearchPage); | |
| setTimeout( | |
| function() { | |
| /* Check if found and input field, then continue */ | |
| if (addedSearchPage == 1) { | |
| /* add event to search page */ | |
| inputSearchPage | |
| .addEventListener("input", performSearchPage); | |
| } else { | |
| stopRecurSearchPage++; | |
| if (stopRecurSearchPage < 20) { | |
| domSearchPage(); /* recurse - probably selecting */ | |
| } else { | |
| let skip; /* do nothing */ | |
| } | |
| } | |
| }, 1000); | |
| } | |
| /* Call main function. */ | |
| domSearchPage(); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment