【问题标题】:Can't access elements by Id, class name, etc. in a new (AJAX) window?无法在新 (AJAX) 窗口中按 Id、类名等访问元素?
【发布时间】:2014-07-23 11:37:08
【问题描述】:

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

<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 实际上创建了一个“对话框”

,其中包含我想要操作的内容的 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?
}


如何点击该按钮?

【问题讨论】:

  • 有机会加我聊天吗?我很乐意与您分享该网站的链接,但不希望公开。

标签: javascript iframe greasemonkey tampermonkey


【解决方案1】:

当您双击该图像 (#iconImage_3) 时,目标页面会创建一个包含您要查找的内容的 &lt;iframe&gt;。 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>

看起来像这样:

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

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

如果可行,则回答此问题。为其他问题打开一个新问题,但您应该能够通过修改processMessageWindow() 来填充变量rs,如下所示:

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。

【讨论】:

  • Whelp 只是一时糊涂了,没关系哈哈,需要一些时间来查找所有涉及的功能,谢谢您的回答!
  • 不客气!祝你好运。可能会删除您的第一条评论。保持整洁。
  • - 我自己“设法”在新标签页中打开消息框,基本上只是打开了源代码,为什么它仍然是 iframe?这是该页面上唯一的内容。
  • BOOM,在带有源的新标签中按下 ID 消息!
  • 我现在可以聊一会儿。目前尚不清楚这些 cmets 的含义。
猜你喜欢
  • 1970-01-01
  • 2011-11-06
  • 2014-07-18
  • 1970-01-01
  • 2018-04-12
  • 2019-11-08
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
相关资源
最近更新 更多