使用Greasemonkey脚本在框架中调用函数

3

我正在创建一个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>

我要做的是设置FIELD_109094_DROPDOWN_null选择元素的selectedIndex。然后,我试图运行附加到元素更改事件的脚本中包含的updateDep函数;此功能根据当前在选择元素中设置的值显示某些其他字段。

使用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上时,会出现以下错误:
“Error: frames.content.document.getElementById("FIELD_109094_DROPDOWN_null") is null”
但是,如果我使用以下代码,我至少可以更改选择元素的选定索引:
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);

非常感谢您的帮助。

2个回答

1

关于框架和iFrame的诀窍是它们在Greasemonkey中看起来都像是独立的页面。

因此,对于问题中的HTML,根据@include@exclude和/或@match指令的配置方式,GM脚本可能会运行3次。

所以,同一个元素会根据脚本正在循环的运行不同而呈现出不同(甚至不出现)。因此,除非你准确地了解/控制脚本的执行状态,否则不要使用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() 中。


嘿,布洛克,这个完美地运行了,谢谢你,我非常感激。 - achillesminor

0

我的发现是GM不会通过名称识别框架。我让脚本工作的唯一方法是使用索引而不是名称。

 frames[2].document...

替代

 frames['aname'].document...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接