I have the following code in the top frame of a two frame page:
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;
This works on the original document load, but when I call this function from another frame (usually when only one frame reloads), the hook is set, but when the onkeydown
function fires, it does not receive the appropriate arguments, instead evt == null
.
Full Code follows:
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>
To recreate the issue, right click the bottom frame, click refresh, click "Reset Hooks", and press keys.
Related Question: Handle keyPress Accross Frames in IE
I've also read an article on Javascript closures, but I'm not sure how it applies.
Sorry for the narrowness of question, but I really don't know Javascript well enough to figure out the trick to this.