Jeferson Tenorio
Jeferson Tenorio

Reputation: 2190

How to submit items in a list using CasperJS

I'm trying iterate in a grid where each line has an action link button. I need to click on this button and go back to the grid and click the button on the next line.

See the CasperJS script:

for(var i=1; i<lines.length; i++) {

    var element = this.getElementInfo(x('//*[@id="elx"]/tbody/tr[' + i +']/td[1]'));
    var item = x('//*[@id="gdvConsulta"]/tbody/tr[' + i +']/td[3]/a');

    var model = {
        'custom': element.text,
        'item': item.text
    };

    // Click on item
    casper.click(item);
    this.waitForSelector(x('//*[@id="grid"]'),
        function pass () {
            utils.dump('ok');
            var backbutton = x('//*[@id="back"]/a');

            casper.click(backbutton);
        },
        function fail () {
            utils.dump('error');
        }
    );

    utils.dump('done line');
}

Note: the message 'done line' has been printed for all lines before the click on my first iterate of loop.

How to make a real waitForSelector() without going to next iteration?

Upvotes: 0

Views: 71

Answers (1)

Artjom B.
Artjom B.

Reputation: 61952

You've inappropriately mixing synchronous and asynchronous functions. You can use a loop, because you know the number of iterations beforehand, but the problem might be that you're clicking on every item before even the first waitForSelector() step is executed.

All then*() and wait*() functions are asynchronous step functions. By calling them, you schedule a step that is executed after the current step. You need to wrap the synchronous code in a step such as this:

for(var i=1; i<lines.length; i++) {
    (function(i){
        casper.then(function(){
            var element = this.getElementInfo(x('//*[@id="elx"]/tbody/tr[' + i +']/td[1]'));
            var item = x('//*[@id="gdvConsulta"]/tbody/tr[' + i +']/td[3]/a');

            // Click on item
            casper.click(item);
        });


        casper.waitForSelector(x('//*[@id="grid"]'),
            function pass () {
                utils.dump('ok');
                var backbutton = x('//*[@id="back"]/a');

                casper.click(backbutton);
                utils.dump('done line');
            },
            function fail () {
                utils.dump('error');
            }
        );
    })(i);
}

Please note that you need to enclose the i variable from the loop, because the inside of the loop is executed asynchronously and i references for all iterations will point to the last possible i. See more here: JavaScript closure inside loops – simple practical example

Upvotes: 1

Related Questions