Обработка нажатия правой кнопки мыши (oncontextmenu) Сложность: средняя Сложность: средняя

Задача: отловить нажатие правой кнопки мыши в окне браузера и показать собственное контекстное меню.

Что происходит при нажатии правой кнопки мыши в окне браузера? Появится контекстное меню, внешний вид и набор функций которого будет зависеть от типа браузера и того места, куда вы кликнули.
А что, если мы захотели заблокировать браузерное контекстное меню и показать собственное? Возможно? Да. К сожалению не кроссбраузерно, но код приведенный ниже будет работать в Gecko, Safari и IE. Opera таких возможностей по умолчанию не предоставляет.

Для начала прорисуем три DIV-а, в 2-х из которых покажем собственное контекстное меню, а в третьем оставим дефолтное браузерное.
• Код HTML
<div oncontextmenu="return menu(1, event);" style="height:100px; border:1px solid red; background-color:#FFCCCC;">Кликни правой кнопкой</div>
<div oncontextmenu="return menu(2, event);" style="height:100px; border:1px solid blue; background-color:#CCCCFF;">Кликни правой кнопкой</div>
<div style="height:100px; border:1px solid green; background-color:#CCFFCC;">Кликни правой кнопкой</div>

<!-- Контер для собственного контекстного меню. По умолчания - скрыт. -->
<div id="contextMenuId" style="position:absolute; top:0; left:0; border:1px solid #666; background-color:#CCC; display:none; float:left;"></div>

Как видите, отлов нажатия правой кнопки происходит с помощью события oncontextmenu. Для написания кода функции menu необходимы следующие составляющие:
Функция для добавления обработчиков событий. Используется для скрытия собственного контекстного меню при кликах в других частях документа.
Функция для определения координат указателя мыши. Используется для определения положения, в котором мы покажем контекстное меню.
Блокировать всплывание стандартного браузерного меню можно элементарно возвращая false.

Теперь код:
• Код JavaScript
// Функция для определения координат указателя мыши
function defPosition(event) {
      var x = y = 0;
      if (document.attachEvent != null) { // Internet Explorer & Opera
            x = window.event.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
            y = window.event.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
      } else if (!document.attachEvent && document.addEventListener) { // Gecko
            x = event.clientX + window.scrollX;
            y = event.clientY + window.scrollY;
      } else {
            // Do nothing
      }
      return {x:x, y:y};
}

function menu(type, evt) {
      // Блокируем всплывание события contextmenu
      evt = evt || window.event;
      evt.cancelBubble = true;
      // Показываем собственное контекстное меню
      var menu = document.getElementById("contextMenuId");
      var html = "";
      switch (type) {
            case (1) :
                  html = "Меню для первого ДИВа";
                  html += "<br><a href=\"#\">Первая функция<\/a>";
                  html += "<br><a href=\"#\">Вторая функция<\/a>";
                  html += "<br><a href=\"#\">Третья функция<\/a>";
            break;
            case (2) :
                  html = "Меню для второго ДИВа";
                  html += "<br><i>(пусто)<\/i>";
            break;
            default :
                  // Nothing
            break;
      }
      // Если есть что показать - показываем
      if (html) {
            menu.innerHTML = html;
            menu.style.top = defPosition(evt).y + "px";
            menu.style.left = defPosition(evt).x + "px";
            menu.style.display = "";
      }
      // Блокируем всплывание стандартного браузерного меню
      return false;
}

// Закрываем контекстное при клике левой или правой кнопкой по документу
// Функция для добавления обработчиков событий
function addHandler(object, event, handler, useCapture) {
      if (object.addEventListener) {
            object.addEventListener(event, handler, useCapture ? useCapture : false);
      } else if (object.attachEvent) {
            object.attachEvent('on' + event, handler);
      } else alert("Add handler is not supported");
}
addHandler(document, "contextmenu", function() {
      document.getElementById("contextMenuId").style.display = "none";
});
addHandler(document, "click", function() {
      document.getElementById("contextMenuId").style.display = "none";
});

Пример обработки нажатия правой кнопки мыши.

Замечание:
Выражение "правая кнопка мыши" в данной статье не стоит понимать в буквальном смысле, т.к. пользователь может настроить свою мышь так, что функции правой будет выполнять левая кнопка ;-)
На работе скриптов это естественно никак не отразится.

Опубликовано: 11-2-2008
Автор: Александр Бурцев


Комментарии [ Написать комментарий ]

barbuza:
ну и нахрена учить людей использовать innerHTML?
Александр Бурцев: Re: barbuza
Смысл вашего замечания не понятен.
Anonymous: На заметку
Предыдущие сообщения получились путем обновления страницы - криво сделано значит...
Anonymous:
И да...
This page is not Valid HTML 4.01 Transitional!
:)
вот теперь все ) пошел дальше...
Sirius:
Не работает в Опере (9.5 - точно)
Александр Бурцев: Ответ предыдущим трем авторам
Re: Anonymous: На заметку
Спасибо, в новой версии сайта этого не будет

Re: Anonymous
[quote]This page is not Valid HTML 4.01 Transitional!
:)
вот теперь все ) пошел дальше...[/quote]
Ага, идите.

Re: Sirius
Такая беда во всех операх, об этом и в статье написано. Такие вот у этого браузера настройки умолчательные.
Anonymous:
Да чего вы так,
надо просто исправлять :) я ж с добрых побуждений все три коммента написал.

Вот валидатор на вашу страницу матерится из-за 2 дурацких ошибок :

This page is not Valid HTML 4.01 Transitional!

Validation Output: 2 Errors
Line 51, Column 26: document type does not allow element "STYLE" here.
<br><style type="text/css">.html_table {color:#008080;}.html_form {color:#FF8000

&#9993;

The element named above was found in a context where it is not allowed. This could mean that you have incorrectly nested elements -- such as a "style" element in the "body" section instead of inside "head" -- or two elements that overlap (which is not allowed).

One common cause for this error is the use of XHTML syntax in HTML documents. Due to HTML's rules of implicitly closed elements, this error can create cascading effects. For instance, using XHTML's "self-closing" tags for "meta" and "link" in the "head" section of a HTML document may cause the parser to infer the end of the "head" section and the beginning of the "body" section (where "link" and "meta" are not allowed; hence the reported error).
Line 63, Column 26: document type does not allow element "STYLE" here.
<br><style type="text/css">.single_comment {color: #808080; font-weight:normal;}

&#9993;

The element named above was found in a context where it is not allowed. This could mean that you have incorrectly nested elements -- such as a "style" element in the "body" section instead of inside "head" -- or two elements that overlap (which is not allowed).

One common cause for this error is the use of XHTML syntax in HTML documents. Due to HTML's rules of implicitly closed elements, this error can create cascading effects. For instance, using XHTML's "self-closing" tags for "meta" and "link" in the "head" section of a HTML document may cause the parser to infer the end of the "head" section and the beginning of the "body" section (where "link" and "meta" are not allowed; hence the reported error).
Александр Бурцев: Re: Anonymous
Знаю, тут такая штука, что подсветка для кода формируется в виде css-вставок в зависимости от языка подсветки. В новой версии сайта подсветка будет geshi и бага пофиксится сама собой.

Метки

AJAX Canvas & VML JS::Unsorted JS::Разработка JSправочник Дата и время Координаты, размеры, ресайз, скролл Обработка изображений Работа с DOM События (event) Строковые данные (String) Формы (<form>)

Полезные ссылки

DOM onReady на habr DomContentLoaded fixing Google Map API JavaScript 1.5 на Mozilla.org (eng) JavaScript и не только на suncloud (рус) Измерение размеров и полей элементов в ИЕ Нововведения в JavaScript 1.6 (eng) Правильный WYSIWYG (рус) Редактор jEdit Рисуем JavaScript-ом

Новый портал для web-программистов!

Рад вам сообщить, что открылся новый информационный проект о web-технологиях - webew.ru. Здесь вы найдете актуальные статьи по XML, HTML, PHP, MySQL, Javascript, SEO и др. Заходите, регистрируйтесь и оставляйте свои посты и комментарии!

Комментарии!

У вас появилась возможность добавлять комментарии. В конце каждой статьи найдется ссылка "Написать комментарий", открывающая форму. Новая возможность не требует авторизации. Просьба не злоупотреблять тем, что двери открыты ;)

Пишите...

Если вы увидели на fastcoder.org ошибку или неточность, захотели написать и разместить здесь свою статью или просто решили поблагодарить авторов за понравившийся скрипт - заходите сюда и отправляйте сообщения.