Главное меню

Выделение пункта меню

Что ж, скрытие и открытие вложенных списков, формирующих полосу навигации, в "содружестве" с библиотекой Ext Core реализуется весьма просто. Но работа над полосой навигации еще не закончена.

Хорошим тоном сейчас считается как-то выделять пункт меню, соответствующий открытой в данный момент Web-страницы. Выделяют его обычно рамкой или "инверсными" цветами (в качестве цвета текста используется цвет фона, а в качестве цвета фона — цвет текста). Давайте и мы сделаем нечто подобное.

- Пункт вложенного списка мы будем выделять "инверсными" цветами.

- Пункт "внешнего" списка, не имеющий вложенного списка, мы также будем выделять "инверсными" цветами.

- Пункт "внешнего" списка, имеющий вложенный список, мы никак выделять не будем — его выделит открытый вложенный список.

Заодно давайте объединим установку выделения на пункт полосы навигации со скрытием и открытием вложенных списков.

Откроем таблицу стилей main.css и добавим в нее стили из листинга 16.7.

Выделение пункта полосы навигации, соответствующего открытой в данный момент Web-странице

Здесь мы определяем стилевой класс selected, который будем привязывать к выделяемому пункту списка, и четыре стиля, задающие "инверсные" цвета для текста, которые будут применяться к гиперссылке, находящейся в выделенном пункте списка, в зависимости от ее состояния.

Сохраним таблицу стилей. И откроем файл Web-сценария main.js. Удалим из него объявление функции showInnerList, созданное ранее, и вставим на его место объявление функции, приведенной в листинге 16.8.

Выделение пункта меню

Эта функция с именем selectItem будет выполнять несколько действий:

- Если первым параметром передан порядковый номер пункта "внешнего" списка, который содержит вложенный список, она откроет данный список и скроет все остальные вложенные списки.

- Если первым параметром передан порядковый номер пункта "внешнего" списка, который не содержит вложенный список, она выделит данный пункт "внешнего" списка и, опять же, скроет все остальные вложенные списки.

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

Рассмотрим ее код построчно.

Получаем "внешний" список, формирующий полосу навигации:

var elNavbar = Ext.get("navbar");

Убираем из привязки ко всем пунктам всех списков, формирующих полосу навигации, — и "внешнего", и вложенных — стилевой класс selected:

elNavbar.select("LI").removeClass("selected");

Так мы снимем выделение со всех пунктов всех списков.

Сворачиваем все вложенные списки:

var ceInnerLists = elNavbar.select("UL");
ceInnerLists.setDisplayed(false);

Эти три выражения перекочевали из функции showInnerList без изменений.

Формируем строку, содержащую селектор CSS, который выбирает пункт "внешнего" списка с переданным функции selectItem в качестве первого параметра порядковым номером, и получаем этот пункт:

var sSelector = "> LI:nth(" + iIndex + ")";
var elOuterItem = elNavbar.child(sSelector);

Получаем вложенный список, присутствующий в этом пункте, разумеется, если он там есть:

var elInnerList = elOuterItem.child("UL");

Если вложенный список есть, метод child вернет экземпляр объекта Element, в противном случае — значение null.

Проверяем, что мы получили в результате вызова метода child в предыдущем выражении:

if (elInnerList) {

Если этот метод вернул экземпляр объекта Element, последний будет преобразован в значение true, и условие выполнится. Если же он вернул значение null, оно будет преобразовано в false, и условие не выполнится.

Если вложенный список существует, открываем его:

elInnerList.setDisplayed(true);

Проверяем, был ли функции selectItem передан второй параметр — текст пункта вложенного списка, который следует выделить:

if (sText) {

Если он был передан, формируем строку с селектором CSS, выбирающим пункт вложенного списка, потомок которого содержит текст, переданный этим самым вторым параметром:

sSelector = "LI:has(:nodeValue(" + sText + "))";

Получаем пункт вложенного списка, удовлетворяющий сформированному ранее селектору, и сразу же привязываем к нему стилевой класс selected:

elOuterItem.child(sSelector).addClass("selected");
}

Если полученный ранее пункт "внешнего" списка с указанным порядковым номером не содержит вложенного списка, привязываем к этому пункту стилевой класс selected:

} else
elOuterItem.addClass("selected");

На этом выполнение функции завершается.

В теле функции, передаваемой в качестве параметра методу onReady объекта Ext, ранее мы добавили вызов функции showInnerList. Удалим его и вместо него вставим такой код:

selectItem(outerIndex, innerText);

Здесь мы вызываем функцию selectItem, передавая ей в качестве параметров значения переменных outerIndex и innerText. Первая переменная будет хранить номер вложенного списка, который требуется открыть, а вторая — текст пункта вложенного списка, который нужно выделить.

Откроем Web-страницу index.htm, найдем код, вставленный ранее в ее секцию заголовка, и дополним его таким образом:

<SCRIPT>
outerIndex = 1;
innerText = null;
</SCRIPT>

Мы добавили выражение, присваивающее переменной innerText значение null. При выполнении Web-сценариев, хранящихся в файле main.js, в том числе и вызове функции selectItem, значения обеих этих переменных будут переданы данной функции в качестве параметров. В результате откроется первый вложенный список, и ни один его пункт не будет выделен.

Откроем Web-страницу t_audio.htm и дополним вставленный ранее код в ее секцию заголовка так:

<SCRIPT>
outerIndex = 1;
innerText = "AUDIO";
</SCRIPT>

В результате будет открыт первый вложенный список и в нем выделен пункт "AUDIO".

Аналогично заменим вставленный ранее код во всех остальных Web-страницах нашего Web-сайта и проверим их в действии.