Skip to content

Instantly share code, notes, and snippets.

@Serubin
Last active January 20, 2023 15:48
Show Gist options
  • Save Serubin/1b908bb3688f0199844dba24a540625b to your computer and use it in GitHub Desktop.
Save Serubin/1b908bb3688f0199844dba24a540625b to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name GithubJSNavDisable
// @version 1
// @grant none
// ==/UserScript==
const LINK_REFRESH = 1500;
let LAST_LINK_LIST = [];
/*
* Removes attributes that assit in trigger github nav events.
* Specifically targets buttons and file-finder links
*/
const ATTR_TO_REMOVE = ['role', 'data-hydro-click'];
function findAndRemoveAttr(target) {
for (let attr of ATTR_TO_REMOVE) {
if (target.hasAttribute(attr)) target.removeAttribute(attr);
}
}
/*
* Finds the anchor tag that the event fired on
* Sometimes events (specifically nav bread crumbs and tabs) dont fire with the a tag as the originalTarget.
* This climbs the DOM tree until we find an a tag and then assumes it fired the target.
*/
function findAnchor(target) {
console.log(`finding target`, target);
if (target.tagName === 'A') {
return target;
}
return findAnchor(target.parentElement);
}
/*
* Window.location.assign wrapper
*/
function routeTo(href) {
console.info(`Rerouting to ${href}`);
window.location.assign(href);
}
/*
* Event handler for click overrides
*/
function rerouteEvent(ev) {
const target = findAnchor(ev.originalTarget);
routeTo(target.href);
ev.stopPropagation();
ev.preventDefault();
return false;
}
/*
* Given a list of anchors, determines and returns all new anchors (not seen/hooked before)
* Side effect: saves a list of all anchors to LAST_LINK_LIST for tracking
*/
function findNewLinks(anchors) {
const anchorsArray = Array.from(anchors);
const newAnchors = anchorsArray.filter(a => !LAST_LINK_LIST.includes(a));
LAST_LINK_LIST = anchorsArray;
return newAnchors;
}
/*
* Hook page - override click events and remove hydro-click.
* This function should be called any time the page changes without a relaod
*/
function hookPage() {
// Hook buttons and file-finder links - removes event triggering attributes
document.querySelectorAll('a[data-hydro-click]').forEach(a => a.removeAttribute('data-hydro-click'));
// Override click events on all a tags
const anchors = document.querySelectorAll('a:not(.js-expand)');
const newAnchors = findNewLinks(anchors);
if (newAnchors.length !== 0) {
console.log(`Found ${newAnchors.length} out of ${anchors.length} total`);
newAnchors.forEach((a) => {
findAndRemoveAttr(a);
a.addEventListener('click', rerouteEvent);
});
console.info(`Overriding ${newAnchors.length} links`);
}
setTimeout(hookPage, LINK_REFRESH);
}
function run() {
window.addEventListener('popstate', (ev) => routeTo(ev.target.location.href));
window.addEventListener('combobox-commit', rerouteEvent);
hookPage();
}
run();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment