Search code examples
javascriptdomclickcasperjs

How to click on an element based on coordinates and how to retrieve element properties with CasperJS?


I would like to get attributes about objects using CasperJS, for example I have something like this:

var casper = require('casper').create();
casper.start('http://www.seznam.cz', function() {
    if (this.exists('div#info')) {
        require('utils').dump(this.getElementInfo('div#info'));
    } 
    else {
        this.echo(' not found', 'ERROR');
    }
});
casper.run(); 

I can see in console many attributes for example position of the element. Now given this, is it somehow possible to get these coordinates and perform for example this.click(coordinates)? If it is, how?

I also would like to know hot to get another properties, like parentNode, childNodes.


Solution

  • I can see in console many attributes for example position of the element. Now given this, is it somehow possible to get these coordinates and perform for example this.click(coordinates)? If it is, how?

    A function like casper.getElementInfo(selector) provides the coordinates and dimensions of the first element matched by the given selector. It would be strange if CasperJS wouldn't have the ability to use those.

    CasperJS has multiple modules for different task. One of those is the mouse module. This module provide a click() function that either takes a selector or the coordinates to click somewhere.

    casper.then(function(){
        var info = this.getElementInfo('div#info');
        this.mouse.click(info.x+1, info.y+1);
    });
    

    +1 is necessary so that the element is actually clicked and not its border.

    I also would like to know hot to get another properties, like parentNode, childNodes.

    This is much more difficult. CasperJS (and PhantomJS) has two contexts. The outer context is the code that you have in your script, but not completely. casper.evaluate() is the window into the sandboxed page context.

    The function that is passed into casper.evaluate() has no access to variables defined outside. Values have to be explicitly passed. They will be serialized as JSON along the way. So when you want to pass DOM nodes out of the page context, they will lose their meaning, because they are not JSON serializable.

    What you can do on the other hand, is to never pass the DOM nodes that you get when you call parentNode or childNodes outside. Only work with them completely in the page context. Store them on the global window object for later use for example and then use another casper.evaluate() later in your script to access them.

    If you don't actually need the actual nodes, you can retrieve a representation of those nodes. The textContent is a good candidate for it:

    var childContentsArray = casper.evaluate(function(){
        return [].map.call(document.querySelector("#someId").childNodes, function(child){
            return child.textContent;
        });
    });