Java 脚本,难以获取页面中所有嵌套框架的列表

Java Script, Difficulty getting list of all nested frames in page

你好,我需要为我的 GreaseMonkey 脚本获取所有帧的列表,但实际上我猜这是 一般 Javascript 问题.如果我可以访问嵌套在页面中的每个框架,那就太好了。到目前为止,我在获取主文档框架中嵌套的框架数时遇到了问题。

我正在处理的页面由 frameset 组成,即 multilevel 并且框架包含其他框架。我已经设法获得有关主文档框架集的顶级框架的信息(在代码 级别 1 中)但是在这个级别我得到的信息是这些框架的帧数等于 0 而不是是的。

我想出了以下代码

$(document).ready(function(){
var frames = window.frames;
var i,j;
var reportText = "level 0 > " + frames.length +"\r\n";

for (i = 0; i < frames.length; i++) {
    var frames2 = frames[i].frames;
    reportText += "level 1 - " + i + " > " + frames[i].name + " - " + frames2.length +"\r\n";

    for (j = 0; j < frames2.length; j++) {
      var frames3 = frames2[j].frames; 
      reportText += "level 2 - " + i + " - " + j + " > "  + frames2[j].name + " - " + frames3.length +"\r\n";
    }
}

alert(reportText);});

所以 level 0 这实际上是主文档框架计数和 level 1 名称或主文档框架 - 这些东西被正确报告但不是每个 1 级 帧的帧数。我想知道这是不是因为我的代码出错了,或者可能是因为子帧没有完全加载。

我试过从键盘快捷键调用我的代码,毕竟看起来它已完全加载,但这里还有另一个问题,似乎以下代码似乎不适用于仅包含框架集的页面

 (function(){
 document.addEventListener('keydown', function(e) {
 if (e.keyCode == 72 && !e.shiftKey && !e.ctrlKey && e.altKey && !e.metaKey) {
 
 //...my previous code inside document.ready...
 
   }
 }, false);})();

最好是代码自动梳理所有帧和子帧,但其当前形状(每个级别都有自己的循环)也很好。

无法使用快捷键的问题是次要的。 主要是获取主文档框架内及其他框架内的正确帧数。

编辑: 示例输出和带有嵌套框架集的我的测试页

输出

level 0 > 3

level 1 - 0 > main1 - 0

level 1 - 1 > main2 - 0

level 1 - 2 > main3 - 0

带有嵌套框架集的测试页

frame0.htm

<!DOCTYPE html>
<html>
<frameset cols="25%,*,25%">
  <frame id="frmain1" name="main1" src="frame0_1.htm">
  <frame id="frmain2" name="main2" src="frame0_2.htm">
  <frame id="frmain3" name="main3" src="frame0_3.htm">
</frameset>
</html>

frame0_1.htm

<!DOCTYPE html>
<html>
<frameset rows="25%,*">
  <frame id="frsub11" name="sub11" src="frame0_1_1.htm">
  <frame id="frsub12" name="sub12" src="frame0_1_2.htm">
</frameset>
</html>

frame0_1_1.htm

<!DOCTYPE html>
<html>
<body style="background: darkorange;">
</body>
</html>

frame0_1_2.htm

<!DOCTYPE html>
<html>
<body style="background: lightyellow;">
</body>
</html>

frame0_2.htm

<!DOCTYPE html>
<html>
<frameset rows="25%,*,25%">
  <frame id="frsub21" name="sub21" src="frame0_2_1.htm">
  <frame id="frsub22" name="sub22" src="frame0_2_2.htm">
  <frame id="frsub23" name="sub23" src="frame0_2_3.htm">
</frameset>
</html>

frame0_2_1.htm

<!DOCTYPE html>
<html>
<body style="background: skyblue;">
</body>
</html>

frame0_2_2.htm

<!DOCTYPE html>
<html>
<body style="background: cornflowerblue;">
</body>
</html>

frame0_2_3.htm

<!DOCTYPE html>
<html>
<body style="background: slateblue;">
</body>
</html>

frame0_3.htm

<!DOCTYPE html>
<html>
<frameset rows="25%,*">
  <frame id="frsub31" name="sub31" src="frame0_3_1.htm">
  <frame id="frsub32" name="sub32" src="frame0_3_2.htm">
</frameset>
</html>

frame0_3_1.htm

<!DOCTYPE html>
<html>
<body style="background: darkgreen;">
</body>
</html>

frame0_3_2.htm

<!DOCTYPE html>
<html>
<body style="background: lightgreen;">
    <a id="test" href="http://www.google.com">testlink</a>
</body>
</html>

问题出在您调用它的事件上。 $(document).ready() 在加载当前 DOM 时触发。所以在加载3个主框架时触发。但此时这些帧还没有加载它们的 iframes。通过将事件更改为 window.onload,您应该会得到预期的结果。像这样:

$(window).load(function(){
    ...

window.onload = function(){
    ...

参见window.onloadhttps://developer.mozilla.org/en/docs/Web/API/GlobalEventHandlers/onload

The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images, scripts, links and sub-frames have finished loading.

https://api.jquery.com/ready/

frameset is not supported in html5

请看下面的演示:frameset Demo。我已经修改了 htm 文件。这个想法是监听框架集 onload 事件并在 onlnoad 事件被触发后访问它的内容。

为了访问子框架的内容,必须调用Same-Origin policy

工作代码解决方案

使用递归函数和 window load 事件,就像这样(适用于最新版本的 Chrome、FireFox 和 Edge;没有测试其他人。可能适用于IE5+ 也一样)。

在您的顶层使用此代码 framesetframe0.htm:

<!DOCTYPE HTML Frameset DTD>
<html>
<head>
<script>
window.onload = function()
{
    var allFrames = [];
    function recursFrames(context)
    {
        for(var i = 0; i < context.frames.length; i++)
        {
            console.log(context.frames[i].name + " -- " + context.frames[i].location.href);
            allFrames.push(context.frames[i]);
            recursFrames(context.frames[i]);
        }
    }
    recursFrames(window);
    console.log("Frames count: " + allFrames.length);
}
</script>
</head>
<frameset cols="25%,*,25%">
  <frame id="frmain1" name="main1" src="frame0_1.htm">
  <frame id="frmain2" name="main2" src="frame0_2.htm">
  <frame id="frmain3" name="main3" src="frame0_3.htm">
</frameset>
</html>

这写入控制台只是为了向您展示正在发生的事情,但是您当然可以使用此信息做任何您想做的事情。它创建了一个包含所有子框架的平面列表(数组),但您可以根据需要分层构建它,或其他任何方式。

HTML 5条提醒

您正在使用 HTML5 DOCTYPE,但 HTML5 不支持 frameset。但是由浏览器决定何时停止支持它,而且许多浏览器仍然这样做。我建议您尽快停止使用 frameset。如果您需要 frame-like 行为(不同 windows 和文档),请改用 iframe