Search code examples
javascriptgreasemonkeyautofilluserscriptstampermonkey

Clicking multiple buttons automatically with the addition of waitForKeyElements


I've been searching for a way to automatically select survey form buttons that contain specific words across different websites. I am using Tampermonkey in Google Chrome to achieve this. In this case, I would like to automatically select buttons with the word 'Male' and 'Mr.' in them.

Here is an example of the type of button I am talking about (including CSS/HTML):

enter image description here

I am currently using the following code in Tampermonkey to achieve the pressing effect:

// ==UserScript==
// @name         Male Test 3
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://tasupport.co1.qualtrics.com/jfe/form/SV_0qez6NHJGoCAmMt
// @match        https://tasupport.co1.qualtrics.com/jfe2/form/SV_0qez6NHJGoCAmMt/next?rand=775440350&tid=1&t=1547858208474
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
// @require     https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant       GM_addStyle
// ==/UserScript==

const fire = () => Array.from(document.querySelectorAll('label > span')).find(e => e.textContent === 'Male').parentElement.click();

waitForKeyElements (
    "label",
    fire
);

The above script successfully selects "Male" upon page load of the above site, but I am unsure how to click on multiple buttons at the same time. I want to also automatically select "Mr." as well, which is another button on the page. So ultimately, I want the script to select Male AND Mr. when the page loads. Fortunately, they are both within a "label," so I think the waitForKeyElements might be fine.

Unfortunately, JavaSript isn't my wheelhouse and I'm having trouble finding the correct syntax to make this possible. It seems like such an easy fix.

I tried things like find(e => e.textContent === 'Male', 'Mr.') but to no avail.

Essentially, all I need to do is include the text for 'Mr.' along with the already specified 'Male.' Any and all help would be awesome.


Solution

  • You can make a function that, given a <span>'s text to find, .finds the appropriate element and clicks its parent. Once waitForKeyElements triggers, call that function with Male and Mr.:

    const findAndClickParent = text => [...document.querySelectorAll('label > span')]
      .find(e => e.textContent === text)
      .parentElement
      .click();
    
    waitForKeyElements (
      "label",
      () => {
        findAndClickParent('Male');
        findAndClickParent('Mr.');
      }
    );
    

    If you wanted to be more efficient, you could create an object of those matching elements when the callback triggers (assuming none that you care about overlap), and access the appropriate property each time, for example:

    waitForKeyElements (
      "label",
      () => {
        const parentsByTextContent = Array.prototype.reduce.call(
          document.querySelectorAll('label > span'),
          (a, e) => {
            a[e.textContent] = e.parentElement;
            return a;
          },
          {}
        );
        parentsByTextContent['Male'].click();
        parentsByTextContent['Mr.'].click();
      }
    );