...
...

Программы просмотра и редакторы сценариев

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

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

Взять хотя бы известный практически каждому путешественнику в киберпространстве браузер Netscape Navigator. Вот уже четвертая версия распространяется среди пользователей, а внешне практически все функции полностью совпадают с прошлой, третьей, версией. Разве что внешний вид изменился.

Появление Netscape Navigator 3.0 и новой версии JavaScript 1.1 заставляет составить обзор новых возможностей управления сценариями просмотра web-страниц. В этой версии языка были введены: возможность взаимодействия JavaScript и Java, определение установленных модулей расширений (plug-in), новые типы объектов (Area, Function, Image) и ряд других особенностей, которые, по мнению разработчиков, должны повысить мощь программирования на JavaScript. По своей природе JavaScript - это объектно-ориентированный язык программирования. В отличие от других языков данного типа, JavaScript не оперирует абстрактными объектами. Все его конструкции определены для объектов Navigator. Именно с этих позиций и следует рассматривать развитие самого языка.

Объект навигатора - это либо конструкция HTML, чаще всего контейнер, либо рабочая область программы Netscape Navigator. Если брать конструкции HTML, то каждый контейнер имеет атрибуты, которые в JavaScript рассматриваются в качестве свойств объекта. Над объектами могут быть выполнены некоторые функции, которые в терминах JavaScript называются методами. Помимо методов, существуют и просто функции, которые могут быть определены программистом.

Свойства объектов могут быть переопределены в процессе выполнения программ, что позволяет построить гибкие сценарии просмотра гипертекстовых web-страниц и "оживить" эти страницы. Однако не все свойства переопределяются; некоторые могут быть только прочитаны скриптом, но не изменены в процессе его выполнения.

Таким образом, вместе с развитием конкретной программы просмотра происходит эволюция и языка управления сценариями, который широко применяется в Интернет для самых различных целей. От простого украшательства до организации динамических страниц, страниц "по запросу" и активной обратной связи. Развитие языка идет в направлении расширения типов объектов Navigator, с которыми может манипулировать программист, а также изменения свойств объектов, точнее, расширения возможностей их переопределения.

<P><B><FONT COLOR="#800040"><FONT SIZE=+2>Массивы</FONT></FONT></B> Первым типом новых объектов, которые мы рассмотрим, являются массивы. Тип Array введен в JavaScript 1.1 для возможности манипулирования самыми разными объектами, которые может отображать Navigator. Это список всех гипертекстовых ссылок данной web-страницы, ее картинок, апплетов, список всех элементов формы и т.п. Пользователь может создать и свой собственный массив, используя конструктор Array(). Делается это следующим образом: new_array = new Array() new_array5 = new Array(5) colors = new Array("red", "white", quot;blue").

Размерность массива может изменяться. Можно сначала определить массив, а потом присвоить одному из его элементов значение. Как только это произойдет, изменится и размерность массива: colors = new Array() colors[5] = "red".

В данном случае массив будет состоять из 6 элементов, так как его первым элементом считается элемент с индексом 0.

Для массивов определены три метода: join, reverse, sort. Join объединяет элементы в строку символов. В качестве аргумента в этом методе задается разделитель: colors = new Array("red", "white", quot;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).

<P><B><FONT COLOR="#800040"><FONT SIZE=+2>Графика</FONT></FONT></B> До 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).kg74709a./p> У объекта image существует 10 свойств, из которых самым важным является src. Так, для присваивания конкретных картинок элементам массива img_array следует воспользоваться такой последовательностью команд:kg74709b.p> img_array[0].src="image1.gif"img_array[1].src="image2.gif"...img_array[99].src = "image100.gif".

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

В новой версии языка объект типа image может быть поименован в html-теге img. После этого можно обращаться к нему по имени. Здесь следует учитывать, что если image применяется внутри формы, то он является свойством этой формы. В одном случае для следующего графического объекта должны быть использованы разные составные имена:kg74709d.p> <img name=car src=car.gif><form name=kuku> <img name=car src=car.gif> </form>document.kuku.car.src="car1.gif".

В первом случае задан поименованный объект типа img, а во втором - объект этого же типа, но внутри формы.kg74709f./p> Однако наиболее часто в примерах использования скриптов можно встретить обращение к 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. В этом случае достаточно просто выбрать альтернативу и перейти к новой странице сразу после выбора.

<P><B><FONT COLOR="#800040"><FONT SIZE=+2>Стеки гипертекстовых ссылок</FONT></FONT></B> Значительный толчок в развитии интереса миллионов людей к Интернет произошел после широкого применения разработчиками страниц элементов графики. Кнопок. Движущихся и статичных картинок. С течением времени сайты вообще превратились в произведения изобразительного искусства. Параллельно с этим значительно усовершенствовался инструментарий работы с графикой. Если до недавнего времени любая картинка являлась самостоятельным, но неделимым объектом, то теперь она сама может вмещать в себя самые различные элементы. Например, гиперссылки или меню выбора. В особенности гиперссылки. Это самое наглядное проявление развития языка управления сценариями и возникновения в нем совершенно новых элементов.

Не обошли вниманием авторы 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>.

Таким приемом часто пользуются при программировании событий, связанных с проходом манипулятора (мыши) через поле гипертекстовой ссылки.

<P><B><FONT COLOR="#800040"><FONT SIZE=+2>Фреймы и окна</FONT></FONT></B> При работе с фреймами и окнами в предыдущих версиях JavaScript постоянно приходилось отслеживать последовательность открытия окон и фреймов для того, чтобы аккуратно их потом закрывать. На некоторых неточностях работы с окнами были основаны так называемые mail-bombs. Суть этих "подарков" заключалась в том, что если пользователь по почте принимает документ, который состоит только из одной команды - window.close(), то система, не спрашивая пользователя, закрывала текущее окно, а в этот момент таким окном является окно электронной почты. Теперь перед тем как что-либо закрыть, система будет спрашивать разрешения. Правда, опять-таки не всегда. Если в момент получения команды на закрытие окна на экране только одно окно Navigator, то система его закроет без каких-либо комментариев.

Однако изменения в работе с окнами и фреймами этим не исчерпываются. Во-первых, в систему введено новое свойство opener, которое определено для текущего окна или фрейма, а методы blur и focus распространены на работу с окнами.

Свойство opener определяет окно документа, который вызвал открытие окна текущего документа. Свойство определено для любого окна и фрейма. Если необходимо выполнить некоторые функции по отношению к окну, открывшему данное окно, то можно использовать выражение типа window.opener.[method]. Например, если требуется закрыть окно-предшественник, то можно просто выполнить метод close - window.opener.close().

Точно таким же способом можно изменить содержание этого окна при помощи методов write или writeln. Можно менять и другие свойства объектов в окне-предшественнике. Следующий пример взят из дополнений к спецификации JavaScript компании Netscape Communications: window.opener.document.bgColor="cyan".

В данном случае для окна-предшественника определен светло-голубой цвет фона.

Но самое замечательное, что предшественника можно менять. Таким образом, автор получает возможность открывать и закрывать окна не в строго иерархической последовательности, а произвольно. Управление многооконным интерфейсом в этом случае становится более гибким: window.opener= new_window window.opener = null.

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

Часто при работе с фреймами один из них может быть порожден путем разбиения другого на части. Если при этом потребуется обратиться к окну-предшественнику фрейма-предшественника, то свойство opener здесь незаменимо. В подобной ситуации для закрытия окна с фреймами рассматривался метод загрузки в окно parent страницы терминатора. С появлением свойства opener необходимость в такого рода фокусах отпала.

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

Кроме обращения к различным свойствам окон и фреймов, разработчики расширили действие методов blur и focus с фреймов до окон. Теперь не только фрейм, но и окно может быть сделано текущим при помощи метода focus или, наоборот, переведено в фон при помощи метода blur. В ряде случаев, например при порождении нескольких страниц, обращение к этим функциям бывает довольно полезным.

<P><B><FONT COLOR="#800040"><FONT SIZE=+2>Наследование кода скриптов различными страницами</FONT></FONT></B> Отсутствие какого-либо наследования между различными страницами web-узла заставляло разработчиков перетаскивать из одной страницы в другую довольно большое количество часто используемых функций и переменных. Разговоры о том, что было бы неплохо получить доступ к глобальным ресурсам или возможность определять такие глобальные ресурсы, ведутся с момента появления JavaScript. К сожалению, стройного логичного механизма передачи параметров, функций и переменных от одного окна или фрейма к другому нет и в JavaScript1.1. Однако некоторые шаги в данном направлении сделаны.

У контейнера SCRIPT появился атрибут SRC. Это дает возможность авторам строить своеобразную библиотеку функций, к которым можно обращаться из любой страницы, где будет ссылка на такую библиотеку. Причем вовсе необязательно размещать саму библиотеку на том же сервере, где находятся и гипертекстовые страницы узла. Можно использовать и чужие функции, написанные кем-либо из ветеранов программирования на JavaScript в любой точке земного шара. В атрибуте SRC применяется обычный URL.

Внутри файла скриптов не используются теги SCRIPT. Это обычный файл с применением определений функций и переменных. Естественно, что применение чужих скриптов может обернуться не только полезными приобретениями, но и непредсказуемыми проблемами. В мире программирования термин "троянский конь" не менее известен, чем среди знатоков древневековой истории.

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

Другой новой возможностью работы с функциями стало введение объекта Function. Он порождается конструктором Function: new_Function = new Function(arg1,arg2,...,argn, function_body).

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

Как любой объект, Function имеет свои свойства, но не имеет методов. В качестве свойств функции выступают аргументы и возможность назначения новых свойств через prototype.

В заключение разговора о функциях и наследовании хочется еще раз обратить внимание на свойство opener окон и фреймов. Его можно использовать при обращении к объектам страницы-родителя, что позволяет компенсировать отсутствие наследования и глобальных переменных в JavaScript.

<P><B><FONT COLOR="#800040"><FONT SIZE=+2>Java, JavaScript и включаемые модули</FONT></FONT></B> В новой версии языка есть возможность организовать взаимодействие между Java-апплетами и скриптами JavaScript. Достигается это за счет применения атрибута MAYSCRIPT в контейнере APPLET. Собственно, в JavaScript определен объект типа APPLET, к которому можно обращаться либо по имени, либо по индексу в массиве апплетов. У этого объекта есть только одно свойство - имя. Никакие другие свойства или методы для данного типа объектов не определены. Сами детали взаимодействия апплетов и скриптов лучше всего обсуждать в рамках программирования Java-апплетов. Так что в данной статье мы эти особенности опустим.

Кроме апплетов, JavaScript позволяет работать и с включаемыми модулями. Последние представляют собой массив соответствующего типа, для которого определен ряд свойств. Используя эти свойства, можно определить установленные включаемые модули и их соответствия MIME-типам. Назначать включаемые модули или манипулировать ими нельзя.

<P><B><FONT COLOR="#800040"><FONT SIZE=+2>Что дальше?</FONT></FONT></B> Следуя логике авторов JavaScript и направлениям развития World Wide Web, нужно ожидать появления новых типов объектов и изменения свойств существующих. Кроме того, видимо, появятся глобальные переменные и функции. Порождение абстрактных типов тоже не за горами, хотя не совсем понятно, кто выиграет от такой новации. Постепенно совершенствуется и поддержка встроенных функций на разных платформах. Так, например, функция random() реализована в настоящее время везде, что не исключает использование и своих собственных датчиков случайных чисел.

И еще, скорее всего следует ожидать компилятора JavaScript для клиента. Будет ли данная возможность встроена в Navigator или это будет отдельный модуль, пока не ясно, но появление библиотек функций - движение в этом направлении, что хорошо согласуется с принципами кэширования гипертекстовых страниц.

Если просуммировать все сказанное, то можно проследить некоторые тенденции, очень напоминающие процессы, произошедшие практически со всеми языками программирования. Возникнув по большей части как реализация некоторых теоретических построений, они решали достаточно ограниченный круг задач и не отличались достаточной гибкостью. В случае, если идея оказывалась удачной, то широкий интерес потребителей вызывал эволюцию самого языка. Иногда даже затрагивались и его основополагающие принципы. JavaScript также не является исключением и развивается по уже известным законам. Если при возникновении JavaScript в качестве основного достоинства выдвигались его простота, небольшой набор команд, невозможность перехватить управление клиентским компьютером в связи с отсутствием каких-либо инструментов для этого, то сейчас он уверенно обрастает привычными атрибутами самого обычного языка, например C. Разница заключается лишь в том, что для всех прочих языков требуется отдельный компилятор, а JavaScript обрабатывается любым браузером. Однако радует то, что пока прогресс приводит к значительному улучшению киберпространства и сторонники возврата в каменный век еще долго не смогут одержать верх.

Александр Запольскис

© Компьютерная газета

полезные ссылки
Аренда ноутбуков