Содержание

JavaScript События

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

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

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

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

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

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

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

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

Object 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>

Пример. Работаем с мышью: перетаскивание элементов. Drag and Drop.

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

Приступим. Для начала зададимся вопросом - какие события мы будем обрабатывать для перетаскиваемого элемента? Во первых, элемент нужно "схватить" мышью - то есть, нажать на нем левую кнопку мыши. Значит, событие "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>