Javascript 使用Greasemonkey脚本在帧中调用函数

Javascript 使用Greasemonkey脚本在帧中调用函数,javascript,greasemonkey,frame,Javascript,Greasemonkey,Frame,我正在创建一个Greasemonkey脚本来自动设置我们在线票务系统中的一些选项,以使记录呼叫更高效 无论如何,记录调用的屏幕是由多个帧组成的,在自动化方面,我只对其中一个感兴趣。页面和框架(包括我试图编辑的元素)的精简HTML如下所示: <html> <head> </head> <frameset framespacing="0" border="0" bordercolor="#ffffff" rows="130,*,22,0"> &

我正在创建一个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>
// ==/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);
但是,当我将其放入Greasemonkey脚本中,并将其附加到主窗口onload或框架的onload时;我得到这个错误:

错误:frames.content.document.getElementById(“字段_109094_下拉列表_null”)为null

但是,如果使用以下代码,我至少可以更改select元素的选定索引:

document.getElementById("FIELD_109094_DROPDOWN_null").selectedIndex = 2;
我不知道如何通过Greasemonkey脚本运行
updateDep
函数。脚本中的代码如下所示:

<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>
// ==/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);

任何帮助都将不胜感激。

框架和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
指令没有有趣的事情。)


你不应该需要
窗口。addEventListener('load'…
之类的东西,也不需要将代码包装在
initElements()

我的发现是GM不能按名称识别帧。我让脚本工作的唯一方法是使用帧索引而不是名称

 frames[2].document...
而不是

 frames['aname'].document...

嘿,布罗克,这很有效,谢谢你,我真的很感激。