Operations on Evernote's todo-lists and checkbox clicking in JS

DevTools: Choose element selection mode to inspect an element

At some point, Evernote removed the option to quickly uncheck your checklist. By "checklist" I mean a to-do list that you go through more than once, so for example, procedures you need to perform in a specific order, such as manually updating a database (1. do a backup, 2. verify the backup, 3. download the data, 4. verify the data...). Those are typically long and will probably contain commands to quickly copy&paste. I'm sure you have one of those :)

DevTools in Evernote

So, the main trick is that the Evernote application is actually a browser (a Chromium-based browser). This also means it has the DevTools you know from Chrome.

  1. You can open DevTools with F12 (or possibly Cmd + Option + I on MacOS).
  2. You can use element selection mode to select some element in the Inspector (see the screenshot). Choose some element in your note.
  3. Make sure this works: document.querySelector('#en-note .list-bullet-todo');

The last part is important because Evernote uses HTML frames to hold notes. Inspecting an element in your note should select that frame for the DevTools. The querySelector will not work if that didn't work.

Unchecking completed items

// Uncheck completed items (run from F12 in Evernote)
document
    .querySelectorAll('#en-note [data-checked="true"] input.list-bullet-todo')
    .forEach(checkbox => {
        let rect = checkbox.getBoundingClientRect();
        let x = rect.left + rect.width / 2;
        let y = rect.top + rect.height / 2;
        let target = document.elementFromPoint(x, y);
        if (!target) target = checkbox;
 
        console.log({ checkbox, x, y, target });
 
        target.dispatchEvent(new MouseEvent('click', {
            bubbles: true,
            cancelable: true,
            view: window,
            clientX: x,
            clientY: y
        }));
    });

Notice the use of [data-checked="true"]. It turns out that, for some bizarre reason, Evernote doesn't actually use the checkbox to store its state. Instead, the state is kept in the parent element. It's a pretty strange design choice: why use an <input> at all if you're not going to use it? ¯\_(ツ)_/¯

Anyway, you can use the same approach to mark everything as completed as well.

Mark as done

You can mark remaining items as completed this way:

document
    .querySelectorAll('#en-note [data-checked="false"] input.list-bullet-todo')
    .forEach(checkbox => {
        let rect = checkbox.getBoundingClientRect();
        let x = rect.left + rect.width / 2;
        let y = rect.top + rect.height / 2;
        let target = document.elementFromPoint(x, y);
        if (!target) target = checkbox;
 
        console.log({ checkbox, x, y, target });
 
        target.dispatchEvent(new MouseEvent('click', {
            bubbles: true,
            cancelable: true,
            view: window,
            clientX: x,
            clientY: y
        }));
    });