skip to Main Content

I am creating a script to automate a data entry process on a server monitoring website. The site does not have an API for this specific data entry type, so I am using JavaScript to automate the mouse clicking and data entry process.

The script returns the correct document.getElementById("") value for getElement statement. However, it only returns the correct value whenever I manually execute line of individually. If I run the entire script, then the code breaks on one single line.

`var namesAndAddresses = { 'DomainName': 'IP' };

//Function to press sidebar "add device button"
function MenuFunction() {

    MenuId = document.getElementById("menurow_Add/Import Devices").firstChild.nextElementSibling;

    MenuId.click()
}
//Function to press "add device manually button"
function AddDeviceFunction() {

    AddDeviceButton = document.getElementById("addDeviceButtonId_label");

    AddDeviceButton.click();

}
//Function to add device information and then press the save button
function AddDeviceInformationFunction(domain, address) {

    FQDN = document.getElementById("deviceNameId").value =
        domain; //FQDN;

    deviceClass = document.getElementById("deviceClassId").value =
        "Switch/Router";

    OS = document.getElementById("deviceOsId").value =
        "Other Operating System";

    ipAddress = document.getElementById("customUriId").value =
        address; //DictionaryID;

    licenseMode = document.getElementById("licenseModeId").value =
        "Professional Mode";

    saveButton = document.getElementById("cancelButtonId"); //change to save button

    saveButton.click();
}

//manually wait function
function pause(milliseconds) {
    var dt = new Date();
    while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}

//For loop to add each domain and ip that is listed in the dictionary
for (var [domainName, IP] of Object.entries(namesAndAddresses)) {

    window.self = document;
    //Function to press sidebar "add device button"
    MenuFunction();

    //Insert wait for sub-page to load here
    pause(3000);

    //Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
    AddDeviceFunction();

    //Insert wait for objects to load here
    pause(5000);

    //Function to add device information and then press the save button
    AddDeviceInformationFunction(domainName, IP);

    //Insert wait for objects to load here

    pause(5000);

};`

HTML code is below:

enter image description here

I have tried adding in a manual "wait" because window.onload does not work due to all the HTML being loaded already. I also tried adding a try/catch statement within a loop, so that it could make the attempt 10 times over a period of 10 seconds. That didn’t work either.

2

Answers


  1. Your code’s pause function is blocking.

    What this means is that since it "waits" using a while loop, it is not actually waiting but doing a lot of useless work, using up 100% of the CPU, and preventing anything else from actually loading.

    Because of this, I can only presume the elements that are supposed to appear when loading do not get a chance to, meaning getElementById returns null (they do not exist yet)

    Consider using something like setTimeout, which will properly wait, without preventing other work from being done.

    Replace your for loop near the end with

    var entries = Object.entries(namesAndAddresses)
    window.self = document;
    function processEntry(){
        if(!entries.length){
            // Done
            return
        }
        
        // Get (and remove) the first element in the array
        var [domainName, IP] = entries.shift()
    
        //Function to press sidebar "add device button"
        MenuFunction();
    
        //Wait for sub-page to load using setTimeout, which will run this code after 3000ms
        setTimeout(function(){
            //Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
            AddDeviceFunction();
    
            //Wait for objects to load here
            setTimeout(function(){
                //Function to add device information and then press the save button
                AddDeviceInformationFunction(domainName, IP);
    
                //Insert wait for objects to load here
                setTimeout(function(){
                    // Done, go to next entry
                    processEntry();
                }, 5000);
            }, 5000);
        }, 3000);
    };
    processEntry()
    
    

    I would also recommend looking into promises and async/await, which can make this code look much neater:

    function pause(milliseconds) {
        return new Promise(function(finish){
            setTimeout(finish, milliseconds)
        })
    }
    async function processAllEntries(){
        //For loop to add each domain and ip that is listed in the dictionary
        for (var [domainName, IP] of Object.entries(namesAndAddresses)) {
        
            window.self = document;
            //Function to press sidebar "add device button"
            MenuFunction();
        
            //Insert wait for sub-page to load here
            await pause(3000);
        
            //Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
            AddDeviceFunction();
        
            //Insert wait for objects to load here
            await pause(5000);
        
            //Function to add device information and then press the save button
            AddDeviceInformationFunction(domainName, IP);
        
            //Insert wait for objects to load here
            await pause(5000);
        
        }
    }
    
    Login or Signup to reply.
  2. Your pause causes the UI not to be able to render. You can make a function that uses await to look for an element. As soon as it is available it will update.

    function addElem() {
      const div = document.createElement('div');
      div.className = 'foo';
      div.textContent = 'hello';
      document.body.append(div);
    }
    
    
    const waitForElem = (selector) => new Promise((resolve, reject) => {
      const check = () => {
        const elem = document.querySelector(selector);
        if (elem) {
          resolve(elem);
        } else {
          window.setTimeout(check, 1);
        }
      };
      check();
    });
    
    window.setTimeout(addElem, 5000);
    
    (async function() {
    
      const el1 = await waitForElem('#bar');
      el1.textContent = 'found 1';
    
      const el2 = await waitForElem('.foo');
      el2.textContent = 'found 2';
    
    })();
    <div id="bar">Test</div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search