无法在新(AJAX)窗口中按ID,类名等访问元素?

时间:2014-06-03 08:02:49

标签: javascript iframe greasemonkey tampermonkey

目标页面有一个打开新窗口的按钮:

<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);"
>

我需要访问该窗口中的内容,但我很难过。我在下面的脚本代码中收到了错误消息。

而且,我只能在线查找有关window.open的信息,而不是window.newwindow


更新

在SO用户的帮助下,我们了解到window.newWindow实际上创建了一个“对话框”&lt; div&gt;包含一个iframe,其中包含我想要操作的内容。 (例如,元素id="messageHeader_6328087"。)


这是我的代码:

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?
}


如何点击该按钮?

1 个答案:

答案 0 :(得分:0)

双击该图像(#iconImage_3)时,目标页面会创建一个<iframe>,其中包含您要查找的内容。 CSS用于使外观像新窗口一样。

这是一个AJAX场景。当页面加载并且您的用户脚本运行时,iframe不存在。您需要一种方法让您的脚本等待该iframe。一种简单,可靠的方法是使用the waitForKeyElements() utility

例如,访问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>

看起来像这样:

  

test page before user action

然后,当您单击按钮时,它看起来像这样:

  

test page after user action

iframe和内容是通过AJAX添加的。

点击iframed按钮的简单Tampermonkey或Greasemonkey脚本:

// ==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);
}

请注意:

  • #generateMessageBtn是iframed按钮的jQuery selector
  • iframe[src*='BeAnIframe']是iframe本身的jQuery选择器,用于确定对您的特定情况非常重要的src属性。

继续安装该脚本,然后访问the test page。当您单击第一个按钮时,您将看到一条消息,指示用户脚本单击了第二个按钮。



现在,针对您的具体方案,像这样的脚本应该点击指定的节点。 (我们无法测试它。)

// ==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);
}

如果有效,这个问题就得到了回答。针对其他问题打开一个新问题,但您应该能够通过修改r来填充变量sprocessMessageWindow(),如下所示:

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...
}

注意:

  • .parents().find().get()是jQuery函数。
  • 您无法使用document.getElementsByClassNamedocument仍然指向父窗口,而不是iframe。