Пишем свое контекстное меню на jQuery

Сегодня я хочу поделиться опытом написания своего контекстного меню с помощью всеми нами любимой библиотеки jQuery.

Итак, немного предыстории

Что подтолкнуло меня к тому, что я заинтересовался вопросом написания своего контекстного меню и решил написать эту статью? А то, что я являюсь большим фанатом продуктов Google и мне всегда очень нравился подход этой компании к интерфейсам пользователя.

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

Я решил попробовать и вот что у меня получилось.

К делу

Естественно первое с чего нужно начать, это подключить библиотеку jQuery:

<script type="text/javascript" src="js/jquery.js"></script>

Далее нужно запретить вызов стандартного контекстного меню браузера. Для этого нужно добавить слушатель на стандартное событие документа oncontextmenu и просто предотвратить дальнейшее выполнение стандартных действий вернув false:

document.oncontextmenu = function() {return false;};

Далее необходимо сделать то, с чего обычно начинается большинство действий в jQuery, а именно повесить слушатель на событие готовности DOM:

$(document).ready(function(){
    // Все начинается тут
});

Заранее напишем немного css:

/* Класс контекстного меню: */
.context-menu {
    position: absolute; /* Задаем абсолютное позиционирование для нашего меню */
    display: none; /* Изначально не показываем его */
    background-color: #fff; /* Цвет фона меню */
    border: 1px solid #333; /* Граница */

    /* Немного красивостей. Добавляем тень для нашего меню, что бы отобразить его слегка выше остальных элементов страницы: */
    -moz-box-shadow: -5px 2px 10px rgba(0,0,0,0.5); /* Для Firefox */
    -webkit-box-shadow: -5px 2px 10px rgba(0,0,0,0.5); /* Для Safari и Chrome */
    box-shadow: -5px 2px 10px rgba(0,0,0,0.5); /* Параметры тени */
}

/* Добавляем стили для списка которые будет находиться внутри меню и, собственно, содержать его пункты: */
.context-menu ul { list-style: none; margin: 0; padding: 0; }

.context-menu ul li { margin: 0; padding: 0; background-color: #fff; display: block; }

/* Стили для ссылок пунктов меню: */
.context-menu ul li a { color: #333; text-decoration: none; font-size: 12px; display: block; padding: 5px; }

.context-menu ul li a:hover { background-color: #eee; }

Теперь все готово и мы можем начинать творить чудеса jQuery:

$(document).ready(function() {

    // Вешаем слушатель события нажатие кнопок мыши для всего документа:
    $(document).mousedown(function(event) {

        // Убираем css класс selected-html-element у абсолютно всех элементов на странице с помощью селектора "*":
        $('*').removeClass('selected-html-element');
        // Удаляем предыдущие вызванное контекстное меню:
        $('.context-menu').remove();

        // Проверяем нажата ли именно правая кнопка мыши:
        if (event.which === 3)  {

            // Получаем элемент на котором был совершен клик:
            var target = $(event.target);

            // Добавляем класс selected-html-element что бы наглядно показать на чем именно мы кликнули (исключительно для тестирования):
            target.addClass('selected-html-element');

            // Создаем меню:
            $('<div/>', {
                class: 'context-menu' // Присваиваем блоку наш css класс контекстного меню:
            })
            .css({
                left: event.pageX+'px', // Задаем позицию меню на X
                top: event.pageY+'px' // Задаем позицию меню по Y
            })
            .appendTo('body') // Присоединяем наше меню к body документа:
            .append( // Добавляем пункты меню:
                 $('<ul/>').append('<li><a href="#">Remove element</a></li>') 
                                .append('<li><a href="#">Add element</a></li>')
                                .append('<li><a href="#">Element style</a></li>') 
                                .append('<li><a href="#">Element props</a></li>')
                                .append('<li><a href="#">Open Inspector</a></li>')
                   )
             .show('fast'); // Показываем меню с небольшим стандартным эффектом jQuery. Как раз очень хорошо подходит для меню
         }
    });
});

Далее все что нужно сделать, это добавить несколько любых HTML элементов на страницу для тестирования.

Вот что получится:

контекстное меню на jQuery

Так же хотелось бы заострить внимание еще на нескольких вещах:

  • Вам вовсе не обязательно вешать события нажатия кнопки мыши именно на весь документ. При желании вы можете повесить его на кокой либо блок, с помощью класса или идентификатора, тем самым обеспечив поддержку своего меню только в определенной области
  • Очень важным фактом здесь является то, что мы имеем возможность получить тот объект, на котором был произведен клик. Таким образом в дальнейшем мы можем производить над ним любые действия (для чего и призвано контекстное меню). Например менять его свойства, удалить его или добавить в него дочерний элемент.

Спасибо всем за внимание. Надеюсь кому то пригодиться этот рецепт.