I wrote this script so one can press the delete
key on the keyboard to delete the note currently selected in the rabbit hole journal.
How to use
It can be pasted into console or you can search this up on greasyfork.
First, browse to hole.rabbit.tech/journal, then select a note
-
Select a note
And use the delete key on the keyboard to delete the note -
Press
delete
key to delete the selected note -
Multiple selections can be made by holding down the
ctrl
key.
// ==UserScript==
// @name Bind Delete Key to Delete in Rabbit Hole with multiple selection support
// @namespace http://tampermonkey.net/
// @license MIT
// @version 2.1
// @description Binds the Delete key to trigger delete in rabbit hole journal backend. Multiple selection is made with ctrl key.
// @author Rekt
// @match *://hole.rabbit.tech/*
// @grant none
// ==/UserScript==
(function() {
'use strict';
let selectedItems = new Set();
let accessToken = null;
// Hook into fetch to capture access token
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const response = await originalFetch(...args);
if (args[1] && args[1].body) {
try {
const body = JSON.parse(args[1].body);
if (body.accessToken) {
accessToken = body.accessToken;
}
} catch (error) {
console.error("Error parsing request body:", error);
}
}
return response;
};
// Function to delete entries using HTTP deletion and remove placeholders
async function deleteEntries(entryIds) {
if (!accessToken) {
console.error('Access token not available');
return;
}
for (let entryId of entryIds) {
try {
const payload = { accessToken, entryId, deleteEntry: true };
const response = await fetch('/apis/updateJournalEntry', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Remove placeholder from the page
const element = document.querySelector(`[data-entry-id="${entryId}"]`);
if (element) {
element.remove();
}
} catch (error) {
console.error(`Error deleting entry ${entryId}:`, error);
}
}
}
// Function to handle the delete key
function handleDeleteKey(event) {
// Prevent deletion if the user is focused on a contenteditable element
const focusedElement = document.activeElement;
if (focusedElement.hasAttribute('contenteditable')) {
return;
}
// If delete key is pressed and there are selected items, delete them
if (event.key === 'Delete') {
const entryIds = Array.from(selectedItems);
if (entryIds.length > 0) {
deleteEntries(entryIds);
selectedItems.clear();
} else {
// Delete single selected item without Ctrl
const target = document.querySelector('li[data-entry-id].selected');
if (target) {
const entryId = target.getAttribute('data-entry-id');
deleteEntries([entryId]);
target.classList.remove('selected');
}
}
event.preventDefault(); // Prevent default behavior if necessary
}
}
// Function to handle selection with Ctrl key
function handleSelection(event) {
// Check if the clicked element is a list item with a data-entry-id
const target = event.target.closest('li[data-entry-id]');
if (!target) return;
const entryId = target.getAttribute('data-entry-id');
// If Ctrl is pressed, allow multiple selection and toggle current selection state
if (event.ctrlKey) {
if (selectedItems.has(entryId)) {
selectedItems.delete(entryId);
target.classList.remove('selected');
} else {
selectedItems.add(entryId);
target.classList.add('selected');
}
} else {
// Single selection without Ctrl, clear previous selections and select current item
selectedItems.forEach(id => {
const element = document.querySelector(`[data-entry-id="${id}"]`);
if (element) element.classList.remove('selected');
});
selectedItems.clear();
selectedItems.add(entryId);
// Do not apply styling for single selection
}
// Apply styling only for multiple selections
selectedItems.forEach(id => {
const element = document.querySelector(`[data-entry-id="${id}"]`);
if (element && selectedItems.size > 1) element.classList.add('selected');
});
}
// Add event listeners
document.addEventListener('keydown', handleDeleteKey);
document.addEventListener('click', handleSelection);
// Add CSS for the selected class to highlight the selected items
const style = document.createElement('style');
style.innerHTML = `
.selected {
background-color: yellow;
}
`;
document.head.appendChild(style);
})();