Как добавить кнопку в браузере
Данная статья является продолжением статьи Рисуем кнопку в SVG, в которой рассматривались проблемы создания SVG-изображений, предназначенных для использования в качестве кнопок на веб-страницах. Здесь я перейду непосредственно к внедрению полученных картинок в HTML-код и расскажу, с какими проблемами столкнётся при этом разработчик, как эти проблемы можно решать и что делать с проблемами, которые решить не удаётся.
На всякий случай (для тех, кто не читал первую статью) повторю, что многие из проблем решить так и не удалось, и что это в конце концов вынудило меня отказаться от идеи использования SVG. Так если вам не хочется тратить время на чтение статьи, не приводящей к реально использующемуся результату, вы вполне можете её пропустить. Тех же, кому несмотря на это интересны детали и конкретика, прошу под кат.
Вставка кнопки на страницу
- тег ;
- тег ;
- тег ;
- тег ;
- CSS-стиль background.
- Теги , , поддерживаются всеми из протестированных браузеров.
- Тег отказался работать в FF, а в Хроме и Опере работает исключительно в режиме картинки: внедрённые скрипты и события не обрабатываются.
- CSS-стиль background же оказался самым разносторонним:
- в Firefox он не поддерживается совсем;
- в Хроме отображается корректно, но, как и в , не поддерживается обработка событий и скриптов, а вдобавок к этому ещё и анимация не работает;
- в Опере он то работает, то нет; похоже, что стиль не срабатывает, если в коде страницы присутствует ещё и тег с той же SVG-картинкой, причём этот тег должен располагается до элемента с картинкой-фоном. Во всех остальных случаях фон отрабатывает корректно, но, как и в Хроме, выводится статической картинкой, без обработки событий, скриптов и анимаций. (Кстати, спасибо хабралюдям Xpeh и tenshi за их уточнения по поводу этой функциональности в комментариях к предыдущей статье.)
Код вставки объекта выглядит примерно следующим образом:
Внутри тега можно вписать любой HTML-код: он будет использоваться на браузерах, не поддерживающих SVG. Что ж, это нам пригодится, так как рано или поздно всё равно пришлось бы вспомнить про IE (да и другие браузеры без SVG могут встретиться). Для них мы сможем добавить внутрь тега обычный .
Модификация текстовой надписи
Итак, мы вставили нашу кнопку. Собираемся добавить вторую… и тут же понимаем, что для этого нам придётся делать новый SVG-файл, так как надпись хранится внутри SVG-кода. Но количество файлов-картинок хотелось бы минимизировать, ведь в частности именно для этого и задумывалось использование вектора! Как быть? Здесь возможны несколько путей.
1. Наложить надпись поверх кнопки средствами HTML.
Сразу скажу, что я этот способ детально не исследовал, но нутром чую, что проблем он принесёт немало. Типичное решение подобных задач состоит в расположении текста после кнопки и сдвиге его влево с помощью CSS. Но не уверен, что таким способом удастся добиться корректного центрирования текста по кнопке. Значит — JS с подстройкой позиционирования, значит — постоянное слежение за положением объектов на странице (например, при изменении размеров окна или динамическом показе/скрытии блоков)… А ещё стоит учитывать, что дизайн кнопки может подразумевать сдвиг этого текста вниз-вправо при обработке нажатия (для эффекта трёхмерности)… В общем, при одной только мысли обо всём этом мне стало не по себе, поэтому я стал искать другие способы.2. Вставка текста в SVG.
Этот вариант предполагает, что у нас в коде страницы есть скрипт, который пробегает по всем SVG-кнопкам и вставляет в них нужный текст (например, вызывая заранее составленную для этого функцию в самом SVG). Это уже лучше, но неприятным моментом остаётся то, что код кнопки и текст этой кнопки оказываются сильно разнесёнными. Можно, конечно, вписывать после каждого тега ещё и короткую скриптовую строчку с добавлением текста кнопки в какой-нибудь массив, но всё равно это как-то длинновато. Есть третий способ, на мой взгляд, более красивый.3. Вытаскивание текста из тега.
У тега есть атрибут standby, который содержит текст, выводимый браузерами вместо содержимого объекта, пока этот объект грузится. Оказалось, что SVG-кнопка вполне может получить значение этого атрибута и использовать его для модификации надписи своими силами. И получается, что одним махом мы убиваем двух зайцев: с одной стороны, у нас есть подстраховка на случай каких-то залипаний загрузки — пользователь увидит не пустое место, а осмысленный текст (мне, правда, так и не удалось спровоцировать такое поведение); с другой стороны, текстовая метка теперь реализована так же удобно и наглядно, как классический value в теге .Обработка нажатий
Следующая проблема заключается в том, что у нас не получится навесить обработчик мышиного щелчка на тег : щелчок пересылается в SVG-объект и обрабатывается там. Естественно, мы могли бы загнать обработку события внутрь кнопки, но это неразумно: ведь кнопок много, а SVG-файл один. Вместо этого лучше делегировать обработку скриптам из родительской страницы. Здесь, опять-таки, варианты реализации могут разниться, я остановился на следующем: в библиотечном JS-файле определил функцию doClickAction, которая вызывает обработчик конкретной кнопки, а из «кнопочного» скрипта вызываю эту функцию, передавая ей идентификатор кнопки. Примерный код выглядит следующим образом.
Код HTML-страницы:
Код SVG-кнопки:
В этом коде я вставил дополнительные теги для отображения кнопок в не-SVG-браузерах, а в качестве обработчика нажатия назначил для них вызов той же самой doClickAction, передав ей идентификатор родительского object'а (т.е., то же самое, что передаст обработчик из SVG). Учитывая такую однородность, можно было бы попробовать автоматизировать вставку этих кнопок скриптом, но доступ к содержимому объектов в IE попросту блокируется. Впрочем, если делать скриптовый проход, то уж проще сразу заменить все объекты кнопками, не заморачиваясь с вложенностью.Также здесь необходимо учитывать один неочевидный аспект: реально скрипт хоть и вызывает функцию родительской страницы, текущим адресом будет считаться адрес SVG-файла. Как следствие, все относительные адреса будут отсчитываться от каталога, где лежит файл кнопки, а не от реального текущего адреса страницы. Этот момент придётся учитывать, например, при открытии новых окон через window.open(). Решением может быть использование абсолютной адресации либо предварительное сохранение текущего адреса в переменной с последующим использованием её для вычисления нового адреса.
Размер шрифта
Всё это время я аккуратно обходил стороной вопрос размера шрифта для текстовой надписи на кнопке. Но теперь пришла пора заняться этой задачей. Что хотелось бы получить? В идеале — такой же шрифт, как на основной странице. К сожалению, здесь нормального решения найти не удалось. Видимо, правильнее будет в каждом конкретном случае оценивать, в каких пределах могут меняться стили кнопочной надписи, и в зависимости от этого выбирать наименее трудоёмкий путь реализации. Например, в моём проекте шрифт везде одинаковый. Соответственно, свойство font-family я прописал прямо в SVG, а размер высчитываю в инициализационной функции, масштабируя текст по реальной высоте кнопки (которую получаю, обращаясь к элементу родительской страницы). В более сложных случаях может потребоваться менять цвет надписи, толщину или сам вид шрифта. Для таких ситуаций можно воспользоваться, например, навешиванием стиля на тег с последующим вытаскиванием его внутри SVG-функции init(), разбором и присваиванием полученных стилей текстовому элементу. Также вариантом может быть глобальный обработчик в HTML-коде, который после загрузки страницы пробегает по всем кнопкам, вызывая для каждой из них какую-нибудь «подстроечную функцию». Повторюсь, здесь всё слишком индивидуально, чтобы можно было давать какие-то универсальные рекомендации.
К сожалению, даже в таком простом решении, как мой первый вариант, нашлись свои заморочки. А именно: если кнопка изначально скрыта, то Firefox в качестве её размеров возвращает ноль, и размер шрифта вычислить не удаётся. Корректного решения этой проблемы я пока придумать не смог, все варианты выглядят слишком некрасиво и/или неэффективно. Отловить событие показа кнопки не получилось, т.к. его попросту не существует. Делать явный довесок в виде переинициализации кнопки при показе ранее скрытого блока — можно, но таких мест может быть много, и об этом легко забыть. Также можно попробовать каким-то образом вычислить текущие параметры шрифта на странице и использовать в кнопке полученный размер.
Прочие проблемы
- Opera: Не работает текстовый стиль dominant-baseline для изменения положения базы шрифта. В результате становится невозможным выровнять текст по вертикали, приходится подгадывать положение, а то и подстраивать его динамически в зависимости от размеров кнопки и шрифта, чтобы текстовая метка выглядела пристойно.
- Chrome: При использовании масштабирования страницы SVG-элементы масштабируются, а вот размеры областей, выделенных под них — нет. В результате кнопки вылезают за пределы областей и обрезаются, да ещё и полосы прокрутки появляются, закрывая собой бо́льшую часть изображения. Главное преимущество SVG — масштабируемость — оказывается попросту выброшенным на помойку!
- Opera: Активно глючит при переиспользовании изображений из кэша. В частности, если перейти по ссылке, а потом нажать в Опере кнопку Back для возврата на предыдущую страницу, все SVG-изображения не отображаются, а «зависают» во внутреннем SVG-скрипте инициализации. Также иногда наблюдаются проблемы при динамическом создании SVG-кнопки через createElement: если используется изображение, присутствующее на странице, оно подвешивает загрузку страницы и не отображается, пока не нажмёшь Esc (да и после этого периодически наблюдаются разного рода неприятные эффекты).
- Общая проблема: Размер шрифта в вышеописанном решении оказывается фиксированным и не меняется при масштабировании страницы, размеры кнопки и надписи перестают соответствовать друг другу. Соответственно, после изменения масштаба страницу необходимо перезагрузить, чтобы кнопки переинициализировались правильным размером шрифта. Не исключаю, что это я недоразобрался с единицами измерения, но решить эту проблему у меня не получилось. Возможно, подстройку удастся реализовать каким-нибудь глобальным JavaScript-обработчиком, каким-то образом следящим за масштабом и вызывающим принудительное обновление кнопок.
- Firefox: В режиме масштабирования «Только текст» с размером шрифта происходит что-то жуткое. Я сходу не смог понять, по каким правилам выдаются размеры элементов в этом режиме, а задерживаться на этой проблеме уже не видел смысла.
- IE: Как было сказано, SVG в нём не поддерживается, и вместо картинок отображаются обычные кнопки, которые я поместил внутрь тегов . Проблема в том, что до IE очень туго доходит, что он не умеет работать с SVG. Поэтому, встретив кнопку, он выводит пустой блок, задумывается на некоторое время, потом рисует вместо блока кнопку. Потом то же самое со второй кнопкой, с третьей… В общем, отрисовка шести кнопок занимает в нём секунды полторы–две.
Итоги
Что остаётся в сухом остатке? «Ну не шмогла я, не шмогла!» Я для себя сделал вывод, что нынешняя инфраструктура пока не готова к масштабному внедрению SVG (прошу прощения за невольный каламбур). Бодаться со всеми вышеперечисленными (и, вполне возможно, не только с ними) проблемами, ошибками, недоделками — всё это занимает слишком много времени и усилий, при том, что ограничения текущих реализаций не позволяют даже воспользоваться в полной мере теми преимуществами, которые должно было бы принести использование SVG.
Ну что ж, отрицательный результат — тоже результат. Возможно, когда-то в будущем, когда поддержка SVG улучшится, этот опыт пригодится мне для окончательного перехода на масштабируемую графику. А пока отложу её на полочку до лучших времён.
Надеюсь, статья была полезной. Кому-то она поможет сэкономить время и нервы, вовремя отговорив от использования недостаточно проработанных решений. А кого-то, быть может, наоборот, сподвигнет на дальнейшие героические усилия по преодолению отчаянного сопротивления браузеров.
Засим откланиваюсь и благодарю за внимание.
UPD: Добавил в список проблему замедленной отрисовки в IE.
UPD2: В одном месте перепутал браузер, исправлено.Расширение позволяет поместить одну кнопку на панель браузера Opera, справа от поля поиска. Кнопка может включать иконку размером 18х18 пикселей, подсказку (показывается при наведении), бэдж статуса и всплывающее окно.
Создание кнопок
Код создания кнопки должен быть добавлен в элемент script файла index.html. В этом примере мы выполняем код в момент срабатывания события load.
Первый шаг, это определение свойств кнопки. Сделать это можно с помощью объекта ToolbarUIItemProperties. Например:
После того, как вы задали свойства кнопки в ToolbarUIItemProperties, вам необходимо создать собственно кнопку с помощью метода createItem:
Всего, с помощью объекта ToolbarUIItemProperties вы можете определить 5 свойств:disabled
Определяет, активна ли кнопка. Значение по умолчанию — true (неактивна), принимает булево значение. Вы можете сделать кнопку неактивной следующим образом:
title
Свойство title устанавливает подсказку, которая показывает при наведении пользователем курсора на кнопку.
Свойство icon устанавливает иконку, которая используется кнопкой. Если вы укажете картинку размером отличную от 18х18 пикселей, то она будет автоматически отмасштабирована.
onclick
Эта функция вызывается, когда пользователь кликает по кнопке и возбуждается событие click.
onremove
Эта функция вызывается, когда кнопка удаляется из ToolbarContext и возбуждается событие remove.
Добавление кнопки на панель браузера
После создания кнопки нам необходимо поместить её на панель Opera. Сделаем это с помощью метода addItem:
Пробуйте запустить пример. Он не делает ничего особенного, так как вы ещё не определили никаких действий для кнопки.Удаление кнопки с панели браузера
Кнопка может быть удалена с панели браузера методом removeItem:
Создание всплывающего окна
Теперь у вас есть кнопка, вы хотите, чтобы она что-нибудь умела. При клике на кнопку может быть показано всплывающее окно. Всплывающее окно это окно с указанными шириной и высотой. Вы можете подгружать в него страницы, находящиеся в сети или поставляющиеся с вашим расширением.
Чтобы создать всплывающее окно, вам нужно определить свойства объекта Popup с помощью объекта ToolbarUIItemProperties:
Содержимое всплывающего окна
Для указания содержимого всплывающего окна используется свойство href. Вы можете указать на любую страницу в сети, используя её абсолютный URL:
Так же вы можете подгрузить страницу, поставляющуюся с расширением, указав её относительный адрес:
Эта страница может быть обычной HTML-страницей, никаких изменений вносить не нужно. Обратите внимание: если вы измените свойство href, в момент когда всплывающее окно открыто, то оно закроется.Размеры всплывающего окна
Размеры всплывающего окна указываются в пикселях с помощью свойств width и height:
width
height
Всплывающее окно будет создано одновременно с кнопкой в момент вызова метода createItem.
Попробуйте пример кнопки со всплывающим окном. Если вы пробовали пример из статьи «Ваше первое расширение для Opera», то он покажется вам очень знакомым.
Создание бэджа
Бэдж имеет 4 свойства, которые могут быть настроены:display
Свойство display показывает и скрывает бэдж. Корректными значениями являются block и none. Значение по умолчанию — none. Сделать бэдж видимым можно так:
textContent
Текст бэджа может быть выставлен через свойство textContent. Бэдж имеет ограниченное место для отображения текста, поэтому постарайтесь быть лаконичными.
color и backgroundColor
Свойства color и backgroundColor устанавливают цвет текста и цвета фона бэджа. Они принимают значения в формате hexadecimal, RGBA и наименования цвета.
Вы можете попробовать пример кнопки с бэджем и изучить различные пути создания и управления элементами пользовательского интерфейса расширений для Opera.Вы можете обратиться к API расширений для Opera, чтобы получить полную информацию о различных объектах и методах.
Если верить Википедии, контекстное меню — меню, появляющееся при взаимодействии пользователя с графическим интерфейсом (при нажатии правой кнопки мыши). Контекстное меню содержит ограниченный набор возможных действий, который обычно связаны с выбранным объектом.
На вашем компьютере клик правой кнопкой мыши на рабочем столе вызовет контекстное меню операционной системы. Отсюда вы, вероятно, можете создать новую папку, получить какую-то информацию и сделать что-нибудь еще. Контекстное меню в браузере позволяет, например, получить информацию о странице, посмотреть ее исходники, сохранить изображение, открыть ссылку в новой вкладке, поработать с буфером обмена и всякое такое. Причем набор доступных действий зависит от того, куда именно вы кликнули, то есть от контекста. Это стандартное поведение, закладываемое разработчиками браузера [И расширений к нему].
Веб-приложения постепенно начинают заменять стандартные контекстные меню своими собственными. Отличными примерами являются все те же Gmail и Dropbox. Вопрос лишь в том, как сделать свое контекстное меню? В браузере при клике правой кнопкой мыши срабатывает событие contextmenu. Нам придется отменить поведение по умолчанию и сделать так, чтобы вместо стандартного меню выводилось наше собственное. Это не так уж сложно, но разбираться будем пошагово, так что выйдет довольно объемно. Для начала создадим базовую структуру приложения, чтоб разрабатываемый пример не был совсем уж оторван от реальности.
Список задач
Пример результата есть на CodePen. Можете заглянуть туда сразу, если лень читать или хотите убедиться, что действительно заинтересованы в дальнейшем чтении. Ну а пока приступим к пошаговой разработке задуманного. Я буду использовать некоторые современные фишки CSS и создам простейший список задач на data-атрибутах. Также воспользуюсь сбросом стилей от Эрика Мейера и сброшу свойство box-sizing для всех элементов в border-box:
Я не буду использовать префиксы в CSS, но в демо на CodePen включен автопрефиксер.
Создание базовой структуры
Откроем наш HTML-документ, накидаем шапку, контентную часть с некоторым списком задач и подвал. Я также подтяну Font Awesome и шрифт Roboto, чтобы сделать оформление немного лучше. Каждая задача должна содержать атрибут data-id, который в реальности брался бы из БД. Также каждая задача будет содержать список действий. Вот важные части разметки:
Если вы используете CodePen, можете в настройках включить автопрефиксер и подключение CSS-сброса. В противном случае придется делать все руками, если еще не автоматизировали этот процесс. Не забывайте, что наша цель — создание контекстного меню, так что обработка действий не будет реализована. А теперь давайте добавим еще немного CSS:
Полный набор стилей (да и всего остального) представлен на CodePen. А здесь будут самые важные части кода, разметки и оформления. Но давайте уже наконец приблизимся к нашему контекстному меню.
Набросаем наше контекстное меню — разметка
- Просмотр задачи.
- Редактирование задачи.
- Удаление задачи.
- Мы хотим, чтобы контекстное меню появлялось там, где был выполнен правый клик, то есть ему нужно абсолютное позиционирование. Поэтому не стоит его разметку помещать в контейнер с относительным позиционированием.
- Нам потребуются какие-нибудь переменные или атрибуты, чтобы можно было определить, к какой задаче относится выбранное действие.
Приводим наше меню в порядок — CSS
Уже была упомянута необходимость абсолютного позиционирования разрабатываемого меню. Кроме того, установим свойство z-index в 10. Не забывайте, что в вашем приложении может потребоваться другое значение. Это не все возможные стили, в демке наведены прочие красивости, но они уже зависят от ваших потребностей и не являются обязательными. Прежде чем переходить к JS, сделаем меню невидимым по умолчанию и добавим дополнительный класс для его отображения.
Разворачиваем наше контекстное меню — JavaScript
Начнем с того, что посмотрим, как зарегистрировать событие contextmenu. Откроем самовыполняющуюся функцию и отловим событие на всем документе. Также будем логировать событие в консоль, чтобы получить какую-то информацию:
- Потребуется цикл по всем элементам списка задач и добавление обработчика события contextmenu к каждому из них.
- Для каждого обработчика отменим стандартное поведение.
- Будем логировать в консоли событие и элемент, к которому оно относится.
Если заглянуть в консоль, можно увидеть, что уникальное событие срабатывает при каждом нажатии на элемент из списка задач. Теперь помимо отмены поведения по умолчанию реализуем отображение контекстного меню, добавляя к нему вспомогательный класс.
Но для начала давайте добавим к меню ID, чтобы его проще было получать посредством JS. Также добавим переменную состояния меню menuState и и переменную с активным классом. Получились три переменных:
Едем дальше. Пересмотрим функцию contextMenuListener и добавим toggleMenuOn, отображающую меню:
На данный момент правой кнопкой мыши уже можно вызвать наше контекстное меню. Но нельзя сказать, что оно работает правильно. Во-первых, оно находится совсем не там, где хотелось бы. Для устранения проблемы понадобится немного математики. Во-вторых, закрыть это меню пока невозможно. С учетом того, как работают обычные контекстные меню, хотелось бы, чтоб наша его реализация закрывалась при клике не меню и при нажатии Escape. Помимо этого при правом клике вне нашего меню оно должно закрыться, а вместо него требуется открытие меню по умолчанию. Давайте попробуем все это решить.
Рефакторинг нашего кода
- contextmenu — Проверка состояния и раскрытие контекстного меню.
- click — Скрытие меню.
- keyup — Обработка нажатий клавиш. В данном руководстве интересна только ESC.
- Само проверяемое событие.
- Имя класса для сравнения. Если событие произошло внутри элемента, имеющего указанный класс, или родитель этого элемента имеет такой класс, то нужно вернуть этот элемент.
Вернемся и отредактируем contextListener:
Имея вспомогательную функцию, делающую за нас часть грязной работы, и отлавливая событие contextmenu на всем документе, мы можем теперь закрывать меню при клике вне его. Для этого добавим функцию toggleMenuOff и отредактируем contextListener:
Теперь нажмите правой кнопкой по элементу списка. А после — где-нибудь в другом месте документа. Вуаля! Наше меню закрылось и открылось стандартное. Затем сделаем нечто похожее самое для события click, чтобы не от одной правой кнопки оно закрывалось:
Этот кусок кода несколько отличается от предыдущего, потому что Firefox. После того, как правая кнопка мыши отжата, в Firefox срабатывает событие click, так что здесь нам приходится дополнительно убеждаться, что произошел действительно клик левой кнопкой. Теперь меню не моргает при правом клике. Давайте добавим похожий обработчик и на нажатие клавиши ESC:
Мы получили меню, которое открывается и закрывается как задумано, взаимодействующее с пользователем естественным образом. Давайте наконец отпозиционируем меню и попробуем обрабатывать события внутри него.
Позиционирование нашего контекстного меню
С учетом текущих HTML и CSS, наше меню отображается в нижней части экрана. Но нам-то хотелось бы, чтоб оно появлялось там, где произошел клик. Давайте исправим сие досадное упущение. Во-первых, добавим еще одну вспомогательную функцию, получающую точные координаты клика. Назовем ее getPosition и попробуем заставить обрабатывать разные причуды браузеров:
Наш первый шаг в позиционировании меню — подготовка трех переменных. Добавим их в соответствующий блок кода:
Создадим функцию positionMenu, принимающую единственный аргумент — событие. Пока что пусть она выводит координаты меню в консоль:
Отредактируем contextListener, чтобы начать процесс позиционирования:
Снова повтыкайте в контекстное меню и загляните в консоль. Убедитесь, что позиция действительно доступна и логируется. Мы можем использовать встроенные стили для задания свойств top и left посредством JS. Вот и новая версия positionMenu:
- Что будет, если пользователь кликнет близко к правому краю окна? Контекстное меню выйдет за его пределы.
- Что делать, если пользователя меняет размеры окна при открытом контекстном меню? Возникает та же проблема. Dropbox решает эту проблему скрытием переполнения по оси x (x-overflow: hidden).
Как вы помните, по умолчанию наше меню скрыто, так что нельзя просто взять и посчитать его размеры. В нашем случае меню статическое, но при реальном применении его содержимое может меняться в зависимости от контекста, так что рассчитывать ширину и высоту лучше в момент открытия. Получим нужные величины внутри функции positionMenu:
Введем еще две переменных, но на этот раз для размеров окна:
Посчитаем их значения похожим образом:
В конечном счете давайте предположим, что хотим показывать меню не ближе, чем в 4 пикселях от края окна. Можно сравнить значения, как я говорил выше, и скорректировать позицию как-то так:
Сейчас наше меню ведет себя совсем хорошо. Осталось что-то сделать с ресайзом окна. Я уже говорил, как поступает Dropbox, но вместо этого мы будем закрывать контекстное меню. [Такое поведение куда ближе к стандартному] Добавим в функцию init следующую строку:
И напишем саму функцию:
Цепляем события к пунктам контекстного меню
Если ваше приложение сложнее данного примера, и у вас планируется динамическое содержимое контекстного меню, придется подробнее вникнуть в происходящее далее, чтобы самому додумать недостающие детали. В нашем приложении все проще, и есть всего одно меню с постоянным набором действий. Таким образом, можно быстро проверить, какой именно элемент был выбран, и обработать этот выбор. В нашем примере просто сохраним выбранный элемент в переменную и запишем в консоль его data-id и выбранное действие. Для этого отредактируем разметку меню:
Далее давайте закэшируем все нужные объекты:
Появилась переменная taskItemInContext, которой присваивается значение при правом клике по элементу списка. Она нам потребуется для логирования ID элементов. Также появились новые имена классов. Теперь пройдемся по функциональности.
Функция инициализации остается такой же. Первое изменение затрагивает contextListener, ведь мы хотим сохранять в taskItemInContext элемент, на который кликнул пользователь, а функция clickInsideElement как раз его и возвращает:
Мы сбрасываем ее в null, если правый клик произошел не по элементу списка. Ну и возьмемся за clickListener. Как я упоминал ранее, для простоты мы просто будем выводить информацию в консоль. Сейчас при отлавливании события click производится несколько проверок и меню закрывается. Внесем коррективы и начнем обрабатывать клик внутри контекстного меню, выполняя некоторое действие и лишь после этого закрывая меню:
Вы могли заметить, что вызывается функция menuItemListener. Ее мы определим чуть позже. Функции keyupListener, resizeListener и positionMenu оставляем без изменений. Функции toggleMenuOn и toggleMenuOff отредактируем незначительно, изменив имена переменных для лучшей читаемости кода:
Наконец реализуем menuItemListener:
На этом разработка функциональности заканчивается.
Некоторые замечания
- На протяжении всей статьи я упоминал правый клик как событие для открытия контекстного меню. Не все являются правшами и не у всех выставлены стандартные настройки мыши. Но вне зависимости от этого, событие contextmenu действует именно в соответствии с настройками мыши, а не привязано жестко к именно правой кнопке.
- Еще один важный момент заключается в том, что мы рассмотрели только полноценные настольные веб-приложения с мышью в качестве устройства ввода. Пользователи могут пользоваться клавиатурой или мобильными устройствами, поэтому не забудьте предусмотреть альтернативные способы взаимодействия для сохранения дружественного интерфейса.
Большой вопрос
Совместимость с браузерами
- Chrome 39
- Safari 7
- Firefox 33
Заключение и демо
Если вы тщательно все обдумали и уверены, что такая функциональность нужна вашему приложению, вы можете использовать разработанное меню. Конечно, оно может потребовать каких-либо изменений, но данное руководство подробно описывает процесс разработки, так что реализовывать свои поправки должно быть не так сложно.
Кодовая база этого руководства залита на GitHub и будет поддерживаться и, возможно, обновляться в течение долгого времени. А полное рабочее демо можно потыкать на CodePen.
От переводчика
Перевод местами достаточно вольный, но не в ущерб смыслу или содержанию. Все, что не относится напрямую к оригиналу, вынесено в примечания.
С предложениями, пожеланиями и замечаниями, как обычно, в ЛС.Часто бывает так, что пользователю нужны дополнительные кнопки меню при работе с файлами и папками, либо при работе в браузере. Их настройку можно выполнить без установки дополнительного программного обеспечения, а сам процесс займет считанные минуты.
- Как добавить кнопку на панель инструментов
- Как на панель быстрого запуска добавить кнопку "свернуть все окна"
- Как настроить панель инструментов
Откройте любую папку на вашем компьютере. В меню сверху выберите пункт «Вид», далее «Панели инструментов» и «Настройка». У вас появится новое окно, в котором вы можете добавлять любые нужные кнопки на панель инструментов сверху. Здесь же вы можете настроить и их внешний вид, размер значков, подписи к ним и так далее.
Если вам нужно добавить кнопки на панель обозревателя Internet Explorer, откройте браузер и также выберите настройки внешнего вида, как и в предыдущем пункте. Зачастую новые версии этого обозревателя не поддерживают стандартного вида меню, в этом случае найдите кнопку настройки параметров внешнего вида браузера и добавьте нужные для работы иконки.
Если вы хотите изменить последовательность меню, зайдите в пункт «Сервис», далее выберите команду «Настройка». У вас на экране появится новое диалоговое окно, выберите в нем панель инструментов или меню, которые бы вы хотели изменить или переместить. При помощи клавиш со стрелками поменяйте положение кнопок меню в соответствии с желаемой последовательностью.
Если вы хотите изменить пункты содержания меню быстрого доступа, находящейся на панели задач, для этого просто убедитесь, что в настройках поставлена галочка напротив соответствующей опции, затем перетащите на эту панель ярлыки приложений, которые хотели бы видеть там. Удаление ненужных происходит обратным способом либо путем нажатия правой кнопкой мыши и выбора нужного пункта.
Если вы хотите сбросить все измененные настройки панелей инструментов, в меню «Сервис» выберите команду «Настройка», далее перейдите на вкладку «Команды» в открывшемся окне, выберите нужные пункты и нажмите кнопку «Сбросить все». После этого значения для этих позиций будут те, которые были изначально на вашем компьютере после установки системы.
Интернет становится все более интерактивен, и пользователи все чаще начинают взаимодействовать друг с другом через самые разные сайты, используя свои аккаунты в социальных сетях – таких, как ВКонтакте, Facebook, Одноклассники, и другие. Практически на каждом сайте теперь в конце статьи имеется несколько кнопок, нажав на которые, вы можете оперативно поделиться понравившимся материалом с друзьями в своем аккаунте. Установить кнопки социальных сетей вы можете и на свой собственный сайт.
- Как добавить кнопку на сайт
- Как создать кнопку сайта
- Как вставить кнопку
Вы можете пойти простым путем и установить готовые кнопки, коды javascript, которых имеются в соответствующих разделах на сайтах социальных сервисов. Однако javascript существенно снижает скорость загрузки страниц, особенно, если таких элементов на странице много, а также такой формат кнопки не позволяет изменять ее размер и делать все кнопки одинаковыми и аккуратными.
Если вы владеете Photoshop, вы можете сделать кнопки в виде графических файлов, скачав из интернета иконки популярных социальных сетей и доработав их до одинаковой ширины и высоты.
Все, что вам понадобится сделать – это добиться того, чтобы при нажатии на графическую кнопку информация размещалась в вашем аккаунте в соответствующей социальной сети. Используйте обычный системный блокнот для открытия php-файлов.
Все коды кнопок добавляйте в файл single.php или index.php, и формируйте код следующего вида, для соблюдения общего стиля всех кнопок, коды которых вы сформируете и вставите в тег:коды кнопок
Установите кнопки нескольких наиболее популярных социальных сервисов с функцией «поделиться с друзьями» и «разместить материал на своей странице», а также при желании добавьте ссылки на собственные профили в тех же социальных сетях, чтобы посетители вашего сайта могли легко находить с вами контакт.
Читайте также: