В одном из топиков была затронута тема создания приложений для Вконтакте. Что ж, продолжим её, только на этот раз перейдем на другое средство разработки. В этом топике я не буду рассматривать методы API вконтакта, принцип создания подписи и т.п., что было описано в том топике.
Всем известно, что приложения Вконтакте — флеш приложения. В основном для разработки вконтактовских приложений используют продукты Adobe. Я же использую для разработки богатых интернет приложений бесплатную свободную среду OpenLaszlo. Данный фреймворк (назовём его так) бесплатен, его исходные коды доступны, все компоненты можно изменять (сразу оговорюсь, что я не знаю, как лазла компилирует xml файлы в бинарный флеш, потому что я этим не интересовался). Кроме, собственно, компиляции во флеш, есть возможность создавать приложения на DHTML.
Основные понятия.
Исходные коды в лазло — обычные xml файлы. Любое приложение на лазло должно содержать главный узел . Внутрь канваса можно помещать существующие классы в лазло, создавать свои классы. Любой класс в лазло наследуется от класса <node>. Второй по значимости класс в лазло — <view>, похож на элемент <div> в (x)html.
Напишем простенькое приложение на лазло, программку, выводящую hello world:
<canvas>
<text>Hello World<text>
</canvas>
Здесь появился новый стандартный элемент — <text>. Основные атрибуты: text, selectable, pattern, multiline. Дальше заостряться на нём не будем.
Для создания логики приложения используется JavaScript. Приведу пример посложнее:
<canvas height="30">
<class name="clickClock" extends="text">
<attribute name="dayTable"
value='["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]'/>
<handler name="onclick">
var now = new Date;
this.format("You clicked me at %02d:%02d:%02d on %s",
now.getHours(),
now.getMinutes(),
now.getSeconds(),
dayTable[now.getDay()]);
</handler>
</class>
<clickClock>
Click Me!
</clickClock>
</canvas>
Результат
Этот пример полезен тем, что здесь видно, как переопределяются классы, используются обработчики. В частности на основе класса text мы создали свой класс clickClock (обращаю внимание, что лазла чувствительна к регистру). Добавили в класс новый атрибут — dayTable (добавлять атрибуты можно и с помощью js, как — объяснять не буду :)). У тега <attribute> три атрибута: name, value & type. Для задания обработчика onclick используется элемент <handler>. Внутри код на js. Так как используется xml, то внутри скриптов нельзя использовать сущности из xml, такие как <, >, & и др. Вместо них используются всем давно известные & lt;, & gt;, & amp;. Если это кого-то не устраивает, то можно весь скрипт поместить внутрь текстового блока
<![CDATA[ var i = 0; if (i > 1) doSomething; ]]>
На этом знакомство можно закончить и перейти непосредственно к созданию фреймворка для вконтактовских приложений.
Создание фрейморка для приложений Вконтакте на OpenLaszlo.
Для начала создадим основной файл проекта, назовём его main.lzx. В нём пропишем наш канвас
<canvas width="607" height="590" bgcolor="white">
<include href="lib/library.lzx" />
</canvas>
Здесь мы задали максимальный размер для нашего приложения (максимальный, который разрешён вКонтакте), задали белый фон и включили файл с определением наших классов, которые мы сейчас будем создавать. Для этого мы использовали тег <include>. Какое там имя файла — не важно. Просто будем называть файлики говорящими именами. Вот содержимое нашей библиотеки:
<library>
<include href="ServerData.lzx"/>
<include href="framework.lzx"/>
<include href="md5.js"/>
</library>
Библиотека задается элементом <library>. В библиотеке мы подключаем три файла — первый для работы с удалённым сервером и сервером вконтакта, второй, логика приложения, третий — ф-ии для создания md5 хеша. Начнём, пожалуй!
framework.lzx
<library>
<attribute name="api_id" type="string" value=""/>
<attribute name="user_id" type="string" value=""/>
<attribute name="group_id" type="string" value=""/>
<attribute name="viewer_id" type="string" value=""/>
<attribute name="is_app_user" type="string" value=""/>
<attribute name="viewer_type" type="string" value=""/>
<attribute name="auth_key" type="string" value=""/>
<attribute name="secret" type="string" value="secret"/>
<node id="framework">
<handler name="oninit">
<![CDATA[
if ($debug)
{
canvas.setAttribute("api_id", '1566108');
canvas.setAttribute("user_id", '6781573');
canvas.setAttribute("group_id", '0');
canvas.setAttribute("viewer_id", '6781573');
canvas.setAttribute("is_app_user", '1');
canvas.setAttribute("viewer_type", '0');
canvas.setAttribute("auth_key", '556C75F1EFBC11CFB9F300A0247033C4');
}
else
{
canvas.setAttribute("api_id", lz.Browser.getInitArg('api_id'));
canvas.setAttribute("user_id", lz.Browser.getInitArg('user_id'));
canvas.setAttribute("group_id", lz.Browser.getInitArg('group_id'));
canvas.setAttribute("viewer_id", lz.Browser.getInitArg('viewer_id'));
canvas.setAttribute("is_app_user", lz.Browser.getInitArg('is_app_user'));
canvas.setAttribute("viewer_type", lz.Browser.getInitArg('viewer_type'));
canvas.setAttribute("auth_key", lz.Browser.getInitArg('auth_key'));
}
]]>
</handler>
</library>
Здесь мы определяем основные атрибуты приложения. Если находимся в режиме дебага, то используем свои параметры, если в режиме работы, то получаем через флешварс наши параметры. Чтобы не перегружать наш фрейворк, не будем создавать какого-то класса для него, будем использовать корневой класс node. Замечу, что всем элементам можно задавать как идентификаторы, которые видны из любой точки приложения, так и имена. В общем, здесь всё аналогично (x)html. Продолжим развивать фреймворк дальше. Определю я в этом топике только один метод из API вконтакта — getProfile:
Добавим внутрь <node id=«framework»> пару методов
<!-- запросы Вконтакте -->
<method name="_getProfile">
canvas.setAttribute("cntr", canvas.cntr + 1);
this._website.getProfile({c: this, f: "_getProfileCallback"}, canvas.viewer_id);
</method>
<method name="_getProfileCallback" args="data">
status.setText("Загрузка профайла...");
var o = {};
o.auth_key = canvas.auth_key;
o.uid = data.xpathQuery("user/uid/text()");
o.first_name = data.xpathQuery("user/first_name/text()");
o.last_name = data.xpathQuery("user/last_name/text()");
o.sex = data.xpathQuery("user/sex/text()");
status.setText("Регистрация...");
this._register(o);
canvas.setAttribute("cntr", canvas.cntr - 1);
</method>
Обработки ошибок от вконтакта здесь я приводить не буду. Каждый из методов представлен парой — запрос, колбэк. В первом устанавливаем счетчик запросов (canvas.cntr), вызываем метод запроса профайла, передавая туда ссылку на фреймворк, имя метода колбэка, дальше остальные параметры. Во втором методе получаем данные. В данном случае ответ от сервера вконтакте в виде xml (к сожалению в лазле нет поддержки JSON, весь обмен данными только через xml).
Теперь узнаем, что же такое _website. Для этого приведу пример файла serverData.lzx:
<library>
<class name="ServerWebsite" extends="node">
<handler name="oninit">
this.base_url = "http://api.vkontakte.ru/api.php";
</handler>
<method name="_getSignature" args="params">
/*if ($debug)
{
paraxms.test_mode = 1;
}*/
params.test_mode = 1;
params.rnd = Math.random();
var result = "";
var arr = [];
var j = 0;
for (var i in params)
{
result = i + "=" + params[i];
arr[j] = result;
j++;
}
arr.sort();
result = "";
for (j = 0; j < arr.length; j++ )
result += arr[j];
return canvas.viewer_id + result + canvas.secret;
</method>
<method name="getProfile" args="cb_ref, uids">
var data = {};
data.api_id = canvas.api_id;
data.method = "getProfiles";
data.uids = uids;
data.v = "2.0";
data.fields = "sex,photo";
data.sig = md5(_getSignature(data));
var ds = new lz.ServerWebsiteDataset(this, {cb_ref: cb_ref});
ds.setAttribute("src", this.base_url);
ds.setAttribute("querytype", "POST");
ds.setQueryParams(data);
ds.doRequest();
</method>
</class>
<class name="ServerWebsiteDataset" extends="dataset" type="http" request="false">
<attribute name="cb_ref" value="null"/>
<handler name="ondata">
var p = this.getPointer();
p.selectChild();
this.destroy();
this.cb_ref.c[this.cb_ref.f](p);
</handler>
<handler name="onerror">
this.destroy();
this.cb_ref.c[this.cb_ref.f](-1);
</handler>
</class>
</library>
_website — это id созданного экземпляра класса ServerWebsite. Здесь два класса. Первый определяет собственно сами запросы к серверу вконтакта, второй — датасет, делающий запросы и получающий данные от сервера.
Метод _getSignature создаёт подпись для запросов.
Пока остановимся на этом, скажу лишь, что у датасета есть три важных события: ondata, onerror, ontimeout. И все их можно определить самостоятельно. В обработчике ondata мы получаем datapointer и вызываем наш колбек, передав туда датапоинтер. Поинтер нам нужен для траверса xml-ки.
Ссылки
openlaszlo.org — Основной сайт OpenLaszlo.
openlaszlo.org/download — Здесь можно скачать последнюю версию лазлы для Windows, Linux, Mac OS…
С последней версией у меня в висте и семёрке были замечены проблемы с компиляцией, поэтому можно попробовать версию 4.5.1. С ней пока проблем не было.
openlaszlo.org/archive — здесь можно скачать более ранние версии
openlaszlo.org/taxonomy/term/14 — документация для разработчика
openlaszlo.org/node/409 — примеры разработанных приложений на лазло. (Замечу, что есть опыт аутсорсинга для H&R Block. Раньше, года два назад, сайт у них был гораздо интереснее)
Если зайти в мой список приложений вконтакте, то можно посмотреть примеры (работающий только один, ещё один пришлось закрыть. Третий пример сейчас в разработке)
Если нужны будут исходники, то завтра смогу подготовить. Сегодня уже не могу себя заставить.
Жду комментариев :)
_________
Source code was highlighted with Source Code Highlighter.
Текст подготовлен в ХабраРедакторе