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-апплетов может
осуществляться тремя способами:
Классы пакета netscape:
Доступ из 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("<" + "script language="JavaScript1.1">");
doc.write("var myDate = new java.util.Date();");
doc.write("function showStat(param) {");
doc.write("alert(param)}");
doc.write("<" + "/script>");
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>
то следующие три фрагмента кода вернут ссылку
на данный апплет:
- var aplt = document.myapplet
- var aplt = document.applets[0]
- var aplt = document.applets["myapplet"]
После получения ссылки на апплет можно
получить доступ к любым общедоступным (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-объект
document
public Object getMember(String name)
возвращает поле-член JavaScript-объекта. Аналогичен
JavaScript-коду this.name . Напр., код
JSObject win = JSObject.getWindow(this);
JSObject doc = (JSObject)win.getMember("document");
в переменную doc занесет JavaScript-объект
document
public 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 определяется ряд
переменных с текстом на русском языке (не
забудьте защитить символы я и ч обратным
слэшем). Получить к ним доступ из апплета не
составит труда.
|