JS控制台与用户脚本中的不同行为,尝试操作iframed内容
Different behavior in JS console vs userscript, trying to manipulate iframed content
我正在尝试破解一个我不拥有但我希望改进的Web应用程序。
我想在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
确认。
我想拿一张桌子(它总是第三张)并在上面打电话给.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代码中的同一行不起作用。什么给?
您可以使用 .eq(n) 获取选择中的第 n 个对象
saveButton.eq(n).before('<p>HI</p>')
saveButton[2] 不起作用,因为这样你得到一个没有 .before 函数的普通元素,但 .eq 返回 jQuery 包装的对象,你可以在它上面调用 jQuery 函数。
问题的根源也可能是您选择的内容位于 iframe 中。当您从控制台运行 JS 时,您处于外部窗口,您必须"单步"进入 iframe。但是JS可以在内部窗口中运行,从那里运行相同的查询不会找到任何iframe,因此不会向saveButton变量返回任何内容。
它在控制台中工作,因为您比用户脚本慢得多。 ;) 用户脚本在 iframe 完成加载之前很久就会触发,即使 iframe 不使用 AJAX 来设置内容也是如此。
解决此问题的最简单方法是调整您的用户脚本以直接在有问题的 iframe 上工作,这大大简化了。
但是,由于<iframe>
似乎是同一域,因此您也可以使用 AJAX 页面所需的相同技术来处理该 iframe 内容。 在这种情况下,waitForKeyElements
实用程序效果很好。
这是一个完整的脚本,应该适合您(但未经测试,因为我不知道目标页面)。 请注意,如果您运行的是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() + "'.");
}
- 如何运行在加载时操作 iframe 内容的代码
- 如果未输入任何内容,则使 JavaScript 按钮不执行任何操作
- 在不更改 HTML 的情况下操作 HTML 字符串的内容
- 文本内容长度在 DOM 操作后不会更改
- 使用jquery操作html的部分内容
- 如何在我更改输入时添加javascript操作'的内容
- 根据用户点击的内容进行不同的操作
- 如何动态操作jquery可拖动UL元素的内容
- chrome扩展插件在浏览器操作中插入内容脚本
- 如何加载外部HTML内容以由此JS代码操作
- 根据警报消息内容执行某些操作
- JS控制台与用户脚本中的不同行为,尝试操作iframed内容
- 离子在加载所有图像和内容时执行操作
- 基于多个可能的 DIV 内容的 JavaScript 操作
- 在执行某些操作后检查 Javascript 变量的内容
- 当输入某些内容时,使用 jquery 执行某些操作
- 通过Google Chrome/Firefox Addon中的控制台访问/操作内容脚本
- 使用ng-bind-html和默认内容操作内容
- 多个控制器在一个Angular指令中操作内容
- 如何在Ember中创建一个Handlebars块帮助器来包装/操作内容