Реализация подгрузки содержимого

We use cookies. Read the Privacy and Cookie Policy

Реализация подгрузки содержимого

Теоретическая часть главы вышла очень короткой. Значит, больше времени останется на практику!

Давайте создадим новый Web-сайт, в котором и реализуем подгрузку содержимого. Его Web-страницы мы изготовим на основе соответствующих Web-страниц старого Web-сайта.

ВНИМАНИЕ!

Далее будем называть фрагменты содержимого Web-страниц, хранящиеся в отдельных файлах, также Web-страницами. Ведь это Web-страницы и есть! Если же потребуется отметить различие между "полноразмерной" Web-страницей и фрагментом, мы это особо отметим.

Прежде всего, создадим папку, которая станет корневой для нового Web-сайта. На- зовем ее Site 2. Скопируем туда из корневой папки старого Web-сайта (Site 1) файлы main.css, main.js и ext-core.js. И сразу же создадим в ней папки chapters (для Web-страниц разделов), tags (для Web-страниц с описаниями тегов HTML), attrs (для Web-страниц, описывающих атрибуты стиля CSS) и samples (для Web-страниц с примерами).

Откроем в Блокноте Web-страницу index.htm старого Web-сайта и пересохраним под тем же именем в папке Site 2. Удалим из ее контейнера cmain все содержимое и сохраним.

Снова откроем Web-страницу index.htm старого Web-сайта и пересохраним ее в папке chapters, вложенной в папку Site 2, под именем html.htm. Удалим из нее все, кроме содержимого контейнера cmain, и сохраним снова.

Аналогично создадим остальные Web-страницы нового Web-сайта. И не забудем скопировать файлы графического изображения, аудио- и видеоклипа из папки ста- рого Web-сайта в соответствующую папку нового.

Откроем Web-страницу index.htm уже нового Web-сайта и исправим интернет- адреса в гиперссылках, указывающих на другие Web-страницы. При этом будем иметь в виду, что интернет-адреса всех файлов с внедренными объектами (изображениями, аудио- и видеороликами) следует указывать относительно Web-страницы index.htm — ведь именно она фактически будет их загружать.

Web-страницы готовы. Настала пора создавать соответствующее поведение. Откроем Web-страницу index.htm нового Web-сайта в Блокноте и удалим из секции ее заголовка код, объявляющий переменные outerIndex и innerText. Они нам больше не потребуются, так что незачем засорять память компьютера ненужными данными.

Потом откроем файл main.js нового Web-сайта, найдем в нем объявление функции selectItem и удалим его. Также удалим выражение, вызывающее эту функцию, из тела функции, которая передается методу onReady объекта Ext. Весь этот код нам больше не понадобится — скрытие и открытие вложенных списков и выделение пунктов полосы навигации мы реализуем по-другому, более "интеллектуально".

Но как?

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

Далее мы напишем функцию, которая станет обработчиком события click пунктов полосы навигации. Эта функция будет выполнять три задачи. Во-первых, она реализует подгрузку содержимого из файла, чей интернет-адрес указан в гиперссылке

пункта меню, на котором щелкнули мышью, и вывод его в контейнере cmain. Во-вторых, она будет делать тексты примеров скрывающимися и открывающимися при щелчке мышью на их первых потомках (для этого мы используем код, написанный в главе 16). В-третьих, она будет управлять скрытием и открытием вложенных списков и выделением пунктов полосы навигации при щелчках на них.

— Если посетитель щелкнул на пункте "внешнего" списка, формирующего полосу навигации, который имеет вложенный список, эта функция:

удалит выделение с выделенного ранее пункта полосы навигации (если он был выделен). Выделенный пункт полосы навигации будет храниться в особой переменной, которую мы собираемся объявить;

скроет открытый ранее вложенный список (если он был открыт и не вложен в пункт, на котором щелкнули мышью, — в этом случае нам нет нужды скрывать его, чтобы тотчас открыть). Открытый вложенный список также будет храниться в особой переменной, которую мы собираемся объявить;

развернет список, вложенный в пункт, на котором щелкнули мышью.

— Если посетитель щелкнул на пункте "внешнего" списка, не имеющего вложенного списка, эта функция:

скроет открытый ранее вложенный список (если он был открыт);

удалит выделение с выделенного ранее пункта полосы навигации (если он был выделен и если это не тот же самый пункт, на котором щелкнули мышью, — в этом случае незачем снимать с него выделение, чтобы сразу же выделить);

выделит пункт, на котором щелкнули мышью.

— Если посетитель щелкнул на пункте вложенного списка, эта функция:

удалит выделение с выделенного ранее пункта полосы навигации (если он был выделен и если это не тот же самый пункт, на котором щелкнули мышью);

выделит пункт, на котором щелкнули мышью.

Еще нам понадобятся две вспомогательные функции. Первая, совсем простая, будет вызвана после загрузки базовой Web-страницы index.htm и сделает все вложен- ные списки в полосе навигации скрытыми.

Вторая функция удалит все обработчики событий, привязанные к первым потомкам контейнеров со стилевым классом sample ("вместилища" для текста примеров). Перед тем как выводить в контейнере cmain новое содержимое, нужно удалить обработчики событий, привязанные к старому его содержимому. Так мы очистим память компьютера от не нужных более обработчиков событий и устраним потенциальную возможность появления ошибок. Данная функция будет вызываться в теле функции, которую мы описали чуть раньше, перед подгрузкой и выводом содержимого другого файла.

Что ж, задачи ясны. За работу!

В самом начале файла main.js поместим два выражения:

var elLastInnerList = null;

var elLastItem = null;

Они объявляют переменные elLastInnerList и elLastItem и присваивают им значение null. Первая переменная будет хранить открытый в данный момент вложенный список, вторая — выделенный в данный момент пункт полосы навигации.

Далее объявим функцию loadFragment, которая будет обрабатывать событие click пунктов полосы навигации (листинг 17.1). Она будет принимать два параметра: пункт, на котором щелкнули мышью, в виде экземпляра объекта Element и экземпляр объекта EventObject, хранящий сведения о событии. Второй параметр необязательный.

Листинг 17.1

function loadFragment(elLI, e) {

if (e)

e. stopEvent();

var elA = elLI.child("A");

if (elA) {

cleanupSamples();

var href = elA.getAttribute("HREF");

Ext.get("cmain"). load({ url: href, success: prepareSamples });

if (elLI.parent("UL"). id == "navbar") {

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

if (elInnerList) {

if (elLastItem) { elLastItem.removeClass("selected"); elLastItem = null;

}

if ((elLastInnerList) && (elLastInnerList.dom!=

elInnerList.dom))

elLastInnerList.setDisplayed(false); elInnerList.setDisplayed(true); elLastInnerList = elInnerList;

} else {

if (elLastInnerList) { elLastInnerList.setDisplayed(false); elLastInnerList = null;

}

if ((elLastItem) && (elLastItem.dom!= elLI.dom))

elLastItem.removeClass("selected");

elLI.addClass("selected");

elLastItem = elLI;

}

} else {

if ((elLastItem) && (elLastItem.dom!= elLI.dom))

elLastItem.removeClass("selected");

elLI.addClass("selected");

elLastItem = elLI;

}

}

}

Рассмотрим листинг 17.1 построчно.

Если функции loadFragment был передан второй параметр — экземпляр объекта EventObject, хранящий сведения о событии, — отменяем действие события по умолчанию и останавливаем его всплытие:

if (e)

e. stopEvent();

Этот код перекочевал из функции-обработчика события click пунктов полосы навигации нашего предыдущего Web-сайта (подробности — в главе 16).

Получаем гиперссылку, вложенную в пункт полосы навигации, на котором щелк- нули мышью:

var elA = elLI.child("A");

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

if (elA) {

Вызываем функцию cleanupSamples, которая удалит обработчики событий у первых потомков контейнеров с текстами примеров:

cleanupSamples();

Мы объявим эту функцию потом. Получаем интернет-адрес гиперссылки:

var href = elA.getAttribute("HREF");

Загружаем в контейнер cmain содержимое файла, на который указывает полученный интернет-адрес:

Ext.get("cmain"). load({ url: href, success: prepareSamples });

После его загрузки вызываем функцию prepareSamples, которая добавит контейнерам с текстом примеров возможность скрытия и раскрытия в ответ на щелчки мышью. Эту функцию мы объявили в главе 16.

Получаем список — родитель пункта полосы навигации, на котором щелкнули мышью, и проверяем, navbar ли его имя:

if (elLI.parent("UL"). id == "navbar") {

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

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

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

Проверяем, присутствует ли в пункте вложенный список:

if (elInnerList) {

Если вложенный список присутствует, проверяем, выделен ли в данный момент какой-либо пункт полосы навигации, т. е. содержит ли переменная elLastItem ка- кое-либо значение, отличное от null:

if (elLastItem) { elLastItem.removeClass("selected"); elLastItem = null;

}

Если это так, удаляем из привязки к выделенному пункту стилевой класс selected, делая его невыделенным, и присваиваем переменной elLastItem значение null, указывая тем самым, что ни один пункт полосы навигации в данный момент не выделен.

Также проверяем, открыт ли в данный момент какой-либо вложенный список (содержит ли переменная elLastInnerList какое-либо значение, отличное от null), и не тот ли это список, что вложен в пункт, на котором щелкнули мышью:

if ((elLastInnerList) && (elLastInnerList.dom!=

elInnerList.dom))

elLastInnerList.setDisplayed(false);

Если это так, скрываем этот список.

Обратим внимание, как мы проверяем тождественность открытого в данный момент вложенного списка тому, что содержится в пункте, на котором щелкнули мышью. Мы сравниваем не экземпляры объекта Element, возвращенные методами библиотеки Ext Core, а экземпляры объекта HTMLElement Web-обозревателя. Дело в том, что методы библиотеки Ext Core в разные моменты времени могут вер- нуть совершенно разные экземпляры объекта Element, тем не менее, представляющие один и тот же элемент Web-страницы. В то время как экземпляр объекта HTMLElement, представляющий данный элемент Web-страницы, всегда один и тот же.

Чтобы получить доступ к экземпляру объекта HTMLElement, мы используем свойство dom объекта Element. Оно было описано в главе 15.

Далее нам остается только открыть вложенный список, присутствующий в пункте, на котором щелкнули мышью:

elInnerList.setDisplayed(true);

…и сохранить его в переменной elLastInnerList:

elLastInnerList = elInnerList;

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

мышью, отсутствует, выполняется следующий код:

} else {

Проверяем, открыт ли в данный момент какой-либо вложенный список (содержит ли переменная elLastInnerList какое-либо значение, отличное от null):

if (elLastInnerList) { elLastInnerList.setDisplayed(false); elLastInnerList = null;

}

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

Затем проверяем, выделен ли в данный момент какой-либо пункт полосы навигации (содержит ли переменная elLastItem какое-либо значение, отличное от null), и не тот ли это пункт, на котором щелкнули мышью:

if ((elLastItem) && (elLastItem.dom!= elLI.dom))

elLastItem.removeClass("selected");

Здесь мы также сравниваем экземпляры объекта HTMLElement Web-обозревателя. Если какой-то пункт выделен и это не тот же самый пункт, на котором щелкнули мышью, снимаем с него выделение, убрав стилевой класс selected из привязки к нему.

Выделяем пункт, на котором щелкнули мышью, привязав к нему стилевой класс selected:

elLI.addClass("selected");

И сохраняем этот пункт в переменной elLastItem:

elLastItem = elLI;

}

Если пункт, на котором щелкнули мышью, находится во вложенном списке, выполняется следующий код:

} else {

Далее все нам уже знакомо:

if ((elLastItem) && (elLastItem.dom!= elLI.dom))

elLastItem.removeClass("selected");

elLI.addClass("selected");

elLastItem = elLI;

}

}

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

котором щелкнули мышью, привязав к нему стилевой класс selected, и сохраняем этот пункт в переменной elLastItem. На этом выполнение функции loadFragment закончено.

Теперь объявим функцию hideInnerLists, которая скроет все вложенные списки в полосе навигации после загрузки базовой Web-страницы index.htm. Вот соответст- вующий код:

function hideInnerLists() {

var ceInnerLists = Ext.get("navbar"). select("UL");

ceInnerLists.setDisplayed(false);

}

Комментировать здесь особо нечего. Мы получаем все списки, вложенные во "внешний" список navbar, и скрываем их.

На очереди — функция cleanupSamples (листинг 17.2). Она удалит обработчики событий, привязанные к первым потомкам контейнеров с текстом примеров (тех, к которым привязан стилевой класс sample).

Листинг 17.2

function cleanupSamples() {

var ceSamples = Ext.select(".sample");

ceSamples.each(function(el, cl, ind){ var elH6 = el.child(":first"); elH6.removeAllListeners();

});

}

Получаем все элементы Web-страницы с привязанным стилевым классом sample, для каждого получаем первый потомок и убираем все привязанные к нему ранее обработчики событий.

Осталось только внести исправления в код тела функции, которая передается методу onReady объекта Ext. Прежде всего, найдем выражение, привязывающее обработчик события click к пунктам всех списков в полосе навигации. Исправим его так, чтобы оно выглядело следующим образом:

ceLinks.on("click", function(e, t){ loadFragment(Ext.get(this), e) });

Тело нового обработчика этого события представляет собой вызов объявленной нами ранее функции loadFragment. В качестве параметров мы передаем ей экземпляр объекта Element, представляющий пункт полосы навигации, на котором щелкнули мышью, и полученный из экземпляра объекта HTMLElement, доступный из пе- ременной this, а также экземпляр объекта EventObject, хранящий сведения о событии и переданный функции-обработчику первым параметром.

А в конце тела функции, которая передается методу onReady объекта Ext, вставим два выражения:

hideInnerLists();

loadFragment(Ext.get("navbar"). child("> LI: first"));

Первое вызывает функцию hideInnerLists, которую мы объявили ранее. Эта функция скроет все вложенные списки в полосе навигации после загрузки базовой Web- страницы index.htm.

Второе выражение вызовет функцию loadFragment и передаст ей в качестве пара- метра первый пункт "внешнего" списка navbar полосы навигации ("HTML"). В результате изначально в контейнер cmain будет загружено описание языка HTML (содержимое файла html.htm, хранящегося в папке chapters).

Сохраним файл main.js. И проверим наш второй Web-сайт в действии. Как мы пом- ним, для этого понадобится Web-сервер, который у нас уже есть — Microsoft Internet Information Services. (Мы установили его еще в главе 1.)

С помощью любой программы управления файлами (того же Проводника) откроем корневую папку созданного при установке этого Web-сервера тестового Web-сайта (папка c: Inetpubwwwroot). Очистим корневую папку от имеющихся там файлов и скопируем в нее все содержимое папки Site 2 (если кто забыл — в ней мы храним все файлы нового Web-сайта).

ВНИМАНИЕ!

Описанную операцию мы будем выполнять всякий раз после любой правки файлов Web-сайта. Автор больше не будет об этом напоминать.

НА ЗАМЕТКУ

Впрочем, есть способ избежать подобной операции: поместить рабочие файлы Web-сайта в корневую папку Web-сервера и работать с ними прямо там.

Откроем новый Web-сайт в Web-обозревателе, для чего запустим его и наберем в поле ввода интернет-адреса http://localhost. Этот интернет-адрес, как мы помним из главы 1, идентифицирует наш собственный компьютер — локальный хост.

Когда главная Web-страница нового Web-сайта откроется, проверим, присутствует ли в контейнере cmain изначально описание языка HTML и открыт ли первый вложенный список (находящийся в пункте "HTML" полосы навигации). Пощелкаем на пунктах полосы навигации и посмотрим, как меняется содержимое контейнера cmain. И отметим, насколько быстро оно меняется. Вот что значит современные технологии!

Что дальше?

В этой главе мы создали новый Web-сайт, в котором реализовали самую современную на данный момент технологию — подгружаемое содержимое. Теперь нам есть чем похвастаться перед коллегами!

В следующей главе мы совладаем со второй технологией — "последним писком" Web-моды — генерируемым содержимым. Мы будем создавать полосу навигации нашего Web-сайта программно, в Web-сценарии, на основе сведений, хранящихся в базе данных. Ну и попутно узнаем, что такое база данных.

Данный текст является ознакомительным фрагментом.