Практическое введение в JavaScript
Павел Храмцов, Центр Информационных Технологий

Содержание
Назад | Содержание | Вперед
  • Управление просмотром страниц Web-узла. JavaScript
  • Модель объектов JavaScript - объекты Navigator'а
  • Методы объектов и свойства объектов. Управление потоком вычислений
  • События
  • Массивы
  • Графика
  • Стеки гипертекстовых ссылок
  • Фреймы и окна
  • Наследование кода скриптов различными страницами
  • Java, JavaScript и Plug-ins
  • Встраивание в HTML-документ
  • Примеры скриптов
  • Единство в многообразии
  • Приемы программирования на JavaScript
  • Примеры манипулирования окнами
  • Гипертекстовые ссылки и картинки
Назад | Содержание | Вперед


Управление просмотром страниц Web-узла. JavaScript.
Современные гипертекстовые информационные системы условно можно представить в виде совокупности нескольких компонентов: системы хранения гипертекстовых объектов, системы отображения гипертекстовых объектов, системы подготовки гипертекстовых объектов и системы программирования просмотра совокупности гипертекстовых объектов. С этой точки зрения технология World Wide Web только к 1996 году получила законченный, функционально полный вид. Первыми были разработаны системы хранения и просмотра (1989-1991 г.г.), которые продолжают развиваться и в настоящее время. После 1990 года стали появляться первые системы подготовки документов. Наконец, в 1995 году были предложены первые языки управления сценариями просмотра.
Программирование процедуры просмотра гипертекстовой базы данных не является изобретением Netscape, Microsoft или Sun. Практически все локальные гипертекстовые системы в той или иной степени имеют программные средства манипулирования гипертекстовыми объектами. В ряде случаев вся гипертекстовая база данных может быть представлена как одна большая программа, в которой гипертекстовые узлы - это программные модули, а связи между ними - это передача управления от одного модуля другому.
Преимущества такого подхода перед традиционной статической разметкой очевидны: гибкость построения гипертекстовой сети, возможность создания программ прокрутки фрагментов базы дынных, генерация составных гипертекстовых объектов из существующих элементарных компонентов. Динамические объекты могут быть легко получены из статических, т.к. в случае существования программы просмотра система может быть переведена из интерактивного режима просмотра гипертекстовой базы данных в пакетный, когда действия оператора будут заменяться командами программы.
Программы просмотра гипертекстовых страниц традиционно называют скриптами (scripts) по аналогии с исполняемыми файлами, написанными для командных интерпретаторов типа sh. Собственно как это было и раньше в локальных системах, в программировании просмотра гипертекстовых документов World Wide Web существуют два подхода: создание интерпретируемых программой просмотра скриптов или компиляция байт-кода. Первый подход следует традиции World Wide Web, согласно которой для разработки гипертекстовой страницы нужен только обычный текстовый редактор и сам гипертекстовый документ должен легко читаться человеком-оператором. Второй подход позволяет повысить эффективность исполнения программы и защищенность кода от несанкционированных модификаций. Как первый, так и второй способ опираются на объектно-ориентированный подход к программированию. По поводу байт-кодов или мобильных кодов, как их еще называют, написано в контексте технологии программирования Java достаточно много, поэтому сосредоточим свое внимание на скриптах, а точнее на скриптах, написанных на языке JavaScript.


Модель объектов JavaScript - объекты Navigator'а.
Идея JavaScript очень проста. Все операции, которые можно исполнять в программе на JavaScript, описывают действия над хорошо известными и понятными объектами, которыми являются элементы рабочей области программы Netscape Navigator и контейнеры языка HTML. Собственно объектная ориентированность JavaScript на этом и кончается. Есть только объекты с набором свойств и набор функций над объектами. Последние называются методами. Кроме методов существуют и другие функции, которые больше похожи на функции из традиционных языков программирования и позволяют работать со стандартными математическими типами или управлять процессом выполнения программы. Еще в JavaScript есть события - аналог программных прерываний. Эти события также ориентированы на работу в World Wide Web, например, загрузка страницы в рабочую область Navigator'a или выбор гипертекстовой ссылки. Используя события, автор гипертекстовой страницы и программы ее отображающей может организовать просмотр динамических объектов, например, бегущая строка, или управление многооконным интерфейсом.
Описание иерархии классов
Все встроенные объекты JavaScript берут свое начало от рабочей области Netscape, и их можно представить в виде следующей иерархии:
Кроме этих классов объектов пользователь может создавать и свои собственные. Но обычно большинство программ используют эту систему классов и не создают новых.


Методы объектов и свойства объектов. Управление потоком вычислений.
Каждый из этих классов имеет функции управления объектами класса - методы. Самыми главными их этих методов являются те, которые позволяют переназначать значения объектов. Делается это обычно по операции присваивания. Вообще, все типы операторов, которые поддерживаются обычными языками программирования, реализованы JavaScript (+,-,*, /, %, >>,<<, +=, -=, ...). При этом оператор сложения "+" при работе со строками означает конкатенацию последних, т.е. добавление в конец строки новую строку:
s = "string1" + "string2"
Кроме операций с числами и описаний стандартных классов в JavaScript есть команды управления потоком вычислений:
  • var - оператор объявления переменной.
    Тип переменной определяется по присвоенному ей значению.
            var kuku = "kuku"
  • if..else - условный оператор;
            if(i > 0)
        {
            ...
        }
        else
        {
            ...
        }
  • while - условный цикл;
            while(j == k)
        {
            j++;
            k--;
        }
  • break - принудительный выход из цикла;
            while(i < 6)
        {
            if(i == 3) break;
        }
  • continue - переход в конец цикла;
            while(i < 6)
        {
            if(i == 3) continue;
        }
  • for - цикл;
            for(i = 0; i < 9; i++)
        {
            ...
        }
  • for - цикл свойств объекта (переменных определенных в классе);
            for(i in obj)
        {
            str = obj[i]
        }
Перечисленные здесь операторы не представляют полного перечня операторов JavaScript, но их вполне достаточно для выполнения практических занятий.


События.
Важным элементом языка являются события. Программист использует события для выполнения определенных частей программного кода скрипта. Один из наиболее часто используемых приемов - исполнение определенных действий в момент загрузки страницы в Navigator.
Не будем перечислять все события, но упомянем о наиболее часто используемых:
  • onLoad - выполнение скрипта или функции при загрузке;
  • onChange - порождается при изменении значения элемента формы;
  • onClick - порождается при выборе объекта (button, checkbox и т.п.);
  • onSelect - порождается при выборе текстового объекта (text, textarea);
  • onSubmit - при нажатии на кнопку Submit;
  • onUnload - при переходе к другой странице.
Появление JavaScript 1.1 заставляет продолжить обзор возможностей управления сценариями просмотра Website. В новой версии языка были введены: возможность взаимодействия JavaScript и Java, определение установленных plug-ins, определены новые типы объектов (Area, Function, Image) и ряд других особенностей, которые по мнению разработчиков должны повысить мощь программирования на JavaScript.


Массивы.
Первый тип новых объектов, которые мы рассмотрим, являются массивы. Тип "Array" введен в JavaScript 1.1 для возможности манипулирования самыми разными объектами, которые отображаются Navigator'ом. Это - список всех гипертекстовых ссылок данной страницы Website, список всех картинок на данной странице, список всех applet'ов данной страницы, список всех элементов формы и т.п. Пользователь может создать и свой собственный массив, используя конструктор Array(). Делается это следующим образом:
        new_array = new Array()
        new_array5 = new Array(5)
        colors = new Array("red", "white", "blue")
Размерность массива может динамически изменяться. Можно сначала определить массив, а потом присвоить одному из его элементов значение. Как только это значение будет присвоено, изменится и размерность массива:
        colors = new Array()
        colors[5] = "red"
В данном случае массив будет состоять из 6 элементов, т.к. первым элементом массива считается элемент с индексом 0.
Для массивов определены три метода: join, reverse, sort. Join объединяет элементы массива в строку символов, в качестве аргумента в этом методе задается разделитель:
        colors = new Array("red", "white", "blue")
        string = acolors.join("+")
В результате выполнения присваивания значения строке символов string мы получим следующую строку:
        string = "red + white + blue"
Другой метод, reverse, изменяет порядок элементов массива на обратный, а метод sort отсортировывает их в порядке возрастания. У массивов есть два свойства: length и prototype. Length определяет число элементов массива. Если нужно выполнить некоторую рутинную операцию над всеми элементами массива, то можно воспользоваться циклом типа:
        color = new Array("red", "white", "blue")
        n = 0
        while(n != colors.length)
        {
            ...
        }
Свойство prototype позволяет добавить свойства к объектам массива. Однако наиболее часто, в программе на JavaScript используются встроенные массивы, главным образом графические образы (Images) и гипертекстовые ссылки (Links).


Графика.
До Navigator 3.0 в JavaScript использовались только встроенные объекты типа Image. В новой версии языка появился конструктор для этого типа объектов:
    new_image = new Image()
    new_image = new Image (width,height)
Часто для целей создания мультипликации создают массивы графических объектов, которые потом прокручивают один за другим:
    img_array = new Array()
    img_array[0] = new Image(50,100)
    img_array[1] = new Image(50,100)
    ....
    img_array[99] = new Image(50,100)
У объекта Image существует 10 свойств, из которых, пожалуй, самым важным является src. Так, для присваивания конкретных картинок элементам массива img_array следует воспользоваться следующей последовательностью команд:
    img_array[0].src = "IMAGE1.GIF"
    img_array[1].src = "IMAGE2.GIF"
    ...
    img_array[99].src = "IMAGE100.GIF"
В данном случае можно было воспользоваться и циклом для присвоения имен, так как они могут быть составлены из констант и значения индексной переменной. В новой версии языка объект типа Image можно поименовать в HTML-теге IMG. После этого можно обращаться к нему по имени. При этом следует учитывать, что если Image используется внутри формы, то он является свойством этой формы. Это значит, что для следующего графического объекта должны быть использованы разные составные имена:
    <IMG NAME=CAR SRC=CAR.GIF> <--- Встроенный в документ объект
    document.car.src = "CAR1.GIF"

    <form name=kuku>
    <IMG NAME=CAR SRC=CAR.GIF>   <-- Встроенный в форму документ.
    </form>
    document.kuku.car.src = "CAR1.GIF"
Однако, наиболее часто в примерах использования скриптов можно встретить обращение к Image по индексу в массиве всех графических объектов данной страницы. Если наш объект, например, является вторым Image на странице, то будь он внутри формы или за ее пределами, к нему всегда можно обратиться по индексу:
    document.images[1].src = "CAR1.GIF"
Расширяя наш пример с массивом Image построим теперь документ, в котором будет встроена мультипликация, определенная нашим массивом:
    <HTML>
    <HEAD>
    <SCRIPT>
    function multi_pulti()
    {
        img_array = new Array()
        img_array[0] = new Image(50,100)
        ....
        img_array[99] = new Image(50,100)
        img_array[0].src = "IMAGE1.GIF"
        ...
        img_array[99].src = "IMAGE100.GIF"
        n = 0
        while(n == 0)
        {
            document.images[0].src = img_array[0].src
            ...
        }
    }
    </SCRIPT>
    </head>
    <body onLoad="multi_pulti()">
    <IMG SRC=IMAGE1.GIF>
    </body>
    </html>
Довольно часто используют не мультипликацию, а выбор картинки через OPTION, другой новый объект JavaScript. При этом можно через поле формы SELECT менять не только саму картинку, но и гипертекстовую ссылку, которая может быть связана с этой картинкой. На гипертекстовую ссылку также можно ссылаться по индексу:
    DOCUMENT.LINKS[INDEX].HREF = KUKU.HTML
Данный прием оправдан и с точки зрения интерфейса навигатора. При использовании такого сорта массивов ссылок не требуется их длительное перечисление и листание страницы в рабочей области навигатора - можно просто выбрать ссылку из "выпадающего" меню. Другой способ для сокращения числа нажатий на клавиши - использование событий. В том же объекте OPTION можно использовать событие onChange, что делает необязательным нажатие кнопок типа submit. В этом случае достаточно будет просто выбрать альтернативу и перейти к новой странице сразу после выбора.


Стеки гипертекстовых ссылок.
Не обошли своим внимание авторы JavaScript и стеки гипертекстовых ссылок. В язык теперь введен новый тип объектов типа Area. Area - это элемент контейнера MAP, который определяет client-site imagemap. Собственно, главное достоинство такого объекта состоит в том, что гипертекстовые ссылки, которые определены в AREA, стали доступны для переопределения. Они появляются в массиве обычных ссылок страницы, и можно как получить значение URL, так и переопределить его. К объекту AREA нельзя обратиться по имени. Можно использовать только индекс массива гипертекстовых ссылок документа.
В контексте стека гипертекстовых ссылок интересно рассмотреть еще одну возможность JavaScript, связанную с переходом по гипертекстовой ссылке вообще. В обычном случае параметр HREF контейнера A должен иметь какое-нибудь значение. Если, например, по событию onClick необходимо открыть новое окно и в старом сохранить отображенный документ, то его URL следует указывать в качестве значения HREF. В противном случае, в старое окно будет загружена пустая страница, если HREF=" ". В новой версии JavaScript введена функция void. Точнее тип void, который означает отсутствие какого-либо значения. Если нам необходимо выполнить некоторые действия при выборе гипертекстовой ссылки, но при этом не перегружать текущие страницы, то в параметре HREF можно указать конструкцию:
    <A HREF="javascript:void(0)">kuku</A>
Таким приемом часто пользуются при программировании событий, связанных с проходом манипулятора мыши через поле гипертекстовой ссылки.


Фреймы и окна.
При работе с фреймами и окнами в предыдущих версиях JavaScript постоянно приходилось отслеживать последовательность открытия окон и фреймов, для того, чтобы аккуратно их потом закрывать. На некоторых неточностях работы с окнами были основаны так называемые mail-bombs. Суть этих "подарков" заключалась в том, что если пользователь по почте принимает документ, который состоит только из одной команды:
    window.close()
то система не спрашивая пользователя закрывала текущее окно, а в этот момент таким окном является окно электронной почты. Теперь, перед тем как что-либо закрыть, система будет спрашивать разрешения. Правда, опять не всегда. Если в момент получения команды на закрытие окна на экране только одно окно Navgator, то система его закроет без каких-либо комментариев.
Однако, работа с окнами и фреймами на этом не исчерпывается. Во-первых, в систему введено новое свойство opener, которое определено для текущего окна или фрейма, и методы blur и focus распространены на работу с окнами. Свойство opener определяет окно документа, который вызвал открытие окна текущего документа. Свойство определено для любого окна и фрейма. Необходимо выполнить некоторые функции по отношению к окну, открывшему данное окно, и можно использовать выражение типа:
    window.opener.[method]
Например, если требуется закрыть окно-предшественник, то можно просто выполнить метод close:
    window.opener.close()
Точно таким же способом можно изменить содержание этого окна при помощи методов write или writeln. Можно менять и другие свойства объектов в окне предшественнике. Следующий пример взят из дополнений к спецификации JavaScript:
    window.opener.document.bgColor = 'cyan'
В данном случае для окна предшественника определен светло голубой цвет в качестве цвета фона. Но самым замечательным является то, что предшественника можно менять. Это значит, что автор получает возможность открывать и закрывать окна не строго иерархической последовательности, а в произвольном порядке. Управление многооконным интерфейсом в этом случае становится более гибким:
    window.opener= new_window
    window.opener = null
Первый пример переназначает для текущего окна окно-предшественник, в то время как второй вообще защищает предшественника от каких-либо действий. Все, что было сказано об окнах, распространяется и на фреймы, которые являются просто частным случаем окна. При работе с фреймами часто фрейм может быть порожден путем разбиения другого фрейма на части. Если при этом потребуется обратиться к окну-предшественнику фрейма-предшественника, то свойство opener в этом случае незаменимо. Разработчики языка следуют за пожеланиями авторов Websit'ов и практикой применения JavaScrip, которая на начальной стадии разработки языка не была столь очевидной. Кроме обращения к различным свойствам окон и фреймов разработчики расширили действие методов blur и focus с фреймов до окон. Теперь не только фрейм, но и окно может быть сделано текущем с использованием метода focus или, наоборот, переведено в фон при помощи метода blur. В ряде случаев, при порождении нескольких страниц, например, обращение к этим функциям бывает довольно полезным.


Наследование кода скриптов различными страницами.
Отсутствие какого-либо наследования между различными страницами Website заставляло разработчиков перетаскивать из одной страницы в другую довольно большое количество часто используемых функций и переменных. Разговоры о том, что было бы неплохо получить возможность доступа к глобальным ресурсам или возможность определять такие глобальные ресурсы, ведутся с самого момента появления JavaScript. К сожалению, стройного логичного механизма передачи параметров, функций и переменных от одного окна или фрейма другому нет и в JavaScript 1.1. Однако, продвижение в этом направлении есть.
У контейнера SCRIPT появился атрибут SRC. Это дает возможность авторам строить своеобразную библиотеку функций, к которым можно обращаться из любой страницы, в которой будет ссылка на такую библиотеку. При этом вовсе необязательно размещать саму библиотеку на том же сервере, где размещены и гипертекстовые страницы Website. Можно использовать и чужие функции, написанные кем-либо из ветеранов программирования на JavaScript на другом конце Земли. В атрибуте SRC используется обычный URL. Внутри файла скриптов не используются теги SCRIPT. Это обычный файл с использованием определений функций и переменных. Естественно, что использование чужих скриптов может обернуться не только полезными приобретениями, но и непредсказуемыми проблемами. Для обычных пользователей страниц Website подкачка большого количества скриптов может стать просто дополнительным источником затрат. Наиболее вероятным случаем может стать использование одной-двух функций из библиотеки на одной странице, а качать придется всю библиотеку. Другой новой возможностью работы с функциями стало введение нового объекта Function. Объект Function порождается конструктором Function:
    new_Function = new Function(arg1, arg2, ..., argn, function_body)
Главное отличие от обычного декларирования функции заключается в том, что в данном случае порождена переменная new_Function, с которой можно работать, как с любым другим объектом. При обычном переделении функции такой переменной не порождается. Как любой объект Function имеет свои свойства, но не имеет методов. В качестве свойств функции выступают аргументы и возможность назначения новых свойств через prototype. В заключении разговора о функциях и наследовании хочется еще раз обратить внимание на свойство opener окон и фреймов. Это свойство можно использовать при обращении к объектам страницы-родителя, что позволяет компенсировать отсутствие наследования и глобальных переменных в JavaScript.


Java, JavaScript и Plug-ins.
В новой версии языка есть возможность организовать взаимодействие между Java-applet'ами и JavaScrip-скриптами. Достигается это за счет использования атрибута MAYSCRIPT в контейнере APPLET. Собственно в JavaScript определен объект типа APPLET, к которому можно обращаться либо по имени, либо по индексу в массиве applet'ов. У этого объекта есть только одно свойство - имя. Ни какие-либо другие свойства или методы для данного типа объектов не определены. Сами детали взаимодействия applet'ов и скриптов лучше всего обсуждать в рамках программирования Java applet'ов, поэтому здесь мы эти особенности опустим.
Кроме applet'ов JavaScript позволяет работать и с Plug-ins. Последние представляют из себя массив соответствующего типа, для которого определен ряд свойств. Используя эти свойства можно определить установленные plig-ins и их соответствия MIME-типам. Назначить plug-ins или манипулировать ими нельзя.


Встраивание в HTML-документ.
Для встраивания скриптов в тело HTML-документа используется контейнер SCRIPT. Не все программы просмотра способны распознавать и исполнять скрипты, поэтому само тело скрипта помещается в контейнер комментария. Для определенности рассмотрим небольшой пример:
    <HTML>
    <!--
    Author:	Pavel Khramtsov
    Date:	March 5, 1996
    -->
    <HEAD>
    <TITLE>Registration</TITLE>
    <SCRIPT LANGUAGE="JavaScript">
    <!-- The JavaScript Functions Definition
    function help_win()
    {
        Help = window.open("REG_HELP.HTM", "Help", "scrollbars=yes,resizable=yes")
    }
    function main_menu()
    {
        Main_menu = window.open("MAIN_M.HTM", "Main_menu")
    }
    // The end of JavaScript Functions Definition -->
    </SCRIPT>
    </HEAD>
    <BODY>
    <CENTER>
    <TABLE>
    <TR><TH><IMG SRC="RADLEG3.GIF"></TH><TH><H2>ISTC.
    Project	RADLEG(#245)</H2>
    RRC "Kurchatov Institute"<BR>
    <I>Dec, 25, 1995</I>
    </TH></TR>
    </TABLE>
    </CENTER>
    <HR>
    <CENTER>
    <h2>Registration Form</h2>
    <hr>
    ......
    Текст страницы.
    .....
    <hr>
    <FORM NAME=help_call>
    <TABLE BORDER=0>
    <TR>
    <TD><INPUT NAME=next TYPE=button VALUE=Next onClick="main_menu()"></TD>
    <TD><INPUT NAME=help TYPE=button VALUE=Help onClick="help_win()"></TD>
    </TR>
    </TABLE>
    </FORM>
    <hr>
    </CENTER>
    </BODY>
    </HTML>
В данном примере в заголовок документа (контейнер HEAD) включен контейнер SCRIPT. До недавнего времени атрибут LANGUAGE в этом контейнере не являлся обязательным. Но с момента появления VBSCRIPT смысл в указании типа языка появился - Navigator не понимает скриптов на других языках. Отсутствие атрибута может привести к ошибкам при отображении гипертекстовых страниц.
Далее в тексте страницы определен комментарий, в который включен текст скрипта. Начинается комментарий со строки:
    <!-- The JavaScript Functions Definition
и кончается строкой:
    // The end of JavaScript Functions Definition -->
Внутри контейнера скрипта определены две функции пользователя: help_win() и main_menu(). Смысл этих функций достаточно прозрачен. Help_win() предназначена для организации контекстно зависимого help, а main_menu() осуществляет допуск пользователя к главному меню Website. Обе функции используют один и тот же метод open (встроенную в JavaScript функцию, которая определена над объектом window) для того, чтобы открыть новое окно Netscape Navigator и загрузить в него гипертекстовые документы. При этом функция main_menu порождает стандартное окно (с кнопочками, иконками и т.п.), а функция help_win() окно без стандартных атрибутов. У этого окна имеются только линейки прокрутки (scroll bars).
Вызов функций осуществляется после нажатия на соответствующую кнопку, которые определены в HTML-форме help_call. Таким образом выполнение функций будет осуществлено только в том случае, если произойдет событие, описанное атрибутом onClick в контейнере INPUT соответствующего поля формы.
Если быть более точным, то приведенный пример - это фрагмент, реализующий регистрацию пользователя. К моменту его выполнения окно главного меню уже открыто, поэтому создание этого окна при выборе кнопки "NEXT" не происходит, а текст загружается в уже открытое окно.


Примеры скриптов.
Теоретизировать на предмет написания скриптов на JavaScrip можно долго. Но самый продуктивный способ получения представления о языке - это разбор примеров. Если посмотреть на список этих примеров, который можно найти в соответствующей директории Yahoo, то больше всего там различного сорта калькуляторов. Разберем программу такого же типа, только это будет не калькулятор, а программа обучения устному счету.
Пример
    <HTML>
    <!--
    Author:	Pavel Khramtsov
    Date:	February 23, 1996
    URL:	http://144.206.192.100/radleg/mo_input.htm
    -->
    <HEAD>
    <TITLE>Проверка устного счета.</TITLE>
    <SCRIPT LANGUGE="JavaScript">
    <!--
    var max_value = 0
    var operand1 = 0
    var operand2 = 0
    var result = 0
    var flag = 0
    var sign = "+"
    var input = ""
    var v_date = new Date()
    var number = v_date.getTime()

    function init(factor)
    {
        var today = new Date()
        return (factor*today.getTime()/1000)%30000
    }
    //Инициализировать счетчик случайных чисел.

    IX = init(2)
    IY = init(3)
    IZ = init(4)

    //2, 3, and 4 below were arbitrarily chosen.
    //They put some distance between the initial values of IX, IY, and IZ

    //Датчик случайных чисел.

    function random()
    {
        IX = Math.floor(171 * IX % 30269)
        IY = Math.floor(172 * IY % 30307)
        IZ = Math.floor(170 * IZ % 30323)
        return (IX / 30269.0 + IY / 30307.0 + IZ / 30323.0 ) % 1.0
    }

    //Выбрать сложение или вычитание.

    function set_sign(x)
    {
        if(x == "+")
        {
            flag = 0
            sign = "+"
        }
        if(x == "-")
        {
            flag = 1
            sign = "-"
        }
        return true
    }

    // Определить первый операнд.

    function f_operand()
    {
        operand1 = random()*max_value
        return parseInt(operand1)
    }

    // Определить второй операнд.

    function s_operand()
    {
        if(flag == 0)
        {
            operand2 = random() * (max_value-operand1)
        }
        else
        {
            operand2 = random() * operand1
        }
        return parseInt(operand2)
        }

    // Проверить введенные данные.

    function input_sign(x)
    {
        if(x == 10)
        {
            if(flag == 0)
            {
                if(operand1+operand2 == parseInt(input))
                {
                    window.document.test.r0.value = "Молодец!"
                }
            }
            else
            {
                window.document.test.r0.value = "Думай!?"
                window.document.test.input = ""; input = ""
            }

            if(flag == 1)
            {
                if( operand1-operand2 == parseInt(input) )
                {
                    window.document.test.r0.value ="__-__-_р!"
                }
                else
                {
                    window.document.test.r0.value = "Думай!?"
                    window.document.test.input = ""; input = ""
                }
            }
            return true
        }
        input += x
        window.document.test.result.value = input
        return true
    }

    // Генерация варианта.

    function main_calc()
    {
        operand1 = f_operand()
        window.document.test.op1.value = operand1
        operand2 = s_operand()
        window.document.test.op2.value = operand2
        window.document.test.s_sign.value = sign
        input = ""
        window.document.test.input = ""
        window.document.test.r0.value = " ??? "
        return true
    }
    // -->
    </SCRIPT>
    </HEAD>
    <BODY>
    <CENTER>
    <H1>Математический тест</H1>
    <HR>
    <FORM NAME=test>
    <TABLE BORDER=0>
    <TR>
    <TD><INPUT NAME=i10 TYPE=button VALUE="0-10"
        onClick="max_value=10"></TD>
    <TD><INPUT NAME=i20 TYPE=button VALUE="0-20"
        onClick="max_value=20"></TD>
    <TD><INPUT NAME=i100 TYPE=button VALUE="0-100"
        onClick="max_value=100"></TD>
    <TD><INPUT NAME=i+ TYPE=button VALUE=" + "
        onClick="set_sign('+')"></TD>
    <TD><INPUT NAME=i- TYPE=button VALUE=" - "
        onClick="set_sign('-')"></TD>
    </TR>
    </TABLE>
    <HR>
    <TABLE BORDER=0>
    <TR>
    <TD><INPUT NAME=op1 SIZE=2 MAXLENGTH=2></TD>
    <TD><INPUT NAME=s_sign SIZE=1 MAXLENGTH=1></TD>
    <TD><INPUT NAME=op2 SIZE=2 MAXLENGTH=2></TD>
    <TD>=</TD>
    <TD><INPUT NAME=result SIZE=3 MAXLENGTH=3></TD>
    <TD><INPUT NAME=award TYPE=button VALUE=" ? " onClick="main_calc()">
    <TD><INPUT NAME=r0 VALUE=" ??? ">
    </TR>
    </TABLE>
    <HR>
    <TABLE BORDER=2>
    <TR>
    <TD><INPUT NAME=b1 TYPE=button VALUE=" 1 " onClick="input_sign('1')"></TD>
    <TD><INPUT NAME=b2 TYPE=button VALUE=" 2 " onClick="input_sign('2')"></TD>
    <TD><INPUT NAME=b3 TYPE=button VALUE=" 3 " onClick="input_sign('3')"></TD>
    </TR>
    <TR>
    <TD><INPUT NAME=b4 TYPE=button VALUE=" 4 " onClick="input_sign('4')"></TD>
    <TD><INPUT NAME=b5 TYPE=button VALUE=" 5 " onClick="input_sign('5')"></TD>
    <TD><INPUT NAME=b6 TYPE=button VALUE=" 6 " onClick="input_sign('6')"></TD>
    </TR>
    <TR>
    <TD><INPUT NAME=b7 TYPE=button VALUE=" 7 " onClick="input_sign('7')"></TD>
    <TD><INPUT NAME=b8 TYPE=button VALUE=" 8 " onClick="input_sign('8')"></TD>
    <TD><INPUT NAME=b9 TYPE=button VALUE=" 9 " onClick="input_sign('9')"></TD>
    </TR>
    <TR>
    <TD><INPUT NAME=b0 TYPE=button VALUE=" 0 " onClick="input_sign('0')"></TD>
    <TD COLSPAN=2><INPUT NAME=bs TYPE=button VALUE=" OK " onClick="input_sign('10')">
    </TD></TR>
    </TABLE>
    </FORM>
    </CENTER>
    <HR>
    </BODY>
    </HTML>
Приведенный здесь пример содержит датчик случайных чисел (функции init и rand), таблицу, реализующую функции кнопок клавиатуры, и блок проверки результата вычислений. После загрузки программы пользователь должен выбрать тип вычислений (+,-), интервал вычислений (в пределах 10, 20, 100) и нажать кнопку "?" для генерации примера. После ввода с отображаемой клавиатуры числа пользователь нажимает на символ "=", что означает "исполнить", и система проверяет правильность ответа. Если ответ правильный, то программа поздравляет фразой "Молодец!", если нет - "Думай!?". В системе Windows 3.x нет встроенного датчика случайных чисел, поэтому стандартная функция rand в этой версии JavaScript не реализована. Используемый в данной программе датчик был позаимствован из телеконференции по JavaScript. В скрипте кроме этого используются объект типа "дата" и его методы, а также встроенные функции контроля вводимых данных. Как видно из примера обращение к полям HTML-формы представляет из себя обращение к структуре, корнем которой является объект окно, в котором определен объект документ, внутри которого определена форма и ее поля и атрибуты полей. Не у всех полей можно менять значения атрибутов, так, например, атрибут VALUE в кнопке не меняет своего значения, если только не перезагрузить страницу.
Другим часто встречающимся примером является бегущая строка. Строка может бежать либо в поле статуса (низ экрана), либо внутри поля формы. Рассмотрим такой пример.
Пример: Бегущая строка
    <HTML>
    <!-- ady@demos.su, Saturday, January 20, 1996 7:23:31 PM-->
    <!-- Demos WWW cover page -->
    <HEAD>
    <TITLE>Welcome to Demos Company - Moscow, Russia</TITLE>

    <!-- yet another scroller. (C) 1996 Dmitry Altukhov, ady@demos.su -->
    <!--

        Use this code for whatever purposes... provided that you
        retain the copyright notice. I accept no responsibility for any disasters
        caused by this monster. Cannot guess any other cool places for scrollers.
        And MSIE marquee emulation in JS?!
        Er... Mozilla clears windows too slow in JS...
    -->

    <SCRIPT LANGUAGE="JavaScript">
    <!-- roll it

    var rate, pos=0;
    function roll()
    {
        var loop, top, msg1;
        var msg="Hello World";
        for(var i=0; i<10; i++)
        {
            msg = msg + ("  Hello World");
        }
        // move on, make a scrolly... and who said that scrollers suck?! ;-)

        top = (130/msg.length)+1;
        for(loop=0; loop < top; loop++) msg += " " + msg;
        msg1 = msg.substring(pos, pos+130);
        window.defaultStatus = msg1;
        if (pos++ == 130) pos = 0;

        // come on, the poor thing can't roll any faster... buy a Ferrari. ;-)

        rate = setTimeout("roll()", 30);
    }

    // that's all folks ;-)
    // end -->
    </SCRIPT>
    </HEAD>
    <BODY BACKGROUND="BACK.GIF" BGCOLOR="#FFFFFF" TEXT="#000040"
    LINK="#000080" VLINK="#400080" ALINK="#FF0000" onLoad="roll()">
    .....
    </BODY>
    </HTML>
Здесь приведен фрагмент страницы компании Демос разработанный Дмитрием Алтуховым (andy@demos.su). Как видно из этого примера, прокрутка осуществляется за счет изменения содержания отображаемой переменной msg1. Запускается бегущая строка в момент загрузки страницы по событию onLoad. Из комментария к примеру следует, что автор не несет ответственность за проблемы, которые может данный скрипт породить при его отображении программой просмотра на компьютере пользователя. Собственно проблема вызвана применением функции setTimeout. Изначально предполагалось, что программа просмотра, которая поддерживает JavaScript будет исполняться в среде многопотоковых операционных систем. В этом случае к моменту порождения нового потока старый уже завершится и setTimeout будет таким образом порождать последовательно исполняемые потоки. Однако, при реализации JavaScript в Netscape Navigator 2.0 не все было выполнено аккуратно, и setTimeout стала просто "пожирать" ресурсы компьютера. Системы Windows 3.x вообще не являются много поточными и в них просто происходит переполнение стека при выполнении данного скрипта. Весь вопрос заключается только в том, как быстро "упадет" система, что зависит от объема исполняемой по setTimeout функции. Самое лучше, что можно посоветовать, если вдруг на экране появляется прокрутка - поскорее покинуть такую страницу. Справедливости ради следует отметить, что прокрутку можно организовать и другими способами, поэтому ее появление не обязательно должно вызывать крах системы или крах программы просмотра.
Прокручивать можно и вертикальные фрагменты. Достигается это за счет использования полей типа TEXTAREA.
Пример
    <HTML>
    <!--
    Author: Pavel Khramtsov
    Date: February 25, 1996
    -->
    <HEAD>
    <TITLE>Text Block Scrolling</TITLE>
    <SCRIPT LANGUAGE="JavaScript">
    var line_beak = "\n"
    var screen = ""

    // 1234567890123456789012345678901234567890
    screen += "Будем прокручивать			"
    screen += "Данный фрагмент текста			"
    screen += "В поле типа				"
    screen += "TEXTAREA                                	"
    screen += "формы term				"

    for(i=0; i< 6;i++)
        screen += "                                         "

    var i=0
    var j=40
    flag = 0
    function scroll()
    {
        if( flag== 0 )
        {
            display_str = ""
            for(k=0;k<11;k++)
            {
                display_str += screen.substring(i,j)
                i +=40;j = i + 40
                if(i>400) i = 0
            }
            window.document.term.work_field.value = display_str
            i += 40 ; if(i>400) i =0
        }
        id = setTimeout("scroll()",1000)
        return true
    }

    function change_button()
    {
        if(flag==0)
        {
            flag = 1
            return true
        }
        if(flag == 1)
        {
            flag = 0
            return false
        }
    }
    </SCRIPT>
    </HEAD>
    <BODY onLoad="scroll()">
    <CENTER>
    <H1>Text Block Scrolling.</H1>
    <HR>
    <FORM NAME=term>
    <TEXTAREA NAME=work_field COLS=40 ROWS=10 WRAP=ON></TEXTAREA>
    <P>
    <INPUT NAME=alarm VALUE="Start/Stop" TYPE=button onClick="change_button()">
    </FORM>
    </CENTER>
    <HR>
    </BODY>
    </HTML>
Собственно все организовано также, как и в предыдущем примере, только прокрутка осуществляется в поле формы, для этого поля введен параметр переноса текста на новую строку, ширина поля подобрана под размер выводимых строк. Прокрутка осуществляется как по событию onLoad, так и при нажатии на кнопку "Start/Stop". В этом случае не надо немедленно покидать страницу с прокруткой, а достаточно просто ее остановить.
Другой часто встречающийся пример на страницах со скриптами JavaScript - идущие часы:
Пример
    <HTML>
    <HEAD>
    <TITLE> type_Document_Title_here </TITLE>
    <SCRIPT LANGUAGE="JavaScript">
    <!--
    var i=0
    adv_message = "                                         "
    advert = "Russian Research Center \"Kurchatov Institute\""
    adv_message += advert
    adv_message += "                                       "
    adv_length = advert.length
    function move_clock()
    {

        // Clock
        day = new Date()
        clock_screen = day.getHours()+":"+day.getMinutes()+":"+day.getSeconds()
        document.kuku.f_clock.value = clock_screen

        // Rolling Field
        document.kuku.adv_string.value = adv_message.substring(i,i+45)
        document.kuku.i_field.value = i
        i++
        if( i == adv_length + 44 ) i = 0
        id = setTimeout("move_clock()",100)
    }
    // end -->
    </SCRIPT>
    </HEAD>
    <BODY onLoad="move_clock()">
    This is the start point:<BR>
    <a href="#next">
    This the document start point.</a>
    kukuku
    <a name=next>
    <FORM NAME=kuku onSubmit="alert('You submit data to server')" METHOD="GET">
    <INPUT TYPE=SUBMIT NAME=SABMIT VALUE=SUBMIT> Make a clock
    here:  <INPUT NAME=f_clock maxlength=8 size=8> <P> <INPUT
    NAME=adv_string maxlength=45 size=45> <INPUT NAME=i_field size=10>
    </FORM>
    </BODY>
    </HTML>
Пример: Минимизация, максимизация окна и его удаление
    <HTML>
    <!--
    Author: HTMLed User
    Date: May 16, 1996
    -->
    <HEAD>
    <title>Iconize</title>
    <script language="JavaScript">
    function make_icon()
    {
        window.open("TEST_ICON.HTM","test_icon","resizable=yes,scrollbars=no,
        width=50,height=70")
        window.close()
    }
    </script>
    </HEAD>
    <BODY>
    <h1>minimize page</h1>
    <form name=icon>
    <input name=icon_button type=button value=icon onClick="make_icon()">
    </form>
    </BODY>
    </HTML>
Пример: Максимизация окна
    <HTML>
    <!--
    Author: Pavel Khramtsov
    Date: May 16, 1996
    -->
    <HEAD>
    <script>
    function max_window()
    {
        window.open("ICONIZE.HTM", "new", "toolbar=yes,scrollbars=yes,directories=yes,
        status=yes,menubar=yes,resizable=yes,location=yes,width=700,height=500")
        window.close()
    }
    </script>
    </HEAD>
    <BODY>
    <center>
    <a href="" onClick="max_window()"><IMG SRC=BACK.JPG></a>
    </center>
    </BODY>
    </HTML>


Единство в многообразии.
В заключении следует отметить, что JavaScript - это не единственный язык управления сценариями просмотра документов. Microsoft подготовила свою версию аналогичного языка - VBScript на основе Visual Basic. Кроме того, управлять сценарием просмотра можно и из Java-applet'ов, что конечно сложнее, но зато более надежно и безопасно. При этом программист получает все преимущества наследования и прочие атрибуты объектно-ориентированного программирования. В конце концов для создания фреймов и окон можно использовать атрибуты соответствующих контейнеров HTML, которые позволяют делить рабочую область экрана на фрагменты, перекрывать объекты и восстанавливать первоначальный вид страницы. Таким образом, к настоящему времени существует по меньшей мере три способа управления сценариями просмотра гипертекстовых баз данных Web, каждый из которых по своему хорош. Какой из них выбрать - это дело автора Website.
Следуя логике авторов JavaScript и направлениям развития World Wide Web следует ожидать появления новых типов объектов и изменения свойств существующих. Кроме этого, видимо, появятся глобальные переменные и функции. Порождение абстрактных типов тоже не за горами, хотя от такой новации не очень понятно, кто выиграет. Постепенно совершенствуется и поддержка встроенных функций на разных платформах, так, например, функция random() реализована в настоящее время везде, что не исключает использование и своих собственных датчиков случайных чисел. И еще, скорее всего, следует ожидать компилятора JavaScript для клиента. Будет ли эта возможность встроена в Navigator или это будет отдельный модуль - пока не ясно, но появление библиотек функций - движение в этом направлении, хорошо согласующееся с принципами кэширования гипертекстовых страниц.


Приемы программирования на JavaScript.
Проще всего начать изучение программирования на каком-либо языке с простых примеров, которые читатель может немедленно проверить. С подачи авторов языка С все современные книги по программированию начинаются с примера печати фразы "Hello world" в разных ее проявлениях ("Hello Java", "Hello Perl" и т.п.). Для JavaScript точного аналога такого подхода найти нельзя. Но мы попробуем проиллюстрировать на простых примерах основные приемы программирования.
Аналогом "Hello world" можно считать выдачу сообщения в отдельном окне, которое порождается при нажатии на гипертекстовую ссылку:
Пример
Программа выдачи простого предупреждения при выборе гипертекстовой ссылки. Схема URL - JavaScript.
    <HTML>
    <HEAD>
    <title>Самый первый пример JavaScript</title>
    </HEAD>
    <BODY>
    <center>
    <h1>Мой первый пример JavaScript</h1>
    <hr>
    </center>
    В текст этого документа внедрена гипертекстовая ссылка
    <a href="javascript:window.alert('Do you speak English?')">
    "Don`t click here"
    </a>.
    Любопытно, что будет, если все-таки выбрать?
    </BODY>
    </HTML>
В данном примере среди текста документа расположена гипертекстовая ссылка "Don`t click here". Если ее выбрать при просмотре (кликнуть мышкой), то на экране появится окно-предупреждение с вопросом: "Do you speak English?".
Генерация этого окна осуществляется специальным методом window.alert, который выполняется при выборе гипертекстовой ссылки. Если быть более точным, то в качестве URL информационного ресурса, который следует загрузить при переходе по данной гипертекстовой ссылке, используется схема JavaScript - расширение спецификации URI для программирования сценариев просмотра гипертекстовых документов World Wide Web. В этом случае выполнение JavaScript-программы происходит при выборе гипертекстовой ссылки, а сам код программы записан как URL.

Выполнение скрипта при выборе гипертекстовой ссылки
Добиться такого же эффекта можно и другим способом, не прибегая к новой схеме URL. Для этой цели можно использовать событие, которое генерируется программой-навигатором при выборе гипертекстовой ссылки - Click.
Пример
Программа выдачи простого предупреждения по событию Click при выборе гипертекстовой ссылки.
    <HTML>
    <HEAD>
    <title>Самый первый пример JavaScript</title>
    </HEAD>
    <BODY>
    <center>
    <h1>Мой первый пример JavaScript</h1>
    <hr>
    </center>
    В текст этого документа внедрена гипертекстовая ссылка
    <a href="javascript:void(0)" onClick="window.alert('Do you speak
     English?')">"Don`t click here"</a>. Любопытно, что будет,
    если все-таки выбрать?
    </BODY>
    </HTML>
Обойтись без новой схемы URL здесь также не удается, но она используется только для того, чтобы после выбора гипертекстовой ссылки в рабочем поле программы навигатора не появлялось пустой страницы, или не приходилось загружать вновь старую страницу. Для обработки события используется конструкция onClick, которая реализует обращение к обработчику (handler) данного события, который в свою очередь вызывает выполнение кода, записанного вслед за onClick.
Размещение кода программы на JavaScript непосредственно в тагах HTML является обычным делом, но не всегда бывает удобным. Наиболее часто JavaScript-код выносят в специальный HTML-контейнер SCRIPT(</script>.....</script>). Для того, чтобы продемонстрировать применение этого подхода, видоизменим наш пример следующим образом:
Пример
Применение контейнера SCRIPT для размещение JavaScript-кода.
    <HTML>
    <HEAD>
    <title>Самый первый пример JavaScript</title>
    <script language="JavaScript">
    <!-- Start the text of programme
    function question()
    {
        window.alert("Do you speak English?");
    }
    // -->
    </script>
    </HEAD>
    <BODY>
    <center>
    <h1>Мой первый пример JavaScript</h1>
    <hr>
    </center>
    В текст этого документа внедрена гипертекстовая ссылка
    <a href="javascript:void(0)" onClick="question()">"Don`t click
    here"</a>. Любопытно, что будет, если все-таки выбрать?
    </BODY>
    </HTML>
Данный пример развивает применение JavaScript-кода для обработки события Click. Но только в этом случае мы не размещаем весь код обработки события в атрибуте onClick. В данный атрибут помещается только вызов функции, которая будет обрабатывать это событие. Само тело функции размещено в заголовке HTML-документа внутри тагов <script ...> и </script>
Для того, чтобы защитить текст функции от интерпретации браузерами, которые не поддерживают JavaScript, мы поместили код в HTML-комментарий. При этом последняя строка этого комментария должна начинаться как комментарий JavaScript, чтобы браузер, понимающий JavaScript, не интерпретировал ее как часть JavaScript-кода.
Различные браузеры поддерживают разные версии JavaScript, что накладывает определенные ограничения при написании сценариев JavaScript. Для того, чтобы максимально адаптировать свою программу к конкретному типу программного обеспечения, часто включают проверку версии и имени программы-браузера в JavaScript.
Пример
Получение типа программы просмотра HTML-страниц.
    <HTML>
    <HEAD>
    <title>Test of Browser name</title>
    </HEAD>
    <BODY>
    <h1 align=center>Проверка имени типа браузера;</h1>
    <hr>
    Для того, чтобы получить имя вашей программы просмотра
    выберите кнопку "Browser"<br>
    <center>
    <form name=kuku>
    <input type=button name=browser value=Browser
    onClick="window.alert(window.navigator.appName)">
    </form>
    </BODY>
    </HTML>
Данная программа в точности повторяет предпредыдущий пример, но в окне предупреждения выдает имя программы просмотра HTML-страниц (window.navigator.appName). Вообще говоря, в простом сообщении о типе программного обеспечения большого смысла нет, но если вставить проверку данного имени в текст HTML-страницы и реализовать условную компиляцию страницы, то тогда обращение к данной конструкции JavaScript будет оправданным:
Пример
Условная генерация текста страницы по типу программы просмотра.
    <HTML>
    <HEAD>
    <title>Test of Browser name</title>
    </HEAD>
    <BODY>
    <h1 align=center>Проверка имени типа браузера</h1>
    <hr>
    <script language=JavaScript>
    <!--
    if(window.navigator.appName == "Netscape")
    {
        document.write("<br><center><font color=steelblue size=+5>");
        document.write("У вас хороший навигатор.");
        document.write("</font></center>");
    }
    else
    {
        document.write("<font color=red size=+3>Необходим Netscape Navigator
        версии 3.0 и выше.</font>");
        window.alert("Down load new version of your browser now.");
    }
    // -->
    </script>
    </BODY>
    </HTML>
В данном примере текст JаvaScript-программы размещен непосредственно в теле документа. При его загрузке, когда HTML-интерпретатор доходит до контейнера SCRIPT, вызывается JavaScript-интерпретатор. В этот момент будет проверяться условие, которое содержится в операторе if. В зависимости от результата проверки этого условия остальной текст страницы примет тот или иной вид в зависимости от типа программы просмотра. При просмотре данного документа программой отличной от Netscape Navigator будет выдано еще и окно предупреждения.

При загрузке был определен Netscape Navigator в качестве программы-браузера HTML-страниц.
Вообще говоря, проверить тип программы просмотра можно на сервере протокола HTTP и передать программе просмотра уже готовую страницу без условной генерации ее содержания. Но это возможно только в том случае, когда автор страницы имеет возможность программировать на машине где установлен сервер и имеет возможность администрировать этот сервер. В ряде случаев, когда место под Website арендуется и в договоре аренды нет пункта, обеспечивающего управление ресурсами сервера, в этом случае программы с условной генерацией содержания страниц бывают чрезвычайно полезными. Другой случай - это работа в локальном режиме без сервера. Здесь JavaScript является единственным средством управления просмотром. Существует еще ряд случаев, когда применение контейнера SCRIPT в теле документа является вполне оправданным, но на них мы остановимся позже в контексте решения конкретных задач управления сценариями просмотра.
Однако, чаще всего, текст JavaScript-кода размещают в виде описания функций в заголовке документа, что делает использование такого кода более удобным. Связано это с двумя моментами, которые следует учитывать при написании JavaScript-программ: область действия описания программы (из каких частей документа или страницы она видна, а следовательно, на нее можно сослаться как на функцию, и принципы интерпретации кода при просмотре документа.
Если код размещается в теле документа, то он интерпретируется только в случае переразметки отображаемого документа (загрузка, изменение параметров окна, перезагрузка). Если текст размещен в заголовке, то на него можно сослаться из любого места документа, а точнее из любого обработчика событий, которые указываются как атрибуты HTML-тагов.
Вернемся теперь снова к предыдущему примеру, но только разместим теперь код JavaScript не в тексте документа, а в отдельном файле:
Пример
Размещение скрипта в отдельном файле (netscape.jsc).
    <HTML>
    <HEAD>
    <title>Test of Browser name</title>
    </HEAD>
    <BODY>
    <h1 align=center>Проверка имени типа браузера</h1>
    <hr>
    <script language=JavaScript src=netscape.jsc>
    </script>
    </BODY>
    </HTML>
В данном случае текст условной генерации страницы размещен во внешнем файле. При загрузке страницы этот текст докачивается программой просмотра и исполняется так же, как если бы он размещался в документе. Любопытно, что при просмотре текста документа через опцию "View Source" текст скрипта не отображается, что дает возможность скрыть его содержание от пользователя. В самом файле, который содержит конструкции JavaScript, HTML-таги не используются:
Пример
Содержание файла netscape.jsc, ссылка на который установлена в атрибуте SCR тага <SCRIPT>
    if(window.navigator.appName == "Netscape")
    {
        document.write("<br><center><font color=steelblue size=+5>");
        document.write("У вас хороший навигатор.");
        document.write("</font></center>");
    }
    else
    {
        document.write("<font color=red size=+3>Необходим Netscape Navigator
        версии 3.0 и выше.</font>");
        window.alert("Down load new version of your browser now.");
    }
На этом можно закончить вступительную часть, посвященную примерам JavaScript-кода, и перейти к более планомерному изложению приемов программирования на JavaScript, если бы не одно "но". Дело в том, что любой автор, который собирается излагать программирование на JavaScript, встречается с проблемой постепенного наращивания сложности примеров. Материал надо начинать излагать "от печки", но вот этой самой печки нет. Все программы на JavaScript (Client-site JavaScript) - это в той или иной мере программы обработки событий, которые связаны с теми или иными информационными объектами. Без изучения этих объектов нельзя начинать ничего программировать.
Однако, существует лазейка в этом заколдованном круге, которой мы и воспользуемся. Это схема JavaScript универсального локатора ресурсов (URL). В наших примерах мы уже использовали эту схему. Она помогала нам открывать окно-передупреждение при выборе гипертекстовой ссылки (пример 2.10) и избегать перезагрузки страниц (пример 2.11). Мы будем пользоваться этой схемой вызова JavaScript-кода до тех пор, пока не появится в нашем рассмотрении объект (контейнер HTML) с атрибутом обработки события.
После этого небольшого отступления начнем рассматривать приемы программирования на JavaScript в соответствии с иерархией объектов этого языка, начиная с самого старшего объекта и двигаясь вглубь дерева объектов: от объекта "окно" к элементам формы.


Примеры манипулирования окнами.
Как это не покажется странным, но в наших простых примерах мы уже начали манипулировать окнами. Открытие окна-пердупреждения - это операция над объектом "окно". Определим свойства объекта "окно", методы изменения этих свойств и события, которые могут быть связаны с объектом типа "окно". При этом мы не ставим перед собой задачи описания всех известных в JavaScript свойств, методов и событий, связанных с объектами этого класса. Определим только те, которые понадобятся в наших примерах.
Методы позволяют нам создать на экране видимое окно, закрыть окно и проделать с ним другие операции. С методом window.alert мы уже знакомы. Методы window.confirm и window.prompt используются для получения ответов от пользователя:
Пример 2.16: Использование методов Alert, Prompt, Confirm
    <HTML>
    <HEAD>
    <title>Window simple example</title>
    </HEAD>
    <BODY>
    <center>
    <h1>Simple window methods</h1>
    <hr>
    </center>
    <ul>
    <li><a href="javascript:window.alert('Attention!!! press the button to continue.')">Метод Alert.</a>
    <li><a href="javascript:window.status=window.confirm('Answer yes or no.');void(0);">Метод Confirm.</a>
    <li><a href="javascript:window.status=window.prompt('Type string here:','');void(0);">Метод Prompt.</a>
    </ul>
    </BODY>
    </HTML>
В данном примере при вызове метода confirm появляется окно с просьбой подтверждения некоторого действия, при использовании метода prompt - окно с приглашением ввести информацию в поле ввода. В двух последних случаях если не указать функции void(0), произойдет замещение текста HTML-документа на значение, которое возвращают эти два метода. Если внимательно смотреть за полем окна навигатора, в котором отображается информация о загрузке документов, то там можно будет увидеть возвращаемые значения, т.к. они присваиваются свойству status текущего окна, которое связано именно с этим полем, и которому можно присваивать значения, и, следовательно, эти значения будут отображаться в этом поле.
Однако, следует признать, что рассмотренные выше методы используются крайне редко. А тем более в приведенном здесь контексте, поэтому поспешим рассмотреть методы открытия и закрытия окна.
Открыть окно можно используя метод window.open:
    <HTML>
    <HEAD>
    <title>Window simple example</title>
    </HEAD>
    <BODY>
    <center>
    <h1>Open window methods</h1>
    <hr>
    </center>
    Если выбрать гипертекстовую ссылку
    <a href="JAVASCRIPT:WINDOW.OPEN('SIMPLE8.HTM','example','scrollbars,
    resizable,width=300,height=200');void(0);">Открыть окно</a>, то
    будет открыто новое окно. Чаще всего этот прием используют
    при создании контекстно зависимых меню.
    </BODY>
    </HTML>
В данном случае при выборе гипертекстовой ссылки будет открыто окно шириной 300 пикселей и высотой 200 пикселей, в окне не будет никаких стандартных меню навигатора, и в окно будет загружен документ SIMPLE8.HTML. Метод open позволяет также определить области прокрутки, наличие или отсутствие стандартных меню навигатора и возможность изменения размеров окна. Последняя возможность зависит от платформы на которой исполняется скрипт.
Пример: Закрыть текущее окно
    <HTML>
    <HEAD>
    <title>Window simple example</title>
    </HEAD>
    <BODY>
    <center>
    <h1>Close window methods</h1>
    <hr>
    </center>
    Если выбрать гипертекстовую ссылку
    <a href="javascript:window.close();void(0);">
    Закрыть окно</a>, то
    данное окно будет закрыто.
    </BODY>
    </HTML>
В данном примере в качестве гипертекстовой ссылки используется ссылка на метод widow.close(), который закрывает текущее окно. На применении методов open и close построен принцип построения help. По методу open открывается окно подсказки. В него загружают текст документа-подсказки с заранее заготовленной ссылкой на закрытие окна. При выборе этой ссылки окно подсказки закрывается, и пользователь продолжает работать с основным окном навигатора.
Рассмотрим еще один метод, связанный с окном - метод scroll. Данный метод позволяет организовать прокрутку текста в окне.
Пример: Прокрутка текста в окне навигатора
    <HTML>
    <HEAD>
    <title>Scroll text</title>
    </HEAD>
    <BODY>
    <center>
    <h1>Прокрутка текста в окне навигатора</h1>
    <hr>
    [<a href="javascript:for(i=0;i<80;i++)
    {window.scroll(0,i*10)};void(0);">Прокрутить текст</a>]
    <hr>
    </center>
    Вообще говоря, проверить тип программы просмотра можно на сервере
    протокола HTTP и передать программе просмотра уже готовую страницу
    без условной генерации ее
    ...

    <hr>
    <center>[<a href=#top>Вернуться в начало</a>]</center>
    </BODY>
    </HTML>
От метода прокрутки мы перейдем теперь к методу, который позволит нам прокручивать документ более равномерно - это метод setTimeout. Большинству пользователей Web он знаком по бегущим строкам в поле статуса программы-навигатора. Метод setTimeout позволяет отложить выполнение функции, которая указывается в качестве аргумента на определенное количество миллисекунд. Системы прокрутки в этом случае рекурсивно вызывают свое выполнение через этот метод и тем самым порождают бесконечный цикл прокрутки.
Пример: Прокрутка текста по таймеру
    <HTML>
    <HEAD>
    <title>Scroll text</title>
    <script language=JavaScript>
    <!--
    i=0;flag=0;start_stop=0;
    function my_scroll()
    {
        if(start_stop == 1)
        {
            window.scroll(0,i*10);
            if(flag == 0) i++;
            if(flag == 1) i--;
            if(i > 80) {i = 80; flag = 1;}
            if(i < 0) {i = 0; flag = 0;}
        }
        setTimeout("my_scroll()", 500);
    }
    function kuku()
    {
        if(start_stop == 0)
        {
            start_stop =1;
        }
        else
        {
            start_stop =0;
        }
    }
    // -->
    </script>
    </HEAD>
    <BODY onLoad=my_scroll()>
    <center>
    <h1>Прокрутка текста в окне навигатора</h1>
    <hr>
    [<a href="javascript:kuku();void(0);">Запустить/Остановить</a>]
    <hr>
    </center>
    Вообще говоря, проверить тип программы просмотра можно на сервере
    протокола HTTP и передать программе просмотра уже готовую страницу
    без условной генерации ее
    ...
    <hr>
    <center>[<a href=#top>Вернуться в начало</a>]</center>
    </BODY>
    </HTML>
В данном примере мы не стали писать текст программ в самих гипертекстовых ссылках и вынесли его в заголовок документа. В данном случае это облегчает чтение текста и отладку программы. Текст прокручивается через каждые 500 миллисекунд, что делает прокрутку более плавной. В примере мы впервые применили событие onLoad. Это событие запускает процесс выполнения нашей функции. Прокрутка текста осуществляется в двух направлениях: сначала снизу вверх, а по достижении конца документа сверху вниз.
Следует подробно остановиться на особенностях исполнения метода setTimeout. Особенно в части запуска и останова процедуры прокрутки. Рассматривать алгоритм ее исполнения лучше всего в контексте многопоточных или многозадачных систем. Функция my_scroll - это отдельный процесс (поток), который исполняется программой-навигатором. В момент, когда интерпретатор навигатора встречает метод setTimeout, он создает новый процесс (поток), эквивалентный функции my_scroll, и откладывает его исполнение на 500 миллисекунд. После этого он продолжает выполнять текущий процесс (поток). В нашем случае вызов метода setTimeout - это последняя команда функции my_scroll, поэтому после нее ничего не выполняется, а сам процесс или поток, связанный с текущей функцией my_scroll после обработки setTimeout уничтожается. Однако, новый процесс (поток) уже создан в памяти и ждет начала своего исполнения.
В нашем примере новый процесс поток порождается всякий раз, как интерпретатор достигает метода setTimeout, а уничтожается, когда интерпретатор доходит до последнего оператора этого потока. Такой алгоритм выполнения заставляет расположить вызов setTimeout за пределами блока проверки условий скроллинга. Если мы расположим его внутри, то при останове скроллинга новый процесс не будет порожден, а это значит, что и кода, который будет реагировать на флаг скроллинга после останова, не будет существовать, т.е. запустить скроллинг не будет никакой возможности. Именно по этой причине функция my_scroll начинает исполняться сразу после загрузки документа по событию onLoad, но т.к. флаг скроллинга 0, то прокрутки текста не происходит. Процесс порождается все время, пока страница загружена в текущее окно навигатора.
Во второй версии навигатора данная функция была реализована не очень аккуратно, что приводило к переполнению программного стека и краху программы-навигатора.


Гипертекстовые ссылки и картинки.
Гипертекстовые ссылки и картинки - это свойства объекта "документ", который в свою очередь является частью объекта "окно". И гипертекстовые ссылки, и картинки составляют встроенные массивы, к которым можно обращаться по индексу. Рассмотрим несколько примеров программирования массивов гипертекстовых ссылок и картинок.
Просмотр фотографий образцов через список гипертекстовых ссылок
Вся страница размечается как таблица, состоящая из одной строки в две ячейки. В первой ячейке размещается список выбора альтернатив, во второй ячейке размещаются картинки, выбранные при помощи списка альтернатив. Все элементы списка помечены как гипертекстовые ссылки. У каждой ссылки определено событие onSelect. Для того, чтобы не происходил переход к другой странице, а выполнялась только обработка события, в поле href необходимо определить вызов JavaScript. Ниже приведен пример реализации такой компоновки и пример кода самой страницы.
Пример: Изменение картинки через гипертекстовую ссылку
    <HTML>
    <HEAD>
    <TITLE>HTTPD\HTDOCS\JAVASCR\EXAMPLE1</TITLE>
    <SCRIPT>
    <!-- Защитили текст скрипта от старых браузеров
    function l_image(a)
    {
        document.images[1].src=a
    }
    // -->
    </SCRIPT>
    </HEAD>
    <BODY TEXT="#000000" BGCOLOR="#FFFFCC" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
    <H1>
    <FONT COLOR="#000099">Просмотр фотографий образцов</FONT>
    </H1>
    <center>
    <TABLE COLS=2 WIDTH="100%" >
    <CAPTION>
    <FONT COLOR="#000099" SIZE=+2>Образцы бытовой техники</FONT>
    </CAPTION>
    <TR>
    <TD>
    <UL>
    <LI><A HREF="JAVASCRIPT:L_IMAGE('FREEZE.GIF')">Холодильник</A> </LI>
    <LI><A HREF="JAVASCRIPT:L_IMAGE('DUST.GIF')">Пылесосы</LI>
    <LI><A HREF="JAVASCRIPT:L_IMAGE('TOSTER.GIF')">Тостер</LI>
    <LI><A HREF="JAVASCRIPT:L_IMAGE('COOK.GIF')">Варочный стол</LI>
    <LI><A HREF="JAVASCRIPT:L_IMAGE('OVEN.GIF')">Духовка</LI>
    <LI><A HREF="JAVASCRIPT:L_IMAGE('WASH.GIF')">Стиральная машина</LI>
    <LI><A HREF="JAVASCRIPT:L_IMAGE('DISHWASH.GIF')">Посудомоечная машина</LI>
    </UL>
    </TD>
    <TD ALIGN=CENTER VALIGN=CENTER><IMG SRC="DUST.GIF" NAME="tool" > </TD>
    </TR>
    </TABLE>
    </center>
    </BODY>
    </HTML>
В данном примере при выборе гипертекстовой ссылки происходит вызов функции l_image(), которая изменяет значение атрибута SRC в контейнере IMG. Таким образом, можно организовать просмотр различных товаров в одном единственном графическом окне.
Изменение картинки путем выбора предмета из списка.
Вся страница размечается как таблица, состоящая из одного столбца в две ячейки. В первой ячейке размещается выпадающее меню выбора альтернатив, во второй ячейке размещаются картинки, выбранные при помощи списка альтернатив. При выборе альтернативы из меню происходит событие onChange, которое вызывает функцию l_image. Ниже приведен пример реализации такой компоновки и пример кода самой страницы.
Пример: Выбор картинки из списка
    <!-- элементы заголовка -->
    ...
    <SCRIPT>
    <!-- Защитили текст скрипта от старых браузеров
    pictures = new Array()
    for(i = 0; i < 8; i++)
    {
        pictures[i] = new Image()
        if(i==0) pictures[i].src = "FREEZE.GIF"
        if(i==1) pictures[i].src = "DUST.GIF"
        if(i==2) pictures[i].src = "TOSTER.GIF"
        if(i==3) pictures[i].src = "COOK.GIF"
        if(i==4) pictures[i].src = "OVEN.GIF"
        if(i==5) pictures[i].src = "WASH.GIF"
        if(i==6) pictures[i].src = "DISHWASH.GIF"
    }
    function l_image()
    {
        document.images[1].src = pictures[document.form1.item.selectedIndex].src
    }
    // -->
    </SCRIPT>

    Фрагмент HTML-разметки с вызовом функции изменения картинки:

    <center>
    <TABLE COLS=2 WIDTH="100%" >
    <CAPTION>
    <FONT COLOR="#000099" SIZE=+2>Образцы бытовой техники</FONT>
    </CAPTION>
      <TR>
        <th>
          <form name=form1>
          <select name=item onChange=l_image()>
            <option>Холодильник
            <option selected>Пылесос
            <option>Тостер
            <option>Варочный стол
            <option>Духовка
            <option>Cтиральная машина
            <option>Посудомоечная машина
          </select>
          </form>
        </th>
      </tr>
      <tr>
      <th ALIGN=CENTER VALIGN=CENTER><IMG SRC="DUST.GIF" NAME="tool" > </th>
      </TR>
    </TABLE>
    <HR>
    </center>
В данном примере картинка выбирается как элемент списка. При этом происходит событие onChange, и по нему определяют, какой именно элемент был отобран.
Листание картинок и их автоматический просмотр
Вся страница размечается как таблица, состоящая из одного столбца в две ячейки. В первой ячейке размещаются три кнопки управления просмотром картинок "Вперед", "Старт/Стоп", "Назад". Во второй ячейке размещаются картинки, выбранные путем листания. Листание осуществляется кнопками "Вперед" и "Назад". Возможен и другой вариант выбора картинки, когда система сама через некоторый промежуток времени периодически меняет картинки. Для этого следует сначала запустить автоматическую смену картинок, нажав на кнопку "Старт/Стоп", а потом, когда будет показана нужная картинка, остановить автоматическое листание, снова нажав на кнопку "Старт/Стоп". Ниже приведен пример реализации такой компоновки и пример кода самой страницы.
Пример: Листание и прокрутка картинок
    <SCRIPT>
    <!-- Защитили текст скрипта от старых браузеров
    pictures = new Array()
    for(i = 0; i < 8; i++)
    {
        pictures[i] = new Image()
        if(i==0) pictures[i].src = "FREEZE.GIF"
        if(i==1) pictures[i].src = "DUST.GIF"
        if(i==2) pictures[i].src = "TOSTER.GIF"
        if(i==3) pictures[i].src = "COOK.GIF"
        if(i==4) pictures[i].src = "OVEN.GIF"
        if(i==5) pictures[i].src = "WASH.GIF"
        if(i==6) pictures[i].src = "DISHWASH.GIF"
    }
    n=0;
    flag=0;
    function next_image()
    {
        if(flag==0)
        {
            n++;if(n>6) n=0;
            document.images[1].src = pictures[n].src
        }
    }
    function back_image()
    {
        if(flag == 0)
        {
            n--;
            if(n < 0) n = 6;
            document.images[1].src = pictures[n].src
        }
    }
    function scroll_image()
    {
        if(flag == 1)
        {
            n++;
            if(n > 6) n = 0;
            document.images[1].src = pictures[n].src
        }
        setTimeout("scroll_image()",1500);
    }
    function start_stop()
    {
        if(flag == 0)
        {
            flag = 1
        }
        else
        {
            flag = 0
        }
    }
    // -->
    </SCRIPT>

    <TABLE COLS=2 WIDTH="100%" >
    <CAPTION>
    <FONT COLOR="#000099" SIZE=+2>Образцы бытовой техники</FONT>
    </CAPTION>
      <TR>
        <th>
          <form name=form1>
          <input name=f type=button value=Вперед onClick=next_image()>
          <input name=ss type=button value="Старт/Стоп" onClick=start_stop()>
          <input name=b type=button value=Назад onClick=back_image()>
          </form>
        </th>
      </tr>
      <tr>
      <th ALIGN=CENTER VALIGN=CENTER><IMG SRC="DUST.GIF" NAME="tool" > </th>
      </TR>
    </TABLE>
В этом примере мы используем те же средства, что использовали и для организации скроллинга. Алгоритм останова и запуска прокрутки тот же, что и при скроллинге окна.
Пример использования client-site imagemap
В данном примере мы хотим показать возможность изменения картинки imagemap с одновременным изменением гипертекстовых ссылок, связанных с этой картинкой. Такая возможность существует только в том случае, если все картинки, которые мы хотим использовать в качестве imagemap, имеют одинаковую компоновку. Мы реализуем просмотр вариантов в виде горизонтального меню в верхней строке таблицы и imagemap - в нижней строке таблицы, т.к. наша картинка имеет формат ландшафта.
Пример: Динамический imagemap
    <SCRIPT>
    <!-- Защитили текст скрипта от старых браузеров
    function print_form(a)
    {
        document.form1.kuku.value = a
    }
    function set_image(a)
    {
        if(a == "bosh")
        {
            document.form1.kuku.value= "Техника фирмы Bosh."
            document.links[5].href = "javascript:print_form(\'Refregarator: Bosh-10245(-24C;Remote Control)\')"
            document.links[6].href = "javascript:print_form(\'Aero-Filter: Bosh-1212(Steel Filter)\')"
            document.links[7].href = "javascript:print_form(\'Oven: Bosh-3432(Варочный стол + духовка)\')"
            document.links[8].href = "javascript:print_form(\'Wash mashine: Bosh-2343(Dry Mode)\')"
            document.links[9].href = "javascript:print_form(\'Dish wash machine: Bosh-DW-44\')"
            document.links[10].href = "javascript:print_form(\'Water pipe: Bosh(Steel + Ceramic)\')"
        }
        if(a == "Indesit")
        {
            document.form1.kuku.value= "Техника фирмы Indesit."
            document.links[5].href = "javascript:print_form(\'Indesit-105(-18C)\')"
            document.links[6].href = "javascript:print_form(\'Indesit-101(Steel Filter)\')"
            document.links[7].href = "javascript:print_form(\'Indesit-3432(Варочный стол + духовка)\')"
            document.links[8].href = "javascript:print_form(\'Indesit-343(Wash only)\')"
            document.links[9].href = "javascript:print_form(\'Indesit-DWR-Safe\')"
            document.links[10].href = "javascript:print_form(\'No in the frame\')"
        }
        if(a == "candy")
        {
            document.form1.kuku.value= "Техника фирмы Candy."
            document.links[5].href = "javascript:print_form(\'Candy-122(-24C;Hidden model)\')"
            document.links[6].href = "javascript:print_form(\'Candy-12(Steel Filter + Carbone Filter)\')"
            document.links[7].href = "javascript:print_form(\'Candy(Варочный стол + духовка)\')"
            document.links[8].href = "javascript:print_form(\'Candy-343(Dry Mode)\')"
            document.links[9].href = "javascript:print_form(\'Candy-DWR Elite\')"
            document.links[10].href = "javascript:print_form(\'Candy(Ceramic)\')"
        }
        document.images[1].src= a+".GIF"
    }
    // -->
    </SCRIPT>

    <MAP name=kitchen_map>
      <area name=freeze shape=rect coords="14,11,88,171" href="javascript:void(0)">
      <area name=aero shape=rect coords="179,12,238,58" href="javascript:void(0)">
      <area name=oven shape=rect coords="179,95,237,172" href="javascript:void(0)">
      <area name=dry shape=rect coords="239,95,297,173" href="javascript:void(0)">
      <area name=wash shape=rect coords="297,96,370,173" href="javascript:void(0)">
      <area name=kran shape=rect coords="90,95,138,172" href="javascript:void(0)">
    </map>
    <TABLE border=0>
    <CAPTION>
      <FONT COLOR="#000099" SIZE=+2>Образцы бытовой техники</FONT>
    </CAPTION>
      <TR>
        <TH>
        <a href="javascript:set_image('bosh')">Bosh</a>
        </th>
        <th>
        <a href="javascript:set_image('idezit')">Indesit</a>
        </th>
        <th>
        <a href="javascript:set_image('candy')">Candy</a>
        </th>
      </TR>
      <TR>
        <th colspan=3><IMG SRC="BOSH.GIF" NAME="tool" USEMAP=#kitchen_map></th>
      </TR>
      <tr><th colspan=3><form name=form1><input name=kuku size=40 value=Выбери набор техники.></form></th></tr>
    </TABLE>
В данном примере меняются не только картинки, но и стеки гипертекстовых ссылок под ними. Для каждой новой картинки определяются свои собственные гипертекстовые ссылки.


About Chm4You!

О программе Chm4You!
Разработчик: Сергей Тарасенко (aka Tarantul)
Версия: Chm4You! 1.2
Веб-сайт: http://supex.by.ru
Почта: tarantuls@ukr.net

Компилятор: hhc.exe 4.78.8702.0 (Microsoft)
Динамическая библиотека: hha.dll 4.78.8702.0 (Microsoft)
Декомпилятор: hh.exe 4.78.8702.0 (Microsoft)