Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Code Reviews

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

75%
+4 −0
Code Reviews How to programmatically click through a list of elements if one has to wait for a click to load a set of predefined new elements?

I would like to download the old-time radio show I Love a Mystery from the OTRR website. I figured out how to construct the list of right URLs, const urlStub = "https://otrr.org/OTRRLibrary/jukebo...

1 answer  ·  posted 7mo ago by toraritte‭  ·  edited 4mo ago by toraritte‭

Question javascript
#4: Post edited by user avatar toraritte‭ · 2024-01-09T18:09:08Z (4 months ago)
  • I would like to download the old-time radio show [I Love a Mystery](https://www.otrr.org/OTRRLibrary/otrrlibrary.html?idp=4919) from the OTRR website. I figured out how to construct the list of right URLs,
  • ```javascript
  • const urlStub = "https://otrr.org/OTRRLibrary/jukebox/";
  • copy(Array.from(
  • document.getElementsByTagName('a')).
  • map( a => `"${urlStub}${a.href.split('/').pop()}"` ).
  • join(' ')
  • )
  • ```
  • but when I call it with `curl`,
  • ```bash
  • for url in <copied-list>; do curl -k -O $url; done
  • ```
  • I get a lot of `404 Not Found`. I realized that clicking on the titles will load a player on the page "pre-loading" the audio file, and then I can use `curl`. It is quite a chore to go through hundreds of files though, so I figured I would make it a bit easier by collecting the "title" elements, and click them one by one until it errors out,
  • ```javascript
  • const t = Array.from(document.querySelectorAll('td.colTitle'));
  • t.pop().click()
  • ...
  • t.pop().click()
  • ```
  • but this is still not the best.
  • ### The solution thus far
  • I cobbled together the snippet below that uses [`MutationObserver`][2] recursively, based on the SO threads below, but I assume that there is a simpler solution (and one that doesn't potentially run out of memory on a page with thousands of episodes).
  • + `stackoverflow` [javascript - How to wait until an element exists?](https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists)
  • + `stackoverflow` [javascript - How to check if an element has been loaded on a page before running a script?](https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script)
  • It seems to get to job done, but the `Promise` will always remain `pending` and it feels very hacky:
  • ```javascript
  • function waitForElement(querySelector, elemArr) {
  • return new Promise((resolve, reject) => {
  • if (elemArr.length) {
  • console.log(elemArr);
  • elemArr.pop().click();
  • } else {
  • return resolve();
  • }
  • if (document.querySelectorAll(querySelector).length) {
  • waitForElement(querySelector, elemArr);
  • }
  • const observer = new MutationObserver( () => {
  • if (document.querySelectorAll(querySelector).length) {
  • observer.disconnect();
  • waitForElement(querySelector, elemArr);
  • }
  • });
  • observer.observe(document.body, {
  • childList: true,
  • subtree: true
  • });
  • });
  • }
  • t = Array.from(document.querySelectorAll('td.colTitle'))
  • waitForElement("audio", t)
  • ```
  • [1]: https://i.stack.imgur.com/LTAKW.gif
  • [2]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  • I would like to download the old-time radio show [I Love a Mystery](https://www.otrr.org/OTRRLibrary/otrrlibrary.html?idp=4919) from the OTRR website. I figured out how to construct the list of right URLs,
  • ```javascript
  • const urlStub = "https://otrr.org/OTRRLibrary/jukebox/";
  • copy(Array.from(
  • document.getElementsByTagName('a')).
  • map( a => `"${urlStub}${a.href.split('/').pop()}"` ).
  • join(' ')
  • )
  • ```
  • but when I call it with `curl`,
  • ```bash
  • for url in <copied-list>; do curl -k -O $url; done
  • ```
  • I get a lot of `404 Not Found`. I realized that clicking on the titles will load a player on the page "pre-loading" the audio file, and then I can use `curl`.<sup><b>1</b></sup> It is quite a chore to go through hundreds of files though, so I figured I would make it a bit easier by collecting the "title" elements, and click them one by one until it errors out,
  • <sup>\[1] TODO: Why so? It bothers me that I don't understand this part.</sup>
  • ```javascript
  • const t = Array.from(document.querySelectorAll('td.colTitle'));
  • t.pop().click()
  • ...
  • t.pop().click()
  • ```
  • but this is still not the best.
  • ### The solution thus far
  • I cobbled together the snippet below that uses [`MutationObserver`][2] recursively, based on the SO threads below, but I assume that there is a simpler solution (and one that doesn't potentially run out of memory on a page with thousands of episodes).
  • + `stackoverflow` [javascript - How to wait until an element exists?](https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists)
  • + `stackoverflow` [javascript - How to check if an element has been loaded on a page before running a script?](https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script)
  • It seems to get to job done, but the `Promise` will always remain `pending` and it feels very hacky:
  • ```javascript
  • function waitForElement(querySelector, elemArr) {
  • return new Promise((resolve, reject) => {
  • if (elemArr.length) {
  • console.log(elemArr);
  • elemArr.pop().click();
  • } else {
  • return resolve();
  • }
  • if (document.querySelectorAll(querySelector).length) {
  • waitForElement(querySelector, elemArr);
  • }
  • const observer = new MutationObserver( () => {
  • if (document.querySelectorAll(querySelector).length) {
  • observer.disconnect();
  • waitForElement(querySelector, elemArr);
  • }
  • });
  • observer.observe(document.body, {
  • childList: true,
  • subtree: true
  • });
  • });
  • }
  • t = Array.from(document.querySelectorAll('td.colTitle'))
  • waitForElement("audio", t)
  • ```
  • [1]: https://i.stack.imgur.com/LTAKW.gif
  • [2]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
#3: Post edited by user avatar toraritte‭ · 2024-01-09T17:54:24Z (4 months ago)
  • I would like to download the old-time radio show [I Love a Mystery](https://www.otrr.org/OTRRLibrary/otrrlibrary.html?idp=4919) from the OTRR website. I figured out how to construct the list of right URLs,
  • ```javascript
  • const urlStub = "https://otrr.org/OTRRLibrary/jukebox/";
  • copy(Array.from(
  • document.getElementsByTagName('a')).
  • map( a => `"${urlStub}${a.href.split('/').pop()}"` ).
  • join(' ')
  • )
  • ```
  • but when I call it with `curl`,
  • ```bash
  • for url in <copied-list>; do curl -k -O $u; done
  • ```
  • I get a lot of `404 Not Found`. I realized that clicking on the titles will load a player on the page "pre-loading" the audio file, and then I can use `curl`. It is quite a chore to go through hundreds of files though, so I figured I would make it a bit easier by collecting the "title" elements, and click them one by one until it errors out,
  • ```javascript
  • const t = Array.from(document.querySelectorAll('td.colTitle'));
  • t.pop().click()
  • ...
  • t.pop().click()
  • ```
  • but this is still not the best.
  • ### The solution thus far
  • I cobbled together the snippet below that uses [`MutationObserver`][2] recursively, based on the SO threads below, but I assume that there is a simpler solution (and one that doesn't potentially run out of memory on a page with thousands of episodes).
  • + `stackoverflow` [javascript - How to wait until an element exists?](https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists)
  • + `stackoverflow` [javascript - How to check if an element has been loaded on a page before running a script?](https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script)
  • It seems to get to job done, but the `Promise` will always remain `pending` and it feels very hacky:
  • ```javascript
  • function waitForElement(querySelector, elemArr) {
  • return new Promise((resolve, reject) => {
  • if (elemArr.length) {
  • console.log(elemArr);
  • elemArr.pop().click();
  • } else {
  • return resolve();
  • }
  • if (document.querySelectorAll(querySelector).length) {
  • waitForElement(querySelector, elemArr);
  • }
  • const observer = new MutationObserver( () => {
  • if (document.querySelectorAll(querySelector).length) {
  • observer.disconnect();
  • waitForElement(querySelector, elemArr);
  • }
  • });
  • observer.observe(document.body, {
  • childList: true,
  • subtree: true
  • });
  • });
  • }
  • t = Array.from(document.querySelectorAll('td.colTitle'))
  • waitForElement("audio", t)
  • ```
  • [1]: https://i.stack.imgur.com/LTAKW.gif
  • [2]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  • I would like to download the old-time radio show [I Love a Mystery](https://www.otrr.org/OTRRLibrary/otrrlibrary.html?idp=4919) from the OTRR website. I figured out how to construct the list of right URLs,
  • ```javascript
  • const urlStub = "https://otrr.org/OTRRLibrary/jukebox/";
  • copy(Array.from(
  • document.getElementsByTagName('a')).
  • map( a => `"${urlStub}${a.href.split('/').pop()}"` ).
  • join(' ')
  • )
  • ```
  • but when I call it with `curl`,
  • ```bash
  • for url in <copied-list>; do curl -k -O $url; done
  • ```
  • I get a lot of `404 Not Found`. I realized that clicking on the titles will load a player on the page "pre-loading" the audio file, and then I can use `curl`. It is quite a chore to go through hundreds of files though, so I figured I would make it a bit easier by collecting the "title" elements, and click them one by one until it errors out,
  • ```javascript
  • const t = Array.from(document.querySelectorAll('td.colTitle'));
  • t.pop().click()
  • ...
  • t.pop().click()
  • ```
  • but this is still not the best.
  • ### The solution thus far
  • I cobbled together the snippet below that uses [`MutationObserver`][2] recursively, based on the SO threads below, but I assume that there is a simpler solution (and one that doesn't potentially run out of memory on a page with thousands of episodes).
  • + `stackoverflow` [javascript - How to wait until an element exists?](https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists)
  • + `stackoverflow` [javascript - How to check if an element has been loaded on a page before running a script?](https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script)
  • It seems to get to job done, but the `Promise` will always remain `pending` and it feels very hacky:
  • ```javascript
  • function waitForElement(querySelector, elemArr) {
  • return new Promise((resolve, reject) => {
  • if (elemArr.length) {
  • console.log(elemArr);
  • elemArr.pop().click();
  • } else {
  • return resolve();
  • }
  • if (document.querySelectorAll(querySelector).length) {
  • waitForElement(querySelector, elemArr);
  • }
  • const observer = new MutationObserver( () => {
  • if (document.querySelectorAll(querySelector).length) {
  • observer.disconnect();
  • waitForElement(querySelector, elemArr);
  • }
  • });
  • observer.observe(document.body, {
  • childList: true,
  • subtree: true
  • });
  • });
  • }
  • t = Array.from(document.querySelectorAll('td.colTitle'))
  • waitForElement("audio", t)
  • ```
  • [1]: https://i.stack.imgur.com/LTAKW.gif
  • [2]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
#2: Post edited by user avatar toraritte‭ · 2023-10-24T14:35:00Z (7 months ago)
  • I would like to download the old-time radio show [I Love a Mystery](https://www.otrr.org/OTRRLibrary/otrrlibrary.html?idp=4919) from the OTRR website. I figured out how to construct the list of right URLs,
  • ```javascript
  • const urlStub = "https://otrr.org/OTRRLibrary/jukebox/";
  • copy(Array.from(
  • document.getElementsByTagName('a')).
  • map( a => `"${urlStub}${a.href.split('/').pop()}"` ).
  • join(' ')
  • )
  • ```
  • but when I call it with `curl`,
  • ```bash
  • for url in <copied-list>; do curl -k -O $u; done
  • ```
  • I get a lot of `404 Not Found`. I realized that clicking on the titles will load a player on the page "pre-loading" the audio file, and then I can use `curl`. It is quite a chore to go through hundreds of files though, so I figured I would make it a bit easier by collecting the "title" elements, and click them one by one until it errors out,
  • ```javascript
  • const t = Array.from(document.querySelectorAll('td.colTitle'));
  • t.pop().click()
  • ...
  • t.pop().click()
  • ```
  • but this is still not the best.
  • ### The solution thus far
  • I cobbled together the snippet below that uses [`MutationObserver`][2] recursively, based on the SO threads below, but not sure if there would something simpler (and one that doesn't potentially run out of memory a page with thousands of episodes).
  • + `stackoverflow` [javascript - How to wait until an element exists?](https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists)
  • + `stackoverflow` [javascript - How to check if an element has been loaded on a page before running a script?](https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script)
  • It seems to get to job done, but the `Promise` will always remain `pending` and it feels very hacky:
  • ```javascript
  • function waitForElement(querySelector, elemArr) {
  • return new Promise((resolve, reject) => {
  • if (elemArr.length) {
  • console.log(elemArr);
  • elemArr.pop().click();
  • } else {
  • return resolve();
  • }
  • if (document.querySelectorAll(querySelector).length) {
  • waitForElement(querySelector, elemArr);
  • }
  • const observer = new MutationObserver( () => {
  • if (document.querySelectorAll(querySelector).length) {
  • observer.disconnect();
  • waitForElement(querySelector, elemArr);
  • }
  • });
  • observer.observe(document.body, {
  • childList: true,
  • subtree: true
  • });
  • });
  • }
  • t = Array.from(document.querySelectorAll('td.colTitle'))
  • waitForElement("audio", t)
  • ```
  • [1]: https://i.stack.imgur.com/LTAKW.gif
  • [2]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
  • I would like to download the old-time radio show [I Love a Mystery](https://www.otrr.org/OTRRLibrary/otrrlibrary.html?idp=4919) from the OTRR website. I figured out how to construct the list of right URLs,
  • ```javascript
  • const urlStub = "https://otrr.org/OTRRLibrary/jukebox/";
  • copy(Array.from(
  • document.getElementsByTagName('a')).
  • map( a => `"${urlStub}${a.href.split('/').pop()}"` ).
  • join(' ')
  • )
  • ```
  • but when I call it with `curl`,
  • ```bash
  • for url in <copied-list>; do curl -k -O $u; done
  • ```
  • I get a lot of `404 Not Found`. I realized that clicking on the titles will load a player on the page "pre-loading" the audio file, and then I can use `curl`. It is quite a chore to go through hundreds of files though, so I figured I would make it a bit easier by collecting the "title" elements, and click them one by one until it errors out,
  • ```javascript
  • const t = Array.from(document.querySelectorAll('td.colTitle'));
  • t.pop().click()
  • ...
  • t.pop().click()
  • ```
  • but this is still not the best.
  • ### The solution thus far
  • I cobbled together the snippet below that uses [`MutationObserver`][2] recursively, based on the SO threads below, but I assume that there is a simpler solution (and one that doesn't potentially run out of memory on a page with thousands of episodes).
  • + `stackoverflow` [javascript - How to wait until an element exists?](https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists)
  • + `stackoverflow` [javascript - How to check if an element has been loaded on a page before running a script?](https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script)
  • It seems to get to job done, but the `Promise` will always remain `pending` and it feels very hacky:
  • ```javascript
  • function waitForElement(querySelector, elemArr) {
  • return new Promise((resolve, reject) => {
  • if (elemArr.length) {
  • console.log(elemArr);
  • elemArr.pop().click();
  • } else {
  • return resolve();
  • }
  • if (document.querySelectorAll(querySelector).length) {
  • waitForElement(querySelector, elemArr);
  • }
  • const observer = new MutationObserver( () => {
  • if (document.querySelectorAll(querySelector).length) {
  • observer.disconnect();
  • waitForElement(querySelector, elemArr);
  • }
  • });
  • observer.observe(document.body, {
  • childList: true,
  • subtree: true
  • });
  • });
  • }
  • t = Array.from(document.querySelectorAll('td.colTitle'))
  • waitForElement("audio", t)
  • ```
  • [1]: https://i.stack.imgur.com/LTAKW.gif
  • [2]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
#1: Initial revision by user avatar toraritte‭ · 2023-10-24T13:44:44Z (7 months ago)
How to programmatically click through a list of elements if one has to wait for a click to load a set of predefined new elements?
I would like to download the old-time radio show [I Love a Mystery](https://www.otrr.org/OTRRLibrary/otrrlibrary.html?idp=4919) from the OTRR website. I figured out how to construct the list of right URLs,

```javascript
const urlStub = "https://otrr.org/OTRRLibrary/jukebox/";
copy(Array.from(
    document.getElementsByTagName('a')).
        map( a => `"${urlStub}${a.href.split('/').pop()}"` ).
        join(' ')
)
```

but when I call it with `curl`,

```bash
for url in <copied-list>; do curl -k -O $u; done
```

I get a lot of `404 Not Found`. I realized that clicking on the titles will load a player on the page "pre-loading" the audio file, and then I can use `curl`. It is quite a chore to go through hundreds of files though, so I figured I would make it a bit easier by collecting the "title" elements, and click them one by one until it errors out,

```javascript
const t = Array.from(document.querySelectorAll('td.colTitle'));

t.pop().click()
...
t.pop().click()
```

but this is still not the best.

### The solution thus far

I cobbled together the snippet below that uses [`MutationObserver`][2] recursively, based on the SO threads below, but not sure if there would something simpler (and one that doesn't potentially run out of memory a page with thousands of episodes).

+ `stackoverflow` [javascript - How to wait until an element exists?](https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists)

+ `stackoverflow` [javascript - How to check if an element has been loaded on a page before running a script?](https://stackoverflow.com/questions/34863788/how-to-check-if-an-element-has-been-loaded-on-a-page-before-running-a-script)

It seems to get to job done, but the `Promise` will always remain `pending` and it feels very hacky:

```javascript
function waitForElement(querySelector, elemArr) {
    return new Promise((resolve, reject) => {
    
        if (elemArr.length) {
            console.log(elemArr);
            elemArr.pop().click();
        } else {
            return resolve();
        }
    
        if (document.querySelectorAll(querySelector).length) {
            waitForElement(querySelector, elemArr);
        }
    
        const observer = new MutationObserver( () => {
            if (document.querySelectorAll(querySelector).length) {
                observer.disconnect();
                waitForElement(querySelector, elemArr);
            }
        });
      
        observer.observe(document.body, {
            childList: true, 
            subtree: true
        });
    });
}

t = Array.from(document.querySelectorAll('td.colTitle'))

waitForElement("audio", t)
```


  [1]: https://i.stack.imgur.com/LTAKW.gif


  [2]: https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver