1
\$\begingroup\$

I created the following Chrome bookmarklet to open all elements with text Extra Examples boxes on this page. For example - the element labeled with text Extra Examples below can be clicked:

screenshot of extra examples element

When it is clicked then a list of examples will be displayed:

screenshot of extra examples element expanded

The element can then be clicked again to hide the list of examples.

The bookmarklet code

javascript:$('.box_title').click();

It works with no problem. However, I'd prefer to use vanilla JavaScript. This is what I have for now:

javascript:document.querySelectorAll('.box_title').forEach(e => e.click());

Do you see any problem, or can it be improved?

Demonstration

Below is a runnable snippet that shows a sample of the page without the bookmarklet:

<link href="https://www.oxfordlearnersdictionaries.com/external/styles/oald10.css" rel="stylesheet" />
<link href="https://www.oxfordlearnersdictionaries.com/external/styles/interface.css" rel="stylesheet" />
<span class="shcut-g" id="get_sngs_2"> <h2 class="shcut" htag="h2" id="get_shcut_2" hclass="shcut">bring</h2><li class="sense" cefr="a1" id="get_sng_4" hclass="sense" htag="li" sensenum="5" ox3000="y"><a class="open oup_icons" title="Add to My Word Lists"><span class="star-btn" aria-hidden="true">​</span></a>
<span
  class="sensetop" hclass="sensetop" htag="span">
  <div class="symbols" htag="div" hclass="symbols"><a href="https://www.oxfordlearnersdictionaries.com/wordlists/oxford3000-5000?dataset=english&amp;list=ox3000&amp;level=a1"><span class="ox3ksym_a1">&nbsp;</span></a></div>
  </span> <span class="grammar" hclass="grammar" htag="span">[transitive]</span> <span class="def" htag="span" hclass="def">to go to a place and bring somebody/something back</span> <span class="xrefs" htag="span" xt="nsyn" hclass="xrefs"><span class="prefix">synonym</span>  <a class="Ref" href="https://www.oxfordlearnersdictionaries.com/definition/english/fetch" title="fetch definition"><span class="xr-g" href="fetch_e" bord="n"><span class="xh">fetch</span></span></a></span>
  <ul class="examples" hclass="examples" htag="ul">
    <li class="" htag="li"> <span class="cf" htag="span" hclass="cf">get somebody/something</span> <span class="x">Quick—<span class="cl">go and get</span> a cloth!</span>
    </li>
    <li class="" htag="li"><span class="x">Somebody get a doctor!</span></li>
    <li class="" htag="li"><span class="x">She went to <span class="cl">get help</span>.</span>
    </li>
    <li class="" htag="li"><span class="x">I have to go and get my mother from the airport <span class="gloss" htag="span" hclass="gloss">(= collect her)</span>.</span>
    </li>
    <li class="" htag="li"> <span class="cf" hclass="cf" htag="span">get something for somebody</span> <span class="x">Get a drink for John.</span></li>
    <li class="" htag="li"> <span class="cf" htag="span" hclass="cf">get somebody/yourself something</span> <span class="x">Get John a drink.</span></li>
  </ul>
  <div class="collapse" htag="div" hclass="collapse"><span class="unbox" id="get_unbox_2" unbox="extra_examples"><span class="box_title">Extra Examples</span>
    <ul class="examples" hclass="examples" htag="ul">
      <li class="" htag="li"><span class="unx">She's gone to get a few more chairs.</span></li>
      <li class="" htag="li"><span class="unx">Could you go upstairs and get my wallet for me, please?</span></li>
      <li class="" htag="li"><span class="unx">Can I get you anything to eat or drink?</span></li>
    </ul>
    </span>
  </div>
  </li>
  </span>
<div id="flex-menu"></div>
<div id="panel-smartphone"></div>
<div id="dictionarySelector"></div>
<script src="https://www.oxfordlearnersdictionaries.com/common.js"></script>
<script src="https://www.oxfordlearnersdictionaries.com/external/scripts/jquery.lightbox-0.5.min.js"></script>
<script src="https://www.oxfordlearnersdictionaries.com/external/scripts/oxford.js"></script>
<script src="https://www.oxfordlearnersdictionaries.com/external/scripts/entry.js"></script>
<script language="javascript" type="text/javascript">
    var contextId= (location.hash != "" ? location.hash : null);
    // global variable that contains the path to external files
    // and used by the lightbox script 
    var lightboxImageLoading = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-ico-loading.gif?version=2.3.41";
    var lightboxImageBtnPrev = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-btn-prev.gif?version=2.3.41";
    var lightboxImageBtnNext = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-btn-next.gif?version=2.3.41";
    var lightboxImageBtnClose = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-btn-close.gif?version=2.3.41";
    var lightboxImageBlank = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-blank.gif?version=2.3.41";
    if (document.readyState != 'loading'){
        initEntry('See more', 'See less');
    } else if (document.addEventListener) {
      document.addEventListener('DOMContentLoaded', function(){initEntry('See more', 'See less');});
    } else {
      document.attachEvent('onreadystatechange', function() {
        if (document.readyState != 'loading')
            initEntry('See more', 'See less');
      });
    }
</script>

And here is the code with the effect of the bookmarklet added:

document.addEventListener('DOMContentLoaded', function() {
    document.querySelectorAll('.box_title').forEach(e => e.click());
});
<link href="https://www.oxfordlearnersdictionaries.com/external/styles/oald10.css" rel="stylesheet" />
<link href="https://www.oxfordlearnersdictionaries.com/external/styles/interface.css" rel="stylesheet" />
<span class="shcut-g" id="get_sngs_2"> <h2 class="shcut" htag="h2" id="get_shcut_2" hclass="shcut">bring</h2><li class="sense" cefr="a1" id="get_sng_4" hclass="sense" htag="li" sensenum="5" ox3000="y"><a class="open oup_icons" title="Add to My Word Lists"><span class="star-btn" aria-hidden="true">​</span></a>
<span
  class="sensetop" hclass="sensetop" htag="span">
  <div class="symbols" htag="div" hclass="symbols"><a href="https://www.oxfordlearnersdictionaries.com/wordlists/oxford3000-5000?dataset=english&amp;list=ox3000&amp;level=a1"><span class="ox3ksym_a1">&nbsp;</span></a></div>
  </span> <span class="grammar" hclass="grammar" htag="span">[transitive]</span> <span class="def" htag="span" hclass="def">to go to a place and bring somebody/something back</span> <span class="xrefs" htag="span" xt="nsyn" hclass="xrefs"><span class="prefix">synonym</span>  <a class="Ref" href="https://www.oxfordlearnersdictionaries.com/definition/english/fetch" title="fetch definition"><span class="xr-g" href="fetch_e" bord="n"><span class="xh">fetch</span></span></a></span>
  <ul class="examples" hclass="examples" htag="ul">
    <li class="" htag="li"> <span class="cf" htag="span" hclass="cf">get somebody/something</span> <span class="x">Quick—<span class="cl">go and get</span> a cloth!</span>
    </li>
    <li class="" htag="li"><span class="x">Somebody get a doctor!</span></li>
    <li class="" htag="li"><span class="x">She went to <span class="cl">get help</span>.</span>
    </li>
    <li class="" htag="li"><span class="x">I have to go and get my mother from the airport <span class="gloss" htag="span" hclass="gloss">(= collect her)</span>.</span>
    </li>
    <li class="" htag="li"> <span class="cf" hclass="cf" htag="span">get something for somebody</span> <span class="x">Get a drink for John.</span></li>
    <li class="" htag="li"> <span class="cf" htag="span" hclass="cf">get somebody/yourself something</span> <span class="x">Get John a drink.</span></li>
  </ul>
  <div class="collapse" htag="div" hclass="collapse"><span class="unbox" id="get_unbox_2" unbox="extra_examples"><span class="box_title">Extra Examples</span>
    <ul class="examples" hclass="examples" htag="ul">
      <li class="" htag="li"><span class="unx">She's gone to get a few more chairs.</span></li>
      <li class="" htag="li"><span class="unx">Could you go upstairs and get my wallet for me, please?</span></li>
      <li class="" htag="li"><span class="unx">Can I get you anything to eat or drink?</span></li>
    </ul>
    </span>
  </div>
  </li>
  </span>
<div id="flex-menu"></div>
<div id="panel-smartphone"></div>
<div id="dictionarySelector"></div>
<script src="https://www.oxfordlearnersdictionaries.com/common.js"></script>
<script src="https://www.oxfordlearnersdictionaries.com/external/scripts/jquery.lightbox-0.5.min.js"></script>
<script src="https://www.oxfordlearnersdictionaries.com/external/scripts/oxford.js"></script>
<script src="https://www.oxfordlearnersdictionaries.com/external/scripts/entry.js"></script>
<script language="javascript" type="text/javascript">
    var contextId= (location.hash != "" ? location.hash : null);
    // global variable that contains the path to external files
    // and used by the lightbox script 
    var lightboxImageLoading = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-ico-loading.gif?version=2.3.41";
    var lightboxImageBtnPrev = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-btn-prev.gif?version=2.3.41";
    var lightboxImageBtnNext = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-btn-next.gif?version=2.3.41";
    var lightboxImageBtnClose = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-btn-close.gif?version=2.3.41";
    var lightboxImageBlank = "https://www.oxfordlearnersdictionaries.com/external/images/lightbox-blank.gif?version=2.3.41";
    if (document.readyState != 'loading'){
        initEntry('See more', 'See less');
    } else if (document.addEventListener) {
      document.addEventListener('DOMContentLoaded', function(){initEntry('See more', 'See less');});
    } else {
      document.attachEvent('onreadystatechange', function() {
        if (document.readyState != 'loading')
            initEntry('See more', 'See less');
      });
    }
</script>

P.S. This is where everything started: "Expand all comments" button. A jQuery snippet is already suggested, but I prefer a plain JavaScript solution as jQuery isn't always available, e.g., on this dictionary.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ IMO, looks as good as it can as-is. No need to be extra smart here \$\endgroup\$
    – casraf
    Dec 6, 2022 at 9:11
  • \$\begingroup\$ If you only care about opening the boxes, you could change the selector to only find the ones that are actually closed, this well prevent them from closing when there somehow already open \$\endgroup\$
    – 0stone0
    Dec 6, 2022 at 13:32

1 Answer 1

3
\$\begingroup\$

Be aware of all elements selected by the selector

In the first revision it was stated:

I created the following Chrome bookmarklet to open all Extra Examples boxes on this page

And the code selects elements with the class name box_title:

document.querySelectorAll('.box_title')

Running that in the console on that URL I see 8 elements in the node list, though when I do a find on that page for "Extra Examples" there are only 4 elements. The other elements with that class name are for similar elements - e.g. labeled Verb Forms, Synonyms Understand, More Like This Verbs with two objects, and Word Origin - so the bookmarklet is toggling all of those elements. While this may not have any negative side-effects, it is doing more than the original intention.

If the goal was to only click on the elements containing that text, then the jQuery :contains() selector could be used, though the goal here is to use vanilla JavaScript.

While inspecting the HTML of those elements it appears that there is an attribute on the parent <span> with an unbox attribute set to extra_examples:

<span class="unbox" id="get_unbox_5" unbox="extra_examples">
    <span class="box_title">Extra Examples</span>
    <ul class="examples" htag="ul" hclass="examples">
        <li class="" htag="li"><span class="unx">I finally got Michael to talk to them and he explained everything.</span></li>
        <li class="" htag="li"><span class="unx">We had trouble getting enough people to sign up.</span></li>
    </ul>
</span>

An attribute selector utilizing that unbox attribute could be used to find all elements with class box_title that are a direct child of an element with that attribute - e.g.

document.querySelectorAll('[unbox="extra_examples"] > .box_title')

Modifying classes directly

I did explore other options besides calling the click method.

The best I could come up with was toggling the class name directly on the elements using the toggle() method of the classList property, but it gets more complex because the class name is-active needs to be added to both the parent <span> and the <span> with the text Extra Examples. Any event handlers that detect clicks would not be triggered - this could be a drawback, though it is possible that the page owner is attempting to detect clicks and maybe that leads to something like targeted advertising.

document.querySelectorAll('[unbox="extra_examples"], [unbox="extra_examples"] > .box_title').forEach(e => e.classList.toggle('is-active')) 
\$\endgroup\$
1
  • \$\begingroup\$ Sam, I really appreciate editing my question and the detailed answer! 🙏 \$\endgroup\$
    – Mori
    Dec 8, 2022 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.