I'm looking to select a specific dropdown value from dozens of HTML dropdowns for a userscript. Is there a way to do this using the ID I have ({"Id":"302"}
)?
I've tried selecting all items based on the class as a jumping off point but I'm not having much success. Ideally though if I could select based on the provided ID it would allow me to be more specific with the selections.
What I have:
waitForDropdown (".control:has(option[value='See Notes'])", selectDropdown);
function selectDropdown (jNode) {
var evt = new Event ("click");
jNode[0].dispatchEvent (evt);
jNode.val('See Notes');
evt = new Event ("change");
jNode[0].dispatchEvent (evt);
}
This is the HTML:
<div class="field tabular">
<span class="item-data">{"Id":"302"}</span>
<div class="field-content">
<div class="title" title="Dropdown A">Dropdown A</div>
<div class="data">
<div class="errors"></div>
<div class="control">
<select>
<option value="Not Checked" selected="selected">Not Checked</option>
<option value="Checked & Cleaned">Checked & Cleaned</option>
<option value="Not Applicable">Not Applicable</option>
<option value="See Section Notes">See Notes</option>
</select>
<!-- Etc... -->
Could I use the title to narrow the selection? Or would the ID make more sense?
To answer your question: "Could I use the title to narrow the selection? Or would the ID make more sense?"
A stable, numerical id is usually your best bet. Title, or other, text is subject to: editing or translation/internationalization. But if the id changes from page to page, or from page reload; don't use it.
There are several problems with that code:
waitForDropdown()
is neither standard nor defined. Questions should contain MCVEs.waitForKeyElements
-- which is now common, standard, and battle tested.option[value='See Notes']
does not match any of the HTML.jNode.val('See Notes');
is attempting to set an invalid value.jNode.val('See Notes');
is operating on a <div class="control">
. It needs to operate on the <select>
.Anyway, the companion question illustrates a top-down tree traversal to get the right nodes. So, here, I will illustrate a bottom up approach. It is also AJAX aware, unlike that other answer.
Refer to the jQuery Tree Traversal docs.
Here is a complete userscript that show how to discriminate options based on an associated node/id. (The userscript is just the first gray block):
// ==UserScript==
// @name _Set <select> value under specific HTML section id
// @match *://YOUR_SERVER.COM/YOUR_PATH/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// @grant GM.getValue
// ==/UserScript==
//- The @grant directives are needed to restore the proper sandbox.
waitForKeyElements (".control > select > option[value$='Cleaned']", selectId302Value);
function selectId302Value (jNode) {
//-- Make sure control belongs to the correct id:
var idNode = jNode.closest (".field-content").prev (".item-data");
if (idNode.length === 0) {
console.error ("Page structure changed or invalid in selectId302Value().");
return;
}
if (idNode.text ().includes ('"302"') ) {
var evt = new Event ("click");
jNode[0].dispatchEvent (evt);
//-- Correct val already determined by WFKE selector.
jNode.parent ().val(jNode.val () );
//-- The select node would get any required change event.
evt = new Event ("change");
jNode.parent ()[0].dispatchEvent (evt);
}
}
<!----------------------------------------
----- Simulated target page follows: -----
----------------------------------------->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="//greasyfork.org/scripts/2199-waitforkeyelements/code/waitForKeyElements.js"></script>
<div class="field tabular">
<span class="item-data">{"Id":"302"}</span>
<div class="field-content">
<div class="title" title="Dropdown A">Dropdown A</div>
<div class="data">
<div class="errors"></div>
<div class="control">
<select>
<option value="Not Checked" selected="selected">Not Checked</option>
<option value="Checked & Cleaned">Checked & Cleaned</option>
<option value="Not Applicable">Not Applicable</option>
<option value="See Section Notes">See Notes</option>
</select>
</div></div></div>
<span class="item-data">{"Id":"777"}</span>
<div class="field-content">
<div class="title" title="Dropdown B">Dropdown B</div>
<div class="data">
<div class="errors"></div>
<div class="control">
<select>
<option value="Not Checked" selected="selected">Not Checked</option>
<option value="Checked & Cleaned">Checked & Cleaned</option>
<option value="Not Applicable">Not Applicable</option>
<option value="See Section Notes">See Notes</option>
</select>
</div></div></div>
</div>
Run the code snippet to see it in action.