Использование JavaScript в проектах IntraWeb.

 

Николай Ренжиглов ®

 

            Использование JavaScript-кода в проектах IntraWeb не обязательно. Все программирование может быть сведено к заданию бизнес-объектов и описанию обработчиков событий в среде IDE Delphi. Такой путь позволяет создавать WEB-проекты любой степени сложности. Тем не менее, поддержка работы с  Java-скриптами в IW-проектах осуществляется  в достаточном объеме. Основная цель такой поддержки общеизвестна - разгрузить сервер и перенести обработку некоторой части логики программы на компьютер клиента.

 

 

Код серверный и код клиентский.

 

            Какая же часть бизнес-кода IW-проекта выполняется на сервере, а какая на клиентском компьютере? Для уяснения этого создадим Stand Alone - приложение с формой, содержащей кнопку. Для обработчика нажатия кнопки запишем такой код:

 

procedure TformMain.IWButton1Click(Sender: TObject);

var

  f        : textfile;

begin

  assignfile(f,'c:\t.txt'); rewrite(f);

  writeln(f,'Мама мыла раму');

  closefile(f);

end;

 

            Очевидно, что запись файла будет выполняться на серверном компьютере: после нажатия кнопки клиентом, администратор сервера обнаружит "неожиданно" появившийся на его компьютере файл t.txt.

Заставим обработчик выполнять более "безобидный" код, например:

 

procedure TformMain.IWButton1Click(Sender: TObject);

begin

  IWButton1.Caption:='кнопка нажата';

end;

 

Запустим проект и нажмем на кнопку. Текст на кнопке изменится и, при этом мы заметим, что происходит какая-то задержка, в течение которой WEB-страница перерисовывается. Остановим Stand Alone IW-сервер перед нажатием кнопки (например, если проект работает в режиме отладки в Delphi, нажмем Ctrl+F2). Далее нажмем кнопку на нашей WEB-странице и получим сообщение о том, что HTTP-сервер не найден.

Поразительно! Для того, чтоб изменить заголовок кнопки, система использует работу IW Stand Alone-сервера c получением запроса и возвратом новой страницы. Это представляется довольно тяжеловесным и именно по этой причине в подобных случаях удобнее применять программирование на JavaScript.

Если вы не использовали ранее приемы WEBSnap-программирования, то привыкание к совместному использованию Delphi и языка скриптов может потребовать определенного времени. Однако потраченные усилия стоят того -  в IW такое совместное использование позволит вам создавать  гибкие и мощные WEB-приложения.

 

 

Запись обработчика на JavaScript[1].

 

В тексте HTML-страницы мы обнаружим следующий Java-код, имеющий отношение к нашей кнопке:

 

function IWBUTTON1_OnClick(ASender) {

return SubmitClickConfirm('IWBUTTON1','', true, '');

}

 

Здесь SubmitClickConfirm является некой внутренней JScript-функцией IW Stand Alone-сервера. Она часто используется в серверной обработке, но что и как она делает, мы обсудим позднее. Здесь важно лишь то, что посредством результата, возвращаемого этой функцией, в обработку события вовлекается сервер.

Устраним из Delphi-проекта код, обрабатывающий нажатие кнопки для того, чтоб в дальнейшем перенести его в JavaScript-часть. Для этого:

 

·       Полностью устраним текст обработчика TformMain.IWButton1Click в  Delphi (то есть не просто закроем комментариями или еще каким-либо образом). Важно, чтоб кода обработчика вообще не существовало, иначе система ведет себя несколько иначе, чем ожидается.

·       В инспекторе объектов для кнопки выберем  свойство ScriptEvents и для обработчика события  OnClick запишем JavaScript-код:

 

 

 

Запустим проект на выполнение и обнаружим, что при нажатии на кнопку программа выполняется без вовлечения в процесс сервера. Текст HTML-страницы, имеющий отношение к нашей кнопке, теперь выглядит так:

 

            function IWBUTTON1_onClick(ASender) {

ASender.value='кнопка нажата'}

 

Возвращаемое значение JScript-функции не определено, а значит система трактует его как false. Заставим функцию возвращать значение true, для чего проделаем два исправления в коде:

 

·       Delphi. Восстановим обработчик TformMain.IWButton1Click и запишем какой-либо код, требующий перезагрузки HTML-документа, например:

procedure TformMain.IWButton1Click(Sender: TObject);

begin

  IWButton1.Caption:='кнопка нажата';

end;

·       JScript. Явно укажем, какое значение должна возвращать JScript-функция:

            function IWBUTTON1_onClick(ASender) {

  ASender.value='кнопка нажата';

  return true;

}

 

 

Управление будет передано сначала JScript-коду, а затем, поскольку он вернул значение true, Delphi-обработчику события. В результате и клиентский и серверный код будет выполнен.

 

Подводя итог, можно сказать, что JScript-код IW-компонента может выполнять любой бизнес-код проекта, но если мы хотим после выполнения этого кода на клиентском компьютере решать вопрос о вовлечении в процесс сервера, необходимо возвращать из JScript-части значение функции true (Delphi-обработчик выполняется, документ передается на сервер) или false (соответственно не выполняется и не передается).

 

 

Свойство ScriptEvents.

 

            События ScriptEvents генерируют следующие IW-классы:

 

 

Эти классы, в итоге, реализуют визуальные компоненты (элементы) WEB-форм, события которых могут быть обработаны с использованием JavaScript прямо на клиентском компьютере. Как мы видели выше, в JavaScript-обработчике нет необходимости записывать объявления function. Эта часть кода добавляется IW автоматически. Тем не менее, необходимость помнить о формате передаваемых параметров, существует. Параметр ASender хранит элемент WEB-формы, событие которого подлежит обработке. Вы можете обработать следующие общие свойства:

 

Свойство элемента

Тип

Описание

Name

Строковая константа

Содержит имя элемента на WEB-форме.

Value

Строковая константа

Содержит значение элемента

default[2]

Строковая константа

Содержит начальное значение поля

 

Множество членов (методов, событий и свойств) ASender зависит от того, какой объект страницы вызывает обработчик. Как правило, фактическим параметром вызова является объект this - аналог объявления self в Оbject-Pascal:

 

function IWBUTTON1_onClick(ASender) {

ASender.value='кнопка нажата'

}

 

….

 

Вызов из HTML-кода:

<input value="IWButton1" name="IWBUTTON1" type="button" 

onclick="return IWBUTTON1_onClick(this);"

id="IWBUTTON1" class="IWBUTTON1CSS">

….

 

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

 Список событий, перечисленных в свойстве JavaScript, не требует пояснений. Все они стандартны и подробно описаны в многочисленных источниках по JavaScript (например, [[3]]). Вопрос возникает, например, в таком случае: что произойдет, если задать обработчик для события, не вырабатываемого компонентом? Например, кнопка не вырабатывает событие onChange. Это событие характерно для INPUT-компонентов формы и вырабатывается, когда INPUT-поле теряет фокус ввода, и при этом пользователь изменил текст, содержащийся в этом поле (такое событие в подавляющем большинстве случаев используется для проверки данных в поле). Тем не менее, Delphi позволяет вписать код обработчика onChange для кнопки.

Ответ в этом случае прост: ничего не произойдет. WEB-форма просто будет содержать функционально-избыточный код, который никогда не будет выполняться.

 

 

Свойство JavaScript для IW-формы.

 

JavaScript-функции могут быть описаны в отдельном месте - свойстве формы JavaScript. Выберем это свойство и заполним его следующим кодом, например:

 

function CheckLength(ASender) {

 if (ASender.value.length < 6)

 {

   alert("Слишком короткое имя");

 }        

}

           

Поместим на форму строку ввода IWEdit и в его свойстве ScriptEvents зададим код для события onChange:

 

CheckLength(this)

 

Запустим проект на выполнение и в строке ввода наберем текстовое значение длиной менее 6 символов. При попытке переместить фокус на другой элемент формы или вообще закрыть ее будет вырабатываться сообщение "Слишком короткое имя". Обработка сообщения осуществляется в модальном окне. После обработки фокус ввода сохраняется за элементом ввода, пославшим сообщение.

 

 

Свойство JavaScript и ExtraHeader для IW-формы.

 

Поскольку JScript-код можно поместить в любом месте внутри тега <Header>, свойство ExtraHeader также может быть использовано для записи функций на языке JavaScript. В этом случае код функций требует описания языка программирования и его версии, например:

 

<script language="Javascript1.2">

function CheckLength(ASender)

{

 if (ASender.value.length < 6)

 {

   alert("Слишком короткое имя");

 }        

}

</script>

 

Вызов функции посредством обработки события onChange для строки ввода остается без изменений.

 

Объекты HTML-формы.

 

            Компоненты формы в JScript- процедурах могут быть доступны посредством их имен, определяемых в IntraWeb как ИМЯ_КОМПОНЕНТА{IWCL}. Например, строка ввода IWEdit1 будет доступна посредством имени  IWEDIT1IWCL, кнопка IWButton1  посредством IWBUTTON1IWCL и т.д. Очевидно, что эти компоненты будут иметь совершенно другие имена для их свойств и методов, определенных в JavaScript.

            Работа со свойствами может выглядеть, например для кнопки, следующим образом:

 

IWBUTTON1IWCL.style.color='brown';

 

Подобный код может быть записан как в самом обработчике ScriptEvents для компонента, так и в тексте JavaScript или ExtraHeader для IW-формы.

 

 

 

Пример работы с объектами HTML-формы и IW-компонентами.

 

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

 

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

 

Разместим на форме Stand Alone-проекта компонент IWEdit и кнопку для отправки формы. Раскроем список JScript-событий для кнопки и для события onClick запишем обработчик:

 

IWEDIT1IWCL.value = screen.Height;

return true;

 

Обработчик присваивает текстовому полю IWEdit1.Text значение высоты экрана клиентского компьютера в пикселах. Определим public-поле для формы с именем UserHeight, которое будет содержать переданное значение. Статус public позволит использовать содержимое этого поля в серверном коде как этой формы, так и других форм проекта.

 

type

  TIWForm1 = class(TIWAppForm)

    IWEdit1: TIWEdit;

    IWButton1: TIWButton;

    procedure IWButton1Click(Sender: TObject);

public

    UserHeight        : string;

end;

 

 

 Кроме того, зададим Delphi-обработчик для кнопки:

 

procedure TIWForm1.IWButton1Click(Sender: TObject);

begin

  UserHeight:=IWEdit1.Text;

end;

 

Дальнейшая работа программы не требует подробных объяснений. При нажатии на кнопку управление получает JScript-обработчик события. Строка ввода получает значение высоты экрана в пикселах, например, "600". Поскольку обработчик возвращает значение true, управление передается серверу и выполняется присвоение переменной UserHeight, равное "600" в процедуре IWButton1Click.

 Таковы общие принципы взаимодействия компонентов HTML-формы и IW, а также серверного и клиентского JScript-кода в IntraWeb-приложении.

 

 

 

Предопределенные функции.

 

В IntraWeb разработано большое количество JScript-функций, используемых при работе сайта. Для того, чтоб ознакомиться с ними, вы можете использовать файлы IWCL.js_*, IWExplorer.js_*, IWCommon.js_* (здесь значок "*" означает номер используемой IW-версии), расположенные в папках временного хранения файлов, загруженных из интрасети. Эти функци можно вызывать напрямую из JScript-обработчиков событий. Приведем несколько примеров.

 

Status(Stat). Функция отображает текст Stat в строке статуса WEB-браузера, например, Status("Не все поля заполнены");

 

FindElem(EName). Функция возвращает объект по его имени EName. Пример использования:

 

var df=FindElem("IWEDIT1");

if (df.value == "On")

{

df.value = "Off"

};

 

SubmitClickConfirm. Используется для подтверждения введенных в компоненты формы значений. Параметры вызова следующие:

function SubmitClickConfirm(AObjectName, AParam, ADoValidation, AConfirmation)

 

AObjectName - текстовое имя объекта, для которого осуществляется проверка.

AParam - параметр действия на форме.

ADoValidation- указывает признак того, нужна ли проверка.

AСonfirmation- строка, отображаемая при проверке.

 

Эта функция вызывается автоматически, когда вы задаёте строку Confirmation для компонента. Например, нажатие на кнопку с определенным таким образом свойством, вызовет появление диалогового окна с предложением подтвердить нажатие или отменить его. Любой JScript- код, записанный в обработчике onClick не будет вызываться в случае отказа. И, соответственно, любой код будет вызываться и форма будет отправлена на сервер в случае подтверждения нажатия.

Можно вызвать эту функцию "вручную" с тем же самым эффектом, вставив ее в Jscript-обработчик onClick, например:

 

 SubmitClickConfirm("IWBUTTON1", "", true, "Переслать форму?");

 

В этом случае вы получаете возможность анализировать возвращаемый код и строить соответствующим образом JScript-часть бизнес-логики.

 

 Обратите внимание, что имя объекта IWBUTTON1, а также IWEDIT1 (пример для FindElem) записано в другом формате, нежели это заданно разработчиками IW и рассмотрено в разделе " Объекты HTML-формы ".

 



[1] VBScript в качестве языка скриптов в рассматриваемых версиях IW не поддерживается.

[2] Только для полей типа Input

[3] Джерри Бранденбау. "JavaScript: сборник рецептов". Издательство "Питер" 2000 год.