Mashup-страницы, больше чем просто отчеты

Создание виджета HTML-формы для использования с табличными фидами IBM Mashup Center

У разработчиков самых разных специализаций периодически возникает необходимость создания приложений, выполняющих простые обновления таблиц базы данных. В этой статье рассказывается, как создать виджет IBM® Mashup Center в виде HTML-формы, позволяющей пользователям обновлять таблицы реляционной базы данных. Кроме того, вы сможете быстро создать собственную mashup-страницу с помощью доступного для загрузки тестового виджета, связав его с вашей HTML-формой.

Луиc Мау, архитектор решений, IBM

Луиc Мау (Louis Mau) является членом группы разработки InfoSphere MashupHub. В настоящее время занимается оказанием помощи клиентам в создании ситуационных приложений, использующих IBM Mashup Center. До этого занимался разработкой сервера DB2 Everyplace Sync Server, который помогает синхронизировать данные корпоративных баз данных с небольшими базами данных, работающими на мобильных устройствах.



Клаус Родер, архитектор решений, IBM

Клаус Родер (Klaus Roder) – архитектор решений для IBM Mashup Center, работает в лаборатории IBM, расположенной в Силиконовой долине. Его основной задачей является разработка и развертывание у заказчиков корпоративных mashup-приложений на основе IBM Mashup Center. Ранее Клаус был участником группы разработчиков, занимавшихся такими проектами как IBM Web Interface for Content Management (WEBI) и WebSphere Information Integrator Content Edition (IICE). Клаус имеет степень магистра в области вычислительной техники, полученную в университете прикладных наук г. Вюрцбург, Германия, а также является членом местного отделения Ассоциации по вычислительной технике (ACM) района залива Сан-Франциско.



06.09.2012

Краткий обзор

У разработчиков самых разных направлений периодически возникает необходимость создания приложений, выполняющих простые обновления таблиц базы данных. Начиная со второй версии IBM Mashup Center, вы легко можете создать табличный (JDBC) фид, который может выполнять простые SQL-команды INSERT, UPDATE или DELETE. В этой статье рассказывается, как создать виджет, помогающий использовать такие фиды в mashup-приложениях.

Предполагается, что вы уже знакомы с созданием mashup-приложений и фидов, а также с основами написания виджетов. В частности, вы должны уметь программировать на JavaScript и иметь опыт работы с IBM Mashup Center. В разделе Ресурсы вы найдете ссылки на две статьи, которые помогут вам быстрее разобраться с некоторыми основами создания mashup-приложений: "Создание фидов на основе базы данных предприятия (JDBC)" и "Разработка виджетов для IBM Mashup Center".

Поддержка баз данных в IBM Mashup Center

IBM Mashup Center включает в себя компоненты InfoSphere MashupHub и Lotus Mashups. В его состав также входит готовый генератор табличных фидов, предназначенных для получения данных из самых распространенных СУБД, включая DB2®, Informix® и IMS™.

Табличные фиды обновлений

В IBM Mashup Center вы можете создать фид на основе данных, полученных в результате выполнения реляционного запроса. Фид создается путем выбора требуемых таблиц и столбцов, либо путем выполнения SQL-запроса к базе данных. Фид создается на основе результирующего набора данных, возвращаемого в ответ на запрос.

Начиная со второй версии IBM Mashup Center, в дополнение к использованию SQL-оператора SELECT вы можете использовать генератор табличных фидов для выполнения SQL-команд INSERT, UPDATE или DELETE. Выполняться может только одиночный SQL-оператор, поэтому данная возможность не может быть использована для выполнения сложных транзакций. Тем не менее, вы можете использовать эту возможность для обновления данных во многих относительно простых сценариях, таких как:

  • Создание снимков состояния для проведения трендового анализа. Предположим, что у вас имеется фид, возвращающий общее количество заказов на каждый день. Сохраняя содержимое фида в таблицу базы данных, вы можете сгенерировать фид, описывающий динамику заказов. С помощью mashup-редактора вы можете создать mashup данных, содержащий оператор FOREACH, для вставки (INSERT) содержимого каждой повторяющейся записи в его собственную строку.
  • Сохранение комментариев или заметок. Например, можно написать простое приложение-опрос для сбора информации о мнениях или предпочтениях пользователей.
  • Разработка формы для работы с ToDo-перечнями, которые сохраняются в базе данных.
  • Разработка формы для приема запросов на техническую поддержку. Например, это могут быть запросы на разработку приложений, установку оргтехники или обслуживание ИТ-инфраструктуры.

В некоторых случаях создание mashup-страницы для использования простого табличного фида обновлений может оказаться непростым делом. Например, для генерации управляющих элементов, таких как текстовые поля, можно было бы использовать виджет User Input из состава IBM Mashup Center. Однако этот виджет не может напрямую обращаться к табличному фиду обновлений; кроме того, не существует виджета, который мог бы выводить полученные результаты в удобной форме.

Из этой статьи вы узнаете, как создать пользовательский виджет, упрощающий использование табличных фидов обновлений в случаях, подобных второму из перечисленных сценариев. Этот виджет использует HTML-форму в качестве конфигурационного параметра. Он обрабатывает форму, помещает ее данные в табличный фид обновлений и выводит статус операции обновления. Поскольку данный пользовательский виджет может работать с произвольным фрагментом HTML-формы, вы можете уделить больше внимания ее проектированию. Использование фрагмента HTML-формы также упрощает создание одинаковых форм на различных страницах. Следующий раздел мы начнем с описания примера сценария, использованного нами для демонстрации возможностей виджета HTML-формы.


Тестовый сценарий

Для простоты мы будем использовать в этом сценарии таблицу полисов, входящую в состав тестовой БД Apache Derby, устанавливаемой вместе с IBM Mashup Center. На рисунке 1 представлена копия экрана mashup-приложения, которое мы будем создавать в этой статье. Это простое приложение состоит всего из двух виджетов.

Рисунок 1. Тестовая mashup-страница
Рисунок 1. Тестовая mashup-страница

Как видно из рисунка 1, расположенный слева виджет DataViewer используется для отображения списка интересующих нас полисов, полученного из базы данных. Когда мы выбираем строку (полис), в правом виджете HTML-формы отображается подробная информация о нем. Виджет HTML-формы позволяет пользователям изменить адрес и нажать кнопку подтверждения. По нажатию этой кнопки вызывается на исполнение табличный фид обновления, в результате чего формируется XML-документ. Затем происходит разбор этого документа и выдается простое уведомление об успехе либо неудаче выполнения операции. На рисунке 2 показано сообщение об успешном результате.

Если вы хотите протестировать этот виджет немедленно, используя свою собственную форму, загрузите его по ссылке в разделе Загрузки и добавьте в IBM Mashup Center. После этого вы можете пропустить раздел о создании этого виджета и перейти сразу к разделу Собираем все вместе.

Рисунок 2. Сообщение об успешном выполнении операции
Рисунок 2. Сообщение об успешном выполнении операции

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


Создание JDBC-фидов

Как упоминалось ранее, для простоты мы будем использовать в нашем примере таблицу полисов, входящую в состав тестовой базы данных, устанавливаемой вместе с IBM Mashup Center.

Чтобы создать табличные фиды для таблицы полисов, выполните следующие шаги.

  1. На странице Catalog Home Page нажмите кнопку Create.
  2. Выберите New Feed.
  3. В качестве источника данных укажите Enterprise Database (JDBC).
  4. Чтобы подключиться к базе данных, содержащей таблицу полисов, в поле Connection Profile выберите Mashup Hub Sample Database.

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

    • Connection Profile Name: MashupHub Sample Database
    • Database Type: Derby Embedded
    • Connection Type: Driver Manager (Non-managed Connection)
    • Database Name: <installDir>/Hub/installedApps/Mashup Hub.ear/mashuphub-enterprise.war/hubsample
  5. Используйте следующие SQL-команды для создания двух фидов, с которыми будут работать виджеты, показанные на рисунке 1:
    • Первый фид предназначен для виджета DataViewer, отображающего список полисов. Заметьте, что добавление параметра state позволяет отфильтровывать полисы для определенного штата.
      select * from samples.policyholders where state = ':state'
    • Второй фид предназначен для табличного фида обновления, использующегося виджетом HTML-формы.
      update samples.policyholders set address = ':address', city = ':city', 
      state = ':state' where policyid = ':policyid'

    Предполагается, что вы уже знакомы с созданием табличных фидов в IBM Mashup Center. Поскольку оба SQL-запроса используют параметры, необходимо создать их, вставив SQL-выражения в поле Advanced редактора JDBC-фидов. Ссылки на подробные инструкции по созданию табличных фидов вы можете найти в разделе Ресурсы.

Прежде чем продолжить, обратите внимание на ряд моментов, требующих особого внимания при использовании табличных фидов обновления.

  • Использование метода HTTP GET.

    Как описано в документации консорциума W3C, ссылку на которую вы можете найти в разделе Ресурсы, в тех случаях, когда "выполняемое действие изменяет состояние источника таким образом, что пользователь может это заметить (например, подписка на какой-либо сервис)", следует использовать метод HTTP POST. Одной из причин этой рекомендации является то, что URL-адреса HTTP GET можно легко поместить в закладки или кэш, что может отразиться на их случайном и непреднамеренном вызове. Виджет HTML-формы, который вы разрабатываете в этой статье, использует в качестве метода доступа метод HTTP POST. По умолчанию в IBM Mashup Center включена поддержка обоих методов – GET и POST. Вы можете отключить метод HTTP GET, нажав кнопку Access Method на странице описания фида и сняв флажок GET.

  • Избегайте дублирующихся строк.

    Табличный фид обновлений состоит из единственного SQL-оператора. Поскольку он не содержит логики обработки ошибок, для обеспечения семантической целостности данных необходимо использовать ограничения БД. Например, для исключения дублирующихся строк один из столбцов должен являться ключевым (быть объявлен с ключом KEY) – в этом случае будет невозможно добавить строку, содержащую уже использующийся ключ.

  • Кэширование.

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

С учетом вышесказанного можно приступить к написанию собственного виджета HTML-формы.


Создание виджета

Виджеты Mashup Center соответствуют спецификации iWidget. Существует два типа виджетов, главным отличием которых является метод развертывания.

  • Виджеты, основанные на WAR-файлах – эти виджеты могут содержать серверные компоненты и должны быть развернуты на сервере приложений.
  • Облегченные виджеты – виджеты, которые полностью выполняются на стороне клиента, и которые не нужно разворачивать на сервере приложений. Виджет HTML-формы, рассматриваемый в этой статье, является облегченным виджетом.

Чтобы приступить к разработке тестового виджета HTML-формы с помощью IBM Mashup Center V2, выполните следующие шаги.

  1. Откройте вкладку Go to View, расположенную в верхнем правом углу страницы Mashup Builder, и выберите пункт Create a New Widget..., как показано на рисунке 3.
    Рисунок 3. Меню создания виджета
    Рисунок 3. Меню создания виджета
  2. В диалоговом окне Widget Builder щелкните на ссылке Work with the widget editor, как показано на рисунке 4.
    Рисунок 4. Диалоговое окно Widget Builder
    Рисунок 4. Диалоговое окно Widget Builder
  3. В следующем диалоговом окне выберите Create a new project.
  4. В диалоговом окне New Widget Project выберите Create a project from starter files, в результате чего будет создан новый проект, содержащий каркас определения виджета и файл каталога. Все файлы поддерживаются сервером. Как видно из рисунка 5, имена файлов перечислены в списке "Select a file" диалогового окна Customized Widget Project. Используя кнопки, расположенные под этим списком, вы можете выбрать для редактирования любой существующий файл или добавить в проект дополнительные файлы.
    Рисунок 5. Диалоговое окно Customized Widget Project
    Рисунок 5. Диалоговое окно Customized Widget Project
  5. Когда вы будете готовы протестировать виджет, щелкните Export и выберите Add to palette.

В этой статье рассматривается достаточно простой проект, состоящий лишь из двух файлов.


Файл определений виджета

Нет необходимости менять содержимое сгенерированного файла catalog.xml. В этом файле содержатся лишь имя виджета, отображаемое в панели инструментов, и местоположение файла определений виджета (iWidget.xml). Файл iWidget.xml указывает на файл JavaScript, реализующий логику, статические события, получаемые или посылаемые виджетом, а также макеты для режимов просмотра и редактирования. В этом разделе будут рассмотрены все изменения, которые необходимо внести в файл iWidget.xml.

В листинге 1 показан корневой элемент файла iWidget.xml. Атрибут iScope в корневом элементе iwidget является наиболее важным. Он определяет объект JavaScript, реализующий функции обратного вызова iWidget. Файл, содержащий код JavaScript, загружается с помощью элемента resource. Для получения дополнительной информации об этих и других атрибутах обратитесь к документации по программированию и API виджетов, ссылки на которую вы можете найти в разделе Ресурсы.

Листинг 1. Заголовок файла iWidget.xml
<iw:iwidget name="htmlForm"
            xmlns:iw="http://www.ibm.com/xmlns/prod/iWidget"
            iScope="sample.mashupcenter.htmlForm"
	    allowInstanceContent="true" supportedModes="view edit"
            mode="view" lang="en">

<iw:resource uri="htmlForm.js"/>

В листинге 2 показаны определения одного предопределенного события receive и двух событий send. Событие receive обозначено атрибутами handled и onEvent. Значением атрибута onEvent является имя функции, вызываемой при получении события. Значение атрибута published определяет имя опубликованного события. В разделе Обработка и генерация событий будет показано, как обрабатываются эти события.

Листинг 2. Определение событий в файле iWidget.xml
<iw:event id="ResetForm" handled="true" onEvent="handleReset"
          eventDescName="desc_handleReset"/>
<iw:eventDescription id="desc_handleReset" payloadType="any" title="Clear all Fields"
                        description="Clear all the fields in the form" lang="en">
</iw:eventDescription>

<iw:event id="actionSuccessful" eventDescName="desc_actionSuccessful" published="true"/>
<iw:eventDescription id="desc_actionSuccessful" payloadType="text"
                        description="Number of records updated by WebService" lang="en">
</iw:eventDescription>

<iw:event id="actionFailed" eventDescName="desc_actionFailed" published="true" />
<iw:eventDescription id="desc_actionFailed" payloadType="text"
                        description="Failure to assign" lang="en">
</iw:eventDescription>

Наконец, файл определений содержит макеты виджета для режимов просмотра и редактирования. Макет определяется HTML-разметкой, которая заключена в элемент iw:content под заголовком CDATA. В листинге 3 показана HTML-разметка для режима просмотра. Заметьте, что все элементы div имеют атрибут id, что позволяет манипулировать ими с помощью JavaScript. Также обратите внимание на то, что значение каждого атрибута id начинается с префикса _IWID_. Во время выполнения IBM Mashup Center заменяет каждый префикс _IWID_ на уникальный идентификатор экземпляра виджета, который генерируется при его создании. Этим достигается уникальность каждого идентификатора даже в тех случаях, когда на одной HTML-странице запущено несколько экземпляров виджета. В определении макета режима просмотра присутствуют два элемента div. Изначально пустой элемент div с идентификатором _IWID_formdiv содержит фрагмент HTML-формы. Второй элемент div содержит атрибут style со значением display:none; это означает, что он является невидимым. Этот элемент содержит шаблон для отображения результатов выполнения формы и может стать видимым после выполнения одного из фидов обновлений.

Листинг 3. Определение макета режима просмотра в файле iWidget.xml
<iw:content mode="view">
  <![CDATA[
  <div id='_IWID_formdiv'></div>

  <div id='_IWID_resultdiv' style='display:none; font-size:1.3em;'>
      <div id="_IWID_ResultXML" ></div>
      <br />
      <a href=""
         onclick="javascript:iContext.iScope().showFormAndHideResult();return false;">
         Back</a>
  </div>

  ]]>
</iw:content>

Раздел для режима редактирования содержит код формы с одной текстовой областью и тремя текстовыми полями. Эта форма отображается при нажатии пользователем кнопки Edit Settings. Текстовая область используется для ввода кода фрагмента HTML-формы. Три текстовых поля предназначены для ввода URL-адресов (от одного до трех). В следующих разделах этой статьи будет описано, как связать эти URL-адреса с кнопками, расположенными на форме. Значения URL-адресов должны совпадать со значениями атрибута формы method. То есть, после знака "?" из URL-адреса удаляется часть, содержащая пары "имя-значение".

На рисунке 7 вы можете посмотреть на код формы, представленный в графическом виде. Для краткости в этой статье не приводится полный код макета режима редактирования HTML-формы (этот код входит в состав пакета, который можно загрузить по ссылке, приведенной в разделе Ресурсы).


Реализация JavaScript

Код JavaScript содержится в файле htmlForm.js. Это класс библиотеки Dojo, который обрабатывает стандартные события, такие как load, unload, view, edit и прочие пользовательские события, а также управляет взаимодействиями с сервером. Ниже приводится краткий обзор функций, содержащихся в этом файле.

  • onLoad – функция, содержащая код инициализации. Как правило, в ней выполняется сбор конфигурационной информации, сохраненной в осуществленных ранее вызовах диалогового окна Edit Settings.

    Вспомните, что все атрибуты id в макетах просмотра и редактирования HTML-разметки содержат префикс _IWID_, который заменяется реальным идентификатором экземпляра виджета при его создании. Это означает, что прежде, чем код JavaScript сможет найти HTML-элемент по его идентификатору id, необходимо использовать идентификатор id экземпляра виджета из объекта iContext , чтобы создать реальный идентификатор. Обратите внимание на то, как в листинге 4 происходит получение данных виджета от объекта attributes, связанного с объектом iContext.

    Листинг 4. Функция onLoad
    onLoad: function() {
    
            this.uid = "_" + this.iContext.widgetId + "_";
    
            this.formDivNode   = dojo.byId(this.uid + 'formdiv');
            this.resultNode = dojo.byId(this.uid + 'resultdiv');
    
            // загрузка атрибутов
            var attributes = this.iContext.getiWidgetAttributes();
            this.formHtml  = attributes.getItemValue( "formHtml" );
            ::::::::::::::::::::::::
    },
  • onUnload – функция, вызываемая перед уходом со страницы. Обычно не возникает необходимости в очистке ресурсов, однако в данном случае это не означает, что реализация данной функции не нужна. Поскольку идентификаторы Dojo V1.3 Dijit должны быть уникальными, и они не удаляются автоматически во время очистки ресурсов при переключении между страницами, необходимо делать это вручную.
    Листинг 5. Функция onUnload
    onUnload: function()
    {
        // необходимо очистить все существующие dijit (для освобождения всех id)
        if ( this.formDijit != null )
            this.formDijit.destroyRecursive( false );
    },
  • onview – функция, вызываемая при каждом отображении виджета. Если тестовый виджет не был настроен (например, если он впервые размещен на странице), он просто отображает сообщение по умолчанию.
    Листинг 6. Функция onview
    onview: function()
    {
        if ( this.formHtml == null  ||  this.formHtml.length <= 0 ) {
            this.formDivNode.innerHTML = "Switch To Edit to specify HTML form";
        } else if ( this.viewContent.length <= 0 ) {
            this.displayForm();
            this.reCreateEvents( );
        }  // иначе форма уже есть, делать ничего не нужно
    },
  • onedit – функция, вызываемая при нажатии Edit Settings. Код листинга 7 просто заполняет диалоговое окно Edit Settings последними введенными пользователем значениями.
    Листинг 7. Функция onedit
    onedit: function()
    {
        dojo.byId( this.uid + "formHtml" ).value = this.formHtml;
        :::::::::::::::::::::::::::::::::::
    },
  • saveConfigData – данная функция не связана с какими либо внутренними событиями. Это специальная функция, определенная в методе onclick кнопки Save (в макете режима редактирования HTML-разметки). Код листинга 8 просто получает и сохраняет последние значения, введенные пользователем в диалоговом окне Edit Settings. Событие onModeChanged используется для того чтобы информировать среду выполнения виджета о необходимости закрыть диалог Edit Settings.
    Листинг 8. Функция saveConfigData
    saveConfigData: function()
    {
        this.formHtml = dojo.byId( this.uid + "formHtml" ).value;
        ::::::::::::::::::::::::::::::::::::::::::::::::::
    
        this.iContext.iEvents.fireEvent("onModeChanged", null, "{newMode:'view'}");
    
        var attributes = this.iContext.getiWidgetAttributes();
        attributes.setItemValue("formHtml"  ,  this.formHtml );
        ::::::::::::::::::::::::::::::::::::::::::::::::::
        attributes.save();
    },

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


Отображение HTML-формы

Для использования виджета необходимо иметь HTML-форму. Ее можно создать с помощью любого понравившегося редактора или инструмента. После создания HTML-формы убедитесь, что для каждого ее поля ввода имеется соответствующий атрибут dojotype (за примером обратитесь к листингу из раздела Собираем все вместе). Ваша форма может иметь несколько кнопок. Чтобы кнопка была активной, она должна содержать атрибут onclick со значением, указанным ниже.

            onclick="_${widgetId}_iContext.iScope().submit('formUrl1');"

Данный синтаксис используется для вызова функции submit, определенной в JavaScript-файле виджета. Подробная обработка функции submit будет рассмотрена в разделе Обработка функции submit HTML-формы, а пока, для того чтобы вышеприведенный код стал рабочим, просто замените подстроку ${widgetId} на реальный идентификатор вашего виджета. Как это сделать, рассмотрим ниже.

Чтобы отобразить фрагмент HTML-формы, вставленный в диалоговое окно Edit Settings, вы просто делаете HTML-строку значением объекта innerHTML элемента div из листинга 3, как показано в листинге 9. Но прежде чем сделать это, необходимо заменить подстроку ${widgetId} на реальный идентификатор id виджета. Для этого вызовите служебную строковую функцию Dojo substitute (это также показано в листинге 9). И последнее, о чем необходимо упомянуть относительно листинга 9: поскольку форма содержит объекты Dojo Dijit, то для того, чтобы класс Dojo правильно работал, необходимо вызывать метод Dojo parse.

Листинг 9. Функция displayForm
displayForm: function()
{
    // Назначение метода submit действию кнопки onclick.
    this.viewContent = dojo.string.substitute( this.formHtml
                                             , { widgetId: this.iContext.widgetId });
"
    // Добавление содержимое формы в корневой узел содержимого представления.
    if ( this.formDijit != null )  // необходимо очистить все существующие
                                        // dijit (для освобождения всех id)
        this.formDijit.destroyRecursive( false );
    this.formDivNode.innerHTML = this.viewContent;

    // Вставка компонентов dojo для отображения виджетов Dojo
    dojo.parser.parse( this.formDivNode );
    this.formDijit = this.getFormDijit(  this.formDivNode );
},

Обработка и генерация событий

Ключевая особенность виджета HTML-формы заключается в том, что в него можно передавать данные. Как было описано в разделе Тестовый сценарий, щелчок по строке в виджете DataViewer приводит к тому, что значения ее столбцов передаются в поля ввода виджета HTML-формы. Поскольку поля ввода разных форм могут различаться, невозможно статически определить события receive для полей ввода входной формы в файле iWidget.xml, как это было сделано для предопределенного события receive и двух событий send в листинге 2.

Чтобы динамически создавать события для каждого поля ввода формы, сначала необходимо выполнить разбор полученного кода HTML для каждого из этих полей, как показано в листинге 10.

Листинг 10. Функция createEventsForFields
createEventsForFields : function(  )
{   
    this.eventNames = [];
    this.dijitMap   = {};

    var children = this.formDijit.getChildren();
    for (var i = 0  ;  i < children.length  ;  i++ ) {
        var widget = children[i];
        var name  = widget.attr( 'name' );
        if ( name == null ||  name.length == 0 )
            continue;  // пропускаем поля ввода без имени
        if ( widget.type == 'radio'  &&  widget.checked == false )
            continue;   // выберем поле ввода, для которого
                            // переключатель установлен в true

После идентификации поля ввода формы создадим для него событие с таким же именем, как показано в листинге 11.

Листинг 11. Динамическое создание событий
this.eventNames.push( name );
this._createEvent({
    name : name,
    type: "any",
    isHandled : true,
    handlingFn : dojo.hitch(this, this.handleEvent )
});

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

Листинг 12. Карта dijitMap для хранения имен событий
// также сопоставим dijit обработке события
this.dijitMap[ name ] = widget;

Далее необходимо поместить код обработки этих событий, выполняющийся при их запуске. Когда одно из событий передается в виджет, имя этого события используется для поиска (с помощью кода dijitMap) нужного поля ввода формы. Если поле ввода формы не пустое, то введенное значение устанавливается в качестве значения виджета, как показано в листинге 14.

Листинг 14. Функция handleEvent
handleEvent: function(iEvent){
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    var  evtname    = iEvent.name;
    var  widget     = this.dijitMap[ evtname ];
    if ( widget != null )
        widget.setValue( iEvent.payload ); 
}

Обработка функции submit HTML-формы

Как было отмечено в разделе Отображение HTML-формы, кнопки фрагмента HTML-формы должны содержать явный вызов функции submit. Аргумент функции submit определяет, какой из URL-указателей фидов, определенных в диалоговом окне htmlForm Edit (рисунок 7), вызывается при нажатии кнопки. Как видно из листинга 15, аргументом должна быть одна из следующих строк.

  • formUrl1 – вызов URL-указателя фида, определенного для метода формы First .
  • formUrl2 – вызов URL-указателя фида, определенного для метода формы Second.
  • formUrl3 – вызов URL-указателя фида, определенного для метода формы Third.
Листинг 15. функция submit
submit: function( action ) {
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    var actionURL = "";
    // Указываем корневой URL фида, на который необходимо переключиться:
    if ( action == 'formUrl1' ) {
        if (  this.formUrl1  &&  this.formUrl1.length > 0 )
            actionURL = this.formUrl1;
    } else if ( action == 'formUrl2' ) {
        if (  this.formUrl2  &&  this.formUrl2.length > 0 )
            actionURL = this.formUrl2;
    } else if ( action == 'formUrl3' ) {
        if (  this.formUrl3  &&  this.formUrl3.length > 0 )
            actionURL = this.formUrl3; 
    ::::::::::::::::::::::::::::::::::::::::::::::::::

Теперь, когда вы определили нужный базовый URL для выбранного действия, необходимо собрать данные формы, введенные пользователями. Это делается с помощью функции collectNVP. Как показано в листинге 16, вся трудоемкая работа по получению значений из различных полей ввода формы выполняется с помощью функции Dijit getValues библиотеки Dojo. Ваш код должен лишь циклически проверять поля и кодировать значения с целью убедиться, что они не содержат недопустимых символов.

Листинг 16. Функция collectNVP
collectNVP: function(  ) {
    this.debugTrace( "collectNVP entered" );

    var formData = "";
    var temp = this.formDijit.getValues();
    for ( var  name in temp ) {
        if ( formData.length > 1 )  formData += '&';
        // Шифруем ключ и значение, чтобы убедиться в отсутствии недопустимых символов.
        formData +=  encodeURI( name );
        formData +=  "=";
        // encodeURI( value );   doesn't escape &, ...
        var value =  temp[ name ];
        formData +=  escape( value );
    }
    return formData;
}

После того, как данные и базовый URL получены, с помощью метода xhrPost библиотеки Dojo выполняется AJAX-вызов. В соответствии с рекомендациями раздела Создание JDBC-фидов используйте для запуска табличного фида обновлений метод HTTP Post, а не метод HTTP GET.

Как показано в листинге 17, аргументы метода xhrPost включают в себя функции обратного вызова для случаев load (успех) и error. Подробно функции обратного вызова описываются в следующих двух разделах. Аргумент urlToLoad, содержащий базовый URL или метод формы, не используется напрямую, поскольку механизм защиты браузера требует, чтобы базовый URL, указанный пользователем, был перенаправлен через AJAX-прокси mashup-сервера. Это достигается путем вызова функции reWriteURI объекта iContext.

Листинг 17. Подача данных формы
// Используем метод POST для URL типа update
submitUrl: function(urlToLoad, formdata )
    var location = this.iContext.io.rewriteURI( urlToLoad );
    dojo.xhrPost({
        url     : location,
        postData: formdata,
        load    :  dojo.hitch( this, this.handleFeedContent ),
        error   :  dojo.hitch( this, this.handleErrorResponse ),
        handleAs: "xml",
        sync    : true
    });
}

Обработка успешной отправки данных формы

В соответствии с кодом AJAX-вызова xhrPost, при успешной отправке данных формы (submit) происходит вызов функции handleFeedConent. Этот виджет создан для работы только с реляционными (JDBC) фидами обновлений MashupCenter. Фид возвращает XML-ответ, показанный на рисунке 6. Если был получен другой ответ, программа выводит сообщение "Unsupported result format" (результат возвращен в неподдерживаемом формате).

Рисунок 6. Ответ об успешном выполнении фида обновлений
Рисунок 6. Ответ об успешном выполнении фида обновлений

Как показано в листинге 18, если результат был возвращен в правильном формате, функция handleFeedConent выводит сообщение"Operation successful" (успешная операция) и количество успешно добавленных строк. Также эта функция запускает событие actionSuccessful, статически определенное в файле iWidget.xml, который был рассмотрен в разделе Файл определений виджета.

Листинг 18. Успешная обработка данных формы
handleFeedContent: function(data){
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    resultHTML += "Operation successful.";
    resultHTML += rowCount;
    resultHTML += " record(s) changed.";

    this.iContext.iEvents.fireEvent("actionSuccessful", null, "" );
    ::::::::::::::::::::::::::::::::::::::::::::::::::

Если вызов модуля MashupCenter Relational (JDBC) возвращает ошибку (-1) (см. листинг 19), функция handleFeedConent генерирует результирующую строку с сообщением, возвращаемую в элемент systemmsg. Также эта функция запускает событие actionFailed, определенное в листинге 2.

Листинг 19. Сообщение об ошибке, возвращаемое после успешной обработки данных формы
handleFeedContent: function(data){
    ::::::::::::::::::::::::::::::::::::::::::::::::::
    if (  rowCount ==  "-1" ) {

       var  msg     = "Unknown error. <br><br>";
       var  msgList = dojo.query( "systemmsg" , data );
       if ( msgList  &&  msgList[0] )
            msg = dojox.xml.parser.textContent( msgList[0] );
       resultHTML += msg;

       this.iContext.iEvents.fireEvent("actionFailed", null, rowCount );

Обработка ошибок во время отправки данных формы

Как показано в листинге 20, если во время обработки данных возникает ошибка, функция handleErrorResponse отображает результат, возвращенный неудачным сеансом связи, путем вызова функции displayResult.

Листинг 20. Функция handleErrorResponse
handleErrorResponse: function(data)
{
    this.debugTrace( "handleErrorResponse entered data="  + data );
    this.displayResult( data );
}

Отображение результатов отправки данных формы

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

Значением атрибута style для объекта resultNode, изначально заданным в макете режима просмотра (файл iWidget.xml в листинге 3), является display:none. Это означает, что данный объект скрыт. Как показано в листинге 21, функция displayResult делает объект resultNode видимым, присваивая его свойству style.display значение block.

Листинг 21. Функция displayResult
displayResult: function(data)
{
    // сохранение текущего размера
    var  formSize = dojo.contentBox( this.formDivNode );
    // скрытие формы
    this.formDivNode.style.display = "none";

    // отображение результата
    this.resultNode.style.display = "block";
    dojo.contentBox( this.resultNode, formSize );
    var resultXmlNode = dojo.byId(this.uid + 'ResultXML');
    resultXmlNode.innerHTML = data;
},

Объект resultdiv содержит ссылку Back, которая вызывает функцию showFromAndHideResult. Как показано в листинге 22, эта функция скрывает объект resultdiv и снова отображает форму.

Листинг 22. Функция showFormAndHideResult
// Очистка данных, скрытие результирующего узла и повторное отображение формы.
showFormAndHideResult: function()
{
    this.debugTrace( "handleFeedContent entered" );

    this.formDivNode.style.display = "block";

    // Удаление текста сообщения.
    var resultXmlNode = dojo.byId(this.uid + 'ResultXML');
    resultXmlNode.innerHTML = "";
    this.resultNode.style.display = "none";
},

Собираем все вместе

Теперь все готово для присоединения вашего виджета HTML-формы к тестовому mashup-приложению, описанному в разделе Тестовый сценарий. Начнем с фрагмента HTML-формы для записи о полисе. Как показано в листинге 23, для организации текстовых полей используется HTML-таблица. Как было сказано ранее, форма должна использовать объекты Dojo Dijit. Так же, как и на обычной HTML-странице, поля ввода формы должны иметь имена, совпадающие с именами параметров, которые используются в табличном фиде обновлений (этот фид был создан в разделе Создание JDBC-фидов). Форма может содержать несколько кнопок, соответствующих любой комбинации действий INSERT, UPDATE или DELETE. Чтобы продемонстрировать возможность дальнейшего расширения функционала, форма содержит дополнительную нерабочую кнопку с надписью Delete Policy, не имеющую соответствующего фида.

Листинг 23. HTML-форма для работы с полисами
<form dojotype="dijit.form.Form" style="font-size:1.3em;">

  <div style='background-color:#D1EACC; height:4em; padding-top:5px; padding-bottom:5px'>
      <center><h3>Policy Address Update and Delete Form</h3></center>
  </div>

  <br>
  <table>

  <tr><td>Policy Id:</td>
      <td><input type="text"  name="policyid"  dojotype="dijit.form.TextBox"
                 style="width: 6em;" readonly /></td>
      <td></td>
      <td></td>
  </tr>

           :::::::::::::::::::::::::::::::::::::::::

  <tr>
  <td></td>
  <td colspan='4' align='right'>
      <button dojotype="dijit.form.Button" value="formUrl1">Update Address
              onclick="_${widgetId}_iContext.iScope().submit('formUrl1');"
      </button>
      <button dojotype="dijit.form.Button" value="formUrl2">Delete policy</button>
  </td>
  </tr>
  </table>
</form>

Теперь, как показано на рисунке 7, перейдем в диалоговое окно htmlForm Edit и вставим фрагмент HTML-формы в поле Form Html, а табличные фиды, созданные в разделе Создание JDBC-фидов – в поля соответствующих методов формы. Для завершения настройки виджета нажмите кнопку Save.

Рисунок 7. Диалоговое окно htmlForm Edit
Рисунок 7. Диалоговое окно htmlForm Edit

При выборе строки в виджете DataViewer заполняются все поля ввода. Как объяснялось в разделе Обработка и генерация событий, виджет HTML-формы динамически создает события receive для каждого из полей ввода формы. Все, что необходимо сделать, это связать их с событиями send виджета DataViewer. На рисунке 8 показан процесс привязки одного из сгенерированных событий receive к соответствующему событию виджета DataViewer.

Рисунок 8. Привязка событий receive
Рисунок 8. Привязка событий receive

Наконец, необходимо привязать событие actionSuccessful виджета HTML-формы к виджету URL Customizer. Последний привязан к виджету DataViewer и настроен на использование того же самого URL, который использует виджет DataViewer. На рисунке 9 показаны виджет URL customizer и диалоговое окно Wiring Graph.

Рисунок 9. URL Customizer и Wiring Graph
Рисунок 9. URL Customizer и Wiring Graph

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

Рисунок 10. Привязка событий send
Рисунок 10. Привязка событий send

Заключение

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

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


Загрузка

ОписаниеИмяРазмер
Пример к статьеHTMLformWidget.zip8 КБ

Ресурсы

Научиться

Получить продукты и технологии

  • Посетите Web-страницу Lotus greenhouse (EN), чтобы получить практические навыки работы с IBM Mashup Center.
  • Загрузите бесплатную ознакомительную версию IBM Mashup Center (EN) с Web-сайта сообщества developerWorks.

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Information Management, Lotus
ArticleID=833452
ArticleTitle=Mashup-страницы, больше чем просто отчеты
publish-date=09062012