如何从脚本访问iframe的javascript? [英] How do I access an iframe's javascript from a userscript?

查看:107
本文介绍了如何从脚本访问iframe的javascript?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 < p $ p $>我试图使用Chrome的用户脚本或Tampermonkey脚本修改这个结构的页面。体> 
content up here

< iframe id =mainsrc =foo.dat>< / iframe>
< / body>

iframe是同源。



我需要访问 iframe#main 中的函数。我认为我可以使用 unsafeWindow 来获得它,但我一直没有收到任何东西,或者返回 undefined



我试过了一些东西:


  • 试过在 iframe 中创建一个新的脚本元素,但即使使用 $('frame#main')。contents()。也会附加到父元素上。 (script) $('frame#main')。contents()[0] .createElement('script')


  • window.frames [#main]。contentWindow 返回undefined。




我尝试了许多其他我现在还记不起的东西,但我已经用尽了所有的想法,觉得我输入的垃圾比任何重要的东西都多。

我无法弄清楚如何玩iFrame的 unsafeWindow

解决方案


  1. unsafeWindow Chrome,Tampermonkey或Firefox上的帧/ iframe很好。

  2. 尝试使用jQuery访问全局(到框架)JS,就像这样,将无法工作。

  3. userscripts将在符合 @include @exclude 和/或 @match

因此,您需要考虑多个脚本运行,然后您有两种基本方法,具体取决于您尝试的方式去完成。您可以:

(A)根据框架

$ b <对象来抓取你想要的特定功能。



以下脚本演示了这两种方法。将其安装在Tampermonkey 1 (或Firefox Greasemonkey)中,然后访问 此测试jsBin 的页面。


$ b

  // == UserScript == 
// @name _Calling iframe函数
// @namespace _pc
// @include http://jsbin.com/ugoruz/*
// @include http:/ /jsbin.com/okequw/*
// == / UserScript ==

console.log(Script start ...);

/ * ---这个下一个函数调用仅适用于Firefox或Tampermonkey,
不是纯Chrome用户。
* /
console.log(calling functionOfInterest()...);
unsafeWindow.functionOfInterest();


if(window.top === window.self){
// ---当页面是主站点时运行的代码...
console.log(Userscript在MAIN页面中。);

// ---帧对象与unsafeWindow不兼容。
/ * ---接下来的三项工作在Firefox中,但不是Tampermonkey,也不是纯粹的Chrome。
console.log(1,frames [1] .variableOfInterest); //未定义
console.log(2,unsafeWindow.frames [1] .variableOfInterest); //未定义
console.log(3,frames [1] .unsafeWindow); //未定义
* /
/ * ---接下来会导致无声崩溃,所有浏览器...
console.log(4,unsafeWindow.frames [1]。 unsafeWindow.variableOfInterest);
* /

// ---要获得iFramed JS,我们必须注入我们的JS。
withPages_jQuery(demoAccessToFramedJS);
}
else {
// ---页面在iframe中时运行的代码...
console.log(Userscript位于FRAMED页面中。) ;
console.log(帧的ID是:,window.self.frameElement.id);



函数demoAccessToFramedJS($){
$(body)。prepend(
'< button id =gmMain> ;在主窗口上运行JS< / button>'
+'< button id =gmFrame>在iframe上运行JS< / button>'
);
$ b $(#gmMain,#gmFrame)。click(function(){
if(this.id ===gmMain){
functionOfInterest();
}
else {
frames [1] .functionOfInterest();
}
console.log(this.id +was clicked。);
});


函数withPages_jQuery(NAMED_FunctionToRun){
// ---使用命名函数进行清晰度和调试...
var funcText = NAMED_FunctionToRun.toString() ;
var funcName = funcText.replace(/^function\s+(\w+)\s*\((.|\\\
|\r )+$/,$ 1);
var script = document.createElement(script);
script.textContent = funcText +\\\
\\\
;
script.textContent + ='jQuery(document).ready (function(){'+ funcName +'(jQuery);});';
document.body.appendChild(script);
};

console.log(脚本结束);



< hr>

您将看到脚本从主页面和iframe中都运行了一个函数,控制台输出(Tampermonkey)将会是:

 
Tampermonkey开始
脚本开始...
调用functionOfInterest()...
Userscript位于MAIN页面
脚本结束
Tampermonkey启动
脚本启动...
调用functionOfInterest()...
Userscript位于FRAMED页面
框架ID为:iframe2
脚本结束






1 如果您删除 unsafeWindow 行。


I'm trying to use a Chrome userscript or a Tampermonkey script to modify a page with this structure:

<body>
content up here

<iframe id="main" src="foo.dat"></iframe>
</body>

The iframe is same-origin.

I need to access a function that's in iframe#main. I thought I could use unsafeWindow to get it but I keep getting nothing or undefined returned.

I've tried a slew of things:

  • Tried creating a new script element in the iframe, but it attaches to the parent even with $('frame#main').contents().append(script) or $('frame#main').contents()[0].createElement('script')

  • window.frames["#main"].contentWindow returns undefined.

I have tried many other things I can't recall at the moment, but I have exhausted all my ideas and feel that I'm typing rubbish more than anything that counts.
I can't figure out how to play with the unsafeWindow of the iFrame.

解决方案

  1. unsafeWindow doesn't play nice with frames/iframes on Chrome, Tampermonkey, or Firefox.
  2. Trying to access global (to the frame) JS with jQuery, like that, will not work.
  3. userscripts will run on iframes that meet the @include, @exclude, and/or @match requirements.

So, you need to account for the multiple script runs and then you have two basic approaches, depending on what you are trying to accomplish. You can:

(A) Tailor the script to specific frame(s), as in this answer.

or (B) inject your JS and use the special frames object to grab the specific function you want.

The following script demonstrates both. Install it in Tampermonkey1 (or Firefox Greasemonkey), and then visit this test page at jsBin.

// ==UserScript==
// @name        _Calling iframe functions
// @namespace   _pc
// @include     http://jsbin.com/ugoruz/*
// @include     http://jsbin.com/okequw/*
// ==/UserScript==

console.log ("Script start...");

/*--- This next function call will work in Firefox or Tampermonkey ONLY,
    not pure Chrome userscript.
*/
console.log ("calling functionOfInterest ()...");
unsafeWindow.functionOfInterest ();


if (window.top === window.self) {
    //--- Code to run when page is the main site...
    console.log ("Userscript is in the MAIN page.");

    //--- The frames object does not play nice with unsafeWindow.
    /*--- These next three work in Firefox, but not Tampermonkey, nor pure Chrome.
    console.log ("1", frames[1].variableOfInterest);                // undefined
    console.log ("2", unsafeWindow.frames[1].variableOfInterest);   // undefined
    console.log ("3", frames[1].unsafeWindow);                      // undefined
    */
    /*--- This next would cause a silent crash, all browsers...
    console.log ("4", unsafeWindow.frames[1].unsafeWindow.variableOfInterest);
    */

    //--- To get at iFramed JS, we must inject our JS.
    withPages_jQuery (demoAccessToFramedJS);
}
else {
    //--- Code to run when page is in an iframe...
    console.log ("Userscript is in the FRAMED page.");
    console.log ("The frame's ID is:", window.self.frameElement.id);
}


function demoAccessToFramedJS ($) {
    $("body").prepend (
          '<button id="gmMain">Run JS on main window</button>'
        + '<button id="gmFrame">Run JS on iframe</button>'
    );

    $("#gmMain, #gmFrame").click ( function () {
        if (this.id === "gmMain") {
            functionOfInterest ();
        }
        else {
            frames[1].functionOfInterest ();
        }
        console.log (this.id + "was clicked.");
    } );
}

function withPages_jQuery (NAMED_FunctionToRun) {
    //--- Use named functions for clarity and debugging...
    var funcText        = NAMED_FunctionToRun.toString ();
    var funcName        = funcText.replace (/^function\s+(\w+)\s*\((.|\n|\r)+$/, "$1");
    var script          = document.createElement ("script");
    script.textContent  = funcText + "\n\n";
    script.textContent += 'jQuery(document).ready(function() {'+funcName+'(jQuery);});';
    document.body.appendChild (script);
};

console.log ("Script end");



You will see that the script runs a function from both the main page and from the iframe. The console output (Tampermonkey) will be:

Tampermonkey started
Script start...
calling functionOfInterest ()...
Userscript is in the MAIN page.
Script end
Tampermonkey started
Script start...
calling functionOfInterest ()...
Userscript is in the FRAMED page.
The frame's ID is: iframe2
Script end


1 It will also work as a straight-up Chrome userscript if you remove the unsafeWindow line(s).

这篇关于如何从脚本访问iframe的javascript?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆