1

If you go to Google Alert website while you are not login with your Google Account you would have a chance of creating an alert send to your Yahoo account for example.

I am going create an alert using PhantomJS. Then I would need to click on the CREATE ALERT button. I need to do that using JavaScript. But it seems that PhantomJS cannot click on this button!

I have even tried to click on this button through Google Console but I could not.

I have used three different ways for clicking on the button which nothing works. Can someone help me to click on the CREATE ALERT button?

javascript:if(!window.jQuery||confirm('Overwrite\x20current\x20version?\x20v'+jQuery.fn.jquery))(function(d,s){s=d.createElement('script');s.src='https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.js';(d.head||d.documentElement).appendChild(s)})(document);

var inputOne = document.getElementsByTagName('input')[0];
inputOne.value = "testAlert";

var inputTwo = document.getElementsByTagName('input')[1];
inputTwo.value = "test@yahoo.com";

var button = document.getElementById('create_alert');

//1.
//button.click();

//2.
//$(button).trigger('click');
//$(button).trigger('change');

//3.
var event = document.createEvent("MouseEvents");
event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
button.dispatchEvent(event);

And I am using following code in PhantomJS

phantom.injectJs("functions/jquery.js");

var page = require('webpage').create();

var load, contoroller;
var numOfActions = 1;
var clicked = false;

var initialURL = "https://www.google.com/alerts";

page.open(initialURL, function(status) {

    load = true;
});


page.onLoadFinished = function(status) 
{

    clearInterval(contoroller);
    if (clicked)
    {
        console.log("The status of loading the page is " + status + "\n");
        page.render("SCREENSHOTS/page_" + numOfActions + ".png");
        numOfActions += 1;

        phantom.exit();
    }
    else
    {
        contoroller = setInterval(function () {

            if (load)
            {
                console.log("The status of loading the page is " + status + "\n");
                page.render("SCREENSHOTS/page_" + numOfActions + ".png");
                numOfActions += 1;

                load = false;

                enterQuery("test");
            }
            else
            {
                console.log("The status of loading the page is " + status + "\n");
                page.render("SCREENSHOTS/page_" + numOfActions + ".png");
                numOfActions += 1;

                page.evaluate(function(){
                    var input = document.getElementsByTagName('input')[1];
                    input.value = "test@test.com";

                })

                click();
            }
        }, 5000);
    }
}


function enterQuery(query)
{
    page.injectJs("functions/jquery.js");

    page.evaluate(function(query)
    {
        var box = document.getElementsByTagName('input')[0];
        box.value = query;
        //$(box).keypress();
    }, query);
}


function click()
{
    clicked = true;
    clearInterval(contoroller);

    var but = page.evaluate(function(){

        var button = document.getElementById('create_alert');

        //var event = document.createEvent("MouseEvents");
        //event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
        //button.dispatchEvent(event);

        return button;

    })

    page.sendEvent('click', but);

    window.setTimeout(function () { 

        console.log("The status of loading the page is " + status + "\n");
        page.render("SCREENSHOTS/page_" + numOfActions + ".png");
        numOfActions += 1;

        phantom.exit();

    }, 5000);
}

It seems that I need to first hover the mouse on the button. When you hover the mouse you will see that the class attribute of the element changes. I have tried $(button).trigger('mouseover') but after that the class attribute did not change. How can I trigger mouseover on this element?

Suo6613
  • 431
  • 5
  • 17
  • You say you tried 3 different methods. I see only one. Have you tried [this](http://stackoverflow.com/a/24026636/1816580) or [this](http://stackoverflow.com/a/20022929/1816580)? – Artjom B. Jul 20 '15 at 15:06
  • I just tried `page.sendEvent()` which you suggested. I have updated the `click()` function in my code. It did not work either. Have you tried it in Chrome? Don't you thinkd that I need to trigger the `mouseover` first? – Suo6613 Jul 20 '15 at 15:40

1 Answers1

1

There are two problems with your code: typing and clicking.

When you set the value of an input field directly, none of the input event handlers are called. You could use the native page.sendEvent("keypress", keys) which types keys as if a user would type them, so all event handlers will be triggered. Since the function doesn't know where to type to, you need to focus on the element first:

page.evaluate(function(selector){
    document.querySelector(selector).focus();
}, selector);
page.sendEvent("keypress", query);

You can solve the clicking also with page.sendEvent("click", posx, posy). Now the challenge becomes to find out the position of the elements on the page. This answer provides a jQuery way of solving this:

page.injectJs("jquery.min.js");

var rect = page.evaluate(function(selector) {
    return $(selector)[0].getBoundingClientRect();
}, selector);

page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);

This is your full script that works as expected:

var page = require('webpage').create();

var load, contoroller;
var numOfActions = 1;
var clicked = false;

var initialURL = "https://www.google.com/alerts";

page.open(initialURL, function(status) {
    load = true;
});


page.onLoadFinished = function(status) 
{

    clearInterval(contoroller);
    if (clicked)
    {
        console.log("1| The status of loading the page is " + status + "\n");
        page.render("SCREENSHOT/page_" + numOfActions + ".png");
        numOfActions += 1;

        phantom.exit();
    }
    else
    {
        contoroller = setInterval(function () {

            if (load)
            {
                console.log("2| The status of loading the page is " + status + "\n");
                page.render("SCREENSHOT/page_" + numOfActions + ".png");
                numOfActions += 1;

                load = false;

                enter("input", "test"); // very first input
            }
            else
            {
                console.log("3| The status of loading the page is " + status + "\n");
                page.render("SCREENSHOT/page_" + numOfActions + ".png");
                numOfActions += 1;

                enter("input.email_input", "test@test.com");

                setTimeout(function(){
                    click("#create_alert");
                }, 500);
            }
        }, 5000);
    }
}


function enter(selector, query)
{
    page.evaluate(function(selector){
        document.querySelector(selector).focus();
    }, selector);
    page.sendEvent("keypress", query);
}


function click(selector)
{
    clicked = true;
    clearInterval(contoroller);

    page.injectJs("functions/jquery.js");

    var rect = page.evaluate(function(selector) {
        return $(selector)[0].getBoundingClientRect();
    }, selector);

    page.sendEvent('click', rect.left + rect.width / 2, rect.top + rect.height / 2);

    window.setTimeout(function () { 

        console.log("4| The status of loading the page is " + status + "\n");
        page.render("SCREENSHOT/page_" + numOfActions + ".png");
        numOfActions += 1;

        phantom.exit();

    }, 5000);
}
Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222