Обрабатывать нажатие клавиш через фреймы в IE
Я пытался обработать событие onkeydown для нескольких кадров (нет, я, к сожалению, не могу избавиться от кадров) с помощью javascript (см. Мой предыдущий вопрос здесь). Я получаю дескриптор документа в другом фрейме и устанавливаю его обработчик onkeydown равным моей функции. Ошибка не выдается, но когда я позже проверю настройки документа, onkeydown будет нулевым. Я получил одинаковые результаты в IE6 и IE7. Что я делаю неправильно.
функция
function setKeyHook(doc) { try{ if (doc) if (parent.TOP.handleKeypress){ doc.onkeydown = parent.TOP.handleKeypress; logMessage('Attached handler'); } else{ logMessage('No handleKeypress'); } else logMessage('No doc'); } catch (ex){ logMessage(ex.toString()); } }
Вызов
setTimeout("setKeyHook(parent.document.getElementById(\"bottom\").document);", 1000);
Выход
Прикрепленный обработчик
- После исполнения
BOTTOM.protocol = Протокол передачи гипертекста BOTTOM.onkeypress = null BOTTOM.onrowenter = null BOTTOM.onmousedown = null
Как мне применить один и тот же обработчик событий для всех кадров?
Примечание: это должно работать (и только работать) в IE6 и IE7.
2 ответа
Я получил это на работу
frameset.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<title>Test</title>
</head>
<frameset rows="50%,50%">
<frame src="frame1.html" name="TOP">
<frame src="frame2.html" name="BOTTOM">
</frameset>
</html>
frame1.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<title>Frame 1</title>
<script type="text/javascript">
onload = function()
{
top.frames.BOTTOM.document.onkeydown =
self.document.onkeydown = function( evt )
{
return function()
{
// Just an example to show it's working
document.getElementById( 'output' ).value += String.fromCharCode( evt.keyCode );
}
}( window.event );
}
</script>
</head>
<body>
frame1
<textarea id="output"></textarea>
</body>
</html>
frame2.html
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
"http://www.w3.org/TR/html4/frameset.dtd">
<html>
<head>
<title>Frame 2</title>
</head>
<body>
frame2
<textarea></textarea>
</body>
</html>
Прежде всего, всегда стоит быть достаточно явным с вашими объектными ссылками. Использование проприетарных ярлыков DOM (таких как window. FrameName) просто добавляет ненужный потенциал ошибок. Вот почему мой скрипт явно просматривает коллекцию кадров объекта окна.
Далее следует ознакомиться с различными встроенными ссылками на окна в DOM при работе с наборами кадров. Всего 4
- окно - текущее окно. Это также подразумевается, когда не учтено (то есть window.onload === onload)
- parent - родительское окно для текущего
- top - самое верхнее окно в семействе фреймов. parent === top, когда у вас есть только один набор фреймов.
- псевдоним окна
Итак, в основном, что я сделал здесь, когда событие onload срабатывает в окне frame1, это добавление функции обработчика к событию keydown для документов в обоих окнах frame.
Эта функция использует замыкание, чтобы гарантировать, что событие, сгенерированное в frame1, доступно фактическому обработчику, независимо от того, какое окно генерирует событие keydown. Это необходимо из-за того, как IE делает события. В то время как другие браузеры создают новые объекты событий по мере их появления и передают их обработчикам событий, IE просто изменяет глобальный объект события (на который ссылается window.event или более простое событие just), чтобы отразить текущее событие.
Я надеюсь, что в этом есть смысл.
Если у вас возникли проблемы с чтением объекта события фрейма, когда событие обрабатывается в другом фрейме, вам придется явно ссылаться на него
var event = top.frames.BOTTOM.event;
Я сам столкнулся с этой проблемой, и начало моего обработчика событий было
var myFrame = top.frames[0];
myFrame.onkeydown = keyboardHandler;
function keyboardHandler(e) {
if (!e && event) {
e = event; //For handling the event in IE
}
if (!e && myFrame.contentWindow.event) {
e = myFrame.contentWindow.event; //For handling event in IE6 from inside the iFrame
}
if (e) {
...
}
}