3

I am writing a Greasemonkey script to interact with orders on Shipstation.com.

The script will select certain values in <select> and <input> elements of the order modal based on certain criteria.

Thus, the script must be able to interact with these elements.

However, I cannot figure out how to do so.

So far, I have tried to do the following and have been unable to trigger a click on the element:

  • Set the value of the element using JS .value
  • Set the value of the element using jQuery .val
  • Trigger a click event on the element using JS .click()
  • Trigger a click event on the element using this code:
function triggerMostButtons (jNode) {
    triggerMouseEvent (jNode, "mouseover");
    triggerMouseEvent (jNode, "mousedown");
    triggerMouseEvent (jNode, "mouseup");
    triggerMouseEvent (jNode, "click");
}

function triggerMouseEvent (node, eventType) {
    var clickEvent = document.createEvent('MouseEvents');
    clickEvent.initEvent (eventType, true, true);
    node.dispatchEvent (clickEvent);
}

triggerMostButtons(jNode);

It appears that Shipstation is locking the value of <select> and <input> values.

Here are examples of the SO questions I have read to try and figure this out. I haven't been able to trigger a click on these elements using any of these approaches:

How else can I trigger a click on these elements?

Alternatively, how can I set the value of these fields using JS? Do I have to find the data model in the JS and edit the value directly? Or find a way to hijack the functions that are triggered when a user clicks on these elements?

enter image description here

Sean
  • 963
  • 1
  • 10
  • 28

3 Answers3

0

Maybe the values are loaded dynamically from the server, so you need to wait until the full page is loaded by adding a load event.

Then grab the select elements by a document.getElementById (or querySelector) and set your desired value (If I understood correctly, you don't need a click event).

You didn't provide an example I can work with, but I tried it with this https://www.shipstation.com/step1/ Notice how after the page loads, the country will be set to Canada:

// ==UserScript==
// @name     Unnamed Script 933923
// @version  1
// @grant    none
// @match *://*.shipstation.com/*
// ==/UserScript==


window.addEventListener('load', (event) => {
  
  document.getElementById('country').value = "CA";
  document.getElementById('howdidyouhearaboutus').value = "Banner Ad";
  
});
ahmelq
  • 593
  • 7
  • 11
  • Sorry I wasn't more clear - the elements I am trying to interact with are the drop downs that define the an order's properties. Your method doesn't set the values of those dropdowns (it only changes them cosmetically). – Sean Apr 24 '22 at 03:29
  • Sean your response above sounds like you expect an event to be fired. How about calling that directly from your script instead of relaying on events? – Chris S. Apr 24 '22 at 21:45
0

you can select an option by doing this

function selectItemInDropdownList(selectElement, ov) {
  const optionToSelect = '' + ov
  const options = selectElement.getElementsByTagName('option')
  for (const optionEle of options) {
    if (optionToSelect === optionEle.innerText || optionToSelect === optionEle.value) {
      optionEle.selected = true // selects this option
      return true
    }
  }
  return false // failed
}

/*
const dropdownEle = document.getElementById('whatever')
const status = selectItemInDropdownList(dropdownEle, "WHAT") 
console.log(status ? 'success' : 'failed')
*/

I think main issue is its a popup form and the select element 'may' not be available in DOM tree at first. so make sure to call this function when its available.

bogdanoff
  • 1,705
  • 1
  • 10
  • 20
  • As I mention in my question - I need to set the state of the page, this doesn't set the state of the page. – Sean May 09 '22 at 22:21
  • what do you mean by "state of the page" and where have you mentioned it because i cant find it question. – bogdanoff May 10 '22 at 04:21
0

This solution works well in 2022. No jQuery is used.

Auto expand select options in element cb:

cb.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }))

Input focus on element cb (tested on Safari), watch the compatibility note on MDN:

cb.focus()

Below are the working solution for you to copy and run on a browser. (Since input focus feature is failed to run in the code snippet here, while the feature auto expand the select options still works.)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <select id="select-1">
        <option value="1">Option 1</option>
        <option value="2">Option 2</option>
    </select>

    <input id="input-1" type="text"/> 

    <script>
        window.onload = function() {
            const select = document.getElementById('select-1');
            const input = document.getElementById('input-1');

            input.focus();
            setTimeout(function() {
                select.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
            }, 1000);
        }
    </script>
</body>
</html>
mondayrris
  • 539
  • 4
  • 13
  • As I mention in my question - I need to set the state of the page. Your code only sets the value of an option whose state is not controlled by backbone / react etc. – Sean May 09 '22 at 22:22
  • Noted, let’s clarify. Is that you need a pure javascript solution or other else? – mondayrris May 09 '22 at 22:38
  • My current solution is missing a handle change and storing e.target.value to global window, as a workaround of page state, isn’t it? – mondayrris May 09 '22 at 22:40