В этой главе на примере работы с записной книжкой будут рассмотрены три способа организации из сценария диалога с пользователем.
Во-первых, мы еще раз подробно остановимся на том, как можно использовать параметры командной строки для запуска различных заданий из многозадачного WS-файла, который в нашем случае будет реализовывать несколько функций для работы с записной книжкой.
Во-вторых, для того же WS-файла мы создадим кнопочное (командное) меню, в котором пользователь сможет выбрать нужное ему действие с помощью ввода определенных символов в диалоговом окне.
Наконец, будет показано, как можно организовать в сценарии полноценный пользовательский интерфейс с помощью HTML-форм и браузера Internet Explorer.
В качестве примера рассмотрим сценарий для работы с записной книжкой в XML-формате (структура файла book.xml, в котором хранится записная книжка, описана в предыдущей главе), в котором будут реализованы следующие функции:
□ просмотр всех записей в алфавитном порядке;
□ поиск записей по фамилии;
□ добавление и удаление записей.
Каждая из этих задач реализуется в виде отдельного задания в файле PhoneBook.wsf (листинг 7.1).
…
…
…
…
Некоторые функции (например, настройка пути к XML-файлу) должны присутствовать во всех заданиях, поэтому такие общие функции мы вынесем в отдельный файл Usage.js, который будет подключаться в каждом из заданий следующим образом:
В файл Usage.js помещены следующие функции:
□ конструктор объекта
Person
(одна запись из книжки);
□ функция
GetTagVal(obj, tgName)
, которая возвращает значения тега tgName
XML-элемента obj
;
□ функция
PersonToArray(XNode)
, которая заполняет поля экземпляра PersonRec
объекта Person
данными из соответствующих XML-элементов и добавляет сформированную запись в массив PersonArr
;
□ функции
TopReport(Mess)
и BottomReport(Mess)
, с помощью которых в выходной файл печатается заголовок отчета и итоговая информация соответственно;
□ функция
PrintPerson(PersRec)
, в которой происходит вывод данных из полей объекта PersonRec
в выходной файл;
□ функция
MakeOut()
, которая обеспечивает запуск Блокнота и открывает в нем выходной файл;
□ функция InitPath(), в которой строятся пути к XML-файлу, содержащему данные, и выходному файлу.
Usage.js объявляются глобальные переменные и константы. Полностью содержимое файла Usage.js приведено в листинге 7.2.
/*******************************************************************/
/* Имя: Usage.js */
/* Язык: JScript */
/* Описание: Общие функции для записной книжки */
/*******************************************************************/
//Объявляем переменные
var
WshShell,FSO,
BasePath, //Путь к текущему каталогу
PathBook, //Путь к файлу с данными
PathOut, //Путь к выходному файлу
FBook, //Файл с данными
FOut, //Выходной файл
NomRec=0, //Счетчик количества записей
PersonRec, //Объект для хранения данных об одном человеке
PersonArr; //Массив для хранения объектов PersonRec
ForWriting=2; //Константа для создания выходного файла
//Инициализируем константы для диалоговых окон
var vbYesNo=4,vbQuestion=32,vbInformation=64,vbYes=6,vbOkOnly=0;
//Конструктор объекта Person
function Person(LastName,Name,Phone,Street,House,App,Note) {
this.LastName=LastName; //Фамилия
this.Name=Name; //Имя
this.Phone=Phone; //Телефон
this.Street=Street; //Улица
this.House=House; //Дом
this.App=App; //Квартира
this.Note=Note; //Примечание
}
//Определение значения тега tgName XML-элемента obj
function GetTagVal(obj, tgName) {
var ElemList;
//Создаем коллекцию дочерних для obj элементов, которые
//задаются тегом tgName
ElemList=obj.getElementsByTagName(tgName);
//Проверяем, есть ли в коллекции ElemList элементы
if (ElemList.length>0)
//Возвращаем значение тега tgName
return ElemList.item(0).text
else return "";
}
//Заполнение нового элемента массива
function PersonToArray(XNode) {
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName=GetTagVal(XNode,"LastName");
PersonRec.Name=GetTagVal(XNode,"Name");
PersonRec.Phone=GetTagVal(XNode,"Phone");
PersonRec.Street=GetTagVal(XNode,"Street");
PersonRec.House=GetTagVal(XNode,"House");
PersonRec.App=GetTagVal(XNode,"App");
PersonRec.Note=GetTagVal(XNode,"Note");
//Сохраняем объект PersonRec в массиве
PersonArr[PersonArr.length]=PersonRec;
}
//Запись в выходной файл заголовка отчета
function TopReport(Mess) {
FOut.WriteLine(Mess);
FOut.WriteLine("--------------------");
FOut.WriteLine("");
}
//Запись в выходной файл итоговой информации
function BottomReport(Mess) {
FOut.WriteLine(Mess);
}
//Запись данных из объекта Person в выходной файл
function PrintPerson(PersRec) {
FOut.WriteLine("Фамилия: "+PersRec.LastName);
FOut.WriteLine("Имя: "+PersRec.Name);
FOut.WriteLine("Телефон: "+PersRec.Phone);
FOut.WriteLine("Улица: "+PersRec.Street);
FOut.WriteLine("Дом: "+PersRec.House);
FOut.WriteLine("Кв.: "+PersRec.App);
FOut.WriteLine("Заметки: "+PersRec.Note);
FOut.WriteLine("*********************************");
NomRec++;
}
//Просмотр содержимого выходного файла в Блокноте
function MakeOut() {
//Закрываем выходной файл
FOut.Close();
//Открываем выходной файл в Блокноте
WshShell.Run("notepad "+PathOut,1);
}
//Построение путей к файлам
function InitPath() {
BasePath=WshShell.CurrentDirectory+"\\";
//Путь к файлу с данными
PathBook=BasePath+"book.xml",
//Путь к выходному файлу
PathOut=BasePath+"out.txt";
}
/************* Конец *********************************************/
Также в отдельный файл WSHInputBox.vbs мы поместим функцию
WSHinputBox(Message, Title)
на языке VBScript, с помощью которой из JScript-сценариев будет выводиться диалоговое окно со строкой ввода (напомним, что ни язык JScript, ни объектная модель WSH такой функции не предоставляют):
Function WSHInputBox(Message,Title)
'Выводим диалоговое окно со строкой ввода
WSHInputBox = InputBox(Message,Title)
End Function
Сами задания из файла PhoneBook.wsf составлены (с некоторыми изменениями, на которых мы подробно останавливаться не будем) из одиночных сценариев, которые были рассмотрены в предыдущей главе: см. листинг 6.3 (просмотр всех записей в алфавитном порядке), листинг 6.4 (добавление записей) и листинг 6.5 (поиск записей по фамилии и удаление записей).
В листинге 7.3 приводится полный текст сценария PhoneBook.wsf.
//Создание массива объектов Person
function FileToArray() {
var XML,Root,NomRec,CurrNode,ex,i;
//Создаем массив PersonArr
PersonArr=new Array();
//Создаем объект XML DOM
XML = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-документ из файла
XML.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//Перебираем все дочерние элементы первого уровня вложенности
//для корневого элемента
for (i=1; i<=Root.childNodes.length-1;i++) {
//Выделяем в коллекции XML-элементов i-й элемент
CurrNode=Root.childNodes.item(i);
//Добавляем новый элемент в массив объектов Person
PersonToArray(CurrNode);
}
}
//Сортировка массива и вывод его содержимого в выходной файл
function ListPersonArray() {
var i;
//Сортировка массива по фамилии
PersonArr.sort(SortLastName);
//Цикл по всем элементам массива PersonArr
for (i=0;i<=PersonArr.length-1;i++) {
//Запись информации в выходной файл
PrintPerson(PersonArr[i]);
}
}
//Функция для сортировки массива по фамилии
function SortLastName(Pers1,Pers2) {
if (Pers1.LastName
else if (Pers1.LastName==Pers2.LastName) return 0;
else return 1;
}
//Основная запускная функция
function Main() {
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Открываем выходной файл для записи
FOut=FSO.OpenTextFile(PathOut,ForWriting,true);
//Печатаем заголовок отчета
TopReport("Список всех записей, сортировка по фамилии");
//Считываем данные из файла в массив
FileToArray();
//Записываем информацию из массива в выходной файл
ListPersonArray();
//Печатаем итоговую информацию
BottomReport("Всего записей: "+PersonArr.length);
//Открываем выходной файл в Блокноте
MakeOut();
}
//Запускаем основную функцию
Main();
//Поиск в XML-файле нужных записей и сохранение их в
//массиве PersonArr
function RecordsToArray(LastName) {
var XMLDoc,Root,sSelect,i,Parent,NodeList;
//Создаем массив PersonArr
PersonArr=new Array();
//Создаем объект DOMDocument
XMLDoc = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-файл
XMLDoc.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XMLDoc.documentElement;
//Формируем строку для поиска фамилии
sSelect="Person/LastName[text()='"+LastName+"']";
//Создаем коллекцию NodeList всех элементов LastName,
//значение которых совпадает со значением переменной LastName
NodeList=XMLDoc.documentElement.selectNodes(sSelect);
if (NodeList.length==0) {//Коллекция NodeList пуста
//Выводим диалоговое окно с сообщением
WshShell.Popup("Фамилия "+ LastName+ " не найдена!", 0,
"Записная книжка",vbInformation+vbOkOnly);
//Завершаем выполнение задания
WScript.Quit();
} else { //Требуемая фамилия найдена
//Цикл по всем найденным элементам LastName
for (i=0;i<=NodeList.length-1;i++) {
//Определяем родительский элемент (Person) для найденного
//элемента LastName
Parent=NodeList.item(i).parentNode;
//Добавляем новый элемент в массив объектов Person
PersonToArray(Parent);
}
}
}
//Вывод в выходной файл информации о найденных записях
function PrintAllFind() {
var i;
for (i=0;i
PrintPerson(PersonArr[i]);
}
}
//Основная запускная функция
function Main() {
var LastName;
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Создаем объект FileSystemObject
FSO=WScript.CreateObject("Scripting.FileSystemObject");
//Открываем выходной файл для записи
FOut=FSO.OpenTextFile(PathOut,ForWriting,true);
//Печатаем заголовок отчета
TopReport("Поиск записей");
//Вводим фамилию для поиска
LastName=WSHInputBox("Введите фамилию для поиска:","Записная книжка")
//Ищем в XML-файле нужные записи и сохраняем их в массиве PersonArr
RecordsToArray(LastName);
//Выводим все найденные записи из массива PersonArr в выходной файл
PrintAllFind(LastName);
//Печатаем итоговую информацию
BottomReport("Всего найдено: "+PersonArr.length);
//Открываем выходной файл в Блокноте
MakeOut();
}
//Запускаем основную функцию
Main();
//Поиск фамилии в записной книжке и удаление всех
//реквизитов, относящихся к этой фамилии
function FindAndDelRecord(LastName) {
var Root,sSelect,i,Parent,NodeList;
//Создаем объект DOMDocument
XMLDoc = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-файл
XMLDoc.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XMLDoc.documentElement;
//Формируем строку для поиска фамилии
sSelect="Person/LastName[text()='"+LastName+"']";
//Создаем коллекцию NodeList всех элементов LastName,
//значение которых совпадает со значением переменной LastName
NodeList=XMLDoc.documentElement.selectNodes(sSelect);
if (NodeList.length==0) //Коллекция NodeList пуста
//Выводим диалоговое окно с сообщением
WshShell.Popup("Фамилия "+LastName+ " не найдена!", 0,
"Записная книжка",vbInformation+vbOkOnly);
else { //Требуемая фамилия найдена
//Цикл по всем найденным элементам LastName
for (i=0;i<=NodeList.length-1;i++) {
//Определяем родительский элемент (Person) для найденного
//элемента LastName
Parent=NodeList.item(i).parentNode;
//Удаляем элемент Person вместе со всеми его дочерними элементами
Root.removeChild(Parent);
//Выводим диалоговое окно с сообщением
WshShell.Popup("Запись удалена!",0,
"Записная книжка",vbInformation+vbOkOnly);
}
//Сохраняем содержимое XML-файла на диске
XMLDoc.save(PathBook);
}
}
//Основная запускная функция
function Main() {
var LastName,Res;
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
LastName=WSHInputBox("Введите фамилию для удаления:","Записная книжка")
//Запрос на удаление записи
Res=WshShell.Popup("Удалить фамилию "+LastName+ " из \n"+PathBook+"?",0,
"Записная книжка",vbQuestion+vbYesNo);
if (Res==vbYes) { //Нажата кнопка Да
//Ищем в книжке нужную фамилию и удаляем относящуюся к
//ней запись
FindAndDelRecord(LastName);
}
}
//Запускаем основную функцию
Main();
//Ввод значений полей объекта PersonRec
function MakePersonRec() {
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Вводим значения полей добавляемой записи с помощью диалогового
//окна со строкой ввода
PersonRec.LastName=WSHInputBox("Введите фамилию","Добавление записи");
PersonRec.Name=WSHInputBox("Введите имя","Добавление записи");
PersonRec.Phone=WSHInputBox("Введите телефон","Добавление записи");
PersonRec.Street=WSHInputBox("Введите улицу","Добавление записи");
PersonRec.House=WSHInputBox("Введите дом","Добавление записи");
PersonRec.App=WSHInputBox("Введите квартиру","Добавление записи");
PersonRec.Note=WSHInputBox("Введите примечание","Добавление записи");
}
//Сохранение данных из объекта PersonRec в XML-файле
function RecordToFile(PersRec) {
var Root,NewElem,s;
//Создаем объект DOMDocument
XMLDoc = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-файл
XMLDoc.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XMLDoc.documentElement;
//Создаем XML-элемент Person
NewElem=XMLDoc.createElement("Person");
//Добавляем новый элемент в XML-файл
Root.appendChild(NewElem);
//Сохраняем в переменной Root ссылку на последний добавленный
//элемент Person
Root=Root.lastChild;
//Создаем элемент LastName
NewElem=XMLDoc.createElement("LastName");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента LastName
//значение поля LastName объекта PersRec
Root.lastChild.text=PersRec.LastName;
//Создаем элемент Name
NewElem=XMLDoc.createElement("Name");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента Name
//значение поля Name объекта PersRec
Root.lastChild.text=PersRec.Name;
//Создаем элемент Phone
NewElem=XMLDoc.createElement("Phone");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента Phone
//значение поля Phone объекта PersRec
Root.lastChild.text=PersRec.Phone;
//Создаем элемент Street
NewElem=XMLDoc.createElement("Street");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента Street
//значение поля Street объекта PersRec
Root.lastChild.text=PersRec.Street;
//Создаем элемент House
NewElem=XMLDoc.createElement("House");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента House
//значение поля House объекта PersRec
Root.lastChild.text=PersRec.House;
//Создаем элемент App
NewElem=XMLDoc.createElement("App");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента App
//значение поля House объекта PersRec
Root.lastChild.text=PersRec.App;
//Создаем элемент Note
NewElem=XMLDoc.createElement("Note");
//Добавляем новый элемент в XML-файл (внутри элемента Person)
Root.appendChild(NewElem);
//Подставляем в качестве содержимого элемента App
//значение поля House объекта PersRec
Root.lastChild.text=PersRec.Note;
//Сохраняем содержимое XML-файла на диске
XMLDoc.save(PathBook);
}
//Добавление новой записи в книжку
function AddRecord() {
//Заполняем поля объекта PersonRec
MakePersonRec();
//Сохраняем данные из объекта PersonRec в XML-файл
RecordToFile(PersonRec);
}
//Построение путей к файлам
function InitPath() {
BasePath=WshShell.CurrentDirectory+"\\";
//Путь к файлу с данными
PathBook=BasePath+"book.xml";
}
//Основная запускная функция
function Main() {
var Res;
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Запрос на создание нового ключа
Res=WshShell.Popup("Добавить запись в \n"+PathBook+"?",0,
"Записная книжка",vbQuestion+vbYesNo);
if (Res==vbYes) { //Нажата кнопка Да
//Добавляем новую запись в книжку
AddRecord();
//Выводим информацию на экран
WshShell.Popup("Новая запись\n\n"+PersonRec.LastName+" "+
PersonRec.Name+"\n"+PersonRec.Phone+"\n"+
PersonRec.Street+", "+PersonRec.House+"-"+PersonRec.App+"\n\n"+
"добавлена!",0, "Записная книжка",vbInformation+vbOkOnly);
}
}
//Запускаем основную функцию
Main();
Итак, у нас теперь имеется многозадачный WS-файл PhoneBook.wsf, обеспечивающий необходимую функциональность для работы с записной книжкой, и следующая задача состоит в организации более или менее удобного диалога с пользователем для запуска заданий из этого файла.
Самый простой вариант организовать диалог с пользователем состоит в использовании параметров командной строки. Напомним, что объектная модель WSH предоставляет несколько методов, которые позволяют производить анализ именных и безымянных параметров (см. разд. "Работа с параметрами командной строки сценария" главы 2), с которыми был запущен сценарий, а в схеме WS XML есть несколько специальных элементов (
, <named>
,
,
и
), предназначенных для быстрого создания встроенной справки, описывающей синтаксис сценария и смысл каждого из параметров.
Для нашего примера мы создадим сценарий ArgMenu.wsf, в котором будем анализировать аргументы командной строки и в зависимости от них запускать то или иное задание из файла PhoneBook.wsf. Названия и назначения именных параметров, которые мы будем использовать, приведены в табл. 7.1.
Таблица 7.1. Параметры командной строки сценария для работы с записной книжкой
Название параметра | Назначение |
---|---|
|
Просмотр всех записей книжки (сортировка по фамилии) |
|
Поиск записей по фамилии, которая вводится в диалоговом окне |
|
Добавление записи по фамилии (данные вводятся в диалоговом окне) |
|
Удаление записи (фамилия для удаления вводится в диалоговом окне) |
Если запустить сценарий ArgMenu.wsf вообще без параметров, либо с параметрами, не указанными в табл. 7.1, то на экран будет выведена встроенная справка (рис. 7.1).
Рис. 7.1. Встроенная справка для сценария ArgMenu.wsf
В листинге 7.4 приводится полный текст сценария ArgMenu.wsf.
Сценарий для работы с телефонной книжкой
var WshShell;
WshShell=WScript.CreateObject("WScript.Shell");
if ((WScript.Arguments.Named.Exists("L")) ||
(WScript.Arguments.Named.Exists("l"))) {
WshShell.Run("wscript PhoneBook.wsf //Job:SortName");
WScript.Quit();
}
if ((WScript.Arguments.Named.Exists("F")) ||
(WScript.Arguments.Named.Exists("f"))) {
WshShell.Run("wscript PhoneBook.wsf //Job:FindName");
WScript.Quit();
}
if ((WScript.Arguments.Named.Exists("A")) ||
(WScript.Arguments.Named.Exists("a"))) {
WshShell.Run("wscript PhoneBook.wsf //Job:AddRec");
WScript.Quit();
}
if ((WScript.Arguments.Named.Exists("D")) ||
(WScript.Arguments.Named.Exists("d"))) {
WshShell.Run("wscript PhoneBook.wsf //Job:DelRec");
WScript.Quit();
}
//Ни один из нужных аргументов не был указан, выводим
//описание параметров
WScript.Arguments.ShowUsage();
Теперь, если понадобится ввести дополнительную функцию при работе с записной книжкой (например, поиск по номеру телефона), нужно будет в файл PhoneBook.wsf добавить задание с новым идентификатором, а в файл ArgMenu.wsf — обработку нового параметра командной строки.
Вторым вариантом организации диалога, который мы рассмотрим, является кнопочное (командное) меню. Принцип его работы в нашем примере остается практически тем же, что и при описанной выше обработке аргументов командной строки — пользователь должен в диалоговом окне ввести символ, соответствующий одной из описанных в этом окне команд (рис. 7.2). Этот символ анализируется в сценарии, и в зависимости от его значения вызывается то или иное задание из файла PhoneBook.wsf.
Рис. 7.2. Кнопочное меню для работы с записной книжкой
Диалоговое окно, показанное на рис. 7.2, выводится в цикле
while
, в котором с помощью оператора switch
анализируется введенный пользователем символ. Выход из цикла совершается, если введенный символ совпадает с "q" или "Q".
Текст сценария ComMenu.wsf, реализующего кнопочное меню для работы с записной книжкой, приводится в листинге 7.5.
var WshShell,SMenu,Res;
WshShell=WScript.CreateObject("WScript.Shell");
SMenu="[L] - Просмотр содержимого книжки\n";
SMenu+="[F] - Поиск по фамилии\n";
SMenu+="[A] - Добавление записи\n";
SMenu+="[D] - Удаление записи\n";
SMenu+="[Q] - Выход из сценария\n";
SMenu+="\n\nКоманда:";
Res="";
while ((Res!="q") && (Res!="Q")) {
Res=WSHInputBox(SMenu,"Записная книжка");
switch (Res) {
case "L": {
WshShell.Run("wscript PhoneBook.wsf //Job:SortName",1,true);
break;
}
case "l": {
WshShell.Run("wscript PhoneBook.wsf //Job:SortName",1,true);
break;
}
case "F": {
WshShell.Run("wscript PhoneBook.wsf //Job:FindName",1,true);
break;
}
case "f": {
WshShell.Run("wscript PhoneBook.wsf //Job:FindName",1,true);
break;
}
case "A": {
WshShell.Run("wscript PhoneBook.wsf //Job:AddRec",1,true);
break;
}
case "a": {
WshShell.Run("wscript PhoneBook.wsf //Job:AddRec",1,true);
break;
}
case "D": {
WshShell.Run("wscript PhoneBook.wsf //Job:DelRec",1,true);
break;
}
case "d": {
WshShell.Run("wscript PhoneBook.wsf //Job:DelRec",1,true);
break;
}
}
}
Как мы видим из вышеприведенных примеров, ни объектная модель WSH, ни языки JScript и VBScript не предоставляют средств для создания полноценного графического интерфейса пользователя.
Тем не менее, такой интерфейс в сценариях WSH создать можно. Мы продемонстрируем это на примере еще одного сценария (состоящего из однозадачного JScript-файла) для работы с записной книжкой, в котором для диалога с пользователем будет организована пользовательская форма с несколькими кнопками и текстовыми полями ввода. Для создания этой формы и работы с ней будут использоваться HTML-файл и браузер Internet Explorer.
Процесс создания сценария WSH, использующего Internet Explorer в качестве интерфейса, можно условно разделить на несколько этапов:
□ создание HTML-формы в отдельном файле;
□ написание функции для сценария WSH, в которой будет производиться вывод на экран построенной формы;
□ написание части сценария, в которой будет реализована необходимая функциональность (например, обмен информацией между формой и внешним файлом с данными, корректное отображение данных в форме и т.д.);
□ добавление в сценарий функций-обработчиков событий, связанных с поведением браузера Internet Explorer;
□ добавление в сценарий функций-обработчиков событий, которые генерируются элементами управления в форме.
Ниже мы рассмотрим каждый из этих этапов на примере создания сценария IEPhoneBook.js для работы с записной книжкой, которая хранится, как и прежде, в XML-файле book.xml.
В качестве интерфейса записной книжки мы создадим диалоговое окно (пользовательскую форму), которое показано на рис. 7.3.
Рис. 7.3. Диалоговое окно для работы с записной книжкой
Эта форма реализуется с помощью HTML-файл Phone.htm, который полностью приведен в листинге 7.6.
В самом начале файла Phone.htm ставится тег
, указывающий на то, что содержимым файла является текст в формате HTML, а также теги
и
, внутри которых задаются используемая кодировка (charset=windows-1251
) и заголовок формы (теги
и
):
Форма для записной книжки
Для того чтобы задать цвет формы, в теге
используется атрибут bgcolor
со значением "silver
":
Атрибут
scroll="no"
указывает на то, что в диалоговом окне не должно быть полос прокрутки.
Наша форма состоит из семи текстовых полей ввода (табл. 7.2) и восьми кнопок (табл. 7.3).
Таблица 7.2. Поля ввода диалогового окна для работы с записной книжкой
Имя поля | Размер поля (символов) | Назначение |
---|---|---|
|
50 | Поле для ввода фамилии |
|
50 | Поле для ввода имени |
|
15 | Поле для ввода номера телефона |
|
50 | Поле для ввода названия улицы |
|
10 | Поле для ввода номера дома |
|
5 | Поле для ввода номера квартиры |
|
80 | Поле для ввода примечания |
Таблица 7.3. Кнопки диалогового окна для работы с записной книжкой
Текст кнопки | Имя кнопки | Назначение |
---|---|---|
<< |
|
Переход к первой записи |
< |
|
Переход к предыдущей записи |
Новая запись |
|
Добавление новой пустой записи |
Записать |
|
Сохранение сделанных изменений в XML-файле |
Отменить |
|
Отмена сделанных в форме изменений |
Удалить |
|
Удаление текущей записи |
> |
|
Переход к следующей записи |
>> |
|
Переход к последней записи |
Команды, создающие форму, находятся внутри тегов
и
. Сами текстовые поля ввода и кнопки создаются в HTML-файле с помощью одного и того же тега
. Внутри этого тега нужно указать несколько атрибутов:
□
type
— определяет тип элемента управления (для поля ввода type="text"
, для кнопки type="button"
);
□
name
— задает имя элемента управления;
□
size
— определяет длину строки поля ввода в символах;
□
value
— задает надпись на кнопке.
Для того чтобы поля ввода располагались точно друг под другом, мы поместим их в таблицу с невидимыми границами, состоящую из двух столбцов: в первом находится описание (метка) для поля, во втором — сам элемент управления. Таблица в HTML-файле создается с помощью парных тегов
и
, внутри которых приводятся теги и
, задающие начало и конец одной строки таблицы соответственно:
Здесь аргумент
border
задает ширину границ таблицы (в нашем случае границы невидимы), а в аргументе style
указываются название и размер шрифта, которым будет выводиться содержимое таблицы.
В свою очередь, внутри тегов
и
находятся теги и
, определяющие одну ячейку таблицы, например:
Фамилия
Для тегов
указывается аргумент width
, задающий ширину строки в процентах от общей ширины строки.
Кнопки в форме выводятся друг за другом, нужное расстояние между ними достигается с помощью неразрывных пробелов (escape-последовательность
 
), например:
Листинг 7.6. Описание формы в HTML-файле (Phone.htm)
Форма для записной книжки
Фамилия
Имя
Телефон
Улица
Дом
Кв.
Примечание
Создание объекта для обмена данными между XML-файлом и формой
В отличие от рассмотренного выше сценария PhoneBook.wsf, в сценарии IEPhoneBook.js функции для работы с записной книжкой не будут разделены по разным заданиям, поэтому для более четкой организации сценария мы воспользуемся объектно-ориентированным подходом и создадим два объекта
Person
и ListPersons
, методы которых и будут осуществлять обработку данных и связь между XML-файлом и пользовательской формой.
Как и раньше, в свойствах объекта
Person
будет храниться запись об одном человеке. Кроме этого, мы добавим в объект Person
метод LoadDialog
, который будет заполнять поля ввода в форме данными из соответствующих свойств объекта Person
:
//Конструктор объекта Person
function Person() {
//Инициализируем свойства объекта
this.LastName="";
this.Name="";
this.Phone="";
this.Street="";
this.House="";
this.App="";
this.Note="";
//Устанавливаем для метода LoadDialog указатель на
//функцию Person_LoadDialog
this.LoadDialog=Person_LoadDialog;
}
//Заполнение полей в форме для текущей записи
function Person_LoadDialog() {
//Заполняем поля ввода в форме значениями соответствующих
//свойств объекта Person
doc.all.txtLastName.value = this.LastName;
doc.all.txtName.value=this.Name;
doc.all.txtPhone.value=this.Phone;
doc.all.txtStreet.value=this.Street;
doc.all.txtHouse.value=this.House;
doc.all.txtApp.value = this.App;
doc.all.txtNote.value = this.Note;
}
Принцип доступа к полям ввода формы по их именам, который используется в методе
LoadDialog()
, объясняется ниже (см. разд. "Обработка событий, генерируемых элементами управления формы").
Основным объектом, который обеспечивает обмен данными между XML-файлом записной книжки и разработанной нами формой, является объект
ListPersons
. Этот объект будет содержать три свойства и десять методов.
Первым свойством объекта
ListPersons
мы сделаем массив PersonArr
объектов Person
; этот массив будет служить промежуточным буфером при чтении данных из XML-файла для отображения в форме и при записи измененных данных из формы в файл. В остальных двух свойствах СurRecord
и IsChanged
объекта ListPersons
будут соответственно храниться номер текущей записи и логическое значение (true
или false
), являющееся признаком того, были ли изменены пользователем данные в форме.
Назначение методов объекта
ListPersons
ясно из комментариев, которые приведены в конструкторе этого объекта (листинг 7.7).
Листинг 7.7. Конструктор объекта ListPersons
function ListPersons() {
// Свойства объекта
//Создаем массив PersonArr экземпляров объекта Person
this.PersonArr = new Array();
//Инициализируем номер текущей записи
this.CurRecord = 0;
//Сбрасываем признак изменения данных в форме
this.IsChanged = false;
// Методы объекта
//Устанавливаем для методов указатели на соответствующие функции
this.FileToArray=ListPersons_FileToArray;
this.SaveData=ListPersons_SaveData;
this.LoadDialog=ListPersons_LoadDialog;
this.RefreshDialog=ListPersons_RefreshDialog;
this.NextRecord=ListPersons_NextRecord;
this.PreviousRecord=ListPersons_PreviousRecord;
this.FirstRecord=ListPersons_FirstRecord;
this.FinalRecord=ListPersons_FinalRecord;
this.NewRecord=ListPersons_NewRecord;
this.DelRecord = ListPersons_DelRecord;
}
Текст всех методов объекта
ListPersons
с подробными комментариями приведен в листинге 7.8.
Листинг 7.8. Методы объекта ListPersons
//Считывание данных из XML-файла в массив объектов Person
function ListPersons_FileToArray() {
var Root,CurrNode,i;
//Создаем объект XML DOM
XML = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-документ из файла
XML.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//Обнуляем массив PersonArr
this.PersonArr.length=0;
//Перебираем все дочерние элементы первого уровня вложенности
//для корневого элемента
for (i=1; i<=Root.childNodes.length-1;i++) {
//Выделяем в коллекции XML-элементов i-й элемент
CurrNode=Root.childNodes.item(i);
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName=GetTagVal(CurrNode,"LastName");
PersonRec.Name=GetTagVal(CurrNode,"Name");
PersonRec.Phone=GetTagVal(CurrNode,"Phone");
PersonRec.Street=GetTagVal(CurrNode,"Street");
PersonRec.House=GetTagVal(CurrNode,"House");
PersonRec.App=GetTagVal(CurrNode,"App");
PersonRec.Note=GetTagVal(CurrNode,"Note");
//Сохраняем объект PersonRec в массиве PersonArr
this.PersonArr[this.PersonArr.length]=PersonRec;
}
}
//Запись данных из формы в XML-файл
function ListPersons_SaveData() {
var Root,CurrNode,ElemList;
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//Сохраняем в переменной CurrNode ссылку на (CurRecord+1)-й
//элемент Person
CurrNode=Root.childNodes.item(this.CurRecord+1);
//Записываем данные из полей ввода формы в соответствующие
//XML-элементы, которые являются дочерними узлами
//относительно CurrNode
SetTagVal(CurrNode,"LastName",doc.all.txtLastName.value);
SetTagVal(CurrNode,"Name",doc.all.txtName.value);
SetTagVal(CurrNode,"Phone",doc.all.txtPhone.value);
SetTagVal(CurrNode,"Street",doc.all.txtStreet.value);
SetTagVal(CurrNode,"House",doc.all.txtHouse.value);
SetTagVal(CurrNode,"App",doc.all.txtApp.value);
SetTagVal(CurrNode,"Note",doc.all.txtNote.value);
//Сохраняем XML-файл на диске
XML.save(PathBook);
}
//Загрузка данных для текущей записи в форму
function ListPersons_LoadDialog() {
//Вызываем метод LoadDialog для объекта Person,
//который является CurRecord-м элементом массива PersonArr
this.PersonArr[this.CurRecord].LoadDialog();
}
//Обновление данных в форме
function ListPersons_RefreshDialog(IsGoTop) {
//Обнуляем массив PersonArr
this.PersonArr.length=0;
//Заново загружаем данные из XML-файла в массив PersonArr
this.FileToArray();
if (IsGoTop)
//Переходим к первой записи в массиве
this.FirstRecord()
else
//Переходим к последней записи в массиве
this.FinalRecord();
//Загружаем в форму данные для текущей записи
this.LoadDialog();
}
//Переход к следующей записи
function ListPersons_NextRecord() {
if (this.CurRecord
//Если текущая запись не является последней, увеличиваем
//номер текущей записи
this.CurRecord++;
}
//Переход к предыдущей записи
function ListPersons_PreviousRecord() {
if (this.CurRecord > 0)
//Если текущая запись не является первой, уменьшаем
//номер текущей записи
this.CurRecord--;
}
//Переход к первой записи
function ListPersons_FirstRecord() {
this.CurRecord = 0;
}
//Переход к последней записи
function ListPersons_FinalRecord() {
this.CurRecord = this.PersonArr.length - 1;
}
//Добавление новой записи
function ListPersons_NewRecord() {
var Root,NewElem;
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//Создаем новый элемент Person
NewElem=XML.createElement("Person");
//Добавляем новый элемент в XML-файл
Root.appendChild(NewElem);
//Сохраняем XML-файл на диске
XML.save(PathBook);
//Обновлем в форме данные для последней добавленной записи
this.RefreshDialog(false);
}
//Удаление текущей записи
function ListPersons_DelRecord() {
var Root,DelNom;
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//В переменной DelNom сохраняем номер удаляемого элемента Person
DelNom=this.CurRecord+1;
//Удаляем DelNom-й элемент Person из XML-файла
Root.removeChild(Root.childNodes.item(DelNom))
//Сохраняем XML-файл на диске
XML.save(PathBook);
//Выводим сообщение о том, что запись удалена
WshShell.Popup("Запись N "+DelNom+" удалена",0,"Информация",
vbInformation+vbOkOnly);
//Обновлем в форме данные для первой записи
this.RefreshDialog(true);
}
Вывод формы из сценария WSH
Для того чтобы вывести из сценария WSH разработанную HTML-форму на экран, нужно вначале получить ссылку на объект
Application
, который определяется в объектной модели Internet Explorer. Делается это следующим образом:
var ie = WScript.CreateObject("InternetExplorer.Application", "ie_");
При этом в память загружается новый экземпляр Internet Explorer, а ссылка на этот объект присваивается переменной
ie
(само окно браузера по умолчанию невидимо, для его отображения на экране необходимо установить свойство Visible
объекта Application
в 1). В качестве второго параметра метода CreateObject
указан префикс "ie
_", посредством которого мы сможем написать функции-обработчики событий Internet Explorer.
Внешний вид браузера Internet Explorer настраивается с помощью нескольких свойств объекта
Application
:
//Устанавливаем свойства объекта ie для отображения формы
ie.AddressBar = false; //Адресная строка не выводится
ie.Fullscreen = false; //Полноэкранный режим запрещен
ie.MenuBar = false; //Главное меню браузера не выводится
ie.Resizable = false; //Изменять размеры окна нельзя
ie.StatusBar = false; //Строка статуса не выводится
ie.ToolBar = false; //Инструментальная панель не выводится
//Устанавливаем размеры окна
ie.Height = 300; //Высота
ie.Width = 780; //Длина
Для того чтобы загрузить в браузер нужный нам файл Phone.htm с описанием формы, используется метод Navigate объекта Application:
ie.Navigate(PathHTML);
В качестве параметра метода
Navigate
указывается путь к файлу Phone.htm, который заранее устанавливается в функции InitPath()
:
function InitPath() {
BasePath=WshShell.CurrentDirectory+"\\";
//Путь к файлу с данными
PathBook=BasePath+"book.xml";
//Путь к файлу с HTML-формой
PathHTML=BasePath+"Phone.htm";
}
Далее следует учесть, что сценарий WSH и окно браузера, в котором загружена форма, — это два независимых процесса. Поэтому в сценарии после загрузки формы в окно браузера необходимо дождаться, пока пользователь не закроет это окно. Для этого мы присвоим глобальной переменной
IsQuit
значение false
и заставим сценарий выполняться до тех пор, пока значение этой переменной не станет равным true
:
while (!IsQuit)
//Приостанавливаем сценарий на 0,1 сек
WScript.Sleep(100);
При закрытии формы будет генерироваться событие
OnQuit
объекта Application
, поэтому мы напишем функцию-обработчик ie_OnQuit()
этого события, в которой будем устанавливать isQuit
в true
и сохранять в XML- файле данные, которые были изменены в форме (листинг 7.9).
Листинг 7.9. Функция-обработчик закрытия окна браузера
function ie_OnQuit() {
IsQuit=true;
//Сохраняем данные из формы в XML-файле
objListPersons.SaveData();
}
В нашем сценарии загрузка в браузер HTML-файла с формой будет производиться в основной запускной функции
Main()
(листинг 7.10).
Листинг 7.10. Функция Main()
function Main() {
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Создаем объект InternetExplorer.Application с возможностью
//обработки событий этого объекта
ie = WScript.CreateObject("InternetExplorer.Application", "ie_");
//Устанавливаем свойства объекта ie для отображения формы3
ie.AddressBar = false;
ie.FullScreen = false;
ie.MenuBar = false;
ie.Resizable = false;
ie.StatusBar = false;
ie.ToolBar = false;
//Устанавливаем размеры окна
ie.Height = 300; //Высота
ie.Width = 780; //Длина
IsQuit=false;
//Загружаем HTML-файл с формой
ie.Navigate(PathHTML);
while (!IsQuit)
//Приостанавливаем сценарий на 0,1 сек
WScript.Sleep(100);
}
После окончания загрузки в браузер HTML-файла с формой нужно считать информацию из XML-файла с данными и отобразить в форме данные для первой записи. Мы будем это делать в функции-обработчике
ie_DocumentComplete()
события DocumentComplete
объекта Application
, которое генерируется как раз после окончания загрузки документа в браузер (листинг 7.11).
Листинг 7.11. Функция-обработчик окончания загрузки документа в браузер
function ie_DocumentComplete() {
//Создаем экземпляр objListPersons объекта ListPersons
objListPersons = new ListPersons();
//Загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
//Получаем ссылку на объект Document
doc = ie.Document;
//Устанавливаем заголовок окна
doc.title = "Редактирование данных";
//Указываем функции-обработчики нажатий на кнопки формы
doc.all.btnSave.onclick=btnSave_OnClick;
doc.all.btnCancel.onclick=btnCancel_OnClick;
doc.all.btnFirst.onclick=btnFirst_OnClick;
doc.all.btnPrevious.onclick=btnPrevious_OnClick;
doc.all.btnNew.onclick=btnNew_OnClick;
doc.all.btnDelete.onclick=btnDelete_OnClick;
doc.all.btnNext.onclick=btnNext_OnClick;
doc.all.btnFinal.onclick=btnFinal_OnClick;
//Указываем функции-обработчики изменения текста в полях ввода
doc.all.txtLastName.onchange = txtBoxOnChange;
doc.all.txtName.onchange = txtBoxOnChange;
doc.all.txtPhone.onchange = txtBoxOnChange;
doc.all.txtStreet.onchange = txtBoxOnChange;
doc.all.txtHouse.onchange = txtBoxOnChange;
doc.all.txtApp.onchange = txtBoxOnChange;
doc.all.txtNote.onchange = txtBoxOnChange;
if (objListPersons.PersonArr.length < 1)
//Если в XML-файле нет данных, добавляем пустую запись
objListPersons.AddRecord();
//В качестве текущей устанавливаем первую запись
objListPersons.CurRecord = 0;
//Загружаем в форму данные из массива PersonArr
//для первой записи
objListPersons.LoadDialog();
// Делаем окно Internet Explorer'а видимым
ie.Visible = true;
}
В функции
ie_DocumentComplete()
, кроме прочего, задаются функции-обработчики событий, генерируемых в форме текстовыми полями ввода и кнопками. К описанию процесса обработки таких событий мы и перейдем.
Обработка событий, генерируемых элементами управления формы
В нашем сценарии мы будем обрабатывать события, связанные с нажатием на кнопки в форме и с изменением текста в полях ввода. Для этого нужно, во-первых, получить ссылку на соответствующий элемент управления в форме, зная его имя, которое задается атрибутом name в HTML-файле, например:
Для доступа к элементу управления используется объект Document, который соответствует загруженному в браузер HTML-документу. Ссылка на объект Document Хранится в свойстве Document объекта Application:
//Получаем ссылку на объект Document
doc = ie.Document;
Обработчики событий для элементов управления формы указываются тогда следующим образом:
doc.all.ControlName.EventName=FunctionName;
Здесь ControlName
— имя элемента управления, EventName
— имя обрабатываемого события, FunctionName
— имя функции-обработчика, которая будет вызываться при наступлении события EventName
. Событие, возникающее при нажатии на кнопку в форме, называется
onclick
, а событие, происходящее при изменении текста в поле ввода, — onchange
:
//Указываем функции-обработчики нажатий на кнопки формы
doc.all.btnSave.onclick=btnSave_OnClick;
doc.all.btnCancel.onclick=btnCancel_OnClick;
doc.all.btnFirst.onclick=btnFirst_OnClick;
doc.all.btnPrevious.onclick=btnPrevious_OnClick;
doc.all.btnNew.onclick=btnNew_OnClick;
doc.all.btnDelete.onclick=btnDelete_OnClick;
doc.all.btnNext.onclick=btnNext_OnClick;
doc.all.btnFinal.onclick=btnFinal_OnClick;
//Указываем функции-обработчики изменения текста в полях ввода
doc.all.txtLastName.onchange = txtBoxOnChange;
doc.all.txtName.onchange = txtBoxOnChange;
doc.all.txtPhone.onchange = txtBoxOnChange;
doc.all.txtStreet.onchange = txtBoxOnChange;
doc.all.txtHouse.onchange = txtBoxOnChange;
doc.all.txtApp.onchange = txtBoxOnChange;
doc.all.txtNote.onchange = txtBoxOnChange;
Сами функции-обработчики нажатий на различные кнопки и изменения текста в полях ввода приведены с подробными комментариями в листинге 7.12.
Листинг 7.12. Функции-обработчики нажатия кнопок и изменения поло ввода
//Функция-обработчик нажатия на кнопку "Сохранить"
function btnSave_OnClick() {
//Сохраняем данные из формы в XML-файле
objListPersons.SaveData();
}
//Функция-обработчик нажатия на кнопку "Отменить"
function btnCancel_OnClick() {
//Заново загружаем данные из текущего элемента массива
//в форму
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Данные восстановлены";
}
//Функция-обработчик нажатия на кнопку "<<"
function btnFirst_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к первой записи в массиве
objListPersons.FirstRecord();
//Загружаем в форму данные из массива PersonArr
//для первой записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик нажатия на кнопку "<"
function btnPrevious_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к предыдущей записи в массиве
objListPersons.PreviousRecord();
//Загружаем в форму данные из массива PersonArr
//для текущей записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик нажатия на кнопку "Новая запись"
function btnNew_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Добавляем новую запись в XML-файл
objListPersons.NewRecord();
//Загружаем в форму данные из массива PersonArr
//для добавленной записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Добавлена новая запись";
}
//Функция-обработчик нажатия на кнопку "Удалить"
function btnDelete_OnClick() {
//Удаляем текущую запись из XML-файла
objListPersons.DelRecord();
//Загружаем в форму данные из массива PersonArr
//для первой записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись удалена";
}
//Функция-обработчик нажатия на кнопку ">"
function btnNext_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к следующей записи в массиве
objListPersons.NextRecord();
//Загружаем в форму данные из массива PersonArr
//для текущей записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик нажатия на кнопку ">>"
function btnFinal_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к последней записи в массиве
objListPersons.FinalRecord();
//Загружаем в форму данные из массива PersonArr
//для текущей записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик изменения текста в полях ввода
function txtBoxOnChange() {
//Устанавливаем признак изменения данных в форме
objListPersons.IsChanged = true;
//Выводим сообщение в заголовке окна
doc.title = "Редактирование данных";
}
Окончательная доработка сценария IEPhoneBook.js
Выше были описаны все основные функции, которые используются для работы с записной книжкой в диалоговом режиме. Осталось лишь собрать эти функции в один JScript-сценарий IEPhoneBook.js, определить глобальные переменные и добавить вспомогательные функции
GetTagVal(obj, tgName)
и SetTagVal(obj, tgName, sVal)
для доступа к значениям XML-элементов (листинг 7.13).
Листинг 7.13. Функция для доступа к значениям XML-элементов
//Определение значения тега tgName XML-элемента obj
function GetTagVal(obj, tgName) {
var ElemList;
//Создаем коллекцию дочерних для obj элементов, которые
//задаются тегом tgName
ElemList=obj.getElementsByTagName(tgName);
//Проверяем, есть ли в коллекции ElemList элементы
if (ElemList.length>0)
//Возвращаем значение тега tgName
return ElemList.item(0).text
else return "";
}
//Изменение значения тега tgName XML-элемента obj
function SetTagVal(obj, tgName, sVal) {
var ElemList,New;
//Создаем коллекцию дочерних для obj элементов, которые
//задаются тегом tgName
ElemList=obj.getElementsByTagName(tgName);
//Проверяем, есть ли в коллекции ElemList элементы
if (ElemList.length>0)
//Устанавливаем значение элемента, задаваемого
//тегом tgName
ElemList.item(0).text=sVal;
else {
//Создаем новый элемент с именем tgName
NewElem=XML.createElement(tgName);
//Добавляем новый элемент в качестве дочернего для
//элемента obj
obj.appendChild(NewElem);
//Устанавливаем значение добавленного элемента
obj.lastChild.text=sVal;
}
}
Полный текст сценария IEPhoneBook.js приведен в листинге 7.14.
Листинг 7.14. Сценарий IEPhoneBook.js
/*******************************************************************/
/* Имя: IEPhoneBook.js */
/* Язык: JScript */
/* Описание: Сценарий для работы с записной книжкой */
/* (графический интерфейс пользователя на основе */
/* HTML-формы). */
/*******************************************************************/
//Объявляем глобальные переменные
var
WshShell,
PathBook, //Путь к файлу с данными
PathHTML, //Путь к HTML-файлу с формой
XML, //Экземпляр объекта XML DOM
ie, //Экземпляр объекта InternetExplorer.Application
doc, //Экземпляр объекта Document
IsQuit, //Признак выхода из сценария
objListPersons; //Экземпляр объекта ListPersons
//Инициализируем константы для диалоговых окон
var vbInformation=64,vbOkOnly=0;
//Построение путей к файлам
function InitPath() {
BasePath=WshShell.CurrentDirectory+"\\";
//Путь к файлу с данными
PathBook=BasePath+"book.xml";
//Путь к файлу с HTML-формой
PathHTML=BasePath+"Phone.htm";
}
//Определение значения тега tgName XML-элемента obj
function GetTagVal(obj, tgName) {
var ElemList;
//Создаем коллекцию дочерних для obj элементов, которые
//задаются тегом tgName
ElemList=obj.getElementsByTagName(tgName);
//Проверяем, есть ли в коллекции ElemList элементы
if (ElemList.length>0)
//Возвращаем значение тега tgName
return ElemList.item(0).text
else return "";
}
//Изменение значения тега tgName XML-элемента obj
function SetTagVal(obj, tgName, sVal) {
var ElemList,New;
//Создаем коллекцию дочерних для obj элементов, которые
//задаются тегом tgName
ElemList=obj.getElementsByTagName(tgName);
//Проверяем, есть ли в коллекции ElemList элементы
if (ElemList.length>0)
//Устанавливаем значениеэлемента, задаваемого
//тегом tgName
ElemList.item(0).text=sVal;
else {
//Создаем новый элемент с именем tgName
NewElem=XML.createElement(tgName);
//Добавляем новый элемент в качестве дочернего для
//элемента obj
obj.appendChild(NewElem);
//Устанавливаем значение добавленного элемента
obj.lastChild.text=sVal;
}
}
//Конструктор объекта Person
function Person() {
//Инициализируем свойства объекта
this.LastName="";
this.Name="";
this.Phone="";
this.Street="";
this.House="";
this.App="";
this.Note="";
//Устанавливаем для метода LoadDialog указатель на
//функцию Person_LoadDialog
this.LoadDialog=Person_LoadDialog;
}
//Заполнение полей в форме для текущей записи
function Person_LoadDialog() {
//Заполняем поля ввода в форме значениями соответствующих
//свойств объекта Person
doc.all.txtLastName.value = this.LastName;
doc.all.txtName.value=this.Name;
doc.all.txtPhone.value=this.Phone;
doc.all.txtStreet.value=this.Street;
doc.all.txtHouse.value=this.House;
doc.all.txtApp.value = this.App;
doc.all.txtNote.value = this.Note;
}
//Конструктор объекта ListPersons
function ListPersons() {
// Свойства объекта
//Создаем массив PersonArr экземпляров объекта Person
this.PersonArr = new Array();
//Инициализируем номер текущей записи
this.CurRecord = 0;
//Сбрасываем признак изменения данных в форме
this.IsChanged = false;
// Методы объекта
//Устанавливаем для методов указатели на соответствующие функции
this.FileToArray=ListPersons_FileToArray;
this.SaveData=ListPersons_SaveData;
this.LoadDialog=ListPersons_LoadDialog;
this.RefreshDialog=ListPersons_RefreshDialog;
this.NextRecord=ListPersons_NextRecord;
this.PreviousRecord=ListPersons_PreviousRecord;
this.FirstRecord=ListPersons_FirstRecord;
this.FinalRecord=ListPersons_FinalRecord;
this.NewRecord=ListPersons_NewRecord;
this.DelRecord = ListPersons_DelRecord;
}
//Считывание данных из XML-файла в массив объектов Person
function ListPersons_FileToArray() {
var Root,CurrNode,i;
//Создаем объект XML DOM
XML = WScript.CreateObject("Msxml.DOMDocument");
//Загружаем XML-документ из файла
XML.load(PathBook);
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//Обнуляем массив PersonArr
this.PersonArr.length=0;
//Перебираем все дочерние элементы первого уровня вложенности
//для корневого элемента
for (i=1; i<=Root.childNodes.length-1;i++) {
//Выделяем в коллекции XML-элементов i-й элемент
CurrNode=Root.childNodes.item(i);
//Создаем новый экземпляр PersonRec объекта Person
PersonRec=new Person();
//Заполняем поля объекта PersonRec
PersonRec.LastName=GetTagVal(CurrNode,"LastName");
PersonRec.Name=GetTagVal(CurrNode,"Name");
PersonRec.Phone=GetTagVal(CurrNode,"Phone");
PersonRec.Street=GetTagVal(CurrNode,"Street");
PersonRec.House=GetTagVal(CurrNode,"House");
PersonRec.App=GetTagVal(CurrNode,"App");
PersonRec.Note=GetTagVal(CurrNode,"Note");
//Сохраняем объект PersonRec в массиве PersonArr
this.PersonArr[this.PersonArr.length]=PersonRec;
}
}
//Запись данных из формы в XML-файл
function ListPersons_SaveData() {
var Root,CurrNode,ElemList;
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//Сохраняем в переменной CurrNode ссылку на (CurRecord+1)-й
//элемент Person
CurrNode=Root.childNodes.item(this.CurRecord+1);
//Записываем данные из полей ввода формы в соответствующие
//XML-элементы, которые являются дочерними узлами
//относительно CurrNode
SetTagVal(CurrNode,"LastName",doc.all.txtLastName.value);
SetTagVal(CurrNode,"Name",doc.all.txtName.value);
SetTagVal(CurrNode,"Phone",doc.all.txtPhone.value);
SetTagVal(CurrNode,"Street",doc.all.txtStreet.value);
SetTagVal(CurrNode,"House",doc.all.txtHouse.value);
SetTagVal(CurrNode,"App",doc.all.txtApp.value);
SetTagVal(CurrNode,"Note",doc.all.txtNote.value);
//Сохраняем XML-файл на диске
XML.save(PathBook);
}
//Загрузка данных для текущей записи в форму
function ListPersons_LoadDialog() {
//Вызываем метод LoadDialog для объекта Person,
//который является CurRecord-м элементом массива PersonArr
this.PersonArr[this.CurRecord].LoadDialog();
}
//Обновление данных в форме
function ListPersons_RefreshDialog(IsGoTop) {
//Обнуляем массив PersonArr
this.PersonArr.length=0;
//Заново загружаем данные из XML-файла в массив PersonArr
this.FileToArray();
if (IsGoTop)
//Переходим к первой записи в массиве
this.FirstRecord()
else
//Переходим к последней записи в массиве
this.FinalRecord();
//Загружаем в форму данные для текущей записи
this.LoadDialog();
}
//Переход к следующей записи
function ListPersons_NextRecord() {
if (this.CurRecord
//Если текущая запись не является последней, увеличиваем
//номер текущей записи
this.CurRecord++;
}
//Переход к предыдущей записи
function ListPersons_PreviousRecord() {
if (this.CurRecord > 0)
//Если текущая запись не является первой, уменьшаем
//номер текущей записи
this.CurRecord--;
}
//Переход к первой записи
function ListPersons_FirstRecord() {
this.CurRecord = 0;
}
//Переход к последней записи
function ListPersons_FinalRecord() {
this.CurRecord = this.PersonArr.length - 1;
}
//Добавление новой записи
function ListPersons_NewRecord() {
var Root,NewElem;
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//Создаем новый элемент Person
NewElem=XML.createElement("Person");
//Добавляем новый элемент в XML-файл
Root.appendChild(NewElem);
//Сохраняем XML-файл на диске
XML.save(PathBook);
//Обновлем в форме данные для последней добавленной записи
this.RefreshDialog(false);
}
//Удаление текущей записи
function ListPersons_DelRecord() {
var Root,DelNom;
//Сохраняем в переменной Root ссылку на корневой элемент
//документа
Root=XML.documentElement;
//В переменной DelNom сохраняем номер удаляемого элемента Person
DelNom=this.CurRecord+1;
//Удаляем DelNom-й элемент Person из XML-файла
Root.removeChild(Root.childNodes.item(DelNom))
//Сохраняем XML-файл на диске
XML.save(PathBook);
//Выводим сообщение о том, что запись удалена
WshShell.Popup("Запись N "+DelNom+" удалена",0,"Информация",
vbInformation+vbOkOnly);
//Обновлем в форме данные для первой записи
this.RefreshDialog(true);
}
// Обработчики событий Internet Explorer'a
//Функция-обработчик окончания загрузки документа в Internet Explorer
function ie_DocumentComplete() {
//Создаем экземпляр objListPersons объекта ListPersons
objListPersons = new ListPersons();
//Загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
//Получаем ссылку на объект Document
doc = ie.Document;
//Устанавливаем заголовок окна
doc.title = "Редактирование данных";
//Указываем функции-обработчики нажатий на кнопки формы
doc.all.btnSave.onclick=btnSave_OnClick;
doc.all.btnCancel.onclick=btnCancel_OnClick;
doc.all.btnFirst.onclick=btnFirst_OnClick;
doc.all.btnPrevious.onclick=btnPrevious_OnClick;
doc.all.btnNew.onclick=btnNew_OnClick;
doc.all.btnDelete.onclick=btnDelete_OnClick;
doc.all.btnNext.onclick=btnNext_OnClick;
doc.all.btnFinal.onclick=btnFinal_OnClick;
//Указываем функции-обработчики изменения текста в полях ввода
doc.all.txtLastName.onchange = txtBoxOnChange;
doc.all.txtName.onchange = txtBoxOnChange;
doc.all.txtPhone.onchange = txtBoxOnChange;
doc.all.txtStreet.onchange = txtBoxOnChange;
doc.all.txtHouse.onchange = txtBoxOnChange;
doc.all.txtApp.onchange = txtBoxOnChange;
doc.all.txtNote.onchange = txtBoxOnChange;
if (objListPersons.PersonArr.length < 1)
//Если в XML-файле нет данных, добавляем пустую запись
objListPersons.AddRecord();
//В качестве текущей устанавливаем первую запись
objListPersons.CurRecord = 0;
//Загружаем в форму данные из массива PersonArr
//для первой записи
objListPersons.LoadDialog();
// Делаем окно Internet Explorer'а видимым
ie.Visible = true;
}
//Функция-обработчик закрытия окна Internet Explorer'а
function ie_OnQuit() {
IsQuit=true;
//Сохраняем данные из формы в XML-файле
objListPersons.SaveData();
}
// Обработчики нажатий на кнопки в форме
//Функция-обработчик нажатия на кнопку "Сохранить"
function btnSave_OnClick() {
//Сохраняем данные из формы в XML-файле
objListPersons.SaveData();
}
//Функция-обработчик нажатия на кнопку "Отменить"
function btnCancel_OnClick() {
//Заново загружаем данные из текущего элемента массива
//в форму
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Данные восстановлены";
}
//Функция-обработчик нажатия на кнопку "<<"
function btnFirst_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к первой записи в массиве
objListPersons.FirstRecord();
//Загружаем в форму данные из массива PersonArr
//для первой записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик нажатия на кнопку "<"
function btnPrevious_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к предыдущей записи в массиве
objListPersons.PreviousRecord();
//Загружаем в форму данные из массива PersonArr
//для текущей записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик нажатия на кнопку "Новая запись"
function btnNew_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Добавляем новую запись в XML-файл
objListPersons.NewRecord();
//Загружаем в форму данные из массива PersonArr
//для добавленной записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Добавлена новая запись";
}
//Функция-обработчик нажатия на кнопку "Удалить"
function btnDelete_OnClick() {
//Удаляем текущую запись из XML-файла
objListPersons.DelRecord();
//Загружаем в форму данные из массива PersonArr
//для первой записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись удалена";
}
//Функция-обработчик нажатия на кнопку ">"
function btnNext_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к следующей записи в массиве
objListPersons.NextRecord();
//Загружаем в форму данные из массива PersonArr
//для текущей записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик нажатия на кнопку ">>"
function btnFinal_OnClick() {
//Проверяем, были ли сделаны изменения в форме
if (objListPersons.IsChanged) { //Изменения были сделаны
//Сохраняем данные в XML-файле
objListPersons.SaveData();
//Заново загружаем данные из XML-файла в массив PersonArr
objListPersons.FileToArray();
}
//Переходим к последней записи в массиве
objListPersons.FinalRecord();
//Загружаем в форму данные из массива PersonArr
//для текущей записи
objListPersons.LoadDialog();
//Выводим сообщение в заголовке окна
doc.title = "Запись N " + (objListPersons.CurRecord + 1);
}
//Функция-обработчик изменения текста в полях ввода
function txtBoxOnChange() {
//Устанавливаем признак изменения данных в форме
objListPersons.IsChanged = true;
//Выводим сообщение в заголовке окна
doc.title = "Редактирование данных";
}
//Основная запускная функция
function Main() {
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Определяем пути к файлам
InitPath();
//Создаем объект InternetExplorer.Application с возможностью
//обработки событий этого объекта
ie = WScript.CreateObject("InternetExplorer.Application", "ie_");
//Устанавливаем свойства объекта ie для отображения формы3
ie.AddressBar = false;
ie.FullScreen = false;
ie.MenuBar = false;
ie.Resizable = false;
ie.StatusBar = false;
ie.ToolBar = false;
//Устанавливаем размеры окна
ie.Height = 300; //Высота
ie.Width = 780; //Длина
IsQuit=false;
//Загружаем HTML-файл с формой
ie.Navigate(PathHTML);
while (!IsQuit)
//Приостанавливаем сценарий на 0,1 сек
WScript.Sleep(100);
}
/******************* Начало **********************************/
Main();
/************* Конец *********************************************/
Загрузка...