Web-сценарий выполняющий поиск

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

Откроем файл Web-сценария main.js в Блокноте и добавим в его начало такое выражение:

var cSearchHeight = 0;

Оно объявляет служебную переменную, в которой будет сохранена изначальная высота контейнера csearch. Это значение мы будем использовать для позиционирования данного контейнера. Его высота в процессе работы будет постоянно меняться, поэтому для его позиционирования нам понадобится изначальное значение высоты.

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

Ext.get("search_result").setDisplayed(false);

cSearchHeight = Ext.get("csearch").getHeight();

Первое выражение сразу скроет список search_result, а второе присвоит изначальную высоту контейнера csearch объявленной ранее служебной переменной.

Функцию adjustContainers, задающую размеры контейнеров, мы объявили еще на странице "Создание интерактивных Web-страниц" и с тех пор ни разу к ней не возвращались. Настала пора внести в объявление этой функции некоторые правки.

Вот выражения, которые мы добавим в самый конец adjustContainers:

var elCSearch = Ext.get("csearch");

elCSearch.setLocation(clientWidth — elCSearch.getWidth(),

Ext.get("cmain").getY() — cSearchHeight);

Они позиционируют контейнер csearch так, чтобы он в любом случае находился над верхним левым углом контейнера cmain. Кстати, здесь используется значение изначальной высоты контейнера csearch, которое мы сохранили ранее.

Теперь найдем объявление функции searchData и переделаем его так, как показано в листинге 21.6.

Web-сценарий выполняющий поиск

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

Перед поиском нам нужно удалить все пункты, уже присутствующие в списке search_result. Для этого мы сначала удаляем все обработчики событий, привязанные к гиперссылкам, находящимся в пунктах этого списка, а потом удаляем сами пункты:

var elSearchResult = Ext.get("search_result");

elSearchResult.select("A").removeAllListeners();

elSearchResult.dom.innerHTML = "";

elSearchResult.setDisplayed(false);

Напоследок скрываем список search_result.

Обратим внимание, как выполняется удаление пунктов списка search_result. Из главы 15 о библиотеке Ext Core мы знаем, что объект Web-обозревателя HTMLElement поддерживает свойство innerHTML, хранящее HTML-код, создающий содержимое данного элемента Web-страницы, в виде строки. Значит, чтобы удалить все содержимое данного элемента, мы можем получить соответствующий ему экземпляр объекта HTMLElement (через свойство dom объекта Ext Core Element) и присвоить его свойству innerHTML пустую строку. Что мы и делаем.

Web-сценарий выполняющий поиск

Фрагмент кода, приведенный в листинге 21.7, перекочевал из предыдущей реализации функции searchData практически без изменений. Мы уже знаем, что он делает.

Сформировав пункты списка search_result, открываем его:

elSearchResult.setDisplayed(true);

}

}

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

Функция cleanupSamples, которую мы объявили в главе 16, удаляет обработчики событий, привязанные к гиперссылкам раздела "См. также" и результатам поиска. Найдем объявляющий ее код и удалим выражения, которые убирают обработчики событий у гиперссылок результатов поиска, — ведь ранее мы поместили выполняющий это действие код в функцию searchData. После этого объявление функции cleanupSamples будет выглядеть так, как в листинге 21.8.

Web-сценарий выполняющий поиск

Так, бóльшую часть работы мы сделали. Осталось реализовать скрытие списка search_result при щелчке на содержимом Web-страницы.

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

Ext.getBody().on("click",

function(){ Ext.get("search_result").setDisplayed(false); });

Оно привязывает к событию click секции тела Web-страницы обработчик, который скрывает список search_result.

В главе 15 мы узнали, что некоторые события, в том числе и click, имеют обыкновение всплывать из элементов, в которых они изначально возникли, в их родители, затем – в родители их родителей и, наконец, в секцию тела Web-страницы. Обработчик события click, который мы только что привязали к секции тела Web-страницы, сработает независимо от того, в каком элементе Web-страницы возникло это событие, и список search_result в любом случае будет скрыт.

Но тут возникает очень неприятный момент: событие click кнопки запуска поиска также рано или поздно всплывет в секцию тела Web-страницы. Давайте посмотрим, что получится в результате. Посетитель нажмет кнопку запуска поиска, функция searchData сформирует пункты списка результатов и откроет этот список, после чего выполнится обработчик события click, привязанный нами к секции тела Web-страницы, который скроет список результатов. Непорядок!

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

Ext.get("find").on("click", searchData);

Оно привязывает обработчик к событию click кнопки, запускающей поиск. Изменим его следующим образом:

Ext.get("find").on("click", function(e){

searchData();

e.stopPropagation();

});

Новый обработчик события click сначала вызовет функцию searchData, собственно выполняющую поиск, а потом подавит всплытие возникшего события. Как видим, для этого используется метод stopPropagation объекта Ext Core EventObject (см. главу 15).

И еще. В обработчике события click пунктов полосы навигации (функция loadFragment) у нас подавляется всплытие этого события. Следовательно, если посетитель щелкнет на пункте полосы навигации (или гиперссылке раздела "См. также", или гиперссылке пункта в списке результатов поиска), событие click не всплывет в секцию тела Web-страницы, привязанный к нему обработчик не выполнится, и список search_result скрыт не будет. Нам нужно это исправить.

Найдем код, объявляющий функцию loadFragment, и добавим в самый его конец такое выражение:

Ext.get("search_result").setDisplayed(false);

Сохраним все исправленные файлы и проверим поиск в действии.