0

Trying to maintain my sense of humour here - I've been blundering around trying to prepare code which will allow me to auto-complete different parts of a web form using the console. I can't use Selenium. After marking lots of progress (with the help of answers from here), the website has been updated (using Bootstrap?) and most of my commands now don't work. On this particular item, there is a dropdown menu on the page which brings up a list of colours. Clicking on one or more colours will make it selected in the input box. I am trying to achieve the same by putting code into the console.

I tried repurposing the the code I was using before, but I think the element is entirely different type. Can anyone assist please? Below is the code for the dropdown (I don't think I need to include the HTML here?):

<div class="form-group col-sm-12" element="div"> <label>colour type</label>
  <select name="colourTypes[]" style="width: 100%" data-init-function="bpFieldInitSelect2MultipleElement" data-select-all="false" data-options-for-js="[2,1,5,7,6,13,12,9,10,16,4,15,3,8,11]" class="form-control 
select2_multiple select2-hidden-accessible" multiple="" data-select2-id="10" tabindex="-1" aria-hidden="true" data-initialized="true">

    <option value="" data-select2-id="17">-</option>

    <option value="2" data-select2-id="18">N/A</option>
    <option value="1" data-select2-id="19">Red</option>
    <option value="5" data-select2-id="20">Green</option>
    <option value="7" data-select2-id="21">Blue</option>
    <option value="6" data-select2-id="22">Magenta</option>
    <option value="13" data-select2-id="23">Turquoise</option>
    <option value="12" data-select2-id="24">Maroon</option>
    <option value="9" data-select2-id="25">Olive</option>
    <option value="10" data-select2-id="26">Yellow</option>
    <option value="16" data-select2-id="27">Grey</option>
    <option value="4" data-select2-id="28">Silver</option>
    <option value="15" data-select2-id="29">Other/Unclear</option>
    <option value="3" data-select2-id="30">Crimson</option>
    <option value="8" data-select2-id="31">Dark blue</option>
    <option value="11" data-select2-id="32">Light blue</option>

  </select><span class="select2 select2-container select2-container--bootstrap select2-container--
focus select2-container--below select2-container--open" dir="ltr" data-select2-id="11" style="width: 100%;"><span class="selection"><span class="select2-selection select2-selection--multiple" 
role="combobox" aria-haspopup="true" aria-expanded="true" 
tabindex="-1" aria-disabled="false" aria-owns="select2-colourTypes-9c-results">
<ul class="select2-selection__rendered"><li class="select2-search select2-search--inline">
<input class="select2-search__field" 
type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="none" spellcheck="false" role="searchbox" aria-autocomplete="list" 
placeholder="" style="width: 0.75em;" aria-controls="select2-colourTypes-9c-results">
</li></ul></span></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>



</div>
Yesterdec
  • 37
  • 1
  • 6

2 Answers2

0

Yes. One option is grabbing all the options and loop over them.

Then, select the desired options.

const options = document.querySelectorAll('select[name="colourTypes[]"] option'); // a CSS selector

[...options].forEach((curr) => {
  // Select values of 1, 5, and ''
  if (['1', '5', ''].indexOf(curr.value) !== -1) {
    curr.selected = true;
  }
});
<div class="form-group col-sm-12" element="div"> <label>colour type</label>
  <select name="colourTypes[]" style="width: 100%" data-init-function="bpFieldInitSelect2MultipleElement" data-select-all="false" data-options-for-js="[2,1,5,7,6,13,12,9,10,16,4,15,3,8,11]" class="form-control 
select2_multiple select2-hidden-accessible" multiple="" data-select2-id="10" tabindex="-1" aria-hidden="true" data-initialized="true">

    <option value="" data-select2-id="17">-</option>

    <option value="2" data-select2-id="18">N/A</option>
    <option value="1" data-select2-id="19">Red</option>
    <option value="5" data-select2-id="20">Green</option>
    <option value="7" data-select2-id="21">Blue</option>
    <option value="6" data-select2-id="22">Magenta</option>
    <option value="13" data-select2-id="23">Turquoise</option>
    <option value="12" data-select2-id="24">Maroon</option>
    <option value="9" data-select2-id="25">Olive</option>
    <option value="10" data-select2-id="26">Yellow</option>
    <option value="16" data-select2-id="27">Grey</option>
    <option value="4" data-select2-id="28">Silver</option>
    <option value="15" data-select2-id="29">Other/Unclear</option>
    <option value="3" data-select2-id="30">Crimson</option>
    <option value="8" data-select2-id="31">Dark blue</option>
    <option value="11" data-select2-id="32">Light blue</option>

  </select><span class="select2 select2-container select2-container--bootstrap select2-container--
focus select2-container--below select2-container--open" dir="ltr" data-select2-id="11" style="width: 100%;"><span class="selection"><span class="select2-selection select2-selection--multiple" 
role="combobox" aria-haspopup="true" aria-expanded="true" 
tabindex="-1" aria-disabled="false" aria-owns="select2-colourTypes-9c-results">
<ul class="select2-selection__rendered"><li class="select2-search select2-search--inline">
<input class="select2-search__field" 
type="search" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="none" spellcheck="false" role="searchbox" aria-autocomplete="list" 
placeholder="" style="width: 0.75em;" aria-controls="select2-colourTypes-9c-results">
</li></ul></span></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>



</div>
Chris Happy
  • 7,088
  • 2
  • 22
  • 49
0

I might need more clarity on what you're looking to do, but from what I gathered from your question, I think you're looking for a way to populate all these fields using your console, specifically this select field. You should be able to populate it simply by setting its value equal to the value of the option you want to select.

Using the code that you included, the below JavaScript would select the option with a value of 5, namely "Green":

document.querySelector('select[name="colourTypes[]"]').value = "5";
// selected  —>  <option value="5" data-select2-id="20">Green</option>

Once running this, you can even test to ensure it actually selected that option with either of these methods in your console:

Array.from(document.querySelectorAll('select[name="colourTypes[]"] option')).filter(e => e.selected)[0].value;
// returns "5"
Array.from(document.querySelectorAll('select[name="colourTypes[]"] option')).filter(e => e.selected)[0].textContent;
// returns "Green"
document.querySelector('select[name="colourTypes[]"]').value;
// returns "5"

To do this for multiple fields, you could either do something similar to this method for each and just run them consecutively. This is one way to complete this task. Another way to accomplish this—my preferred method—is to create a JavaScript object with all the key/value (field name/value) pairs and then loop over the object instead. This makes it easier for you to adjust your choices and additional fields later without having to worry about which type of field a particular field is.

Let's see that in action here:

const fieldValues = {
  "Full Name": "David Webb",
  "Alias": "Jason Bourne",
  "Food": ["chicken","tacos"],
  "Color": "#663399",
  "DOB": "1970-09-13",
  "Email": "thebourneybunch@gmail.com",
  "Spam": "phone",
  "Places": ["north-america","europe","antarctica"],
  "State": "MO",
  "Bio": "No, it doesn't start to come back. The knot's like everything else, I just found the rope and I did it.\n\nThe same way I can read, I can write, I can add, subtract, I can make coffee, I can shuffle cards, I can set up a chessboard.",
  "Username": "JamesBondWishesHeWasMe",
  "Password": "Kittens4EVER!"
};

const button = document.querySelector('button');
button.addEventListener('click', function() {
  // loop through the `fieldValues` object we created to compare your desired values with those of the form fields
  for ([fieldName, value] of Object.entries(fieldValues)) {
    // store all found fields of each field name into a `fields` variable
    const fields = Array.from(document.querySelectorAll(`[name="${fieldName}"]`));
    // ensure that at least one field exists for each requested field name
    if (fields.length) {
      // if the input type permits multiple selected values (e.g. checkbox list, multi-select field)
      if (fields[0].matches && (fields.length > 1 || (fields.length === 1 && fields[0].matches('select[multiple]')))) {
        // store desired value as an array, even if it is a string, (i.e. "0" —> ["0"], ["1","2"] —> ["1","2"])
        const values = [value].flat();
        const isMultiSelect = fields[0].matches('select[multiple]');
        // if the field is a multi-select field, evaluate its child option elements, otherwise, evaluate the actual fields (checkboxes)
        const fieldOptions = isMultiSelect ? Array.from(fields[0].querySelectorAll('option')) : fields;
        // deselect any pre-selected options for fields with the associated field name, using the selected/checked properties accordingly
        fieldOptions.forEach(option => option[isMultiSelect ? "selected" : "checked"] = false);
        // select/check any options/checkboxes that match values from the `fieldValues` object
        fieldOptions.filter(option => values.includes(option.value)).forEach(option => option[isMultiSelect ? "selected" : "checked"] = true);
      } else {
        // if the field type only accepts one value, set it equal to the value from the `fieldValues` object
        fields[0].value = value;
      }
    }
  }
});
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css');

body {
  padding: 30px;
}
form {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 10px;
}
label, input, textarea, select, button {
  font-family: system-ui, arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
select[multiple] {
  height: 130px;
  overflow: hidden;
}
textarea {
  height: 90px;
  resize: none;
}
label, button {
  font-weight: bold;
}
label + div {
  display: flex;
  flex-wrap: wrap;
  gap: 5px 10px;
}
label + div > label {
  white-space: nowrap;
}
button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  appearance: none;
  -webkit-appearance: none;
  margin-bottom: 20px;
  padding: 8px 16px;
  background-color: #58f;
  border: none;
  border-radius: 50px;
  font-size: 18px;
  color: #fff;
  cursor: pointer;
}
button i {
  margin-left: 10px;
}
<button>Fill this form<i class="fas fa-magic"></i></button>

<form>
  <label for="fullName">Full Name</label>
  <input id="fullName" type="text" name="Full Name" placeholder="Clark Kent">
  <label for="alias">Alias</label>
  <input id="alias" type="text" name="Alias" placeholder="Superman (you get the idea…)">
  <label for="favoiteColor">Favorite Color</label>
  <input id="favoiteColor" type="color" name="Color" value="#FF0000">
  <label for="food">I'm craving…</label>
  <select id="food" name="Food" multiple>
    <option value="chicken">Chicken</option>
    <option value="fried-rice">Fried rice</option>
    <option value="pizza">Pizza</option>
    <option value="tacos">Tacos</option>
    <option value="ice-cream">Ice cream</option>
    <option value="pasta">Pasta</option>
  </select>
  <label for="dob">DOB</label>
  <input id="dob" type="date" name="DOB">
  <label for="email">Email Address</label>
  <input id="email" type="email" name="Email">
  <label for="spam">Spam me via…</label>
  <div>
    <label for="spam-email"><input id="spam-email" type="radio" name="Spam" value="email"> Email</label>
    <label for="spam-phone"><input id="spam-phone" type="radio" name="Spam" value="phone"> Phone</label>
</div>
  <label for="places">I've been to…</label>
  <div>
    <label for="africa"><input id="africa" type="checkbox" name="Places" value="africa"> Africa</label>
    <label for="antarctica"><input id="antarctica" type="checkbox" name="Places" value="antarctica"> Antarctica</label>
    <label for="asia"><input id="asia" type="checkbox" name="Places" value="asia"> Asia</label>
    <label for="australia"><input id="australia" type="checkbox" name="Places" value="australia"> Australia</label>
    <label for="europe"><input id="europe" type="checkbox" name="Places" value="europe"> Europe</label>
    <label for="north-america"><input id="north-america" type="checkbox" name="Places" value="north-america"> North America</label>
    <label for="south-america"><input id="south-america" type="checkbox" name="Places" value="south-america"> South America</label>
</div>
  <label for="state">Home state</label>
  <select id="state" name="State">
    <option value="" style="display: none;" disabled="disabled" selected="selected">Choose a state…</option>
    <option value="AL">Alabama</option>
    <option value="AK">Alaska</option>
    <option value="AZ">Arizona</option>
    <option value="AR">Arkansas</option>
    <option value="CA">California</option>
    <option value="CO">Colorado</option>
    <option value="CT">Connecticut</option>
    <option value="DE">Delaware</option>
    <option value="FL">Florida</option>
    <option value="GA">Georgia</option>
    <option value="HI">Hawaii</option>
    <option value="ID">Idaho</option>
    <option value="IL">Illinois</option>
    <option value="IN">Indiana</option>
    <option value="IA">Iowa</option>
    <option value="KS">Kansas</option>
    <option value="KY">Kentucky</option>
    <option value="LA">Louisiana</option>
    <option value="ME">Maine</option>
    <option value="MD">Maryland</option>
    <option value="MA">Massachusetts</option>
    <option value="MI">Michigan</option>
    <option value="MN">Minnesota</option>
    <option value="MS">Mississippi</option>
    <option value="MO">Missouri</option>
    <option value="MT">Montana</option>
    <option value="NE">Nebraska</option>
    <option value="NV">Nevada</option>
    <option value="NH">New Hampshire</option>
    <option value="NJ">New Jersey</option>
    <option value="NM">New Mexico</option>
    <option value="NY">New York</option>
    <option value="NC">North Carolina</option>
    <option value="ND">North Dakota</option>
    <option value="OH">Ohio</option>
    <option value="OK">Oklahoma</option>
    <option value="OR">Oregon</option>
    <option value="PA">Pennsylvania</option>
    <option value="RI">Rhode Island</option>
    <option value="SC">South Carolina</option>
    <option value="SD">South Dakota</option>
    <option value="TN">Tennessee</option>
    <option value="TX">Texas</option>
    <option value="UT">Utah</option>
    <option value="VT">Vermont</option>
    <option value="VA">Virginia</option>
    <option value="WA">Washington</option>
    <option value="WV">West Virginia</option>
    <option value="WI">Wisconsin</option>
    <option value="WY">Wyoming</option>
  </select>
  <label for="bio">Bio</label>
  <textarea id="bio" name="Bio" placeholder="Tell us a bit about yourself…"></textarea>
  <label for="username">Username</label>
  <input id="username" type="text" name="Username">
  <label for="password">Password</label>
  <input id="password" type="password" name="Password">
</form>

EDITED: Feb 22 2021

Okay, I see what you're trying to do here, selecting multiple values from the multi-select field. My original script did not account for multiple selected values for field types such as checkbox lists and multi-select fields, but with a minor tweak, we can add support for both of those field types too! Please check the snippet above as I've now updated it to reflect this.

Essentially, we check for either of those field types and if they exist, we clear any preset values from their fields and then loop through an array of your desired inputs (a single string will be turned into an array of length 1, containing that string) and select each desired value. Using a ternary expression I account for both multi-select fields and checkbox lists by looking at the select's option tag descendants and setting the selected property to true/false, rather than the checked property.

Brandon McConnell
  • 5,776
  • 1
  • 20
  • 36
  • Also, if this is a form you need to auto-populate regularly, just combine this sort of JS autocomplete with an in-browser extension like TamperMonkey or GreaseMonkey (depending on which browser you use), and the extension will auto-populate those fields any time you visit that page. – Brandon McConnell Feb 20 '21 at 22:05
  • Many thanks Chris and Brandon. Brandon I think I was able to use your suggestion to make JavaScript select the option with a value of 5. I'm afraid I don't understand the different sections about selecting options in multiple fields (might have to come back to that!). On the script to selection the option with a value of 5, I believe that only works to select a single colour right? In this field, I also need to be able to select multiple colours in the same box if necessary (this is possible using the mouse, but of course I'm looking to do it with a script). – Yesterdec Feb 21 '21 at 21:11
  • Hi @Yesterdec — thanks for clarifying! I see what you're trying to do now, selecting multiple options from a multi-select field. I've just updated my answer (see the new solution under the "EDITED" header above). In my updated solution, I account for field types such as checkbox lists and multi-select fields, which may have multiple answers. These fields will support either a single line of text for one desired value or an array of values to select multiple options. Please let me know if this works for you and if you have any additional questions regarding my solution. – Brandon McConnell Feb 22 '21 at 06:05
  • I also just added comments to better understand what my JS code is doing every step of the way, but you can likely remove most of that in your production use – Brandon McConnell Feb 22 '21 at 06:15
  • Many thanks for the updated solution Brandon. Bear with me with these questions please ;-). Are fieldValues all the options available to select from the dropdown, or the values I would like to select from the dropdown? Or are they something else? And how can I find the fieldNames? I can't seem to find those when viewing source or inspecting in the console. And why have you included three separate snippets of code? – Yesterdec Feb 23 '21 at 23:00
  • @Yesterdec I built out the fieldValues object myself. That's something you would build as well. The keys in that object (before the colon symbol ":") are the name attribute for the field you'd like to fill, and the values in the object (to the right of the colon symbol) are the values you'd like to set/select for each field. So to clarify, these all represent the values you would like to set for each field. – Brandon McConnell Feb 23 '21 at 23:33
  • @Yesterdec did that answer all your questions? If my solution worked for you, would you mind selecting my solution as the accepted answer? Otherwise, I’m happy to answer any other follow-up questions. – Brandon McConnell Feb 28 '21 at 23:07
  • Sorry for the delay replying Brandon. Unfortunately it turns out development on the page in question is still ongoing, and they've changed the structure yet again so I haven't been able to put your suggestions to the test (it's clear I also need to read up on some terminology and concepts as well). Many thanks for the assist, but for the time being, question is unanswered. – Yesterdec Apr 20 '21 at 21:52