Skip to content

Instantly share code, notes, and snippets.

@SUT0L
Last active August 2, 2023 06:58
Show Gist options
  • Select an option

  • Save SUT0L/cf852bdf44f750949be561346c39d592 to your computer and use it in GitHub Desktop.

Select an option

Save SUT0L/cf852bdf44f750949be561346c39d592 to your computer and use it in GitHub Desktop.
Quick Select buttons / anchor tags
// ==UserScript==
// @name Quick Click
// @namespace http://tampermonkey.net/
// @version 0.0.3
// @description Quick Select buttons / anchor tags
// @author Sutol
// @license MIT
// @match *://*/*
// @grant none
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
let theme = {
modal: {
position: "fixed",
zIndex: "9999",
left: "0",
top: "0",
width: "100%",
height: "100%",
overflow: "auto",
backgroundColor: "rgba(26, 32, 44, 0.95)",
display: "none"
},
searchContainer: {
display: "flex",
justifyContent: "center",
marginBottom: "20px"
},
modalContent: {
backgroundColor: "#F7FAFC",
margin: "15% auto",
padding: "20px",
border: "1px solid #A0AEC0",
borderRadius: "0.375rem",
width: "60%",
boxShadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)"
},
input: {
id: "search-box",
autocomplete: "off",
width: "100%",
backgroundColor: "white",
borderRadius: "0.375rem",
padding: "0.5rem 1rem",
border: "1px solid #E2E8F0"
},
resultList: {
listStyleType: "none",
padding: "0",
maxHeight: "600px",
overflowY: "scroll",
overflowX: "hidden"
},
listItem: {
display: "flex",
justifyContent: "space-between",
border: "1px solid #CBD5E0",
padding: "0.5rem 1rem",
borderRadius: "0.375rem",
marginTop: "2px",
normalBg: "#F7FAFC",
highlightBg: '#F56565'
},
href: {
normalColor: "#bdbdbd",
selectedColor: "#ffffff",
textDecoration: "none",
}
}
// If you're using the shift key, you must make the "key" the uppercase
let keybinds = {
search: { key: 'F', ctrlKey: true, metaKey: false, shiftKey: true },
navigateDown: { key: 'ArrowDown', ctrlKey: false, metaKey: false, shiftKey: false },
navigateUp: { key: 'ArrowUp', ctrlKey: false, metaKey: false, shiftKey: false },
select: { keys: ['Enter'], ctrlKey: false, metaKey: false, shiftKey: false },
newTabSelect: { key: 'Enter', ctrlKey: true, metaKey: false, shiftKey: false },
cancel: { key: 'Escape', ctrlKey: false, metaKey: false, shiftKey: false }
};
let modal = document.createElement("div");
Object.assign(modal.style, theme.modal);
document.body.appendChild(modal);
let modalContent = document.createElement("div");
Object.assign(modalContent.style, theme.modalContent);
modal.appendChild(modalContent);
let input = document.createElement("input");
input.id = theme.input.id;
input.setAttribute("autocomplete", theme.input.autocomplete);
Object.assign(input.style, theme.input);
modalContent.appendChild(input);
let resultList = document.createElement("ul");
Object.assign(resultList.style, theme.resultList);
modalContent.appendChild(resultList);
let currentIndex = -1;
let matches = [];
window.addEventListener("keydown", function (e) {
if (e.key === keybinds.search.key && e.ctrlKey === keybinds.search.ctrlKey && e.metaKey === keybinds.search.metaKey && e.shiftKey === keybinds.search.shiftKey) {
e.preventDefault();
modal.style.display = "block";
input.value = "";
input.focus();
}
if (e.key === keybinds.cancel.key && e.ctrlKey === keybinds.cancel.ctrlKey && e.metaKey === keybinds.cancel.metaKey && e.shiftKey === keybinds.cancel.shiftKey) {
modal.style.display = "none";
}
});
input.addEventListener("keydown", function (e) {
if (e.key === keybinds.navigateDown.key && e.ctrlKey === keybinds.navigateDown.ctrlKey && e.metaKey === keybinds.navigateDown.metaKey && e.shiftKey === keybinds.navigateDown.shiftKey) {
if (matches.length > 0) {
resetHighlight();
currentIndex = (currentIndex + 1) % matches.length;
updateHighlight();
}
} else if (e.key === keybinds.navigateUp.key && e.ctrlKey === keybinds.navigateUp.ctrlKey && e.metaKey === keybinds.navigateUp.metaKey && e.shiftKey === keybinds.navigateUp.shiftKey) {
if (matches.length > 0) {
resetHighlight();
currentIndex = (currentIndex - 1 + matches.length) % matches.length;
updateHighlight();
}
} else if (keybinds.select.keys.includes(e.key) && e.ctrlKey === keybinds.select.ctrlKey && e.metaKey === keybinds.select.metaKey && e.shiftKey === keybinds.select.shiftKey) {
if (currentIndex >= 0 && matches[currentIndex].click) {
matches[currentIndex].click();
modal.style.display = "none";
}
}
else if (e.key === keybinds.newTabSelect.key && e.ctrlKey === keybinds.newTabSelect.ctrlKey && e.metaKey === keybinds.newTabSelect.metaKey && e.shiftKey === keybinds.newTabSelect.shiftKey) {
if (currentIndex >= 0 && matches[currentIndex].click) {
window.open(matches[currentIndex].href, '_blank');
modal.style.display = "none";
}
}
else if (e.key === keybinds.cancel.key && e.ctrlKey === keybinds.cancel.ctrlKey && e.metaKey === keybinds.cancel.metaKey && e.shiftKey === keybinds.cancel.shiftKey) {
modal.style.display = "none";
}
});
input.addEventListener("input", function (e) {
let searchTerm = input.value.toLowerCase();
let isRegex = searchTerm.startsWith("$");
let isHash = searchTerm.startsWith("#");
if (isRegex) {
searchTerm = searchTerm.substring(1);
matches = Array.from(document.querySelectorAll('a, button')).filter(el => el.innerText && new RegExp(searchTerm, "i").test(el.innerText.toLowerCase()));
} else {
matches = Array.from(document.querySelectorAll('a, button')).filter(el => {
if (isHash) {
return (el.innerText && el.innerText.toLowerCase().includes(searchTerm.substring(1)) && el.href && /#.+/.test(el.href)) || (el.href && el.href.includes(searchTerm));
} else {
return el.innerText && el.innerText.toLowerCase().includes(searchTerm) && (!el.href || !/#.+/.test(el.href));
}
});
}
// fk off the junk
let seen = new Set();
matches = matches.filter(el => {
let innerText = el.innerText.trim();
let href = el.href || "";
if (innerText === "" || href === "") {
return false;
}
let identifier = innerText + href;
if (seen.has(identifier)) {
return false;
}
seen.add(identifier);
return true;
});
matches.sort((a, b) => {
let aInnerText = a.innerText.toLowerCase();
let bInnerText = b.innerText.toLowerCase();
if (aInnerText === searchTerm && bInnerText !== searchTerm) {
return -1;
}
if (aInnerText !== searchTerm && bInnerText === searchTerm) {
return 1;
}
return aInnerText.length - bInnerText.length;
});
resultList.innerHTML = '';
if (matches.length > 0) {
currentIndex = 0;
} else {
currentIndex = -1;
}
matches.slice(0, 20).forEach((el, i) => {
let li = document.createElement("li");
Object.assign(li.style, theme.listItem, { cursor: 'pointer' });
let name = document.createElement("span");
name.textContent = el.innerText;
li.appendChild(name);
let href = document.createElement("span");
href.style.textDecoration = theme.href.textDecoration;
if (el.href) {
href.textContent = el.href;
}
li.appendChild(href);
if (i === currentIndex) {
href.style.color = theme.href.selectedColor;
li.style.backgroundColor = theme.listItem.highlightBg;
} else {
href.style.color = theme.href.normalColor;
li.style.backgroundColor = theme.listItem.normalBg;
}
li.addEventListener('click', () => {
if (currentIndex >= 0 && matches[currentIndex].click) {
matches[currentIndex].click();
modal.style.display = "none";
}
});
resultList.appendChild(li);
});
});
function resetHighlight() {
Array.from(resultList.children).forEach((el, i) => {
el.style.backgroundColor = theme.listItem.normalBg;
el.lastChild.style.color = theme.href.normalColor;
});
}
document.addEventListener('focusin', (event) => {
if (modal.style.display === 'block') {
event.preventDefault();
input.focus();
}
});
function updateHighlight() {
if (currentIndex >= 0) {
let highlightedElement = Array.from(resultList.children)[currentIndex];
highlightedElement.style.backgroundColor = theme.listItem.highlightBg;
highlightedElement.lastChild.style.color = theme.href.selectedColor;
highlightedElement.scrollIntoView({ block: 'nearest', inline: 'start' });
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment