How to catch new window opend by window.open(url, _blank) in PhantomJS?

℡╲_俬逩灬. 提交于 2019-12-05 00:24:46

问题


I'd like to check with PhantomJS whether my script correctly opens a new window/tab on click. The open is triggerd by a js event listener and opened through window.open(url, "_blank").

How can I listen for the new window with PhantomJS?


回答1:


There seem to be three ways to do this:

onPageCreated

CasperJS solves this by using page.onPageCreated. So when window.open is called in the page, a new page is created and page.onPageCreated is triggered with the newly created page.

page.open(address, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        page.onPageCreated = function(newPage){
            newPage.onLoadFinished = function(){
                console.log(newPage.url);
                phantom.exit();
            };
        };
        page.evaluate(function(url){
            window.open(url+"?something=other", "_blank");
        }, address);
    }
})

pages

PhantomJS' page has a pages property which handles of the child pages. So, when you open a new page/tab, a new webpage object is created for that page. You need to try to add an onLoadFinished event listener to the page before it fires (no promises). It can be hard and when the window.open is called with an unknown delay from the page context.

This can be fixed by using something like waitFor to wait for the new page to appear and attach the event handler before the page is loaded. Here is the complete code with a small adjustment. The retry interval is reduced to 50ms from 250ms.

var page = require('webpage').create();
var address = "http://example.com/";

function waitFor(testFx, onReady, timeOutMillis) {
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
        start = new Date().getTime(),
        condition = false,
        interval = setInterval(function() {
            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
                // If not time-out yet and condition not yet fulfilled
                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
            } else {
                if(!condition) {
                    // If condition still not fulfilled (timeout but condition is 'false')
                    console.log("'waitFor()' timeout");
                    phantom.exit(1);
                } else {
                    // Condition fulfilled (timeout and/or condition is 'true')
                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
                    clearInterval(interval); //< Stop this interval
                }
            }
        }, 50); //< repeat check every 50ms
};

page.open(address, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        console.log("p:", page.ownsPages, typeof page.pages, page.pages.length, page.pages);
        waitFor(function test(){
            return page.pages && page.pages[0];
        }, function ready(){
            page.pages[0].onLoadFinished = function(){
                console.log("p:", page.ownsPages, typeof page.pages, page.pages.length, page.pages);
                console.log("inner:", page.pages[0].url);
                phantom.exit();
            };
        });
        page.evaluate(function(url){
            window.open(url+"?something=other", "_blank");
        }, address);
    }
})

Proxy solution

The window.open function can be proxied and after the opening the page in the page context, an event handler can be registered in phantom context signaled through window.callPhantom and caught in onCallback.

page.onInitialized = function(){
    page.evaluate(function(){
        var _oldOpen = window.open;
        window.open = function(url, type){
            _oldOpen.call(window, url, type);
            window.callPhantom({type: "open"});
        };
    });
};
page.onCallback = function(data){
    // a little delay might be necessary
    if (data.type === "open" && page.pages.length > 0) {
        var newPage = page.pages[page.pages.length-1];
        newPage.onLoadFinished = function(){
            console.log(newPage.url);
            phantom.exit();
        };
    }
};
page.open(address, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        page.evaluate(function(url){
            window.open(url+"?something=other", "_blank");
        }, address);
    }
})


来源:https://stackoverflow.com/questions/27980178/how-to-catch-new-window-opend-by-window-openurl-blank-in-phantomjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!