Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Identifying a DOM element without an ID value

I regularly use a web app from Invisalign® to set up orthodontic cases. I use Keyboard Maestro to make keyboard shortcuts within the app by activating JavaScript.

An example of the JavaScript triggered by keyboard maestro:

document.getElementById('myButton').click();

The web app was recently updated and there is no longer a button ID. Thus, the getElementByID is no longer functioning.

I have tried the following but it does not work:

document.getElementByClass('myClass').click();

(I have tried c01143 and c0012)

An example of the HTML for the page is:

<div class='c0012'>
        <button type="button" tabindex="-1" data-qa-name="lower" data-qa-toggled="false" class="c0180 c01149 c01151">
            <div class="c01143">
                <svg class="c0189 c0191" viewBox="0 0 24 24"><path d="M2,13 L22,13 L22,16 L2,16 L2,13 Z M8,8 L16,8 L16,11 L8,11 L8,8 Z"></path></svg>
            </div>
        <span class="c01142">Lower</span>
    </button>
</div>

I have also tried:

document.getElementBydata-qa-name('lower').click();

That also doesn't work. Hopefully someone can help out with what might be a very simple solution. Although I know some HTML and CSS my JavaScript is almost nonexistent.

like image 769
Sage Avatar asked Oct 06 '20 19:10

Sage


1 Answers

The non-descriptive class names (e.g., c0012, c01143) strongly indicate that, somewhere in the site's stack, the HTML/CSS/JS is being dynamically compiled/generated. As such, you should expect that these identifiers could change drastically and quite frequently & you shouldn't rely on them in your snippet.


Method #1 - document.querySelector() using data-qa-name

You can use the document.querySelector() method to identify based on the button tag, the button type value, as well as the custom data-qa-name attribute. The following demonstrates that this method works to identify the element without relying on the class name or the (no longer-existent) ID value:

(() => {
  console.log(document.querySelector("button[type='button'][data-qa-name='lower']"));
})();
<div class='c0012'>
  <button type="button" tabindex="-1" data-qa-name="lower" data-qa-toggled="false" class="c0180 c01149 c01151">
            <div class="c01143">
                <svg class="c0189 c0191" viewBox="0 0 24 24"><path d="M2,13 L22,13 L22,16 L2,16 L2,13 Z M8,8 L16,8 L16,11 L8,11 L8,8 Z"></path></svg>
            </div>
        <span class="c01142">Lower</span>
    </button>
</div>

You would lift and shift the above by simply calling click() on the identified element, as you had previously:

document.querySelector("button[type='button'][data-qa-name='lower']").click();

Method #2 - document.querySelectorAll(), filtered using .innerText value

While from what you've posted there isn't any strong indication that this data-qa-name attribute would change in either name or value, you can also target the element based on its innerText value similar to the following:

[...document.querySelectorAll("button[type='button']")].find(function (ele) {return ele.innerText === "Lower"})).click();

The following snippet, while it appears succinct, performs the following steps:

  1. Enumerates all button elements with an attribute type of button into an Array structure.
  2. Finds and returns the first element in the array that has an innerText property equal to the string Lower.
  3. Executes the click() method on the identified button.

The only scenario in which this particular snippet wouldn't work to your requirements would be if there are buttons appearing somewhere in the DOM tree before the intended button element that also have an innerText property equal to the string "Lower". You'll have to perform a small amount of testing to confirm which of these snippets will work most consistently in your scenario.


Further reading

Considering your self-professed limited understanding of JavaScript, you may wish to consult the following MDN documentation pages to get a better grasp on the methods and linguistic conventions leveraged above:

  • document.querySelector()
  • document.querySelectorAll()
  • Spread syntax (...)
  • Glossary - Array
  • Array.find()
like image 135
esqew Avatar answered Sep 25 '22 08:09

esqew