0

Goal: Automate data backup from a third party site.

Scenario:

The data is available on a web page as a series of elements. ex:

[Data A] [Data B] [Data ...] 
  1. Click on a Data element.
  1. After a short delay, elements will be populated under the data element and a [Save] button will appear. ex:
+ [Data A] [ ] item 1 [ ] item 2 ... [ ] item N [Save] 
  1. Select all items
  1. Click [Save] to download.

Repeat steps 1-4 to save each Data element for a complete backup.

In synchronous psuedo code this would be:

alerts [array] for i in alerts click alerts[i].load check if data ready; ready when save button appears click select_all click save 

How can this be done in Javascript?

5
  • What is causing the new element to come into existence? Commented Jan 29, 2020 at 0:47
  • Are you writing code to scrape or otherwise interact with a 3rd party page, or do you control this page? Commented Jan 29, 2020 at 0:53
  • @tmdesigned step 1. clicking the specific alert. Commented Jan 29, 2020 at 1:45
  • @David 3rd party site Commented Jan 29, 2020 at 1:45
  • @MisterJojo your comment directly contradicts the docs api.jquery.com/click w3schools.com/jsref/met_html_click.asp ; perhaps a thorough reading of the docs is in order unless you desire to confuse others and hinder their learning Commented Jan 29, 2020 at 18:56

2 Answers 2

1

It's a little unclear on the flow of your steps and what you are wanting the output to be. However, I think what you're ultimately after is how to listen to an event, wait some time, then do another event.

Below is an example of using Promises to create a wait method.

  1. Click Alerts button
  2. Save button appears
  3. 5 second wait time is triggered
  4. After 5 seconds, you will see a console.log message

const btn = document.getElementById('alerts'); btn.addEventListener( 'click', async () => { createSaveElement(); console.log('waiting 5 seconds'); await wait(5); console.log('finished waiting 5 seconds'); }); function createSaveElement() { const container = document.getElementById('container'); const saveBtn = document.createElement('button'); saveBtn.innerText = 'Save'; container.append(saveBtn); } async function wait(seconds) { return new Promise( (resolve, reject) => { setTimeout( () => { resolve(); }, seconds * 1000); }); }
<button id="alerts">Alerts</button> <div id="container"></div>

Sign up to request clarification or add additional context in comments.

3 Comments

I'm automating the tedious task of backing up my information from a site: click the alert -> wait to load data/element -> select all events for that instance -> click save (to download the file)
That makes a little more sense. In that case, put all that logic within the Promise. You can you while loop logic there, but I would suggest you look into DOM Mutation Events or some other method to tell you when the page has loaded the data you're after. At the end of all that, resolve your Promise. You can pass whatever data you want into the resolve(...) function. It will be returned to whatever is awaiting it.
I kinda see how that relates to the code above, but unsure how to hook in the mutation listener or which mutation listener to use. It would be helpful if you provide an example or link the relevant docs.
0

Got it done with a macro and Firefox console.

Solution that works:

  1. What is the JavaScript version of sleep()?
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function backup() { var alerts = $('.alerts'); var imax = alerts.length; for (let i = 0; i < imax; i++) { alerts[i].click(); await sleep(2000); $('.ui-select-all').click(); await sleep(200); $('#save'); await sleep(500); } } backup(); 

Solution that may work:

  1. javascript synchronous execution

JavaScript pausing execution of function to wait for user input

A recursive, callback version

If there's a succinct event based approach I'd prefer and accept that as the answer


Update: optimal solution: Event delegation allows an event listener to be attached to a dynamically created element, even if that element does not yet exist. The event listener can call an anonymous function after the sub element is created.

https://davidwalsh.name/event-delegate

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events

https://learn.jquery.com/events/event-delegation/

Attach event to dynamic elements in javascript

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.