Skip to content

Instantly share code, notes, and snippets.

@fearphage
Last active August 22, 2022 21:08
Show Gist options
  • Save fearphage/5cd072ed187e8604ca65b033c853c8c5 to your computer and use it in GitHub Desktop.
Save fearphage/5cd072ed187e8604ca65b033c853c8c5 to your computer and use it in GitHub Desktop.
Modifying Archidekt to add some convenience functionality

Archidekt Enhancements

Current Functionality

Quick Add

  1. Enter selects the first element in the dropdown.
  2. Ctrl-Enter adds the selected card to the maybeboard.
  3. Shift-Enter adds the selected card to the sideboard.

Comming Soon:tm:

Card Overlay - keyboard shortcuts (next, previous, toggle foil, etc.)

// ==UserScript==
// @name Archidekt Enhancements
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Add some convenience functionality to Archidekt
// @author You
// @match https://www.archidekt.com/decks/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=archidekt.com
// @grant GM_log
// ==/UserScript==
(function() {
'use strict';
const debug = (...args) => GM_log('enchance', ...args);
const getQuickAdd = () => document.querySelector('input[placeholder^="Quick Add"]');
// https://developer.mozilla.org/en-US/docs/Web/API/XPathResult#constants
const FIRST_ORDERED_NODE_TYPE = 9;
const xpath = (expression, resultType = FIRST_ORDERED_NODE_TYPE) => document.evaluate(expression, document.body, null, resultType, null);
// finds a card by name and moves it to the maybeboard/sideboard
const moveCard = (name, destination) => {
// find card in decklist
const result = xpath(`//div[starts-with(@id, "stack_")]//*[text()="${name}"]`);
if (!result) {
debug(`Couldn't find "${name}" in decklist`);
return;
}
const element = result.singleNodeValue;
// outermost div for the card/row
// const wrapper = element.closest('div[id^="stack_"] > div');
const eventOptions = {
bubbles: true,
cancelable: true,
view: unsafeWindow,
};
// dont' rush React. take it slow
setTimeout(() => {
element.dispatchEvent(new MouseEvent('mouseover', eventOptions));
setTimeout(() => {
const input = getQuickAdd();
// if we dispatch the mouse event with the input element in focus, it will be ignored
input.blur();
// the first letter should 's' (sideboard) or 'm' (maybeboard)
element.dispatchEvent(new KeyboardEvent('keydown', { key: destination[0], ...eventOptions }));
// retore focus
input.focus()
setTimeout(() => {
element.dispatchEvent(new MouseEvent('mouseleave', eventOptions));
});
}, 100);
}, 100);
};
let shouldIgnore = false;
const arrows = [
'ArrowDown',
'ArrowUp',
'Down',
'Up',
];
// When enter is pressed, select the first result in the list
// even if the first element isn't selected, move it to the appropriate column
// based on the modifier key
//
// ctrl+enter -> Maybeboard
// shift+enter -> Sideboard
const onEnterPressed = e => {
if (e.key !== 'Enter') {
if (arrows.includes(e.key)) {
shouldIgnore = true;
}
return;
}
const firstResult = e.target.closest('span').querySelector('div.result');
const cardName = firstResult.textContent;
// the user is arrowing around so let the plugin handle it
if (!shouldIgnore) {
e.preventDefault();
e.stopImmediatePropagation();
firstResult.click();
}
shouldIgnore = false;
// move the card to appropriate column
if (e.ctrlKey || e.shiftKey) {
setTimeout(moveCard, 500, cardName, e.ctrlKey ? 'maybeboard' : 'sideboard');
}
};
const MAX_COUNT = 10;
let count = 0;
const enhance = () => {
const input = getQuickAdd();
if (!input) {
if (count++ > MAX_COUNT) {
debug('ran out of time waiting for input element to render. bailing...');
}
else {
setTimeout(enhance, 500);
}
}
else {
input.addEventListener('keydown', onEnterPressed, true);
}
}
setTimeout(enhance);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment