Тверской государственный университет
Опубликован: 13.09.2006 | Доступ: свободный | Студентов: 5133 / 388 | Оценка: 4.23 / 3.83 | Длительность: 28:12:00
Специальности: Программист, Менеджер
Лекция 11:

Создание интерактивных Web-документов

Создание программного кода

С нетерпением ждал, когда же, наконец, можно перейти к описанию программного кода, связанного с этой страницей. Этот момент наступил. Что должен делать это код, уже говорилось. На серверной стороне он должен сформировать интерфейсный элемент - список, содержащий названия всех имеющихся книг. На клиентской стороне необходимо в скрытые поля формы передать информацию о выборе пользователем из списка той или иной книги. Ну и, конечно, нужно обеспечить передачу информации серверу и переход на другую страницу при нажатии командных кнопок.

Код, исполняемый на сервере

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

<SCRIPT LANGUAGE=vbscript RUNAT=Server>
'**********************************************************
'** Объявления глобальных переменных, процедур и функций **
'************ на серверной стороне ************************ 
'Задание объектов ADODB - Connection, Command, Recordset
Dim Con1	'Объект ADODB, задающий соединение
Dim Cmd1	'Объект ADODB, задающий команду
Dim Rst1	'Объект ADODB, задающий набор записей

Sub CreateConnection()
	'Создание соединения с тестовой базой данных Access
	Dim strConnStr	'Строка соединения
	If Con1.State <> 1 Then
		strConnStr="Provider=Microsoft.jet.oledb.4.0; " & _
			"Data Source =c:\Ch20\dbPP2000.mdb"
		Con1.Open strConnStr
	End If
End Sub 'CreateConnection
Sub CreateRstBooks()
	'Создание набора записей по данным хранимого запроса
	With Cmd1
		.ActiveConnection = Con1
		.CommandText = "Select * From [список книг]"
		.CommandType = 1	'adCmdText
		Set Rst1 =.Execute		
	End With
End Sub 'CreateRstBooks
Sub CreateOptions()
	'Програмное создание списка SelectBook
	'Заполнение элементов этого списка по данным набора записей
	Dim str1	'Строковая переменная - автор и название книги 
	Dim str2,str3,str4	'Строковые константы 
		str2 = "<OPTION value = """
		str3= """>"
		str4="</OPTION>"
	With Rst1
		'Проход по набору записей и формирование элементов списка
		.MoveFirst
		'Создание элемента SelectBook
		Response.Write("<Select id=""SelectBook""" &	_
			"Style= ""position:absolute; top:100; left:170"" > ")
		Do While Not .EOF
			str1 = Rst1("Автор") & ": " & Rst1("Название")
			Response.Write(str2 & str1 & str3 & str1 & str4)
			.MoveNext
		Loop
		Response.Write("</SELECT>")
	End With
End Sub 'CreateOptions
</SCRIPT>

Ну а теперь, как всегда, некоторые комментарии к этому коду. Работа с базой данных будет вестись, как и положено, через хорошо знакомые объекты ADO. Глобальные переменные Con1, Cmd1, Rst1, задающие эти объекты, уже не один раз встречались в наших примерах. Это же касается и процедуры CreateConnection, устанавливающей соединение с базой данных. В процедуре CreateRstBooks создается набор записей, содержащий данные о книгах. Подобные процедуры также встречались неоднократно при рассмотрении объектов ADO. На одно обстоятельство хочу обратить внимание. Для получения информации из базы данных используется хранимый запрос с именем "список книг". Вот его SQL-текст:

SELECT Книги.Автор, Книги.Название
FROM Книги
ORDER BY Книги.Автор;

При работе с базами данных на Web-страницах рекомендую использовать всюду, где можно, хранимые процедуры. В базе данных Microsoft Access, с которой я работаю во всех примерах данной книги, роль хранимых процедур играют хранимые запросы. Помимо многих других преимуществ такой способ хорош еще и тем, что надежно работает. В то же время при использовании других приемов работы с объектами ADO зачастую возникали ошибки там, где их не должно было бы быть.

Процедура CreateOptions по данным полученного набора записей программно создает интерфейсный объект - раскрывающийся список и определяет элементы этого списка. Если говорить более точно, то процедура динамически дописывает к имеющемуся HTML-коду страницы новый фрагмент HTML-кода, определяющий тег Select. Метод Write серверного объекта Response выполняет эту задачу. Когда браузер получит страницу от сервера и начнет выполнять присланный HTML-код страницы, то он создаст в дополнение к элементам определенным при проектировании страницы, и динамически созданный сервером элемент SelectBook.

Мы рассмотрели декларативную часть серверного кода. Теперь давайте взглянем на исполняемый код. Он небольшой и сводится к инициализации переменных и вызову рассмотренных нами процедур. Вот он:

<body>
<SCRIPT LANGUAGE=vbscript RUNAT=Server>
'**********************************************************
'** Исполняемый код на серверной стороне **
'************ на серверной стороне ************************ 
'Формирование глобальных объектов
Set Con1=Server.CreateObject("ADODB.Connection")
Set Cmd1=Server.CreateObject("ADODB.Command")
Set Rst1=Server.CreateObject("ADODB.Recordset")

'Этот оператор моделирует регистрацию пользователя.
Session("UserId")=6
'Получение информации о книгах из базы данных
'и формирование списка - элемента SelectBook
	'Создать соединение с базой данных
	CreateConnection()
	'Получить набор записей
	CreateRstBooks()
	'Создать интерфейсный элемент - список SelectBook
	CreateOptions

</SCRIPT>

Из этого кода хочу обратить внимание на оператор, создающий объект Session("UserId"). Реально этот объект создается на начальной индексной странице при регистрации пользователя. Поскольку я не собираюсь описывать индексную страницу, то решил промоделировать ее работу, введением этого оператора, явным образом создавая объект Session и присваивая конкретное значение Id пользователю, работающему со страницей.

Разбор кода, выполняемого на серверной стороне, закончен, и можно переходить к коду, выполняемому на стороне клиента. Возможно, следовало бы привести полный HTML-код страницы, передаваемой клиенту, но я ограничусь только программным кодом.

Код, исполняемый на стороне клиента

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

Программирование на клиентской стороне в большей степени является программированием, управляемым событиями. Это и понятно - здесь расположены элементы управления, с которыми работает пользователь, а именно он, его действия при работе с документом являются источником возникновения событий. Поэтому основу декларативной части клиентского кода составляют, как правило, процедуры-обработчики событий, возникающих с интерфейсными объектами и другими объектами, расположенными на странице. По этой причине нет необходимости в исполняемом фрагменте кода, хотя он и может присутствовать. Но более естественно для данного стиля программирования для инициирования вычислений иметь процедуру, обрабатывающую событие Load, которая автоматически будет вызываться при открытии страницы. Когда же пользователь начнет работать, то будут вызываться и другие обработчики событий. А теперь взгляните на декларативный код клиентской части нашей страницы. Конечно же, он включает процедуры-обработчики различных событий, возникающих с объектами страницы. Вот этот код:

<SCRIPT LANGUAGE=vbscript>

<!--
'**********************************************************
'** Объявления глобальных переменных, процедур и функций **
'************ на стороне клиента ************************** 
Sub Window_onLoad()
	'Обработчик события Load - вызывается при открытии страницы
	'Заполняем скрытые поля формы - автор и название книги
	FromSelectToHiddenFields
End Sub 'Window_onLoad

Sub SelectBook_onChange
	'Обработчик события Change - вызывается при выборе книги
	'в списке SelectBook
	'Заполняем скрытые поля формы - автор и название книги
	FromSelectToHiddenFields
End Sub 'SelectBook_onChange
 
Sub btnLookmyQ_onClick
	'Обработчик события Click - вызывается при нажатии
	'командной кнопки "Посмотреть мои вопросы и ответы на них" 
	'Вызов страницы qomFromBase с показом вопросов и ответов
	CallNextPage("LookmyQ")
End Sub 'btnLookmyQ

Sub btnLookAllQ_onClick
	'Обработчик события Click - вызывается при нажатии
	'командной кнопки "Посмотреть все вопросы и ответы на них" 
	'Вызов страницы qomFromBase с показом всех вопросов и ответов
	CallNextPage("LookAllQ")
End Sub 'btnLookAllQ

Sub btnLookOM_onClick
	'Обработчик события Click - вызывается при нажатии
	'командной кнопки "Посмотреть отзывы и оценки"	
	'Вызов страницы qomFromBase с показом отзывов и оценок
	CallNextPage("LookOM")
End Sub 'btnLookOM

Sub FromSelectToHiddenFields()
	'Передача данных от выбранного элемента списка книг
	'к скрытым полям формы
	Dim str1,str2,str3	'строковые переменные
	Dim Ind1	'индекс вхождения
	'Разбор строки с названием книги и фамилией автора
	str1=SelectBook.Value
	Ind1= InStr(str1,":")-1
	str2= Left(str1,Ind1)
	str3 = Mid(str1,Ind1+2)
	'Запись данных в поля формы
	frmMain.Author.value = str2
	frmMain.Title.value = str3
	'MsgBox(frmMain.Author.value & frmMain.Title.value)
End Sub 'FromSelectToHiddenFields

Sub CallNextPage(NameOfButton)
	'NameOfButton - Имя нажатой кнопки
	'Вызов страницы qomFromBase с передачей параметров:
	'имени нажатой кнопки, названия и автора книги
	Dim str1, str2 'строковые пременные
	str1=frmMain.Author.value
	str2=frmMain.Title.value
	Window.navigate "qomFromBase.asp" & _
	"?btnName=" & NameOfButton & "&Author="	& str1 & "&Title=" & str2 
End Sub 'CallNextPage
-->
</SCRIPT>

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

Когда на клиентской стороне открывается страница, возникает событие Load объекта Window и вызывается соответствующая процедура. Действие ее достаточно просто - она обращается к процедуре FromSelectToHiddenFields, которая значение элемента SelectBook преобразует в название книги и фамилию автора и заполняет этими данными скрытые поля формы.

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

Комментировать работу процедуры FromSelectToHiddenFields вряд ли имеет смысл - обычная работа с объектами и строковыми переменными.

Следующие три процедуры в этом тексте - это обработчики события Click для трех объектов, задающих разные командные кнопки. Напомню, что ожидаемое действие при нажатии этих кнопок аналогично действию при нажатии кнопки Submit - должна быть вызвана некоторая страница узла и этой странице должны быть переданы параметры, необходимые для выполнения на сервере запрашиваемого действия. Все три обработчика устроены одинаково - вызывают процедуру CallNextPage, передавая ей в качестве параметра имя нажатой кнопки.

Процедура CallNextPage обеспечивает связь с сервером. Вызов метода Navigate объекта Window позволяет достаточно просто решить требуемую задачу. Метод позволяет задать вызываемую страницу сервера и передать ей параметры. Заметьте, вызывается страница qomFromBase, которая предназначена для того, чтобы по запросу пользователя читать данные из базы данных и отображать их в нужном виде на клиентском компьютере. Три параметра передаются этой странице - имя нажатой командной кнопки, фамилия автора и название книги. Первый параметр определяет, по сути, запрос пользователя - хочет ли он просмотреть по выбранной им книге ответы на его вопросы, все вопросы и ответы или все отзывы и оценки.

Вот и весь программный код, обеспечивающий интерактивность нашей странице. Я рассмотрел создание интерфейса страницы и создание кода, поддерживающего этот интерфейс. На этом я заканчиваю рассмотрение вопросов создания основной страницы нашего узла. Думаю, что она является достаточно типичным примером интерактивной Web-страницы - примером страницы, в которой пользователь запрашивает необходимую ему информацию. Чтобы пример был законченным, нужно еще рассмотреть, как устроены страницы qomToBase и qomFromBase, организующие реакцию на запросы пользователя. Но прежде, чем перейти к их рассмотрению, хочу сказать несколько слов о том, как я придаю структуру программному коду.

Ольга Гафарова
Ольга Гафарова

Добрый день. Подскажите формулы при решении задачи на рис. 2.2 в лекции №2. Закон Ома, какие должны использоваться формулы для I и R

Курс: Основы офисного программирования и документы Excel

Серегй Лушников
Серегй Лушников