Шаг 13 - Динамическое переопределение обработчиков

Недавно пришло вот такое письмо от Jurij Kulikov <...83@inbox.lv>:

Читал ваши уроки по JavaScript на FirstSteps.ru , но не нашел там 
динамического переопределения юбработчиков соытий!
Вот что меня интересует:При нажатии одной и той-же кнопки должны вызываться 
3 разных файла. Обработчики переопределяются с помощью тега вида 
<a href="#" onClick="document.forms[0].but1.onClick=button1()">

Я полазил по просторам нета, и кое чего нашел, но работает оно не коректно...

<script language="JavaScript">
<!--
function button1() {
window.location.href = "1.htm";
}
function button2() {
window.location.href = "2.htm";
}
function button3() {
window.location.href = "3.htm";
}
//-->
</script>

Здесь надо onclick!

<form>
<input name="but1" type="button" value="Загрузить файл">
</form><p>
<a href="#" onClick="document.forms[0].but1.onClick=button1()">
Задать загрузку файла 1 при нажатии кнопки </a><BR>
<a href="#" onClick="document.forms[0].but1.onClick=button2()">
Задать загрузку файла 2 при нажатии кнопки </a><BR>
<a href="#" onClick="document.forms[0].but1.onClick=button3()">
Задать загрузку файла 3 при нажатии кнопки </a> 

при данном коде, обработчик не переопределяется, а при нажатие 
на гиперссылку, сразу запускается обработчик (который надо поставить на кнопку).
Объясните почему так происходит, я сколько не искал ошибку не могу 
найти, ведь вроде все правильно, а работает не коректно!

Раз пришлось тратить время на ответ, то пусть знают все :) Разбираться с вашим кодом я сначала не захотел, и попытался реализовать поставленную задачу самостоятельно. Но вот сейчас, набирая эти строки на клавиатуре похоже я нашел ошибку и в вашем коде. Проверить ее мне конечно сейчас сложно, для этого придется набирать ваш код в файл :)

Но так как я при разработке своего примера придерживался этого правила, то у Вас оно определенно забыто.

Давайте посмотрим что я тут придумал:

<html><body>

<script>
function noevent() {};

var ehandler = noevent;

function buttonclick(){
    ehandler();
};
    
function event1() {
    document.form1.t.value = "event1 exec";
};

function event2() {
    document.form1.t.value = "event2 exec";
};
	    
function eventchanger(a) {
    ehandler = a;
};
</script>
		    
<form name=form1>
<input type=text name=t>
<input type=button onclick="buttonclick()" value=Click>
<br>
<button onclick="eventchanger(event1)">Event 1</button>
<input type=button onclick="eventchanger(event2)" value="Event 2">
<br>
<a href=# onclick="eventchanger(event1)">Event 1</a>
<a href="javascript:eventchanger(event2)">Event 2</a>
		    
</form>
		    
</body></html>

Честно говоря, JavaScript я не люблю по одной простой причине - код который Вы пишете может не всегда правильно работать на всех браузерах, поэтому чтобы убедиться в работоспособности данного решения пришлось к набору Internet Explorer и Opera скачать и установить дополнительно Mozilla Firefox.

Итак о том, что же все-таки пришлось делать. Это классическая структура подобной программы, если бы Вы разарабатывали ее на Си. Первое, что требуется сделать - оределить пустой обработчик события, т.е. набор из пустой функции и переменной хранящей адрес функции обработчика. Далее определяется набор функций обработчиков, и функция замены обработчика путем присвоения адреса нового обработчика переменной.

Вот как раз в этом переопределении адреса у Вас и затык. Либо у Вас маленький опыт, либо набивали на автоматизме, но Вы похоже забыли ключевое для данного случая правило синтаксиса. Вы вместо event1 набрали event1(), таким образом присвоили не значение адреса функции, а результат ее работы. Таким образом и получается, что Ваш обработчик просто запускается в работу, а не переопределяется событие onclick.

По всей видимости, если Вы исправите эту ошибку, то у Вас тоже все заработает, но если нет, то берите мой код. Его я проверил на всех браузерах, и об этом мы сейчас поговорим.

Не зря я ставил все доступные браузеры, оказывается спектр решений не большой. Вы все должны видеть, что переопределение обработчиков я делаю четырьмя различными способами, чтобы проверить работоспособность всех методов. Так вот оказывается, что Opera и Firefox метод замены обработчика через <button onclick=""> не воспринимают вообще, в то время как в Internet Explorer этот метод работает нормально. Все остальные методы работают везде и имеют право на жизнь, поэтому можете использовать любое в зависимости от того, что Вам требуется по дизайну.

Каюсь, не хотелось отвечать на это письмо, но повторная просьба перетянула чашу весов :) И теперь хочу поблагодарить вас Юра, за то что мне пришлось получить эти знания.


Предыдущий Шаг | Оглавление
Автор Кузин Андрей - 21.05.2006