JavaScript События

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

Иногда события возникают без участия пользователя. К таким событиям относятся, например, окончание загрузки элемента и выгрузка элемента - load и unload.

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

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

  • Привязка обработчиков событий

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

  • Первый способ назначения обработчика события состоит в использовании HTML атрибутов элемента:
    <элемент имя_события="код обработчика">
  • Второй способ состоит в использовании свойств элемента из сценария JavaScript. Предположим, на странице есть элемент с идентификатором "element1". Тогда программирование реакции этого элемента на щелчек мыши осуществляется следующим образом:
    element1.имя_события = обработчик;

    где обработчик - имя функции, которая вызывается в ответ на возникновение события. Такой способ назначения обработчика события применяется в тех случаях, когда объекту не соответствует HTML элемент (например - объект window, ему не соответствует ни один элемент страницы, однако иногда возникает необходимость обрабатывать события изменения размеров - onresize).

  • addEventListener(). DOM- привязка: разработанная W3C. Привязка осуществляется при помощи функции addEventListener, принимающей три параметра: название события (например, click), функцию, которая будет обрабатывать событие, и логический флаг(фаза) для разрешения или отмены захвата события. Если логический флаг(фаза) установлен в true, то при срабатывании события во вложенном элементе, обработчик будет вызван на фазе "захвата", а если значение будет false, то - на фазе "всплытия". Чаще всего фаза останавливается в false так IE не поддерживает модель событий DOM уровня 2 и поэтому не понимает фазы "захвата".
    // Обнаружение первого элемента <form> и привязка к нему обработчика события
    // 'submit'
    document.getElementsByTagName("form")[0].addEventListener('submit',function(e){
    // Остановка всех попыток отправки данных формы
    return stopDefault( e );
    }, false);

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

Недостаток W3C- привязки: он не работает в Internet Explorer до версии 9; вместо него в старых версиях IE нужно применять функцию attachEvent.

addEventListener позволяет установить несколько обработчиков одного и того же события(порядок выполнения не гарантируется).

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

Object Event

Объект Event позволяет получать подробную информацию о событии, что позволяет сделать обработку более эффективной. Необходимо помнить следующее:

  • объект event создается браузером автоматически
  • объект event доступен только в обработчиках событий
  • объект event не имеет методов. В вашем распоряжении только свойства, которые в момент возникновения события принимают те или иные значения.
Всплытие событий. Когда в элементе DOM возникает событие, браузер проверяет наличие обработчика данного события в самом элементе, и если таковой определен, вызывает его. После того как элемент получит свой шанс обработать событие, браузер проверяет наличие обработчика событий данного типа в родительском элементе, и если в этом элементе присутсвует обработчик события данного типа, он также будет вызван; затем подобная проверка происходит у родителя этого элемента, пока не будет достигнута вершина дерева DOM.
Свойство Пояснение 
type Возвращает тип события 
returnValue позволяет установить возвращаемое обработчиком события значение. 
true - (по умолчанию) стандартный обработчик будет вызван 
false - стандартный обработчик не вызывается 
 
cancelBubble устанавливает признак "всплывания" события 
true - всплывание события не происходит 
false - (по умолчанию) событие всплывает 
 
srcElement элемент - источник события 
toElement указывает элемент, на который был уведен курсор мыши при возникновении события onMouseOut 
fromElement указывает элемент, с которого пришел курсор мыши при возникновении события onMouseOver 
button определяет, какие кнопки мыши были нажаты в момент возникновения события 
0 - нет нажатых кнопок 
1 - левая кнопка 
2 - правая кнопка 
3 - левая и правая кнопки 
4 - средняя кнопка 
5 - левая и средняя кнопки 
6 - правая и средняя кнопки 
7 - все три кнопки 
 
wheelDelta определяет смещение при прокрутке колеса мыши. Отрицательное значение - поворот колеса "на себя", положительное - поворот колеса "от себя" 
offsetX, offsetY Координаты курсора мыши в момент возникновения события относительно верхнего левого угла элемента, отправившего событие. 
x, y Координаты курсора мыши в момент возникновения события относительно верхнего левого угла относительно позиционируемого родительского элемента. 
clientX, clientY Координаты курсора мыши в момент возникновения события относительно верхнего левого угла клиентской области страницы. 
screenX, screenY Координаты курсора мыши в момент возникновения события относительно верхнего левого угла экрана. 
keyCode Код нажатой на клавиатуре клавиши в Unicode 
altKey Признак состояния кнопки Alt в момент возникновения события: true - нажата, false - свободна 
altLeft Признак состояния левой кнопки Alt в момент возникновения события: true - нажата, false - свободна 
ctrlKey Признак состояния кнопки Ctrl в момент возникновения события: true - нажата, false - свободна 
ctrlLeft Признак состояния левой кнопки Ctrl в момент возникновения события: true - нажата, false - свободна 
shiftKey Признак состояния кнопки Shift в момент возникновения события: true - нажата, false - свободна 
shiftLeft Признак состояния левой кнопки Shift в момент возникновения события: true - нажата, false - свободна 
repeat признак удерживания клавиши 

Существует ряд элементов в HTML, для которых определены некоторые обработчики событий по умолчанию или стандартные обработчики. Так для элемента <a> (гиперссылка) определен обработчик onclick выполняющий переход на ресурс, заданный атрибутом href. Если вы желаете, чтобы после вашей обработки некоторого события стандартный обработчик не вызывался, присвойте значение false свойству returnValue объекта event.

Листинг: запрет вызова стандартного обработчика

<html>
    <head>
        <style type="text/css">
           a.btn {
		       padding: 3;
			   background-color: #dddddd;
			   color: #000000;
			   text-decoration: none;			   
			   border: 1px solid #333333;
		   }
		   a.btn:hover {
		       background-color: #ddeeff;
		   }		   
		   
        </style>
        <script type="text/javascript">
            function clickHandler () {			    
                alert ("Пользовательский обработчик!");
            }
        </script>
    </head>
    <body>
	    <a class="btn" href="" onclick="clickHandler(); event.returnValue=false;">Это гиперссылка</a>
    </body>
</html>
Вместо строки event.returnValue=false можно с тем же успехом использовать оператор return false.

Существует ряд задач, когда в решении о вызове стандартного обработчика должет принять участие пользователь (прямо или коссвенно). В таких случаях поступают следующим образом:

Листинг: принятие решения о вызове стандартного обработчика

<html>
    <head>
        <style type="text/css">
           a.btn {
		       padding: 3;
			   background-color: #dddddd;
			   color: #000000;
			   text-decoration: none;			   
			   border: 1px solid #333333;
		   }
		   a.btn:hover {
		       background-color: #ddeeff;
		   }		   
		   
        </style>
    </head>
    <body>
	<a class="btn" href="http://www.microcoft.com" 
           onclick="return confirm('Переход на страницу'+this.innerText+'.\nПродолжить?');">
            http://www.microcoft.com
        </a>
    </body>
</html>

Разберем пример по порядку. На странице расположена гиперссылка на web-узел компании Microsoft®. При щелчке не гиперссылке будет вызван обработчик события click, состоящий из оператора return, возвращающего значение "истина" или "ложь", в зависимости от кнопки, нажатой пользователем в диалоговом окне confirm. Таким образом, переход по гиперссылке осуществляется только в том случае, если пользователь согласится с переходом.

На web страницах часто используют этот прием. Например, приводится описание некоторого примера в сокращенном виде и добавляется кнопка, при нажатии на которую раскрывается дополнительная информация - полный код примера. Раскрытие дополнительной информации осуществляется путем изменения свойства style.display некоторого элемента. Для того, чтобы пример был изначально скрыт, его свойство style.display должно иметь значение "none". Для раскрытии кода примера, свойству style.display присваивают значение "block".

<html>
    <head>
        <style type="text/css">
            #primer1 {
                display: none;
                padding: 5;
                background-color: #dddddd;
            }
        </style>
        <script type="text/javascript">
            function display(elem) {
                if (elem.style.display != "block") { 
                    elem.style.display = "block";
                    event.srcElement.innerText = "Скрыть";
                }
                else {
                    elem.style.display = "none";
                    event.srcElement.innerText = "Отобразить";
                }
                return false;
            }
        </script>
    </head>
    <body>
        <a href="#" onclick="return  display(primer1)">Отобразить</a> пример
        <pre id="primer1">
#include <iostream.h> 

void main () {
    cout<<"Hello, world!";
}
        </pre>
    </body>
</html>

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

Приступим. Для начала зададимся вопросом - какие события мы будем обрабатывать для перетаскиваемого элемента? Во первых, элемент нужно "схватить" мышью - то есть, нажать на нем левую кнопку мыши. Значит, событие "mousedown" отрабатывать необходимо. Так же дело обстоит и с "отпусканием" элемента. К списку обрабатываемых событий добавляем "mouseup". Осталось событие перемещения курсора мыши - "mousemove", при котором мы будем менять позицию перетаскиваемого элемента.

Итак, с событиями вопрос выяснен. Теперь разберемся с самими элементами. Дело в том, что задавать координаты элементов (left и top) можно только для абсолютно позиционируемых (в нашем случае) элементов. Значит - в стилевое оформление перетаскиваемых элементов должна входить строка "position: absolute;".

Ниже приводится полный код примера. Обратите внимание на следующую особенность: события mousedown и mouseup обрабатываются для перетаскиваемого элемента, а событие "mousemove" - для элемента <body>. Это связано с тем, что мышь - инертный манипулятор. То есть, при резком рывке курсора мы рискуем выскочить за пределы перетаскиваемого элемента и "уронить" его, тогда как вылететь за пределы страницы можно не бояться. После выполнения примера, вы столкнетесь (или уже столкнулись) с "маленькой" неприятностью: при "захвате" элемента его верхний левый угол "прыгает" в позицию курсора, после чего отцепиться от элемента не представляется возможным иначе, как перезагрузкой страницы.

Исправим этот недостаток. Для этого будем при "захвате" элемента запоминать смещение курсора относительно верхнего левого угла перетаскиваемого элемента в глобальных переменных. Информация о смещении курсора хранится в свойствах offsetX и offsetY объекта event.

<html>
    <head>
        <style type="text/css">
           #square1 {
               width: 50;
               height: 50;
               position: absolute; 
               left: 10;
               top: 10;
               border: 1px solid black;
               background: #DDDDDD;
           }
        </style>
        <script type="text/javascript">
            var elementToDrag = null;            			
    var offX, offY; // глобальные переменные для хранения смещения     
    function captureElement (elem) { // "захват" элемента мышью 
        if (!elementToDrag) {
            elementToDrag = elem;
            offX = event.offsetX; // запоминаем координаты курсора 
            offY = event.offsetY; // в момент щелчка 
        }
    }    
    function releaseElement () { // "отпускание" элемента 
        elementToDrag = null;
    }    
    function dragElement () { // "перетаскивание" элемента 
        if (elementToDrag){
            elementToDrag.style.pixelLeft = event.clientX - offX; // вносим поправку 
            elementToDrag.style.pixelTop = event.clientY - offY;  // в координаты элемента 
        }
    }
        </script>

    </head>
    <body onmousemove="dragElement()">
        <span id="square1" 
              onmousedown="captureElement(this)" 
              onmouseup="releaseElement()">
        </span>
    </body>
</html>
PQ VPS сервера в 28+ странах.