Druzya.org
Возьмемся за руки, Друзья...
"); Определение класса myRecord мы уже описали выше. Перейдем теперь ко второй части нашего сценария, расположенной в теле документа HTML. Здесь мы создаем два объекта rec1 и rec2 на базе класса myRecord, а затем устанавливаем свойство secure объекта rec2 в состояние true. Далее сценарий последовательно выводит в документ HTML две таблицы, соответствующие созданным объектам, вызывая для этого методы printTableHead, printRecord и printTableEnd. Как видите, применение собственного класса позволили сильно упростить задачу инициализации и отображения содержимого записей нашей воображаемой телефонной базы данных. Фактически мы свели эту задачу к вызовам нескольких методов, определенных заранее в нашем классе. Массивы в JavaScript Язык сценариев JavaScript допускает работу с массивами встроенных объектов, объектов браузера и объектов, созданных программистом. К сожалению, нет единого способа создания массивов, пригодного для применения в разных версиях браузеров. Мы расскажем вам о двух способах, первый из которых необходим для версий браузеров Netscape Navigator, более ранних чем 3.0, а второй используется новыми браузерами фирм Netscape и Microsoft. Первый способ предполагает создание собственного класса. Это можно сделать, например, так: function createArray(nLength) { this.length = nLength; for(var i = 1; i <= nLength; i++) { this[i] = 0; } return this; } Здесь в классе определено свойство с именем length, которое хранит размер массива, передаваемый конструктору класса через параметр nLength. Конструктор выполняет инициализацию массива, записывая в его ячейки нулевые значения. Таким образом мы создаем массив для хранения чисел. После инициализации конструктор возвращает ссылку на созданный объект, то есть на наш массив. Как пользоваться классом createArray? Прежде всего вы должны объявить переменную для хранения массива, а затем создать объект класса createArray с помощью ключевого слова new: var myArray; myArray = new createArray(256); После этого можно обращаться к ячейкам массива: myArray[0] = 255; myArray[1] = 254; myArray[255] = 0; Нумерация ячеек начинается с нуля. Второй способ создания массивов проще. При его использовании вы можете создать массив как объект встроенного класса Array: var myArray; myArray = new Array(256); . . . myArray[0] = 255; myArray[1] = 254; myArray[255] = 0; Так как класс Array - встроенный, вам не нужно определять его самостоятельно. Объект window Далее мы рассмотрим в деталях объекты браузера, необходимые вам практически в любом сценарии JavaScript. Прежде всего это объекты window, document, а также объекты, связанные с формами, определенными в документах HTML. Первый объект браузера, которым мы займемся вплотную, это окно - объект с именем window. Свойства объекта window Объект window имеет свойства, описывающие размеры окна, расположенные в окне фреймы, имя окна, содержимое строки состояния окна и другие: СвойствоОписаниеdefaultStatusСообщение, отображаемое в строке состояния окна браузера по умолчаниюframesМассив всех фреймов данного окнаlengthКоличество фреймов в родительском окнеnameИмя окна, указанное при его открытии методом open, а также в параметре TARGET оператора или в параметре NAME оператора
parentСиноним имени окна. Относится к окну, содержащему набор фреймов selfСиноним имени окна. Относится к текущему окнуstatusТекущее сообщение, отображаемое в строке состояния окна браузераtopСиноним имени окна. Относится к окну верхнего уровняwindowСиноним имени окна. Относится к текущему окну Что касается свойства defaultStatus, то оно используется только в браузере Netscape Navigator. Если записать в это свойство произвольное сообщение, оно будет отображаться в строке состояния Netscape Navigator, когда окно браузера выдвигается на передний план. К сожалению, браузер Microsoft Internet Explorer версий 3.02 и 4.0 игнорирует свойство defaultStatus. Свойство status, напротив, применяется обоими конкурирующими браузерами. Периодически записывая сообщение в это свойство и каждый раз сдвигая это сообщение на одну позицию, можно добиться эффекта бегущей строки. Применение строки состояния для отображения бегущей строки распространено достаточно широко. В нашей книге вы найдете пример готового сценария, выполняющего эту работу. Заметим, однако, что в браузере Microsoft Internet Explorer версии 4.0 строка состояния разделена на несколько областей. Область, содержимое которой соответствует свойству status, расположена слева и имеет относительно небольшие размеры (особенно в режимах видеоадаптера с низким разрешением). Это необходимо учитывать, если вы собираетесь использовать бегущую строку для привлечения внимания пользователя. Свойства windows и self - синонимы. Вы можете применять любое их них по своему усмотрению. Остальные свойства, в частности, свойства frames и length, применяются в том случае, когда в окно загружен документ HTML с фреймами. Анализируя свойство length вы можете определить количество фреймов в окне, а при помощи свойства frames (которое является массивом) нетрудно получить доступ к окнам этих фреймов. Работе с фреймами в сценариях JavaScript мы посвятим отдельную главу нашей книги. Методы объекта window Среди методов, определенных в объекте window, отметим методы, предназначенные для открытия новых окон и закрытия существующих, для отображения на экране простейших диалоговых панелей с сообщениями и методы для установки таймера: МетодОписаниеalertОтображение диалоговой панели Alert с сообщением и кнопкой OK closeЗакрытие окнаconfirmОтображение диалоговой панели Confirm с кнопками OK и CancelopenОткрытие окнаpromptОтображение диалоговой панели Prompt с полем ввода setTimeoutУстановка таймераclearTimeoutСброс таймера Метод alert Что касается метода alert, то мы его уже использовали в разделе первой главы с названием “Вариация пятая: с диалоговой панелью”. Там мы применили этот метод для вывода на экран простейшей диалоговой панели, отображающей приветственное сообщение. Применение некоторых других методов и свойств объекта window мы проиллюстрируем ниже на примерах составленных нами сценариев JavaScript. Приведем формат вызова метода alert: alert("Сообщение"); Через единственный параметр методу alert передается сообщение, отображаемое в диалоговой панели. После вызова этого метода выполнение сценария (точнее говоря, функции сценария, вызвавшей этот метод) задерживается до тех пор, пока пользователь не нажмет кнопку OK, расположенную в диалоговой панели с сообщением. Заметим, что при вызове метода alert мы не указали объект, для которого вызывается метод - объект window. Если при вызове метода объект не указан, интерпретатор сценария, встроенный в браузер, предполагает, что метод относится к объекту window. Тем не менее, вы можете явно указывать объект window: window.alert("Сообщение"); Результат будет тем же самым. Метод confirm С помощью метода confirm вы также можете отобразить на экране диалоговую панель с сообщением, однако в этой панели будет две кнопки - OK и Cancel. В зависимости от того, какая кнопка будет нажата, метод возвратит, соответственно, значение true или false. Метод confirm обычно используется следующим образом: if(confirm("Сообщение")) { // Нажата кнопка OK . . . } else { // Нажата кнопка Cancel . . . } Метод prompt Если вам в своем сценарии необходимо получить от пользователя одну текстовую строку, для этого можно применить метод prompt. Этот метод отображает на экране диалоговую панель, в которой есть одно текстовое поле ввода и кнопка OK. Когда пользователь нажимает эту кнопку, метод prompt возвращает введенную строку. Метод prompt вызывается следующим образом: Var szInput=””; szInput=prompt(“Сообщение”,“Строка ввода по умолчанию”); Через первый параметр методу передается сообщение, которое отображается в диалоговой панели над текстовым полем ввода. Второй параметр необязательный. Если он указан, поле ввода инициализируется текстовой строкой, заданной этим параметром. Заметим, что с помощью метода prompt сценарий может получить от пользователя только одну текстовую строку. В тех случаях, когда необходимо ввести и обработать сразу несколько строк, вы можете создать в документе HTML форму, имеющую произвольное количеством полей и кнопку завершения ввода с обработкой события. Когда пользователь нажмет эту кнопку, обработчик соответствующего события сможет извлечь из полей формы введенные значения. Подробно работа с формами будет рассмотрена в отдельной главе нашей книги. Метод open С помощью метода open сценарий может открыть новое окно браузера и загрузить в это окно документ HTML для просмотра. Формат вызова метода open приведен ниже: open("Адрес URL", "Имя Окна", "Параметры окна"); Метод возвращает имя нового окна, которое можно использовать для ссылки на свойства и методы окна, а также на свойства и методы объектов, расположенных в этом окне. Первый параметр метода open задает адрес URL документа HTML, предназначенный для загрузки в новое окно. Второй параметр определяет имя окна для использования в параметре TARGET оператора
или в операторе . Вы можете указать его как пустую строку вида “”. Третий, необязательный параметр, задает различные параметры, определяющие внешний вид создаваемого окна браузера. Этот параметр указывается как текстовая строка, где через запятую перечислены значения отдельных параметров, например: var wndNewWindow; wndNewWindow=open("hello.html", "", "toolbar=no,menubar=no,scrollbars=no,width=300,height=100"); Ниже мы перечислили все возможные параметры окна: ПараметрОписаниеtoolbarЕсли параметр имеет значение yes или 1, окно снабжается стандартной инструментальной линейкой. Если же значение этого параметр равно no, то инструментальная линейка будет отсутствоватьlocationПараметр определяет, будет ли отображаться поле ввода адреса документаdirectories Аналогично предыдущему, но управляет отображением кнопок каталогов браузера Netscape Navigator, таких как "What's New" и "What's Cool"statusОтображение строки состоянияmenubarОтображение линейки менюscrollbarsОтображение полос просмотра resizableЕсли этот параметр указан как yes или 1, пользователь сможет изменять размер вновь созданного окнаwidthШирина окна в пикселахheightВысота окна в пикселах Метод close С помощью метода close вы можете закрыть созданное вами или основное окно браузера. Формат вызова этого метода такой: wndNewWindow.close() Заметим, что текущее окно браузера (то есть окно, в которое загружен документ HTML с работающим сценарием) может быть закрыто одним из двух следующих способов: window.close() self.close() Этот метод мы будем использовать в одном сценарии, описанном ниже. Метод setTimeout С помощью метода setTimeout вы можете установить таймер, указав при этом выражение JavaScript и задержку во времени: idTimer=setTimeout(cmd, timeout); Метод setTimeout создает и запускает таймер, возвращая его идентификатор. Когда пройдет время, заданное вторым параметром timeout (в миллисекундах), запускается выражение JavaScript, заданное параметром cmd. Рассмотрим такой фрагмент сценария: var cmd="NoAccess()"; idTimer=window.setTimeout(cmd, 10000); Здесь мы создаем таймер с временем задержки 10 секунд. После прошествия этого времени будет вызвана функция с именем NoAccess, которая должна быть определена в сценарии заранее. Эта функция будет выполнена только один раз. Ниже мы приведем примеры сценариев, в которых метод setTimeout используется для периодического вызова функции сдвига сообщения в строке состояния браузера (“бегущая” строка) и для ограничения времени ввода пользователем строки пароля. Еще одно применение метода setTimeout - создание анимационных эффектов в сценарии JavaScript. Соответствующий пример вы найдете в пятой главе нашей книги, посвященной растровым графическим изображениям. Метод clearTimeout С помощью метода clearTimeout можно остановить таймер, запущенный только что рассмотренным методом setTimeout. В качестве параметра методу clearTimeout необходимо передать идентификатор таймера, полученный от метода setTimeout: clearTimeout(idTimer); События для объекта window С объектом класса window связаны два события - onLoad и onUnload. Первое из них возникает, когда браузер заканчивает загрузку окна или всех окон фреймов, определенных оператором , а второе - когда пользователь завершает работу с документом HTML. В своем сценарии вы можете предусмотреть обработку этих событий, назначив для каждого из них свою функцию. Функция, которая вызывается при завершении загрузки документа, может выполнять какие-либо инициализирующие действия, создавать дополнительные окна или выводить сообщения. Обработчик события onUnload может освобождать полученные ресурсы или выводить какие-либо дополнительные сообщения. В качестве примера рассмотрим следующий фрагмент документа HTML, содержащий сценарий: . . . function Hello() { window.alert("Welcome to my home page!") } function Bye() { window.alert("Bye! Come back again!") } . . . . . . Здесь в операторе мы определили обработчики событий onLoad и onUnload. При возникновении первого события будет вызываться функция Hello, а при возникновении второго события - функция Bye. Заметим, что так как документ HTML интерпретируется в направлении сверху вниз, функции Hello и Bye необходимо определить до появления оператора . Лучшее место для определения этих функций - заголовок документа HTML. Если вам нужно проследить загрузку всех фреймов, вы можете указать обработчик события onLoad в операторе . Сценарии, работающие с объектами window Изучение свойств и методов объектов JavaScript лучше всего проводить на конкретных примерах сценариев. В этом разделе вы найдете ряд готовых сценариев, причем некоторые из них после небольшого изменения или даже в первоначальном виде можно использовать на практике при оформлении страниц вашего сервера Web. Как закрыть окно браузера Попробуем решить задачу, невозможную без применения файла сценария, - закрыть главное окно браузера при помощи кнопки, расположенной в документе HTML (рис. 2.4). Рис. 2.4. Документ HTML, способный закрыть главное окно браузера Если нажать на кнопку с названием “Close Navigator Window”, сценарий отобразит на экране диалоговую панель, показанную на рис. 2.5. Рис. 2.5. Диалоговая панель с вопросом о закрытии главного окна браузера Данная диалоговая панель отображается с помощью метода confirm. Если вы нажмете на кнопку OK, сценарий попытается закрыть окно браузера при помощи метода close. Заметим, что браузер Microsoft Internet Explorer версии 4.0 запрашивает разрешение на закрытие окна еще раз (рис. 2.6). Рис. 2.6. Второй вопрос о закрытии главного окна браузера Исходный текст документа HTML, закрывающего главное окно браузера, представлен в листинге 2.3. Листинг 2.3. Файл chapter2/CloseAll/CloseAll.html Закрываем окно браузера

Закрываем окно браузера

Для того чтобы закрыть окно браузера, нажмите кнопку "Close Navigator Window", расположенную ниже:

В области заголовка документа определена функция CloseNavWnd: function CloseNavWnd() { if(confirm("Вы действительно желаете закрыть окно браузера?")) window.close(); } Эта функция обращается к методу confirm, который выводит на экран диалоговую панель с запросом на закрытие окна. Если пользователь нажмет кнопку OK, метод возвратит значение true, а если на кнопку Cancel - значение false. В случае положительного ответа функция CloseNavWnd вызывает метод close для текущего объекта window. В данном случае таким объектом является окно браузера. Заметим, что вместо объекта window можно указывать объект self, так как это синоним текущего окна: self.close(); Для того чтобы функция CloseNavWnd вызывалась после того как пользователь нажимает кнопку, в строке определения этой кнопки мы указали обработчик события onClick:

Таким образом, сценарии JavaScript делают формы полезными даже в тех случаях, когда вы не применяете программы CGI или расширения ISAPI. Открываем новое окно При открытии нашего следующего документа HTML на экране появляется диалоговая панель с сообщением, показанная на рис. 2.7. Рис. 2.7. Сообщение об открытии документа HTML Если нажать на кнопку OK в этой диалоговой панели, то в окне браузера появится содержимое документа (рис. 2.8). Рис. 2.8. Содержимое документа NewWnd.html В этом окне расположена кнопка “Open Hello window”. Если нажать на эту кнопку, будет создано еще одно окно браузера, в которое загрузится содержимое файла Hello.html. Однако внешний вид этого окна будет несколько необычен (рис. 2.9). Рис. 2.9. Новое окно для просмотра содержимого документа Hello.html Как видите, в окне нет ни полос просмотра, ни меню, ни инструментальной линейки. Дело в том, что создавая это окно в нашем сценарии, мы указали, что перечисленные выше элементы пользовательского интерфейса отображать не нужно. Кроме того, мы определили точные размеры окна. Если теперь закрыть окно документа NewWnd.html, на экране появится диалоговая панель с приглашением, показанная на рис. 2.10. Рис. 2.10. Диалоговая панель с приглашением Исходный текст документа HTML NewWnd.html представлен в листинге 2.4. Листинг 2.4. Файл chapter2/NewWnd/NewWnd.html Window object

Open second window

В операторе мы задали обработку событий onLoad и onUnload: Когда пользователь загружает наш документ, после окончания загрузки браузер вызывает функцию Hello, назначенную нами для обработки события onLoad. Перед удалением окна с документом вызывается обработчик события onUnload, реализованный в функции Bye. Функции Hello и Bye определены в заголовке документа HTML и не имеют никаких особенностей. Для вывода диалоговой панели с сообщением эти функции вызывают метод alert. Когда пользователь нажимает кнопку "Open Hello window", определенную в форме, вызывается функция OpenHelloWnd. Эта функция открывает новое окно браузера, загружая в него новый документ HTML. Окно открывается следующим образом: wndNewWindow = window.open("hello.html", "", "toolbar=no,menubar=no,scrollbars=no,width=300,height=100"); В качестве первого параметра методу open передается адрес URL документа HTML, который должен быть загружен в окно. Второй параметр определяет имя окна (мы его не задали), а третий - определяет параметры окна. Бегущий текст в строке состояния браузера Решим одну очень распространенную задачу - отображение бегущего текста в строке состояния браузера (рис. 2.11). Рис. 2.11. Бегущий текст в строке состояния браузера Строка состояния обычно используется браузерами для отображения различной информации, например, информации о выполнении текущей операции. Для того чтобы записать что-нибудь в строку состояния, необходимо изменить содержимое свойства status объекта window окна браузера. Эту задачу можно решить, например, так: window.status = “Новая строка”; Для создания эффекта бегущей строки операцию обновления свойства status необходимо выполнять периодически, отображая текст с изменяющимся сдвигом. Однако не стоит делать это в цикле, так как в результате нормальная работа браузера будет нарушена. В нашем сценарии (листинг 2.5) мы применим способ выполнения периодических процедур, основанный на использовании метода setTimeout, определенного для объекта window. Напомним, что этот метод позволяет организовать отложенное во времени выполнение команды, заданной первым параметром. Время, через которое команда будет запущена, указывается методу setTimeout вторым параметром. Листинг 2.5. Файл chapter2/StatusScroll/StatusScroll.html Авторский компакт-диск

Новый выпуск авторского CD

Первый выпуск нашего компакт-диска уже появился в продаже. Информацию об этом, а также следующем выпуске вы найдете на нашем сервере Web, адрес которого отображается в окне состояния браузера В области заголовка документа мы определили глобальные переменные szMsg, nSpace и nIteration, а также функцию sscroll. Переменная szMsg инициализируется текстовым сообщением, которое будет непрерывно перемещаться в строке состояния браузера. Значение, записанное в переменную nSpace, определяет количество пробелов, которое будет добавлено к строке сообщения слева перед началом операции сдвига. И, наконец, переменная nIteration служит счетчиком сдвигов для функции sscroll. Функция sscroll вызывается первый раз в теле документа:

Новый выпуск авторского CD

. . . В дальнейшем функция sscroll организует при помощи метода setTimeout свой собственный вызов, отложенный во времени на 50 миллисекунд, и завершает работу. Однако через указанное время наша функция будет вызвана вновь, и это будет продолжаться до тех пор, пока документ HTML, содержащий сценарий, остается загруженным в окно браузера. Упрощенно структура функции sscroll показана ниже: function sscroll() { var cmd = "sscroll()"; . . . // Отображение сообщения в строке состояния браузера . . . // Сдвиг сообщения влево на одну позицию . . . timer = window.setTimeout(cmd, 50); } После отображения сообщения в строке состояния и сдвига этого сообщения влево на одну позицию функция sscroll вызывает метод setTimeout, передавая ему через первый параметр переменную с командой, подлежащей выполнению, а через второй - время задержки, по прошествии которого данную команду нужно будет выполнить. В качестве выполняемой команды мы указываем методу setTimeout вызов функции sscroll. Таким образом в нашем сценарии эта функция вызывается периодически. В функции sscroll мы определили три локальные переменные. Переменная cmd хранит команду вызова функции sscroll. В переменной szOut мы подготавливаем текст, отображаемый в строке состояния браузера при каждом вызове функции sscroll. Текстовая переменная szText используется как рабочая. В ней формируется сообщение для вывода. Вначале в переменную szText записывается nSpace пробелов, а затем добавляется строка szMsg: for (i=0 ; i < nSpace ; i++) { szText += " "; } szText += szMsg; Для того чтобы при каждом вызове функции sscroll наше сообщение отображалось со сдвигом на одну позицию, мы извлекаем из переменной szText подстроку. Извлечение подстроки выполняется с помощью метода substring, определенного во встроенном классе текстовых строк String. Полученная подстрока записывается в свойство status объекта window и таким образом отображается в строке состояния: szOut = szText.substring(nIteration, nSpace + nIteration); window.status = szOut; Первый параметр метода substring определяет начальную позицию подстроки внутри строки, а второй - конечную. После отображения сообщения функция sscroll увеличивает значение глобального счетчика nIteration на единицу: nIteration++; Когда в результате сдвига сообщение полностью уходит из строки состояния, счетчик nIteration снова устанавливается в нулевое значение: if(nIteration > nSpace + szMsg.length) { nIteration = 0; } Обратите внимание, что общая длина сдвигаемой строки здесь вычисляется как сумма значения nSpace (количество начальных пробелов) и длины сообщения szMsg. Последняя определяется с помощью метода length, определенного во встроенном классе String. Ограничение времени реакции пользователя Иногда пользователь, попав на страницу Web, долго не может понять, что нужно делать. Вы можете создать сценарий, который отображает в этой ситуации документ HTML с подсказкой. Разумеется, подсказка должна отображаться только в том случае, если пользователь не выполняет над вашей страницей никаких действий в течении достаточно продолжительного времени. Но как измерить время, в течении которого пользователь не активен? В этом вам помогут методы setTimeout и clearTimeout. Первый из этих методов мы уже использовали в предыдущем сценарии для организации периодического выполнения функции. Мы продемонстрируем применение этих методов для решения другой задачи, связанной с ограничением времени ввода пароля. Когда пользователь загружает документ HTML, исходный текст которого представлен в листинге 2.6, на экране появляется форма с полем, предназначенным для ввода текстовой строки пароля (рис. 2.12). Рис. 2.12. Форма в документе HTML для ввода пароля Сразу после загрузки документа в окно браузера сценарий запускает таймер, вызывая метод setTimeout из этого же класса. Таймер устанавливается на 10 секунд. Именно за это время вы должны ввести пароль и нажать кнопку “Enter Password” в форме, показанной на рис. 2.12, чтобы получить доступ к странице. Если повременить с вводом пароля или ввести неправильный пароль, сценарий загружает в окно браузера динамически сформированный документ HTML с сообщением о запрещении доступа (рис. 2.13). Рис. 2.13. Сообщение о запрещенном доступе Только в том случае, если пароль введен правильно и в течении 10 секунд, на экране появляется сообщение о предоставлении доступа и ссылка, с помощью которой можно перейти к просмотру главной страницы нашего сервера Web (рис. 2. 14). Рис. 2.14. Сообщение о разрешении доступа и ссылка на главную страницу нашего сервера Web Разумеется, приведенный нами пример едва ли стоит использовать на практике для ограничения доступа к странице сервера Web. Во-первых, исходный текст сценария легко просмотреть и проанализировать (если только сценарий не находится в отдельном файле, адрес которого указан при помощи параметра SRC). Во-вторых, узнав один раз адрес страницы сервера, пользователь может просто отметить эту страницу закладкой и в дальнейшем посещать ее без ввода пароля. Мы привели данный пример сценария только для иллюстрации применения методов класса window. С помощью аналогичного сценария вы можете узнать, не заснул ли пользователь, пока смотрел на вашу страницу. Теперь рассмотрим исходный текст сценария JavaScript, встроенного в документ HTML (листинг 2.6). Листинг 2.6. Файл chapter2/Password/Password.html Ввод пароля

Доступ ограничен

Мы ограничили доступ к нашему серверу :)

Вы должны ввести пароль (слово password) в течении 10 секунд.



Прежде всего обратим ваше внимание на заголовок документа HTML. В первой странице этого заголовка мы указали с помощью оператора номер кодовой страницы 1251, соответствующей кириллице в Windows: Без этой строки наш документ отображался неправильно браузером Microsoft Internet Explorer версии 4.0. В первых строках сценария, расположенного в заголовке документа, мы объявили переменную idTimer и определили функцию StartMyTimer: var idTimer=0; function StartMyTimer() { var cmd="NoAccess()"; idTimer=window.setTimeout(cmd, 10000); } Функция StartMyTimer запускает таймер, сохраняя его идентификатор в глобальной переменной idTimer. Для запуска таймера мы применили знакомый вам метод с именем setTimeout. Когда таймер сработает (а это произойдет через 10 секунд после загрузки нашего документа HTML в окно браузера), будет вызвана функция NoAccess. Эта функция выводит в окно браузера сообщение о запрещении доступа к странице. Для того чтобы функция StartMyTimer запускалась сразу после загрузки документа HTML в окно браузера, мы указали ее имя в параметре onLoad оператора , организовав таким образом обработку соответствующего события: Итак, если пользователь загрузил документ и просто смотрит на него, через 10 секунд содержимое документа в окне браузера будет перезаписано функцией NoAccess, что иллюстрируется на рис. 2.13. Для ввода пароля необходимо использовать форму, которая определена в нашем документе HTML следующим образом:

Имя формы pwdForm указано в параметре NAME оператора
. Это имя нам потребуется для извлечения строки пароля из текстового поля, определенного в форме с помощью оператора . Имя этого текстового поля pwd также задается параметром NAME. Помимо текстового поля, в форме имеется кнопка с надписью “Enter Password”. Для этой кнопки мы определили обработчик события onClick, который вызывается, когда пользователь нажимает мышью на кнопку. Обработчиком в нашем случае является функция CheckPassowd, определенная в нашем сценарии. Эта функция проверяет пароль и, если пароль введен правильно, останавливает таймер, запущенный при загрузке документа HTML. Как наш сценарий извлекает строку пароля из поля формы? Это делается следующим образом: var szPwd=""; szPwd=document.pwdForm.pwd.value; Здесь мы выполняем ссылку на свойство value объекта pwd, которым является текстовое поле формы (вспомните, что это поле называется pwd). Объект pwd находится внутри формы с именем pwdForm, которая, в свою очередь располагается в документе HTML, загруженным в окно браузера. Этим документом является объект document. Получив введенную пользователем строку, функция CheckPassowd проверяет ее: if(szPwd=="password") { clearTimeout(idTimer); . . . } Если строка введена правильно, таймер останавливается методом clearTimeout. В качестве параметра этому методу передается идентификатор таймера, полученный от метода setTimeout. При ошибке в документ HTML записывается сообщение о запрещении доступа. Загрузка документа HTML в окно браузера В разделе этой главы с названием “Открываем новое окно” мы рассказали вам о том, как сценарий JavaScript может открыть новое окно, загрузив в него документ HTML. Однако часто возникает и другая задача - отобразить новый документ HTML в текущем окне браузера, не создавая новое окно. Наш следующий сценарий (листинг 2.7) решает как раз эту задачу. Листинг 2.7. Файл chapter2/JumpTo/JumpTo.html Jump to other Web page

Jump to other Web page

Когда в пользователь нажимает кнопку Jump в форме selectForm (показанной на рис. 2.15), запускается функция urlJump. Рис. 2.15. Кнопка Jump, предназначенная для перехода к просмотру другой страницы Web Эта функция вызывает метод prompt, определенный в классе window: var szNewURL=""; szNewURL=prompt("Enter new URL address:", "http://"); Метод prompt отображает на окне монитора диалоговую панель, предназначенную для ввода текстовой строки. В нашем случае это должна быть строка адреса URL документа HTML, который будет загружен в окно браузера (рис. 2.16). Рис. 2.16. Диалоговая панель для ввода нового адреса URL Введенный адрес (на рис. 2.16 мы ввели адрес главной страницы нашего сервера Web) записывается в переменную szNewURL. Теперь можно переходить к загрузке нового документа в окно браузера. Когда мы рассказывали об объектах класса window, то говорили, что такие объекты содержат в себе другие объекты. В частности, объект window содержит в себе объект location, описывающий расположение документа HTML, загруженного в окно браузера. Для того чтобы загрузить в окно новый документ, достаточно изменить содержимое свойства объекта location с именем href: window.location.href=szNewURL; Это свойство хранит адрес URL документа. Изменение содержимого свойства href объекта location главного окна браузера приводит к загрузке в это окно нового документа (рис. 2.17). Рис. 2.17. В главное окно браузера загружен новый документ HTML Объект document Специально для работы с документами HTML в языке JavaScript имеется отдельный объект с названием document. Пользуясь его свойствами и методами, сценарий JavaScript может получить информацию о текущем документе, загруженном в окно браузера, а также управлять отображением содержимого этого документа. В первой главе нашей книги мы уже применяли один из методов объекта document с именем write для записи строки в тело документа HTML. Когда в 29 томе “Библиотеки системного программиста” мы рассказывали о документах HTML, то говорили, что такие документы состоят из заголовка и тела документа. Заголовок определяется при помощи оператора языка HTML , а тело документа - при помощи оператора . Прежде чем мы перейдем к описанию свойств и методов объекта document, рассмотрим назначение отдельных параметров оператора . В общем виде этот оператор выглядит следующим образом: Описание параметров оператора приведено ниже: ПараметрОписаниеBACKGROUNDС помощью этого параметра можно указать адрес URL изображения, заполняющего фон тела документаBGCOLORПараметр BGCOLOR применяется в тех случаях, когда фон документа необходимо раскрасить в какой-либо цвет. Цвет задается в виде "#rrggbb", где константы rr, gg и bb - соответственно, красная, зеленая и голубая компоненты цвета. Значение констант может находиться в диапазоне от 0 до FF (в шестнадцатеричном виде). Цвет может также задаваться символическими константами, такими как red или whiteTEXTЦвет текста. Задается таким же образом, что и цвет фона BGCOLORLINKПараметр LINK определяет цвет ссылок, размещенных в документе HTML, и еще не посещенных пользователемALINK Этот параметр определяет цвет ссылок, выбранных пользователемVLINKПараметр VLINK определяет цвет ссылок, размещенных в документе HTML, которые уже посещались пользователем ранееonLoadС помощью параметра onLoad можно определить обработчик события, который получит управление при загрузке документа в окно браузераonUnloadАналогично предыдущему, однако обработчик события получит управление при удалении документа из окна браузера Анализируя свойства объекта document, сценарий JavaScript может определить значения перечисленных выше параметров. Кроме того, сценарию доступны локальные метки, формы и связи документа как элементы соответствующих массивов, а также информация из заголовка документа. Свойства объекта document Перечислим свойства объекта document, доступные сценарию JavaScript: СвойствоОписаниеalinkColorСодержимое параметра ALINKanchorsМассив локальных меток, размещенных в документе. Эти метки применяются для организации ссылок внутри документаappletsМассив объектов, соответствующих аплетам Java, расположенным в документе HTML bgColorСодержимое параметра BGCOLOR cookie Значение cookie для текущего документа. О том, что это такое, мы расскажем в последней главе нашей книгиembedsМассив объектов plug-in, содержащихся в документе HTMLfgColorСодержимое параметра TEXT formsМассив, содержащий в виде объектов все формы, расположенные в документе HTMLimagesМассив растровых изображений, включенных в документlastModifiedДата последнего изменения документа HTMLlinkColorСодержимое параметра LINKlinksМассив, содержащий все ссылки в документе HTMLlocationПолный адрес URL документа HTMLreferrerАдрес URL вызывающего документа HTMLtitleЗаголовок документа, заданный с помощью оператора URLПолный адрес URL документа HTMLvlinkColorСодержимое параметра VLINK Объект document может содержать в себе другие объекты, доступные как свойства: СвойствоОписаниеanchorЛокальная метка, определенная в документе HTML с помощью оператора <A>formФорма, определяемая в документе HTML с помощью оператора <FORM>historyСписок адресов URL, посещенных пользователемlinkТекст или изображение, играющее роль гипертекстовой ссылки. Создается с помощью оператора языка HTML <A>, в котором дополнительно задаются обработчики событий onClick и onMouseOver Методы объекта document Сценарии JavaScript могут вызывать следующие пять методов, определенных в объекте document: МетодОписаниеclearУдаление содержимого документа из окна просмотраcloseЗакрытие потока данных, открытого для документа методом open. В окне будут отображены все изменения содержимого документа, сделанные сценарием после открытия потока openОткрытие выходного потока для записи в документ HTML данных типа MIME при помощи методов write и writelnwriteЗапись в документ произвольной конструкции языка HTMLwritelnАналогично предыдущему, но в конце строки добавляется символ новой строки Цветовое оформление документа Большинство свойств объекта objects доступно сценарию JavaScript как для чтения, так и для записи. Сначала мы попробуем динамически изменить цветовое оформление документа HTML, показанного на рис. 2.18. Рис. 2.18. Документ HTML с цветовым оформлением, измененным при помощи сценария JavaScript Сценарий изменил пять свойств документа HTML - цвет фона и текста, а также цвета посещенных, не посещенных и выбранных пользователем ссылок (листинг 2.8). Листинг 2.8. Файл chapter2/ColorLinks/ColorLinks.html <HTML> <HEAD> <TITLE>Color Links

Изменение цветового оформления

Посетите эти серверы:

Наша домашняя страница

Каталог программ Auramedia

Страница сервера Microsoft про Java

Локальный раздел


Локальный раздел

Этот локальный раздел вы можете просмотреть, даже если ваш компьютер не подключен к Internet Обратите внимание, что наш сценарий переопределяет цвет фона, заданный параметром BGCOLOR в операторе : document.bgColor = "#00FF80"; Немного усложнив сценарий, вы можете изменять цвет фона, например, в зависимости от времени суток или от календарной даты. Например, цвет страницы по выходным дням можно сделать праздничным, а по рабочим - деловым. Выбор цифровых констант, определяющих праздничный и деловой цвета в шестнадцатеричном виде, мы оставляем на ваше усмотрение или на усмотрение вашего дизайнера. Ссылки и метки в документе Как мы уже рассказывали в 29 томе “Библиотеки системного программиста” с названием “Сервер Web своими руками”, для того чтобы вставить в документ HTML ссылку или локальную метку, необходимо использовать оператор . В общем виде этот оператор представлен ниже: Текст ссылки Описание параметров оператора мы привели ниже: ПараметрОписаниеHREFПараметр HREF задает адрес URL или имя локальной метки документа, куда будет сделан переход по ссылкеNAMEЕсли указан параметр NAME, оператор определяет локальную метку. Значение этого параметра задает имя меткиTARGETПараметр TARGET задает имя окна, куда будет загружен документ при выполнении ссылки. Это может быть имя существующего окна фрейма, определенного с помощью оператора , или одним из следующих зарезервированных имен - _top, _parent, _self, или _blankonClickС помощью параметра onClick можно определить обработчик события, который получит управление, когда пользователь сделает щелчок левой клавишей мыши по ссылкеonMouseOverАналогично предыдущему, однако обработчик события получит управление, когда пользователь разместит курсор мыши над ссылкой Для каждой ссылки, размещенной в документе HTML, создается отдельный объект. Все такие объекты находятся в объекте документа Document как элементы массива links. Сценарий JavaScript может определить свойства каждой ссылки, расположенной в документе HTML, анализируя элементы объекта links. Вот список этих свойств: СвойствоОписаниеhashИмя локальной ссылки, если она определена в адресе URLhost Имя узла и порт, указанные в адресе URLhostnameИмя узла и доменное имя узла сети. Если доменное имя недоступно, вместо него указывается адрес IPhrefПолный адрес URLpathnameПуть к объекту, указанный в адресе URLportНомер порта, используемого для передачи данных с сервером, указанным в данной ссылкеprotocol Строка названия протокола передачи данных (включающая символ “двоеточие”), указанного в ссылкеsearchСтрока запроса, указанная в адресе URL после символа “?”targetЗначение параметра TARGET, заданное в ссылкеlengthКоличество элементов в массиве links, то есть количество ссылок в текущем документе HTML Рассмотрим пример сценария JavaScript, работающего со ссылками как с элементами массива links. Мы приведем пример документа, с формой, списком и кнопкой Jump. Сценарий JavaScript заполняет список ссылками, размещенными в документе HTML. Внешний вид этого документа показан на рис. 2.19. Рис. 2.19. Документ со списком расположенных в нем ссылок Выбрав из списка ссылку и нажав кнопку Jump, вы загрузите в окно браузера документ, указанный в этой ссылке или запустите почтовую программу для подготовки и отправки сообщения (если выбрана ссылка на адрес электронной почты). Так как список ссылок формируется сценарием динамически, новые ссылки, добавленные в документ HTML, появятся в списке автоматически без дополнительных усилий по редактированию сценария. В нижней части этого же документа HTML, показанного на рис. 2.20, сценарий отображает детальную информацию по каждой ссылке, извлеченную из свойств объектов класса links, соответствующих ссылкам. Рис. 2.20. Детальная информация о ссылках Что за информация здесь отображается? Вначале выводятся свойства перовй ссылки, содержащей адрес главной страницы нашего сервера Web в сети Internet: http://www.glasnet.ru/~frolov/index.html host: www.glasnet.ru:80 hostname: www.glasnet.ru href: http://www.glasnet.ru/~frolov/index.html pathname: ~frolov/index.html port: 80 protocol: http: search: target: Так как в этой ссылке указан полный адрес URL, включающий путь к файлу документа index.html, то этот путь записывается в свойство с именем pathname. Хотя порт, с использованием которого устанавливается соединение с сервером Web, не указан, в свойства host и port записывается значение, применяемое для этой цели по умолчанию, а именно 80. Рассмотрим следующую ссылку: http://www.auramedia.ru/ host: www.auramedia.ru:80 hostname: www.auramedia.ru href: http://www.auramedia.ru/ pathname: port: 80 protocol: http: search: target: Здесь путь к файлу документа HTML не указан, поэтому свойство pathname содержит пустую строку. В ссылке на сервер Microsoft мы указали путь к каталогу java: http://www.microsoft.com/java/ host: www.microsoft.com:80 hostname: www.microsoft.com href: http://www.microsoft.com/java/ pathname: java/ port: 80 protocol: http: search: target: newwnd Этот частичный путь оказался записанным в свойство pathname. Кроме того, для отображения содержимого сервера Microsoft должно быть создано новое окно. Имя этого окна задано как newwnd в параметре TARGET оператора . С помощью этого оператора мы разместили ссылку в документе HTML. Как и следовало ожидать, имя окна оказалось записано в свойство target. Последняя ссылка - это адрес электронной почты: mailto:[email protected] host: glas.apc.org hostname: glas.apc.org href: mailto:[email protected] pathname: port: 0 protocol: mailto: search: target: В свойстве protocol данной ссылки записана строка “mailto:”. Рассмотрим теперь исходный текст документа HTML, содержащий сценарий JavaScript, работающий со ссылками (листинг 2.9). Листинг 2.9. Файл chapter2/LinksList/LinksList.html Links and Anchors

Просмотр ссылок

Посетите эти серверы:

Наша домашняя страница
Каталог программ Auramedia
Страница сервера Microsoft про Java

Пишите нам по адресу: frolov@glas. apc.org


Список ссылок

Этот список сформирован динамически сценарием JavaScript

В секции заголовка документа HTML определена функция urlJump, загружающая в окно браузера объект, соответствующий выбранной в списке ссылке: function urlJump() { var szNewURL=""; szNewURL = document.links[Sel.ListOfLinks.selectedIndex]; window.location.href=szNewURL; } Список ссылок, а также кнопка Jump, служащая для активизации выбранной ссылки, определена следующим образом: Имя формы, необходимое сценарию JavaScript для доступа к списку и кнопке, определено в параметре NAME оператора как Sel. Список с именем ListOfLinks создается оператором В результате у объекта Document появилось свойство Sel. К этому свойству можно адресоваться следующим образом: Document.Sel Любая форма содержит определения полей и органов управления, таких как списки, переключатели и кнопки. При определении полей и органов управления им можно задать имя, указав его в параметре NAME соответствующего оператора языка HTML. В примере, приведенном выше, в форме определен список с именем ListOfLinks. Для адресации из сценария JavaScript отдельных органов управления можно воспользоваться тем фактом, что они доступны как свойства содержащих их форм. Например, если в форме Sel определен список ListOfLinks, то для доступа к списку как к объекту вы можете использовать следующее выражение: Document.Sel.ListOfLinks Так как поля формы и органы управления являются объектами, то для них определены свои свойства и методы. Например, свойство selectedIndex, содержащее номер выбранного пользователем элемента списка, доступно следующим образом: Document.Sel.ListOfLinks.selectedIndex С помощью рис. 2.2 вы можете проследить иерархию объектов документа и, в частности, иерархию объектов в формах. Заметим, что в качестве одного из свойств объекта Document определено свойство forms. Это массив всех форм, расположенных в документе HTML. Размер массива равен document.forms.length. Вы можете адресоваться к формам как к элементам массива forms, причем первый элемент массива (с индексом 0) соответствует самой первой форме, определенной в документе, второй - следующей и так далее. Однако удобнее обращаться к формам по их именам, заданным в параметре NAME оператора . Форма и ее свойства Подробно о том, как создавать формы в документах HTML, мы рассказывали в 29 томе “Библиотеки системного программиста”. Сейчас мы повторим основные моменты, сделав акцент на вопросах, важных для обработки форм средствами сценариев JavaScript. Оператор
В наиболее общем виде оператор , предназначенный для создания форм в документах HTML, выглядит следующим образом: . . . определение полей и органов управления . . . Параметр NAME задает имя формы. Вы можете его не указывать, если форма не предназначена для совместной работы со сценарием JavaScript, однако это не наш случай. Нам это имя нужно для адресации формы как свойства объекта Document, поэтому мы всегда будем его задавать. Назначение параметра TARGET аналогично назначению этого же параметра в операторе . Когда форма используется для передачи запроса расширению CGI или ISAPI сервера Web, ответ, полученный от сервера, отображается в окне. Имя этого окна задано параметром TARGET. Если ответ должен отображаться в том же окне, что и форма, то параметр TARGET задавать не нужно. С помощью параметра ACTION указывается адрес URL загрузочного файла программы CGI или библиотеки динамической компоновки DLL расширения ISAPI, а также передаваемые расширению параметры. В том случае, когда форма предназначена для передачи данных расширению сервера Web, параметр ACTION является обязательным. Но если данные, введенные в форме, обрабатываются сценарием JavaScript локально и не передаются серверу Web, этот параметр можно опустить. Параметр METHOD задает метод передачи данных из формы расширению сервера Web и может принимать значения GET или POST. Подробнее об этом вы можете прочитать в только что упомянутом нами 29 томе “Библиотеки системного программиста”. Если данные из полей формы обрабатываются сценарием JavaScript локально, параметр METHOD задавать не нужно. Параметр ENCTYPE задает тип MIME передаваемых данных и используется очень редко. Если форма предназначена для передачи текстовых данных (как это обычно бывает), этот параметр по умолчанию имеет значение application/x-www-form-urlencoded. В этом случае для передаваемых данных используется так называемая кодировка URL. Тип данных multipart/form-data позволяет передавать как текстовые, так и двоичные данные. Очевидно, при локальной обработке данных сценарием JavaScript параметр ENCTYPE не задается. Помимо параметров, для формы можно определить обработчик события, связанный с кнопкой типа SUBMIT. Такая кнопка предназначена для посылки данных из заполненной формы расширению сервера Web. Назначив обработчик события, сценарий JavaScript может управлять этим процессом. Свойства объекта form Объект form имеет два набора свойств, состав одного из которых является фиксированным, а состав другого зависит от того, какие поля и органы управления определены в форме. Первый набор свойств приведен ниже: СвойствоОписаниеactionСодержит значение параметра ACTIONelementsМассив всех элементов (полей и органов управления), определенных в формеencodingСодержит значение параметра ENCTYPElengthРазмер массива elementsmethodСодержит значение параметра METHODtargetСодержит значение параметра TARGET Большинство свойств первого набора просто отражает значения соответствующих параметров оператора
. Вы можете их использовать в сценариях JavaScript для проверки параметров. Что же касается массива elements, то в нем находятся объекты, соответствующие полям и органам управления, определенным в форме. Эти объекты образуют второй набор свойств объекта form: СвойствоОписаниеbuttonКнопка с заданной надписьюcheckboxПереключатель типа Check Box. Может использоваться в составе набора независимых друг от друга переключателей или отдельноhiddenСкрытое поле, которое не отображается. Содержимое этого поля может быть считано и проанализировано расширением сервера Web, либо сценарием JavaScriptpasswordТекстовое поле для ввода паролей. Набранный в этом поле текст не отображается на экранеradioПереключатель для группы зависимых друг от друга переключателей. Используется обычно для выбора одного значения из нескольких возможныхresetКнопка, с помощью которой пользователь может сбросить содержимое полей ввода и состояние переключателей в их исходное состояниеselectСписок произвольных текстовых строкsubmitКнопка для посылки данных из заполненной формы расширению сервера Web. Для этой кнопки можно задать произвольную надписьtextОднострочное текстовое полеtextarea Многострочное текстовое поле Объекты, входящие в состав форм Далее мы приступим к изучению свойств и методов перечисленных в предыдущем разделе объектов. Для каждого объекта мы приведем пример сценария JavaScript, иллюстрирующего основные приемы работы с объектом. Кнопка button В общем виде кнопка класса button определяется в форме с помощью оператора следующим образом: Параметр TYPE оператора должен иметь значение button, как это показано в нашем примере. С помощью параметра NAME задается имя объекта, соответствующего кнопке (а не надпись на кнопке). Надпись на кнопке указывается с помощью параметра VALUE. Определив обработчик события, вы можете задать сценарий JavaScript, который получит управление после того как пользователь нажмет на кнопку. Свойства объекта button Объект button имеет два свойства, отражающие значения соответствующих параметров оператора : СвойствоОписаниеnameЗначение параметра NAMEvalueЗначение параметра VALUE Методы объекта button Для объекта button определен всего один метод, не имеющий параметров, - click: click() Вызов этого метода приводит к такому же эффекту, что и щелчок левой клавишей мыши по кнопке. Пример сценария В качестве первого примера мы приведем сценарий, выполняющего обработку щелчка по кнопке с надписью Click me, расположенной в форме (рис. 3.1). Рис. 3.1. Форма в документе HTML с кнопкой Если нажать на эту кнопку, сценарий отобразит в окне браузера свойства кнопки как объекта класса button (рис. 3.2). Рис. 3.2. Отображение свойств кнопки как объекта класса button Исходный текст документа HTML со встроенным в него сценарием JavaScript приведен в листинге 3.1. Листинг 3.1. Файл chapter3/button/button.html Button demo

Click Button

В теле документа HTML определена форма с именем TestForm, для чего в операторе
мы указали параметр NAME. Другие параметры этого оператора здесь не нужны. Форма содержит одну-единственную кнопку с именем bt и надписью Click me. Для этой кнопки в качестве обработчика события мы назначили функцию btnClick, определенную в заголовке документа HTML. Когда пользователь нажимает кнопку, функция btnClick получает управление и сохраняет в текстовых переменных szTxt и szTxt1 надпись и имя кнопки, соответственно: szTxt=document.TestForm.bt.value; szTxt1=document.TestForm.bt.name; Затем функция выводит в окно браузера строку, ограниченную сверху и снизу разделительной линией, отображающую значение свойств value и name: document.write("


"); document.write("You press button: " + szTxt.bold() + ", name=" + szTxt1.bold()); document.write("
"); Переключатель checkbox Переключатели checkbox обычно применяются для выбора каких-либо независимых друг от друга параметров или возможностей. В форме переключатель checkbox создается с помощью оператора с параметром TYPE, равным строке "checkbox": Текст, отображаемый рядом с переключателем Параметр NAME задает имя переключателя. Это имя можно использовать для определения состояния этого переключателя в сценарии JavaScript. С помощью параметра VALUE вы можете определить строку, которая передается расширению сервера при посылке заполненной формы, если переключатель находится во включенном состоянии. Если этот параметр не указан, то по умолчанию посылается строка “on”. Сценарий JavaScript также может получить значение параметра VALUE. Необязательный параметр CHECKED указывается в том случае, если при начальном отображении формы переключатель должен отображаться во включенном состоянии. Если для переключателя определен обработчик события, вы можете задать сценарий JavaScript, получающий управление после того как пользователь изменит состояние переключателя. Свойства объекта checkbox Объект checkbox имеет несколько свойств, отражающих значения соответствующих параметров оператора : СвойствоОписаниеnameЗначение параметра NAMEcheckedСвойство типа Boolean, отражающее состояние переключателя. Если переключатель включен, свойство имеет значение true, в противном случае - false. С помощью этого свойства сценарий может изменять состояние переключателяvalueЗначение параметра VALUE defaultCheckedСвойство типа Boolean, отражающее значение параметра CHECKED. Если параметр CHECKED присутствует в определении переключателя, свойство имеет значение true, в противном случае - false. Сценарий может определять или устанавливать значение этого свойства Методы объекта checkbox Для объекта checkbox определен один метод click, не имеющий параметров: click() При вызове этого метода переключатель устанавливается во включенное состояние. Переключатель radio Переключатели типа radio применяются в тех случаях, когда нужно организовать выбор одной из нескольких возможностей. Исходя из этого, в форме обычно располагается несколько таких переключателей. Определение переключателя radio выглядит следующим образом: Текст, отображаемый рядом с переключателем Назначение параметров NAME, VALUE и CHECKED переключателя radio такое же как и назначение аналогичных параметров переключателя checkbox. Отличие заключается в том, что все переключатели radio, принадлежащие к одной группе, должны иметь одинаковые имена, определенные параметром NAME. Что же касается переключателей checkbox, то если их несколько, то все они должны называться по-разному. Для того чтобы расширение сервера Web или сценарий JavaScript, обрабатывающие форму, могли узнать, какой же из переключателей radio группы находится во включенном состоянии, все такие переключатели должны иметь различные значения VALUE. Кроме того, только один из переключателей radio может быть определен с параметром CHECKED. Свойства объекта radio Объект radio имеет следующие свойства: СвойствоОписаниеnameЗначение параметра NAMEcheckedСвойство типа Boolean, отражающее состояние переключателя. Если переключатель включен, свойство имеет значение true, в противном случае - false. С помощью этого свойства сценарий может изменять состояние переключателяlengthКоличество переключателей типа radio, определенных в группе с именем, заданным параметром NAMEvalueЗначение параметра VALUEdefaultCheckedСвойство типа Boolean, отражающее значение параметра CHECKED. Если параметр CHECKED присутствует в определении переключателя, свойство имеет значение true, в противном случае - false. Сценарий может определять или устанавливать значение этого свойства Методы объекта radio Для объекта radio определен метод click, не имеющий параметров: click() При вызове этого метода переключатель выбирается для работы. Пример формы с переключателями В этом разделе мы приведем исходный текст документа HTML со сценарием, предназначенным для динамического создания новой страницы при помощи сценария JavaScript. Параметры этой страницы определяются состоянием переключателей типа checkbox и radio, расположенными в этом документе (рис. 3.3). Рис. 3.3. Форма с переключателями различных типов Наш документ содержит одну форму, в которой есть три переключателя с независимой фиксацией типа checkbox (расположенные в группе Page elements), три переключателя с зависимой фиксацией (образующие группу Text color), и две кнопки - Create Page и Reset. Если включен переключатель Show title, создаваемый сценарием JavaScript документ HTML будет снабжен заголовком. При включении переключателя Show horizontal lines информация о состоянии переключателей, отображаемая в документе, будет выделена сверху и снизу горизонтальными разделительными линиями. Переключатель Table view влияет на способ отображения информации. Если он включен, информация будет показана в табличном виде, а если выключен - в виде списка (рис. 3.4). Рис. 3.4. Отображение состояния переключателей в виде списка Внешний вид страницы при включении всех трех переключателей группы Page elements показан на рис. 3.5. Рис. 3.5. Отображение состояния переключателей в виде таблицы с заголовком, выделенной линиями Переключатели с зависимой фиксацией группы Text color, расположенные в исходном документе HTML, задают цвет строк при отображении информации в виде списка или цвет названий переключателей при табличном отображении. В нижней части формы находятся две кнопки с надписями Create Page и Reset. Если нажать на первую из этих кнопок, будет вызвана функция JavaScript, которая определит текущее состояние переключателей и сформирует новый документ HTML. Этот документ появится в окне браузера вместо исходного. С помощью кнопки Reset можно установить начальное состояние переключателей. Текст документа HTML со сценарием, выполняющим все описанные выше действия, представлен в листинге 3.2. Листинг 3.2. Файл chapter3/checkradio/checkradio.html Переключатели checkbox и radio Page elements:

Show title
Show horizontal lines
Table view

Text color:

Red
Green
Blue

 
 
Наши Друзья

Александр Градский
Мемориальный сайт Дольфи. 
				  Светлой памяти детей,
				  погибших  1 июня 2001 года, 
				  а также всем жертвам теракта возле 
				 Тель-Авивского Дельфинариума посвящается...

 
liveinternet.ru: показано количество просмотров и посетителей

Библиотека :: Компьютеры и Программирование :: А.В. Фролов, Г.В. Фролов - Сценарии JavaScript в активных страницах Web
 [Весь Текст]
Страница: из 116
 <<-
 
АННОТАЦИЯ
   В книге описан язык JavaScript, предназначенный для создания активных 
страниц сервера Web, а также классы JavaScript. На конкретных примерах исходных 
текстов документов HTML рассмотрены различные способы применения этого языка в 
формах и фреймах. Показано, как с помощью сценария JavaScript можно работать с 
графическими изображениями и анимацией.
   В отдельных главах рассказано об организации взаимодействия программ 
JavaScript и аплетов Java, расположенных в документе HTML, а также о применении 
cookie для хранения данных посетителей сервера Web. 
   Книга предназначена для всех, кто интересуется созданием физических или 
виртуальных серверов Web в сети Internet, а также в корпоративной сети Intranet.
 Она может быть полезна разработчикам справочно-информационных систем, 
ориентирующихся на технологии, связанные с применением HTML.
ПРЕДИСЛОВИЕ
   В этой книге мы расскажем о новой технологии, предназначенной для 
разработчиков серверов Web. Это язык сценариев JavaScript, получивший широкое 
распространение в глобальной сети Internet.
   Для тех, кто еще не знаком с Internet, предназначен наш 23 том “Библиотеки 
системного программиста”, который называется “Глобальные сети компьютеров. 
Практическое введение в Internet, E-Mail, FTP, WWW и HTML, программирование для 
Windows sockets”. Здесь вы найдете всю информацию, необходимую для того чтобы 
подключиться к этой сети и приступить к работе.
   Тем из вас, кто интересуется созданием собственных серверов в сети Internet, 
мы рекомендуем прочитать 29 том “Библиотеки системного программиста” с 
названием “Сервер Web своими руками”. В этом томе мы рассказали о языке 
разметки гипертекста HTML, о программах CGI и приложениях ISAPI, а также, 
конечно, о том, как установить и настроить свой сервер Web.
   Многие современные серверы Web являются активными или содержат активные 
страницы, которые взаимодействуют с пользователем. Описанные в только что 
упомянутом 29 томе программы CGI и приложения ISAPI позволяют создавать 
активные серверы Web, способные получать данные от удаленного пользователя, 
обрабатывать их и посылать результат обработки обратно в виде документа HTML. В 
качестве примера активных приложений, работающих на сервере Web, можно назвать 
чрезвычайно популярные счетчики посещений, гостевые книги, базы данных, 
доступные через Internet и так далее.
   Что же касается активных страниц Web, то с их помощью также можно создавать 
диалоговые приложения, однако обработка введенных данных выполняется не на 
сервере, а на рабочей станции пользователя, то есть локально. Активными мы 
будем называть документы HTML, которые содержат в себе аплеты Java, а также 
программы, составленные на таких языках, как JavaScript и VBScript.
   Преимущества, которые можно получить при использовании активных страниц, 
заключаются не только в улучшении внешнего вида страниц (что само по себе 
немаловажно), но и в снижении потока данных между рабочей станцией пользователя 
и сервером Web, а также в снижении загрузки этого сервера. Это, в свою очередь, 
благоприятно сказывается на скорости реакции сервера.
   Что касается аплетов и полноценных приложений Java, то им посвящены тома 30 
и 32 “Библиотеки системного программиста”, которые называются “Создание 
приложений Java. Часть 1” и “Создание приложений Java. Часть 2”, соответственно.
 Размещая на страницах сервера Web аплеты Java, вы можете выполнять на рабочей 
станции достаточно сложную локальную обработку данных. Реализация такой 
обработки с помощью программ CGI или приложений ISAPI была бы затруднительной 
или вовсе невозможной.
   Предметом изучения книги, которую вы сейчас держите в руках, является еще 
одно средство, предназначенное для создания активных страниц - язык JavaScript.
   Заметим сразу, что язык JavaScript не имеет никакого отношения к языку Java, 
несмотря на схожее название. 
   Язык программирования Java был создан фирмой Sun и произошел от языка Oak. 
По своему синтаксису он сильно похож на С++, однако есть немаловажные отличия, 
описанные нами в 30 томе “Библиотеки системного программиста”.
   Первоначальное название языка JavaScript, разработанного фирмой Netscape 
Communication Corporation, было LiveScript. Затем, после того как язык Java 
получил всемирную известность, LiveScript переименовали в JavaScript. Возможно, 
это было сделано фирмой Netscape из коммерческих соображений: все, что имело в 
своем названии ключевое слово “Java”, вызывало живой интерес.
   При разработке языка программирования JavaScript предполагалось, что он 
будет предназначен для непрофессионалов. По простоте использования JavaScript 
больше всего напоминает Basic, хотя с помощью него квалифицированные 
программисты могут решать достаточно серьезные и, что немаловажно, полезные 
задачи.
   В первой главе нашей книги мы приведем семь сценариев JavaScript, 
демонстрирующих основные возможности этого языка, расскажем о переменных и 
операторах JavaScript.
   Во второй главе мы расскажем о классах и объектах JavaScript. Заметим, что 
несмотря на свою простоту, JavaScript является объектно-ориентированным языком. 
Мы приведем достаточно полное описание классов, доступных разработчикам 
сценариев JavaScript, и многочисленные примеры применения этих классов. 
   Третья глава посвящена описанию приемов обработки сценариями JavaScript 
данных, которые пользователи вводят в полях формы, а также другим аспектом 
интеграции сценариев JavaScript и форм. Мы подробно расскажем об объектах 
JavaScript, создаваемых для органов управления форм, и научим их использовать в 
практике разработки интерактивных документов HTML. Отдельно будут рассмотрены 
вопросы проверки содержимого полей формы перед их отправкой расширению сервера 
Web для обработки.
   В четвертой главе мы расскажем о том, как с помощью сценариев JavaScript 
можно передавать данные между различными фреймами и получать эффекты, 
недостижимые в случае применения одного только языка разметки гипертекста HTML.
   Сценарий JavaScript может работать с растровыми графическими изображениями, 
расположенными в документе HTML, обращаясь к ним как к объектам JavaScript. В 
пятой главе мы описали методику динамической замены растрового графического 
изображения, которую можно использовать для “оживления” документа HTML.
   Шестая глава затрагивает вопросы взаимодействия сценария JavaScript с 
аплетами Java, встроенными в документ HTML. Такое взаимодействие 
предусматривает вызов из сценария JavaScript методов, определенных в аплете, а 
также обращение к полям классов аплета.
   В седьмой главе мы подробно рассмотрим механизм cookie, предназначенный для 
организации локального хранения информации пользователя. Эту информацию можно 
устанавливать и считывать как при помощи сценариев JavaScript, так и 
расширениями сервера Web (программами CGI или приложениями ISAPI). Мы приведем 
исходные тексты сценариев JavaScript и расширений сервера Web, работающих с 
cookie.
   Что вам потребуется для работы с книгой?
   Прежде всего, нужен компьютер, оснащенный 8-16 Мбайт оперативной памяти с 
операционной системой Microsoft Windows 95 или Microsoft Windows NT. Вам также 
потребуются браузер Microsoft Internet Explorer версии 4.0 и отладчик Microsoft 
Script Debugger. Последние две программы вы можете бесплатно переписать к себе 
с сервера Web корпорации Microsoft по адресу http://www.microsoft.com/ie. Для 
проверки совместимости созданных вами программ неплохо также иметь браузер 
Netscape Navigator 3.0 или 4.0, демонстрационную версию которого можно 
бесплатно получить с сервера http://www.netscape.com.
   Для редактирования программ JavaScript вы можете применять любые средства 
создания документов HTML, хотя вполне достаточно редактора, входящего в 
комплект отладчика Microsoft Script Debugger или даже приложения Notepad.
   Кроме всего прочего, чтобы составлять программы на JavaScript, вы должны 
быть знакомы с языком HTML. Для изучения этого языка мы рекомендуем вам 
прочитать 29 том нашей “Библиотеки системного программиста”, содержащей 
описание HTML в необходимом объеме.
   Для отладки сценариев JavaScript, описанных в седьмой главе и 
взаимодействующих с расширениями сервера Web, вам потребуется сервер Microsoft 
Internet Information Server. Вы можете использовать также сервер Web, входящий 
в комплект операционной системы Microsoft Windows NT Workstation версии 4.0 или 
даже Microsoft Personal Web Server, разработанный для Microsoft Windows 95. 
Сервер Microsoft Personal Web Server доступен для бесплатной загрузки из 
Internet.
   Исходные тексты всех программ вы можете найти на компакт-диске, который 
продается вместе с книгой. Эти тексты, так же как и исходные тексты программ из 
всех предыдущих томов “Библиотеки системного программиста”, есть также и на 
нашем авторском компакт-диске. Подробная информация об авторском компакт-диске 
есть в сети Internet на сервере авторов этой книги по адресу http://www.glasnet.
ru/~frolov или http://www.dials.ccas.ru/frolov.
   Мы выражаем благодарность генеральному директору АО “ДиалогНаука” Антимонову 
Сергею Григорьевичу и его заместителю Лященко Юрию Павловичу за возможность 
размещения информации о наших книгах на сервере Web по адресу http://www.dials.
ccas.ru/frolov, а также за возможность доступа к сети Internet через сервер АО 
“ДиалогНаука”.
   Мы также благодарим корректора Кустова В. С. и сотрудников издательского 
отдела АО “Диалог-МИФИ” Голубева О. А., Дмитриеву Н. В., Виноградову Е. К., 
Кузьминову О. А.
АВТОРСКИЙ КОМПАКТ-ДИСК
   В сентябре 1997 года в продаже появился авторский компакт-диск (как 
спецвыпуск журнала “Аурамедиа”), на котором вы можете найти наши первые книги 
серий “Библиотека системного программиста” и “Персональный компьютер. Шаг за 
шагом” в исходных текстах, дискеты ко всем книгам серии “Библиотека системного 
программиста”, статьи, написанные нами для периодических изданий, библиотеку 
программ FreeWare и ShareWare, ссылки на интересные ресурсы Internet, вернисаж 
художника Алексея Абрамкина и другую информацию.
   Компакт-диск можно приобрести непосредственно в издательстве “Аурамедиа” и 
“Диалог-МИФИ”, а также по подписке.
КАК СВЯЗАТЬСЯ С АВТОРАМИ
   Полную информацию о всех наших книгах серий “Библиотека системного 
программиста” и “Персональный компьютер. Шаг за шагом”, а также дискеты к 
книгам, статьи и другую информацию вы можете найти в сети Internet на серверах 
Web по следующим адресам:
http://www.glasnet.ru/~frolov
http://www.dials.ccas.ru/frolov
   Вы можете передать нам свои замечания и предложения по содержанию этой и 
других наших книг через электронную почту по адресам:
[email protected]
[email protected]
   Если электронная почта вам недоступна, присылайте ваши отзывы в АО 
“Диалог-МИФИ” по адресу:
115409, Москва, ул. Москворечье, 31, корп. 2, 
тел. 324-43-77
   Приносим свои извинения за то что не можем ответить на каждое письмо. Мы 
также не занимаемся продажей и рассылкой книг, дискет, компакт-дисков, рекламы, 
отдельных фрагментов наших книг и исходных текстов к книгам. По этим вопросам 
обращайтесь непосредственно в издательство “Диалог-МИФИ”. Авторский 
комопакт-диск можно приобрести также в издательстве “Аурамедиа”.
1 ВВЕДЕНИЕ В JAVASCRIPT
   Прежде чем приступить к созданию активных страниц Web с использованием 
JavaScript, рассмотрим особенности этого языка.
   Язык программирования JavaScript не предназначен для создания автономных 
программ или аплетов, и в этом он сильно отличается от других языков, таких как 
С или Java. Конструкции JavaScript встраиваются непосредственно в исходный 
текст документов HTML и интерпретируются браузером  по мере загрузки этих 
документов. Более того, с помощью JavaScript вы можете динамически формировать 
и изменять текст загружаемого документа HTML. 
   JavaScript является интерпретируемым языком. Категорию языков, к которой 
относится JavaScript, в литературе называют языками сценариев или скриптами. 
Последний термин - жаргон, который получился в результате транслитерации слова 
Script, поэтому в нашей книге мы его не будем использовать.
   Языки сценариев существовали давно. Они применялись, например, для 
автоматизации различных задач. В качестве примера можно привести язык сценариев 
UNIX, язык пакетных заданий MS-DOS или имеющий большее отношение к технологиям 
Internet язык Perl, предназначенный для создания программ CGI.
   Еще одна важная особенность языка JavaScript - это его объектная 
ориентированность. И хотя объектно-ориентированные возможности JavaScript 
заметно беднее, чем в С++ или Java, они все же есть в этом языке. Программистам 
доступны многочисленные объекты, встроенные в браузер и загруженные в него 
документы HTML, такие как документы HTML, фреймы, формы, ссылки на другие 
документы и так далее. Допускается создание собственных классов, а также 
группирование объектов и структур данных для расширения базовых классов.
   С помощью конструкций JavaScript, встроенных в документы HTML, можно 
обрабатывать события. Эти события возникают в результате выполнения 
пользователем различных операций над документом HTML, загруженным в окно 
браузера. Это позволяет получать различные визуальные эффекты, например, 
изменение внешнего вида органов управления, когда над ними находится курсор 
мыши. Можно предварительно проверять данные, введенных пользователем в полях 
формы перед их отправкой для обработки на сервер Web, а также выполнять 
произвольные действия перед загрузкой документа HTML в окно браузера и делать 
другую полезную работу.
   Заметим, что JavaScript не предназначен для создания сложных программ. 
Подобные задачи лучше решать с использованием других языков программирования, 
например, с помощью Java. Однако с помощью JavaScript вы можете быстро 
создавать активные страницы с достаточно сложным поведением. Этот язык несложен 
в изучении, а программы, составленные с его использованием, легко поддаются 
отладке. 
   Когда в наших томах “Библиотеки системного программиста” мы рассказывали о 
стандартах на язык HTML, то обращали ваше внимание на различия в реализации 
этого стандарта для браузеров Netscape Navigator и Microsoft Internet Explorer. 
А как обстоит дело с совместимостью в случае языка JavaScript?
   К сожалению, не очень хорошо. Несмотря на то что новые версии Microsoft 
Internet Explorer “понимают” язык JavaScript, существуют различные особенности. 
Фактически в браузере Microsoft Internet Explorer реализован язык сценариев 
Jscript, который хотя и совместим с JavaScript, но эта совместимость не 
является полной. Причина, вероятно, заключается в том, что Microsoft продвигает 
другой язык сценариев с названием VBScript, произошедший от языка Visual Basic. 
Возможно, мы посвятим VBScript одну из наших следующих книг.
  Семь вариаций на тему “Hello, world!” 
   Мы продолжим хорошую традицию начинать изучение нового языка 
программирования с классической программы “Hello, world!”, впервые составленной 
создателями языка С. В этом разделе вы найдете несколько вариантов такой 
программы, демонстрирующих различные (но пока не самые впечатляющие) 
возможности JavaScript. 
  Вариация первая: самый простая
   На первом этапе мы составим программу JavaScript, которая вставит слова 
“Hello, world!” непосредственно в документ HTML (рис. 1.1).

Рис. 1.1. Внешний вид документа HTML с первой программой на  JavaScript
   Как мы уже говорили, программы или сценарии JavaScript встраиваются в 
документ HTML. Взгляните на листинг 1.1, в котором мы привели исходный текст 
документа с нашей первой программой, составленной на JavaScript.
Листинг 1.1. Файл chapter1/hello/hello.html

  
    Hello, world!
  
  
    

JavaScript Test

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

и

задают стилевое оформление первой строки документа “JavaScript Test”, которая служит строкой заголовка первого уровня. Что же касается собственно программы JavaScript, то в нашем первом примере она встроена в документ HTML при помощи операторов , как это показано ниже: С помощью оператора Ссылка оформлена с применением операторов , однако между этими операторами нет ни одной строчки исходного текста. Мы перенесли этот текст в файл hello.js (листинг 1.3). Листинг 1.3. Файл chapter1/SecretHello/hello.js document.write("
"); document.write("Hello from JavaScript!"); document.write("
"); В параметр SRC нашего примера задано только имя файла, так как он находится в том же каталоге, что и ссылающийся на него файл документа HTML. Однако вы можете указать и полный адрес URL, например: Этот способ работает в браузерах Microsoft Internet Explorer версии 3.02, 4. 0 и Netscape Navigator версии 3.01. Использовать ли вам параметр SRC при создании своих страниц? Если вы создаете сервер в сети Internet, то необходимо учитывать тот факт, что пользователи применяют различные браузеры. Наибольшей популярностью по-прежнему пользуется браузер фирмы Netscape, однако доля владельцев бесплатного браузера Microsoft Internet Explorer стремительно растет. Кроме того, есть еще браузеры, работающие на платформе UNIX. На ваш сервер могут зайти даже такие пользователи, которые просматривает страницы серверов Web в текстовом режиме при помощи программы Lynx. Если вам нужно обеспечить максимальную посещаемость своего сервера, его необходимо сделать так, чтобы с ним можно было работать при помощи любого браузера. Не следует думать, что если вы напишете на главной странице, что ее нужно просматривать только браузером Netscape Navigator, то все владельцы Microsoft Internet Explorer сразу бросятся загружать файл этого браузера из сети. Скорее всего они просто уйдут с вашего сервера на чей-нибудь другой, чтобы больше никогда не вернуться назад. Лучшее решение заключается в том, чтобы сервер сам определял тип браузера пользователя, подстраиваясь автоматически под его возможности без лишних слов и вопросов. Эта, казалось бы, трудная задача, легко решается при помощи сценариев JavaScript, в чем вы еще сможете убедиться. Вариация третья: с переменной и функциями В сценариях JavaScript активно применяют функции и переменные. Подробно об этом мы расскажем в следующих разделах этой главы, а сейчас приведем исходный текст простой программы, в которой используется одна переменная и две функции (листинг 1.4). Листинг 1.4. Файл chapter1/HelloFn/HelloFn.html Hello, world!

JavaScript Test

Message: Эта программа записывает в документ сообщение “Hello, world!”, выделяя его жирным шрифтом (рис. 1.3). Рис. 1.3. Сообщение выделено жирным шрифтом Рассмотрим исходный текст нашего документа HTML и встроенного в него сценария JavaScript. Прежде всего, обратите внимание на область заголовка документа, выделенную операторами и . В этой области расположено определение одной переменной и двух функций, оформленное с применением операторов : Кроме того, в теле документа HTML есть еще один раздел сценариев, выделенный аналогичным образом: Переменная с именем szHelloMsg определяется при помощи оператора var, причем ей сразу же присваивается начальное значение - текстовая строка "Hello, world!". Заметим, что в отличие от Java, язык JavaScript не является типизированным. Это означает, что программист не может указать явным образом тип создаваемых им переменных. Этот тип определяется интерпретатором JavaScript автоматически, когда переменной в первый раз присваивается какое-либо значение. В дальнейшем вы можете легко изменить тип переменной, просто присвоив ей значение другого типа. Отсутствие строгой типизации упрощает создание сценариев, особенно для непрофессиональных программистов, однако может привести к ошибкам. Поэтому мы рекомендуем вам внимательно следить за тем, какие типы данных вы применяете. Не исключено, что вам поможет использование префиксов имен, по которым можно судить о типе переменной. Эти префиксы хорошо знакомы программистам, создававшим приложения для операционной системы Microsoft Windows на языке программирования С. Например, текстовые строки можно начинать с префикса sz, а численные значения - с префикса n. Помимо переменной szHelloMsg, в области заголовка документа HTML мы определили с помощью ключевого слова function две функции с именами printString и printHello. Первая из этих функций выводит в документ HTML строку, передаваемую ей в качестве параметра, а вторая выводит сообщение “Hello, world!”, вызывая для этого первую функцию. Интерпретация документа HTML и встроенных в него сценариев происходит по мере загрузки документа. Поэтому если в сценарии одни функции вызывает другие, необходимо разместить определения вызываемых функций выше вызывающих. Размещение определений переменных и функций в разделе заголовка документа гарантирует, что они будут загружены до момента загрузки тела документа. Изучая приведенный в листинге 1.4 исходный текст, обратите внимание на функцию printString: function printString(szString) { document.write(szString.bold()); } Здесь для объекта document вызывается метод write. В качестве параметра мы передаем этому методу объект szString, вызвав для него метод bold. Значит, переменная szString, определенная с помощью ключевого слова var, является объектом? После того как мы присвоили этой переменной значение текстовой строки, она стала объектом встроенного класса текстовых строк, для которого определены несколько методов. С помощью этих методов можно выполнять различные операции над текстовыми строками, такие как извлечение подстрок, преобразование символов из прописных в заглавные и обратно, наложение шрифтового оформления и так далее. Разумеется, для того чтобы выделить сообщение жирным шрифтом, мы могли использовать и обычную конструкцию языка HTML: var szHelloMsg = "Hello, world!"; Однако в данном случая нам хотелось продемонстрировать возможность вызова методов для переменных типа текстовых строк. Вариация четвертая: создание страницы “на лету” Следующий сценарий имеет одну интересную особенность: в содержащем его документе HTML нет области (листинг 1.5). Листинг 1.5. Файл chapter1/HelloGen/HelloGen.html Если в предыдущем примере мы встраивали фрагменты сценария в область заголовка и в тело документа HTML, то сейчас весь сценарий находится в заголовке. Наш документ HTML не содержит ничего, кроме сценария JavaScript. Когда такой документ загружается в окно браузера, программа JavaScript формирует недостающую часть заголовка (с помощью операторов и <TITLE>, а также тело документа. Таким образом, сценарии JavaScript позволяют формировать все содержимое страницы динамически. Так как в языке JavaScript есть условные операторы, вы можете создавать разные страницы в зависимости от тех или иных обстоятельств. Например, определив тип и версию установленного у пользователя браузера, нетрудно сформировать для него страницу, учитывающую особенности конкретной версии приложения, с помощью которого пользователь просматривает ваш сервер Web. Вариация пятая: с диалоговой панелью Язык JavaScript имеет встроенные средства для отображения простейших диалоговых панелей, таких как панель сообщений (рис. 1.4). Рис. 1.4. Диалоговая панель, которая появляется при загрузке страницы в браузер В листинге 1.6 мы привели исходный текст сценария JavaScript, в котором вызывается функция alert, предназначенная для отображения диалоговых панелей с сообщениями. Листинг 1.6. Файл chapter1/HelloBox/HelloBox.html <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript"> <!-- document.write("<TITLE>Hello, world!"); document.write(""); document.write("

JavaScript Test

"); alert("Hello, world!"); document.write(""); // --> Для продолжения загрузки страницы необходимо нажать кнопку OK. Только после этого содержимое страницы (состоящее в данном случае из одной строки заголовка) появится на экране. Помимо представленной в этом примере диалоговой панели сценарии JavaScript могут выводить на экран и более сложные. В них пользователь может делать, например, выбор из двух альтернатив или даже вводить какую-либо информацию. Подробнее об этом мы расскажем позже. Вариация шестая: обработка события В языке JavaScript есть удобные средства обработки событий. В нашем следующем примере когда пользователь пытается выбрать ссылку “Select me!” (рис. 1.5), разместив над ней курсор мыши, на экране появляется диалоговая панель Microsoft Internet Explorer с сообщением “Hello, world!”. Рис. 1.5. Диалоговая панель появляется, когда пользователь размещает курсор мыши над ссылкой Исходный текст соответствующего документа HTML с встроенным в него сценарием представлен в листинге 1.7. Листинг 1.7. Файл chapter1/HelloOnSelect/HelloOnSelect.html Hello from JavaScript!

JavaScript Test


Select me! Здесь для нас интересна строка оператора . Напомним, что этот оператор обычно применяется для организации ссылок на другие документы HTML или файлы различных объектов. В данном случае поле ссылки параметра HREF пустое, однако дополнительно в оператор включена следующая конструкция: onMouseover="alert('Hello, world!');" Она указывает, что при возникновении события onMouseover должна выполняться следующая строка программы JavaScript: alert('Hello, world!'); Обратите внимание, что строка задана не в двойных кавычках, а в одинарных. В сценариях JavaScript допустимо использовать и те, и другие кавычки, однако закрывающая кавычка должна быть такой же, что и открывающая. Внутренняя пара кавычек должна отличаться от внешней. Вы можете установить обработчики таких событий, как загрузка страницы, щелчок по ссылке или кнопке формы, выбор ссылки или поля формы и других событий. Более подробно обработка событий будет рассмотрена позже. Вариация седьмая: с определением типа браузера Последний пример сценария, который мы рассмотрим в этом разделе, показывает, как программа JavaScript может легко определить тип и версию браузера. На рис. 1.6 показан результат просмотра документа HTML с этим сценарием при помощи браузера Microsoft Internet Explorer. Рис. 1.6. Информация о браузере Microsoft Internet Explorer То, что вы увидите, просмотрев этот же документ браузером Netscape Navigator, представлено на рис. 1.7. Рис. 1.7. Информация о браузере Netscape Navigator Давайте посмотрим на текст сценария, позволяющего извлекать подобную информацию. Он представлен в листинге 1.8. Листинг 1.8. Файл chapter1/HelloInfo/HelloInfo.html Hello, world!

Something about you...

Здесь сценарий JavaScript формирует в документе HTML строки таблицы, записывая в них названия различных свойств объекта navigator и значения, соответствующие этим свойствам. Объект navigator - это сам браузер. Обращаясь к свойствам этого объекта, можно получить различную информацию о браузере. Наиболее интересны для нас свойства navigator.appName и navigator. appVersion, так как они позволяют однозначно определить тип браузера и его версию. Обладая этой информацией, вы можете динамически “приспособить” документ HTML к навигатору, установленному у пользователя. Заметим, что в браузере Microsoft Internet Explorer реализован еще один метод определения версии браузера, который мы рассмотрим позже. К сожалению, этот метод несовместим с браузером Netscape Navigator. Переменные в JavaScript В сценариях JavaScript вы можете использовать переменные, адресуясь к ним по имени. Переменные могут быть как глобальные, так и локальные. Глобальные переменные доступны из любого места сценария. Область действия локальных переменных ограничивается функцией, внутри которой эти переменные объявлены. Так же как и в языке программирования Basic, при составлении сценариев JavaScript вы можете использовать переменные без их предварительного объявления. Исключение из этого правила - локальные переменные, определенные в функциях. Мы рекомендуем объявлять переменные перед их использованием, а также присваивать им начальные значения. Это упростит отладку сценариев и уменьшит вероятность возникновения ошибок при составлении исходного текста, особенно если вы применяете одновременно глобальные и локальные переменные. Объявление переменных Все переменные в JavaScript объявляются с помощью ключевого слова var, как это показано ниже: var szHelloMsg; Еще раз обращаем ваше внимание на то, что при объявлении тип переменной не указывается. Этот тип присваивается переменной только тогда, когда ей присваивается какое-либо значение. Ниже мы записываем в переменную, которая не была предварительно объявлена, текстовую строку: szMsg = “Привет!”; После такого присвоения имя переменной szMsg становится доступным. При выборе имен переменных вы должны придерживаться следующих простых правил: * имя переменной должно начинаться с буквы или с символов “_”, “$” и может состоять только из букв, цифр, а также символов “_”, “$”; * имя переменной не должно совпадать с зарезервированными ключевыми словами JavaScript. Список зарезервированных ключевых слов JavaScript приведен ниже: breakifcase*import*catch*inclass*newconst*nullcontinuereturndebugger*super* default*switch*deletethisdo*throw*elsetrue*enum*tryexport*typeofextends*var  falsevoidfinally*whileforwithfunction Ключевые слова, представленные в этом списке, еще только планируется применять в языке JavaScript при его развитии. Эти слова отмечены символом *. Мы рекомендуем избегать их использования в ваших программах в качестве имен переменных. Нужно также следить, чтобы имена переменных не совпадали с именами встроенных объектов, методов и функций. Присвоение значения переменным Вы можете присвоить значение переменной при помощи оператора присвоения “=”. Например, ниже мы объявляем переменную и затем записываем в нее текстовую строку: var szHelloMsg; szHelloMsg = “Hello, world!”; В любом месте программы мы можем присвоить переменной szHelloMsg численное значение, например, так: szHelloMsg = 4; После выполнения такой операции тип переменной изменится, причем в процессе интерпретации сценария браузер не отобразит никаких предупреждающих сообщений. Вы можете присвоить переменной специальное значение null: szHelloMsg = null; Такое присвоение не назначает переменной никакого типа. Оно применяется в тех случаях, когда вам нужно объявить переменную и проинициализировать ее, не присваивая этой переменной никакого начального значения и типа. В частности, в только что приведенном примере переменной szHelloMsg не присваивается ни численное значение 0, ни пустая текстовая строка. Типы данных Хотя при создании переменной вы не можете присвоить ей тип, в языке JavaScript все же существует несколько типов данных. Это числа, текстовые строки, логические данные, объекты, данные неопределенного типа, а также специальный тип null. Объекты мы рассмотрим позже, а сейчас расскажем об основных типах данных. Числа Язык сценариев JavaScript допускает использование чисел в различных форматах. Это целые числа, числа в формате с плавающей десятичной точкой и числа в научной нотации. Целые числа могут быть представлены по основанию 8, 10 или 16. Например: ПримерОписание25Целое число по основанию 100137Целое число по основанию 80xFF Целое число по основанию 16386.7Число с плавающей десятичной точкой25e5 или 25E5Число в научной нотации, равно 2500000 В некоторых случаях арифметические функции могут возвращать так называемое “нечисло”, которое называется в JavaScript как NaN (Not a Number). “Нечисло” - это специальное значение, которое не соответствует никакому числу. Оно возникает в тех случаях, когда результат выполнения операции над числами не может быть представлен в виде числа. С помощью функции isNaN вы можете проверить, является ли значение “нечислом”. Текстовые строки Текстовые строки - это последовательность символов Unicode, заключенных в одинарные или двойные кавычки, например: “Hello, world!” “” “12345” ‘Это текстовая строка’ Строка “” - пустая. Заметим, что следующие два присвоения не эквивалентны: szStr=”” szStr1=null В первом случае в переменной szStr хранится текстовая строка (хотя бы и пустая), во втором - совсем ничего. Логические данные Логические данные могут иметь только два значения: true и false. Эти значения никак не соотносятся с числами 1 и 0. Они предназначены главным образом для выполнения операций сравнения, а также для использования в условных операторах. Данные неопределенного типа Если переменная была объявлена, но ей еще ни разу не присваивалось значение, она имеет неопределенный тип. Например, в следующей строке сценария объявлена переменная MyVariable, которая имеет неопределенный тип: var MyVariable; Если же этой переменной присвоить значение null, то тип переменной изменится - теперь это будет переменная, содержащая значение null: MyVariable = null; Преобразование типов данных Когда в выражениях встречаются переменные разных типов, интерпретатор JavaScript может автоматически преобразовывать численные данные в текстовые строки. Обратное же преобразование (строк в числа) приходится выполнять с помощью специальных функций, таких как parseInt и parseFloat. Поясним это на примере (листинг 1.9). Листинг 1.9. Файл Conversion/Conversion.html Type conversion sample

Type conversion sample

Здесь мы объявили переменную szTextBuf и проинициализировали ее пустой строкой. Далее мы присвоили этой строке сумму числа 4 и двух текстовых строк: szTextBuf = 4 + " - число четыре" + "
"; При вычислении этого выражения значение 4 было автоматически преобразовано в текстовую строку. Дальнейшее суммирование выполнялось как слияние (конкатенация) трех текстовых строк. Обратите внимание на символ неразделяющего пробела  , который используется в документах HTML. Если заменить его на обычный пробел, то после конкатенации строк этот пробел исчезнет. В следующей строке мы преобразовываем текстовую строку “2” в численное значение с помощью функции parseInt, прибавляем к результату преобразования число 2, а затем выполняем конкатенацию с двумя текстовыми строками: szBuf2 = (parseInt("2")+2)+" - число четыре"+ "
"; В результате переменная szBuf2 будет содержать ту же самую строку, что и переменная szTextBuf, в чем нетрудно убедиться, взглянув на рис. 1.8. Рис. 1.8. Результат работы сценария, представленного в листинге 1.9 Здесь в окне браузера отображаются две одинаковые строки, хотя они были получены разными способами. Операторы языка JavaScript Операторы языка сценариев JavaScript напоминают общеизвестные операторы языка C, поэтому мы ограничимся только кратким их описанием. Унарные операторы Унарные операторы применяются для изменения знака, выполнения операции дополнения, инкремента и декремента: Унарный операторНазначение-Изменение знака на противоположный!Дополнение. Используется для реверсирования значения логических переменных++Увеличение значения переменной. Может применяться как префикс переменной или как ее суффикс--Уменьшение значения переменной. Может применяться как префикс переменной или как ее суффикс Вот примеры использования унарных операторов: i=0; // начальное значение переменной i равно 0 i++; // значение i равно 1 --i; // значение i снова равно 0 var j=3; // значение переменной j равно 3 i = -j; // значение переменной i равно -3 var fYes = true; // значение переменной fYes равно true testFlag(!fYes); // функции testFlag передается // значение false Бинарные операторы Бинарные операторы соединяют два операнда. В языке сценариев JavaScript предусмотрены бинарные операторы для вычитания, сложения, умножения, деления и вычисления остатка деления: Бинарный операторНазначение-Вычитание+Сложение*Умножение/Деление%Вычисление остатка от деления Эти операторы используются таким же образом, что и в языке программирования C, например: i=0; // начальное значение переменной i равно 0 i = i + 1; // значение i равно 1 var j=9; // значение переменной j равно 9 i = j / 2; // значение переменной i равно 4 k = j % 2; // значение переменной i равно 1 Операторы для работы с отдельными битами В своих сценариях вы можете применять операторы, выполняющие над битами переменных такие логические операции, как И, ИЛИ, ИСКЛЮЧАЮЩЕЕ ИЛИ, НЕ: ОператорЛогическая операция&И|ИЛИ^ИСКЛЮЧАЮЩЕЕ ИЛИ~НЕ Перечисленные выше операторы перед выполнением своих функций преобразуют значения переменных в 32-разрядные целые числа. Операторы сдвига Для выполнения операций сдвига в языке JavaScript предусмотрено три оператора: Оператор сдвигаНазначение>>Сдвиг в правую сторону<<Сдвиг в левую сторону>>> Сдвиг в правую сторону с заполнением освобождаемых разрядов нулями Перед использованием операторов сдвига значение переменной преобразуется в 32-разрядное целое число. Ниже мы привели пример, в котором в переменную nValue записывается значение, полученное в результате сдвига бит числа 4. Сдвиг выполняется на два бита влево: var nValue; nValue = 4 << 2; Операторы отношения Операторы отношения используются для сравнения значений переменных. Эти операторы возвращают логические значения true или false в зависимости от результата сравнения и применяются главным образом в условных операторах. Эти операторы мы опишем позже в этой главе. Итак, ниже мы представили список операторов отношения языка сценариев JavaScript: Оператор отношенияУсловие, при котором оператор возвращает значение true>Левый операнд больше правого>=Левый операнд больше или равен правому<Левый операнд меньше правого<=Левый операнд меньше или равен правому==Левый операнд равен правому!=Левый операнд не равен правому Примеры использования этих операторов вы найдете в разделе, посвященном условным операторам. В условных операторах также часто применяются логические операторы: Логический оператор Описание||Оператор ИЛИ. Возвращает значение true, когда один из операндов равен true&&Оператор И. Возвращает значение true, когда оба операнда равны true Оператор присваивания Оператор присваивания применяется для присваивания значений переменным. В языке сценариев JavaScript, так же как и в языке программирования С, допускается комбинирование этого оператора с другими для изменения содержимого переменных. Ниже мы перечислили все возможные комбинации оператора присваивания и других операторов: ОператорОписание=Простое присваивание+=Увеличение численного значения или слияние строк-=Уменьшение численного значения*=Умножение/=Деление%=Вычисление остатка от деления>>=Сдвиг вправо>>>=Сдвиг вправо с заполнением освобождаемых разрядов нулями<<=Сдвиг влево|=ИЛИ&=И^=ИСКЛЮЧАЮЩЕЕ ИЛИ Для тех, кто никогда не программировал на языке С, комбинации оператора присваивания с другими операторами могут показаться непривычными и сложными для использования. На самом деле они упрощают сценарии, сокращая листинги исходных текстов. Рассмотрим, например, применение оператора += для увеличения содержимого числовой переменной. Вначале решим эту задачу без использования данного оператора. Ниже мы объявили переменную с именем nCounter и присвоили ей начальное значение 1, а затем увеличили это значение на 5: var nCounter = 1; nCounter = nCounter + 5; Теперь сделаем то же самое, но по-другому: var nCounter = 1; nCounter += 5; Как видите, второй способ короче первого. Для того чтобы сдвинуть содержимое переменной на три разряда вправо, вы можете воспользоваться оператором >>=, как это сделано в следующем фрагменте исходного текста: nCounter >>= 3; Результат при этом будет такой же, как и при выполнении следующей строки: nCounter = nCounter >> 3; Условные операторы Любой язык программирования был бы бесполезен, если бы в нем не были предусмотрены те или иные средства ветвления при выполнении программы. В языке JavaScript предусмотрен условный оператор else-if, который позволяет выполнять разные программные строки в зависимости от условия. Общий вид оператора else-if представлен ниже: if(условие) строка 1 [else строка 2] Часть оператора, выделенная квадратными скобками, является необязательной. При выполнении этого оператора оценивается условие, заданное в круглых скобках после ключевого слова if. Если в результате оценки условия получилось логическое значение true, выполняется строка 1. Если же получилось значение false, то выполняется строка 2 (в том случае, когда она присутствует. Оператор if-else может быть вложенным. Учтите, что если в строке 1 или строке 2 необходимо расположить несколько операторов, их следует выделить фигурными скобками: if(nYourAge < 18) { bAccessDenied = true; szNextPage = “bye18.html”; } else if(nYourAge > 99) { bAccessDenied = true; szNextPage = “bye99.html”; } else { bAccessDenied = false; szNextPage = “welcome.html”; } Здесь вначале оценивается условие (nYourAge < 18). Если содержимое переменной nYourAge меньше 18, переменной bAccessDenied присваивается значение true, а переменной szNextPage - текстовая строка “bye18.html”. Затем содержимое nYourAge сравнивается с числом 99. Если переменная nYourAge имеет значение, большее чем 99, в переменную bAccessDenied записывается значение true, а переменную szNextPage - текстовая строка “bye99.html”. И, наконец, если ни одно из двух условий не было выполнено, то есть значение переменной nYourAge находится в интервале от 18 до 99, в переменную bAccessDenied записывается значение false, а переменную szNextPage - текстовая строка “welcome.html”. Существует также специальный тип условного оператора, который называется оператором ?:. Этот оператор в общем виде записывается так: выражение ? строка 1 : строка 2 При вычислении оператора ?: вначале оценивается логическое выражение, расположенное в левой части. Если оно равно true, выполняется строка 1, а если false - строка 2. Ниже мы привели пример использования условного оператора ?: для присвоения значения переменной bAccessDenied в зависимости от содержимого переменной nYourAge: bAccessDenied = (nYourAge < 18 || nYourAge > 99) ? true : false; Если значение переменной nYourAge находится в интервале от 18 до 99, переменной bAccessDenied присваивается значение true, а если оно не попадает в этот интервал - false. Традиционное решение этой задачи с помощью оператора else-if заняло бы больше места: if(nYourAge < 18 || nYourAge > 99) bAccessDenied = true; else bAccessDenied = false; В приведенных выше примерах мы указывали составное условие: (nYourAge < 18 || nYourAge > 99) В соответствии таблицей старшинства операторов, которую вы найдете ниже в этой главе, оператор || вычисляется после операторов < и >. Если вам не хочется разбираться с таблицей старшинства, для указания порядка вычисления используйте скобки: ((nYourAge < 18) || (nYourAge > 99)) Операторы цикла В языке JavaScript есть несколько операторов, предназначенных для организации циклов. Оператор for Общий вид оператора for представлен ниже: for([инициализация;] [условие;] [итерация]) { . . . строки тела цикла . . . } В области инициализации обычно выполняется присваивание начальных значений переменным цикла. Здесь допустимо объявление новых переменных при помощи ключевого слова var. Вторая область задает условие выхода из цикла. Это условие оценивается каждый раз при прохождении цикла. Если в результате оценки получается логическое значение true, выполняются строки тела цикла. Область итерации применяется для изменения значений переменных цикла, например, для уменьшения счетчика цикла. Оператор for-in Оператор for-in предназначен для просмотра всех свойств объекта и записывается в следующем виде: for(переменная in объект) { . . . строки тела цикла . . . } Оператор while Для организации циклов с проверкой условия их завершения перед выполнением итерации используется оператор while: while(условие) { . . . строки тела цикла . . . } Если в результате оценки условия получается значение true, тогда итерация выполняется, если false - цикл прерывается. Оператор break С помощью оператора break можно прервать выполнение цикла, созданного операторами for или while, в любом месте. Например: var i = 0; while(true) { . . . i++; if(i > 10) break; . . . } Оператор continue Выполнение оператора continue внутри цикла for или while приводит к тому, что итерация прерывается, а затем возобновляется заново. Этот оператор не прерывает цикл. Ниже мы привели пример использования оператора continue: var i = 0; while(i < 100) { i++; if(i < 10) continue; . . . } Здесь фрагмент тела цикла, отмеченный многоточием, будет выполняться только после того, как значение переменной i станет равным 10. Когда же это значение достигнет 100, цикл будет завершен. Прочие операторы Среди прочих операторов языка сценариев JavaScript мы рассмотрим оператор доступа к полю, индексирование массива, скобки и запятую: ОператорОписание.Доступ к полю объекта[]Индексирование массива()Скобки,Запятая Первый из этих операторов применяется для вызова методов, определенных в объектах, а также для доступа к полям объектов или, как их еще называют, к свойствам объектов. Ниже, например, мы вызвали метод write, определенный в объекте document: document.write("Hello, world!"); Квадратные скобки используются для индексации массивов аналогично тому, как это делается в других языках программирования. Что касается круглых скобок, то они применяются либо для изменения порядка вычисления выражений, либо для передачи параметров функциям. Оператор запятая предназначен для разделения выражений, которые должны оцениваться последовательно. Этот прием называется многократным вычислением. Например, в фрагменте исходного текста, показанном ниже, на каждой итерации цикла выполняется увеличение содержимого переменных i и nCycleCount: var i; var nCycleCount = 0; for(i = 0; i < 25; i++, nCycleCount++) { . . . } Старшинство операторов JavaScript Ниже мы привели таблицу старшинства операторов JavaScript. С помощью этой таблицы можно определить порядок вычисления составных операторов. При этом следует учитывать, что все логические операции выполняются слева направо. Первыми вычисляются операторы, расположенные в начале таблицы старшинства: ОператорОписание. [] ()Доступ к полю, индексирование в массиве, вызов функции++ -- - ~ ! Унарные операторы* / %Умножение, деление, вычисление остатка от деления+ - +Сложение, вычитание, слияние текстовых строк<< >> >>>Битовые сдвиги < <= > >=Меньше, меньше или равно, больше, больше или равно== !=Равенство, неравенство&Логическая операция И^Логическая операция ИСКЛЮЧАЮЩЕЕ ИЛИ| Логическая операция ИЛИ&&Логический оператор отношения И||Логический оператор отношения ИЛИ?:Условный оператор= += -= *= /= %= >>= >>>= <<= |= &= ^= Присваивание,Многократное вычисление Функции в языке сценариев JavaScript Вы можете оформить фрагменты исходного текста в виде функции, вызывая эту функцию по мере необходимости из различных мест сценария JavaScript. Обычно функции определяются в разделе заголовка документа HTML, отмеченного операторами и . Как мы уже говорили, функция должна быть определена перед вызовом. Размещение всех определений функций в разделе заголовка документа HTML гарантирует доступность этих функций при обработке документа. Общий вид определения функции представлен ниже: function имя([параметр 1] [,параметр 2] [...,параметр N]) { . . . строки тела функции . . . [return значение] } Все параметры передаются функции по значению. Поэтому функция не может изменить содержимое переменных, передаваемых ей в качестве параметров. С помощью ключевого слова return функция может вернуть значение. Примеры использования операторов цикла Приведем три примера использования операторов цикла for и while. Во всех этих примерах сценарий отображает в окне документа десять строк “Hello, world!”, как это показано на рис. 1.9. Рис. 1.9. Сценарий отображает в документе HTML десять одинаковых строк Исходный текст первого сценария представлен в листинге 1.10. Листинг 1.10. Файл chapter1/Operators/for.html Hello, world!

JavaScript Test

Message:
Здесь сразу после загрузки документа вызывается функция printHello. В теле этой функции, в свою очередь, вызывается функция printNString, которой передаются два параметра: printNString(szHelloMsg, 10); Через первый параметр этой функции мы передаем текстовую строку szHelloMsg, а через второй - количество повторов этой строки при выводе. Вывод строки выполняется функцией printNString в цикле: for(i = 0; i < n; i++) { document.write(szString.bold() + "
"); } Здесь значение переменной цикла i изменяется от нуля до n, где n - количество повторов. Когда значение переменной цикла достигнет значения n, цикл будет завершен. В листинге 1.11 показан сценарий, решающий ту же самую задачу другим методом - с использованием оператора while. Листинг 1.11. Файл chapter1/Operators/while.html Hello, world!

JavaScript Test

Message:
Здесь i также используется как переменная цикла: i = 0; while(i < n) { document.write(szString.bold() + "
"); i++; } Как работает этот цикл? После вывода строки методом write значение переменной цикла увеличивается на единицу. Затем перед началом следующей итерации проверяется, достигла ли переменная цикла значения n. Если достигла, цикл завершает свою работу. Совместное применение операторов while и break демонстрируется в сценарии, показанном в листинге 1.12. Листинг 1.12. Файл chapter1/Operators/break.html Hello, world!

JavaScript Test

Message:
Так же как и в предыдущем случае, i используется как переменная цикла, однако в операторе while на месте условия завершения цикла стоит значение true: i = 0; while(true) { document.write(szString.bold() + "
"); i++; if(i > n) break; } Для того чтобы прервать цикл, мы применили оператор break. Этот оператор вызывается в том случае, если значение переменной цикла i превысило значение n. 2 КЛАССЫ И ОБЪЕКТЫ В JAVASCRIPT Язык сценариев JavaScript является объектно-ориентированным, подобно языку программирования С++, однако в реализации объектов между этими языками есть весьма существенные отличия. Объекты JavaScript представляют собой наборы свойств и методов. Можно сказать, что свойства объектов - это данные, связанные с объектом, а методы - функции для обработки данных объекта. Те из вас, кто программировал на языке С++, могут провести аналогию с полями и методами, определенными в классе. Адресация свойств в сценариях JavaScript возможна либо по именам свойств, либо по их номеру. Последнее возможно благодаря тому, что все свойства объекта хранятся как элементы массива и потому каждое свойство имеет свой номер. Три типа объектов JavaScript В языке JavaScript имеется три типа объектов: встроенные объекты, объекты браузера и объекты, которые программист создает самостоятельно (рис. 2.1). Рис. 2.1. Объекты в сценариях JavaScript Каждый из этих типов имеет свое назначение и свои особенности. Встроенные объекты Ниже мы перечислили встроенные объекты, свойства и методы которых доступны в сценариях JavaScript без предварительного определения этих объектов: ОбъектОписаниеArray*МассивBoolean*Логические данныеDateКалендарная дата Function*ФункцияGlobal*Глобальные методыMathМатематические константы и функции Number*ЧислаObject*ОбъектString Строки Здесь символом * отмечены встроенные объекты, определенные в языке Microsoft JScript версии 3.0. Эта версия реализована в браузере Microsoft Internet Explorer версии 4.0. Встроенные объекты очень удобны для выполнения различных операций со строками, календарными датами, массивами, числами и так далее. Они освобождают программиста от выполнения различных рутинных операций вроде преобразования строк или вычисления математических функций. Как работать со встроенными объектами? Достаточно просто. Программа создает реализации (instance) объектов, а затем обращается к свойствам и методам объектов. В качестве примера, имеющего практическое значение, рассмотрим документ HTML, в котором отображается текущая дата и время. Исходный текст этого документа вы найдете в листинге 2.1. Листинг 2.1. Файл chapter2/date/date.html Show date and time

Show date and time

Здесь сценарий JavaScript создает объект Data, применяя для этого ключевое слово new, знакомое всем поклонникам языка С++, и конструктор Date без параметров: var dt; dt = new Date(); Создаваемый таким образом объект Data инициализируется текущей локальной датой, установленной у пользователя (а не на сервере Web, с которого был загружен соответствующий документ HTML). В следующей строке формируется текстовая строка даты: szDate = "Date: " + dt.getDate() + "." + dt.getMonth() + "." + dt.getYear(); Значение календарного числа, номера месяца и года здесь получается при помощи методов getDate, getMonth и getYear, соответственно. Эти методы вызываются для объекта dt, содержащего текущую дату. Текстовая строка даты выводится в документ HTML с помощью метода write, определенного в объекте document: document.write(szDate); Этот способ мы уже использовали в примерах сценариев, приведенных в первой главе нашей книги. Заметим, что объект Date содержит также информацию о текущем времени. Эта информация извлекается для отображения с помощью методов getHours, getMinutes и getSeconds (соответственно, часы, минуты и секунды): document.write("Time: " + dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds()); Внешний вид документа HTML при его просмотре в окне браузера Microsoft Internet Explorer версии 4.0 показан на рис. 2.2. Рис. 2.2. Просмотр локальной даты и времени Применение других встроенных объектов мы продемонстрируем позже по мере изучения материала. Объекты браузера С точки зрения сценария JavaScript браузер представляется иерархически организованным набором объектов. Обращаясь к свойствам и методам этих объектов можно выполнять различные операции над окном браузера, загруженным в это окно документом HTML, а также над отдельными объектами, размещенными в документе HTML. Например, можно создавать новые окна браузера, загружая в них документы HTML, динамически формировать текст документа HTML, обращаться к полям форм, определенных в документе HTML и так далее. Объекты браузера являются тем интерфейсом, с помощью которого сценарий JavaScript взаимодействует с пользователем и документом HTML, загруженным в окно браузера, а также с самим браузером. В сценариях JavaScript вы не можете создавать новые классы на базе классов, соответствующих этим объектам, однако свойства и методы объектов браузера вам доступны. Иерархия объектов браузера Иерархия объектов браузера схематически показана на рис. 2.2. Рис. 2.2. Иерархия объектов браузера Объект window находится в корне иерархии. Когда в окно браузера загружается документ HTML, внутри этого объекта создаются другие объекты - document, parent, frame, location и top. Если в окно браузера загружается документ HTML с фреймами, то для каждого фрейма создается отдельное окно, причем это окно создается как объект window. Объект document содержит в себе другие объекты, состав которых полностью определяется документом HTML, загруженным в окно браузера. Это могут быть формы, ссылки на другие документы HTML или локальные ссылки внутри одного документа, объекты, определяющие адрес URL документа и так далее. Если в документе имеются формы, то они также представляются в виде иерархического набора объектов. Объект-форма может содержать в себе такие объекты, как кнопки, переключатели, поля для ввода текстовой информации. Обращаясь к свойствам перечисленных выше объектов, сценарий JavaScript может определить различные характеристики документа HTML, такие как, например, заголовок. Ему доступны все ссылки, размещенные в документе, а также содержимое полей форм, определенных в документе HTML. События, связанные с объектами Сделаем еще одно очень важное замечание относительно объектов браузера. С каждым таким объектом связывается определенный набор событий, обработка которых возможна в сценарии JavaScript. Например, с объектом window связаны события onLoad и onUnload. Первое из этих событий возникает, когда браузер завершает загрузку окна и всех расположенных в нем фреймов (если эти фреймы определены в окне). Второе событие возникает, когда пользователь завершает работу с документом, закрывая окно браузера или переключаясь на другой документ. Сценарий JavaScript может, например, при обработке события onLoad выводить для пользователя приветственное сообщение или запрашивать дополнительную информацию. При завершении работы с окном (когда возникает событие onUnload) сценарий может освобождать какие-либо ресурсы, связанные с этим окном, или выводить сообщение на экран монитора. С другими объектами браузера также связаны события. Мы расскажем о них при описании этих объектов. Объекты на базе классов, создаваемых программистом Многочисленные книги для начинающих, посвященные языку программирования С++, предлагают представить себе класс как структуру данных, где помимо обычных полей определены функции-методы для работы с этими данными. Так вот, в языке JavaScript для создания собственных классов используется прямо противоположный метод. Класс JavaScript создается как функция, в которой определены свойства, играющие роль данных. Что же касается методов, то они тоже определяются как функции, но отдельно. Приведем конкретный пример. Пусть нам нужно создать класс, предназначенный для хранения записи воображаемой телефонной базы данных. В этом классе нам нужно предусмотреть свойства для хранения имени, фамилии, номера телефона, адреса, а также специального признака для записей, закрытых от несанкционированного доступа. Дополнительно требуется разработать методы, предназначенные для отображения содержимого объекта в табличном виде, как это показано на рис. 2.3. Рис. 2.3. Просмотр содержимого записей Прежде всего займемся созданием собственного класса с названием myRecord. Пусть пока в нем не будет методов, мы добавим их позже. Искомый класс создается следующим образом: function myRecord(name, family, phone, address) { this.name = name; this.family = family; this.phone = phone; this.address = address; this.secure = false; } Нетрудно заметить, что описание нашего класса есть ни что иное, как функция конструктора. Параметры конструктора предназначены для установки свойств объекта при его создании на базе класса. Свойства определяются простыми ссылками на их имена с указанием ключевого слова this. Это ключевое слово здесь указывает, что в операторе выполняется ссылка на свойства того объекта, для которого вызван конструктор, то есть для создаваемого объекта. Обратите внимание, что наш конструктор инициализирует свойство с именем secure, записывая в него значение false. Соответствующий параметр в конструкторе не предусмотрен, что вполне допустимо. Как пользоваться определенным классом? На базе этого класса вы можете создать произвольное количество объектов. Ниже мы привели фрагмент сценария JavaScript, где на базе класса myRecord создается два объекта rec1 и rec2: var rec1; var rec2; rec1 = new myRecord("Иван", "Иванов", "000-322-223", "Малая Большая ул., д. 225, кв. 226"); rec2 = new myRecord("Петр", "Петров", "001-223-3334", "Большая Малая ул., д. 552, кв. 662"); rec2.secure = true; Объекты создаются при помощи оператора new, знакомого тем, кто составлял программы на языках С++ и Java. Здесь мы передаем конструктору параметры для инициализации свойств создаваемых объектов. Что же касается свойства с именем secure, то в объекте rec2 оно инициализируется уже после создания последнего. В него записывается значение true. Мы не изменяли свойство secure объекта rec1, поэтому в нем хранится значение false. Теперь наша задача - добавление в определенный нами класс новых методов с именами printTableHead, printTableEnd и printRecord. Первые два из этих методов выводят в документ HTML, соответственно, начальный и конечный фрагмент таблицы, а третий - строки таблицы, отражающие содержимое записей. В сокращенном виде новое определение класса myRecord представлено ниже: function printTableHead() { . . . } function printTableEnd() { . . . } function printRecord() { . . . } function myRecord(name, family, phone, address) { this.name = name; this.family = family; this.phone = phone; this.address = address; this.secure = false; this.printRecord = printRecord; this.printTableHead = printTableHead; this.printTableEnd = printTableEnd; } Здесь перед определением конструктора мы расположили определения для функций-методов нашего класса. Кроме этого, в конструктор добавлено определение новых свойств: this.printRecord = printRecord; this.printTableHead = printTableHead; this.printTableEnd = printTableEnd; Эти свойства хранят ссылки на методы, определенные выше. После такого определения класса вы можете создавать объекты и обращаться к определенным методам: rec1.printTableHead(); rec1.printRecord(); rec1.printTableEnd(); rec2.printTableHead(); rec2.printRecord(); rec2.printTableEnd(); Возвращаясь к документу, показанному выше на рис. 2.3, приведем его полный исходный текст (листинг 2.2). Листинг 2.2. Файл chapter2/NewObject/NewObject.html Просмотр записей

Просмотр записей

Определение нового класса myRecord и его методов мы расположили в области заголовка документа HTML, как это принято делать. Метод printTableHead выводит в документ HTML заголовок таблицы. Внешний вид этого заголовка зависит от содержимого свойств объекта. Прежде всего метод printTableHead проверяет свойство secure, получая его значение при помощи ключевого слова this: var szSec = ""; if(this.secure) szSec = " (Secure)"; else szSec = " (Unsecure)".fontcolor("red"); Здесь это ключевое слово означает, что необходимо использовать свойство того объекта, для которого был вызван метод printTableHead. Если содержимое свойства secure равно true, в текстовую переменную szSec записывается строка " (Secure)". Если же оно равно false, в эту переменную заносится строка " (Unsecure)", причем для строки устанавливается красный цвет. Так как в JavaScript все текстовые строки (в том числе и литералы) являются объектами встроенного класса String, то для них можно вызывать определенные в этом классе методы. В частности, метод fontcolor позволяет установить цвет строки, чем мы и воспользовались. Далее метод printTableHead выводит в документ HTML оператор с параметром BORDER, с которого начинается определение таблицы, имеющей рамку. Надпись над таблицей задается с помощью динамически формируемого оператора
. В эту надпись включается имя и фамилия, извлеченные из соответствующих свойств объекта, для которого был вызван метод printTableHead. Затем этот метод выводит надписи для столбцов таблицы. Метод printTableEnd выводит в документ HTML оператор
, завершающий определение таблицы, а также пустой параграф для отделения таблиц, следующих друг за другом: function printTableEnd() { document.write("
"); document.write("

"); } Последний метод, определенный в нашем классе, называется printRecord. Он печатает содержимое первых четырех свойств объекта как строку таблицы, определенной в документе HTML только что описанной функцией printTableHead. Обратите внимание, что содержимое свойств объекта печатается наклонным шрифтом, для чего мы вызываем метод italics: document.write("

Name:" + this.name.italics() + "
В области заголовка документа HTML мы определили три функции с именами resetRCHBox, chkRadio и btnClick. Первая из этих функций предназначена для инициализации переменных, в которых хранится текущее состояние переключателей: function resetRCHBox() { bTitle=false; bHorzLine=false; bTable=false; szColor="Red"; } Функция resetRCHBox вызывается в тот момент, когда пользователь нажимает в исходном документе кнопку Reset. Она устанавливает значения четырех переменных. Переменные bTitle, bHorzLine и bTable отражают состояние, соответственно, переключателей с независимой фиксацией Show title, Show horizontal lines и Table view. Если переключатель включен, в соответствующей переменной хранится значение true, если выключен - false. В переменной szColor находится цвет текста, выбранный с помощью группы переключателей с зависимой фиксацией Text color. Начальное состояние переменных, задаваемое функцией resetRCHBox, соответствует начальному состоянию переключателей сразу после загрузки исходного документа HTML в окно браузера. Для того чтобы обеспечить вызов функции resetRCHBox при нажатии на кнопку Reset, в определении этой кнопки задан обработчик события onClick, как это показано ниже: Обработка события заключается в простом вызове функции. Теперь мы займемся переключателями с зависимой фиксацией. Эти переключатели определены в форме следующим образом: Red
Green
Blue Когда пользователь изменяет состояние переключателя, делая по нему щелчок левой клавишей мыши, вызывается обработчик события onClick. Для всех кнопок этот обработчик выглядит одинаково: if(this.checked) { chkRadio(this.form,this.value); } Прежде всего обработчик проверяет состояние переключателя, вызывая для этого метод checked. Ссылка на объект, для которого вызывается этот метод (то есть на переключатель), выполняется с помощью ключевого слова this. В том случае, когда переключатель включен, обработчик вызывает функцию chkRadio, определенную в заголовке документа следующим образом: function chkRadio(form,value) { szColor = value; } Хотя мы передаем функции два параметра (ссылку на форму, содержащую переключатель, и значение параметра VALUE текущего переключателя), используется только второй параметр. Значение этого параметра, определяющее цвет текста, сохраняется в переменной szColor. Работа с переключателями типа checkbox выполняется немного проще: Show title
Show horizontal lines
Table view Когда пользователь включает переключатель, обработчик события onClick устанавливает в состояние true соответствующую переменную. Например, при изменении состояния переключателя Show title выполняются следующие действия: if(this.checked) { bTitle=true; } Последний орган управления, который мы рассмотрим, это кнопка Create Page. Эта кнопка запускает процесс создания нового документа HTML. Для нее также определен обработчик события onClick: Этот обработчик вызывает функцию btnClick, передавая ей в качестве параметра ссылку на форму. Функция btnClick определена в области заголовка документа HTML, исходный текст которого представлен в листинге 3.2. Внутри этой функции мы определили рабочую текстовую переменную szTxt, присвоив ей значение пустой строки: var szTxt=""; Когда функция btnClick получает управление, прежде всего она формирует пустую область заголовка документа HTML: document.write(""); Далее функция анализирует содержимое переменной bTitle: if(bTitle) document.write("

Switches Checkbox and Radio

"); Если перед тем как нажать кнопку Create Page пользователь включил переключатель Show title, в переменной bTitle будет находиться значение true. В этом случае сценарий снабдит формируемый документ заголовком “Switches Checkbox and Radio”, оформив его стилем

. Аналогичным образом анализируется содержимое переменной bHorzLine: if(bHorzLine) document.write("
"); Эта переменная отражает состояние переключателя Show horizontal lines. Далее функция btnClick анализирует содержимое переменной bTable, отвечающей за способ отображения информации о состоянии переключателей в создаваемом документе HTML: if(bTable) { . . . } else { . . . } Если переключатель Table view находится во включенном состоянии, информация отображается в виде таблицы. При формировании первого столбца таблицы цвет текста внутри ячейки устанавливается в соответствии с содержимым переменной szColor: szTxt=" " + bTitle; document.write("Title:" + szTxt.bold() + ""); Напомним, что эта переменная хранит значение цвета текста, установленное группой переключателей с зависимой фиксацией Text color. Если состояние переключателей отображается в виде списка строк, цвет текста устанавливается следующим образом: document.write(""); Список select С помощью оператора мы привели ниже: Все параметры оператора , рассмотренного выше, для списка вы можете определить три обработчика события: onFocus, onBlur и onChange. События onFocus и onBlur возникают, когда список получает и теряет фокус ввода, соответственно. Что же касается события onChange, то оно создается, когда пользователь изменяет состояние списка, то есть выбирает в нем другой элемент. Примеры сценариев, работающих со списками В этом разделе мы приведем два примера сценариев, работающих со списками. Первый из этих примеров предназначен для работы с готовым списком, заполненным заранее, второй заполняет список динамически. Работа с готовым списком При работе со списками из сценария JavaScript чаще всего требуется определить, какие элементы были выбраны пользователем. На рис. 3.6 мы показали форму, в которой расположены два списка. Рис. 3.6. Форма с двумя списками различного размера Первый из этих списков предназначен для выбора цвета, а второй - размера некоторого предмета (в данном случае не имеет значение, какого именно). Списки отличаются количеством элементов, видимых одновременно. Для того чтобы увидеть все элементы списка размеров вы можете воспользоваться полосой просмотра, расположенной в правой части этого списка. Что же касается первого списка, то для того чтобы выбрать из него нужный цвет, необходимо сделать щелчок по кнопке с треугольником. При этом список раскроется (рис. 3.7). Рис. 3.7. Форма с раскрытым списком Помимо списков, в форме есть две кнопки с надписями Complete и Reset. Кнопка Reset возвращает списки в исходное состояние, в котором они находились сразу после отображения документа HTML. Если же сделать щелчок по кнопке Complete, управление получит сценарий JavaScript, который отобразит выбранный цвет и размер на экране в виде диалоговой панели с сообщением (рис. 3.8). Рис. 3.8. Выбранный цвет и размер Исходный текст документа HTML, содержащего форму и сценарий для ее обработки, представлен в листинге 3.3. Листинг 3.3. Файл chapter3/select/select.html Работа со списками

Работа со списками

Выберите цвет:

Выберите размер:

Как видно из этого листинга, в документе определена форма с именем Sel, содержащая списки ColorList и SizeList. Во втором списке мы задали размер видимой части, указав в операторе Перед заполнением этого списка мы создали массив элементов elem: elem = new Array(); Заполнение этого массива выполнялось в цикле, причем для создания элемента массива мы вызывали конструктор Option, задавая для него четыре параметра: elem[i] = new Option("Elem" + i, i, false, false); Первый параметр задает текст, который отображается в списке, второй - значение, назначаемое элементу списка при помощи параметра VALUE. Третий и четвертый параметры соответствуют свойствам, соответственно, defaultSelected и selected. Переменная i - это параметр цикла, изменяющий свое значение от нуля и до количества элементов, добавляемых в список. После того как элемент списка создан как объект класса option, его нужно записать в соответствующий элемент массива options: Sel.ListOfLinks.options[i] = elem[i]; Sel.ListOfLinks.options[i].text = document.links[i]; Здесь мы также дополнительно устанавливаем значение для свойства text элемента этого массива, записывая текст, который должен отображаться в списке. Определение выбранного из нашего списка элемента выполняется аналогично тому, как это сделано в предыдущем примере: function urlJump() { var szNewURL=""; szNewURL = document.links[Sel.ListOfLinks.selectedIndex]; window.location.href=szNewURL; } Вначале мы определяем номер выбранного элемента как значение Sel.ListOfLinks. selectedIndex. Затем это значение используется как индекс в массиве document. links, из которого в цикле происходило заполнение нашего списка. Однострочное поле text Наверное, наиболее часто в формах, размещенных на страницах серверов Web встречаются однострочные поля, предназначенные для ввода и редактирования текста. Для того чтобы встроить такое поле в форму, необходимо использовать оператор с параметром TYPE, равным значению “text”: Дополнительно можно указать параметры NAME, VALUE и SIZE, а также четыре обработчика событий, создаваемых текстовым полем. Параметр NAME позволяет задать имя поля, необходимое для обращения к свойствам объекта text, соответствующего этому полю. С помощью параметра VALUE можно записать в поле произвольную текстовую строку. Эта строка будет отображаться сразу после загрузки документа HTML в окно браузера. Параметр SIZE определяет размер (ширину) текстового поля в символах. Это размер видимой части поля. Он не ограничивает длину строки, которую можно ввести в данном поле. Свойства объекта text Сценариям JavaScript доступны три свойства поля редактирования как объекта класса text: СвойствоОписаниеdefaultValueОтражает состояние параметра VALUE nameЗначение параметра NAMEvalueТекущее содержимое поля редактирования Сразу после отображения поля редактирования свойства defaultValue и value хранят одинаковые строки. Когда пользователь редактирует текст, все изменения отражаются в свойстве value. Заметим, что изменяя содержимое свойства value, сценарий JavaScript может изменить содержимое поля редактирования. Методы объекта text Для объекта text определены методы focus, blur и select, не имеющие параметров. С помощью метода focus сценарий JavaScript может передать фокус полю редактирования, а с помощью метода blur - отобрать фокус у этого поля. Вызов метода select приводит к выделению содержимого поля редактирования. Обработчики событий объекта text Обработчики событий вызываются в следующих случаях: ОбработчикКогда вызываетсяonFocusВызывается, когда поле редактирования получает фокус вводаonBlurВызывается, когда поле редактирования теряет фокус ввода onChangeПри изменении содержимого поля редактированияonSelectПри выделении содержимого поля редактирования Проверка анкеты Методику работы с текстовыми полями в сценариях JavaScript мы рассмотрим на примере документа HTML с формой для ввода анкеты, показанной на рис. 3.9. Рис. 3.9. Форма для ввода анкеты Наш сценарий выполняет несложную обработку информации, которая вводится в текстовых полях этой формы. В частности, сценарий преобразует символы фамилии в прописные. Если указать возраст, меньший 18 лет, сценарий сделает его равным нулю. Если после заполнения анкеты нажать кнопку Complete, на экране появится диалоговая панель, отображающая содержимое отдельных полей формы (рис. 3.10). Рис. 3.10. Отображение содержимого полей анкеты Кнопка Reset устанавливает поля в исходное состояние. Исходный текст документа HTML с описанной выше формой и сценарием JavaScript вы найдете в листинге 3.4. Листинг 3.4. Файл chapter3/text/text.html Работа с текстовыми полями

Заполните анкету

Фамилия:
Имя:
Телефон:
Возраст:
Для того чтобы преобразовать символы фамилии в прописные, для поля family мы определили обработчик события onChange: onChange="this.value=this.value.toUpperCase()" После внесения изменений в содержимое поля этот обработчик вызывает метод toUpperCase, определенный в классе строк. Преобразованное значение записывается снова в свойство this.value. Поле Age имеет два обработчика для событий onChange и onFocus: onChange="this.value=CheckAge(this.value)" onFocus="this.select()" Первый из этих обработчиков вызывает функцию проверки возраста CheckAge, передавая ей значение из поля Age. Возвращенное этой функцией значение снова записывается в то же самое поле. Функция CheckAge выглядит очень просто: function CheckAge(age) { if(age < 18) return "0"; else return age; } Если ей передается строка, содержащая число, меньшее 18, она возвращает нулевое значение. В том случае, когда число больше 18 или когда в этом поле находится нечисловое значение, функция CheckAge возвращает переданную ей строку без изменений. Обработчик события onFocus вызывает метод select, выделяющий содержимое поля редактирования. Действие этого обработчика вы можете увидеть, нажимая клавишу табуляции до тех пор, пока фокус ввода не будет передан полю Age. Кнопку Complete пользователь нажимает после заполнения анкеты. Для нее мы определили обработчик события onClick: Этот обработчик вызывает функцию с именем Complete, в задачу которой входит отображение содержимого полей формы. Исходный текст функции Complete мы привели ниже: function Complete() { var szElement=""; szElement="Фамилия: " + Sel.family.value + "\nИмя: " + Sel.Name.value + "\nТелефон: " + Sel.PhoneNumber.value + "\nВозраст: " + Sel.Age.value; alert(szElement); } Обратите внимание на то, как мы адресуемся к свойствам полей формы, указывая имя формы, имена полей и имя свойства value. Многострочное поле textarea В тех случаях, когда редактируемый текст должен занимать несколько строк, в форме между операторами располагают многострочное текстовое поле: Здесь с помощью параметра NAME вы должны указать имя поля. Оно нужно для того чтобы сценарий JavaScript мог обращаться к свойствам и методам этого поля. Параметры ROWS и COLS определяют видимый размер многострочного поля редактирования, задавая, соответственно, количество строк и столбцов (количество символов, которые могут поместиться в одной строке). Параметр WRAP задает способ свертки текста и может иметь одно из трех следующих значений: ЗначениеСпособ свертки текстаoffСвертка выключена, строки отображаются так, как вводятсяvirtualСтроки сворачиваются только при отображении в окне редактирования, но передаются расширению сервера Web и сценарию JavaScript точно в таком виде, в котором вводятсяphysicalПри свертке в передаваемый текст записываются символы новой строки Методы объекта textarea Для объекта textarea определены такие же методы, что и для объекта text. Это методы focus, blur и select, не имеющие параметров. С помощью метода focus сценарий JavaScript может передать фокус полю редактирования, а с помощью метода blur - отобрать фокус у этого поля. Вызов метода select приводит к выделению содержимого многострочного поля редактирования. Обработчики событий объекта textarea Обработчики событий вызываются в следующих случаях: ОбработчикКогда вызываетсяonFocusВызывается, когда поле редактирования получает фокус вводаonBlurВызывается, когда поле редактирования теряет фокус ввода onChangeПри изменении содержимого поля редактированияonSelectПри выделении содержимого поля редактирования Пример сценария, заполняющего поле textarea Многострочное поле редактирования располагается в формах для того чтобы пользователь мог записать в нем свой отзыв, комментарий, вопрос или аналогичную информацию. При помощи сценария JavaScript нетрудно выполнить предварительное заполнение поля каким-либо текстом. Например, пусть нам нужно создать форму, предназначенную для отправления через Internet отзыва о работе некоторой программы (рис. 3.11). Рис. 3.11. Форма для отправки отзыва о работе программы Если включить переключатель “Благодарность”, сценарий автоматически запишет в поле редактирования дату и время подготовки отзыва, а также текст положительного отзыва. К этому тексту вам останется добавить только подпись. Для отправки отзыва нажмите кнопку Complete. В результате на экране появится диалоговая панель с текстом положительного отзыва (рис. 3.12). Рис. 3.12. Диалоговая панель с текстом положительного отзыва Для того чтобы сообщить изготовителю программы об ошибках, включите переключатель “Проблемы”. Сразу после этого сценарий запишет в многострочное поле текст соответствующего сообщения. Этот текст надо будет отредактировать и дополнить, описав, например, внешние проявления обнаруженной ошибки (рис. 3.13). Рис. 3.13. Отправка сообщения об ошибке Нажав кнопку Complete, вы увидите текст сообщения (рис. 3.14). Рис. 3.14. Полный текст сообщения об ошибке, обнаруженной в программе Исходный текст документа HTML, в котором определена форма для отправки отзыва, а также обрабатывающий эту форму сценарий JavaScript, представлен в листинге 3.5. Листинг 3.5. Файл chapter3/textarea/textarea.html Работа с многострочным текстовым полем

Пришлите ваш отзыв

Благодарность
Проблемы

Обратите внимание, что в нашей форме многострочное поле редактирования текста textarea создано пустым: Это поле называется “Comment”, имеет пять строк, в которых размещается до 25 символов, и режим свертки текста physical, предполагающий добавление символов новой строки, разделяющих отдельные строки введенного текста. Как происходит заполнение этого поля? В самом конце области тела документа HTML, ограниченного операторами и , мы вставили вызов функции init: Эта функция вызывается после завершения загрузки тела документа и выполняет начальное заполнение многострочного поля редактирования textarea: Sel.Comment.value = getDate() + szOK; Строка, которая записывается в это поле, образуется путем сложения строки текущей даты, полученной от функции getDate (эту функцию мы определили в нашем сценарии), со строкой szOK, содержащей текст положительного отзыва. Функция getDate определена следующим образом: function getDate() { var szDate = ""; szDate = new Date(); return szDate.toLocaleString() + "\n"; } В этой функции мы сначала создаем объект класса Data, а затем вызываем для этого объекта метод toLocaleString, возвращающий текстовую строку даты. В верхней части формы находятся два переключателя с зависимой фиксацией. С помощью этих переключателей пользователь может выбрать вид отзыва (благодарность или сообщение об ошибке): Благодарность
Проблемы Оба переключателя относятся к одной группе и потому имеют одинаковое значение параметра NAME. Для первого из них мы дополнительно указали параметр CHECKED, поэтому по умолчанию он находится во включенном состоянии (здесь мы предположили, что количество положительных отзывов будет превышать количество сообщений об ошибках). Каждый из переключателей имеет обработчик события onClick, определенный следующим образом: if(this.checked) { chkRadio(this.form,this.value); } При изменении состояния переключателя вызывается функция chkRadio. Эта функция проверяет имя включенного переключателя и заполняет поле многострочного редактора textarea соответствующим сообщением: function chkRadio(form,value) { if(value == "Thanks") Sel.Comment.value = getDate() + szOK; else Sel.Comment.value = getDate() + szTrouble + szProbList; } Функция chkRadio комбинирует тексты сообщений из текущей даты и заранее проинициализированных строк szOK, szTrouble и szProbList. Теперь о том, как наш сценарий получает текст из поля редактирования и отображает его в диалоговой панели. Для кнопки Complete мы определили обработчик события onClick: Этот обработчик вызывает функцию Complete, отображающую подготовленный отзыв на экране: function Complete() { szMsg = Sel.Comment.value; alert(szMsg); } Здесь текст извлекается из поля textarea как значение свойства value для соответствующего объекта, а затем отображается на экране при помощи встроенной функции alert. Однострочное поле password Для ввода такой информации, как пароли, в формах размещают однострочные поля редактирования типа password: Для поля password можно указать параметры NAME, VALUE и SIZE. Заметим, что это поле не может иметь обработчики событий. Параметр NAME позволяет задать имя поля, которое необходимо для обращения к свойствам объекта password, соответствующего этому полю. С помощью параметра VALUE можно записать в поле произвольную текстовую строку. Параметр SIZE определяет размер (ширину) текстового поля в символах. Это размер видимой части поля. Он не ограничивает длину строки, которую можно ввести в данном поле. Поле password похоже на поле text, рассмотренное нами ранее. Главное отличие заключается в том, что символы введенного в этом поле текста заменяются на звездочки. Свойства объекта password Сценариям JavaScript доступны три свойства поля редактирования password: СвойствоОписаниеdefaultValueОтражает состояние параметра VALUE nameЗначение параметра NAMEvalueТекущее содержимое поля редактирования Так же, как и для поля text, сразу после отображения поля редактирования свойства defaultValue и value хранят одинаковые строки. Когда пользователь редактирует текст, все изменения отражаются в свойстве value. Изменяя содержимое свойства value, сценарий может изменить содержимое поля редактирования типа password. Методы объекта password Для объекта password определены методы focus, blur и select, не имеющие параметров. С помощью метода focus сценарий JavaScript может передать фокус полю редактирования, а с помощью метода blur - отобрать фокус у этого поля. Вызов метода select приводит к выделению содержимого поля редактирования. Ввод идентификатора и пароля В качестве практического примера применения сценария JavaScript для обработки информации из полей text и password приведем документ HTML, предназначенный для регистрации пользователей. В форме регистрации новый пользователь должен ввести свой идентификатор, а также задать пароль (3.15). Рис. 3.15. Форма для регистрации нового пользователя В процессе ввода пароля легко допустить ошибку, поэтому обычно в системах регистрации требуется вводить новый пароль два раза. Если оба раза был введен одинаковый пароль, то он становится активным для данного пользователя. Наш сценарий, обрабатывающий данные из формы, показанной на рис. 3.15, решает две задачи. Во-первых, он преобразует символы идентификатора пользователя в прописные. Во-вторых, сценарий проверяет идентичность паролей, введенных в полях “Пароль” и “Проверка пароля”. Если введенные пароли идентичны, то после нажатия на кнопку Complete пользователь увидит на экране диалоговую панель с введенным идентификатором и паролем (рис. 3.16). Рис. 3.16. Диалоговая панель с идентификатором и паролем нового пользователя Если пароли не совпадают, сценарий предлагает пользователю повторить ввод паролей (рис. 3.17). Рис. 3.17. Приглашение для повторного ввода пароля Исходный текст нашего документа HTML, регистрирующего новых пользователей, показан в листинге 3.6. Листинг 3.6. Файл chapter3/password/password.html Ввод и проверка пароля

Регистрация

Идентификатор:
Пароль:
Проверка пароля:

Преобразование символов идентификатора пользователя выполняет обработчик события onChange, определенный для поля id типа text: Это преобразование выполняет функция toUpperCase, которой мы уже пользовались раньше. Что же касается проверки пароля, то этим занимается функция Complete, определенная в качестве обработчика события onClick для одноименной кнопки, предназначенной для посылки заполненной формы. Вот исходный текст этой функции: function Complete() { if(Sel.pwd.value != Sel.pwd1.value) alert("Ошибка при вводе пароля\nПопробуйте еще раз"); else { var szId=""; var szPwd=""; szId = Sel.id.value; szPwd = Sel.pwd.value; alert("Регистрация выполнена:\n" + "ID=" + szId + "\nPassword=" + szPwd); } } Если пользователь ввел разные пароли, значения свойств Sel.pwd.value и Sel. pwd1.value не совпадают. В этом случае функция Complete отображает диалоговую панель с сообщением об ошибке. При совпадении паролей функция Complete извлекает значения идентификатора пользователя Sel.id.value и его пароля Sel.pwd.value, а затем отображает их на экране. Проверка заполнения формы Для того чтобы сократить количество обращений к расширению сервера Web можно с помощью сценария JavaScript выполнить локальную проверку правильности заполнения формы. О том как проверить содержимое отдельных полей формы вы уже знаете из предыдущих разделов этой главы. Сейчас же мы остановимся на взаимодействии формы, сценария JavaScript и расширения сервера Web, такого как программа CGI или приложение ISAPI. Если вы ранее занимались созданием расширений сервера Web, обрабатывающих данные, полученные от форм, то знаете, что для посылки данных расширению используется кнопка типа submit. Эта кнопка встраивается в форму следующим образом: Параметры NAME и VALUE здесь имеют такое же назначение, что и для изученной нами ранее кнопки типа button. Обработчик события onClick позволяет сценарию JavaScript выполнить обработку содержимого полей формы, прежде чем данные из этих полей будут переданы расширению сервера Web. К сожалению, вне зависимости от результатов обработки данные из формы всегда передаются серверу Web, что не всегда удобно. Было бы лучше, если бы сценарий JavaScript мог отказаться от посылки этих данных, если они введены пользователем с ошибкой. Простейший выход из этой ситуации - замена кнопки типа submit на обычную кнопку button. С этой кнопкой должен быть связан сценарий JavaScript, который проверяет данные, введенные пользователем в поля формы, и посылающий их серверу Web явным образом. В этом разделе мы приведем исходные тексты документа HTML, предназначенного для ввода идентификатора пользователя и пароля (листинг 3.7). Это документ аналогичен приведенному в предыдущем разделе. В нашем примере с помощью сценария JavaScript мы не только проверяем пароль, но и отправляем данные расширению сервера Web, если пароль введен правильно. Листинг 3.7. Файл chapter3/validation/validation.html Ввод и проверка пароля

Регистрация

Идентификатор:
Пароль:
Проверка пароля:

При определении формы для оператора мы указали параметр ACTION:
Этот параметр задает путь к загрузочному файлу программы CGI, расположенному в каталоге сценариев сервера Web. Отметим, что такой каталог создается администратором сервера Web. С помощью специальной программы администратор указывает права доступа к этому каталогу, разрешающие исполнение расположенных там загрузочных файлов CGI и библиотек динамической компоновки DLL приложений ISAPI. Подробно об этом вы можете прочитать в 29 томе нашей “Библиотеки системного программиста”, который называется “Сервер Web своими руками”. Функция Complete, которая вызывается при нажатии на одноименную кнопку, проверяет пароли, введенные в полях pwd и pwd1. Если эти пароли совпадают, сценарий посылает данные серверу с помощью метода submit, определенного в форме: document.forms[0].submit(); Здесь мы обращаемся к первой (и единственной) форме, определенной в нашем документе HTML. Программа CGI с именем control.exe отображает полученные данные в динамически создаваемом документе HTML (рис. 3.18). Рис. 3.18. Данные, полученные программой CGI от формы В списке значений полей, расположенным в нижней части этого документа, находится идентификатор и пароль пользователя. Исходный текст программы CGI, с которой работает наш документ HTML, показан в листинге 3.8. Листинг 3.8. Файл chapter3/validation/controls/controls.c // =============================================== // Программа CGI controls.c // Получение данных от формы и их // отображение в документе HTML, // создаваемом динамически // // (C) Фролов А.В., 1997, 1998 // E-mail: // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // =============================================== #include #include #include // Прототипы функций перекодировки void DecodeStr(char *szString); char DecodeHex(char *str); // ------------------------------------------------ // Функция main // Точка входа программы CGI // ------------------------------------------------ void main(int argc, char *argv[]) { int lSize; FILE * fileReceived; char * szMethod; char szBuf[8196]; char szSrcBuf[8196]; char * szPtr; char * szParam; // Вывод заголовка HTTP и разделительной строки printf("Content-type: text/html\n\n"); // Вывод начального форагмента документа HTML, // формируемого динамически printf(""); printf("User Registration" ""); // Определяем метод передачи данных szMethod = getenv("REQUEST_METHOD"); // Обработка метода POST if(!strcmp(szMethod, "POST")) { // Определяем размер данных, полученных от браузера // при передаче данных из полей формы lSize = atoi(getenv("CONTENT_LENGTH")); // Читаем эти данные в буфер szBuf из // стандартного потока ввода STDIN fread(szBuf, lSize, 1, stdin); // Создаем файл, в который будут записаны // принятые данные fileReceived = fopen("received.dat", "w"); // Выполняем запись принятых данных fwrite(szBuf, lSize, 1, fileReceived); // Закрываем файл принятых данных fclose(fileReceived); // Отображаем значения некоторых переменных среды printf("

Переменные среды

"); // Метод доступа printf("REQUEST_METHOD = %s", getenv("REQUEST_METHOD")); // Размер полученных данных в байтах printf("
CONTENT_LENGTH = %ld", lSize); // Тип полученных данных printf("
CONTENT_TYPE = %s", getenv("CONTENT_TYPE")); // Закрываем буфер данных двоичным нулем, // превращая его таким образом в строку szBuf[lSize] = '\0'; // Делаем копию принятых данных в буфер szSrcBuf strcpy(szSrcBuf, szBuf); // Отображаем принятые данные без обработки printf("

Принятые данные

"); printf("

%s", szSrcBuf); // Выполняем перекодировку принятых данных DecodeStr(szSrcBuf); // Отображаем результат перекодировки printf("

Данные после перекодировки

"); printf("

%s", szSrcBuf); // Выводим список значений полей формы printf("

Список значений полей

"); // Дописываем в конец буфера принятых данных // символ "&", который используется в качестве // разделителя значений полей szBuf[lSize] = '&'; szBuf[lSize + 1] = '\0'; // Цикл по полям формы for(szParam = szBuf;;) { // Ищем очередной разделитель szPtr = strchr(szParam, '&'); // Если он найден, раскодируем строку параметров if(szPtr != NULL) { *szPtr = '\0'; DecodeStr(szParam); // Выводим в документ значение параметра printf("%s
", szParam); // Переходим к следующему параметру szParam = szPtr + 1; // Если достигнут конец буфера, завершаем цикл if(szParam >= (szBuf + lSize)) break; } else break; } // Выводим завершающий фрагмент документа HTML printf(""); return; } } // ------------------------------------------------ // Функция DecodeStr // Раскодирование строки из кодировки URL // ------------------------------------------------ void DecodeStr(char *szString) { int src; int dst; char ch; // Цикл по строке for(src=0, dst=0; szString[src]; src++, dst++) { // Получаем очередной символ перекодируемой строки ch = szString[src]; // Заменяем символ "+" на пробел ch = (ch == '+') ? ' ' : ch; // Сохраняем результат szString[dst] = ch; // Обработка шестнадцатеричных кодов вида "%xx" if(ch == '%') { // Выполняем преобразование строки "%xx" // в код символа szString[dst] = DecodeHex(&szString[src + 1]); src += 2; } } // Закрываем строку двоичным нулем szString[dst] = '\0'; } // ------------------------------------------------ // Функция DecodeHex // Раскодирование строки "%xx" // ------------------------------------------------ char DecodeHex(char *str) { char ch; // Обрабатываем старший разряд if(str[0] >= 'A') ch = ((str[0] & 0xdf) - 'A') + 10; else ch = str[0] - '0'; // Сдвигаем его влево на 4 бита ch <<= 4; // Обрабатываем младший разряд и складываем // его со старшим if(str[1] >= 'A') ch += ((str[1] & 0xdf) - 'A') + 10; else ch += str[1] - '0'; // Возвращаем результат перекодировки return ch; } Это упрощенный вариант программы CGI, которую мы описали в упомянутом выше 29 томе “Библиотеки системного программиста”. Там вы найдете ее полное описание. Шестнадцатеричный калькулятор На языке сценариев JavaScript можно составлять достаточно большие программы. В качестве примера мы приведем исходный текст сценария, выполняющего функции шестнадцатеричного калькулятора (рис. 3.19). Рис. 3.19. Калькулятор, выполненный на языке сценариев JavaScript Калькулятор создан в документе HTML как форма с двумя текстовыми полями и кнопками, расположенными в ячейках таблицы. С помощью кнопок 0 - F можно вводить шестнадцатеричные числа, которые будут отображаться в текстовом поле Hex. В поле Dec находится десятичное значение введенного шестнадцатеричного числа или результата вычислений. Кнопки “+”, “-“, “*” и “/” предназначены, соответственно, для выполнения операции сложения, вычитания, умножения и деления. При помощи кнопки “Enter” можно получить результат вычислений. Кнопка CE позволяет стереть текущее введенное число, а кнопка C - сбросить промежуточный результат вычислений и текущее введенное число. Исходный текст документа HTML с калькулятором представлен в листинге 3.9. Листинг 3.9. Файл chapter3/hexcalc/hexcalc.html Hexadecimal calculator
Hex:
Dec:
Рассмотрим наиболее интересные моменты. Когда калькулятор отображается в первый раз, в текстовых полях displayHex и displayDec, предназначенных, соответственно, для отображения чисел в шестнадцатеричном и десятичном виде, находятся нулевые значения: . . . . . . . . . Это значение устанавливается параметром VALUE. Обратите внимание, что для текстовых полей displayHex и displayDec мы предусмотрели обработчики событий onFocus. Этот обработчик получает управление, когда пользователь передает полю фокус ввода. Задача обработчика заключается в том, чтобы снова отобрать фокус ввода, предотвратив непосредственное редактирование числа пользователем. С каждой из кнопок, связанной с вводом шестнадцатеричного числа, связан обработчик события onClick, вызывающий функцию putNumber, например: INPUT TYPE="button" NAME="F" VALUE=" F " onClick="putNumber(this,this.form);"> Этой функции передаются два параметра - нажатая кнопка (как объект класса button) и форма, в которой эта кнопка находится. Задача функции putNumber - ввод числа и его отображение в двух текстовых полях, расположенных в верхней части калькулятора: function putNumber(btn,form) { var szOld = ""; var szNew = ""; if(newnumber) { form.displayHex.value = ""; form.displayDec.value = ""; newnumber = false; } szOld = form.displayHex.value; szNew = szOld.concat(btn.name); nCurrent = eval("0x" + szNew); form.displayHex.value = szNew; form.displayDec.value = nCurrent; } В самом начале функция putNumber проверяет двоичную переменную newnumber. Если значение этой переменной равно true, пользователь вводит первую цифру нового числа. В этом случае функция putNumber сбрасывает содержимое текстовых полей displayHex и displayDec, а также устанавливает значение newnumber, равное false. Далее функция добавляет введенную пользователем цифру спереди к переменной szOld, равной текущему значению из поля displayHex. При этом она вызывает метод concat из класса String, предназначенный для слияния (конкатенации) строк. На следующем этапе к введенному шестнадцатеричному числу добавляется префикс “0x”, после чего происходит вычисление текущего значения функцией eval. Эта функция пытается интерпретировать текстовую строку, переданную ей в качестве параметра, как арифметическое выражение, возвращая результат интерпретации в виде численного значения. Этот результат сохраняется в переменной nCurrent и отображается в текстовом поле displayDec (исходное шестнадцатеричное число отображается в поле displayHex). Если после ввода числа пользователь нажимает одну из четырех кнопок, предназначенных для выполнения операций сложения, вычитания, умножения и деления, вызываются функции, назначенные для этих кнопок в обработчике события onClick. Это функции plusOp (сложение), minusOp (вычитание), mulOp (умножение) и divOp (деление). Перечисленные функции похожи друг на друга, поэтому мы ограничимся подробным рассмотрением только одной из них, выполняющую операцию сложения: function plusOp(form) { var result; result = total + " " + lastOperation + " " + form.displayDec.value; total = eval(result); lastOperation = "+"; form.displayHex.value = dec2hex(total); form.displayDec.value = total; newnumber = true; } Здесь глобальная переменная total, имеющая начальное значение, равное нулю, используется для хранения промежуточных результатов вычислений. Она складывается с пробелом и текстовой строкой lastOperation, затем еще с одним пробелом и, наконец, со строкой десятичного представления введенного числа, извлеченного из поля displayDec. Строка lastOperation предназначена для хранения кода операции, которая выполнялась в последний раз. Дополнительные пробелы нужны для корректной работы с отрицательными числами. С помощью функции eval функция plusOp вычисляет результат операции и записывает его в переменную total. Затем в переменную lastOperation записывается код операции сложения - строка “+”. На следующем этапе функция plusOp преобразует значение total с помощью функции dec2hex и отображает результат в шестнадцатеричном виде в поле displayHex, а также в двоичном - в поле displayDec. Перед тем как возвратить управление, функция plusOp записывает в переменную newnumber значение true. Это приводит к тому, что при дальнейшем вводе цифр они будут рассматриваться как цифры второго слагаемого, участвующего в операции сложения. Функция getResult вызывается, когда пользователь нажимает на клавишу нашего калькулятора с надписью “Enter”: function getResult(form) { var result; result = total + lastOperation + eval("0x" + form.displayHex.value); total = eval(result); form.displayHex.value = dec2hex(total); form.displayDec.value = total; newnumber = true; } От только что описанной функции plusOp эта функция отличается лишь тем, что она не изменяет значение переменной lastOperation (так как данная кнопка служит для получения итогового результата, а не для выполнения арифметической операции). Рассмотрим функцию dec2hex, выполняющую преобразование десятичного числа в шестнадцатеричное. Результат преобразования эта функция возвращает в виде текстовой строки. В начале своей работы функция dec2hex проверяет знак исходного числа. Отрицательные числа преобразуются в положительные, при этом в переменную bNegative записывается значение true. Алгоритм преобразования десятичного числа в шестнадцатеричное основан на делении исходного числа на 16 в цикле. Если целая часть результата деления, вычисляемая с помощью метода Math.floor, оказывается меньше 16, цикл завершается. В противном случае остаток от деления рассматривается как значение текущего шестнадцатеричного разряда. Для того чтобы получить символическое представление шестнадцатеричного числа по его значению, мы извлекаем нужный символ из строки szHexTable, вызывая для этого метод charAt: szBuf=szHexTable.charAt(nRem); szResult = szBuf.concat(szResult); После завершения цикла функция вычисляет старшие разряды результата, а также корректирует знак этого результата в соответствии с состоянием переменной bNegative. Электронные часы С помощью сценария JavaScript и формы вы можете сделать достаточно сложные электронные часы, которые будут показывать не только время, но и дату в различных форматах с учетом смещения часового пояса (рис. 3.20). Рис. 3.20. Электронные часы в документе HTML Исходный текст документа HTML с электронными часами представлен в листинге 3. 10. Листинг 3.10. Файл chapter3/clock/clock.html Электронные часы

Электронные часы

Дата:
Время:
Смещение часового пояса:
Дата GMT:
Локальная дата:
Часы запускаются сразу после загрузки документа HTML в окно браузера. При этом управление получает функция updateClock. Эта функция определена в заголовке, а ее вызов находится в конце области тела документа HTML. Получив управление, функция updateClock создает объект Data для текущей даты, установленной в компьютере: var dtDate = new Date(); Затем функция определяет три компоненты времени (часы, минуты и секунды), вызывая для этого методы getHours, getMinutes и getSeconds, определенные в классе Date: var nHours = dtDate.getHours(); var nMinutes = dtDate.getMinutes(); var nSeconds = dtDate.getSeconds(); Полученные таким образом значения комбинируются в текстовой строке szCurrentTime: szCurrentTime = nHours + ":" + nMinutes + ":" + nSeconds; В дальнейшем время будет записано функцией updateClock в поле time формы Clock, как это показано ниже: Clock.time.value = szCurrentTime; Строка текущей даты получается в результате вызова методов getDate, getMonth и getYear: szCurrentDate = dtDate.getDate() + "." + dtDate.getMonth() + "." + dtDate.getYear(); Эта строка записывается в поле dat формы Clock: Clock.dat.value = szCurrentDate; Для вычисления смещения часового пояса мы воспользовались методом getTimezoneOffset, возвращающим значение в минутах: szTimeZone = dtDate.getTimezoneOffset() / 60; Для того чтобы вычислить смещение в часах, мы разделили результат, полученный от метода getTimezoneOffset, на 60. Вычисленное смещение часового пояса записывается в поле timeZone формы Clock: Clock.timeZone.value = szTimeZone; Для получения времени по Гринвичу мы воспользовались методом toGMTString: szGMT = dtDate.toGMTString(); Полученное значение будет записано в поле gmt формы Clock: Clock.gmt.value = szGMT; И, наконец, локальную дату и время мы определяем с помощью метода toLocaleString: szLocal = dtDate.toLocaleString(); Результат записывается в поле loc формы Clock: Clock.loc.value = szLocal; Периодическое выполнение функции updateClock достигается с помощью метода setTimeout: nTimer = setTimeout("updateClock()", 1000); Здесь мы указали, что период обновления показаний наших часов должен быть равен одной секунде. 4 JAVASCRIPT И ФРЕЙМЫ Для того чтобы работать сразу с несколькими документами HTML, можно предоставить пользователю многооконный интерфейс, реализованный при помощи фреймов. Подробно о фреймах мы рассказали в 29 томе “Библиотеки системного программиста”. Который называется “Сервер Web своими руками”. Файл описания фреймов Для того чтобы объединить несколько документов HTML при помощи фреймов, вам нужно подготовить специальный документ HTML, в котором находится описание параметров фреймов, таких как размер и расположение. Особенность такого документа - отсутствие на своем обычном месте области тела документа, выделенного операторами и . Вместо этого в файле описания фреймов располагаются операторы , , и , как это показано ниже: . . . . . . . . . Параметры ROWS и COLS оператора определяют размеры фреймов и задаются в виде списка значений, разделенных запятой. Вы можете определить обработчики событий onLoad и onUnload, получающие управление, соответственно, при загрузке содержимого в главное окно фрейма и при замене текущего документа HTML в этом окне на другой. Фактически эти обработчики относятся не к фреймам, а к окну, где эти фреймы отображаются. Для тех браузеров, которые не могут работать с фреймами, необходимо подготовить документ HTML, расположив его тело между операторами и . В этом документе имеет смысл разместить сообщение о том, что для просмотра данной страницы Web необходимо применять более современный браузер. Параметры оператора Рассмотрим подробнее параметры оператора , предназначенного для определения набора фреймов. ПараметрОписаниеCOLSШирина колонки в процентах, пикселах или относительный размерROWSВысота строки в процентах, пикселах или относительный размер FRAMEBORDERЕсли значение этого параметра равно 1, фреймы будут иметь трехмерную рамку, ширина которой задается в пикселах. В том случае, когда указано значение 0, рамка не создаетсяBORDERИспользуется только браузером Netscape Navigator. Задает толщину рамки фрейма в пикселахFRAMESPACINGС помощью этого параметра можно задать дополнительное расстояние между фреймами в пикселах Параметры COLS и ROWS нужны в том случае, когда фреймы, определенные в наборе, располагаются в виде таблицы. Первый из этих параметров указывает ширину колонки, а второй - высоту строки. Если фреймы располагаются в одном столбце, параметр COLS указывать не надо. Аналогично, если фреймы занимают только одну строку, не нужно указывать параметр ROWS. Вы можете задать значения для параметров COLS и ROWS либо в процентном отношении, соответственно, к ширине и высоте окна браузера, либо в пикселах. Если вместо значения указан символ *, колонка или строка занимают всю оставшуюся часть окна. Например, ниже указано, что высота первого фрейма равна 90 пикселам, а второй фрейм занимает всю нижнюю часть окна браузера: В следующем примере два фрейма, расположенные рядом, занимают, соответственно, 20% и 80% ширины окна браузера. Параметры оператора Между операторами и располагаются операторы , определяющие параметры отдельных фреймов. Это параметры SRC и NAME. Первый из этих параметров задает адрес URL документа HTML, который будет загружен в данный фрейм, а второй - имя фрейма, которое можно использовать в сценарии JavaScript для адресации объектов, расположенных во фрейме. Заметим, что адрес URL не должен содержать ссылки на локальные метки (anchor). Оператор имеет следующие параметры: ПараметрОписаниеALIGNИспользуется только для “плавающих фреймов” в браузере Microsoft Internet Explorer. Задает выравнивание фрейма или текста, расположенного рядом с фреймом. Этот параметр может принимать следующие значения: LEFT, CENTER, RIGHT, TOP, BOTTOMMARGINHEIGHTРазмер отступа по вертикали от границ фрейма в пикселахMARGINWIDTHРазмер отступа по горизонтали от границ фрейма в пикселахFRAMEBORDERЕсли значение этого параметра равно 1, фреймы будут иметь трехмерную рамку, ширина которой задается в пикселах. В том случае, когда указано значение 0, рамка не создаетсяNAMEЭтот параметр задает имя фрейма, которое используется в операторе ссылки
для указания, в какой фрейм нужно загрузить новый документNORESIZEЕсли указан этот параметр, пользователь не сможет изменять размеры фрейма, передвигая его границы мышью SCROLLINGПараметр SCROLLING определяет, нужно ли создавать полосы просмотра для свертки содержимого фрейма. Для этого параметра можно указывать следующие значения: YES полосы просмотра создаются всегда; NO полосы просмотра не создаются; AUTO полосы просмотра создаются только при необходимости, когда документ HTML не помещается полностью в окне фреймаSRCАдрес URL файла с документом HTML, который загружается в окно фрейма Взаимодействие между фреймами С помощью сценариев JavaScript вы можете наделить фреймы возможностями, недостижимыми с применением одного лишь только языка разметки гипертекста HTML. Например, один из фреймов может содержать ссылки на документы, которые при активизации этих ссылок загружаются в окно другого фрейма. Сценарий JavaScript позволит загружать таким образом не один документ, а одновременно несколько документов в разные фреймы. Пример организации такого взаимодействия мы рассмотрим немного позже, а сейчас на конкретном примере расскажем о том, как можно передавать данные между объектами форм, расположенных в разных фреймах. Десятично-шестнадцатеричный преобразователь На рис. 4.1. показан внешний вид десятично-шестнадцатеричного преобразователя, выполненного на базе документов HTML с фреймами и сценарием JavaScript. Рис. 4.1. Десятично-шестнадцатеричный преобразователь, выполненный с использованием фреймов Верхний фрейм используется для размещения заголовка. Клавиатура преобразователя, предназначенная для ввода десятичных чисел и запуска процесса преобразования, находится в левом фрейме. Правый фрейм используется для отображения исходного десятичного числа и результата преобразования. Вы можете вводить исходное число не только с помощью клавиатуры, но и непосредственно в поле Dec, расположенное в правом фрейме. Поле Hex заблокировано для вода при помощи обработчика события onFocus. Аналогичный прием мы использовали в шестнадцатеричном калькуляторе, исходные тексты которого были приведены в предыдущей главе. Исходный текст файла описания фреймов представлен в листинге 4.1. Листинг 4.1. Файл chapter4/Converter/index.html Десятично-шестнадцатеричный преобразователь Наш сценарий будет работать с фреймами toc и mainpage, расположенными, соответственно, в файлах с именами toc.html и main.html. В файле title.html располагается заголовок (листинг 4.2). Листинг 4.2. Файл chapter4/Converter/title.html

Десятично-шестнадцатеричный преобразователь

Исходный текст документа, содержащего форму с полями Dec и Hex, представлен в листинге 4.3. Листинг 4.3. Файл chapter4/Converter/main.html
Для поля исходного десятичного числа при помощи параметра NAME мы задали имя decValue. Поле результата называется hexValue. Эти имена используются сценарием JavaScript для адресации наших полей. Документ toc.html (листинг 4.4) содержит форму с кнопками и сценарий JavaScript. Листинг 4.4. Файл chapter4/Converter/toc.html
Hex:
Dec:
Сценарий нашего десятично-шестнадцатеричного преобразователя работает аналогично сценарию шестнадцатеричного калькулятора (за исключением, конечно, того, что преобразователь не выполняет никаких арифметических действий). Главное отличие заключается в том, что теперь поля для ввода и отображения чисел располагаются в другом документе HTML, загруженном в отдельный фрейм. Для того чтобы проинициализировать поля hexValue и decValue, мы ссылаемся на форму, расположенную внутри фрейма mainpage: parent.mainpage.document.forms[0].hexValue.value = ""; parent.mainpage.document.forms[0].decValue.value = ""; Здесь parent ссылается на объект, который является родительским по отношению к документу HTML, содержащему сценарий. В данном случае это окно, содержащее все наши фреймы. Для чтения содержимого поля decValue применяется аналогичная техника: szOld = parent.mainpage.document.forms[0].decValue.value; Функция getResult, выполняющая десятично-шестнадцатеричное преобразование, получает исходное число из поля decValue и передает его функции dec2hex . Результат преобразования, выполненного этой функцией, записывается затем в поле hexValue: function getResult(form) { parent.mainpage.document.forms[0].hexValue.value = dec2hex(parent.mainpage. document.forms[0].decValue.value); bNewNumber = true; } Отображение нескольких документов HTML На рис. 4.2 мы показали внешний вид содержимого нашего авторского компакт-диска, первый выпуск которого появился недавно в продаже. Рис. 4.2. Авторский компакт-диск Информация отображается в трех фреймах. Верхний фрейм используется для заголовка, левый выполняет роль оглавления, и, наконец, правый - служит для показа содержимого. Нажимая кнопки, расположенные в левом фрейме, вы можете просматривать в правой части окна различные документы HTML. В первом выпуске компакт-диска мы не использовали сценарии JavaScript. Сейчас мы покажем, как можно с помощью несложного сценария усовершенствовать интерфейс пользователя. Мы будем использовать фрейм заголовка, расположенный в верхней части окна, для размещения аннотации на материал, представленный в правом фрейме. При этом если нажать кнопку с надписью “Добро пожаловать”, в заголовке появится наш логотип, показанный на рис. 4.2. Если же нажать кнопку “Книги” или “Статьи”, заголовок будет выглядеть так, как это показано на рис. 4.3 и 4.4, соответственно. Рис. 4.3. Просмотр информации о книгах Рис. 4.4. Просмотр информации о статьях В листинге 4.5 мы показали исходный текст файла описания фреймов. Листинг 4.5. Файл chapter4/ourCD/index.html Авторский диск Александра Фролова и Григория Фролова Так же как и в предыдущем примере, здесь описаны три фрейма. Документ заголовка, который отображается сразу после загрузки фрейма, а также после того как пользователь нажмет кнопку “Добро пожаловать”, показан в листинге 4.6. Листинг 4.6. Файл chapter4/ourCD/title.html

Александр Фролов и Григорий Фролов, технические 
писатели из Москвы Александр Фролов и Григорий Фролов, технические 
писатели из Москвы

Файл main.html представлен в листинге 4.7 (в сокращенном виде). Он не имеет никаких интересных особенностей. Листинг 4.7. Файл chapter4/ourCD/main.html Untitled

Добро пожаловать!

Вы приобрели первый выпуск авторского компакт-диска технических писателей Александра Фролова и Григория Фролова. . . .

© Александр Фролов, Григорий Фролов, 1997
Гораздо важней для нас файл toc.html. В этом файле находятся функции сценария JavaScript и ссылки на другие документы HTML. Этот файл с несущественными сокращениями показан в листинге 4.8. Листинг 4.8. Файл chapter4/ourCD/toc.html

Добро пожаловать
Книги
Статьи
. . .

Функция loadPage загружает в фреймы mainpage и title документы HTML, адреса URL которых передаются ей через параметры. Для загрузки мы устанавливаем свойство location.href для окна соответствующего фрейма: parent.mainpage.window.location.href=szNewURL; parent.title.window.location.href=szTitle; Для вызова функции loadPage мы использовали следующую конструкцию: Добро пожаловать Здесь в параметре HREF оператора ссылки после ключевого слова javascript мы расположили строку вызова функции. Обратите внимание на использование одинарных и двойных кавычек. Так как в сценариях JavaScript вложение одинаковых кавычек недопустимо, для строк, передаваемых функции в качестве параметров, мы применили одинарные кавычки. Значение параметра HREF выделено при этом двойными кавычками. 5 РАСТРОВЫЕ ИЗОБРАЖЕНИЯ Растровые изображения в виде файлов формата GIF и JPEG широко применяются в документах HTML, так как с их помощью можно значительно улучшить внешний вид страниц серверов Web. К сожалению, возможности HTML не позволяют добиться достаточно сложных видеоэффектов без применения дополнительных средств, таких как аплеты Java, компоненты ActiveX и сценарии JavaScript. Фактически кроме статической графики вы можете использовать только анимационные изображения, построенные с применением многосекционных файлов GIF, и сегментированные графические изображения. Последние нужны для создания ссылок. В этой главе мы рассмотрим некоторые возможности по графическому оформлению страниц серверов Web, которые будут в вашем распоряжении при использовании сценариев JavaScript. Растровое изображение как объект Для того чтобы встроить растровое изображение в документ HTML, необходимо использовать оператор . Общий вид этого оператора показан ниже: Здесь мы указали только три параметра. Полный список параметров оператора с кратким их описанием вы найдете ниже: ПараметрОписаниеSRCАдрес URL файла с растровым графическим изображениемNAMEИмя объекта, соответствующего растровому графическому изображению. Это имя может быть использовано для ссылки на объект в сценариях JavaScriptALTТекстовая строка, которая отображается в тех случаях, когда браузер не может показывать графические изображения или когда такая возможность отключенаALIGNВыравнивание текста относительно графического изображения LEFT по левой границе; RIGHT по правой границе; TOP по верхней границе; MIDDLE по центру изображения; BOTTOM по нижней границе; TEXTTOP выравнивание по верхней границе относительно самых высоких символов в текстовой строке; ABSMIDDLE выравнивание середины текстовой строки относительно середины изображения; BASELINE выравнивание нижней рамки изображения относительно базовой линии текстовой строки; ABSBOTTOM выравнивание нижней границы изображения относительно нижней границы текущей строкиHEIGHTВысота изображения в пикселахWIDTHШирина изображения в пикселахBORDERШирина рамки вокруг изображения в пикселах (используется только браузером Netscape Navigator)HSPACEШирина свободного пространства в пикселах, отделяющее изображение от текста по горизонталиVSPACEШирина свободного пространства в пикселах, отделяющее изображение от текста по вертикалиUSEMAP Адрес URL файла, содержащего так называемую карту изображения. Эта карта используется для сегментированной графикиISMAPЭтот параметр указывает, что данное изображение является сегментированным Параметры оператора определяют адрес файла с изображением, выравнивание текста, расположенного возле изображения и так далее. С помощью параметров HEIGHT и WIDTH вы можете выполнять масштабирование графических изображений. Значение этих параметров можно указывать в процентах от ширины окна просмотра. Масштабирование позволяет подготовить графический файл относительно небольшого размера, который быстро передается через Internet, и занимает при этом значительную площадь в окне браузера. Вы, однако, не можете масштабировать сегментированные графические изображения и фоновые изображения. Применение сегментированной графики мы подробно рассмотрели в 29 томе “Библиотеки системного программиста. Если в документе HTML размещено несколько растровых изображений, то вы можете адресовать соответствующие объекты как элементы массива document.images. Например, первое изображение адресуется следующим образом: document.images[0]. Однако в некоторых случаях удобнее пользоваться именами изображений, определенными параметром NAME оператора . Объект-изображение имеет свойство src, соответствующее параметру SRC оператора . Адресуясь к этому свойству, вы можете не только определять текущий адрес URL изображения, но и задавать новый. Этим мы воспользуемся в следующем разделе нашей книги. Динамическая замена растровых изображений Одна из наиболее интересных возможностей, доступных при использовании сценариев JavaScript, заключается в динамической замене графических изображений, указанных в параметре SRC оператора . Например, в следующей строке сценария JavaScript мы указываем, что изображение с именем btn1 должно иметь адрес URL pic/aurap.gif: document.btn1.src=”pic/aurap.gif” Здесь мы указали неполный адрес URL, однако можно указывать и полный адрес. Что произойдет при выполнении приведенной выше строки сценария? Область, выделенная в окне браузера для растрового изображения btn1 будет заполнена изображением pic/aurap.gif. Если до этого там было другое изображение, оно будет заменено на новое. Как можно воспользоваться динамической заменой растровых изображений? Во-первых, вы можете создавать графические ссылки, которые изменяют свой вид, когда над ними находится курсор мыши. Во-вторых, с помощью замены растровых изображений в сценарии JavaScript можно создавать анимационные изображения. Рассмотрим примеры сценариев, решающих указанные задачи. Изменение внешнего вида графических ссылок В документе HTML, внешний вид которого показан на рис. 5.1, находятся две кнопки, созданные как растровые графические изображения. Они используются для активизации ссылок, соответствующих двум другим документам HTML. Рис. 5.1. Кнопка с надписью АУРАМЕДИА изменила свой цвет Если расположить курсор над одной из этих кнопок, надпись на этой кнопке изменит свой цвет. Это достигается динамической заменой графического изображения кнопки при помощи сценария JavaScript. Обратите внимание на исходный текст документа HTML, показанный в листинге 5. 1. Листинг 5.1. Файл chapter5/grbutton/grbutton.html

Журнал Аурамедиа
Soft-каталог
Для создания ссылок мы воспользовались оператором . Этот оператор использован здесь совместно с оператором , поэтому ссылка отображается как графическое изображение. Для оператора ссылки мы определили обработчики событий onMouseOver и onMouseOut: onMouseOver="document.btn1.src='pic/aurap.gif'" onMouseOut="document.btn1.src='pic/aura.gif'" Когда курсор мыши оказывается над ссылкой (то есть над графическим изображением ссылки), управление получает обработчик события onMouseOver. Этот обработчик загружает изображение pic/aurap.gif, где слово АУРАМЕДИА написано красным цветом (для второй кнопки в аналогичной ситуации загружается изображение pic/softcatp.gif). После того как пользователь убирает курсор мыши с поверхности кнопки, в дело включается обработчик события onMouseOut. Он восстанавливает исходное изображение, указанное в параметре SRC оператора . Создание анимационных изображений В следующем примере мы покажем, как с помощью динамической смены растровых графических изображений в сценарии JavaScript можно получить эффект анимации. На рис. 5.2 мы показали документ HTML, в котором используется такая анимация. Рис. 5.2. Анимация с помощью сценария JavaScript В окне браузера последовательно отображаются кадры анимационного изображения (рис. 5.3), причем сначала в прямой, а затем - в обратной последовательности. Это выглядит так, как будто слово Noise периодически тонет в цветном шуме и затем проявляется вновь. Заметим, что похожий эффект мы уже получали совершенно другими средствами в аплете Java, исходный текст которого был опубликован в журнале “Мир ПК” №1 за 1998 год. Рис. 5.3. Изображения отдельных кадров анимационной последовательности Также мы обратим ваше внимание, что для достижения подобного эффекта при помощи многосекционного файла GIF размер этого файла было бы необходимо удвоить. Причина этого заключается в том, что вам пришлось бы включить в файл кадры вначале в прямой, а затем в обратной последовательности. Сценарий JavaScript позволяет более тонко управлять процессом отображения кадров, что можно использовать для достижения достаточно сложных визуальных эффектов относительно простыми средствами. Исходный текст документа HTML, в котором имеется сценарий, выполняющий анимацию, показан в листинге 5.2. Листинг 5.2. Файл chapter5/noise/noise.html Animation with JavaScript В теле документа с помощью оператора мы разместили первый кадр анимационной последовательности: С помощью параметра NAME мы задали имя Img. Это имя будет использовано сценарием JavaScript для ссылки на объект. Кроме того, в теле нашего документа находится вызов функции showNextImage. Данная функция предназначена для отображения очередного кадра анимационной последовательности. В области заголовка документа HTML находится определение функции showNextImage и двух глобальных переменных: var i=1; var bForward=true; Переменная i хранит номер текущего кадра, отображаемого в окне браузера. Этот номер вначале увеличивается функцией showNextImage от 1 до 16, а затем снова уменьшается до 1. Изменение номера происходит на 1 (в ту или в другую сторону) при каждом вызове функции showNextImage. В переменной bForward хранится направление изменения номера кадра. Значение true соответствует прямому направлению, а значение false - обратному. Когда функция showNextImage получает управление, она анализирует содержимое переменной bForward. Если в этой переменной находится значение true, функция showNextImage увеличивает значение переменной i, а затем сравнивает результат с числом 17. Когда отображение всех кадров в прямой последовательности завершено, в переменную bForward записывается false, после чего при следующем вызове функции showNextImage номер текущего кадра будет не увеличиваться, а уменьшаться. Для отображения очередного кадра функция showNextImage изменяет значение свойства src изображения document.Img, как это показано ниже: document.Img.src= "img0" + i + ".gif"; Имя файла, в котором хранится изображение кадра, конструируется из строки “img0”, номера кадра, и строки “.gif”. Последнее, что делает функция showNextImage перед тем как возвратить управление, - вызывает функцию setTimeout: setTimeout("showNextImage()", 100); Напомним, что функция setTimeout устанавливает таймер. Задержка срабатывания таймера определяется вторым параметром и в нашем случае равна 100 миллисекундам. Когда таймер сработает, будет запущена на выполнение строка сценария JavaScript, которая была передана функции setTimeout в качестве первого параметра. Мы вызываем после окончания задержки функцию showNextImage, и таким образом обеспечиваем вызов этой функции в бесконечном цикле. Ожидание загрузки всех изображений Если вы собираетесь разместить в своем документе HTML анимационное изображение, состоящее из отдельных кадров, которые, в свою очередь, расположены в отдельных файлах, возникает одна проблема. Она связана с непредсказуемостью времени загрузки всех изображений анимационной последовательности через медленный и нестабильный канал Internet. Чтобы анимационное изображение было показано без искажений, необходимо вначале дождаться завершения процесса загрузки файлов отдельных кадров, и лишь затем запускать анимацию. В листинге 5.3 мы привели исходный текст документа HTML со сценарием, который работает подобным образом. Листинг 5.3. Файл chapter5/noise/noise2.html Animation with JavaScript В теле документа HTML расположен сценарий, вызывающий последовательно функции loadAllImages и showNextImage: loadAllImages(nNumberOfImages); showNextImage(); Функции loadAllImages в качестве параметра передается общее количество изображений в анимационной последовательности. В нашем случае оно равно 18. Задача функции loadAllImages заключается в заполнении массива объектов класса Image. Этот массив определен в области заголовка нашего документа HTML: var imgArray = new Array(18); Заполнение массива выполняется в цикле: var i; for(i=0; i, например: Перечислим допустимые параметры оператора : ПараметрОписаниеALIGNВыравнивание окна аплета относительно окружающего его текста. Возможны следующие значения: LEFT выравнивание влево относительно окружающего текста; CENTER центрирование; RIGHT выравнивание вправо относительно окружающего текста; TOP выравнивание по верхней границе; MIDDLE центрирование по вертикали; BOTTOM выравнивание по нижней границеALTС помощью этого параметра можно задать текст, который будет отображаться в окне аплета в том случае, если браузер не может работать с аплетами JavaCODEИмя двоичного файла, содержащего код аплета. По умолчанию путь к этому файлу указывается относительно каталога с файлом HTML, куда встроен аплет. Такое поведение может быть изменено параметром CODEBASE CODEBASEБазовый адрес URL аплета, то есть путь к каталогу, содержащему аплет HEIGHTНачальная ширина окна аплета в пикселахWIDTHНачальная высота окна аплета в пикселахHSPACEЗазор слева и справа от окна аплетаVSPACEЗазор сверху и снизу от окна аплетаNAMEИмя аплета. Оно может быть использовано другими аплетами, расположенными в одном и том же документе HTML, а также сценариями JavaScript TITLEСтрока заголовка Дополнительно между операторами и вы можете задать параметры аплета. Для этого используется оператор . Пользуясь операторами , расположенными в документе HTML сразу после оператора , можно передать аплету произвольное количество параметров, например, в виде текстовых строк: . . . Здесь через параметр NAME оператора передается имя параметра аплета, а через параметр VALUE - значение соответствующего параметра. Вызов методов аплета Java из сценария JavaScript Сценарий JavaScript может получить доступ к полям и методам аплетов, расположенных в документе HTML, адресуясь к аплетам как к элементам массива document.applets. Например, для доступа к первому аплету вы можете использовать строку document.applets[0]. Однако удобнее указывать имя аплета, заданное в параметре NAME оператора , например document.MyApplet. В качестве примера покажем, как можно вызывать из сценария JavaScript методы аплета Rectangles, описанного нами в упомянутом выше 32 томе “Библиотеки системного программиста”. Этот аплет рисует в своем окне прямоугольники случайного размера, закрашенные случайным цветом. Мы создали документ HTML, разместив в нем аплет Rectangles и форму с кнопками Start Animation и Stop Animation (рис. 6.1). Рис. 6.1. Аплет Rectangles управляется кнопками с помощью сценария JavaScript Сразу после загрузки документа в окне аплета запускается процесс анимации. Если нажать кнопку Stop Animation, рисование новых прямоугольников будет приостановлено. С помощью кнопки Start Animation можно возобновить процесс рисования. Заметим, что если поместить курсор мыши в область окна аплета, анимация будет остановлена, а когда курсор мыши покинет пределы окна аплета - снова запущена. Однако такое поведение определяется самим аплетом и не имеет отношения к нашему сценарию JavaScript. Исходный текст документа HTML, содержащий аплет и форму с кнопками, представлен в листинге 6.1. Листинг 6.1. Файл chapter6/Rectangles/Rectangles.html Rectangles

The source. Здесь параметр NAME оператора задает имя аплета как Rectangles. Когда пользователь нажимает на кнопку Start Animation, управление получает обработчик события onClick, определенный следующим образом: onClick="document.Rectangles.start()" Этот обработчик вызывает метод start, определенный в аплете Rectangles. Этот метод запускает анимацию в окне аплета, если она была остановлена. Аналогично, обработчик события onClick кнопки Stop Animation вызывает метод stop, также определенный в аплете Rectangles и предназначенный для остановки анимации: onClick="document.Rectangles.stop()" Исходный текст аплета Rectangles мы воспроизвели в листинге 6.2. Подробное описание этого аплета вы найдете в разделе “Приложение Rectangles” первой главы 32 тома “Библиотеки системного программиста”. Листинг 6.2. Файл chapter6/Rectangles/Rectangles.java // ========================================================= // Рисование прямоугольников в отдельной задаче // // (C) Фролов А.В, 1997, 1998 // // E-mail: // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ========================================================= import java.applet.*; import java.awt.*; import java.util.*; public class Rectangles extends Applet implements Runnable { // Ссылка на задачу рисования прямоугольников Thread m_Rectangles = null; // ------------------------------------------------------- // getAppletInfo // Метод, возвращающей строку информации об аплете // ------------------------------------------------------- public String getAppletInfo() { return "Name: Rectangles\r\n" + "Author: Alexandr Frolov\r\n" + "E-mail: " + "WWW: http://www.glasnet.ru/~frolov" + "Created with Microsoft Visual J++ Version 1.0"; } // ------------------------------------------------------- // paint // Метод paint, выполняющий рисование в окне аплета // ------------------------------------------------------- public void paint(Graphics g) { // Определяем текущие размеры окна аплета Dimension dimAppWndDimension = size(); // Выбираем в контекст отображения желтый цвет g.setColor(Color.yellow); // Закрашиваем внутреннюю область окна аплета g.fillRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); // Выбираем в контекст отображения черный цвет g.setColor(Color.black); // Рисуем рамку вокруг окна аплета g.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); } // ------------------------------------------------------- // start // Метод вызывается при первом отображении окна аплета // ------------------------------------------------------- public void start() { if (m_Rectangles == null) { m_Rectangles = new Thread(this); m_Rectangles.start(); } } // ------------------------------------------------------- // stop // Метод вызывается, когда окно аплета исчезает с экрана // ------------------------------------------------------- public void stop() { if (m_Rectangles != null) { m_Rectangles.stop(); m_Rectangles = null; } } // ------------------------------------------------------- // run // Метод, который работает в рамках отдельной задачи // Он рисует в окне аплета прямоугольники случайного // цвета, размера и расположения // ------------------------------------------------------- public void run() { // Получаем контекст отображения для окна аплета Graphics g = getGraphics(); // Определяем текущие размеры окна аплета Dimension dimAppWndDimension = size(); while (true) { int x, y, width, height; int rColor, gColor, bColor; // Выбираем случайным образом размеры // и расположение рисуемого прямоугольника x = (int)(dimAppWndDimension.width * Math.random()); y = (int)(dimAppWndDimension.height * Math.random()); width = (int)(dimAppWndDimension.width * Math.random()) / 2; height = (int)(dimAppWndDimension.height * Math.random()) / 2; // Выбираем случайный цвет для рисования // прямоугольника rColor = (int)(255 * Math.random()); gColor = (int)(255 * Math.random()); bColor = (int)(255 * Math.random()); // Устанавливаем выбранный цвет в контексте // отображения g.setColor(new Color(rColor, gColor, bColor)); // Рисуем прямоугольник g.fillRect(x, y, width, height); // Выполняем задержку на 50 миллисекунд try { Thread.sleep(50); } catch (InterruptedException e) { stop(); } } } // ------------------------------------------------------- // mouseEnter // Метод вызывается, когда курсор мыши оказывается над // окном аплета // ------------------------------------------------------- public boolean mouseEnter(Event evt, int x, int y) { if (m_Rectangles != null) { // Когда курсор мыши оказывается над поверхностью // окна аплета, временно приостанавливаем // задачу рисования прямоугольников m_Rectangles.suspend(); } return true; } // ------------------------------------------------------- // mouseExit // Метод вызывается, когда курсор мыши покидает // окно аплета // ------------------------------------------------------- public boolean mouseExit(Event evt, int x, int y) { if (m_Rectangles != null) { // Когда курсор мыши покидает окно аплета, // возобновляем работу задачи рисования // прямоугольников m_Rectangles.resume(); } return true; } } Доступ к полям аплета Java из сценария JavaScript В предыдущем примере сценарий JavaScript вызывал методы, определенные в аплете Java. В следующем примере сценарий будет обращаться к полю, определенному в главном классе аплета. Заметим, что сценарию JavaScript доступны только те поля и методы аплета, определенные как public. На рис. 6.2 показан внешний вид документа HTML, в котором расположен один аплет и форма с одним многострочным текстовым полем и одной кнопкой. Рис. 6.2. Сценарий JavaScript вызывает получает информацию от аплета В окне аплета, расположенном в верхней части документа, находится поле редактирования текста и кнопка с надписью “Получить строку”. Если набрать в поле редактирования любую текстовую строку и нажать эту кнопку, то введенная строка будет отображена в нижней части аплета после символа >. Такой аплет мы описали в 30 томе “Библиотеки системного программиста” в разделе “Приложение TxtField” пятой главы. Если нажать кнопку “Get applet info and text”, то сценарий JavaScript извлечет из аплета введенную текстовую строку (она хранится в поле с именем str), а также получит описание аплета, вызвав метод getAppletInfo, определенный в нашем аплете. Введенная строка и информация об аплете будет затем отображена сценарием в многострочном поле редактирования, как это показано на рис. 6.2. Таким образом, наш сценарий обращается к полю и методу, определенным в аплете. Исходный текст документа HTML вы найдете в листинге 6.3. Листинг 6.3. Файл chapter6/TxtField/TxtField.html Get text

The source. Для кнопки, расположенной в форме с именем GetForm, мы определили обработчик события onClick: onClick="getTextFromApplet();" Этот обработчик вызывает функцию getTextFromApplet, выполняющую взаимодействие с аплетом. Функция getTextFromApplet обращается к аплету как к самому первому элементу массива document.applets[0]: GetForm.Comment.value = document.applets[0].str + "\n" + "---------------------------\n" + document.applets[0].getAppletInfo(); Здесь мы записываем в свойство value многострочного поля GetForm.Comment значение переменной str, к которому добавлен разделитель из символов “-“ и строка описания аплета, полученная от метода getAppletInfo. Исходный текст аплета приведен в листинге 6.4. Листинг 6.4. Файл chapter6/TxtField/TxtField.java // ========================================================= // Однострочное текстовое поле класса TextField // // (C) Фролов А.В, 1997, 1998 // // E-mail: // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ========================================================= import java.applet.*; import java.awt.*; public class TxtField extends Applet { // Создаем ссылку на объекты типа TextField TextField txt; // Создаем ссылку на объекты типа Button Button btnGetText; // Строка для хранения введенных данных public String str; // ------------------------------------------------------- // getAppletInfo // Метод, возвращающей строку информации об аплете // ------------------------------------------------------- public String getAppletInfo() { return "Name: TxtField\r\n" + "Author: Alexandr Frolov\r\n" + "E-mail: \r\n" + "WWW: http://www.glasnet.ru/~frolov\r\n" + "Created with Microsoft Visual J++ Version 1.0"; } // ------------------------------------------------------- // init // Метод, получающий управление при инициализации аплета // ------------------------------------------------------- public void init() { // Создаем редактируемое однострочное текстовое поле txt = new TextField("Введите строку текста", 35); // Создаем кнопку, с помощью которой можно получить // содержимое текстового поля btnGetText = new Button("Получить строку"); // Добавляем текстовое поле в окно аплете add(txt); // Добавляем кнопку в окно аплете add(btnGetText); // Получаем и сохраняем текущий текст, // установленный в поле str = txt.getText(); // Устанавливаем цвет фона setBackground(Color.yellow); } // ------------------------------------------------------- // action // Метод вызывается, когда пользователь выполняет // действие над компонентами // ------------------------------------------------------- public boolean action(Event evt, Object obj) { // Ссылка на кнопку, от которой пришло сообщение Button btn; // Проверяем, что событие вызвано кнопкой, а не // другим компонентом if(evt.target instanceof Button) { // Получам ссылку на кнопку, вызвавшую событие btn = (Button)evt.target; // Проверяем ссылку на кнопку if(evt.target.equals(btnGetText)) { // Получаем и сохраняем текущий текст, // установленный в поле str = txt.getText(); // Перерисовываем окно аплета repaint(); } // Если событие возникло от неизвестной кнопки, // мы его не обрабатываем else { return false; } // Возвращаем признак того, что мы обработали событие return true; } // Если событие вызвано не кнопкой, // мы его не обрабатываем return false; } // ------------------------------------------------------- // paint // Метод paint, выполняющий рисование в окне аплета // ------------------------------------------------------- public void paint(Graphics g) { // Определяем текущие размеры окна аплета Dimension dimAppWndDimension = size(); // Выбираем в контекст отображения черный цвет g.setColor(Color.black); // Рисуем рамку вокруг окна аплета g.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); // Рисуем строку, полученную из текстового поля g.drawString("> " + str, 10, 100); } } Этот текст воспроизведен нами с небольшими изменениями из 30 тома “Библиотеки системного программиста”. Изменения заключаются в том, что мы добавили к определению поля str ключевое слово public: public String str; Это необходимо для того чтобы поле str было доступно из сценария JavaScript. Динамическая загрузка аплетов Java Еще одна полезная возможность, которая появляется у вас при использовании сценариев JavaScript, - это динамическая перезагрузка аплетов Java в документах HTML, созданных с использованием фреймов. Идея динамической загрузки аплетов заключается в том, что сценарий JavaScript динамически создает документ HTML, в котором находится оператор . Передавая аплету в этом документе различные значения параметров с помощью оператора , сценарий JavaScript может управлять его работой. На рис. 6.3 мы показали документ HTML, состоящий из двух фреймов. Рис. 6.3. Строка в окне аплета и ее шрифтовое оформление зависят от положения переключателей в левом фрейме В левом фрейме находится форма с переключателями и кнопкой, а правой - аплет Java. Если включить один из переключателей с названиями шрифтов, а затем нажать кнопку, то в окне аплета появится название шрифта. Это название будет оформлено с применением шрифта, выбранного вами в левом фрейме. Займемся описанием исходных текстов нашего документа HTML. В файле Index.html (листинг 6.6) находится описание фреймов. Листинг 6.6. Файл chapter6/FrameLoad/Index.html Динамическая загрузка аплетов Левый фрейм называется toc, а правый - mainpage. Исходный текст документа для фрейма toc мы привели в листинге 6.6. Листинг 6.6. Файл chapter6/FrameLoad/toc.html
Font:
Arial
Courier
TimesRoman
Helvetica

Для работы с переключателями типа radio мы использовали уже знакомую вам методику. Обработчик события onClick проверяет, находится ли переключатель во включенном состоянии. Если это так, обработчик вызывает функцию chkRadio, передавая ей ссылку на форму и значение свойства value, соответствующее включенному переключателю. Функция chkRadio сохраняет это значение в переменной szFont: function chkRadio(form,value) { szFont = value; } Каждый из переключателей имеет значение параметра VALUE, соответствующее названию одного из шрифтов, доступных аплетам Java. Поэтому переменная szFont хранит название шрифта, выбранного пользователем в левом фрейме. Обработчик события onClick для кнопки, расположенной в левом фрейме, выглядит следующим образом: onClick="parent['mainpage'].location='main.html';" Он устанавливает свойство location фрейма mainpage (то есть правого фрейма), присваивая ему адрес документа main.html. Исходный текст этого документа приведен в листинге 6.7. Листинг 6.7. Файл chapter6/FrameLoad/main.html Тело документа main.html содержит только сценарий JavaScript. Этот сценарий динамически создает строки оператора с параметрами Str1, Font1 и Type1. Параметр Str1 задает текст, отображаемый в окне аплета. Наш сценарий использует для этого параметра название шрифта, выбранного пользователем в левом фрейме: var szFont = parent.toc.szFont; Параметр Font1 задает шрифт для текста, отображаемого в окне аплета. Этот параметр также задается с использованием названия шрифта, выбранного в левом фрейме: document.write(""); И, наконец, третий параметр с именем Type1 задает тип шрифта - обычный, жирный или наклонный. В нашем случае всегда используется обычный шрифт. Исходный текст аплета Java, использованного в нашем примере, приведен в листинге 6.8. Это упрощенный вариант алпета, описанного нами в 30 томе “Библиотеки системного программиста” в разделе “Приложение TextOut третьей главы. Листинг 6.8. Файл chapter6/FrameLoad/TextOut.java // ========================================================= // Установка различных шрифтов. // Демонстрация способов передачи параметров в аплет // // (C) Фролов А.В, 1997, 1998 // // E-mail: // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ========================================================= import java.applet.*; import java.awt.*; public class TextOut extends Applet { // ------------------------------------------------------- // Поля класса. // Создаются автоматически для всех параметров аплета // ------------------------------------------------------- private String m_Str1 = "Hello 1"; private String m_Font1 = "Arial"; private String m_Type1 = "Bold"; // ------------------------------------------------------- // Имена параметров // ------------------------------------------------------- private final String PARAM_Str1 = "Str1"; private final String PARAM_Font1 = "Font1"; private final String PARAM_Type1 = "Type1"; // ------------------------------------------------------- // getAppletInfo // Метод, возвращающей строку информации об аплете // ------------------------------------------------------- public String getAppletInfo() { return "Name: TextOut\r\n" + "Author: Alexandr Frolov\r\n" + "E-mail: " + "WWW: http://www.glasnet.ru/~frolov" + "Created with Microsoft Visual J++ Version 1.0"; } // ------------------------------------------------------- // getParameterInfo // Метод, возвращающий описание параметров // ------------------------------------------------------- public String[][] getParameterInfo() { String[][] info = { { PARAM_Str1, "String", "Text string to write" }, { PARAM_Font1, "String", "Text font" }, { PARAM_Type1, "String", "Font type" }, }; return info; } // ------------------------------------------------------- // init // Вызывается во время инициализации аплета // ------------------------------------------------------- public void init() { // Рабочая переменная для получения параметров String param; // Получение параметров и сохранение // их значений в полях класса // Строки, которые будут выведены в окно аплета param = getParameter(PARAM_Str1); if (param != null) m_Str1 = param; // Шрифты для отображения строк param = getParameter(PARAM_Font1); if (param != null) m_Font1 = param; // Начертание шрифтов param = getParameter(PARAM_Type1); if (param != null) m_Type1 = param; } // ------------------------------------------------------- // paint // Метод paint, выполняющий рисование в окне аплета // ------------------------------------------------------- public void paint(Graphics g) { // Начальная координата для вывода по вертикали int yStart = 20; // Текущая координата для вывода строки int yCurrent = 20; // Определяем текущие размеры окна аплета Dimension dimAppWndDimension = size(); // Выбираем в контекст отображения желтый цвет g.setColor(Color.yellow); // Закрашиваем внутреннюю область окна аплета g.fillRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); // Выбираем в контекст отображения черный цвет g.setColor(Color.black); // Рисуем рамку вокруг окна аплета g.drawRect(0, 0, dimAppWndDimension.width - 1, dimAppWndDimension.height - 1); // Получаем стиль шрифта и выбираем шрифт // в соответствии с этим стилем if(m_Type1.equals("Bold")) g.setFont(new Font(m_Font1, Font.BOLD, 25)); else if(m_Type1.equals("Italic")) g.setFont(new Font(m_Font1, Font.ITALIC, 25)); else if(m_Type1.equals("Plain")) g.setFont(new Font(m_Font1, Font.PLAIN, 25)); // Отступ для первой строки yCurrent += yStart; // Рисуем первую строку g.drawString(m_Str1, 10, yCurrent); } } 7 ПРИМЕНЕНИЕ COOKIE Возможно, изучая настройки браузера вы сталкивались с таким понятием, как cookie. Что это такое? Скажем сразу, что с кулинарным искусством это связано мало, хотя некоторую аналогию все же можно провести. Говоря кратко, cookie представляет собой свойство документа HTML. Данные cookie физически хранятся локально на компьютере пользователя, загрузившего к себе этот документ, в виде специального системного файла. С помощью cookie пользователь может настроить, или “приготовить” по собственному вкусу документ HTML, если для него предусмотрена такая настройка. Проще всего представить себе cookie как набор строковых параметров, каждый из которых имеет имя и значение. Сценарий JavaScript может создавать cookie для документа HTML, определяя в нем произвольное количество параметров и задавая для них произвольные значения. После создания такой набор параметров становится принадлежностью данного конкретного документа HTML и может быть проанализирован, изменен или удален сценарием JavaScript. Как мы уже говорили, основное, для чего нужно cookie - это для того, чтобы дать пользователю возможность настроить под свои потребности интерфейс активных документов HTML. Эти настройки могут анализироваться или не анализироваться сервером Web, но в любом случае они хранятся у пользователя. Настройки, разумеется, пропадут, если пользователь, скажем, отформатирует свой жесткий диск. После этого параметры настраиваемого документа HTML придется задавать заново. Конечно, задачу индивидуальной настройки параметров страниц можно было бы решить и другими способами, например, при помощи расширений сервера Web, таких как программы CGI или приложения ISAPI. Для этого на сервере Web должна быть установлена база данных, хранящая настройки для всех зарегистрированных в ней пользователей. В этом случае расширение сервера Web может динамически создавать настраиваемые документы HTML, используя для определения внешнего вида страниц параметры, хранящиеся в базе данных. Наличие базы данных настройки пользователей усложняет сопровождение сервера Web, и потому неприемлемо во многих случаях. Например, если ваш сервер Web виртуальный и расположен на дисках сервера какого-либо провайдера Internet, создание базы данных может превратиться в трудно преодолимую проблему. Возлагая на пользовательский браузер задачу хранения настроек отдельных документов HTML, вы сильно упрощаете задачу организации настройки диалогового интерфейса. А для этого как раз нужны cookie и сценарии JavaScript. Еще одно практическое применение cookie - хранение товара, выбранное посетителем вашего сервера Web, выполняющего роль виртуального магазина. Покупатель может выбирать разный товар на разных страницах сервера, при этом полный заказ может вначале быть сформирован и сохранен в cookie, а затем по явному запросу пользователя отправлен на сервер. Среди других применений cookie можно отметить сетевые игры. Вы можете, например, хранить в cookie текущее состояние игры или другие параметры. Выполнение основных операций с cookie Рассмотрим основные операции с cookie, такие как создание cookie, получение и изменение значений параметров cookies, а также удаление cookie. Создание cookie Существуют два способа создание cookie, первый из которых используется расширениями сервера Web, а второй - сценариями JavaScript. Мы рассмотрим оба этих способа. Первый способ: создание cookie расширением сервера Web Для того чтобы создать cookie первым способом, расширение сервера Web обычно добавляет в заголовок HTTP динамически создаваемого документа HTML поле с именем Set-Cookie. В этом поле определяются имена и значения параметров cookie. Когда расширение сервера Web вызывается из документа HTML, имеющего cookie, параметры cookie предаются этому расширению через поле Cookie заголовка HTTP и могут быть проанализированы. Заголовок HTTP, предназначенный для создания cookie, выглядит следующим образом: Set-Cookie: Имя=Значение; expires=Дата_GMT; path=Адрес_URL; domain=Домен; secure Описание отдельных полей заголовка Set-Cookie приведено ниже: ПолеОписаниеИмяПроизвольное имя параметра, определенного в cookie. Здесь вы можете использовать любую строку, лишь бы в ней не было пробелов, запятых и двоеточий. В том случае, когда имя должно содержать перечисленные выше символы, используйте кодировку URLЗначениеТекстовая строка значений параметров. В этой строке не должно быть пробелов, запятых и двоеточий, поэтому вы должны использовать для нее кодировку URLexpiresДата автоматического удаления cookie по Гринвичу. Если эта дата не указана, а параметр expires отсутствует, cookie будет удалено сразу после того, как браузер закончит сеанс связи с сервером Web domainДоменная часть адреса URL, для которой действует данный cookie. Если этот параметр не указан, то по умолчанию используется доменный адрес URL документа HTML, где был установлен cookiepathЧасть адреса URL, задающая путь к документу HTML, для которой действует данный cookie. Если этот параметр не указан, то по умолчанию используется адрес URL документа HTML, где был установлен cookie secureЕсли указано это поле, данные cookie необходимо предавать только с использованием защищенного протокола SSL. Такой протокол используется серверами HTTPS Все поля, кроме первых двух (Имя и Значение), необязательны. Дата должна быть записана в формате День_недели, ДД-Мес-ГГ ЧЧ:ММ:СС GMT, где: * День_недели - английское трехбуквенное сокращение названия дня недели (например, Mon); * ДД - номер дня недели; * Мес - английское трехбуквенное сокращение названия месяца (например, Jun); * ГГ - две последние цифры года; * ЧЧ - часы; * ММ - минуты; * СС - секунды Например, дата может быть указана так: Mon, 07-Jun-93 14:45:00 GMT Сделаем небольшое замечание относительно полей domain и path, определяющих условие, при котором выполняется установка cookie. Когда браузер загружает документ HTML с сервера Web и среди заголовков HTTP этого документа присутствует заголовок Set-Cookie, он проверяет возможность установки cookie. В процессе проверки анализируется адрес URL, откуда был загружен этот документ, а также содержимое полей domain и path. Если эти поля не указаны, то по умолчанию считаются, что они соответствуют адресу URL, по которому находится загруженный документ HTML. В этом случае выполняется установка cookie. В том случае, когда указано поле domain, установка cookie выполняется только тогда, когда документ был загружен с сервера Web, принадлежащего данному домену. С помощью параметра path можно установить ограничение на адреса URL в рамках домена, для которых выполняется установка cookie. При этом значение “/” соответствует всем адресам данного домена. Одновременно сервер Web может создать несколько параметров cookie, включив в заголовок документа HTML несколько заголовков Set-Cookie. Второй способ: создание cookie в сценарии JavaScript Второй способ предполагает использование свойства document.cookie. Это свойство мы упомянули, рассказывая о свойствах и методах объекта document, создаваемого для документа HTML, загруженного в окно браузера. В общем виде сценарий JavaScript может создать cookie следующим образом: document.cookie = “Имя=Значение; Здесь мы просто записываем в свойство cookie объекта document текстовую строку, определяющую cookie. Для пересчета текущей даты в формат GMT в сценариях JavaScript можно использовать встроенные функции, о чем мы скоро расскажем. В качестве примера приведем исходный текст функции addCookie, которую мы будем использовать в своих сценариях для создания cookie: function addCookie(szName,szValue,dtDaysExpires) { var dtExpires = new Date(); var dtExpiryDate = ""; dtExpires.setTime(dtExpires.getTime() + dtDaysExpires * 24 * 60 * 60 * 1000); dtExpiryDate = dtExpires.toGMTString(); document.cookie = szName + "=" + szValue + "; expires=" + dtExpiryDate; } Функция addCookie получает три параметра. Через параметр szName передается имя параметра, хранящегося в cookie. Параметр szValue определяет значение этого параметра cookie. Что же касается последнего параметра с именем dtDaysExpires, то он задает интервал времени по отношению к моменту создания cookie, когда этот cookie необходимо удалить. Самое сложное в функции addCookie - это определение даты удаления cookie и преобразование этой даты в формат GMT. Данная задача решается следующим образом. Прежде всего функция addCookie создает объект класса Date с помощью ключевого слова new: var dtExpires = new Date(); Записанная таким образом в переменную dtExpires дата соответствует моменту вызова функции addCookie. Далее с помощью метода getTime функция addCookie определяет текущую дату в миллисекундах и прибавляет к результату значение параметра dtDaysExpires, полученное функцией, умноженное на константу (24 * 60 * 60 * 1000): dtExpires.getTime() + dtDaysExpires * 24 * 60 * 60 * 1000 Константа представляет собой количество часов в сутках, умноженное на количество минут в часе, затем на количество секунд в минуте, и, наконец, на количество миллисекунд в секунде. Результат вычислений записывается при помощи метода setTime в переменную даты dtExpires. Теперь здесь хранится дата автоматического уничтожения cookie браузером. Осталось лишь преобразовать эту дату в формат GMT. Такое преобразование нетрудно сделать с помощью специально предназначенного для этого метода toGMTString, возвращающего текстовую строку в нужном нам формате: dtExpiryDate = dtExpires.toGMTString(); Теперь нам остается только сформировать текстовую строку определения cookie и записать ее в свойство document.cookie: document.cookie = szName + "=" + szValue + "; expires=" + dtExpiryDate; На этом создание cookie завершено. Теперь, когда в вашем распоряжении есть функция addCookie, создание cookie представляет собой очень простую задачу. Например, в следующей строке мы создаем cookie с именем Count, значением 0, причем через 10 дней браузер автоматически удалит этот cookie: addCookie("Count","0",10); При необходимости использования других параметров cookie, таких как path или domain, вы можете немного дополнить текст функции addCookie. С этой задачей вы легко справитесь самостоятельно. Получение значения cookie Итак, вы научились создавать cookie в сценариях JavaScript. Теперь решим другую задачу - определение значения параметров cookie. Эта задача сводится к простому сканированию текстовой строки, полученной следующим образом: var szCookieString = document.cookie; В этой строке вам нужно найти подстроку “Имя=Значение;”, а затем извлечь полученное значение. Для облегчения этой работы вы можете воспользоваться функцией findCookie. Исходный текст этой функции приведен ниже: function findCookie(szName) { var i = 0; var nStartPosition = 0; var nEndPosition = 0; var szCookieString = document.cookie; while(i <= szCookieString.length) { nStartPosition = i; nEndPosition = nStartPosition + szName.length; if(szCookieString.substring( nStartPosition,nEndPosition) == szName) { nStartPosition = nEndPosition + 1; nEndPosition = document.cookie.indexOf(";",nStartPosition); if(nEndPosition < nStartPosition) nEndPosition = document.cookie.length; return document.cookie.substring( nStartPosition,nEndPosition); break; } i++; } return ""; } После извлечения строки из свойства document.cookie и записи этой строки в переменную szCookieString функция findCookie организует цикл по всем символам этой строки. Условием завершения цикла является просмотр всех szCookieString. length символов. Сравнивая имя параметра с подстрокой, извлеченной из строки szCookieString при помощи метода substring, функция findCookie пытается найти нужный параметр. Если такая попытка оказывается успешной, функция findCookie пропускает символ присваивания, извлекая значение параметра, ограниченное символом точка с запятой. Это значение возвращается функцией findCookie. Если же поиск оказывается неудачным, функция findCookie возвращает пустую строку. Как пользоваться функцией findCookie? Во-первых, с помощью этой функции вы можете проверить, установлен ли для данного документа cookie с заданным именем: if(findCookie("Visit") == "") { // cookie с именем Visit установлен . . . } else { // cookie с именем Visit не установлен . . . } Для того чтобы записать в текстовую переменную значение параметра cookie с заданным именем, вы должны сделать следующее: var szVisitValue = findCookie("Visit"); Как видите, пользоваться функцией findCookie достаточно просто. Изменение значения параметра cookie Для изменения значения параметра cookie с заданным именем вы можете просто вызвать функцию addCookie еще раз: addCookie("Count","0",10); // Значение параметра Count равно 0 . . . addCookie("Count","5",10); // Значение параметра Count равно 5 Здесь мы вначале установили для параметра Count значение 0, а затем изменили это значение на 5. Удаление cookie Самый простой способ удалить cookie - установить для него такое время автоматического удаления, которое уже прошло. Для этого нужно получить текущую дату, уменьшить ее, например, на одну микросекунду, а затем изменить значение document.cookie. Все это делает функция removeCookie: function removeCookie(szName) { var dtExpires = new Date(); dtExpires.setTime(dtExpires.getTime() - 1); var szValue = findCookie(szName); document.cookie = szName + "=" + szValue + "; expires=" + dtExpires.toGMTString(); } В последней строке этой функции мы указали такое значение параметра expires, которое вызывает немедленное удаление cookies браузером. Ограничения на использование cookie На использование cookie накладываются определенные ограничения, которые мы перечислили ниже: * всего может быть создано не более чем 300 cookie; * каждый cookie не может превышать по своему размеру 4 Кбайт; * для каждого домена может быть создано не более 20 cookie Если указанные значения будут превышены, браузер может удалить самые старые cookie или обрезать значения параметров cookie. Несколько примеров использования cookie В этом разделе на примере конкретных сценариев JavaScript мы покажем, как можно использовать cookies для решения различных практических задач. Фиксация повторных посещений страницы В нашем первом примере документ HTML содержит форму с двумя кнопками (рис. 7. 1). Рис. 7.1. Кнопки для перехода к динамически создаваемому документу HTML и для удаления cookie Если нажать на кнопку Go to page, сценарий JavaScript создаст новый документ HTML. Внешний вид этого документа зависит от того, сколько раз пользователь нажимал на эту кнопку. Кнопка Remove All Cookies предназначена для удаления cookie, созданного в нашем документе HTML. Когда вы нажимаете на кнопку Go to page в первый раз, cookie еще не создано. При этом создается документ HTML, внешний вид которого показан на рис. 7.2. Рис. 7.2. Внешний вид созданного динамически документа HTML при первом посещении Во второй и последующий разы внешний вид документа изменяется (рис. 7.3). Рис. 7.3. Внешний вид созданного динамически документа HTML при третьем посещении Теперь здесь виден новый заголовок, а также содержимое параметров cookie с именами Visit и Count. При каждом новом посещении значение параметра Count будет увеличиваться на единицу. Если же в документе, показанном на рис. 7.1, нажать кнопку Remove All Cookies, подсчет посещений начнется заново. Исходный текст документа HTML представлен в листинге 7.1. Листинг 7.1. Файл chapter7/Again/Again.html Cookies demo

Visit our page!

Функции addCookie, findCookie и removeCookie, определенные в этом документе, вам уже знакомы. Они предназначены, соответственно, для создания cookie, извлечения значения заданного параметра cookie и удаления cookie. Функция btnClick вызывается, когда пользователь нажимает в форме кнопку с надписью Go to page. Прежде всего эта функция ищет параметр cookie с именем Visit. Если такой параметр не найден, считается, что страница посещается в первый раз. В этом случае функция btnClick создает параметры cookie с именами Visit и Count, а затем формирует текст документа HTML с приглашением: addCookie("Visit","Alexandr_Frolov",10); addCookie("Count","0",10); document.write("

You are welcome!

"); В том случае, когда пользователь посещает страницу повторно, параметр cookie с именем Visit уже существует. В этом случае функция btnClick пытается найти параметр с именем Count и получить его значение: var szCnt = findCookie("Count"); Это значение затем увеличивается на единицу и записывается обратно в параметр cookie с именем Count: i = szCnt; i++; szCnt = i.toString(); addCookie("Count",szCnt,10); Завершая свою работу, функция btnClick записывает приглашение для повторно посетивших страницу пользователей и отображает содержимое свойства document. cookie: document.write("

You are welcome AGAIN!

"); document.write(document.cookie); Обработчик события onClick кнопки с надписью Remove All Cookies вызывает функцию removeCookie для параметров cookie с именами Count и Visit, удаляя их: Записная книжка Cookies Notepad В следующем примере мы применили cookie для хранения произвольного текста, набранного пользователем в многострочном окне редактирования (рис. 7.4). Рис. 7.4. Документ с записной книжкой Cookies Notepad При первой загрузке документа HTML с записной книжкой окно редактирования остается пустым. Вы можете набрать здесь любой текст и записать его в cookie, нажав кнопку Store text. Если теперь закрыть документ HTML и открыть его вновь, набранный вами ранее текст появится в окне редактирования. Для того чтобы удалить текст и cookie, достаточно нажать кнопку Clear text. Исходный текст документа HTML с записной книжкой Cookies Notepad представлен в листинге 7.2. Листинг 7.2. Файл chapter7/Notebook/Notebook.html Cookies demo

Cookies Notepad

Функция addCookie, использованная нами в этом документе, имеет одну особенность: перед записью текстовой строки в параметр cookie она выполняет ее кодировку в формате URL, вызывая для этого функцию escape: document.cookie = szName + "=" + escape(szValue) + "; expires=" + dtExpiryDate; Это необходимо по той причине, что введенный в окне редактирования текст может содержать пробелы и любые другие символы. Аналогичные изменения мы внесли и в функцию findCookie. Эта функция возвращает значение, перекодированное в обычный текст функцией unescape, выполняющей действия, обратные по отношению к функции escape: szTemp = document.cookie.substring( nStartPosition,nEndPosition); return unescape(szTemp); Когда пользователь нажимает кнопку Store text, вызывается функция btnClick: function btnClick() { addCookie("MyText",TestForm.Comment.value,10); } Эта функция просто записывает в параметр cookie с именем MyText текстовую строку, извлеченную из многострочного поля редактирования TestForm.Comment. value. При удалении текста кнопкой Clear text вызывается функция removeCookie, удаляющая параметр cookie с именем 'MyText, а также записывается пустая строка в окно многострочного редактирования: В самом конце тела документа HTML находится небольшой фрагмент сценария JavaScript, запускающийся сразу после загрузки этого документа: var szMyText=""; szMyText = findCookie("MyText"); if(szMyText != "") { TestForm.Comment.value = szMyText; } Этот фрагмент пытается получить значение параметра cookie с именем MyText. Если это ему удается и функция findCookie возвращает непустую строку, полученная строка записывается в окно многострочного поля редактирования TestForm.Comment.value. В результате сразу после загрузки документа это окно оказывается заполненным текстом, сохраненным в cookie. Вы можете посмотреть системный файл, хранящий данные cookie. Для этого откройте каталог Temporary Internet Files, расположенный в системном каталоге Microsoft Windows 95 или Microsoft Windows NT. Там должен быть файл и именем Notebook\. Вы можете скопировать этот файл, например, на поверхность рабочего стола и открыть для просмотра любым текстовым редактором. Вы увидите примерно это: MyText This%20is%20sample%20text. %0D%0A%u042D%u0442%u043E%20%u0442%u0435%u043A%u0441%u0442%2C%20%u043A%u043E%u0442%u043E%u0440%u044B%u0439%20%u044F%20%u043D%u0430%u0431%u0440%u0430%u043B%20%u0434%u043B%u044F%20%u043F%u0440%u0438%u043C%u0435%u0440%u0430. %0D%0A%0D%0A%u0410%u043B%u0435%u043A%u0441%u0430%u043D%u0434%u0440%20%u0424%u0440%u043E%u043B%u043E%u0432. ~~local~~/E:\JavaScript\Source\chapter7\Notebook\ 0 642302464 29173566 2120102016 29171554 * В самом начале файла видно имя MyText параметра cookie. На следующих строках до строки ~~local~~ расположено значение параметра MyText, соответствующее тексту, показанному на рис. 7.4. Вслед за строкой ~~local~~ идет локальный адрес URL документа и другие параметры cookies, такие как дата, по достижению которой браузер удалит cookie. Если удалить файл Notebook\ и затем открыть документ HTML, многострочное окно редактирования будет пустым. Удалив этот файл, мы удалим и расположенный в нем cookie. Настройка параметров документа HTML Третий пример демонстрирует, как можно использовать cookie для настройки пользователем параметров документа HTML. На рис. 7.5 показан документ HTML с двумя кнопками и переключателем, имеющим зависимую фиксацию. Рис. 7.5. Главный документ HTML, при помощи которого можно выполнить настройку Если нажать верхнюю кнопку, то в окне браузера появится документ HTML, созданный динамически сценарием JavaScript. В первый раз этот документ будет таким, как показано на рис. 7.6. Рис. 7.6. Внешний вид документа при первом посещении При помощи переключателей вы можете выбрать один из четырех цветов фона документа. Выбранное значение запоминается в cookie. Для того чтобы вернуться к цвету, принятому по умолчанию, в документе HTML, показанному на рис. 7.5, нужно нажать нижнюю кнопку. При последующих посещениях внешний вид документа изменится (рис. 7.7). Рис. 7.7. Внешний вид документа при третьем посещении Его фон будет иметь такой цвет, какой был выбран при помощи переключателей. Исходный текст документа HTML приведен в листинге 7.3. Листинг 7.3. Файл chapter7/CustomPage/CustomPage.html Customize your page

Посетите вашу персональную страницу


Настройка параметров персональной страницы

Цвет фона:

Белый
Желтый
Зеленый
Малиновый

Помимо функций addCookie, findCookie и removeCookie, предназначенных для работы с cookie, в сценарии определена переменная szColor, предназначенная для хранения выбранного пользователем цвета фона, а также функции btnGo, chkRadio и setDefault. Функция btnGo прежде всего проверяет наличие параметра cookie с именем Count. Если такого параметра нет, сценарий считает, что пользователь просматривает этот документ в первый раз. В этом случае функция btnGo добавляет два параметра cookie с именами Count и bgColor: addCookie("Count","0",10); addCookie("bgColor",szColor,10); Первый из них предназначен для хранения счетчика посещений, а второй - для хранения цвета фона. Далее функция btnGo формирует документ HTML с приглашением для пользователя, просматривающего документ в первый раз, и завершает свою работу. В том случае, когда сразу после вызова функция btnGo нашла параметр cookie с именем Count и получила его значение, это значение увеличивается на единицу и записывается обратно. Кроме того, оно отображается в тексте документа: document.write("

Рады видеть вас снова!

"); document.write("Вы посетили эту страницу в " + szCnt.bold()+" раз."); Затем функция btnGo устанавливает цвет фона сформированного документа HTML в соответствии со значением, извлеченным из параметра cookie с именем bgColor: document.bgColor=findCookie("bgColor"); Функция chkRadio вызывается, когда пользователь включает один из переключателей выбора цвета: function chkRadio(form,value) { szColor = value; addCookie("bgColor",szColor,10); } Эта функция записывает значение выбранного цвета в переменную szColor, а также в параметр cookie с именем bgColor. И, наконец, функция setDefault удаляет параметр cookie с именем Count и устанавливает в переменной szColor белый цвет фона, принятый по умолчанию: function setDefault(form) { removeCookie('Count'); szColor="White"; } Эта функция вызывается, когда пользователь нажимает кнопку с надписью "Параметры по умолчанию": Обратите внимание, что данная кнопка имеет тип reset. Когда пользователь нажимает на нее, в форме включается переключатель, задающий белый цвет фона. Это происходит потому, что указанный переключатель определен с параметром CHECKED, а кнопка типа reset устанавливает все органы управления формы в исходное состояние. Получение cookie расширением сервера Web В этом разделе мы приведем пример документа HTML, создающего cookie, а также исходные тексты расширения сервера ISAPI, отображающее на динамически создаваемой странице заголовки HTTP этого документа. Когда браузер создает cookie, расширение сервера получает заголовок HTTP_COOKIE и отображает его. Наш документ аналогичен описанному ранее в разделе “Записная книжка Cookies Notepad” (рис. 7.8). Рис. 7.8. Документ HTML, работающий с cookie и расширением сервера ISAPI Дополнительно мы разместили в документе кнопку Send. С помощью этой кнопки содержимое окна редактирования и заголовок HTTP_COOKIES передается расширению ISAPI сервера Web. Расширение ISAPI отображает содержимое cookie, как это показано на рис. 7.9. Рис. 7.9. Результат работы расширения ISAPI Исходный текст документа HTML вы найдете в листинге 7.4. Листинг 7.4. Файл chapter7/NotebookISAPI/NotebookISAPI.html Cookies demo

Cookies Notepad

В нем, по сравнению с документом из раздела “Записная книжка Cookies Notepad”, мы добавили параметр ACTION в оператор
, а также кнопку типа submit с надписью Send. С помощью этой кнопки данные из формы отправляются расширению ISAPI: . . . . . . . . . Исходный текст расширения ISAPI представлен в листинге 7.5. Он сделан на базе примера, взятого из 29 тома нашей “Библиотеки системного программиста” (раздел “Приложение ISHELLO” восьмой главы). Листинг 7.5. Файл chapter7/NotebookISAPI/ishello.c // =============================================== // Расширение ISAPI ishello.c // Пример расширения ISAPI, отображающего // содержимое cookie // // (C) Фролов А.В., 1997, 1998 // E-mail: // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // =============================================== #include #include // ========================================================= // Функция GetExtensionVersion // Запись версии интерфейса ISAPI и // строки описания расширения // ========================================================= BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) { // Записываем версию интерфейса ISAPI pVer->dwExtensionVersion = MAKELONG(HSE_VERSION_MINOR,HSE_VERSION_MAJOR ); // Записываем строку описания расширения lstrcpyn(pVer->lpszExtensionDesc, "Cookie show ISAPI DLL", HSE_MAX_EXT_DLL_NAME_LEN); return TRUE; } // ========================================================= // Функция HttpExtensionProc // ========================================================= DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK *lpECB) { CHAR szBuff[4096]; CHAR szTempBuf[4096]; DWORD dwSize; // Нулевой код состояния - признак успешного выполнения lpECB->dwHttpStatusCode = 0; // Записываем в буфер заголовок HTTP и начальный // фрагмент формируемого динамически документа HTML wsprintf(szBuff, "Content-Type: text/html\r\n\r\n" "Simple ISAPI Extension\n" "

Hello from ISAPI Extension!

\n"); // Добавляем разделительную линию strcat(szBuff, "
"); // Добавляем версию интерфейса ISAPI wsprintf(szTempBuf, "

Extension Version: %d.%d", HIWORD(lpECB->dwVersion), LOWORD(lpECB->dwVersion)); strcat(szBuff, szTempBuf); // Название метода передачи данных wsprintf(szTempBuf, "
Method: %s", lpECB->lpszMethod); strcat(szBuff, szTempBuf); // Строка параметров запуска расширения ISAPI wsprintf(szTempBuf, "
QueryString: %s", lpECB->lpszQueryString); strcat(szBuff, szTempBuf); // Физический путь к программному файлу расширения ISAPI wsprintf(szTempBuf, "
PathTranslated: %s", lpECB->lpszPathTranslated); strcat(szBuff, szTempBuf); // Полный размер данных, которые нужно получить wsprintf(szTempBuf, "
TotalBytes: %d", lpECB->cbTotalBytes); strcat(szBuff, szTempBuf); // Тип данных wsprintf(szTempBuf, "
ContentType: %s", lpECB->lpszContentType); strcat(szBuff, szTempBuf); // Отображаем содержимое COOKIE strcat(szBuff, "


Cookie:
"); dwSize = 4096; lpECB->GetServerVariable(lpECB->ConnID, (LPSTR)"HTTP_COOKIE", (LPVOID)szTempBuf, &dwSize); strcat(szBuff, szTempBuf); // Конечный фрагмент документа HTML strcat(szBuff, ""); // Посылаем содержимое буфера удаленному пользователю if(!lpECB->ServerSupportFunction(lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, NULL, NULL, (LPDWORD)szBuff)) { // Если послать данные не удалось, // завершаем работу нашего расширения ISAPI // с кодом ошибки return HSE_STATUS_ERROR; } // Записываем код успешного завершения lpECB->dwHttpStatusCode = 200; // Возвращаем принак успешного завершения return HSE_STATUS_SUCCESS; } Файл определения модуля для библиотеки DLL расширения приведен в листинге 7. 6. Листинг 7.6. Файл chapter7/NotebookISAPI/ishello.def LIBRARY ishello DESCRIPTION 'Simple ISAPI DLL' EXPORTS GetExtensionVersion HttpExtensionProc Для извлечения значения cookie, предаваемого расширению через заголовки HTTP, мы использовали функцию GetServerVariable, указав ей в качестве второго параметра имя интересующей нас переменной HTTP_COOKIE: lpECB->GetServerVariable(lpECB->ConnID, (LPSTR)"HTTP_COOKIE", (LPVOID)szTempBuf, &dwSize); Полученное таким образом значение дописывается в буфер динамически создаваемого документа HTML. Этот буфер впоследствии будет отправлен клиенту при помощи функции ServerSupportFunction. Счетчик посещений на базе cookie и программы CGI Последний пример, приведенный в этой главе, показывает основные приемы работы с cookie в программах CGI и сценарии JavaScript, вставляемом в тело динамически формируемого документа HTML. Внешний вид исходного документа HTML, вызывающего программы CGI, показан на рис. 7.10. Рис. 7.10. Документ HTML, вызывающий программу CGI Как видно из этого рисунка, в документе определена форма с двумя кнопками. Обе эти кнопки предназначены для вызова одной и той же программы CGI, но с разными параметрами. Если нажать на кнопку с надписью Go to page, программа GCI создаст документ HTML, предварительно проанализировав заголовок пришедшего к ней запроса на предмет наличия в нем информации о cookie. Кнопка Remove All Cookies предназначена для вызова программы CGI с целью удаления cookie. В том случае, когда этой информации нет, программа CGI динамически сформирует документ HTML, добавив к его заголовку HTTP заголовок Set-Cookie (рис. 7.11). Рис. 7.11. Документ HTML, создаваемый программой CGI при первом посещении При последующих посещениях cookie уже определен, и наша программа CGI получает его значение, интерпретируя это значение как счетчик посещений. Затем она увеличивает значение счетчика на единицу, и записывает заголовок Set-Cookie в заголовок HTTP создаваемого документа HTML с новым значением cookie. Значение счетчика посещений отображается в теле документа (рис. 7.12). Рис. 7.12. Документ HTML, создаваемый программой CGI при третьем посещении Далее программа CGI вставляет в текст этого документа сценарий JavaScript, расположенный в отдельном файле. Данный сценарий определяет значение cookie своими средствами и отображает его вместе со значением счетчика посещений в многострочном окне редактирования. Исходный документ HTML представлен в листинге 7.7. Листинг 7.7. Файл chapter7/AgainCGI/AgainCGI.html Cookies demo

Visit our page!

В этом документе определены две формы. Первая форма предназначена для вызова программы CGI с параметром go, а вторая - с параметром clear. Исходный текст программы CGI, использованной в нашем примере, вы найдете в листинге 7.8. Листинг 7.8. Файл chapter7/AgainCGI/Again.c // =============================================== // Расширение CGI, предназначенное для // работы с cookie // // (C) Фролов А.В., 1998 // E-mail: // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // =============================================== #include #include #include #include // Прототипы функций, определенных в нашей программе char *findCookie(char * szName); void insertHTML(char * pszFileName, char * pszBuf); void main(int argc, char *argv[]) { char * pszQueryString; char * pszCookie; char * pszMyCookie; int nCount; char szBuf[4096]; char szBuf1[20]; // Заголовок для добавления cookie char szCookieHeader[] = "Set-Cookie: AgainCount=0;\r\nContent-type: text/html\r\n\r\n"; // Заголовок для удаления cookie char szCookieRemoveHeader[] = "Set-Cookie: AgainCount=0;expires=Mon 03-May-1993 12:00:00 GMT;" "\r\nContent-type: text/html;\r\n\r\n"; // Получаем параметр запуска CGI pszQueryString = getenv("QUERY_STRING"); // Получаем строку Cookie из заголовка HTTP pszCookie = getenv("HTTP_COOKIE"); // Посещение страницы if(!strcmp(pszQueryString, "go")) { // Если cookie не обнаружен, создаем его if(pszCookie == NULL) { // Выводим заголовок для создания cookie printf("Content-type: text/html\r\n"); printf(szCookieHeader); // Выводим приглашение для первого посещения printf("Cookie demo"); printf("

Welcome to our page!

"); } else { // Получаем значение параметра cookie // с именем AgainCount pszMyCookie = findCookie("AgainCount"); if(pszMyCookie != NULL) { // Преобразуем это значение в число и увеличиваем // на единицу при каждом посещении nCount = atoi(pszMyCookie); nCount++; sprintf(szBuf1, "%d", nCount); // Выводим заголовок для обновления cookie printf("Content-type: text/html\r\n"); strcpy(szBuf, "Set-Cookie: AgainCount="); strcat(szBuf, szBuf1); strcat(szBuf, ";\r\nContent-type: text/html\r\n\r\n"); printf(szBuf); // Выводим приглашение для повторных посещений printf("

Welcome to our page AGAIN!

"); // Выводим счетчик посещений printf("

Access count: %s",szBuf1); // Вставляем документ HTML с текстом сценария // JavaScript, который тоже работает с cookie insertHTML("script.ht", szBuf); printf(szBuf); } } } // Удаление cookie else if(!strcmp(pszQueryString, "clear")) { // Выводим заголовок для удаления cookie printf("Content-type: text/html\r\n"); printf(szCookieRemoveHeader); // Выводим сообщение об успешном удалении cookie printf("Cookie demo"); printf("

Cookie Removed"); } printf(""); } // ----------------------------------------------- // findCookie // Получение значение параметра cookie по его // имени // ----------------------------------------------- char *findCookie(char * szName) { char * pszCookie; char * pszBegin; char * pszEnd; char szBuf[4096]; // Получаем текстовую строку cookie pszCookie = getenv("HTTP_COOKIE"); if(pszCookie != NULL) { // Копируем ее в рабочий буфер strcpy(szBuf, pszCookie); // Ищем в строке имя параметра pszBegin = strstr(szBuf, szName); if(pszBegin == NULL) return NULL; else { // Пропускаем символ равенства pszBegin += strlen(szName) + 1; // Ищем символ ; и заменяем его на // двоичный нуль pszEnd = strstr(pszBegin, ";"); if(pszEnd != NULL) *pszEnd = 0; // Возвращаем значение параметра return pszBegin; } } } // ----------------------------------------------- // insertHTML // Вставка в буфер содержимого текстового файла // ----------------------------------------------- void insertHTML(char * pszFileName, char * pszBuf) { HFILE hSrcFile; DWORD dwFileSize; // Открываем файл hSrcFile = _lopen(pszFileName, OF_READ); // Определяем его длину dwFileSize = _llseek(hSrcFile, 0, 2); // Устанавливаем указатель на начало файла _llseek(hSrcFile, 0, 0); // Читаем файл в буфер _hread(hSrcFile, pszBuf, dwFileSize); // Закрываем буфер двоичным нулем pszBuf[dwFileSize] = '\0'; // Закрываем файл _lclose(hSrcFile); } В переменной szCookieHeader мы подготовили заголовок Set-Cookie, предназначенный для создания параметра cookie с именем AgainCount: char szCookieHeader[] = "Set-Cookie: AgainCount=0;\r\nContent-type: text/html\r\n\r\n"; Начальное значение этого параметра равно нулю. Заголовок, хранящийся в переменной szCookieRemoveHeader, предназначен для удаления cookie: char szCookieRemoveHeader[] = "Set-Cookie: AgainCount=0;expires=Mon 03-May-1993 12:00:00 GMT;\r\nContent-type: text/html;\r\n\r\n"; Эффект удаления достигается благодаря тому, что в параметре expires мы указали уже наступившую дату. Сразу после запуска программа CGI получает значение переменных среды QUERY_STRING и HTTP_COOKIE: pszQueryString = getenv("QUERY_STRING"); pszCookie = getenv("HTTP_COOKIE"); В первой из них хранится параметр запуска программы CGI, а во второй - строка cookie (если она определена). Далее наша программа анализирует параметр запуска. Если программа вызвана с параметром go, она проверяет переменную pszCookie. В эту переменную функция getenv записывает строку cookie или значение NULL, если cookie не определено. При первом посещении cookie еще нет, поэтому наша программа добавляет к заголовку HTTP формируемого документа заголовок Set-Cookie: printf("Content-type: text/html\r\n"); printf(szCookieHeader); Затем программа выводит приглашение для первого посещения и завершает свою работу. В том случае, если в принятом запросе уже имеется информация о cookie, программа CGI извлекает значение параметра cookie с именем AgainCount, вызывая для этого функцию findCookie: pszMyCookie = findCookie("AgainCount"); Эта функция определена в нашей программе и будет описана чуть позже. Полученная строка преобразуется в численное значение при помощи функции atoi, после чего это значение увеличивается на единицу, преобразуется обратно в тестовую строку и записывается в буфер szBuf1: nCount = atoi(pszMyCookie); nCount++; sprintf(szBuf1, "%d", nCount); На следующем этапе программа формирует заголовок Set-Cookie с новым значением параметра AgainCount: printf("Content-type: text/html\r\n"); strcpy(szBuf, "Set-Cookie: AgainCount="); strcat(szBuf, szBuf1); strcat(szBuf, ";\r\nContent-type: text/html\r\n\r\n"); printf(szBuf); Этот заголовок вместе с заголовком Content-type записывается в создаваемый документ HTML. Далее после вывода приглашения для повторного посещения страницы программа CGI записывает в документ новое значение счетчика посещений: printf("

Access count: %s",szBuf1); И, наконец, перед завершением своей работы программа вставляет в текст документа HTML файл со сценарием JavaScript, вызывая для этого функцию insertHTML: insertHTML("script.ht", szBuf); Эта функция определена в нашей программе, как и функция findCookie. Когда программа CGI вызывается для удаления cookie с параметром clear, она выводит специально предназначенный для этого заголовок с просроченной датой: printf("Content-type: text/html\r\n"); printf(szCookieRemoveHeader); Теперь мы кратко расскажем о работе функции findCookie. Получив текстовую строку cookie при помощи функции getenv, эта функция копирует строку в рабочий буфер, который можно редактировать (напомним, что содержимое буфера, полученного от функции getenv, изменять нельзя). Далее, вызывая функцию strstr, мы ищем в рабочем буфере имя нужного нам параметра cookie. Если это имя найдено, то мы пропускаем символ равенства, ищем символ разделителя ‘;’ и заменяем его на двоичный нуль. После выполнения всех этих действий наша функция возвращает адрес искомой строки со значением нужного нам параметра cookie. Функция insertHTML просто открывает файл, имя которого передается ей в качестве параметра, читает его содержимое в оперативную память, и затем в буфер, адрес которого передается через второй параметр. Текст сценария, вставляемого функцией insertHTML в динамически формируемый документ HTML, представлен в листинге 7.9. Листинг 7.9. Файл chapter7/AgainCGI/script.ht


Cookie information from JavaScript:

С функцией findCookie вы уже знакомы. Она предназначена для получения значения параметра cookie по его имени. После завершения загрузки документа HTML наш сценарий при помощи этой функции получает текущее значение параметра cookie с именем AgainCount, установленное программой CGI: var szMyText=""; szMyText = findCookie("AgainCount"); Далее это значение добавляется к полной строке cookie и отображается в многострочном поле редактирования: TestForm.Comment.value = "Cookie: " + document.cookie + "\nAccess count: " + szMyText; Форма, содержащая поле редактирования, определена в начале вставляемого файла сценария JavaScript. Настройка браузера для работы с cookie Хотя cookie не представляют собой никакой опасности для пользователей, не все пожелают, чтобы хранящаяся в них информация передавалась на сервер Web. В сочетании с другими полями заголовка HTTP данные cookie позволяют собирать определенную статистику о пользователях, а это нравится далеко не всем. Настраивая браузер соответствующим образом, пользователи могут ограничить или вовсе отключить возможность работы с cookie. Вы должны это учитывать, если при создании активных документов HTML надеетесь на использование cookie. Браузер Microsoft Internet Explorer версии 4.0 допускает установку трех режимов работы с cookies. Эти режимы указываются на странице Advanced блокнота Internet Options (рис. 7.13), доступного из меню View браузера. Рис. 7.13. Установка режимов работы с cookie По умолчанию включен переключатель Always accept cookies, разрешающий использование cookie. Переключатель Disable all cookie use полностью запрещает использование cookie. Если включить переключатель Prompt before accepting cookies, при попытке установить cookies на экране появится предупреждающее сообщение (рис. 7.14). Рис. 7.14. Предупреждающее сообщение при попытке записи данных cookie Нажав кнопку More Info, вы можете получить подробные сведения о данных cookie, которые планируется записать на диск вашего локального компьютера, а также просмотреть эти данные в поле Data. ПРИЛОЖЕНИЕ 1. РАБОТА С ОТЛАДЧИКОМ MICROSOFT SCRIPT DEBUGGER Для отладки создаваемых вами сценариев JavaScript удобно использовать специальные отладчики, например, отладчик Microsoft Script Debugger. Вы можете получить его бесплатно с сервера Microsoft, расположенного в Internet по адресу http://www.microsoft.com. Установка отладчика Microsoft Script Debugger Процедура установки отладчика Microsoft Script Debugger очень проста. Если у вас уже установлен браузер Microsoft Internet Explorer, то вам достаточно запустить загруженный из Internet дистрибутивный файл. Единственно, о чем необходимо позаботиться, это чтобы версия отладчика Microsoft Script Debugger соответствовала версии браузера Microsoft Internet Explorer. После установки вам необходимо убедиться, что установки параметров браузера разрешают отладку сценариев JavaScript. Для этого запустите Microsoft Internet Explorer, и из меню View выберите строку Internet Options. На экране появится одноименная диалоговая панель, показанная на рис. 8.1. Рис. 8.1. Диалоговая панель Internet Options В этой панели вам нужно открыть страницу Advanced и выключить переключатель Disable script debugging, если он включен. Процесс отладки сценария Вы можете отлаживать сценарий в различных режимах, выполняя его по шагам, устанавливая точки останова, проверяя и изменяя содержимое переменных. Запуск сценария в режиме отладки Мы рассмотрим три способа запуска сценария в режиме отладки. Первый из них предполагает встраивание команды вызова отладчика непосредственно в текст сценария. При втором способе запуск отладчика выполняется из меню браузера Microsoft Internet Explorer. Третий способ - автоматический. Отладчик запускается автоматически, если в тексте сценария обнаружена ошибка. Использование команды вызова отладчика Если вам нужно проверить, как ведет себя та или иная строка сценария JavaScript, вы можете вставить перед этой строкой команду вызова отладчика debugger. В качестве примера для изучения способов запуска отладчика мы будем использовать сценарий, исходный текст которого представлен в листинге 8.1. Листинг 8.1. Файл chapter8/callDebugger.html Hello, world!

JavaScript Test

Message: Обратите внимание, что в функции printHello мы вставили строку вызова отладчика непосредственно перед обращением к функции printString. Когда вы попробуете просмотреть этот документ в браузере Microsoft Internet Explorer версии 4.0 с установленным отладчиком Microsoft Script Debugger, на экране появится окно отладчика, показанное на рис. 8.2. Рис. 8.2. Окно отладчика Microsoft Script Debugger Обратите внимание, что строка вызова отладчика выделена цветом и отмечена стрелкой. Это текущая строка, на которой выполнение сценария было остановлено. Теперь вы можете просмотреть или изменить содержимое переменных, установить точки останова, а затем запустить сценарий в пошаговом режиме либо просто продолжить его выполнение. Запуск отладчика через меню браузера Для того чтобы запустить отладчик Microsoft Script Debugger через меню браузера, откройте меню View и выберите там меню второго уровня Script Debuger. В этом меню есть две строки: Open и Break at next Statement. Первая из них просто открывает окно отладчика, а вторая - запускает отладчик и останавливает сценарий на следующей строке. Вы можете попробовать оба режима, например, для одного из сценариев, приведенных нами в первой главе нашей книги. Автоматический запуск отладчика при возникновении ошибки Если в процессе интерпретации сценария JavaScript браузер обнаруживает ошибку, он выводит на экран диалоговую панель с сообщением об ошибке и предоставляет возможность запустить отладчик. Вы можете попробовать этот режим на сценарии, представленном в листинге 8.2, куда мы намеренно внесли ошибку. Листинг 8.2. Файл chapter8/error.html Hello, world!

JavaScript Test

Message: Сразу после запуска на экране появится диалоговая панель Internet Explorer Script Error, показанная на рис. 8.3. Рис. 8.3. Сообщение об ошибке Из текста сообщения ясно, что в седьмом по счету символе девятой строки документа HTML обнаружена ошибка: указанный в сценарии метод или свойство не определено для объекта. Нажав кнопку Yes в панели Internet Explorer Script Error, будет запущен отладчик. Документ HTML с ошибкой будет загружен в окно отладчика, а текстовый курсор покажет ошибочную строку (рис. 8.4). Рис. 8.4. Курсор указывает на строку с ошибкой Просмотр открытых документов в окне отладчика Чтобы загрузить в отладчик документ HTML, выберите из меню View строку Running Documents. С помощью этой строки вы можете открыть окно Running Documents, в котором отображается список документов, доступных для отладки (рис. 8.5). Рис. 8.5. В отладчик загружены два документа HTML Чтобы открыть документ, достаточно сделать двойной щелчок левой клавишей мыши по соответствующей строке списка. Установка и сброс точек останова Сразу после запуска отладчика вы можете установить точки останова в текущем документе, загруженном в отладчик, или в другом произвольном документе, который загружен в браузер Microsoft Internet Explorer. В открытом документе можно установить точки останова. Для этого запустите отладчик из браузера, воспользовавшись строкой Open и Break at next Statement меню View. Затем вам нужно запустить сценарий. Это можно сделать, обновив документ в окне браузера или вызвав какое-либо событие, в результате которого сценарий получит управление. Далее нужно поместить текстовый курсор на ту строку, где необходимо установить точку останова, а затем выбрать из меню Debug строку Toggle Breakpoint. Строка, в которой находится точка останова, будет выделена красным цветом и отмечена красным кружочком, как это показано на рис. 8.6. Рис. 8.6. Мы установили точку останова При необходимости вы можете сбросить все или некоторые точки останова. Для сброса точки останова вы должны поместить в соответствующую строку текстовый курсор, а затем выбрать из меню Debug строку Toggle Breakpoint. Если нужно сбросить все точки останова, воспользуйтесь строкой Clear All Breakpoints из меню Debug. Выполнение сценария в пошаговом режиме Когда выполнение сценария было приостановлено, вы можете его продолжить в пошаговом режиме. Для этого у вас есть три возможности, которые влияют на режим трассировки вызовов функций. Во-первых, вы можете выполнить один шаг сценария с трассировкой вызовов функций. Для этого из меню Debug нужно выбрать строку Step Into. Во-вторых, можно выполнять вызываемые функции без трассировки, воспользовавшись строкой Step Over меню Debug. И, наконец, в-третьих, можно выбрать из меню Debug строку Step Out. В этом случае останов произойдет на выходе из функции. Выполнение сценария в непрерывном режиме Если после остановки выполнения сценария выбрать из меню Debug строку Run, работа сценария будет продолжена. В этом режиме сценарий будет выполняться до тех пор, пока не будет достигнута точка останова или пока в процессе интерпретации не будет обнаружена ошибка. Просмотр значений переменных и свойств объектов Для того чтобы просмотреть значения переменных или свойств объектов, вам необходимо открыть окно Command Window (рис. 8.7). Это можно сделать при помощи строки Command Window, расположенной в меню View. Рис. 8.7. Работа с окном Command Window Для того чтобы просмотреть значение переменной или свойства объекта, достаточно набрать имя этой переменной или ссылку на объект в окне Command Window и нажать клавишу . На рис. 8.7 мы определили значение свойств navigator.appName, navigator. appVersion, а также значение, записанное в строке szHelloMsg. Изменение значений переменных Окно Command Window можно использовать не только для просмотра содержимого переменных и свойств объектов, но и для изменения их значений. Чтобы изменить значение переменной или свойства объекта, допускающего изменение значения, вы можете воспользоваться обычным оператором присвоения. На рис. 8.8 мы показали, как можно вначале просмотреть значение переменной szHelloMsg, а затем изменить его. Рис. 8.8. Изменение значения переменной szHelloMsg Если теперь продолжить выполнение сценария, на экране вместо строки Hello, world! появится новое сообщение (рис. 8.9). Рис. 8.9. Сообщение изменилось после изменения значения переменной szHelloMsg Просмотр стека вызова функций Выбрав из меню View строку Call Stack, вы можете просмотреть содержимое стека вызова функций. В примере, показанном на рис. 8.10, функция printString была вызвана из функции printHello, которая, в свою очередь, была вызвана в глобальном контексте. Рис. 8.10. Просмотр стека вызова функций Окно просмотра Call Stack может оказать вам помощь при отладке сценариев с большой глубиной вложенности вызовов функций. Установка закладок в исходном тексте Еще одна возможность, которой обладает отладчик Microsoft Script Debugger, может оказаться особенно полезной при отладке больших сценариев, это закладки. Вы можете установить закладку на любой строке исходного текста сценария, поместив в нее текстовый курсор и нажав комбинацию клавиш . Закладка будет отмечена небольшим квадратиком, как это показано на рис. 8.11. Рис. 8.11. Установка закладки в исходном тексте сценария Нажимая клавишу или комбинацию клавиш вы можете перемещаться по закладкам, соответственно, в прямом и обратном направлении. ЛИТЕРАТУРА 1. Фролов А.В., Фролов Г.В. Библиотека системного программиста. М.: ДИАЛОГ-МИФИ. Т.23. Глобальные сети компьютеров. Практическое введение в Internet, E-Mail, FTP, WWW и HTML, программирование для Windows Sockets 2. Фролов А.В., Фролов Г.В. Библиотека системного программиста. М.: ДИАЛОГ-МИФИ. Т.29. Сервер Web своими руками 3. Фролов А.В., Фролов Г.В. Библиотека системного программиста. М.: ДИАЛОГ-МИФИ. Т.30. Microsoft Visual J++. Создание приложений на языке Java. Часть 1. 4. Фролов А.В., Фролов Г.В. Библиотека системного программиста. М.: ДИАЛОГ-МИФИ. Т.32. Microsoft Visual J++. Создание приложений на языке Java. Часть 2. ПРЕДМЕТНЫЙ УКАЗАТЕЛЬ --, 18 -, 18 !, 18 !=, 19 %, 18 %=, 20 &, 19 &&, 19 &=, 20  , 17 (), 22 *, 18 *=, 20 ,, 22 ., 22 /, 18 /=, 20 ?:, 21 [], 22 ^, 19 ^=, 20 _blank, 48 _parent, 48 _self, 48 _top, 48 |, 19 ||, 19 |=, 20 ~, 19 +, 18 ++, 18 +=, 20 <, 19 <<, 19 <<=, 20 <=, 19 , 46; 48; 95 , 108 , 45 , 31
, 32; 60 , 95 , 35; 94 , 102 , 62 , 43 , 94