1

我在两帧页面的顶部框架中有以下代码:

        function setKeyHook()
        {
            logMessage("setKeyHook()");
            top.frames.BOTTOM.document.onkeydown = 
            top.frames.TOP.document.onkeydown = function( evt )
            {
                    return function(){
                        top.frames.TOP.handleKeypress(evt);
                    };

            }( window.event );
        }

        onload = setKeyHook;

这适用于原始文档加载,但是当我从另一帧调用此函数时(通常只重新加载一帧时),设置了钩子,但是当 onkeydown 函数触发时,它不会收到适当的参数,而是 evt ==无效的。

完整代码如下:

关键帧测试.asp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
   "http://www.w3.org/TR/html4/frameset.dtd">
<html>
    <head>
        <title>KeyFrameTest</title>
    </head>
    <frameset Rows="80%,20%">
       <frame id="TOP" name="TOP" src="KeyFrameTestTop.asp">
       <frame id="BOTTOM" name="BOTTOM" src="KeyFrameTestBottom.asp">
    </frameset> 
</html>

KeyFrameTestTop.asp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
   "http://www.w3.org/TR/html4/frameset.dtd">
<html>
    <head>
        <script type="Text/Javascript">

            String.prototype.trim = function() {
                return this.replace(/^\s+|\s+$/g,"");
            }

            NumElements = 5;
            //Alt Vals
            ControlCode = 1;
            ShiftCode = 2;
            ControlShiftCode = 3;
            //Key Vals
            keyR = 82;
            keyJ = 74;
            keyI = 73;
            keyT = 84;
            keyEnter = 13;
            //Array Indexs
            AltIndex = 0;
            KeyIndex = 1;
            FuncIndex = 2;
            KeyFuncMap = new Array(NumElements);
            for (i = 0; i < KeyFuncMap.length; ++i)
            {
                //Three elements, control or shift, key, function
                KeyFuncMap[i] = new Array(3);
            }

            KeyFuncMap[0][AltIndex] = ControlCode;
            KeyFuncMap[0][KeyIndex] = keyR;
            KeyFuncMap[0][FuncIndex] = "parent.TOP.logMessage(\"Ctrl + R\")";

            KeyFuncMap[1][AltIndex] = ControlCode;
            KeyFuncMap[1][KeyIndex] = keyJ;
            KeyFuncMap[1][FuncIndex] = "parent.TOP.logMessage(\"Ctrl + J\")";

            KeyFuncMap[2][AltIndex] = ControlCode;
            KeyFuncMap[2][KeyIndex] = keyI;
            KeyFuncMap[2][FuncIndex] = "parent.TOP.logMessage(\"Ctrl + I\")";

            KeyFuncMap[3][AltIndex] = ControlCode;
            KeyFuncMap[3][KeyIndex] = keyT;
            KeyFuncMap[3][FuncIndex] = "parent.TOP.logMessage(\"Ctrl + T\")";

            KeyFuncMap[4][AltIndex] = ControlCode;
            KeyFuncMap[4][KeyIndex] = keyEnter;
            KeyFuncMap[4][FuncIndex] = "parent.TOP.logMessage(\"Ctrl + Enter\")";

            function CompleteEvent(e)
            {
                e.cancelBubble = true;
                e.returnValue = false;
            }

            function logMessage(msg)
            {
                logBox = parent.TOP.document.getElementById("logBox");
                if( logBox.value.trim().length < 1 )
                {
                    logBox.value = msg;
                }
                else
                {
                    logBox.value = logBox.value + "\r\n" + msg;
                }
            }

            function handleKeypress(e)
            {
                logMessage("handleKeypress(e)");
                e = e || window.event ;
                if (e == null)
                {
                    logMessage("handleKeypress(e): e == null");
                    return false;
                }
                controlVal = getControlVal(e);

                for (i = 0; i < KeyFuncMap.length; i++)
                {
                    if (KeyFuncMap[i][AltIndex] == controlVal &&
                        KeyFuncMap[i][KeyIndex] == e.keyCode)
                    {
                        eval(KeyFuncMap[i][FuncIndex]);
                        CompleteEvent(e);
                    }
                }
            }

            function getControlVal(e)
            {
                if (e.ctrlKey && e.shiftKey)
                {
                    return 3;
                }
                else if (e.ctrlKey)
                {
                    return 1;
                }
                else if (e.shiftKey)
                {
                    return 2;
                }
                else return 0;
            }

            function displayEverything()
            {
                displayProps(top.frames.TOP, "top.frames.TOP", 0, 1);
                displayProps(top.frames.BOTTOM, "top.frames.BOTTOM", 0, 1);
            }

            function clearLog()
            {
                logBox = parent.TOP.document.getElementById("logBox");
                logBox.value = "";
            }

            function displayProps(o, name, level, maxLevel)
            {
                try {
                    if (level > maxLevel)
                        return;
                    for (prop in o){
                        logMessage(name + "." + prop + " = " + o[prop]);
                        if (typeof(o[prop]) == "object" && o[prop] != o){
                            displayProps(o[prop], name + "." + prop, level + 1, maxLevel);
                        }
                    }
                }
                catch (ex){
                    logMessage(ex.toString());
                }
            }

            function setKeyHook()
            {
                logMessage("setKeyHook()");
                top.frames.BOTTOM.document.onkeydown = 
                top.frames.TOP.document.onkeydown = function( evt )
                {
                        return function(){
                            top.frames.TOP.handleKeypress(evt);
                        };

                }( window.event );
            }

            onload = setKeyHook;
        </script>
    </head>
    <body>
        <h1>Hello</h1>
        <textarea id="LogBox" rows="20" cols="80"></textarea><BR>
        <input type="Button" value="Display Properties" onClick="displayEverything();"/>
        <input type="Button" value="Clear Log" onClick="clearLog();"/>
    </body>
</html>    

KeyFrameTestBottom.asp

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
   "http://www.w3.org/TR/html4/frameset.dtd">
<html>
    <head>
    </head>
    <body>
        <p>Press Keys Here</p>
        <input type="Button" value="Reset Handlers" 
            onclick="top.frames.TOP.setKeyHook();">
    </body>
</html>   

要重新创建问题,请右键单击底部框架,单击刷新,单击“重置挂钩”,然后按下键。

相关问题:在 IE 中处理 keyPress 跨帧

我还阅读了一篇关于Javascript 闭包的文章,但我不确定它是如何应用的。

抱歉,问题的范围很窄,但我真的不太了解 Javascript,无法找出解决这个问题的窍门。

4

2 回答 2

2

这是一个放弃处理事件的“旧方式”的解决方案,而是使用更灵活和强大的“事件侦听器”模型。这允许传递事件对象

请注意,attachEvent() 方法仅适用于 IE(您在上一篇文章中规定可以使用 - 但如果您支持其他方法,则需要更改此设置)

function setKeyHook()
{
  var botDocument = top.frames.BOTTOM.document;
  var topDocument = top.frames.TOP.document;
  var eventName = 'onkeydown';
  var handlerFunc = top.frames.TOP.handleKeypress;

  //    Clear them first, or else they'll attach twice and thusly, fire twice
  botDocument.detachEvent( eventName, handlerFunc );              
  topDocument.detachEvent( eventName, handlerFunc );

  topDocument.attachEvent( eventName, handlerFunc );
  botDocument.attachEvent( eventName, handlerFunc );
}

当以这种方式注册事件侦听器时,正确的事件对象会自动作为参数传递给处理函数。

于 2009-06-29T19:02:09.317 回答
1

当对window进行引用时,它会解析调用范围的 window 对象,而不是驻留范围。

这意味着当您通过从底部框架执行 setKeyHook() 重新附加事件侦听器时,对window的引用与top.frames.BOTTOM相同,这不是您要使用的窗口 - 您想要事件从 TOP 窗口 - 这将模拟此功能的初始使用。

因此,您应该能够通过在 TOP 框架中使用对事件的显式引用来解决此问题

function setKeyHook()
{
    logMessage("setKeyHook()");
    top.frames.BOTTOM.document.onkeydown = 
    top.frames.TOP.document.onkeydown = function( evt )
    {
            return function(){
                top.frames.TOP.handleKeypress(evt);
            };

    }( top.frames.TOP.event ); // here
}
于 2009-06-29T18:06:43.000 回答