// ==UserScript== // @name ⌘⌫ Element // @description ⌘⌫ deletes element under cursor, ⌘Z puts back // @match *://*.* // ==/UserScript== let undoWindow = 3000 // can undo for this long let undoCooldown = 1500 // will prevent default undo for this long after last undo let scheduledDeletion = null // timeout id for deleteElements let lastHide = 0 // timestamp for last element was hidden let lastUndo = 0 // timestamp for last successful undo let hiddenElements = [] // elements that can be unhidden by undo let cmdCombo = (ev, key) => !ev.shiftKey && !ev.ctrlKey && !ev.altKey && ev.metaKey && ev.key == key let tsWithin = (ts, t) => (Date.now() - ts) <= t let deleteElements = () => { let e; while ([e,] = hiddenElements.pop()||[]) e.parentNode.removeChild(e) } document.addEventListener('keydown', function(ev) { if (cmdCombo(ev, 'Backspace')) { let el = [...document.querySelectorAll(":hover")].pop() // get innermost elem with under pointer hiddenElements.push([el, el.style.display]) // keep track of it for undo el.style.display = 'none' // hide it lastHide = Date.now() // timestamp for undo window window clearTimeout(scheduledDeletion) // clear pending deletion to extend undo window scheduledDeletion = setTimeout(deleteElements, undoWindow + 1) // really delete elements after undo window times out ev.preventDefault() } if (cmdCombo(ev, 'z') && tsWithin(lastHide, undoWindow)) { let [el, d] = hiddenElements.pop() || [] if (el) { el.style.display = d lastUndo = Date.now() } // preventDefault if we restored an element, or if it's only been 1500ms since last undo, // so you don't accidentally reopen a tab by way of over-undoing if (el || tsWithin(lastUndo, undoCooldown)) ev.preventDefault() } })