Catch the window.open from javascript

2019-02-26 20:05发布

问题:

I have a web page into a html iframe, the web page has a javascript function to open links, that function use the window.open method to open a new window.

I cannot modify the javascript function (the page is made with mapguide), so I want to catch that call outside of the iframe to put the content of the new window into an ajax modal frame, instead of open a new window, is this possible?

回答1:

While I would not recommend this in general, you can overwrite the definition of the window.open function in the iframe, assuming your page and the iframe are in the same domain to avoid XSS security errors.

HTML:

<iframe id="myFrame" src="...">
</iframe>

javascript in the parent window:

var frame = document.getElementById('myFrame');

if (frame) {
    frame.contentWindow.open = function (url, windowName, windowFeatures) {
        // do whatever you want here (e.g. open an ajax modal frame)
    };
}


回答2:

I'll assume the 'mapguide' content is served from a different domain than the page containing the iframe.

If that's the case, you'd need to "proxy" the 'mapguide' content -- i.e: your iframe will need to load the mapguide content from another script URL (I'll assume PHP for this example) on your server, whose code would fetch the 'mapguide' software from wherever it really comes from. This part is easy, and the server-side code might look like this:

<? 
    $content = file_get_contents('http://mapguide.domain/path/to/contents');

    // alter content here

    print $content;
?>

The iframe src attribute should point at the PHP file on your server which contains that code (instead of the 'mapguide' server).

If the 'mapguide' content contains HTML links, loads CSS/JavaScript files, or does AJAX calls, then you'll need to have your server-side code rewrite those URLs to refer back to your server. That part is not very easy, and really depends on how complicated the 'mapguide' JavaScript is.

So after the comment above that says alter content here, you'd need to do some awful regexp replacements on (or parse and re-generate) the HTML contained in $content, with the goal of changing every single URL to pass through your "proxy" PHP script and be loaded from the appropriate place on the 'mapguide' server.

If you manage to pull all of that off, then your iframe will be server from the same domain as your containing HTML page and so the outer page's JavaScript will be able to replace the window.open function of the iframe -- to prevent the popup, or do whatever you want instead -- as @jbabey says in another answer.

All of this presumes that the 'mapguide' content doesn't come with a user agreement and/or copyright policy which forbids "scraping" (automatically copying) their (the 'mapguide' content's authors') content.



回答3:

Here's a similar snippit I've been working on... it was tricky getting the contentWindow right, but maybe this provides some insight?

//get a reference to the iframe DOM node
var node_iframe = document.getElementById("myiframe");

//get a reference to the iframe's window object
var win_iframe = node_iframe.contentWindow;

//override the iframe window's open method
win_iframe.open = function(strUrl,strName,strParams){

    /* create an object (to substitute for the window object) */
    var objWin = new Object;

    /* save the open arguments in case we need them somewhere */
    objWin.strUrl = strUrl;   
    objWin.strName = strName; 
    objWin.strParams = strParams; 

    /* create a blank HTML document object, so any HTML fragments that 
     * would otherwise be written to the popup, can be written to it instead */
    objWin.document = document.implementation.createHTMLDocument(); 

    /* save the object (and document) back in the parent window, so we 
     * can do stuff with it (this has an after-change event listener that 
     * pops a YUI Panel to act as a kind of popup) -- NOTE: the object in 
     * the parent window that we're saving this to has YUI Attribute installed
     * and listens to changes to the objPopupWindow attribute... when it 
     * gets changed by this .set() operation, it shows a YUI Panel. */
    parent.MyCustomClassObjectWithYUIAttributes.set('objPopupWindow', objWin); 

    /* return the object and all its members to whatever was trying to 
     * create a popup window */
    return objWin; 
    };//end override method definition