— При открытии Web-страницы, описывающей тег, атрибут стиля или пример, будет открываться вложенный список, содержащий указывающий на эту Web- страницу пункт.
— В данный момент может быть открыт только один вложенный список — остальные будут скрыты.
— Для скрытия и раскрытия вложенного списка мы будем менять у него значение атрибута стиля display (см. главу 9) с помощью методов объекта Element, управляющих видимостью элемента Web-страницы.
Откроем файл Web-сценария main.js и запишем где-либо в его начале, еще до вызова метода onReady объекта Ext, объявление функции, приведенное в листинге 16.6.
Листинг 16.6
function showInnerList(iIndex) {
var elNavbar = Ext.get("navbar");
var ceInnerLists = elNavbar.select("UL");
ceInnerLists.setDisplayed(false);
if (iIndex) {
var sSelector = "UL: nth(" + iIndex + ")";
elNavbar.child(sSelector). setDisplayed(true);
}
}
Данная функция с именем showInnerList будет скрывать все вложенные списки и открывать только тот из них, порядковый номер которого передан ей в качестве единственного параметра. Если параметр опущен, но никакой вложенный список открыт не будет.
Рассмотрим код этой функции построчно.
Сначала получаем "внешний" список, формирующий полосу навигации:
var elNavbar = Ext.get("navbar");
Затем получаем все вложенные в него списки:
var ceInnerLists = elNavbar.select("UL");
Далее скрываем все вложенные списки, для чего используем метод setDisplayed — так проще:
ceInnerLists.setDisplayed(false);
Проверяем, был ли функции showInnerList передан параметр:
if (iIndex) {
Если он был передан, переменная iIndex будет содержать число, которое преобразуется в значение true, и условие выполнится. В противном случае переменная iIndex получит значение null, которое будет преобразовано в false, и условие не выполнится.
Если параметр функции showInnerList был передан, выполняется следующий код. Формируем строку с селектором CSS, который будет выбирать вложенный список, чей порядковый номер был передан с параметром:
var sSelector = "UL: nth(" + iIndex + ")";
Выбираем вложенный список с заданным номером и открываем его:
elNavbar.child(sSelector). setDisplayed(true);
}
На этом выполнение функции showInnerList завершится.
Теперь вставим в конец тела функции, которая передается в качестве параметра методу onReady объекта Ext, такое выражение:
showInnerList(outerIndex);
Здесь мы вызываем функцию showInnerList, передавая ей в качестве параметра значение переменной outerIndex. Эта переменная будет хранить номер вложенного списка, который требуется открыть.
Теперь откроем Web-страницу index.htm и в секцию ее заголовка (в теге <HEAD>) вставим такой код:
<SCRIPT>
outerIndex = 1;
</SCRIPT>
Мы присваиваем переменной outerIndex число 1 — номер вложенного списка, который должен быть открыт при открытии Web-страницы index.htm (это список раздела "HTML"). Когда будут выполняться Web-сценарии, хранящиеся в файле main.js, в том числе и вызов функции showInnerList, значение этой переменной будет передано данной функции в качестве параметра.
Здесь мы немного нарушили требования концепции Web 2.0, предписывающие хранить поведение Web-страницы отдельно от ее содержимого. Но в данном случае это оправдано, т. к. этот Web-сценарий у разных Web-страниц нашего Web-сайта будет различаться, и создавать ради него для каждой Web-страницы "персональный" файл Web-сценария слишком расточительно.
Такой же Web-сценарий мы вставим в секцию заголовка Web-страниц, описывающих теги HTML. И не забываем сохранять исправленные Web-страницы.
В секцию заголовка Web-страницы css_index.htm и Web-страниц, описывающих атрибуты стиля CSS, мы вставим аналогичный код:
<SCRIPT>
outerIndex = 2;
</SCRIPT>
Он укажет, что при открытии данных Web-страниц должен быть открыт второй по счету вложенный список — раздела "CSS".
В секцию заголовка Web-страницы samples_index.htm и Web-страниц, содержащих примеры, мы вставим код… сами догадайтесь, какой. (Подсказка: он должен раскрыть третий вложенный список.)
А вот в секцию заголовка Web-страницы about.htm вставим такой код:
<SCRIPT>
outerIndex = null;
</SCRIPT>
Поскольку четвертый пункт "внешнего" списка не содержит вложенного списка, открывать там ничего не нужно — следует только скрыть уже открытые вложенные списки.
Сохраним все исправленные Web-страницы и опробуем их в деле. Неплохо получилось, правда?
Выделение пункта полосы навигации, соответствующего открытой в данный момент Web-странице
Что ж, скрытие и открытие вложенных списков, формирующих полосу навигации, в "содружестве" с библиотекой Ext Core реализуется весьма просто. Но работа над полосой навигации еще не закончена.
Хорошим тоном сейчас считается как-то выделять пункт полосы навигации, соответствующий открытой в данный момент Web-страницы. Выделяют его обычно рамкой или "инверсными" цветами (в качестве цвета текста используется цвет фона, а в качестве цвета фона — цвет текста). Давайте и мы сделаем нечто подобное.
— Пункт вложенного списка мы будем выделять "инверсными" цветами.
— Пункт "внешнего" списка, не имеющий вложенного списка, мы также будем выделять "инверсными" цветами.
— Пункт "внешнего" списка, имеющий вложенный список, мы никак выделять не будем — его выделит открытый вложенный список.
Заодно давайте объединим установку выделения на пункт полосы навигации со скрытием и открытием вложенных списков.
Откроем таблицу стилей main.css и добавим в нее стили из листинга 16.7.
Листинг 16.7
selected,
#navbar.selected A: link,
#navbar.selected A: focus,
#navbar.selected A: hover,
#navbar.selected A: active,
#navbar.selected A: visited { color: #F8F8F8; background-color: #576C8C }
Здесь мы определяем стилевой класс selected, который будем привязывать к выделяемому пункту списка, и четыре стиля, задающие "инверсные" цвета для текста, которые будут применяться к гиперссылке, находящейся в выделенном пункте списка, в зависимости от ее состояния.
Сохраним таблицу стилей. И откроем файл Web-сценария main.js. Удалим из него объявление функции showInnerList, созданное ранее, и вставим на его место объявление функции, приведенной в листинге 16.8.
Листинг 16.8
function selectItem(iIndex, sText) { var elNavbar = Ext.get("navbar"); elNavbar.select("LI"). removeClass("selected"); var ceInnerLists = elNavbar.select("UL"); ceInnerLists.setDisplayed(false);
var sSelector = "> LI: nth(" + iIndex + ")"; var elOuterItem = elNavbar.child(sSelector); var elInnerList = elOuterItem.child("UL");
if (elInnerList) {
elInnerList.setDisplayed(true);
if (sText) {
sSelector = "LI: has(:nodeValue(" + sText + "))";
elOuterItem.child(sSelector). addClass("selected");
}
} else elOuterItem.addClass("selected");
}
Эта функция с именем selectItem будет выполнять несколько действий:
— Если первым параметром передан порядковый номер пункта "внешнего" списка, который содержит вложенный список, она откроет данный список и скроет все остальные вложенные списки.
— Если первым параметром передан порядковый номер пункта "внешнего" списка, который не содержит вложенный список, она выделит данный пункт "внешнего" списка и, опять же, скроет все остальные вложенные списки.
— Если вторым параметром передан текст пункта вложенного списка, она дополнительно выделит этот пункт, сняв выделение со всех остальных пунктов вложенных списков. Если второй параметр опущен, она ничего выделять не будет.
Рассмотрим ее код построчно.
Получаем "внешний" список, формирующий полосу навигации:
var elNavbar = Ext.get("navbar");
Убираем из привязки ко всем пунктам всех списков, формирующих полосу навигации, — и "внешнего", и вложенных — стилевой класс selected:
elNavbar.select("LI"). removeClass("selected");
Так мы снимем выделение со всех пунктов всех списков. Сворачиваем все вложенные списки:
var ceInnerLists = elNavbar.select("UL");
ceInnerLists.setDisplayed(false);
Эти три выражения перекочевали из функции showInnerList без изменений. Формируем строку, содержащую селектор CSS, который выбирает пункт "внешнего" списка с переданным функции selectItem в качестве