Почему-то на сайтах, посвященных программированию на JavaScript, традиционно считается, что это невозможно, так как Netscape по щелчку правой клавишей мыши
создает собственное всплывающее меню. Попробуем развеять это заблуждение. Дело в том, что выпадающее меню в Netscape Navigator 7.1 и выше версии (ниже версии
нет в наличии - если код корректно работает в версии Netscape ниже 7.1 - пожалуйста напишите мне), можно отключить с помощью знакомой инструкции:
, но как же создать выпадающее меню, если в Netscape следующий код (работающий в Internet Explorer):
не работает, то есть - функция вызывается, но в Nescape Navigator возникает выпадающее меню, поверх создаваемого нами в функции myfunction. Как же обойти это
ограничение? Я нашел такое решение:
Как вы вполне можете догадаться, функция "myfunction()" в конце своего исполнения возвращает результат - return false, что с точки зрения Netscape Navigator
считается корректным. Но только вот такой код не считается корректным у Internet Explorer. Что поделаешь? Война браузеров! Придется воспользоваться таким
интересным приемом, как условная трансляция (надеюсь, что подобрал словосочетание правильное, по аналогии с условной компиляцией в Си) браузера Internet
Explorer. Дело в том, что Microsoft © позаботилась о создании специальных конструкций, которые для остальных браузеров выглядят как комментарий. С
помощью этих конструкций можно создать достаточно сложные ветвления кода. Попробуем создать ветвление кода на основе этих самых конструкций и разберем его
чуть ниже.
Разберем первую эту часть скрипта подробно. Вначале определяется тип браузера пользователя, эта часть нам не интересна - такие скрипты можно найти в Internet
повсюду. Для начинающих лучше всего воспользоваться редактором с подсветкой синтаксиса. Итак первая интересующая нас инструкция: "/*@cc_on" - это инструкция
начала "условной трансляции", обратить внимание стоит только на ее начало - "/*" - это обычный комментарий. Internet Explorer выше пятой версии разбирает
даже комментарии, и ищет директивы "условной трансляции" (большой брат следит за тобой!). Теперь присмотримся к следующей строке - тут указана на первый
взгляд странная строка: "@if( true )" - условие, которое выполнится в любом случае! Необходимость этого условия не кажется очевидной, но на самом деле все
очень просто, если Internet Explorer прочтет эту инструкцию - он выполнит код, который предназначен только ему одному, а строку идущую после директивы
"@else*/" пропустит. А теперь предположим, что условия "@if( true ) ... @else" нет - что получится? Internet Explorer выполнит сразу две инструкции - и мы
получим в документе сразу два
с разными параметрами! Не очень приятная перспектива. Последняя инструкция @cc_off @*/ завершает "условную
трансляцию". Таким образом мы получили переносимый код, подходящий для браузеров на основе движка Internet Explorer (Avant, Maxthon, etc...) и движка Gecko
(Netscape Navigator, Mozilla, Mozilla Firefox, Mozilla Firebird, etc...).
Создадим примитивный лист стилей (наша задача создать не красивый, а понятный код - украсить его вы можете сами! Наш лист стилей:
Он отвечает только за отображение и сокрытие контекстного меню, что нам собственно и надо. Теперь надо определить координаты курсора в момент щелчка правой
клавиши мыши по документу. Основная проблема заключается в том, что для Netscape Navigator возникает такая проблема, обработчик события event.onmousedown -
перекрывает обработчик, заданный в body (в общем-то вполне логично, поскольку event задается относительно окна, а не документа, как в body). И опять
возникает ненавистное браузерное контекстное меню. Я решил эту проблему таким образом (если кто знает решение проще - пришлите мне письмо):
if( document.all ) {
} else if( document.getElementById ) {
document.captureEvents( Event.MOUSEMOVE );
document.onmousemove = getCoord;
}
Я стал отслеживать каждое передвижение мыши на экране и записывать координаты курсора в глобальные переменные:
var mouseX;
var mouseY;
function getCoord( event ) {
mouseX = event.pageX;
mouseY = event.pageY;
}
Теперь соберем саму функцию отображения меню:
function myfunction() {
if( document.all ) {
if( event.button == 2 || event.button == 3 ) {
if( !document.all.contextmenu )
return;
var menu = document.all.contextmenu;
menu.style.left = event.offsetX;
menu.style.top = event.offsetY;
menu.className = menuState ? "hidemenu" : "showmenu";
menuState = !menuState;
}
} else if ( document.getElementById ) {
if( !document.getElementById( "contextmenu" ) )
return;
var menu = document.getElementById( "contextmenu" );
menu.style.left = mouseX;
menu.style.top = mouseY;
menu.className = menuState ? "hidemenu" : "showmenu";
menuState = !menuState;
return false;
}
}
Функция не требует особых навыков в JavaScript, чтобы в ней разобраться. Скажу лишь вкратце, устанавливается
положение меню на основе координат курсора с ветвлением на два браузера. Разница лишь в том, что Internet Explorer получает координаты из события event, а
Netscape Navigator из глобальных переменных. Если вы правильно собрали скрипт - у вас должно получиться нечто подобное:
Context menu
Для тех же, кто желает "погорячее" привожу код, полностью основанный на "условной трансляции" Microsoft ©. Комментировать код не буду - изложенного выше
материала вполне достаточно, чтобы разобраться в нем самому.
Context menu
С точки зрения производительности такой код лучше, поскольку браузерам, на основе движка Gecko, не требуется проверять дополнительные условия.
И в завершение этой статьи хочу привести пример создания контекстного меню с помощью технологий, встроенных в Internet Explorer. По сути создается отдельное
немодальное окно на основе полученного кода. Этот код не может использовать внешние таблицы стилей (даже встроенные в документ!), поэтому вводить данные о
стиле придется контекстно к элементу.
Microsoft context menu
Главная
страница
Какое-то
действие
Еще что-то
делаем
Вся сложность создания дочернего окна с помощью технологий Internet Explorer - это необходимость внесения всего кода в новое окно, включая JavaScript и CSS.
Результат чего можно видеть в непомерно разросшихся аттрибутах div′ов. Пример взят из MSDN и адаптирован мной для лучшей читаемости кода. Разберем подробнее.
Итак, первое действие window.createPopup() - создает дочернее немодальное окно, но не отображает его на экране. Программистам, знакомым с WinAPI хотя бы
поверхностно - объяснять это не надо. Далее определяем значения длины и высоты нашего меню (можно автоматизировать этот процесс, но это будет уже лишний код
- сейчас главное понять как создается меню) - это переменные mWidth и mHeight. Следующий, интересующий нас оператор, это winPopup.document.body; - мы
получаем ссылку на тело документа нового окна. Далее - получаем код из div′a с идентификатором winContext и присваиваем его телу документа созданного окна.
Далее - просто отображаем новое окно - winPopup.show. Параметры: координата окна по горизонтали, координа окна по вертикали, ширина окна, высота окна, ссылка
на документ-владелец нового окна.
На этом считаю статью законченной, если будут вопросы - пишите на e-mail: texadmin@javaportal.ru
Вячеслав Шуранов aka Чайник (DUmmY)