JS控制台与用户脚本中的不同行为,试图操纵iframe内容

时间:2013-11-07 14:09:15

标签: javascript jquery iframe userscripts

我正在尝试破解我不拥有但我想改进的网络应用程序。

我想在DOM中的元素之前添加一些HTML,同一域iframe。以下是来自控制台的示例:

jQ(".x-panel-body.x-panel-body-noheader").find("iframe").contents().find("body").find("#WorkspaceFrame").find(".x-panel-tbar.x-panel-tbar-noheader").find(".x-toolbar-right").find(".x-toolbar-right-ct").find("table");
[
<table cellspacing=​"0">​…​</table>, 
<table id=​"ext-comp-1046" cellspacing=​"0" class=​"x-btn   x-btn-text-icon" style=​"width:​ auto;​">​…​</table>​, 
<table cellspacing=​"0">​…​</table>​, 
<table cellspacing=​"0">​…​</table>​, 
<table id=​"ext-comp-1067" cellspacing=​"0" class=​"x-btn   x-btn-text-icon " style=​"width:​ auto;​">​…​</table>​, 
<table id=​"ext-comp-1068" cellspacing=​"0" class=​"x-btn   x-btn-text-icon " style=​"width:​ auto;​">​…​</table>​, 
<table id=​"ext-comp-1069" cellspacing=​"0" class=​"x-btn   x-btn-text-icon" style=​"width:​ auto;​">​…​</table>​, 
<table cellspacing=​"0">​…​</table>​, 
<table cellspacing=​"0">​…​</table>​, 
<table id=​"ext-comp-1253" cellspacing=​"0" class=​"x-btn   x-btn-text-icon x-item-disabled" style=​"width:​ auto;​">​…​</table>​, 
<table id=​"ext-comp-1254" cellspacing=​"0" class=​"x-btn   x-btn-text-icon" style=​"width:​ auto;​">​…​</table>​, 
<table cellspacing=​"0">​…​</table>​, 
<table cellspacing=​"0">​…​</table>​, 
<table id=​"ext-comp-1760" cellspacing=​"0" class=​"x-btn   x-btn-text-icon" style=​"width:​ auto;​">​…​</table>​, 
<table cellspacing=​"0">​…​</table>​
]

jQ是我的jQuery的名称(我不能使用$)。

所以基本上它可以在控制台上运行,saveButton包含一个数组。这是我的剧本:

saveButton=jQ(".x-panel-body.x-panel-body-noheader").find("iframe").contents().find("body").find("#WorkspaceFrame").find(".x-panel-tbar.x-panel-tbar-noheader").find(".x-toolbar-right").find(".x-toolbar-right-ct").find("table");
console.log(saveButton);
jQ.each(saveButton, new function(i,v) { console.log("#"+i+": "+v); });

这是控制台输出:

[prevObject: b.fn.b.init[0], context: document, selector: "body #WorkspaceFrame .x-panel-tbar.x-panel-tbar-noheader .x-toolbar-right .x-toolbar-right-ct table", jquery: "1.9.1", constructor: function…]
#undefined: undefined

所以saveButton是一个对象,但不是一个数组,这是由失败的jQ.each确认的。

我想把其中一个表(它总是第3个)并在其上调用.before('<p>something</p>')。我试过了saveButton[2].before('<p>HI</p>'),它没有用。


这是Zoltan回答提示之后的新尝试:

jQ(".x-panel-body.x-panel-body-noheader").find("iframe").contents().find("body").find("#WorkspaceFrame").find(".x-panel-tbar.x-panel-tbar-noheader").find(".x-toolbar-right").find(".x-toolbar-right-ct").find("table").eq(8).find(">:first-child").find(">:first-child").find(">:first-child").before('<td class="x-toolbar-cell"><button>Test</button></td>');

在控制台中正确键入此按钮会在我想要的位置添加按钮,但JS代码中的相同行无法正常工作。是什么给了什么?

2 个答案:

答案 0 :(得分:0)

您可以使用.eq(n)

选择第n个对象
saveButton.eq(n).before('<p>HI</p>')

saveButton [2]不起作用,因为这样你得到一个没有.before函数的普通元素,但.eq返回jQuery包装对象,你可以在其上调用jQuery函数。

问题的根源也可能是您选择的内容在iframe中。当您从控制台运行JS时,您位于外部窗口中,并且必须“进入”iframe。但JS可能会在内部窗口中运行并从那里运行相同的查询,因此找不到任何iframe,因此不会向saveButton变量返回任何内容。

答案 1 :(得分:0)

它在控制台中工作,因为它比用户脚本慢得多。 ;)用户脚本在iframe完成加载之前很久就会触发,即使iframe不使用AJAX来设置内容也是如此。

解决此问题的最简单方法是tune your userscript to work directly on the iframe in question,这简化了很多。

但是,由于<iframe>似乎是相同的域,因此您还可以使用AJAX页面处理iframe内容所需的相同技术。在这种情况下,the waitForKeyElements utility效果很好。

这是一个完整的脚本,应该适合你(但由于我不知道目标页面而未经测试)。请注意,如果您运行的是Chrome,则需要安装Tampermonkey(无论如何都应该这样做)来运行它。 :

// ==UserScript==
// @name     _Interacting with iframed content
// @include  http://YOUR_SERVER.COM/YOUR_PATH/*
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/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.
*/
waitForKeyElements (
    //-- Double check this selector from the console...
    "#WorkspaceFrame .x-toolbar-right-ct table:eq(8) >:first-child >:first-child >:first-child",
    addButton, 
    false, 
    ".x-panel-body.x-panel-body-noheader iframe"
);

function addButton (jNode) {
    jNode.before ('<td class="x-toolbar-cell"><button class="gmMyButton">Test</button></td>');
}



作为奖励,你可以像这样激活你的按钮。 (需要延迟以避免竞争条件。):

waitForKeyElements (
    "body", 
    addButtonHandler, 
    false, 
    ".x-panel-body.x-panel-body-noheader iframe"
);

function addButtonHandler (jNode) {
    jNode.on ("click", "button.gmMyButton", myButtonHandler);
}

function myButtonHandler (evt) {
    var btn = $(evt.target);

    console.log ("You just clicked button '" + btn.text() + "'.");
}