1

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 &amp; Cleaned">Checked &amp; 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?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Patrick
  • 13
  • 2
  • The question is not clear. Are you saying you want to narrow it down via `"Id":"302"`? If so, is 302 a known stable value? ... Also `waitForDropdown` is not defined and the `value` selector does not match any option `value` (Precise rules apply). – Brock Adams Apr 08 '18 at 17:27
  • Apologies @BrockAdams. Hopefully this clarifies. What I'm looking for is to select a value for the dropdown based on the ID ("Id":"302"). 302 is a known stable value. What I've been playing with is: `$("div.control select").val("Checked & Good");` However I'd like to make it more specific to either "Id":"302" or even potentially "Dropdown A" but I'm having trouble adding additional selectors in this case. – Patrick Apr 08 '18 at 17:38
  • This looks suspiciously like [**this other question**](https://stackoverflow.com/questions/49718885/selecting-checkboxes-based-on-value-and-parent-id). Are you Coworkers? Students in the same class? Sock puppets? ... (Although the approach in this question has the potential to be more robust, esp if the page is ajax-driven.) – Brock Adams Apr 08 '18 at 18:01
  • We are indeed working on the same project for work. Is there resources you'd suggest looking at for selecting the title `Dropdown A` to be combined with `div.control select` given the way the title is nested? I've been poking at this for a couple hours now without much success. – Patrick Apr 08 '18 at 18:18
  • Much appreciated. Thanks. I'll continue trying things. – Patrick Apr 08 '18 at 18:21

1 Answers1

0

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:

  1. waitForDropdown() is neither standard nor defined. Questions should contain MCVEs.
    In this case, it looks like a possible version of waitForKeyElements -- which is now common, standard, and battle tested.
  2. The selector: option[value='See Notes'] does not match any of the HTML.
    Refer to the jQuery Attribute selectors docs.
  3. jNode.val('See Notes'); is attempting to set an invalid value.
  4. 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 &amp; Cleaned">Checked &amp; 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 &amp; Cleaned">Checked &amp; 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.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • 1
    Thanks Brock! This is very thorough and I'll be sure to make my questions more clear going forward. – Patrick Apr 08 '18 at 21:57
  • I've run in to an issue with this. The events to click and change the dropdown values fire fine, however these fields are on a form and when I go to save the form the newly selected values are ignored. Only the values selected via manual click and select will save with their new values. – Patrick Apr 11 '18 at 20:53
  • First try the updated code, but that's beyond the scope of this question because neither the actual target page nor an MCVE were provided. ... See [this related question](https://stackoverflow.com/questions/15048223/choosing-and-activating-the-right-controls-on-an-ajax-driven-site) for help if additional tuning is needed. If you get stymied, open a new question but it must either link to the target page or provide an MCVE. – Brock Adams Apr 12 '18 at 03:29