我正在创建一个Greasemonkey脚本来自动设置我们的在线票务系统中的一些选项,以便使日志记录调用更有效率。
无论如何,用于记录呼叫的屏幕由多个帧组成,在自动化方面我只对其感兴趣。页面和框架(包括我正在尝试编辑的元素)的精简HTML显示如下:
<html>
<head>
</head>
<frameset framespacing="0" border="0" bordercolor="#ffffff" rows="130,*,22,0">
<frame scrolling="no" marginwidth="0" marginheight="0" leftmargin="0" topmargin="0" noresize="" src="top.asp?menu=&page=" name="menu">
</frame>
<frameset id="contentCols" framespacing="8" border="8" cols="250, *" bordercolor="#ffffff">
<frame marginwidth="0" marginheight="0" leftmargin="0" topmargin="0" border="0" src="../service/loading.html" name="content" frameborder="0" style="padding-right: 10px;">
<html>
<head>
</head>
<body class="winBack" style="background-color: rgb(255, 255, 255);">
<div id="scrollableContainer" class="lockedTableContainer scrollableContainerHeight" style="position: relative; height: 0px;">
<table cellspacing="1" cellpadding="3" border="0">
<form id="configFields" name="configFields" method="post" action="/ics/tt/ticketNew.asp"></form>
<input type="hidden" value="" name="task">
<input type="hidden" value="account" name="source">
<tbody>
<tr id="ROW_109094">
<td class="webCaption" style="width: 160px;">
</td>
<td class="formText">
<select id="FIELD_109094_DROPDOWN_null" class="formText" style="width: 200px;" title="Establishment Type" name="FIELD_109094_DROPDOWN_null" onchange="updateDep(109094, this.options[this.selectedIndex].value);">
</select>
</td>
</tr>
</tbody>
<table>
</div>
</frame>
</frameset>
</frameset>
</html>
我要做的是设置selectedIndex
选择元素的FIELD_109094_DROPDOWN_null
然后,我试图运行附加到元素的change事件的updateDep
函数(包含在附加到框架的脚本中);此函数根据select元素中当前设置的值显示某些其他字段。
使用Firebug的控制台我可以使用以下两行来实现这一点:
frames["content"].document.getElementById("FIELD_109094_DROPDOWN_null").selectedIndex = 2;
frames["content"].updateDep(109094, frames["content"].document.getElementById("FIELD_109094_DROPDOWN_null").options[2].value);
但是,当我将它放入Greasemonkey脚本时,并将其附加到主窗口onload或框架的onload;我收到这个错误:
错误:frames.content.document.getElementById(“FIELD_109094_DROPDOWN_null”)为空
如果我使用以下代码,我至少可以更改select元素的选定索引:
document.getElementById("FIELD_109094_DROPDOWN_null").selectedIndex = 2;
我无法弄清楚如何通过Greasemonkey脚本运行updateDep
函数。脚本中的代码如下所示:
// ==/UserScript==
var initElements = (function () {
var elementExists = document.getElementById("FIELD_109094_DROPDOWN_null");
if(elementExists)
{
document.getElementById("FIELD_109094_DROPDOWN_null").selectedIndex = 2;
frames["content"].updateDep(109094, frames["content"].document.getElementById("FIELD_109094_DROPDOWN_null").options[2].value);
}
}
)();
window.addEventListener('load', initElements, false);
非常感谢任何帮助。
答案 0 :(得分:1)
使用框架和iFrame的技巧是它们看起来像Greasemonkey的单独页面。
因此,对于问题中的HTML,GM脚本最终可能会运行3次,具体取决于@include
,@exclude
和/或@match
指令的配置方式
因此,相同的元素将以不同的方式显示(或根本不显示),具体取决于脚本循环运行。因此,除非您精确地了解/控制脚本的执行状态,否则不要使用frames["content"]
之类的代码。最好是测试节点并有条件地运行代码。
另一件事是,当使用驻留在目标页面上的javascript时,您需要使用unsafeWindow
或解决方法。
总而言之,这样的代码应该有效:
var depSelect = document.querySelector ("#FIELD_109094_DROPDOWN_null");
if (depSelect) {
depSelect.selectedIndex = 2;
unsafeWindow.updateDep (109094, depSelect.options[2].value);
}
(假设@include
,@exclude
和/或@match
指令没有有趣的业务。)
您不应该需要window.addEventListener('load'...
内容,也不需要将代码包装在initElements()
中。
答案 1 :(得分:0)
我的发现是GM并没有通过名字识别帧。让我的脚本工作的唯一方法是使用框架索引而不是名称。
frames[2].document...
而不是
frames['aname'].document...