1

2フレームページのトップフレームに次のコードがあります。

        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;

これは元のドキュメントの読み込みで機能しますが、別のフレームからこの関数を呼び出すと(通常、1つのフレームのみがリロードされる場合)、フックが設定されますが、onkeydown関数が起動すると、適切な引数を受け取らず、代わりにevt ==ヌル。

完全なコードは次のとおりです。

KeyFrameTest.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への参照が行われると、常駐スコープではなく、呼び出し元スコープのウィンドウオブジェクトが解決されます。

これが意味するのは、下のフレームからsetKeyHook()を実行してイベントリスナーを再接続すると、ウィンドウへの参照は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 に答える