События «мыши»

MouseEvent

Интерфейс MouseEvent представляет собой событие, которое происходит в результате взаимодествия пользователя с мышью:

click
Высокоуровневое событие происходит, когда пользователь кликнул мышью на элементе.
contextmenu
Отменяемое событие происходит, когда пользователь кликнул правой кнопкой мышью на элементе.
dblclick
Событие происходит, когда пользователь выполнил двойной клик на элементе.
mousedown
Событие происходит, когда кнопка мыши нажата над некоторым элементом, но ещё не отпущена.
mouseup
Событие происходит, когда кнопка мыши над некоторым элементом перешла из состояния нажатия, в состояние отпущена.
mouseover
Событие происходит, когда курсор мыши входит в область, принадлежащей элементу или одному из его детей.
mouseout
Событие происходит, когда курсор мыши уходит из области, принадлежащей элементу или одному из его детей.
mouseenter
Событие возникает, когда указатель мыши входит в область, принадлежащую элементу. Это событие часто используется вместе с событием mouseleave, которое происходит, когда указатель мыши уходит из области, принадлежащей элементу. Событие mouseenter подобно событию mouseover и отличается от него только тем, что событие mouseenter не всплывает. Впервые появилось в IE и было стандартизовано в HTML5, но пока поддерживается не всеми браузерами.
mouseleave
Событие происходит, когда указатель мыши уходит из области, принадлежащей элементу. Событие mouseleave подобно событию mouseout и отличается от него только тем, что событие mouseleave не всплывает. Впервые появилось в IE и было стандартизовано в HTML5, но пока поддерживается не всеми браузерами.
mousemove
Событие происходит, когда курсор мыши перемещается внутри области, принадлежащей элементу.
wheel
Событие происходит при движении колёсика мыши.

Свойства объекта MouseEvent

altKey Возвращает true, если нажата клавиша ALT.
ctrlKey Возвращает true, если нажата клавиша CTRL.
shiftKey Возвращает true, если нажата клавиша SHIFT.
metaKey Возвращает true, если нажата клавиша META.
button Возвращает номер нажатой клавиши мыши.
which Возвращает номер нажатой клавиши мыши (1,2,3).
detail Возвращает количество кликов по объекту.
clientX Возвращает координату указателя мыши по оси X относительно окна.
clientY Возвращает координату указателя мыши по оси Y относительно окна.
pageX Возвращает координату указателя мыши по оси X относительно всего документа.
pageY Возвращает координату указателя мыши по оси Y относительно всего документа.
screenX Возвращает координату указателя мыши по оси X относительно экрана.
screenY Возвращает координату указателя мыши по оси Y относительно экрана.
relatedTarget Возвращает элемент, который связан с элементом, сгенерировавшим события мыши.

click

Высокоуровневое событие click происходит, когда пользователь кликнул мышью на элементе. Порядок возникновения событий, связанных с click (для левой и средней кнопки мыши): mousedown → mouseup → click.

Поддерживаемые HTML-теги

Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>

Пример

<p onclick="fun(this,'red')">Нажмите здесь, чтобы изменить цвет текста</p>

<button id="but"> Нажмите здесь для отображения текущего дня, даты и времени: </button>
<p id="demo"></p>

<script>
document.getElementById("but").onclick = fdate;

function fdate() { document.getElementById('demo').innerHTML=Date(); }

function fun(obj,color) {obj.style.color=color;}
</script>

click()

Метод click() имитирует щелчок мыши на элементе.

Синтаксис

element.click()

Пример

<p><a id="demo" href="help.htm"> Справка </a> </p>

<button onclick="f()"> Имитировать щелчок <q>мыши</q> на ссылке <b>Справка</b> </button>


<script>
function f() { document.getElementById('demo').click(); }
</script>

contextmenu

Отменяемое событие contextmenu происходит, когда пользователь кликнул правой кнопкой мыши на элементе. Порядок возникновения событий, связанных с contextmenu (для правой кнопки мыши): mousedown → mouseup → contextmenu.

Поддерживаемые HTML-теги

Все HTML-элементы

Пример

<p id="exmpCM">Правый клик на  кнопке изменит цвет текущего текста. </p>
<button oncontextmenu="document.getElementById('exmpCM').style.color='red';"> 
  Правый клик сюда </button><b>

<button oncontextmenu="document.getElementById('exmpCM').style.color='green'; return false"> 
  Правый клик сюда без показа встроенного меню </button>

Правый клик на кнопке изменит цвет текущего текста.


dblclick

Событие dblclick происходит, когда пользователь выполнил двойной клик на элементе. Порядок возникновения событий, связанных с dblclick: mousedown → mouseup → click → mousedown → mouseup → click → dblclick.

Поддерживаемые HTML-теги

Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>.

Пример

<p ondblclick='this.innerHTML=" Спасибо! Я был дважды нажат!";'> 
  Дважды щелкните меня. 
</p>

Дважды щелкните меня.

mousedown

Событие mousedown происходит, когда кнопка мыши нажата над некоторым элементом, но ещё не отпущена.

Поддерживаемые HTML-теги

Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>.

Пример

<p id="myP" onmousedown="mouseDown()" onmouseup="mouseUp()">
Нажмите на этот текст! Функция mouseDown () запускается, 
когда кнопка мыши нажата над этим абзацем и устанавливает цвет текста в красный. 
Функция mouseUp () запускается при отпускании кнопки мыши и устанавливает цвет текста в зеленый.</p>

<script>
function mouseDown() { document.getElementById("myP").style.color = "red"; }

function mouseUp() { document.getElementById("myP").style.color = "green"; }
</script>

mouseup

Событие mouseup происходит, когда кнопка мыши над некоторым элементом перешла из состояния нажатия, в состояние отпущена.

Поддерживаемые HTML-теги

Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>.

Пример

<div id="demo" style="width:500px; height:200px">Нажмите здесь.</div>

<script>
var d = document.getElementById("demo");

d.onmousedown = function() {mouseDown()};
d.onmouseup = function() {mouseUp()};

function mouseDown() {d.innerHTML = "Кнопка мыши удерживается нажатой.";}

function mouseUp() { d.innerHTML = "Вы отпустили кнопку мыши."; }
</script>

mouseover

Событие mouseover происходит, когда курсор мыши входит в область, принадлежащей элементу или одному из его детей.

Поддерживаемые HTML-теги

Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>.

Пример

<p onmouseover="document.body.style.backgroundColor='red'" 
   onmouseout="document.body.style.backgroundColor=''"> Попробуй </p>

Попробуй

mouseout

Событие mouseout происходит, когда курсор мыши уходит из области, принадлежащей элементу или одному из его детей.

Поддерживаемые HTML-теги

Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>.

Пример

<p>Функция bigImg () запускается, когда пользователь перемещает указатель мыши на изображение.</p>
<p>Функция normalImg () запускается, когда указатель мыши покидает изображение.</p>
<img onmouseover="bigImg(this)" onmouseout="normalImg(this)" 
        src="images/yozhik.jpg" alt="Ёжик" width="48" height="48" />
<script>
function bigImg(x) 
  { x.style.height = "96px"; x.style.width = "96px"; }

function normalImg(x) 
  { x.style.height = "48px"; x.style.width = "48px"; }
</script>

mousemove

Событие mousemove происходит, когда курсор мыши перемещается внутри области, принадлежащей элементу.

Поддерживаемые HTML-теги

Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>.

Пример

<div onmousemove="myFunction(event)"
     style="width:400px; height: 150px; border:1px solid black"></div>

<p>Наведите указатель мыши на прямоугольник  и получите координаты указателя мыши.</p>

<p id="demo"></p>

<script>
function myFunction(event) 
  { var x = event.clientX, y = event.clientY;
    var coor = "Координаты: (" + x + "," + y + ")";
    document.getElementById("demo").innerHTML = coor;
  }
</script>

События mouseenter и mouseleave

События mouseenter/mouseleave похожи на mouseover/mouseout. Они тоже срабатывают, когда курсор заходит на элемент и уходит с него, но с двумя отличиями.

  • Не учитываются переходы внутри элемента.
  • События mouseenter/mouseleave не всплывают.
  • Эти события более интуитивно понятны.

    Курсор заходит на элемент – срабатывает mouseenter, а затем – неважно, куда он внутри него переходит, mouseleave будет, когда курсор окажется за пределами элемента.

    Вы можете увидеть, как они работают проведя курсором над голубым DIV'ом ниже. Обработчик стоит только на внешнем, синем элементе. Обратите внимание – лишних событий при переходе на красного потомка нет!

    Для mouseover/mouseout при переходе на потомка срабатывает mouseout на родителе.

    <style>
    .blue, p span { display: inline-block; width: 180px; margin-right: 80px; }
    .blue { background: blue; height: 180px; }
    
    .red { background: red; width: 120px; height: 120px; margin: 30px; }
    
    textarea { height: 150px; width: 480px; display: block; }
    textarea i.blue {color: blue}
    textarea i.red {color: red}
    </style>
    <p><span>mouseenter и mouseleave</span><span>mouseover и mouseout</span></p>
    <div class="blue" onmouseenter="log(event)" onmouseleave="log(event)">
        <div class="red"></div>
    </div>
    <div class="blue" onmouseover="log(event)" onmouseout="log(event)">
        <div class="red"></div>
    </div>
    
    <textarea id="text"></textarea>
    <input type="button" onclick="text.value=''" value="Очистить">
    <script>
    function log(event) 
      { text.value += event.type + ' [target: ' + event.target.className+ ']\n';
        text.scrollTop = text.scrollHeight; }
    </script>
    

    Поддерживаемые HTML-теги

    Все HTML-элементы, кроме: <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>.

    Совместимость с браузерами

    30,05,5Да6,111,5

    Колёсико «мыши»: "wheel"

    Источник: learn.javascript.ru/mousewheel

    Отличия колёсика от прокрутки

    Несмотря на то, что колёсико мыши обычно ассоциируется с прокруткой, это совсем разные вещи.

    Кроме того, событие onscroll происходит после прокрутки, а onwheel — до прокрутки, поэтому в нём можно отменить саму прокрутку (действие браузера).

    Зоопарк wheel в разных браузерах

    Самые важные свойства современного события и его нестандартных аналогов:

    wheel
    Свойство deltaY — количество прокрученных пикселей по горизонтали и вертикали. Существуют также свойства deltaX и deltaZ для других направлений прокрутки.
    MozMousePixelScroll
    Срабатывает, начиная с Firefox 3.5, только в Firefox. Даёт возможность отменить прокрутку и получить размер в пикселях через свойство detail, ось прокрутки в свойстве axis.
    DOMMouseScroll
    Существует в Firefox очень давно, отличается от предыдущего тем, что даёт в detail количество строк. Если не нужна поддержка Firefox < 3.5, то не нужно и это событие.
    mousewheel
    Срабатывает в браузерах, которые ещё не реализовали wheel. В свойстве wheelDelta — условный «размер прокрутки», обычно равен 120 для прокрутки вверх и -120 — вниз. Он не соответствует какому-либо конкретному количеству пикселей.

    Чтобы кросс-браузерно отловить прокрутку и, при необходимости, отменить её, можно использовать все эти события.

    Пример, включающий поддержку IE8-:

    <style>
    #container { width: 200px; height: 200px;
          border: 1px solid black; background: #0FF; overflow: auto; }
    </style>
    <p>Прокрутка: <span id="delta">0</span></p>
    <div id="container">  Прокрути надо мной.  </div>
    <script>
    var elem = document.getElementById('container');
    if (elem.addEventListener) 
     { if ('onwheel' in document) 
        { elem.addEventListener("wheel", onWheel); } // IE9+, FF17+
       else if ('onmousewheel' in document) 
        { elem.addEventListener("mousewheel", onWheel); } // устаревший вариант события
       else { elem.addEventListener("MozMousePixelScroll", onWheel); } // Firefox < 17
      } 
    else { elem.attachEvent("onmousewheel", onWheel); }// IE8-
    
    // Это решение предусматривает поддержку IE8-
    function onWheel(event) {
      event = event || window.event;
     //   deltaY, detail содержат пиксели
     //   wheelDelta не дает возможность узнать количество пикселей
     //   onwheel || MozMousePixelScroll || onmousewheel
      var delta = event.deltaY || event.detail || event.wheelDelta;
    
      var info = document.getElementById('delta');
    
      info.innerHTML = +info.innerHTML + delta;
    
      event.preventDefault ? event.preventDefault() : (event.returnValue = false);
     }
    </script>
    

    Модификаторы shift, alt, ctrl и meta

    Во всех событиях мыши присутствует информация о нажатых клавишах-модификаторах.

    Синтаксис

    event.altKey
    event.ctrlKey
    event.metaKey   // для Mac
    event.shiftKey
    

    Возвращаемое значение

    Свойство возвращает true, если нажата соответствующая клавиша, и false - в противном случае

    Комментарии

    Чтобы пользователи операционных систем работали с комфортом, в паре с ctrlKey нужно обязательно использовать metaKey.

    В JS-коде это означает, что для удобства пользователей Mac нужно проверять
    if (event.ctrlKey || event.metaKey)
    

    Пример

    <button id="ekey"> Alt+Shift+Кликни меня! </button>
    
    <script>
      document.getElementById('ekey').onclick = function(event) {
        if (!event.altKey || !event.shiftKey) return;
        alert( 'Молодец!' );
      }
    </script>
    

    button

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

    Синтаксис

    event.button
    

    Возвращаемое значение

    Число, представляющее какая кнопка мыши была нажата, когда произошло событие event.

    Возможные значения: Для IE8-:

    which

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

    Синтаксис

    event.which
    

    Возвращаемое значение

    Число, представляющее какая кнопка мыши была нажата, когда произошло событие event.

    Возможные значения:

    Комментарии

    Это свойство не поддерживается IE8-, но можно легко сделать функцию, которая будет ставить свойство which из button, если его нет:

    function fixWhich(event) {
     if (!event.which && event.button) {           // если which нет, но есть button... (IE8-)
       if (event.button & 1) event.which = 1;      // левая кнопка
       else if (event.button & 4) event.which = 2; // средняя кнопка
       else if (event.button & 2) event.which = 3; // правая кнопка
     } }
    

    detail

    Свойство detail возвращает число, указывающее, сколько раз была нажата мышь в течение короткого промежутка времени.

    Синтаксис

    event.detail
    

    Возвращаемое значение

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

    Примечание: Возвращаемое значение для события ondblclick всегда "2", а для OnMouseOver или onmouseout - всегда "0"

    Совместимость с браузерами

    Да9,0ДаДаДа

    Пример

    <button onclick="f(event)">Нажми здесь несколько раз в течение короткого промежутка времени:</button>
    
    <input id="i" type="text" readonly>
    
    <script>
    function f(event) { document.getElementById("i").value =  event.detail; }
    </script>
    

    Координаты в окне: clientX/Y

    Пара свойств clientX/clientY содержит координаты курсора относительно текущего окна (относительно левого верхнего угла клиентской области).

    Синтаксис

    event.clientX
    
    event.clientY
    

    Возвращаемое значение

    Свойство clientX возвращает горизонтальную координату указателя мыши относительно текущего окна.

    Свойство clientY возвращает вертикальную координату указателя мыши относительно текущего окна.

    Пример

    Проведите мышью над полем ввода, чтобы увидеть clientX/clientY:

    <input onmousemove="this.value = event.clientX+':'+event.clientY">
    

    Координаты относительно документа: pageX/Y

    Пара свойств pageX/pageY содержит координаты курсора относительно относительно документа. Так как эти координаты – относительно левого-верхнего узла документа, а не окна, то они учитывают прокрутку.

    Синтаксис

    event.pageX
    
    event.pageY
    

    Возвращаемое значение

    Свойство clientX возвращает горизонтальную координату указателя мыши относительно документа.

    Свойство clientY возвращает вертикальную координату указателя мыши относительно документа.

    Комментарии

    В IE8- этих свойств нет, но можно получить их следующим способом:
    function fixPageXY(event) {
      if (event.pageX == null && event.clientX != null) { // если нет pageX..
        var html = document.documentElement;
        var body = document.body;
    
        event.pageX = event.clientX + (html.scrollLeft || body && body.scrollLeft || 0);
        event.pageX -= html.clientLeft || 0;
    
        event.pageY = event.clientY + (html.scrollTop || body && body.scrollTop || 0);
        event.pageY -= html.clientTop || 0;
      }
    }
    

    Пример

    Проведите мышью над полем ввода, чтобы увидеть pageX/pageY (кроме IE8-):

    <input onmousemove="this.value = event.pageX+':'+event.pageY">
    

    Координаты относительно экрана: screenX/Y

    Пара свойств screenX/screenY содержит координаты курсора относительно экрана.

    Синтаксис

    event.screenX
    
    event.screenY
    

    Возвращаемое значение

    Свойство screenX возвращает горизонтальную координату указателя мыши относительно экрана.

    Свойство screenY возвращает вертикальную координату указателя мыши относительно экрана.

    Пример

    Проведите мышью над полем ввода, чтобы увидеть screenX/screenY:

    <textarea onmousemove="this.value = 'screen: '+event.screenX+':'+event.screenY + 
                             '\nclient:   '+event.clientX+':'+event.clientY">
    </textarea>
    

    relatedTarget

    Свойство relatedTarget возвращает ссылку на элемент, который связан с элементом, сгенерировавшим события мыши

    Синтаксис

    event.relatedTarget
    

    Возвращаемое значение

    Ссылка на соответствующий элемент.

    Описание

    Свойство объекта события relatedTarget позволяет узнать, с какого элемента пришла (или на какой ушла) мышь.

    Например, в обработчике события mouseover/mouseenter:
    Для mouseout/mouseleave всё наоборот:

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

    В IE8- нет свойства relatedTarget. Вместо него используется fromElement для mouseover и toElement для mouseout.
    Можно «исправить» несовместимость с relatedTarget так:

    function fixRelatedTarget(event) {
      if (event.relatedTarget === undefined) {
        if (event.type == 'mouseover') event.relatedTarget = event.fromElement;
        if (event.type == 'mouseout') event.relatedTarget = event.toElement;
      }
    }
    

    Пример

    <style>
    [class^="e-"] { display: inline-block;
       width: 70px;  height: 70px;
       border-radius: 50%; margin-right: 10px; }
    
    .e-green { background: #a9db7a; border: 5px solid #92c563;}
    .e-yellow { background: #eed16a; border: 5px solid #dbae51;}
    .e-red { background: #ee9295; border: 5px solid #e27378;}
    
    #log { width: 420px; height:150px; }
    </style>
    
    <div class="e-green"> </div>
    <div class="e-yellow"> </div>
    <div class="e-red"> </div>
    
    <textarea id="log"> Здесь будут события и relatedTarget </textarea>
    <script>
    var log = document.getElementById('log');
    document.body.onmouseover = document.body.onmouseout = handler;
    
    function handler(event) {
    
      function str(el) {
        if (!el) return "null"
        return el.className || el.tagName;
      }
    
      log.value += event.type + ': ' +
        'target=' + str(event.target) +
        ', relatedTarget=' + str(event.relatedTarget) + "\n";
      log.scrollTop = log.scrollHeight;
    
      if (event.type == 'mouseover') {
        event.target.style.background = 'pink'
      }
      if (event.type == 'mouseout') {
        event.target.style.background = ''
      }
    }
    </script>
    

    Drag & Drop

    В качестве обобщённого примера рассмотрим Drag & Drop - это возможность захватить мышью элемент и перенести его.

    В современном стандарте HTML5 есть поддержка Drag’n’Drop при помощи специальных событий.

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

    Но в плане именно Drag’n’Drop у них есть существенные ограничения. Например, нельзя организовать перенос «только по горизонтали» или «только по вертикали». Также нельзя ограничить перенос внутри заданной зоны. Есть и другие интерфейсные задачи, которые такими встроенными событиями нереализуемы.

    Поэтому здесь мы будем рассматривать Drag’n’Drop при помощи событий мыши.

    Алгоритм Drag & Drop

    1. Отслеживаем нажатие кнопки мыши на переносимом элементе при помощи события mousedown.
    2. При нажатии – подготовить элемент к перемещению. При этом не забыть отключить браузерный Drag’n’Drop, который автоматически запускается и вступает в конфликт с нашим.
      element.ondragstart = function() { return false; }
      
    3. Далее отслеживаем движение мыши через mousemove и передвигаем переносимый элемент на новые координаты путём смены left/top и position:absolute.
    4. При отпускании кнопки мыши, то есть наступлении события mouseup – остановить перенос элемента и произвести все действия, связанные с окончанием Drag’n’Drop.

    В следующем примере эти шаги реализованы для переноса мяча:

    <p>Кликните по мячу и тяните, чтобы двигать его.</p>
    <img src="images/ball.svg" style="cursor:pointer" width="40" height="40" id="ball">
    
    <script>
    var ball = document.getElementById('ball');
    
    ball.onmousedown = function(e) {
      var coords = getCoords(ball);
      var shiftX = e.pageX - coords.left;
      var shiftY = e.pageY - coords.top;
    
      ball.style.position = 'absolute';
      document.body.appendChild(ball);
      moveAt(e);
    
      ball.style.zIndex = 9999; // над другими элементами
    
      function moveAt(e) 
         { ball.style.left = e.pageX - shiftX + 'px';
           ball.style.top  = e.pageY - shiftY + 'px';
         }
    
      document.onmousemove = function(e) { moveAt(e); };
    
     ball.onmouseup = function() 
       { document.onmousemove = null; ball.onmouseup = null; };
    }
    
    ball.ondragstart = function() { return false; };
    
    function getCoords(elem) { // кроме IE8-
      var box = elem.getBoundingClientRect();
      return {
        top:  box.top  + pageYOffset,
        left: box.left + pageXOffset
       };
    }
    </script>
    

    Более подробно о Drag & Drop с большм количеством примеров можно узнать на javascript.ru