Java & JavaScript: принципы и приемы взаимодействия
Рассматриваемые в этой статье возможности подразумевают использование в качестве броузера Netscape Navigator 3.0 или выше. Предполагается, что читатели владеют основами JavaScript и Java.
Известно, что языки JavaScript и Java расширяют возможности представления и обмена информацией на Ваших web-страницах. Но есть ограничения, которые накладываются при использовании этих языков. Вот несколько из них:
Для JavaScript
- Поле деятельности жестко ограничивается рамками броузера: все, что существует за его пределами, для JavaScript не существует вовсе. Обмен информацией с внешним миром возможен только при использовании различных HTML-расширений серверов (единого стандарта для которых нет вовсе), CGI и переменной location.search (Решение)
- Почти никаких функций для работы с изображениями (за исключением смены картинки в документе при помощи поля src объекта Image) (Решение)
- Интерфейс (за исключением форм) статичен и негибок (Решение)
Для Java
- Отсутствует возможность динамической генерации документов (Решение)
- Отсутствует поддержка E-Mail (если не установлены специальные библиотеки, распространяемые отдельно от JDK) (Решение)
- До сих пор не решена проблема отображения символов русского алфавита (если не используется СУБД) (Решение)
Но... Можно заметить, что эти ограничения, накладываемые на один из языков, так или иначе обходятся в другом. Таким образом, обеспечив взаимодействие JavaScript-кода с Java-апплетами, можно еще более повысить гибкость Ваших страниц. В этой статье кратко описывается, как это делается, и даются примеры.
Для того, чтобы разрешить взаимодействие JavaScript и Java, Вам необходимо включить опции Enable Java и Enable JavaScript в меню Options|Network Preferences...|Languages.
Взаимодействие JavaScript и Java-апплетов может осуществляться тремя способами:
- Доступ из JavaScript к переменным, методам, классам и пакетам Java
- Управление Java-апплетами и внедренными объектами (plug-ins)
- Доступ из Java-апплетов к методам и свойствам JavaScript
Классы пакета netscape:
- JSObject
- JSException
Доступ из JavaScript к переменным, методам, классам и пакетам Java
Для доступа к классам и пакетам Java в JavaScript есть
объект Packages
. Используя свойства этого
объекта, можно получить доступ к любому классу
любого пакета, поддерживаемого навигатором.
Напр., для доступа к пакетам java
, sun
и netscape
используются следующие операторы: Packages.java
,
Packages.sun
, Packages.netscape
. Строго говоря,
при обращении к этим трем пакетам использование Packages
необязательно, чего нельзя сказать об остальных
пакетах. Так, Packages.java.lang.System.out.println(myString)
эквивалентно java.lang.System.out.println(myString)
.
Пример:
var myDate = new java.util.Date(); var wnd = open(); var doc = wnd.document; doc.open(); doc.write(""); doc.write("var myDate = new java.util.Date();"); doc.write("function showStat(param) {"); doc.write("alert(param)}"); doc.write(""); doc.write(myDate + "<br>"); for (var i in myDate) doc.write("<a href='javascript:showStat(myDate." + i + "())'>" + i + "</a><br>"); doc.write("<p><a href='javascript:close()'>Закрыть</a>"); doc.close();
Нажав на кнопку, можно увидеть все переменные и методы вновь созданного объекта (внимание! нажатие на гиперссылку в создаваемом документе успешно выполнит только те методы, которые не принимают параметров (почему, видно из кода выше)):
Внимание! Не используйте любые методы Java, которые могут бросать исключения, т.к. в JavaScript нет обработки исключений, и код, вызывающий такие методы, не пройдет: будет выведено соответствующее сообщение
Управление Java-апплетами и внедренными объектами
Для обращения к Java-апплетам в документе можно использовать один из трех путей:
- Обращение по имени апплета (указанному в
параметре NAME тэга APPLET):
document.appletName
- Обращение по индексу в массиве applets:
document.applets[index]
- Обращение по имени апплета в качестве индекса в
массиве applets:
document.applets["appletName"]
Напр., если в документе присутствует
единственный апплет:
<APPLET CODE=MyAplet.class NAME="myapplet" ...> ...</APPLET>
то следующие три фрагмента кода вернут ссылку
на данный апплет:
После получения ссылки на апплет можно получить доступ к любым общедоступным (public) переменным и методам этого апплета.
Пример:
- Исходный текст апплета:
import java.awt.*; import java.applet.Applet; public class myapplet extends Applet { public String myString; TextField myField; public void init() { setLayout(new BorderLayout()); myField = new TextField(); myField.setEditable(false); add("Center", myField); setString("Initial string"); } public void setString(String s) { myField.setText(s); } }
- Фрагмент HTML-кода:
<APPLET CODE=myapplet.class WIDTH=150 HEIGHT=25> </APPLET> <FORM> <INPUT TYPE="text" NAME=mytext SIZE=50> <INPUT TYPE="button" VALUE="Вычислить выражение" onClick="document.applets[0].setString(eval(this.form.mytext.value))"> </FORM>
Нажатие на кнопку вызовет установку текста в апплете равным вычисленному выражению в поле ввода формы.
Внедренные объекты
Внедренные объекты (аудио- и видеофайлы WAV, AU, AVI...) вставляются в документ при помощи тэга EMBED (должен быть установлен соответствующий plug-in). Синтаксис:
<EMBED SRC="URL" [WIDTH=widthValue] [HEIGHT=heightValue]>
ЗдесьURL
- URL внедряемого объекта.
Параметры widthValue
и heightValue
- размер
панели для размещения объекта. Используйте
размеры 140 и 60 соответственно для полного показа
панели и 2 и 2 для скрытия панели. (Установка
размеров в 1x1 или 0x0 в действительности не
принесет желаемого результата). Использование
параметра NAME не рекомендуется, т.к. при этом часто
блокируется работа внедренного объекта (скорее
всего, это ошибка в раелизации Netscape Navigator 3.0) autostart=booleanValue
- при загрузке объекта он сразу воспроизводится
(действительно только для объектов, которые
можно воспроизводить)loop=booleanValue
- при true
воспроизведение
пойдет по циклу (до покидания документа или
вызове метода stop
Доступ к внедренным объектам осуществляется
при помощи массива document.embeds[index]
, где в
качестве index
следует указать индекс
объекта (0 соответствует первому внедренному
объекту, 1 - второму, ... , document.embeds,length - 1 -
последнему).
Чаще всего внедренный объект порождается от
класса netscape.plugin.Plugin
. В этом случае Вы
можете использовать общедоступные переменные и
методы данного класса для управления объектом.
Кроме этого, каждый тип внедренного объекта
может иметь свои собственные переменные и
методы. Следующий код позволяет узнать, какие из
них доступны в конкретном случае:
var myEmbed = document.embeds[myIndex]; var s = myEmbed + "\n"; for (var i in myEmbed) s += i + " = " + myEmbed[i] + "\n"; alert(s);
Общими для всех внедренных объектов являются следующие методы:
getWindow()
- возвращает окно, содержащее документ, в который внедрен данный объектisActive()
- определяет, является ли данный объект активным в данный моментPlugin()
- конструктор
Остальные, не указанные здесь, методы
используются в основном разработчиками новых
внедряемых объектов (plug-ins). Вы не должны их
вызывать.
Кроме этого, наиболее часто в объектах
присутствуют три метода, которые обеспечивают
основные функции управления:play()
- воспроизводит клип (если он таковым
является) (при задании в качестве параметра
функции true
воспроизведение происходит в
режиме LOOP)stop()
- останавливает воспроизведение,
"перематывая" клип в началоpause()
- приостанавливает воспроизведение.
После этого при вызове play()
воспроизведение продолжится с того места, где
было приостановлено
Доступ из Java-апплетов к методам и свойствам JavaScript
Для того, чтобы разрешить Java-апплетам доступ к методам и свойствам JavaScript, необходимо в тэге APPLET указать атрибут MAYSCRIPT, иначе будет бросаться исключение. Для доступа к JavaScript необходимо импортировать пакет Netscape javascript:
import netscape.javascript.*;
При этом в переменную окружения CLASSPATH
необходимо добавить путь к файлу с пакетами,
поставляемыми с Netscape Navigator. Напр., если Netscape Navigator
установлен в каталог c:\Program Files\Navigator
, в
CLASSPATH необходимо добавить (для Netscape Navigator Gold) c:\Program
Files\Navigator\Program\Java\CLASSES\java_301
Пакет javascript определяет класс JSObject для описания объектов JavaScript и исключение JSException, бросаемое при ошибке во время обращения к объектам JavaScript.
Перед тем, как Вы сможете получить доступ к JavaScript, Вам необходимо получить ссылку на окно (объект window), содержащее апплет:
JSObject win = JSObject.getWindow(this)
Лучше всего включить этот оператор в функцию init() апплета.
Получить доступ к объектам и свойствам JavaScript можно одним из следующих способов:
- Применив функцию
eval
объекта window:JSObject win = JSObject.getWindow(this); JSObject myForm = (JSObject)win.eval("document.myForm");
- Использовать метод
getMember
объекта JSObject для доступа к свойствам объектов JavaScript:JSObject win = JSObject.getWindow(this); JSObject doc = (JSObject)win.getMember("document"); JSObject myForm = (JSObject)doc.getMember("myForm");
Вызвать методы объектов JavaScript можно одним из следующих способов:
- Применив функцию
eval
:JSObject win = JSObject.getWindow(this); win.eval("alert('My message !')");
- Применив функцию
call("methodName", argumentsArray)
объекта JSObject:JSObject win = JSObject.getWindow(this); String argums[] = new String[1]; argums[0] = "My message"; win.call("alert", argums);
Данный способ позволяет вызвать не только методы объекта JavaScript, но и определенные пользователем функции (для чего используйте функцию
call
объекта winddow). Если функция/метод не принимает параметры, в качестве второго параметра функцииcall
указывается пустой массив:JSObject win = JSObject.getWindow(this); JSObject nav = (JSObject)win.getMember("navigator"); String argums[] = (""); nav.call("javaEnabled", argums);
Преобразование типов от Java к JavaScript:
- Java-типы byte, char, short, int, long, float и double преобразуются в числа JavaScript
- Java-тип boolean преобразуется в boolean JavaScript
- Java-тип JSObject преобразуется в соответствующий объект JavaScript
- Прочие Java-объекты преобразуются в
объекты-надстройки JavaScript для доступа к полям и
методам этих объектов. Java-объекты могут быть
преобразованы в строку (вызывается метод
Java-объекта
toString
). Если происходит преобразование в число, вызывается метод Java-объектаfloatValue
(который бросит исключение, если такое преобразование невозможно). Аналогично происходит преобразование в boolean (методbooleanValue
) - Java-массивы преобразуются в псевдо-массивы JavaScript (которые в действительности ведут себя точно так же, как и JavaScript-массивы, где в качестве индекса используются целые числа, но устроены по другому)
Преобразование типов от JavaScript к Java:
- Объекты-надстройки для Java-объектов преобразуются в Java-объекты
- Остальные объекты преобразуются в JSObject
- Строки, числа и boolean преобразуются соответственно в Java-объекты String, Float и Boolean
JSObject - объект JavaScript
Любой объект JavaScript в Java-апплетах
представляется потомком класса JSObject
(подробнее см. Доступ из Java-апплетов к
методам и свойствам JavaScript)
Методы класса JSObject
:
public Object call(String methodName, Object args[])
вызывает метод
methodName
объекта JavaScript с аргументамиargs[]
. Эквивалентен JavaScript-коду:this.methodName(args[0], args[1], ...)
public Object eval(String s)
вычисляет выражение
s
, являющееся любым допустимым выражением JavaScript. Вычисление производится в контексте объекта. Напр., кодJSObject win = JSObject.getWindow(this); JSObject doc = (JSObject)win.eval("document");
в переменную
doc
занесет JavaScript-объект documentpublic Object getMember(String name)
возвращает поле-член JavaScript-объекта. Аналогичен JavaScript-коду
this.name
. Напр., кодJSObject win = JSObject.getWindow(this); JSObject doc = (JSObject)win.getMember("document");
в переменную
doc
занесет JavaScript-объект documentpublic Object getSlot(int index)
Возвращает индексированный элемент массива (если объект им является). Аналогичен JavaScript-коду
this[index]
. Напр., кодJSObject win = JSObject.getWindow(this); JSObject frames = (JSObject)win.getMember("frames"); JSObject frame1 = (JSObject)frames.getSlot(0);
в переменную
frame1
занесет первую (т.е. с индексом 0) рамку окнаpublic static JSObject getWindow(Applet applet)
Возвращает JavaScript объект-окно, в котором выполняется апплет. Рекомендуется вызывать первым при взаимодействии с JavaScript
public void removeMember(String name)
Удаляет поле-член JavaScript-объекта с именем
name
public void setMember(String name, Object value)
Устанавливает значение поля-члена с именем
name
вvalue
. Эквивалентен JavaScript-кодуthis.name = value
public void setSlot(int index, Object value)
Устанавливает значение индексированного элемента с индексом
index
вvalue
. Аналогичен JavaScript-кодуthis[index] = value
public String toString()
Преобразует объект JSObject в String
JavaScript: обмен информацией с внешним миром
Как известно, Java-апплеты могут обмениваться информацией с тем сервером, откуда он загружен, а если создать соответствующее серверное приложение, то через него и с любым сервером. (Очень хороший пример такого приложения - IDS Server компании IDS Software, взаимодействующий с апплетами с помощью пакетов ids.sql и с серверами или локальными базами данных через систему псевдонимов). Для того, чтобы код JavaScript мог воспользоваться такими возможностями, достаточно в апплете опреденить public-функцию, осуществляющую необходимый способ обмена информацией. После этого JavaScript вызывает данную функцию апплета, когда нужно.
JavaScript: работа с графикой
С помощью Java можно рисовать как на поверхности визуальных компонентов, так и на поверхности изображений (класс Image). Рисование происходит посредством объекта Graphics, являющегося одним из свойств класса Image. Из JavaScript можно напрямую вызывать функции объекта Graphics, предварительно создав в апплете public-переменную:
Graphics myGraph = myImage.getGraphics();
Таким же образом осуществляется рисование на поверхности компонентов апплета.
JavaScript: гибкий интерфейс
Обычно для поддержки взаимодействия с пользователями бывает достаточно использовать формы. Однако часто бывают ситуации, когда возможностей, предоставляемых формами, недостаточно. К тому же в случаях, когда во взаимодействии участвуют несколько HTML-документов (при большом числе вводимых параметров и необходимости динамически изменять последовательность действий), пользователям приходится много времени ждать загрузки тех или иных документов или блоков информации. Все это решается достаточно тривиально с использованием апплетов: хотя апплеты загружаются дольше обычных компонентов документа, это происходит один раз за сессию работы с броузером, а потом работают достаточно быстро. При этом можно создать один документ и все взаимодействие сосредоточить в нем.
Например, если количество вводимых параметров велико, можно установить для апплета (или какой-либо его панели) менеджер компоновки CardLayout и размещать интерфейсные элементы на его страницах (что является аналогом диалоговых окон в виде блокнота с закладками в Windows).
Если же необходимо динамически изменять последовательность действий и/или интерфейсные элементы, то делается это еще проще. В апплетах для изменения набора выводимых элементов предназначены такие функции класса Container, как void remove(Component comp) (для удаления из контейнера элемента comp), void removeAll() (для удаления из контейнера всех элементов) и Component add(Component comp [, int index]) (для добавления нового элемента). И связанная с этим последовательность действий легко изменяется.
Java: динамическая генерация документов
Часто бавает необходимо из Java-апплетов влиять на внешний вид документа в зависимости от некоторых условий (такие условия могут возникнуть в то время, когда документ уже загружен). Например, нужно создать какую-либо таблицу в ответ на введенные пользователем данные. Если контакт апплет загружен с СУБД-сервера, последний может (но не всегда) предоставить некоторые функции для динамической генерации документов. К сожалению, набор таких функций очень ограничен и неудовлетворителен. В других случаях дела обстоят еще сложнее. Таким образом, мы можем в апплете воспользоваться возможностями JavaScript в области создания документов. Для этого есть функция document.write(...). Грамотно используя данную функцию можно построить документ (почти) любой сложности на лету.
Java: поддержка E-Mail
Из JavaScript есть возможности послать сообщение по E-Mail. Есть для этого три способа:
- Открывается стандартное окно ввода и отправки
сообщения при щелчке на ссылке. Решение для
Java-апплетов (если в документе есть ссылка
наподобие
<A HREF="mailto:rbravant@yahoo.com" NAME=myMail>Send me</A>
):JSObject win = JSObject.getWindow(this); JSObject doc = (JSObject)win.getMember("document"); JSObject myMail = (JSObject)doc.getMember("myMail"); myMail.call("click", null)
Если в тексте ссылки ничего не указать, то ее не будет видно на экране, но она будет функционировать. - Вызывается функция click() кнопки submit
формы, в которой в качестве action установлен
E-Mail адрес (например, все тот же mailto:rbravant@yahoo.com).
Решение для Java-апплетов:
JSObject win = JSObject.getWindow(this); JSObject doc = (JSObject)win.getMember("document"); JSObject myForm = (JSObject)doc.getMember("formName"); myForm.call("submit", null);
- Открывается стандартное окно ввода и отправки
сообщения при присваивании location.href значения
E-Mail адреса. Решение для Java-апплетов:
JSObject win = JSObject.getWindow(this); JSObject location = (JSObject)win.getMember("location"); location.setMember("href", "mailto:rbravant@yahoo.com");
Java: проблема символов русского алфавита
На самом деле существуют особые механизмы, которые позволяют работать с кириллицей несмотря на то, что в Java такая поддержка отсутствует. Они достаточно нетривиальны, и их рассмотрение выходит за рамки обсуждаемой темы. Есть легкий путь с применением JavaScipt вывода кириллицы в апплете. (Текст, введенный в апплет, может также успешно быть отправлен на сервер, хотя никакой гарантии в этом нет.) Решение таково: в документе в секции SCRIPT определяется ряд переменных с текстом на русском языке (не забудьте защитить символы я и ч обратным слэшем). Получить к ним доступ из апплета не составит труда.
Оставить комментарий
Комментарии
[quote]Для Java:
1. Отсутствует возможность динамической генерации документов [/qoute]
В Java есть (и не одна) технология создания динамических страниц, способных обрабатывать даже очень сложные запросы пользователя (Java Server Pages, Servlets). А вот Java-апплеты такой возможности действительно не предоставляют.
Так что не стоит говорить о Java-апплетах, представляющих собой одну из множества технологий Java, как о платформе Java в целом.