1

時,我有在兩幀頁面的頂部框架下面的代碼:的Javascript事件沒有被正確地設置在封閉稱爲跨框架

 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 == null。

完整的代碼如下:

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> 

要重新創建問題,請右鍵單擊底部框架,單擊刷新,單擊「重置掛鉤」,然後按鍵。

相關問題:Handle keyPress Accross Frames in IE

我也看到了有關Javascript closures的文章,但我不知道如何將其應用。

對不起,問題的狹隘性,但我真的不知道Javascript足以找出這個竅門。

回答

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); 
} 

當以這種方式註冊事件偵聽器時,正確的事件對象會自動作爲參數傳遞給處理函數。

1

何時窗口基準製成,它解決了的窗口對象調用範圍,而不是駐留範圍

這意思是,當你從底部框架執行setKeyHook()重新連接事件偵聽器,提及窗口相同top.frames.BOTTOM,這是不窗口你想要使用 - 你想從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 
} 
+0

不起作用。我仍然得到「handleKeypress(e):e == null」。 – 2009-06-29 18:27:58

+0

我認爲這會在IE如何處理事件(全局事件對象vs傳遞事件對象)方面出現弱點。讓我想出另一個解決方案。 – 2009-06-29 18:54:04