Javascript.RU

Введение в события

Практически все JavaScript сценарии используют в своей работе события. Это обусловлено тем, что именно события связывают действия происходящие в документе, с соответствующим кодом JavaScript, тем самым обеспечивая динамику веб-интерфейса.

Обычно обрабатываются события порожденные действиями пользователя, но они могут возникать без его прямого участия, например событие load у некоторых элементов HTML вызывается в момент окончания загрузки этого элемента.

Всего существует много событий, некоторые из которых могут быть обработаны практически на любом элементе HTML, другие - специфические для опеределенных элементов, или объектов JavaScript.

Все события можно условно разделить на следующие типы:

  • События DOM-элементов, которые инициируются действиями пользователя. Например click - клик на элементе, или mouseover - мышь появилась над элементом.
  • События DOM-элементов или объектов JavaScript, которые инициируются в ходе их работы. Например load, readystatechange и т.п.
  • События для окна. Например resize при изменении размера и move при перемещении окна браузера.

После срабатывания события вызывается соответствующий ему обработчик, который нужно назначить заранее. Существует несколько способов сделать это.

Обработчик события можно указать в виде inline-записи, прямо в атрибуте тага onимя_события. Например, чтобы отслеживать нажатия на кнопку input, можно назначить обработчик onclick вот так:

<input id="b1" value="Нажми Меня" onclick="alert('Спасибо!');" type="button"/>

Этот код в действии:

Таким образом можно установить обработчик любого события, используя атрибут onимя_события="код_обработчика" того тага, на котором это событие должно быть обработано.

Стоит обратить внимание, что имя события в атрибуте нужно указывать с префиксом "on", хотя по рекомендации W3C имена событий не содержат этого префикса. Другими словами, для события click используется атрибут onclick, для mouseoveronmouseover, и т.д.

Напомним, что имена атрибутов HTML тагов нечувствительны к регистру, поэтому oNcLiCk сработает так же, как onClick и onclick. Но если вы на своих страницах используете спецификацию XHTML, то имена тагов и их атрибуты должны быть указаны в нижнем регистре, для совместимости с XML.

Это самый простой, старый, но в тоже время самый наглядный способ установки обработчика, который будет работать в любом браузере с поддержкой JavaScript.

Тем не менее, этот способ имеет свои минусы, самым большим из которых является сложность определения контекста события. Например, если вам нужно узнать на каком элементе сработало событие, то в обработчике вы обычно используете ссылку this, но при использовании inline записи обработчика, this будет ссылаться на элемент только внутри значения атрибута, но не в вызванных из него функциях.
Это происходит потому, что фактически обработчиком выступает код, указаный в атрибуте, а не функции, которые в нем вызываются.

<script>
function someEventHandler(element) {
	alert([element, this]); // [object HTMLInputElement],[object Window]
}
</script>

<input value="Теперь нажми меня" onclick="someEventHandler(this)" type="button"/>

Другими словами, вам нужно будет передавать в вызываемые в обработчике функции ссылку на текущий элемент самостоятельно. Подробнее об этом будет написано в разделе "Определение контекста события".

Еще один минус заключается в том, что если в документе много элементов, на которые таким способом установлен обработчик, или установлены обработчики на несколько событий одного элемента, то верстка HTML "захламляется" этими вызовами.
По возможности, лучше полностью разделять код сценариев и верстку HTML, поэтому рекомендуется устанавливать обработчики напрямую из JavaScript.

Самый "близкий родственник" представленного выше способа, это установка функции-обработчика в свойство onимя_события соответствующего элемента. Этот способ тоже будет работать в любом браузере с поддержкой JavaScript (и DOM, в конкретных случаях использования).

Стоит сразу обратить внимание на две детали:

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

    Кроме того, как и все свойства объектов JavaScript, имя свойства onимя_события чувствительно к регистру символов и должно быть всегда быть в нижнем регистре.

  2. Обработчик - не текст, а именно функция javascript.

    При первом способе, т.е когда обработчик прописан напрямую в HTML, браузер автоматом создает из него функцию.

Вот пример установки обработчика события click на элемент документа:

document.getElementById('b1').onclick = function() {
    alert('Спасибо')
}

В этом примере в качестве обработчика использовано анонимное замыкание, но вы также можете установить любую объявленную функцию:

function doSomething() {
	alert('Спасибо');
}

document.getElementById('b1').onclick = doSomething;

Обратите внимание, что не нужно указывать круглые скобки при присваивании, иначе функция будет выполнена не при соответствующем событии, а сразу же, и свойству будет присвоен её результат.

У прямого объявления через свойство есть недостаток - на элемент можно повесить только один обработчик одного события.

input.onclick = function() { alert(1) }
// ...
input.onclick = function() { alert(2) }  // заменит предыдущий

Зато есть и достоинства, например удобное определение условий события - в обработчике this всегда указывает на элемент, на котором сработало событие, а в качестве первого параметра обработчику передается объект Event (см. раздел "Оперделение контекста события").

Кроме того, существует возможность определить установлен ли обработчик на определённое событие элемента, и даже запустить обработчик самостоятельно из Javascript:

var input = document.getElementById('b1');
input.onclick = function() {
    alert('Спасибо')
}

if (typeof input.onclick != "undefined") {
	alert("На элемент было установлено событие!");
	// Запускаем обработчик напрямую:
	input.onclick();
}

Такой способ установки обработчика очень популярен и используется повсеместно, поскольку он работает во всех браузерах и имеет лишь один серьёзный недостаток.

Представленных выше методов иногда недостаточно для случаев, которые возникают при разработке более-менее серьёзного JavaScript приложения. Этими способами невозможно установить два (и больше) обработчика на одно событие одного элемента и невозможно удалить определённый обработчик из нескольких.

Такой функционал может понадобиться например тогда, когда на сайте присутствует несколько (или неопределённое количество) одновременно работающих скриптов, которые инициализируются по событию load документа.

Как всегда, не существует абсолютно кросс-браузерных методов по установке и удалению обработчиков событий, и их существует два варианта.

Методы, предложенные Microsoft, работают только в браузере Internet Explorer и имеют серьёзные недостатки, из-за которых их часто неудобно использовать даже в нем.

Установка обработчика:

element.attachEvent( "on"+имя события, обработчик)

Удаление обработчика:

element.detachEvent( "on"+имя события, обработчик)

Например:

var input = document.getElementById('b1')
var handler = function() {
    alert('Спасибо!')
}
input.attachEvent( "onclick" , handler) // поставить обработчик
// .... 
input.detachElement( "onclick", handler) // убрать обработчик

Как видно из примера, установка обработчиков происходит не сложнее, чем в тех способах, о которых рассказывалось ранее. Тем не менее, существует несколько очевидных (и не очень) недостатков, из-за которых часто не получается использовать решение от Microsoft.

Самым большим недостатком является то, что этот метод вызывает обработчик по указателю, а не копирует его, как все остальные методы, поэтому this внутри обработчика всегда указывает на объект window и совершенно бесполезен.

Кроме того, обработчику не передается currentTarget, а это значит, что в отличие от других методов, невозможно определить на каком элементе сработало событие при "всплывании".

Из-за того, что Internet Explorer поддерживает только "всплывающий" порядок срабатывания событий на вложенных элементах, attachEvent не может обрабатвать событие на фазе "Перехвата" (подробнее об этом в разделе "Порядок срабатывания событий").

Из-за своих недостатков, решение от Microsoft не отвечает требованиям, предъявляемым таким методам, и не является аналогичной альтернативой решению от W3C.

Лучше отказаться от его использования в пользу эмуляции функционала решения W3C, которая используется в кросс-браузерных реализациях установки обработчиков, одна из которых представлена в разделе "Кросс-браузерное управление событиями" этой статьи.

Решение W3C работает практически во всех браузерах, кроме Internet Explorer, и не имеет многих недостатков решения от Microsoft.

Установка обработчика:

element.addEventListener( имя_события, обработчик, фаза)

Удаление обработчика:

element.removeEventListener( имя_события, обработчик, фаза)

Этот метод может работать с любыми объектами, а не только элементами DOM, в отличии от свойства onимя_события. Такое применение часто используется при разработке плагинов для браузера, или в скриптах, которые взаимодействуют с объектами браузера.

Обратите внимание, что имя события указывается без каких-либо префиксов, соответствуя рекомендациям W3C.

Еще одно отличие от решения Microsoft это третий параметр – фаза.
Если он установлен в true, то при срабатывании события во вложенном элементе, обработчик будет вызван на фазе "перехвата", а если значение будет false, то - на фазе "вслывания". Подробнее об этом написано в разделе этой статьи «Порядок срабатывания событий».

Для обычной установки обработчика третий параметр всегда должен быть false.

Использование - аналогично:

// ... объявить функцию-обработчик handler ...
input.addEventListener( "click" , handler, false) // поставить обработчик
// .... 
input.removeEventListener( "click", handler, false) // убрать обработчик

Как и в других случаях, вы должны передать имя обработчика не ставя круглых скобок, иначе функция будет выполнена, а в качестве обработчика будет передан её результат.

Параметры функций в случае должны быть одинаковыми при установке и снятии обработчика. И сразу нужно отметить, что в метод removeEventListener должен быть передан тот же обработчик, который был установлен в функции addEventListener и это накладывает определённые ограничения в использовании анонимных функций в качестве обработчиков.

Есть еще одна проблема, с которой можно столкнуться при управлении событиями: нельзя точно сказать установлен ли определённый обработчик, или нет, и какие обработчики установлены на данный момент.

В спецификации DOM 3 существует объект eventListenerList, но он слишком новый и на данный момент не поддерживается ни одним из браузеров. Тем не менее, вы можете всегда смело вызывать removeEventListener даже для тех обработчиков, на счет которых вы не уверены, были ли они установлены или нет, т.к. это не вызовет ошибки.

Важно учитывать, что порядок срабатывания обработчиков не описан в спецификации, другими словами, в случае:

someElement.addEventListener("click", doSomething1, false);
someElement.addEventListener("click", doSomething2, false);

полагаться на то, что doSomething1 сработает раньше, чем doSomething2 не стоит, хотя это часто происходит именно так.

Еще вы можете столкнуться с задачей, где вам нужно будет установить определённые обработчики в цикле. Если вы попробуете сделать вот так:

var element = document.getElementById("testEvents");
for (var i = 1; i <= 100; i++) {
	element.addEventListener("click", eventHandler, false);
}

То обнаружите, что будет установлен только один обработчик. Решением этой проблемы может быть установка обработчика с небольшим тайм-аутом:

var element = document.getElementById("testEvents");
for (var i = 1; i <= 100; i++) {
	setTimeout( function() {
		element.addEventListener("click", eventHandler, false);
	}, 1); // 1 мс должно хватить.
}

В заключение разговора о addEventListener/removeEventListener можно сказать, что несмотря на небольшие недостатки, использовать эти методы удобно. При работе с ними не появляется проблем с определением контекста, и можно установить обработчик, который будет срабатывать только на определённой фазе цепочки событий.

Этот код создан Dead Edwards и модифицирован Tino Zijdel.

Эти функции реализуют решения от W3C на всех тех браузерах, где отсутствуют addEventListener/removeEventListener, включая Internet Explorer.
Это реализуется через цепочку вложенных обработчиков на свойстве onимя_события.

Заодно, этот способ управления событиями добавляет IE-событиям W3C методы preventDefault и stopPropagation.

// written by Dean Edwards, 2005
// with input from Tino Zijdel - crisp@xs4all.nl
// http://dean.edwards.name/weblog/2005/10/add-event/

function addEvent(element, type, handler)
{
	if (element.addEventListener)
		element.addEventListener(type, handler, false);
	else
	{
		if (!handler.$$guid) handler.$$guid = addEvent.guid++;
		if (!element.events) element.events = {};
		var handlers = element.events[type];
		if (!handlers)
		{
			handlers = element.events[type] = {};
			if (element['on' + type]) handlers[0] = element['on' + type];
			element['on' + type] = handleEvent;
		}
	
		handlers[handler.$$guid] = handler;
	}
}
addEvent.guid = 1;

function removeEvent(element, type, handler)
{
	if (element.removeEventListener)
		element.removeEventListener(type, handler, false);
	else if (element.events && element.events[type] && handler.$$guid)
		delete element.events[type][handler.$$guid];
}

function handleEvent(event)
{
	event = event || fixEvent(window.event);
	var returnValue = true;
	var handlers = this.events[event.type];

	for (var i in handlers)
	{
		if (!Object.prototype[i])
		{
			this.$$handler = handlers[i];
			if (this.$$handler(event) === false) returnValue = false;
		}
	}

	if (this.$$handler) this.$$handler = null;

	return returnValue;
}

function fixEvent(event)
{
	event.preventDefault = fixEvent.preventDefault;
	event.stopPropagation = fixEvent.stopPropagation;
	return event;
}
fixEvent.preventDefault = function()
{
	this.returnValue = false;
}
fixEvent.stopPropagation = function()
{
	this.cancelBubble = true;
}

// Этот фрагмент исправляет проблему, когда onload-атрибут 
// элемента body перезаписывает назначенные до этого обработчики
// события window.onload
if (!window.addEventListener) {
	document.onreadystatechange = function() {
		if (window.onload && window.onload != handleEvent) {
			addEvent(window, 'load', window.onload);
			window.onload = handleEvent;
		}
	}
}

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

Рассмотрим ситуацию, когда у вас есть три элемента "вложенных" друг в друга.

1

2

3
<div class="d1" >1<!-- самый верхний, в представлении DOM, элемент -->
    <div class="d2">2
        <div class="d3">3</div><!-- самый глубокий элемент -->
    </div>
</div>

Если они будут обрабатывать одно событие, то обработчик для какого элемента будет вызван первым? Всего существует 2 модели поведения, они не имеют преимуществ между собой, но используют принципиально разные подходы. Стандарт W3C объединяет две модели в одну универсальную.

Capturing events order
В этой модели сначала будет выполнен обработчик на элементе 1, и последним будет выполнен обработчик на элементе 3. Она называется "перехват", потому что родительские элементы могут обработать событие раньше, чем непосредственная цель события, как бы "перехватывая" обработку.

Визуально это выглядит так (кликните на вложенном элементе, чтоб увидеть, какой будет порядок обработки события):

1

2

3
<div id="capt1" class="d1">
    <div id="capt2" class="d2">
        <div id="capt3" class="d3"></div>
    </div>
</div>

<script>
	document.getElementById("capt1").addEventListener("click", function() { alert(1) }, true);
	document.getElementById("capt2").addEventListener("click", function() { alert(2) }, true);
	document.getElementById("capt3").addEventListener("click", function() { alert(3) }, true);
</script>

Такой порядок был предложен Netscape и никогда не поддерживался в Internet Explorer, поэтому в IE вы не сможете увидеть этот пример в действии. Остальные браузеры поддерживают одновременно такой порядок и порядок "всплывания".

Bubbling events order
В этой модели сначала будет выполнен обработчик на элементе 3, и последним будет выполнен обработчик на элементе 1. Такой порядок называется "всплывающим", потому что событие поднимается с самых "глубоких" элементов в представлении DOM, к самым "верхним", как пузырек воздуха в воде.

Визуально это выглядит так (кликните на вложенном элементе, чтоб увидеть, какой будет порядок обработки события):

1

2

3
<div class="d1" onclick="alert(1)">
    <div class="d2" onclick="alert(2)">
        <div class="d3" onclick="alert(3)"></div>
    </div>
</div>

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

Если такой функционал не нужен, от него можно избавиться, использовав в одном из обработчиков следующую конструкцию:

// Вариант Internet Explorer:
event.cancelBubble = true;
// Вариант стандарта W3C:
event.stopPropagation();

После выполнения обработчика, который содержит такой код, событие прекратит "всплывать". Нужно отметить, что "всплывание" не имеет ничего общего с "действием по-умолчанию", поэтому такой код, например, не отменит действие перенаправления по ссылке, по щелчку на ней.

Во время "всплывания", каждый обработчик имеет доступ к элементу, который стал целью события, и к текущему элементу. Это не относится к обработчикам, установленым через attachEvent/detachEvent - они в такой ситуации остаются слепы. Подробнее об этом в следующем разделе "Определение контекста события".

W3C events order
Решение от W3C объединяет обе модели в одну универсальную.

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

Визуально это выглядит так (кликните на вложенном элементе, чтоб увидеть, какой будет порядок обработки события):

1

2

3
<div id="capt1" class="d1">
    <div id="capt2" class="d2">
        <div id="capt3" class="d3"></div>
    </div>
</div>

<script>
	document.getElementById("capt1").addEventListener("click", function() { alert(1) }, true);
	document.getElementById("capt2").addEventListener("click", function() { alert(2) }, true);
	document.getElementById("capt3").addEventListener("click", function() { alert(3) }, true);
	document.getElementById("capt1").addEventListener("click", function() { alert(1) }, false);
	document.getElementById("capt2").addEventListener("click", function() { alert(2) }, false);
	document.getElementById("capt3").addEventListener("click", function() { alert(3) }, false);
</script>

Как уже было написано ранее, если в качестве третьего параметра функции addEventListener передать значение true, то событие будет срабатывать при первой фазе "захвата", если false – при фазе "всплывания".

При установке обработчиков классическими методами (через свойство элемента или атрибут html тага) события всегда срабатывают на фазе "всплывания".

... TODO ...

Ключевое слово this в обработчике события означает текущий элемент.

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

1

2

3
<div class="d1" onclick="alert(this.className)">1
    <div class="d2" onclick="alert(this.className)">2
        <div class="d3" onclick="alert(this.className)">3</div>
    </div>
</div>

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

Способ передачи - разный, и зависит от браузера.

Internet Explorer
Глобальный объект window.event
Остальные (стандарт)
Первый аргумент обработчика

Обычно делают кроссбраузерное объявление так:

function handler() {
    var event = arguments[0] || window.event
    ...
}

Здесь сначала проверяется, есть ли первый аргумент (стандарт DOM), а если нет - берется глобальный window.event.

Мы разберем только те свойства, из которых можно получить полезную кросс-браузерную информацию.

shiftKey, ctrlKey, altKey
Служат для определения, нажата ли во время события соответствующая клавиша
target/srcElement
Самый внутренний элемент, на котором произошло событие. Причем, не тот элемент, на котором сработал обработчик, а более глубокий.

По стандарту положено называть это свойство target, Microsoft использует srcElement.

В этом примере обработчик стоит только на внешнем диве, но благодаря event.target выводит по клику класс исходного элемента.

1

<div class="d1" onclick="e=arguments[0]||event;t=e.target||e.srcElement;alert(t.className)">
<span class="number">1</span>
    <div class="d2">
        <span class="number">2</span>
        <div class="d3">
            <span class="number">1</span>
        </div>
        <a class="d2a" href="javascript:void(0)">Ссылка</a>
    </div>
</div>
function() {
  // получить объект событие.
  // вместо event лучше писать window.event
  e = arguments[0] || event
  // кросс-браузерно получить target
  t = e.target || e.srcElement
  alert(t.className)
}

+3

Автор: Octane, дата: 14 августа, 2008 - 13:48
#permalink

«addEventListener» и «removeEventListener» не работают без указания 3-го параметра.


Автор: Андрей Параничев, дата: 14 августа, 2008 - 14:25
#permalink

Спасибо за замечание. Многое сейчас дописывается и будет исправлено, это лишь черновик.


Автор: Octane, дата: 15 августа, 2008 - 14:48
#permalink

Обычно делают кроссбраузерное объявление так:

function handler() {
    var event = arguments[0] || window.event
    ...
}

Под словом «handler» обычно понимается объект, который вызвал это событие, т.е. «target» или «srcElement» (в IE), а здесь мы получаем объект «событие», содержащее этот элемент. Мне кажется будет удобнее записать в таком виде:

Function.prototype.event = function() {
	return window.event || this.arguments[0];
};

Function.prototype.handler = function() {
	return this.event().srcElement || this.event().target;
};

Теперь, чтобы получить событие, вызвавшее функцию, нужно написать:

arguments.callee.event()

А для того, чтобы получить «handler»:

arguments.callee.handler()

Автор: Андрей Параничев, дата: 15 августа, 2008 - 16:46
#permalink

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


Автор: Kolyaj, дата: 24 августа, 2008 - 20:52
#permalink

handler - обработчик.

Может проще все-таки так?

function handler(evt) {
  evt = evt || window.event;
  // ...
}

Автор: NetFantom, дата: 25 августа, 2008 - 17:23
#permalink

Скажите, а как можно сгенерировать событие для объекта?
Если имеется к примеру

element.onchange = function () { ... }

то как объекту можно "вручную" послать notify

element.onchange();
element.onchange();

не работает

Объект Event тоже не содержит нужных методов, к тому же хочется кросс браузерное решение.


Автор: Илья Кантор, дата: 26 августа, 2008 - 13:09
#permalink

Попробуйте jQuery использовать, там как раз есть trigger/triggerHandler.

Если без jQuery - в браузерах есть метод fireEvent/dispatchEvent специальный. Названия методов - приблизительны, в IE там одно а в других браузерах - по стандарту.


Автор: Андрей Параничев, дата: 26 августа, 2008 - 17:21
#permalink

Почитайте про методы document.createEventObject и fireEvent для Internet Explorer. И document.createEvent, initEvent, dispatchEvent для W3C-совместимых браузеров.

В вашем случае решение будет примерно такое:

<html>
<head>
	<script>
	function forceOnChange(id)
	{
		var element = document.getElementById(id);
		if (document.createEventObject)
		{
			// Создаем объект событие (для IE не обязательно, но полезно знать, чтоб
			// передавать "синтетические" свойства события обработчику(ам)):
			var evt = document.createEventObject();
			// Запускаем событие на элементе:
			element.fireEvent("onchange", evt);
		} else if (document.createEvent) {
			// Создаем объект событие:
			var evt = document.createEvent("HTMLEvents");
			// Инициализируем:
			evt.initEvent("change", false, false);
			// Запускаем на элементе:
			element.dispatchEvent(evt);
		} else {
			return false;
		}
	}
	</script>
</head>
<body>
	<textarea onchange="alert(this.value)" id="myTextarea">somevalue</textarea><br />
	<a href="javascript://" onClick="forceOnChange('myTextarea')">Change it!</a>
</body>
</html>

Автор: Вова (не зарегистрирован), дата: 16 июня, 2009 - 22:52
#permalink

Молодца. Огромное спасибо, особенно за наглядные примеры !!!


Автор: Alexela (не зарегистрирован), дата: 30 июня, 2009 - 15:43
#permalink

Классный пример с имитацией эвэнтов, но есть трабл, не вешается на инпуты типа file и submit, на батон вешается а на этих двоих нет. Может есть какое решение?


Автор: Гость (не зарегистрирован), дата: 17 августа, 2009 - 19:37
#permalink

Всё вешается!!!


Автор: Гость (не зарегистрирован), дата: 4 ноября, 2009 - 15:14
#permalink

Спасибо за статью и за комментарии к ней

Очепятка в примере реализации MIcrosoft detachEvent (detachEvent назван detachElement'ом):

input.attachEvent( "onclick" , handler) // поставить обработчик
// .... 
input.detachElement( "onclick", handler) // убрать обработчик

Автор: B@rmaley.e><e, дата: 11 января, 2010 - 22:55
#permalink

Этот код создан Dead Edwards

За что так Дена? Он вроде еще жив.


Автор: Барин, дата: 10 сентября, 2010 - 20:01
#permalink

"function doSomething()
{
alert('Спасибо');
}
document.getElementById('b1').onclick = doSomething;

Обратите внимание, что не нужно указывать круглые скобки при присваивании, иначе функция будет выполнена не при соответствующем событии, а сразу же, и свойству будет присвоен её результат."

А что делать, если необходимо вызвать функцию с параметрами?


Автор: B@rmaley.e><e, дата: 11 сентября, 2010 - 22:42
#permalink
function doSomething(p1, p2){
alert('Спасибо\n' + [p1,p2].join('\n'));
}

document.getElementById('b1').onclick = function(){
  doSomething('param1', 'param2')
};

Автор: Барин, дата: 19 сентября, 2010 - 21:22
#permalink

У меня есть такая "форма":

<div id="comment">
<textarea id="teaxtArea" onBlur="alert('Фокус потерян')"></textarea>
<div id="options" onClick="showText('Комментарий отправлен')">Отправить</div>
</div>

Если поставить фокус в текстовую область, а потом нажать "Отправить", то сработает онБлур, а онКлик проигнорируется. Как можно сделать так, чтобы одним щелчком сработали оба события? И если это возможно, чтобы сработал сначала онКлик, а потом онБлур. Попытался использовать примеры из статьи, так и не понял, как сделать так чтобы работал режим Всплывания, а не Перехвата, потому что по умолчанию всегда именно Перехват. Заранее благодарю.


Автор: Геннадий К. (не зарегистрирован), дата: 9 июля, 2011 - 11:09
#permalink

Господа, подскажите, как поступить.
Есть HTML

<li><a href="">some_link</a></li>

На элемент li повешены события onmouseover и onmouseout, которые, скажем, меняют класс самого элемента - устанавливает и снимает соответственно (кстати, спасибо за статью - понял, как сделать кроссбраузерное решение через проверку srcElement). Но при наведении курсора на вложенную ссылку, видимо, срабатывает onmouseout - и у LI снимается установленный ранее класс. Как обойти эту ситуацию? - чтобы при наведении на ссылку не пропадал эффект onmouseover элемента LI.


Автор: Геннадий К. (не зарегистрирован), дата: 9 июля, 2011 - 11:59
#permalink

Нашел недочет в коде - достаточно было браться не за event.target, а за event.currentTarget
И вообще, как оказалось, лучше было его за объект браться как this - и с кроссбраузерностью не было бы мороки


Автор: Маэстро, дата: 13 сентября, 2012 - 18:20
#permalink

Андрей Параничев,
Использовал я function addEvent(element, type, handler) (описанную здесь Вами) года два, свято веря, что автор всё предусмотрел и отладил. Однако, бывает такое, что бяки вылезают и через годы, причем в самых неожиданных местах. В одном из проектов потребовалось совместить перемещение объекта мышью с нажатой клавишей Ctrl. Так вот оказалось, что в IE при этом наблюдается РЕЗКОЕ ЗАМЕДЛЕНИЕ движения мыши (?!!). Исследования причин привели к Вашей функции addEvent()... Вот так вот.


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
3 + 8 =
Введите результат. Например, для 1+3, введите 4.
 
Поиск по сайту
Другие записи этого автора
Андрей Параничев
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Популярные таги
Последние комментарии
Последние темы на форуме
Forum