newspaint

Documenting Problems That Were Difficult To Find The Answer To

How to Click on a Div or Span Using PhantomJS

What is PhantomJS?

PhantomJS is the V8 javascript engine combined with some JS (like Node.JS) to make a headless browser that is extremely useful for testing.

One of the best features is the ability to output the virtual display at any time to a PNG graphic file.

The Problem

I was struggling with how to click on a div or span element using PhantomJS.

Other elements could be clicked on by code not unlike the following (from imagebin.js included in the examples provided with the PhantomJS distribution):

page.open("http://imagebin.org/index.php?page=add", function () {
    page.evaluate( function () {
        document.querySelector('input[name=nickname]').value = 'phantom';
        document.querySelector('input[name=disclaimer_agree]').click()
        document.querySelector('form').submit();
    });
});

The problem is that the element returned by the document.querySelector() function for a div or span does not have a click() method.

The Solution

The solution was found this blog post and the following example should make this clear:

page.evaluate( function() {
    // find element to send click to
    var element = document.querySelector( 'span.control.critical.closer' );

    // create a mouse click event
    var event = document.createEvent( 'MouseEvents' );
    event.initMouseEvent( 'click', true, true, window, 1, 0, 0 );

    // send click to element
    element.dispatchEvent( event );
});

You might ask where I got “span.control.critical.closer” from. Well I use Google Chrome and manually load up the web page with the element I want to click. Then I click on the menu and select tools -> developer tools (alternatively press shift+ctrl+I). Then I click on the magnifying glass icon on the bottom of the screen and then click on the div or span element I want to click – and copy down the name.

Example Usage

I would use code like the following:

function mouseclick( element ) {
    // create a mouse click event
    var event = document.createEvent( 'MouseEvents' );
    event.initMouseEvent( 'click', true, true, window, 1, 0, 0 );

    // send click to element
    element.dispatchEvent( event );
}

function handle_page( page ) {
    page.evaluate(
        function( mouseclick_fn ) {
            var element = document.querySelector( "input#payConf" );
            mouseclick_fn( element );
        },
        mouseclick
    );

    window.setTimeout(
        function () {
            handle_click_reaction( page );
        },
        5000 // give page 5 seconds to process click
    );
}

Important!

Many users new to PhantomJS seem oblivious to the need to wait some time to allow the virtual browser to do whatever action the click intended to do. After you dispatch your mouse event you will either want to call window.setTimeout or implement a waitFor() type function (you can find such a function elsewhere on this blog).

If you expect to get results from your click instantly you will most likely be disappointed!

Leave a comment