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-сайта и проверим их в действии.
Скрытие и открытие текста примеров
На Web-страницах, описывающих теги HTML и атрибуты стиля CSS, мы поместили текст примеров применения того или иного тега или атрибута стиля. Часто его делают скрывающимся и открывающимся в ответ на щелчок мышью — так можно сделать Web-страницы визуально менее громоздкими.
Давайте и мы реализуем нечто подобное на своих Web-страничках. Хотя бы в самом простом варианте.
— Текст примера мы поместим в блочный контейнер, к которому привяжем стилевой класс sample. Этот стилевой класс будет служить двум целям: во-первых, он обозначит данный контейнер как "вместилище" для примера, во-вторых, он задаст для контейнера особое представление, чтобы его выделить среди остального содержимого Web-страницы.
— Особое представление для контейнера с текстом примера будет включать внутренние отступы и рамку.
— Все содержимое контейнера изначально будет скрыто, за исключением первого его потомка (у нас — заголовок "Пример: " шестого уровня).
— При щелчке мышью на первом потомке контейнер (т. е. остальное его содержимое) будет открываться или снова скрываться.
— При наведении курсора мыши на первый потомок контейнера будет меняться цвет его рамки. Кроме того, мы зададим для него особое представление — форму курсора в виде "указующего перста". Так мы дадим посетителю понять, что данный элемент Web-страницы реагирует на щелчки мышью.
— На Web-странице могут быть несколько контейнеров с текстом примеров. Это следует учесть при написании Web-сценария.
Откроем таблицу стилей main.css и добавим в нее такие стили:
sample { padding: 5px; border: thin dotted #B1BEC6 }
sample >:first-child { margin: 0px 0px; cursor: pointer }
Первый стиль — это стилевой класс sample, помечающий контейнер как "вместилище" для примера. Он задает для контейнера параметры внутренних отступов и рамки.
Второй стиль задает для первого непосредственного потомка данного контейнера нулевые внешние отступы (чтобы убрать ненужное свободное пространство выше и ниже его) и форму курсора в виде "указующего перста".
Теперь откроем файл Web-сценария main.js и поместим где-либо в его начале, перед вызовом метода onReady объекта Ext, код листинга 16.9.
Листинг 16.9
function showHideSample(e, t) {
var elDiv = Ext.fly(t). parent(".sample");
var ceSampleText = elDiv.select("*:not(:first-child)"); ceSampleText.setVisibilityMode(Ext.Element.DISPLAY); ceSampleText.toggle();
}
function prepareSamples() {
var ceSamples = Ext.select(".sample");
ceSamples.each(function(el, cl, ind){ var elH6 = el.child(":first"); elH6.on("click", showHideSample); elH6.on("mouseover", function(e, t) {
Ext.get(this). parent("DIV"). addClass("hovered");
});
elH6.on("mouseout", function(e, t) { Ext.get(this). parent("DIV"). removeClass("hovered");
});
var ceSampleText = el.select("*:not(:first-child)");
ceSampleText.setDisplayed(false);
});
}
Мы объявили функции showHideSample и prepareSamples. Первая будет обрабатывать событие click в первом потомке контейнера с текстом примера и в ответ на это событие скрывать или открывать данный контейнер. Вторая будет выполнять подготовительные действия: при открытии Web-страницы скрывать контейнеры с текстом примеров и привязывать к ним обработчики событий.
Рассмотрим код этих функций построчно. И начнем с функции prepareSamples.
Сначала получаем все контейнеры с привязанным стилевым классом sample, т. е. содержащие текст примеров:
var ceSamples = Ext.select(".sample");
Затем для каждого полученного контейнера выполняем описанные далее манипуляции:
ceSamples.each(function(el, cl, ind){
Получаем первый потомок контейнера:
var elH6 = el.child(":first");
Привязываем к нему в качестве обработчика события click функцию
showHideSample:
elH6.on("click", showHideSample);
Привязываем к нему функцию — обработчик события mouseover, которую там же и объявляем:
elH6.on("mouseover", function(e, t) { Ext.fly(this). parent("DIV"). addClass("hovered");
});
Эта функция получит родитель элемента Web-страницы, в котором возникло данное событие, т. е. контейнер с текстом примера, и привяжет к нему стилевой класс hovered.
Не забываем привязать функцию-обработчик события mouseout, которая будет убирать из привязки к контейнеру стилевой класс hovered:
elH6.on("mouseout", function(e, t) { Ext.fly(this). parent("DIV"). removeClass("hovered");
});
Получаем все остальные элементы-потомки контейнера (не являющиеся первым потомком):
var ceSampleText = el.select("*:not(:first-child)");
И скрываем их:
ceSampleText.setDisplayed(false);
});
На очереди — функция showHideSample.
Получаем родитель элемента Web-страницы, в котором возникло событие:
var elDiv = Ext.fly(t). parent(".sample");
Поскольку этот обработчик привязан к первому потомку контейнера с текстом примера, здесь мы получим сам этот контейнер.
Получаем все элементы-потомки контейнера, не являющиеся первым потомком:
var ceSampleText = elDiv.select("*:not(:first-child)");
Указываем, что для управления их видимостью будет использован атрибут стиля display, и изменяем их видимость (открываем, если они скрыты, и скрываем, если они