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?

encore2097
  • 461
  • 2
  • 6
  • 18

2 Answers2

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>
mwilson
  • 10,186
  • 5
  • 41
  • 72
  • 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) – encore2097 Jan 29 '20 at 01:35
  • 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. – mwilson Jan 29 '20 at 03:28
  • 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. – encore2097 Jan 29 '20 at 19:02
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

encore2097
  • 461
  • 2
  • 6
  • 18