Last active
February 22, 2024 07:55
-
-
Save darotar/bb2cc301f5dc642b5e0b0f8bf0281de0 to your computer and use it in GitHub Desktop.
Custom key bindings for Chat Open AI using TamperMonkey
This file contains 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
// ==UserScript== | |
// @name Custom Key Bindings for Chat.OpenAI | |
// @namespace http://tampermonkey.net/ | |
// @version 0.1 | |
// @description Add custom key bindings to Chat.OpenAI | |
// @author You | |
// @match https://chat.openai.com/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=openai.com | |
// @grant none | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
let currentSelectionIndex = -1; // No selection initially | |
function setupInputStyles(inputOverlay) { | |
inputOverlay.style.position = 'fixed'; | |
inputOverlay.style.top = '10px'; | |
inputOverlay.style.left = '50%'; | |
inputOverlay.style.transform = 'translateX(-50%)'; | |
inputOverlay.style.zIndex = '10000'; | |
inputOverlay.style.width = '80%'; | |
inputOverlay.style.padding = '10px'; | |
inputOverlay.style.fontSize = '16px'; | |
} | |
function setupDropdownStyles(dropdown) { | |
dropdown.style.position = 'fixed'; | |
dropdown.style.top = '50px'; | |
dropdown.style.left = '50%'; | |
dropdown.style.transform = 'translateX(-50%)'; | |
dropdown.style.zIndex = '10000'; | |
dropdown.style.width = '80%'; | |
dropdown.style.maxHeight = '300px'; | |
dropdown.style.overflowY = 'auto'; | |
dropdown.style.background = '#3b3b3b'; | |
dropdown.style.border = '1px solid #ccc'; | |
dropdown.style.boxShadow = '0 4px 6px rgba(0,0,0,.1)'; | |
} | |
function updateDropdown(value, dropdown) { | |
// Clear previous results | |
dropdown.innerHTML = ''; | |
// Get all li elements | |
const items = Array.from(document.querySelector('nav').querySelectorAll('li')).filter(li => li.querySelector('div > a > div').textContent.toLowerCase().includes(value.toLowerCase())); | |
// Create a dropdown item for each match | |
items.forEach(item => { | |
const div = document.createElement('div'); | |
div.style.padding = '10px'; | |
div.style.borderBottom = '1px solid #eee'; | |
div.textContent = item.querySelector('div > a > div').textContent; | |
div.setAttribute('data-link', item.querySelector('div > a').attributes.href.value); | |
div.addEventListener('click', () => { | |
document.getElementById('customInputOverlay').value = div.textContent; | |
dropdown.innerHTML = ''; // Clear dropdown after selection | |
}); | |
dropdown.appendChild(div); | |
}); | |
// Show or hide dropdown based on matches | |
dropdown.style.display = items.length > 0 ? '' : 'none'; | |
} | |
function createInputOverlay() { | |
// Check if the input already exists | |
let inputOverlay = document.getElementById('customInputOverlay'); | |
if (!inputOverlay) { | |
// Create the input element | |
inputOverlay = document.createElement('input'); | |
inputOverlay.id = 'customInputOverlay'; | |
setupInputStyles(inputOverlay); | |
// Append the input to the body | |
document.body.appendChild(inputOverlay); | |
// Focus the input | |
inputOverlay.focus(); | |
let dropdown = document.createElement('div'); | |
dropdown.id = 'customInputDropdown'; | |
setupDropdownStyles(dropdown); | |
document.body.appendChild(dropdown); | |
inputOverlay.addEventListener('input', function() { | |
updateDropdown(inputOverlay.value, dropdown); | |
}); | |
// Handle the enter key (submit) | |
inputOverlay.addEventListener('keydown', function(e) { | |
const items = dropdown.querySelectorAll('div'); | |
if (e.key === 'ArrowDown') { | |
e.preventDefault(); | |
if (currentSelectionIndex < items.length - 1) { | |
currentSelectionIndex++; | |
updateHighlight(items); | |
} | |
} else if (e.key === 'ArrowUp') { | |
e.preventDefault(); | |
if (currentSelectionIndex > 0) { | |
currentSelectionIndex--; | |
updateHighlight(items); | |
} | |
} else if (e.key === 'Enter') { | |
e.preventDefault(); | |
if (currentSelectionIndex >= 0 && currentSelectionIndex < items.length) { | |
document.querySelector(`a[href="${items[currentSelectionIndex].dataset.link}"]`).click(); | |
inputOverlay.value = items[currentSelectionIndex].textContent; | |
dropdown.innerHTML = ''; | |
dropdown.style.display = 'none'; | |
document.getElementById('customInputOverlay').remove(); | |
document.getElementById('customInputDropdown').remove(); | |
currentSelectionIndex = -1; | |
} | |
} | |
}); | |
} else { | |
document.getElementById('customInputOverlay').remove(); | |
document.getElementById('customInputDropdown').remove(); | |
currentSelectionIndex = -1; | |
} | |
} | |
function updateHighlight(items) { | |
// Remove highlight from all items | |
items.forEach(item => { | |
item.style.background = '#3b3b3b'; | |
}); | |
// Highlight the current selection | |
if (items[currentSelectionIndex]) { | |
items[currentSelectionIndex].style.background = '#7f7f7f'; | |
items[currentSelectionIndex].scrollIntoView({ block: 'nearest', behavior: 'smooth' }); | |
} | |
} | |
document.addEventListener('keydown', function(e) { | |
if (e.altKey && e.shiftKey) { | |
switch (e.code) { | |
case "KeyN": | |
e.preventDefault(); | |
document.querySelector('button > svg').parentElement.click(); | |
break; | |
case "KeyF": | |
e.preventDefault(); | |
createInputOverlay(); | |
break; | |
} | |
} | |
}); | |
// Your code here... | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment