CasperJS: How do you click on all selected buttons?
Asked Answered
S

2

9

I'm trying to use CasperJS as a web scraper, and there's a page with buttons that will load data when clicked. So, I'd like to click all of these buttons first and wait before actually making a query to grab all the necessary data.

The problem is that with Casper, casper.thenClick(selector) clicks the first element. But how do you iterate and click each element based on the selector?

Note that these buttons do not have ids. They all have generic class selectors.

Ex.

<h3>
    <span>Text 1</span>
    <span>
        <button class="load-btn">show</button>
    </span>
</h3>
<h3>
    <span>Text 2</span>
    <span>
        <button class="load-btn">show</button>
    </span>
</h3>
<h3>
    <span>Text 3</span>
    <span>
        <button class="load-btn">show</button>
    </span>
</h3>

And for some reason casper.thenClick("h3:contains('text 1') .load-btn") doesn't work.

Serpentine answered 1/12, 2016 at 14:45 Comment(0)
F
4

I created a new 'click' function, you can click on each element by using for cycle:

function click(sel){var event=document.createEvent('MouseEvents');event.initMouseEvent('click',1,1,window,1,0,0,0,0,0,0,0,0,0,null);sel.dispatchEvent(event);}
var casper = require('casper').create({
    verbose: true,
    logLevel: 'debug',
    waitTimeout: 5000,
    userAgent: 'Mozilla/5.0 (X11; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0',
    viewportSize:{width: 1600, height: 900}
});
casper
.on("error", function(msg){ this.echo("error: " + msg, "ERROR") })
.on("page.error", function(msg, trace){ this.echo("Page Error: " + msg, "ERROR") })
.on("remote.message", function(msg){ this.echo("Info: " + msg, "INFO") })

.start("http://domu-test-2/node/12", function(){
    this.evaluate(function(click){
        var i, x = document.querySelectorAll("button.load-btn");
        for(i = 0; i < x.length; i++) {
            click(x[i]);
        } //'click' for each element
    }, click);
})
.run();

With this HTML:

<h3>
    <span>Text 1</span>
    <span>
        <button class="load-btn" onclick='console.log("1")'>show</button>
    </span>
</h3>
<h3>
    <span>Text 2</span>
    <span>
        <button class="load-btn" onclick='console.log("2")'>show</button>
    </span>
</h3>
<h3>
    <span>Text 3</span>
    <span>
        <button class="load-btn" onclick='console.log("3")'>show</button>
    </span>
</h3>

Will print:

Info: 1
Info: 2
Info: 3

In green color.

Fer answered 2/12, 2016 at 4:5 Comment(1)
You're passing the click function from the outer context into the page context. This didn't work with PhantomJS 1.x. Did this change? I would be quite surprised if this really works as you describe it.Aloud
R
2

You could try dropping into the DOM using evaluate instead (I assume the page has jquery on it).

casper.thenEvaluate(function() {
  $('button.load-btn').click();
});

Remember that you will need to WAIT for something to appear afterwards.

casper.wait(2000, function() {...});

or using one of the waitFor function

Relegate answered 5/12, 2016 at 8:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.