我正在尝试破解我不拥有但我想改进的网络应用程序。
我想在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代码中的相同行无法正常工作。是什么给了什么?
答案 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() + "'.");
}