Bookmarklets

Scihubify

location.href = 'https://sci-hub.tw/' + location.href

Waybackify

location.href = 'https://web.archive.org/web/*/' + location.href

Record Meet Captions

Records the automatic captions generated by google meet into a new window.

(function() {
    let title = "Captions for " + document.title
    let win = window.open("", title, "width=780,height=200");
    win.document.head.innerHTML = "<title>" + title + "</title>";
    win.document.body.innerText = "";

	function isInfixOf(foo, foobar) {
		return foobar.replace(foo, '') !== foobar;
	}

    // The class names are obfuscated. They'll probably change each time Meet is updated.
    const CAPBOX_CLASS = 'TBMuR';
    const CAPAREA_CLASS = 'a4cQT';

    // Go up the chain looking for the caption containing the new span.
    function findbox(nn) {
        while (!isInfixOf(CAPBOX_CLASS, nn.className) && ('parentNode' in nn)) {
            nn = nn.parentNode;
        }
        if (isInfixOf(CAPBOX_CLASS, nn.className)) {
            return nn;
        }
        return null;
    }

    let lastnode = null;

    function callback_node(node) {
        box = findbox(node);
        if (box === null) {
            return;
        }
        if (lastnode !== null && box.innerText.toLowerCase().startsWith(lastnode.innerText.slice(0,20).toLowerCase())) {
            // Update the last caption.
            console.log('appending', box.innerText)
            lastnode.innerText = box.innerText;
        } else {
            // Create a new caption item.
            console.log('creating', box.innerText)
            let newnode = win.document.createElement('div');
            newnode.innerText = box.innerText;
            win.document.body.appendChild(newnode);
            lastnode = newnode;
        }
    }

    function callback(records) {
        for (record of records) {
            for (node of record.addedNodes) {
                callback_node(node);
            }
        }
    }

    var observer = new MutationObserver(callback);
    // Set a watch on the caption area.
    var targetNode = document.body.getElementsByClassName(CAPAREA_CLASS)[0];
    observer.observe(targetNode, { childList: true, subtree: true });
})();

Enable Text Selection

Override evil web pages that abuse user-select: none.

(function() {
	body = document.querySelector('body');
	st = document.createElement('style');
	st.innerText = '* { user-select: auto !important }';
	body.appendChild(st);
})();

Kill Sticky

Pretty much redundant now that AlwaysKillSticky exists.

(function() {
    var i, elements = document.querySelectorAll('body *');
    for (i = 0; i < elements.length; i++) {
        position = getComputedStyle(elements[i]).position;
        if (position === 'fixed' || position === 'sticky') {
            elements[i].parentNode.removeChild(elements[i]);
        }
    }
})();

Click to Remove

Toggle a mode that kills elements when you click on them.

(function() {
    if (window._rm_md) {
        document.onmousedown = window._rm_md;
        window._rm_md = null;
    } else {
        window._rm_md = document.onmousedown || function() {};
        document.onmousedown = function(e) {
            e = e || window.event;
            e.target.parentNode.removeChild(e.target);
        };
    }
})();