2012-07-24 226 views
5

我试图使用的Chrome userscript或Tampermonkey脚本来修改一个页面,这样的结构:如何从脚本访问iframe的javascript?

<body> 
content up here 

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

的iframe是同源。

我需要访问iframe#main中的函数。我想到我可以使用unsafeWindow来得到它,但我一直没有得到或undefined返回。

我试过的东西摆:

  • 试图在iframe创建一个新的脚本元素,但其附加到父甚至$('frame#main').contents().append(script)$('frame#main').contents()[0].createElement('script')

  • window.frames["#main"].contentWindow回报不确定。

我已经尝试了很多其他的事情,我不能在此刻回想,但我已经用尽了我所有的想法,觉得我打字的垃圾比什么才是最重要了。
我想不出如何玩iFrame的unsafeWindow

+0

这是所有相同的起源 – Skinner927 2012-07-24 20:16:07

回答

10
  1. unsafeWindow在Chrome,Tampermonkey或Firefox上不能很好地处理frame/iframe。
  2. 试图使用jQuery访问全局(到框架)JS,就像那样,将不起作用。
  3. 用户脚本将在满足@include,@exclude和/或@match要求的iframe上运行。

所以,你需要考虑多个脚本运行,然后你有两个基本的方法,这取决于你想要完成什么。您可以:

(A)根据this answer为特定框架定制脚本。 (B)注入你的JS并使用特殊的frames对象来抓取你想要的特定函数。

以下脚本演示了两者。安装在Tampermonkey (或Firefox Greasemonkey)中,然后访问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"); 



您将看到脚本从两个主要页面,并从IFRAME运行的功能。控制台输出(Tampermonkey)将是:

 
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 

它也将作为一个直线上升的Chrome userscript如果去掉unsafeWindow线(S)。

+0

那么你把什么都不适合我的工作,但这与你的参考答案结合起作用。基本上,我最终做的是,如您所建议的那样,将脚本包含在两个框架中,但仅根据脚本的加载位置执行其中的一部分。有点笨重的解决方法,但在这一点上,我会采取任何事情。 谢谢。 – Skinner927 2012-07-26 18:36:13