1

The target page has a button that opens a new window:

<img src="resources/icons/3.png" id="iconImage_3"  
    ondblclick="window.newWindow(3,this.alt,'../messagesBox.aspx?view=inbox&amp;',false,true,null,null,null,null);"
>

I need to access stuff in that window but I'm having a hard time. I get error messages as commented, below, in my script code.

And, I can only find info online regarding window.open, and not about window.newwindow.


Update:

With the help of a SO user in chat, we learned that window.newWindow actually creates a "dialog" <div> containing an iframe with the content I want to manipulate. (Element id="messageHeader_6328087", for example.)


Here is my code:

var messages;
var g=0;
function list() {
    var p = document.getElementById("messageHeader_6328087");

    var aclickEvent = document.createEvent("MouseEvents");
    aclickEvent.initEvent('click', false, true);
    p.dispatchEvent(aclickEvent);
// getting can't click on null 
    var r = document.getElementsByClassName("even unread");
    var s = document.getElementsByClassName("odd unread");
    var msgeven = Array.prototype.slice.call(r, 0);
    var msgodd = Array.prototype.slice.call(s, 0);

    var k = Math.max(msgodd.length,msgeven.length);
    confirm(k);
// this gives 0, so I'm not sure if when returned null they just automatically put     //nothing
    var i = 0;
    while (i < k) {
        if (i< msgeven.length) {
            messages.push(msgeven[i].id);
        }
        if (i< msgodd.length) {
            messages.push(msgodd[i].id);
        }
        i = i + 1;
    }
    alert(messages.length);
    // am getting can't take length of undefined, am I using push wrong?
}


How do I click that button?

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Any chance you could add me chat? I'd be glad to share the link to the website with you but prefer not to in public. –  Jun 03 '14 at 10:45

1 Answers1

0

When you double-click that image (#iconImage_3), the target page creates an <iframe> that contains the content you are looking for. CSS is used to make it look like a new window.

This is an AJAX scenario. That iframe does not exist when the page loads and your userscript runs. You need a way to make your script wait for that iframe. One easy, robust way to accomplish this is to use the waitForKeyElements() utility.

For example, visit this Dynamic Iframe test page on jsBin:

<!DOCTYPE html>
<html><head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script type="text/javascript">
        $(document).ready (jQueryMain);
        function jQueryMain () {
            //--- If this is the iframe, change the content.
            if (/BeAnIframe/i.test (location.search) ) {
                $("body").html (
                    '<h4>This is iFrame content</h4>' +
                    '<button id="generateMessageBtn">This is the button to click via userscript.</button>'
                );
                $("button").click ( function () {
                    $("body").append ('<p>Button was clicked.</p>');
                } );
            }
            else {
                $("button").click ( function () {
                    $("body").append (
                        '<div><iframe src="' + location.href + '?BeAnIframe=1"></iframe></div>'
                    );
                } );
            }
        }
    </script>
</head><body>
<p>Click the button below, and then the userscript will click the button that appears in the iframe.</p>
<p><button>Open the iframe below.</button></p>
</body></html>

It looks like this:

test page before user action

Then, when you click the button, it looks like this:

test page after user action

The iframe and contents were added via AJAX.

A simple Tampermonkey, or Greasemonkey, script to click that iframed button is:

// ==UserScript==
// @name    Dynamic iframe content clicker
// @include http://jsbin.com/xuwosovi/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant   GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/
if (window.top == window.self) {
    //-- Only runs if it's not an iframe.
    waitForKeyElements (
        "#generateMessageBtn",
        clickMessageButton,
        false,
        "iframe[src*='BeAnIframe']"
    );
}

function clickMessageButton (jNode) {
    var clickEvent  = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    jNode[0].dispatchEvent (clickEvent);
}

Note that:

  • #generateMessageBtn is the jQuery selector for the iframed button.
  • iframe[src*='BeAnIframe'] is a jQuery selector for the iframe itself, keying off the src attribute which is important for your particular situation.

Go ahead and install that script and then visit the test page. When you click the first button, You'll see a message indicating that the second button was clicked by the userscript.



Now, for your specific scenario, A script like this should click the indicated node. (We can't test it.)

// ==UserScript==
// @name    Dynamic iframe content clicker
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant   GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/
if (window.top == window.self) {
    //-- Only runs if it's not an iframe.
    waitForKeyElements (
        "#messageHeader_6328087",
        processMessageWindow,
        false,
        "iframe[src*='messagesBox.aspx?view=inbox']"
    );
}

function processMessageWindow (jNode) {
    var clickEvent  = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    jNode[0].dispatchEvent (clickEvent);
}

If that works, this question is answered. Open a new question for additional problems, but you should be able to populate your variables r and s by modifying processMessageWindow() like so:

function processMessageWindow (jNode) {
    var clickEvent  = document.createEvent ('MouseEvents');
    clickEvent.initEvent ('click', true, true);
    jNode[0].dispatchEvent (clickEvent);

    var frameBody   = jNode.parents ("body");
    var r           = frameBody.find (".even.unread").get ();
    var s           = frameBody.find (".odd.unread").get ();

    // Add additional processing here...
}

Note:

  • .parents(), .find() and .get() are jQuery functions.
  • You can't use document.getElementsByClassName for this. document still points to the parent window, not the iframe.
Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • Whelp just got confused for a second, never mind haha, will take some time to look up all the features involved, thanks for the answer! –  Jun 04 '14 at 13:18
  • You're welcome! Good luck. Probably out to delete your 1st comment. Keeps it neater. – Brock Adams Jun 04 '14 at 13:21
  • - I "managed" to open the message box in a new tab all by itself, basically just opened the source, how come it's still an iframe? It's the only thing on that page. –  Jun 04 '14 at 13:21
  • BOOM, pressed a messaged by ID in that new tab with the source! –  Jun 04 '14 at 13:24
  • I can chat now for just a bit. It's unclear what these comments mean. – Brock Adams Jun 04 '14 at 13:26
  • After seeing how much effort Brock put into this and how complicated it is I got desperate to find something else, hopefully I'll be able to pull info by opening it in a new tab. Regardless, I will pick up every bit of the answer and thank you for spending so much time chatting and helping me even after I keep saying misleading and stupid things! –  Jun 04 '14 at 13:27