1

我正在为 Java SE API 参考文档 [ http://docs.oracle.com/javase/8/docs/api/ ] 编写一个简单的 Greasemonkey 脚本。它是这样的:

// ==UserScript==
// @id          Test
// @grant       none
// @include     http://docs.oracle.com/javase/8/docs/api/*
// @version     1
// @run-at      docuitment-end
// ==UserScript==


var classNamesFrame = null;
var classNamesDoc = null;
var classNamesATags = null;
var classNames = null;

function printClassNames()
{
  classNamesATags = classNamesDoc.getElementsByTagName('a');
  classNames = new Array();
  var i;
  for (i = 0; i < classNamesATags.length; i++) {
    classNames.push(classNamesATags[i].textContent);
  }
  console.log(classNames);
  console.log(classNamesDoc.URL);
  console.log('Total number of classes: ' + classNamesATags.length);
  alert("printClassNames called");
}


classNamesFrame = document.getElementsByName('packageFrame') [0];
classNamesDoc = classNamesFrame.contentDocument;
classNamesFrame.onload = printClassNames;
//classNamesFrame.addEventListener("DOMContentLoaded", printClassNames, false);

函数printClassNames()打印它在列出所有类的框架中找到的所有类的名称。当框架完成加载时,我应该这样做。但是在onload加载框架的 HTML 文档之前调用 even。

我尝试过使用DOMContentLoaded事件,但它甚至没有被调用。

printClassNames在框架完全加载完成后,我该怎么做才能调用它?

4

2 回答 2

1

该脚本有各种各样的错误(下面列出),但主要的是它抓住了错误的contentDocument.

这是因为 Firefox 会返回<about:blank>框架内容,直到它被实际页面内容替换。classNamesDoc变量仍然指向空白值。(请注意,Chrome 处理帧的方式略有不同,并classNamesDoc会为您更新。)

所以,移到classNamesDoc = classNamesFrame.contentDocument;里面printClassNames(),最明显的问题就解决了。

其他问题,“最坏的优先”:

  • 格式错误的元数据块。线路不正确// ==/UserScript==。这会导致脚本为您浏览的每个页面和 (i) 框架运行(并崩溃)!

  • 脚本静默崩溃(在 Firefox 上,Chrome 会报告这些错误),但只有一小部分页面/框架。您需要classNamesFrame在使用它之前检查它的值。

    例如,在docs.oracle.com/javase/8/docs/api/页面上,此脚本运行了 4 次,并且在其中的 3 次上静默崩溃。

  • 缺少@name指令。 这可能会导致范围界定、更新和维护问题——以及妨碍上传和共享脚本。

  • 语法错误。它应该是:@run-at document-end,除了你可能根本不需要这个指令,在这种情况下。

将它们放在一起,您的脚本将是:

// ==UserScript==
// @name        Test
// @grant       none
// @include     http://docs.oracle.com/javase/8/docs/api/*
// @version     1
// ==/UserScript==

var classNamesFrame = null;
var classNamesDoc = null;
var classNamesATags = null;
var classNames = null;

function printClassNames()
{
  classNamesDoc = classNamesFrame.contentDocument;
  classNamesATags = classNamesDoc.getElementsByTagName('a');
  classNames = new Array();
  var i;
  for (i = 0; i < classNamesATags.length; i++) {
    classNames.push(classNamesATags[i].textContent);
  }
  console.log(classNames);
  console.log(classNamesDoc.URL);
  console.log('Total number of classes: ' + classNamesATags.length);
  console.log("printClassNames called");
}

classNamesFrame = document.getElementsByName('packageFrame') [0];
if (classNamesFrame) {
    classNamesFrame.onload = printClassNames;
}

-- 适用于 Firefox 和 Chrome(可能还有其他)。

于 2014-07-03T00:46:12.720 回答
0
// ==UserScript==
// @name        Test
// @version     1
// @include     http://docs.oracle.com/javase/8/docs/api/allclasses-frame.html
// @grant       none
// ==/UserScript==

var classNamesATags = document.getElementsByTagName('a');
var classNames = [].map.call(classNamesATags, function(e) {
    return e.textContent;
});
console.log(classNames);
console.log(document.URL);
console.log('Total number of classes: ' + classNamesATags.length);
alert('printClassNames called');
于 2014-07-06T22:59:55.310 回答