Введение
Вы наверняка заметили, что пользовательский интерфейс всех модулей из стандартной поставки TeamWox выполнен в едином стиле. Все модули обладают схожими элементами управления, из чего в конечном итоге складывается ощущение целостности системы.
Из материалов предыдущих статей вы уже получили некоторый опыт в области разработки пользовательских модулей. В этой статье мы поговорим о том, как правильно настроить окружение своих модулей для их последующего распространения, в том числе на платной основе. В качестве примера будем использовать все тот же учебный модуль Hello World.
В частности, вы узнаете как используется структура с информацией о модуле, как обрабатываются шаблоны и ресурсные файлы, как правильно создавать файлы помощи, как добавлять команды на главной странице. Во второй части статьи мы поговорим о виджетах и системном модуле Советы
.
1. Настройка окружения
1.1. Получение информации о модуле
1.2. Получение интерфейсов модуля
2. Ресурсы и шаблоны
2.1. Ресурсы
2.2. Шаблоны
3. Файлы справки
3.1. Структура папок и файлов
3.2. Порядок разделов и страниц
4. Интеграция пользовательских команд в модули TeamWox
4.1. Пользовательские команды в шапке главной страницы TeamWox
4.2. Загрузка скриптов модуля в основном фрейме
1. Настройка окружения
DLL каждого модуля TeamWox обязательно должна экспортировать следующие методы:
ModuleGetInfo(int index, ModuleInfo *info)
. Этот метод получает информацию о модуле путем заполнения структурыModuleInfo
. Эта информация будет использоваться при добавлении и регистрации нового модуля в системе TeamWox.ModuleGetInterface(int id, int server_api_version, IModule **module)
. Этот метод возвращает интерфейсIModule
, чтобы сервер мог взаимодействовать с модулем.
1.1. Получение информации о модуле
Структура ModuleInfo
Рассмотрим, из чего состоит эта структура, содержащая всю необходимую информацию о модуле.
Поле | Тип | Описание |
---|---|---|
id |
int |
Уникальный идентификатор модуля. Первые 65535 цифр зарезервированы для модулей из стандартной поставки. Пользовательские модули должны иметь идентификаторы больше 65535. |
version |
int |
Версия модуля. При отображении целочисленное значение будет представлено в виде числа с плавающей точкой с округлением до двух знаков после запятой. Например, число 100 будет отображаться как 1.00. |
build |
int |
Номер сборки модуля. Важный параметр, по которому можно выполнять различные проверки (как, например, мы это делали в статье TeamWox SDK: Взаимодействие с СУБД). С каждой новой сборкой модуля разработчики должны инкрементировать этот параметр. |
build_date |
wchar_t[16] |
Дата сборки модуля. Информационная строка. |
version_api |
unsigned int |
Версия TeamWox API, с использованием которой был скомпилирован модуль. Проверяется в ModuleGetInterface относительно текущей версии API сервера. Если версия TeamWox API, с которой скомпилирован модуль, больше (новее) чем у сервера - модуль загружен не будет. |
name |
wchar_t[64] |
Краткое название модуля, которое используется в HTTP запросах. Может содержать только символы латинского алфавита и символы подчеркивания. |
dependences |
int[32] |
Список модулей, необходимых для работы данного модуля. DEPRECATED, функционал реализуется через IModule::PostInitialize. |
color |
wchar_t[7] |
Цвет шапки с градиентной заливкой (6 символов и ноль) DEPRECATED, функционал реализуется через шаблоны. |
flags |
int |
Флаги описания модуля. Берутся из перечисления EnModuleFlags (подробнее см. ниже). |
icon_url |
wchar_t[260] |
Путь к иконке модуля, которая отображается на странице Управление -> Модули. |
home_site |
wchar_t[260] |
Ссылка на страницу производителя модуля. |
reserved |
char[256] |
Зарезервированное поле. |
Поля id
, name
, icon_url
, home_site
и reserved
как правило не изменяются в ходе разработки модуля и задаются один раз. При разработке модуля активнее всего изменяется поля build
и build_date
, а также периодически version_api
при выходе новых версий сервера TeamWox (и соответственно TeamWox SDK, включающего TeamWox API).
Для модуля Hello World структура ModuleInfo
заполняется в методе CHelloWorldModule::InfoGet(ModuleInfo *info)
.
ModuleInfo module_info= { HELLOWORLD_MODULE_ID, // HELLOWORLD_MODULE_ID = 65536 ProgramVersion, // #define ProgramVersion 100 ProgramBuild, // #define ProgramBuild 100 ProgramBuildDate, // #define ProgramBuildDate L"12 Oct 2008" TEAMWOX_API_VERSION, // #define TEAMWOX_API_VERSION 76 L"helloworld", // {0}, // L"", // TW_MODULE_FLAG_DIGITAL_SIGN | TW_MODULE_FLAG_MODULE_TAB, // Модуль сертифицирован разработчиками и имеет вкладку L"/helloworld/res/i/logo.gif", // Логотип модуля L"https://www.teamwox.com/" // };
Имя модуля (поле name
) используется при формировании пути в строке HTTP запроса.
Логотип модуля отображается после его включения в интерфейсе модуля Управление на вкладке Модули,
а также в профиле пользователя в разделе Порядок вкладок.
Перечисление EnModuleFlags
Флаги из перечисления непосредственно влияют на отображение модуля в пользовательском интерфейсе.
Имя | Значение | Описание |
---|---|---|
TW_MODULE_FLAG_LEFTPAGE |
0x01 |
Указывает на наличие левой панели. Если флаг выставлен, на странице модуля отображается левая панель, а веб-браузер посылает HTTP запрос вида /имя_модуля/left (подробнее см. далее). |
TW_MODULE_FLAG_DIGITAL_SIGN |
0x02 |
Защита модуля цифровой подписью. Выставленный флаг говорит о том, что модуль сертифицирован разработчиками TeamWox (так же, как модули из стандартной поставки). |
TW_MODULE_FLAG_MODULE_TAB |
0x04 |
Отображение вкладки модуля на главной странице TeamWox. |
TW_MODULE_FLAG_HIDDEN |
0x08 |
Модуль не имеет визуальной части, т.е. интегрируется с другими модулями (например, модуль Отчеты ). |
TW_MODULE_FLAG_MANUAL_CHECK |
0x10 |
Отключение автоматической проверки прав на модуль. Если флаг не выставлен (по умолчанию) и модуль запрещен, то сервер не посылает запросы. Если же флаг выставлен, то запросы будут посылаться в любом случае (например, как в модуле Отчеты). |
1.2. Получение интерфейсов модуля
Теперь, когда мы заполучили информацию о модуле, вторым этапом нам потребуется получить интерфейсы модуля. Класс любого модуля для работы в системе должен реализовывать интерфейс IModule
. Это основной интерфейс, через который сервер взаимодействует с модулем.
Методы, унаследованные модулем от интерфейса IModule, вызываются сервером TeamWox в определенном порядке.
1. Инициализация - Initialize(class IServer *server,int prev_build). Можно запрашивать только интерфейсы сервера и серверных модулей. Для обеспечения корректности работы системы, на этом этапе нет никакого взаимодействия с другими модулями.
2. Пост-Инициализация - PostInitialize(). Все модули загружены, и теперь уже можно запрашивать интерфейсы других модулей.
3. Работа в системе. Это основной этап, на котором через пользовательский интерфейс страниц происходит взаимодействие с сервером.
- Обработка запроса - Process(const Context *context). Для любого модуля в системе TeamWox зарезервированы 2 части URL, которые рекомендуется использовать в HTTP запросах:
/имя_модуля/index
- Перенаправление на главную страницу модуля./имя_модуля/left
- Отображение левой панели. При таком запросе в пользовательском интерфейсе модуля создается дополнительный фрейм (с разделителем), в котором отображается результат этого запроса. В пользовательском интерфейсе левой панели вы можете использовать любые элементы управления, однако рекомендуется применять элемент управленияList
- именно он используется в модулях из стандартной поставки TeamWox.
- Перечисление необходимых интерфейсов - GetInterface(const wchar_t *name, void **iface). Данный метод должен возвращать интерфейсы, которые предоставляет и реализует модуль.
4. Деинициализация - PrepareDestroy(). Сервер прекращает все обработки, подготавливаясь к завершению работы.
5. Освобождение ресурсов - Release(). Завершение работы при останове или перезагрузке сервера.
Помимо этих основных методов, интерфейс IModule
предоставляет несколько вспомогательных методов, с помощью которых можно получить дополнительную информацию о модуле,
а также управлять правами доступа к модулю.
2. Ресурсы и шаблоны
Помимо скомпилированного исходного кода в виде DLL, в состав модуля входят ресурсы (справка, изображения, скрипты, таблицы стилей и пр.), а также шаблоны страниц, определяющие пользовательский интерфейс.
2.1. Ресурсы
Для каждого модуля необходимо настроить доступ к его ресурсам. Обработка HTTP запросов на статические файлы ресурсов реализована в самом сервере, и нет необходимости реализовывать ее для каждого модуля отдельно. Сервер обеспечивает эффективную обработку запросов на статические файлы - кэширует их в памяти для быстрой отдачи.
Чтобы сервер мог обрабатывать HTTP запросы на ресурсы, на первом этапе инициализации модуля (IModule::Initialize)
необходимо зарегистрировать URL и путь до файлов с помощью метода IServer::VirtualPathRegister
.
VirtualPathRegister(const wchar_t *path_virtual,const wchar_t *path_real,int flags)
Параметр | Тип | Описание |
---|---|---|
path_virtual |
wchar_t* |
Префикс URL для обработки ресурсных файлов. Этот путь будет обрабатывать сервер. |
path_real |
wchar_t* |
Путь к ресурсному файлу или папке с ресурсными файлами относительно папки на сервере, в которой находится DLL модуля. |
flags |
int |
Флаги из перечисления EnVirtualFoldersFlags . |
Таким образом, мы связываем фактическое расположение ресурсов с текстом строки HTTP запроса. Для модуля Hello World регистрация виртуальных путей выглядит следующим образом.
//--- мапинг каталогов со статикой - рисунки, скрипты m_server->VirtualPathRegister(L"/res", L"res", TW_VIRTUAL_FOLDER_FLAG_CACHE); //--- JavaScript может содержать перевод - флаг TW_VIRTUAL_FOLDER_FLAG_LANGS m_server->VirtualPathRegister(L"/res/js",L"res\\js",TW_VIRTUAL_FOLDER_FLAG_CACHE | TW_VIRTUAL_FOLDER_FLAG_LANGS);
Теперь рассмотрим флаги, которые можно выставить для ресурсов.
EnVirtualFoldersFlags
Имя | Значение | Описание |
---|---|---|
TW_VIRTUAL_FOLDER_FLAG_CACHE |
0x001 |
В ответ сервера включается HTTP заголовок Expires , который указывают браузеру кэшировать файл до указанного срока, чтобы при повторной загрузке страницы не посылать запрос на сервер. |
TW_VIRTUAL_FOLDER_FLAG_NOCACHE |
0x002 |
В HTTP ответ добавляется заголовок Expires с заведомо прошедшей датой, так что файлы не кэшируются (выставляется несколько флагов, чтобы данные не кэшировались). |
TW_VIRTUAL_FOLDER_FLAG_DYNAMIC |
0x004 |
В HTTP ответ добавляется заголовок Last-Modified , а в HTTP запрос - заголовок If-Modified-Since . Выставление этого флага позволяет реализовать т.н. затратное кэширование. |
TW_VIRTUAL_FOLDER_FLAG_LANGS |
0x008 |
Файл может содержать токены <lngj:> для подстановки переводов. Такие файлы сервер "пропускает" через модуль переводов. |
TW_VIRTUAL_FOLDER_NOT_SECURE |
0x010 |
Разрешено отдавать файлы при запросе по незащищенному протоколу HTTP. Примечание: Не стоит беспокоиться о потенциальных DDoS-атаках. При таких запросах публичная часть не будет отвечать, и это никак не скажется на производительности при работе с системой. |
TW_VIRTUAL_FOLDER_NOT_AUTHORIZE |
0x020 |
Могут обрабатываться HTTP запросы от неавторизованных пользователей. |
TW_VIRTUAL_FOLDER_PUBLIC |
0x040 |
Делает ресурс доступным для неавторизованных пользователей в публичных запросах. |
TW_VIRTUAL_FOLDER_SEND_ATTACHMENT |
0x080 |
Если флаг выставлен для отдельного файла или папки целиком, то в HTTP ответ включается заголовок Content-Disposition: attachment . Таким образом, вне зависимости от MIME-типа, для присланных файлов всегда будет открываться диалоговое окно загрузки. |
Наиболее часто при разработке модулей используются флаги TW_VIRTUAL_FOLDER_FLAG_CACHE
- для уменьшения нагрузки на сервер, и TW_VIRTUAL_FOLDER_FLAG_LANGS
- для обеспечения мультиязычности.
2.2. Шаблоны
Теперь поговорим о шаблонах. Из предыдущих статей вы уже знаете, что в файлах шаблонов задается пользовательский интерфейс страниц. Файлы шаблонов следует помещать в папку относительно DLL модуля. Для удобства, файлы шаблонов группируются во вложенной папке \templates
и имеют расширение *.tpl
.
Так, например, при вызове метода обработки шаблона IServer::PageProcess
для страницы PageIndex вторым параметром указывается следующий относительный путь:
return(server->PageProcess(context, L"templates\\index.tpl", this, TW_PAGEPROCESS_NOCACHE));
3. Файлы справки
Для качественного ПО наличие справочной документации является обязательным условием. Кроме того, это упрощает техническую поддержку пользователей. За отображение контекстной справки в TeamWox отвечает системный модуль Помощь (TWX_HELP
).
В этот модуль изначально заложена возможность вывода электронной документации на всех поддерживаемых в системе языках (в зависимости от языковых настроек в профиле пользователя).
Английский язык справки является обязательным. Он будет использоваться по умолчанию, если для выбранного языка пользовательского интерфейса не найден соответствующий перевод справочной документации.
Вызов справки для определенного модуля осуществляется соответствующей кнопкой в шапке страницы.
Вы уже знаете, что шапка страницы создается с помощью элемента управления PageHeader
, а кнопка справки - его методом Help
. Параметр метода Help
указывается в следующем формате:
имя_модуля/имя_html_файла
Для главной страницы модуля Hello World это выглядит следующим образом:
//+----------------------------------------------+ //| Шапка страницы с командами | //+----------------------------------------------+ var header = TeamWox.Control("PageHeader","#41633C") .Command("<lngj:MENU_HELLOWORLD_NUMBER1>","/helloworld/number_one","<lngj:MENU_HELLOWORLD_NUMBER1>") .Command("<lngj:MENU_HELLOWORLD_NUMBER2>","/helloworld/number_two","<lngj:MENU_HELLOWORLD_NUMBER2>") .Command("<lngj:MENU_HELLOWORLD_REPORTS>","/reports/helloworld/helloworld_report","<lngj:MENU_HELLOWORLD_REPORTS>") .Help("helloworld/index") .Search(65536);
3.1. Структура папок и файлов
Файлы справки - это обычные HTML документы с изображениями и стилями - т.е. относятся к ресурсам модуля. Для отображения файлов справки в модуле Помощь
, разработчикам модуля следует создать структуру папок в следующем формате.
имя_модуля\папка_ресурсов\help\язык\
- папка_ресурсов - Регистрируется методом
IServer::VirtualPathRegister
(см. выше). - help - Зарезервированное имя папки, которое обрабатывается модулем
Помощь
. - язык - Трехбуквенное имя папки, соответствующее языковому коду. Языковой код (например,
eng
,rus
,fra
,ger
,spa
и т.д.) также используется в файлах переводов (*.lng
).
Так, для модуля Hello World на сервере эта структура выглядит следующим образом.
Соответственно, для каждой страницы модуля параметр элемента управления PageHeader
будет выглядеть следующим образом.
helloworld\имя_html_файла
или
helloworld\имя_вложенной папки\имя_html_файла
Подробнее о создании подразделов см. ниже.
Разумеется, имена папок и файлов, а также их структура, внутри языковых папок должны быть полностью одинаковыми - различаться должно лишь содержимое. Для модуля Hello World нажатие кнопки в шапке главной страницы в окне модуля "Помощь" открывает файл index.html на русском или английском языках.
3.2. Порядок разделов и страниц
Порядок корневых разделов в модуле Помощь
устанавливается исходя из идентификаторов модулей - от меньшего к большему. Поскольку ID пользовательских модулей должны начинаться с 65536 (65535 - идентификатор модуля Управление
), разделы справки для пользовательских модулей будут располагаться в конце списка в левой панели модуля Помощь
.
Внутренняя структура страниц в справке модуля определяется иначе. В исходном коде HTML страницы, в шапке (тэг <head></head>
) добавляются мета-данные следующего вида:
<meta content="order:n" />
Значение n от меньшего к большему определяет порядок расположения страниц. Наименьшее n соответствует странице корневого раздела.
Для создания еще одного уровня вложенности достаточно создать папку следующего вида.
имя_модуля\папка_ресурсов\help\язык\папка
Затем в этой папке в коде HTML документов следует просто продолжить нумерацию n в тэге <meta content="order:n" />
. При этом следует помнить, что страницы корневого раздела и всех подразделов должны именоваться index.html
.
Соответственно, обновленная структура папок и файлов будет выглядеть следующим образом.
Для отображения названия корневого раздела используется уже знакомый нам метод IModule::Title
, а для отображения названий всех вложенных разделов - значение тэга <title></title>
в HTML коде страниц.
При редактировании названий разделов справки для вступления изменений в силу необходимо перезагрузить сервер.
4. Интеграция пользовательских команд в модули TeamWox
В последнем разделе статьи мы рассмотрим как сделать так, чтобы команды пользовательских модулей (в виде функций JavaScript) были доступны из других модулей TeamWox. JavaScript команды можно выполнять как в отдельном окне (с помощью элемента управления Window
), так и в основном окне браузера.
Решение этой задачи возможно двумя способами.
Интерфейс
IToolbar
. С его помощью можно добавлять пользовательские команды в шапку главной страницы TeamWox.Интерфейс
IModuleMainframeTopBar
. С его помощью можно прогружать пользовательские скрипты в основном фрейме для последующего использования в других модулях.
Рассмотрим реализацию этого функционала на примере модуля Hello World (исходные коды со всеми изменениями см. в прикрепленном к статье файле).
4.1. Пользовательские команды в шапке главной страницы TeamWox
Интерфейс IToolbar
предоставляет несколько методов, которые вызываются сервером при отрисовке шапки главной страницы TeamWox. Сервер также определяет порядок вызова этих методов.
Total(void)
- Возвращает общее количество пользовательских команд модуля, отображаемых в шапке.InfoGet(int toolbar_num,ToolbarInfo *info)
- Получает информацию о командах.IsAccessible(const Context *context,int toolbar_num)
- В этом методе вы можете реализовать проверку прав доступа на определенные команды.ProcessHeader(const Context *context)
- Выводит дополнительный код, который загружает js-файл с пользовательской функцией.
Список команд пользовательского модуля, которые необходимо отобразить в шапке главной странице TeamWox, задается в структуре ToolbarInfo
.
Поле | Тип | Описание |
---|---|---|
title |
wchar_t[64] |
Ключ перевода имени команды (текст ссылки). |
description |
wchar_t[128] |
Ключ перевода описания команды (всплывающая подсказка). |
url |
wchar_t[128] |
URL команды. |
В качестве примера мы добавим простейшую JavaScript функцию, выводящую окно с сообщением. Файл с кодом функции должен находиться в ресурсах модуля Hello World (\modules\helloworld\res\js\helloworld.js
).
function HelloWorld_Command()
{
alert("<lngj:HELLOWORLD_COMMAND />!!!");
}
4.1.1. Перечислим интерфейс IToolbar
в CHelloWorldModule::GetInterface
.
//--- if(StringCompareExactly(L"IToolbar",name)) { *iface = &m_toolbar; return(RES_S_OK); }
4.1.2. Для удобства реализуем интерфейс в отдельном классе (менеджере).
#include "Managers\HelloWorldToolbar.h"
private: IServer *m_server; CHelloWorldManager m_manager; CHelloWorldToolbar m_toolbar;
4.1.3. Описание класса CHelloWorldToolbar
.
//+------------------------------------------------------------------+ //| Команды главного меню | //+------------------------------------------------------------------+ class CHelloWorldToolbar : public IToolbar { private: static ToolbarInfo m_toolbar[]; //--- IServer *m_server; public: CHelloWorldToolbar(); ~CHelloWorldToolbar(); //--- TWRESULT Initialize(IServer *server); //--- int Total(void); TWRESULT InfoGet(int toolbar_num,ToolbarInfo *info); TWRESULT IsAccessible(const Context *context,int toolbar_num); TWRESULT ProcessHeader(const Context *context); };
Помимо четырех унаследованных от интерфейса IToolbar
методов, объявим метод инициализации. С его помощью можно будет проинициализировать менеджер пользовательских команд в шапке главной страницы на этапе инициализации модуля (CHelloWorldModule::Initialize
).
//--- if(RES_FAILED(res=m_toolbar.Initialize(m_server))) ReturnErrorExt(res,NULL,"failed to initialize main page toolbar");
4.1.4. Реализация класса CHelloWorldToolbar
.
- Заполним структуру
ToolbarInfo
, добавив команду вызова пользовательской функцииHelloWorld_Command()
из ресурсов модуля. Не забудьте добавить переводы новых ключей в языковой файлhelloworld.lng
.
//+------------------------------------------------------------------+ //| TeamWox | //| Copyright 2006-2011, MetaQuotes Software Corp. | //| https://www.metaquotes.net | //+------------------------------------------------------------------+ #include "StdAfx.h" #include "HelloWorldToolbar.h" //--- Список команд ToolbarInfo CHelloWorldToolbar::m_toolbar[] = { {L"HELLOWORLD_COMMAND", L"HELLOWORLD_COMMAND_TITLE", L"javascript:HelloWorld_Command();"} };
- Реализация метода
IToolbar::Total
.
//+------------------------------------------------------------------+ //| Общее количество команд | //+------------------------------------------------------------------+ int CHelloWorldToolbar::Total(void) { //--- return(_countof(m_toolbar)); }
- Реализация метода
IToolbar::Total
.
//+------------------------------------------------------------------+ //| Получить информацию о командах | //+------------------------------------------------------------------+ TWRESULT CHelloWorldToolbar::InfoGet(int toolbar_num,ToolbarInfo *info) { //--- проверки if(toolbar_num<0 || info==NULL) ReturnError(RES_E_INVALID_ARGS); //--- if(toolbar_num>=_countof(m_toolbar)) return(RES_E_NOT_FOUND); //--- memcpy(info,&m_toolbar[toolbar_num],sizeof(*info)); //--- return(RES_S_OK); }
- Реализация метода
IToolbar::IsAccessible
. Для простоты мы не будем реализовывать какие-либо проверки прав доступа, т.е. команды модуля Hello World будут доступны всем пользователям TeamWox.
//+------------------------------------------------------------------+ //| Доступность команды - проверка прав | //+------------------------------------------------------------------+ TWRESULT CHelloWorldToolbar::IsAccessible(const Context *context,int toolbar_num) { //--- проверки if(toolbar_num<0 || context==NULL) ReturnError(RES_E_INVALID_ARGS); //--- if(toolbar_num>=_countof(m_toolbar)) return(RES_E_NOT_FOUND); //--- return(RES_S_OK); }
- Реализация метода
IToolbar::ProcessHeader
. Вывод дополнительного кода осуществляется также, как вIModuleMainframeTopBar::MainframeTopBar
.
//+------------------------------------------------------------------+ //| Вывод дополнительного кода | //+------------------------------------------------------------------+ TWRESULT CHelloWorldToolbar::ProcessHeader(const Context *context) { //--- проверки if(context==NULL || m_server==NULL) ReturnError(RES_E_INVALID_ARGS); //--- context->response->Write(L"<script type='text/javascript' src='"); m_server->WriteStamp(context, L"/helloworld/res/js/helloworld.js"); context->response->Write(L"'></script>"); //--- return(RES_S_OK); }
Метод IServer::WriteStamp
добавляет к имени ресурсного файла постфикс в виде хэша даты изменения. Таким образом, если при загрузке модуля ресурсный файл не изменился, то он не будет запрашиваться, т.к. браузер сможет получить его из кэша.
Если же в ресурсном файле произошли изменения, он гарантированно будет загружен заново, т.к. в конечном итоге за счет изменившегося постфикса ресурсный файл получит новое имя.
4.1.5. Итак, посмотрим, что же у нас получилось. Скомпилируйте модуль, запустите сервер и откройте главную страницу TeamWox.
4.2. Загрузка скриптов модуля в основном фрейме
Иногда может потребоваться, чтобы пользовательские команды были доступны на любой странице (например, всплывающая подсказка с различной информацией). В таких случаях лучше загружать команды в основном фрейме. Для этой цели следует применять интерфейс IModuleMainframeTopBar
.
Интерфейс IModuleMainframeTopBar
предоставляет единственный метод MainframeTopBar
, в котором вы можете добавлять свой JavaScript код, который будет однократно загружен вместе с кодом главной страницы. Затем загруженные функции можно вызывать из других модулей.
В качестве примера, иллюстрирующего эту концепцию, мы видоизменим пример из предыдущего раздела. Поместим JavaScript функцию в другой файл(\modules\helloworld\res\js\helloworld_topbar.js
) и изменим текст выводимого сообщения.
function HelloWorld_TopCommand()
{
alert("Top!!! <lngj:HELLOWORLD_COMMAND />");
}
4.2.1. В методе CHelloWorldModule::GetInterface(const wchar_t *name, void **iface)
перечислите и верните указатель на интерфейс IModuleMainframeTopBar
, который будет реализован в модуле.
//--- if(StringCompareExactly(L"IModuleMainframeTopBar",name)) { *iface = static_cast<IModuleMainframeTopBar*>(this); return(RES_S_OK); }
4.2.2. В классе модуля унаследуем метод интерфейса IModuleMainframeTopBar
.
class CHelloWorldModule : public IModule, public IModuleMainframeTopBar .......................................... public: TWRESULT MainframeTopBar(const Context *context);
4.2.3. В реализации метода IModuleMainframeTopBar::MainframeTopBar
выведем кусок HTML кода, который загружает js-файл с пользовательской функцией.
//+------------------------------------------------------------------+ //| Получение интерфейсов модуля | //+------------------------------------------------------------------+ TWRESULT CHelloWorldModule::MainframeTopBar(const Context *context) { //--- проверки if(context==NULL || m_server==NULL) ReturnError(RES_E_INVALID_ARGS); //--- context->response->Write(L"<script type='text/javascript' src='"); m_server->WriteStamp(context, L"/helloworld/res/js/helloworld_topbar.js"); context->response->Write(L"'></script>"); //--- return(RES_S_OK); }
4.2.4. Для вызова пользовательской функции необходимо использовать URL следующего вида. Префикс top означает, что функция доступна на странице, расположенной уровнем выше (согласно модели DOM), т.е. в основном фрейме страницы.
javascript:top.HelloWorld_TopCommand();
Заключение
Мы рассмотрели основные аспекты настройки окружения пользовательских модулей в системе TeamWox. Во второй части статьи мы поговорим о том, как дополнить модуль Совет дня
своими текстами. Также вы узнаете о виджетах на главной странице и о распространении модулей в компактном виде.
- Как добавить готовый модуль в TeamWox
- Как добавить страницу в модуль TeamWox
- Построение пользовательского интерфейса
- Взаимодействие с СУБД
- Создание пользовательских отчетов
- Файловое хранилище - Часть 1
- Файловое хранилище - Часть 2
- Настройка окружения пользовательских модулей - Часть 1
- Настройка окружения пользовательских модулей - Часть 2
- Поиск и фильтрация - Часть 1
- Поиск и фильтрация - Часть 2
- Настройка "Онлайн-консультанта" на вашем сайте
- Как создать дополнительный языковой пакет для TeamWox
2011.03.22