Skip to content

Instantly share code, notes, and snippets.

@sarnobat
Last active May 11, 2024 00:51
Show Gist options
  • Save sarnobat/b0e3f179fdc4636bbc1de3f20f1d10f3 to your computer and use it in GitHub Desktop.
Save sarnobat/b0e3f179fdc4636bbc1de3f20f1d10f3 to your computer and use it in GitHub Desktop.

Greasemonkey Phrasebook

1) Wait for page to load

window.addEventListener('load', function() {
    alert('page loaded')
}, false);

2) Prepend TODO to top of page

function prependButton(text, onClick) {
  // Create the button element
  const button = document.createElement('button');

  // Set the button text
  button.textContent = text;

  // Add an onClick event listener
  button.addEventListener('click', onClick);

  // Prepend the button to the body
  document.body.prepend(button);
}

3) Fill a text box only if the relevant label exists, do not cause an error

if (elem = document.evaluate('//*[contains(text(), "Username or Library Card Number")]',document).iterateNext()) {
    elem.nextSibling.nextSibling.value = 'sarnobat';
}

4) Click dropdown and wait, then select option

setTimeout(() => {console.log('pep related');                document.evaluate('//*[@aria-controls="dropdown-18"]',document,null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE).snapshotItem(0).click();}, startTime); startTime += interval;
setTimeout(() => {console.log('pep related');                document.querySelector("#No1").click();}, startTime); startTime += interval;

5) Chain actions together, by dependency

setTimeout(() => {
    document.evaluate("//*/input[contains(@data-automation-id, 'name')]",document).iterateNext().value = "Sridhar Sarnobat";
    setTimeout(() => {
    document.evaluate("//*[text()='Save and Continue']",document).iterateNext().click();
    }, interval+buffer);
}, interval);

6) Chain actions together, by time delay (without nesting hell)

Really long lines but it's easier to read repeatable lines

var startTime = 6000;
var interval = 1500;

setTimeout(() => {console.log('username');    document.evaluate('//*[contains(text(), "Username or Library Card Number")]',document).iterateNext().nextSibling.nextSibling.value = 'sarnobat'; }, startTime); startTime += interval;
setTimeout(() => {console.log('log in');    document.evaluate('//*[@value="Log In"]',document).iterateNext().click(); },                                                                        startTime); startTime += interval;

7) Find button by visible text (not by ID) using XPath

Visible text is less fragile. DOM changes frequently

document.evaluate('//*[contains(text(), "Walmart Career Site")]',document).iterateNext().click()

8) Find text field by neighboring visible text (not by ID) using XPath

Visible text is less fragile.

  • DOM changes frequently

  • ids are not always present

  • other attributes are not unique

    document.evaluate('//*[contains(text(), "Username or Library Card Number")]',document).iterateNext().nextSibling.nextSibling.value = 'sarnobat'

9) Delete an obtrusive element

document.evaluate('//*[contains(text(), "Stanford Careers")]',document).iterateNext().parentNode.parentNode.style.display = 'none'

Others, less critical

a) (reactnative) fill in text field

function fillTextField(id, text) {
            let element = document.evaluate(
                '//*[@id="'+id+'"]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)
                .snapshotItem(0);
            setNativeValue(element, text);
            element.dispatchEvent(new Event('input', { bubbles: true }));
}

function setNativeValue(element, value) {
    const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set;
    const prototype = Object.getPrototypeOf(element);
    const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;

    if (valueSetter && valueSetter !== prototypeValueSetter) {
        prototypeValueSetter.call(element, value);
    } else {
        valueSetter.call(element, value);
    }
}

b) (reactnative) click button that uses reactNative

async function simulateMouseClick(el) {
    let opts = {view: window, bubbles: true, cancelable: true, buttons: 1};
    el.dispatchEvent(new MouseEvent("mousedown", opts));
    await new Promise(r => setTimeout(r, 50));
    el.dispatchEvent(new MouseEvent("mouseup", opts));
    el.dispatchEvent(new MouseEvent("click", opts));
}

c) (reactnative) select dropdown value

function fillDropdown(selectId, optionValue) {
                    var selectElement = document.evaluate(
                    '//*[@id="'+selectId+'"]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)
                    .snapshotItem(0);
    var trigger2 = Object.getOwnPropertyDescriptor(
      window.HTMLSelectElement.prototype,
      "value"
    ).set;
    trigger2.call(selectElement, optionValue);
    var event2 = new Event("change", { bubbles: true });
    selectElement.dispatchEvent(event2);
}

d) (reactnative) checkbox toggle

function toggleCheckbox(id) {
        const input = document.evaluate(
        '//*[@id="'+id+'"]', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)
        .snapshotItem(0);
    simulateMouseClick(input);
}

e) Print ID of each form element

function printFormFieldsIdByXpath() {
    var out = "";
    var out3 = "";
  // Get all form elements
  const forms = document.getElementsByTagName('form');

  // Loop through each form
  for (const form of forms) {
    // Get all input elements within the form using XPath
    const inputElements = document.evaluate(
      ".//input[@id]",
      form,
      null,
      XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
      null
    );

    // Loop through each input element and print its ID
    for (let i = 0; i < inputElements.snapshotLength; i++) {
      const element = inputElements.snapshotItem(i);
        if (element.type="text") {
        out += "id = " + element.id + "\t\taria-label=" + element.getAttribute("aria-label")+ "\tvalue = " +element.value+"\n";
        } else if (element.type="radio") {
        out3 += "[radio] id = " + element.id + "\t\taria-label=" + element.getAttribute("aria-label") +"\n";
        }
    }
}

f) Print options from a select input

function printAllSelectOptionsByXpath() {
    // Get all select elements using XPath
    const selectElements = document.evaluate("//select", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

    // Loop through each select element
    for (let i = 0; i < selectElements.snapshotLength; i++) {
    const selectElement = selectElements.snapshotItem(i);

    // Get all option elements within the select element
    const options = selectElement.querySelectorAll("option");
var out = "";
    // Loop through each option element and print its text content
    for (const option of options) {
//      console.log(`Option: ${option.innerText}`);

//        out +=  selectElement.id

    }
    console.log(selectElement.id)

    var out2 = selectElement.id +  "\n========================\n";
    for (const option of options) {

        out2 += option.innerText + "\n";

    }
    //   +"\t\ttext = " + option.innerText +"\n";
    console.log(out2)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment