Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
107
Добавлен:
02.05.2014
Размер:
6.34 Mб
Скачать

 

Глава 10. Опережающий ввод

4Z1

// Отправить запрос Ajax

 

 

Ь

a j a x E n g i n e . s e n d R e q u e s t . a p p l y { ajaxEngine, c a l l P a r m s ) ;

 

 

 

 

m

Чтобы понять, что же делает данный метод, вначале необходимо рассмотреть механизм JavaScript, используемый в последней строке метода.

ajaxEngine.sendRequest.apply( ajaxEngine, callParms);

Здесь применяется метод applyO, доступный для всех функциональных объектов (подробности — в приложении Б). Проиллюстрируем его использование на простом примере.

Greeter,prototype.greetPeople = function(strl, str2)

{

alert('hello ' + strl + 'and ' + str2)

};

Предположим, что имеется экземпляр Greeter, именуемый friendlyperson, и в качестве аргумента ему нужно передать метод greetPeople{). Однако у нас нет параметров удобного для передачи вида, а имеется массив элементов people. В подобном случае выгодно использовать метод apply. Соответствующий код можно записать следующим образом:

var people = [ "Joe", "Sally" ]; friendlyPerson.greetPeople.apply( friendlyPerson, people);

Метод apply () преобразовывает массив, переданный как второй аргумент, в параметры метода первого класса и вызывает метод на объекте, переданном как первый параметр. Таким образом, приведенный код эквивалентен строчке

friendlyPerson.greetPeople( people[0], people[1));

Вернемся к нашей задаче. Нам требуется вызвать метод sendRequest () процессора ajaxEngine, принимающий в качестве первого параметра логическое имя запроса плюс переменное число строковых параметров вида key=value, представляющих параметры запроса. Здесь нужно быть очень аккуратными, поскольку мы запрашиваем параметры из различных источников и не знаем, сколько этих параметров. Рассмотрим код еще раз.

// О

v a r c a l l P a r m s - [ ] ;

c a l l P a r m s . p u s h ( t h i s . i d + ' ^ r e q u e s t ' ) ;

c a l l P a r m s . p u s h ( ' i g n o r e _ c a s e = ' + t h i s . o p t i o n s . i g n o r e C a s e ) ; // ©

v a r a d d i t i o n a l P a r m s = t h i s . o p t i o n s . r e q u e s t P a r a m e t e r s | | [ ] ; f o r ( v a r i=0 ; i < a d d i t i o n a l P a r m s . l e n g t h ; i++ )

c a l l P a r m s . p u s h ( a d d i t i o n a l P a r m s [ i ] ) ;

Массив параметров, отправляемый методу sendRequest () посредством apply, заселяется смешанной информацией: внутренним состоянием объекта, такими элементами, как идентификаторы и lastRequeststring, а также определенными свойствами объекта options (например, count, matchAnywhere, ignoreCase) О.

Тем не менее необходимо еще обеспечить механизм, позволяющий польза вателю компонента передавать помимо указанной информации внешние параметры ©. Для этого мы проверяем существование свойства объекта ор^ tions, именуемого requestParameters. Если его значение не равно null, оно предполагается равным массиву строк вида key=value. Этот массив последовательно проходится и добавляется к массиву callParms, уже заполненному параметрами компонента. Наконец, запрос отправляется.

ajaxEngine.sendRequest.apply{ ajaxEngine, callParms);

Все! С отправкой запроса мы разобрались. Теперь будем надеяться, что сервер находится в рабочем состоянии, получим ответный документ. Давайте разбираться, как мы будем обрабатывать ответ, когда он к нам поступит.

Предлагаемый текст — обработка ответа Ajax

Если мы собираемся обеспечить надежную отправку запросов, нам придется много поработать, поэтому лучше убедиться в надлежащей обработке ответного документа, иначе весь тяжкий труд будет напрасным. Напомним, что механизм ajaxEngine (Rico) направляет запрос к отправившему его методу ajaxUpdatet), передавая содержимое элемента <response>. Следовательно, необходимо написать метод a j axUpdate (), который будет точкой входа в процедуру обработки запроса. Метод ajaxUpdateO показан в листинге 10.24 вместе со своими вспомогательными методами разбора createSuggestionsO и getElementContent().

Листинг 10.24. Обработка ответа Ajax jMHHBHHHHHHBH^I

ajaxUpdate: function( ajaxResponse ) {

//Создать предположительные варианты this.createSuggestions( ajaxResponse ); if ( this.suggestions.length == 0 ) {

this.hideSuggestions{);

S( this.id + "_hidden").value = "";

}

//Создать и показать пользовательский интерфейс else {

this.updateSuggestionsDiv{);

this.showSuggestions();

this.updateSelection(0);

}

//Завершить обработку ответа this.handlingRequest = false; if ( this.pendingRequest ) {

this.pendingRequest = false;

this-lastRequestString = this.textlnput.value; // Отправить другой запрос

this.sendRequestForSuggestions();

}

},

createSuggestions: function(ajaxResponse) { this.suggestions * [];

var entries ~ ajaxResponse.getElementsByTagNamef'entry'); for ( var i = 0 ; i < entries.length ; i++ ) {

Глава 10. Опережающий ввод 423

var strText = this.getElementContent( entries[i1.getElementsByTagName('text') [ 0 ] );

var strValue = this.getElementContent{ entries[i].getElementsByTagName('value')[0]) ;

this.suggestions.push({ text: strText, value: strValue });

}

),

getElementContent: function(element) { return element.firstChild.data;

_ J

 

.

Поскольку мы собираемся сконцентрироваться исключительно на реализации в нужных местах механизмов Ajax, многие элементы будут рассмотрены на высоком уровне, а обработка ответа описана алгоритмически. Итак, сначала необходимо разобрать отклик посредством метода createSuggestions (), преобразовав его во внутреннее представление предлагаемых вариантов, содержащихся в свойстве suggestions. Это свойство представляет собой массив объектов, содержащих текст и значение (соответствуют элементам <text> и <value> каждого элемента <entry> XML-документа).

Остальная часть алгоритма, метод ajaxUpdate(), достаточно очевидна и понятна. Если предлагаемые варианты не найдены, всплывающее окно скрывается, а внутреннее значение, хранимое компонентом посредством скрытого поля, обнуляется. Если предполагаемые варианты найдены, создается раскрывающийся пользовательский интерфейс, заполненный предложениями, затем он отображается на экране с первой выделенной позицией. На этом этапе запрос считается обработанным, поэтому значение рассмотренного ранее свойства this.handlingRequest устанавливается равным false. Наконец, метод ajaxUpdatet) проверяет, имеются ли незавершенные запросы. Если да, значение метки pendingRequest устанавливается равным false, las - tRequestString присваивается текущее значение поля ввода и посредством sendRequestForSuggestions() инициируется следующий цикл запроса.

Таким образом, к концу третьего дня мы получили полный цикл запроса/ответа с поддержкой Ajax. За сегодняшний день сделано довольно много: мы разобрались в структуре с открытым исходным кодом, которая позволила полностью "активизировать Ajax" (требование 7), а также гарантировали возможность настройки и поддержки нескольких экземпляров на одной странице (требования 2 и 3). Собственно созданием, размещением, показом и сокрытием пользовательского интерфейса мы займемся на пятый день. Пока же рассмотрим события компонента и подготовим обработку действий с клавиатурой и мышью.

10.5.4. День 4: обработка событий

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

424 Часть IV. Aiax в примерах

метода injectSuggestBehavior{). Данный код инициирует все модификации DOM существующей разметки, включая обработку событий, дополнительный ввод, и контейнер для предположений. Все эти модификации програь*: мируются, HTML-код страницы затрагиваться не будет (см. требование 1) Введение требуемого поведения показано в листинге 10.25.

Листинг 10.25. Введение требуемого поведения

injectSuggestBehavior:

function() {

 

 

if ( t h i s . i s I E ) {

 

 

//

Убрать взаимодействие

с I n t e r n e t E x p l o r e r

 

 

t h i s . t e x t l n p u t , a u t o c o m p l e t e = "off";

 

 

}

 

 

 

 

 

v a r

JceyEventHandler

=

 

 

 

new T e x t S u g g e s t K e y H a n d l e r ( t h i s ) ;

//

Создать контроллер

 

 

 

 

new

I n s e r t i o n . A f t e r (

t h i s . t e x t l n p u t ,

 

 

 

 

' < i n p u t t y p e = " t e x t " i d - " ' + t h i s . i d +

 

 

 

 

' _ p r e v e n t t s u b m i t ' +

 

 

 

 

' " s t y l e = " d i s p l a y : n o n e " / > ' ) ;

 

 

new

I n s e r t i o n . A f t e r (

t h i s . t e x t l n p u t ,

 

 

 

 

' < i n p u t t y p e = " h i d d e n " name="'+

 

 

 

 

t h i s . i d + ' _ h i d d e n ' +

 

 

 

 

1Tr

i d = ' " + t h i s . i d + l _ h i d d e n r + " ' / > ' );

 

 

t h i s . c r e a t e S u g g e s t i o n s D i v f ) ;

//

Создать пользовательский интерфейс

},

 

 

 

 

я

Данный метод вначале проверяет, не используется ли Internet Explorer. Если используется, то собственному свойству autocomplete присваивается значение off. Благодаря этому встроенные возможности автоматического заполнения не взаимодействуют с нашим всплывающим окном. Далее создается объект TextSuggestKeyHandler, который будет перенаправлять события нужным методам. Действительно, механика событий достаточно запутана, поэтому мы выделяем поведение в отдельный объект, который рассмотрим чуть позже. Следующий метод вводит несколько входных элементов в разметку. Напомним, что в предыдущем цикле разработки кода мы добавили скрытое поле ввода для хранения значения компонента и невидимое текстовое поле, препятствующее отправке формы при нажатии клавиши <Enter>. Поскольку первое требование технической задачи запрещает вмешиваться в HTML-код, вся "грязная работа" выполняется программно — с помощью двух вызовов Insertion.After(). Возможность использования Insertion. After () появилась благодаря библиотеке Prototype. Наконец, вызывается функция createSuggestionsDiv(), создающая элемент div, вмещающий пользовательский интерфейс с предлагаемыми вариантами.

Объект TextSuggestKeyHandler

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

Глава 10. Опережающий ввоо 4*э

01 можно еще отделить все компоненты дизайна, создав явные классы модели 1( представления и обеспечив полный шаблон MVC Это предлагается сделать читателю в качестве самостоятельного упражнения, но в главе 13 будет показано, как разбить архитектуру приложения чтения RSS-сообщений на набор классов, согласующихся с традиционным шаблоном MVC.

Контроллер создается точно так же, как и основной класс, — с использованием Class.create() и метода i n i t i a l i z e ( ) . Конструктор TextSuggestKeyHandler показан в листинге 10.26.

Листинг 10.26. Конструктор TextSuggestKeyHandler TextSuggestKeyHandler = Class.create(); TextSuggestKeyHandler.prototype = {

initialize:

function( textSuggest ) {

this.textSuggest = textSuggest;

this.input = this.textSuggest.textlnput;

// Ссылка на

TextSuggest

t h i s . a d d K e y H a n d l i n g ( ) ;

 

h

 

 

//

остальная часть API

_ Ь

 

 

щ

В процессе создания контроллер использует ссылку на компонент опережающего ввода, а также "родное" поле ввода HTML-формы. Затем с помощью this.addKeyHandlingO он добавляет в поле ввода обработчики событий. Метод addKeyHandling() показан в листинге 10.27.

Листинг 10.27. Обработчик действий с клавиатурой

addKeyHandling: function() { this.input.onkeyup =

this.keyupHandler.bindAsEventListener(this); this.input.onkeydown =

this.keydownHandler.bindAsEventListener(this); this.input.onblur =

this.onblurHandler.bindAsEventListener(this); if ( this.isOpera )

this.input,onkeypress = this.keyupHandler.bindAsEventListener(this);

В данном методе устанавливаются все события, наступление которых требуется отслеживать, а также код для браузера Opera, упоминавшийся в первом цикле разработки данного сценария. Напомним, что метод bindAsEventListener ( ) представляет собой механизм замыкания, полученный благодаря библиотеке Prototype. Данный механизм позволяет нашим обработчикам вызывать методы первого класса на контроллере и сводит к общему знаменателю модели событий Internet Explorer и W3C. Очень хорошо. Методы keyupHandlerO, keydownHandler(), onblurHandler () и их вспомогательные методы представляют собой реструктуризированный вариант уже рассмотренного кода (с минимальными изменениями). Все эти методы будут описаны

ниже с указанием их отличий от первоначального сценария. Начнем с обсу>к- дения метода keydownHandler(), показанного Б листинге 10.28, и того, как он обрабатывает выделение.

keydownHandler: function(e) { var upArrow = 38;

var downArrow = 4 0 ;

if ( e.keyCode =- upArrow ) { this.textSuggest.moveSelectionUp();

setTimeout( this.moveCaretToEnd.bind(this), 1 );

}

 

 

 

else if ( e.keyCode == downArrow )

{

 

 

this.textSuggest.moveSelectionDown();

}

 

 

—h

 

.

 

 

 

 

Наиболее существенные отличия от исходного сценария с точки зрения функциональных возможностей претерпела обработка клавиш со стрелками. В компоненте TextSuggest клавиши со стрелками управляют движением выделения, основываясь на событии onkeydown, а не на onkeyup. Это сделано исключительно для повышения практичности. Иногда пользователя сбивает с толку то, что выделение остается на своем месте при нажатии клавиши и начинает перемещаться после того, как клавиша отпущена. В общем, перемещение выделения обрабатывается методом keydownHandler (). Обратите внимание на то, что методы управления выделением являются методами компонента TextSuggest. Поскольку контроллер во время создания записал ссылку на компонент, он может вызывать эти методы посредством объектной ссылки t h i s . textSuggest. Для полноты изложения мы приводим в листинге 10.29 методы управления визуальным выделением.

Листинг 10.29. Методы TextSuggest, отвечающие за визуальное выделение п

raoveSelectionUp: function{)

{

if ( this . selectedlnde x > 0

) {

this . updateSelection(this . selectedlndex - 1);

}

ь

moveSelectionDown: function() {

if ( this.selectedlndex < (this.suggestions.length - 1) ) { this.updateSelection<this.selectedlndex + 1);

}

ь

updateSelection: function(n) {

var span = $(this.id + "_"+this.selectedlndex); if (span){

span.style.backgroundColor = ""; // Очистить предыдущее выделение

}

this.selectedlndex = n;

var span = 5(this.id+"_"+this.selectedlndex); if (span){

span.style.backgroundColor = this,options.selectionColor;

}

Реальную работу по изменению визуального состояния выделенного элемента выполняет метод updateSelection(). Он обновляет элемент span, созданный в списке выбора (соответствующий код мы напишем на пятый день), и устанавливает его свойство style.backgroundColor равным значению, заданному как options.selectionColor в объекте Configuration нашего компонента.

Перед тем как закрыть тему обработки нажатия клавиш, следует учесть еще один момент. Поскольку при обработке действий с клавишами мы учитываем их нажатие, а не отпускание, необходимо изменить значение клавиши со стрелкой вверх с поведения по умолчанию на перемещение назад каретки в текстовом поле. Для этого применяется метод moveCaretToEndt), вызываемый с миллисекундной задержкой (реализована с помощью setTimeout). Реализация метода moveCaretToEndt) приведена в листинге 10.30.

Листинг 10.30. Метод moveCaretToEnd () компонента TextSuggest • ' 9 | Щ Н moveCaretToEnd: function() {

v a r роз = t h i s . i n p u t . v a l u e . l e n g t h ; if ( t h i s . i n p u t . s e t S e l e c t i o n R a n g e ) {

t h i s . i n p u t . s e t S e l e c t i o n R a n g e ( p o s , p o s ) ;

}

e l s e i f ( t h i s . i n p u t . c r e a t e T e x t R a n g e ) {

v a r m = t h i s . i n p u t . c r e a t e T e x t R a n g e { ) ; m . m o v e S t a r t ( ' c h a r a c t e r 1 , p o s ) ; ra.collapse();

m . s e l e c t ( ) ;

Ь

}

ж

Рассмотрим теперь обработку отпускания клавиш. Реализация отпускания немного проще, чем реализация нажатия клавиш. Все, что требуется, — это перенаправить событие, учитывая текст в поле ввода и нажатую клавишу. Рассмотрим подробнее код, приведенный в листинге 10.31.

Листинг 10.31. Обработка в TextSuggest отпускания клавиш

,

у

keyupHandler: function(e) {

 

 

 

if ( this.input.length == 0 && !this.isOpera )

 

 

this.textSuggest.hideSuggestions();

 

 

if

( 'this.handledSpecialKeys(e) )

 

 

this.textSuggest.handleTextlnput() ;

 

 

Ь

 

 

 

 

 

handledSpecialKeys: function(e)

{

 

 

var

enterKey =

13;

 

 

 

var

upArrow =

38;

 

 

 

var downArrow • 40;

 

 

 

if

( e.keyCode == upArrow II

e.keyCode == downArrow )

{

 

1 return true;

else if ( e.keyCode == enterKey ) { this.textSuggest.setInputFromSelection{); return true;

}

return false;

_ ±

 

^

 

Обработчик отпускания клавиш вначале проверяет, содержится ли текст в поле ввода. Если нет, он сообщает компоненту TextSuggest скрыть всплывающий список предлагаемых вариантов. Далее обработчик проверяет, не была ли нажата одна из специальных клавиш: клавиша со стрелкой вверх, клавиша со стрелкой вниз или <Enter>. Если была нажата одна из клавиш со стрелками, метод не выполняет никаких действий, поскольку нажатие этой клавиши уже было обработано. Однако если была нажата клавиша <Enter>, метод сообщает компоненту TextSuggest установить входное значение на основе выбранной в текущий момент позиции списка предположений. Наконец, если поле ввода содержит значение и нажатая клавиша не является специальной, то обработчик сообщает компоненту TextSuggest о наличии некоторого входа, который нужно обработать с помощью метода textsugcrest.handleTextInput(). Данный метод компонента TextSuggest в конечном счете активизирует структуру Ajax, которую мы успешно настраивали вчера. Код обработчика handleText!nput() представлен в листинге 10.32.

;'• Листинг 10.32. Обработчик ввода текста "ШЯШШШИИВ;. > handleTextlnput: function{) {

var previousRequest = this.lastRequestString;

//

Предыдущее запрашиваемое значение

 

 

 

 

 

t h i s . l a s t R e q u e s t S t r i n g =

 

 

 

 

 

 

t h i s . t e x t I n p u t . v a l u e ;

 

 

 

 

 

//

Текущее запрашиваемое

значение

 

 

 

 

 

 

if { t h i s . l a s t R e q u e s t S t r i n g == "" )

 

 

 

 

 

t h i s . h i d e S u g g e s t i o n s ( ) ;

 

 

 

 

 

 

e l s e if ( t h i s . l a s t R e q u e s t S t r i n g != p r e v i o u s R e q u e s t ) {

 

 

 

 

t h i s . s e n d R e q u e s t F o r S u g g e s t i o n s ( ) ;

 

 

 

//

Запрос данных средствами Ajax

 

 

 

 

 

 

}

 

 

 

 

 

 

- ±

 

 

 

 

 

 

 

M

Вначале

метод handleTextlnputО

устанавливает

значение

локальной

переменной

previousRequest

равным

предыдущему

значению

t h i s . l a s t -

RequestString. Затем он устанавливает значение свойства lastRequestString равным текущему содержимому поля ввода, так что теперь можно сравнить эти два значения и убедиться, что мы не пытаемся запросить ТУ информацию, которая у нас уже есть. Если запрос представляет собой пустую строку, всплывающий список будет скрыт. Если запрос отправлен для получения новой информации, метод handleTextlnput () вызывает ме-

Глава 10. Опережающий ввод 429

т од sendRequestForSuggestions() (который мы написали вчера) для вызова основанного на Ajax источника данных и получения с сервера ряда предположений. Если запрос идентичен последнему посланному запросу, никакие действия не предпринимаются. Похоже, что наконец-то фрагменты начинает собираться в общую картину. Создание, настройка конфигурации, работа инфраструктуры Ajax, обработка событий — мы действуем так, как будто знали, что придется делать. Идем впритык — сейчас уже четвертый день работы!

Класс контроллера должен охватывать еще один класс — обработчик событий onblur, который представляет собой очень простой метод, устанавливающий значение текстового поля согласно текущему выделению и скрывающий предлагаемые варианты. Его реализация выглядит следующим образом:

onblurHandler: function(e) {

if ( this.textSuggest.suggestionsDiv.style.display == " ) this.textSuggest.setlnputFromSelection();

this.textSuggest.hideSuggestions();

}

Обработчики onblurHandler и handledspecialKeys обращаются к методу компонента TextSuggest, который мы еще не рассматривали, — setlnputFromSelection ( ). По сути, этот метод делает то же, что делала ранее функция SetText () — принимает выделенное в текущий момент предположение; присваивает свой текст полю ввода, а значение — скрытому полю; скрывает список предположений. Реализация этого метода приведена ниже.

setlnputFromSelection: function() {

var hiddenlnput « $( this.id + "_hidden" );

var suggestion ~ this.suggestions[ this.selectedlndex ]; this.textlnput.value = suggestion.text;

//Обновить видимое значение hiddenlnput.value = suggestion.value;

//Обновить скрытое значение

this.hideSuggestions();

}

Возможно, для выполнения всего, что было запланировано на сегодня, пришлось немного поработать сверхурочно. Однако в результате мы создали класс controller, обрабатывающий все, что касается управления событиями. Для автоматического создания замыканий и унификации моделей событий Internet Explorer и W3C мы использовали метод bindAsEventListener() библиотеки Prototype. Мы реализовали обработчики нажатия/отпускания клавиш, скрывающие в себе все сложности обработки выделенной позиции и обычного текстового ввода. Мы гарантировали, что запросы будут отправляться только для получения новой информации; разобрались с показом и сокрытием в нужные моменты пользовательского интерфейса; программно обновили DOM для управления скрытым входным значением и невидимым текстовым полем, предотвращающим отправку формы при нажатии клавиши <Enter>. Кроме того, мы обработали обновление скрытого и видимого значений компонента TextSuggest. На пятый день мы доведем до ума и реструктуризируем наш компонент, реализовав все методы, требуемые для создания

430 Часть IV Ajax в примерах

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

10.5.5. День 5: пользовательский интерфейс всплывающего окна с предлагаемыми вариантами

Теперь, когда мы полностью вошли в работу, пришло время разобраться со всеми незавершенными моментами. Пока что мы создали инфраструктуру для обеспечения настроек и значений по умолчанию, обработку запросов и ответов Ajax, а также события, которые все это связывают. Остались вопросы графической реализации. Относительно пользовательского интерфейса необходимо решить следующие вопросы.

Создание пользовательского интерфейса всплывающего окна с предлагаемыми вариантами. Это подразумевает создание элемента div для списка

иэлемента span для каждого варианта.

Размещение всплывающего окна в нужном месте.

Заполнение всплывающего окна предлагаемыми вариантами.

Показ и сокрытие вариантов.

Создание всплывающего окна с предлагаемыми вариантами

Вернемся немного назад и рассмотрим реализацию метода injectSuggestBehavior (). Напомним, что данный код представлял собой точку входа для всех манипуляций DOM, производимых компонентом TextSuggest.

injectSuggestBehavior:

function{) {

// Введение

поведения DOM HTML . . .

t h i s . c r e a t e S u g g e s t i o n s D i v ( ) ;

Ь

 

 

В последней

строке

метода injectSuggestBehavior() вызывается ме-

тод createSuggestionsDiv(), создающий самый внешний контейнер div всплывающего окна с предлагаемыми вариантами. Поскольку это контейнер всех артефактов GUI, именно с него логично начать рассмотрение ко-

да пользовательского

интерфейса. Подробности его реализации показаны

в листинге 10.33.

 

 

 

 

Листинг 10.33. Создание пользовательского интерфейса окна с вариантами

createSuggestionsDiv:

function{)

{

this.suggestionsDiv

= document.createElement("div");

// О Создать элемент div

 

this.suggestionsDiv.className -

this.options.suggestDivClassName;

// © Определить стиль элемента div

var divStyle =

this.suggestionsDiv.style;

// © Добавить стиль поведения

 

divStyle.position

=

'absolute1;

 

divStyle.zlndex

=

101;

 

divStyle.display

 

-

"none";