Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // event-emitter.js
- // Позволяет создавать свои события типа:
- // thisModel.emit('login.fail', obj)
- // И отлавливаем:
- // thisController.model.on('login.fail', function(error) {
- // *Выводим на экран ошибку*
- // })
- function EventEmitter() {
- this.__listeners = {};
- }
- function EventListener(fn, scope, once) {
- this.fn = fn;
- this.scope = scope;
- this.once = once;
- }
- EventEmitter.prototype = {
- /* Вызывает fn в контексте scope при возникновении события type. Если
- * once == true, то выполнится всего один раз.
- */
- on: function(type, fn, scope, once) {
- var index = this.__indexOf(type, fn);
- if (index != -1) {
- // Если обработчик уже задан, то обновляем scope и once для слушателя
- var listener = this.__listeners[type][index];
- listener.scope = scope;
- listener.once = once;
- } else {
- var listeners = this.__listeners[type] || (this.__listeners[type] = []);
- // Добавляем нового слушателя
- var listener = new EventListener(fn, scope, once);
- listeners.push(listener);
- }
- return this;
- },
- /* Вызывает fn в контексте scope при возникновении события type один раз. */
- once: function(type, fn, scope) {
- return this.on(type, fn, scope, true);
- },
- /* Удаляет всех слушателей, либо удаляет слушателей для события type, либо
- * удаляет слушателя с обработчиком fn для события type.
- */
- off: function(type, fn) {
- if (!arguments.length) {
- // .off() - удаляем всех слушателей
- this.__listeners = {};
- } else if (arguments.length == 1) {
- // .off(type) - удаляем слушателей для события type
- if (this.__listeners.hasOwnProperty(type)) {
- delete this.__listeners[type];
- }
- } else {
- // .off(type, fn) - удаляем слушателя для события type с обработчиком fn
- var index = this.__indexOf(type, fn);
- if (index != -1) {
- // Удаляем обработчик
- this.__listeners[type].splice(index, 1);
- if (!this.__listeners[type].length) {
- // Если массив слушателей пуст, то удаляем свойство с именем type
- delete this.__listeners[type];
- }
- }
- }
- return this;
- },
- /* Генерирует событие type и вызывает их обработчики. В функцию обработчик
- * передаются аргументы после type.
- */
- emit: function(type, args) {
- if (this.__listeners.hasOwnProperty(type)) {
- args = [].slice.call(arguments, 1);
- var i = 0;
- var listeners = this.__listeners[type];
- while (i < listeners.length) {
- var listener = listeners[i];
- listener.fn.apply(listener.scope || this, args);
- if (listener.once) {
- // Если обработчик должен выполниться лишь один раз, то удаляем
- // слушателя
- listeners.splice(i, 1);
- } else {
- ++i;
- }
- }
- if (!listeners.length) {
- // Если массив слушателей пуст, то удаляем свойство с именем type
- delete this.__listeners[type];
- }
- }
- return this;
- },
- __indexOf: function(type, fn) {
- if (this.__listeners.hasOwnProperty(type)) {
- var listeners = this.__listeners[type];
- var i = listeners.length;
- while (i--) {
- if (listeners[i].fn === fn) {
- return i;
- }
- }
- }
- return -1;
- }
- };
- EventEmitter.mixin = function(obj) {
- if (typeof obj == "function") {
- obj = obj.prototype;
- }
- var proto = new EventEmitter();
- for (var i in proto) {
- obj[i] = proto[i];
- }
- return obj;
- };
- var testEvents = {};
- EventEmitter.mixin(testEvents);
- // End event-emitter.js
- // =============================================================================
- // http.js
- // Набор функций для работы с сетью
- // .import "http.js" as http
- function encodeQueryParameters(parameters) {
- var pairs = [];
- for (var i in parameters) {
- if (parameters.hasOwnProperty(i)) {
- var name = encodeURIComponent(i);
- var value = encodeURIComponent(parameters[i]);
- pairs.push(name + '=' + value);
- }
- }
- return pairs.join('&');
- }
- function parseQueryString(str) {
- var pairs = str.split("&");
- var ret = {};
- for (var i = 0; i < pairs.length; ++i) {
- var pair = pairs[i].split('=', 2);
- var name = decodeURIComponent(pair[0]);
- var value = pair.length == 2 ? decodeURIComponent(pair[1]) : '';
- ret[name] = value;
- }
- return ret;
- }
- function request(method, url, callback, headers, data) {
- var xhr = new XMLHttpRequest();
- xhr.open(method, url);
- xhr.onload = function() {
- if (typeof callback == "function") {
- try {
- xhr.responseJSON = JSON.parse(xhr.responseText);
- } catch (e) {}
- var data = xhr.responseJSON || xhr.responseText;
- callback(data, xhr.status, xhr);
- }
- };
- if ({}.toString.call(headers) == "[object Object]") {
- for (var i in headers) {
- if (headers.hasOwnProperty(i)) {
- xhr.setRequestHeader(i, headers[i]);
- }
- }
- }
- xhr.send(data);
- }
- function get(url, callback, parameters, headers) {
- if ({}.toString.call(parameters) == "[object Object]") {
- parameters = encodeQueryParameters(parameters);
- url += (url.indexOf('?') == -1 ? '?' : '&') + parameters;
- }
- request('GET', url, callback, headers);
- }
- function post(url, callback, data, headers) {
- if ({}.toString.call(data) == "[object Object]") {
- data = encodeQueryParameters(data);
- headers = headers || {};
- // Если content-type уже задан, то его значение будет выглядеть как:
- // <someshit>, application/x-www-form-urlencoded
- headers["Content-Type"] = "application/x-www-form-urlencoded";
- }
- request('POST', url, callback, headers, data);
- }
- // tests
- // Open link <https://httpbin.org> and run this code in the console
- get('/get?foo', function(data) {
- console.log(data.args);
- }, {bar: 'quix'});
- post("/post", function(data, status, xhr) {
- console.log(data.form);
- }, {foo: 'bar'});
- // End http.js
- // =============================================================================
- // Минимальная реализация работы с Api Вконтакте. Для примера.
- var API_VERSION = 5.44;
- var API_URL = "https://api.vk.com/method";
- var API_DELAY = 0.34; // около 3-х запросов в секунду
- var AUTH_URL = "https://oauth.vk.com/token";
- var CLIENT_ID = 2274003;
- var CLIENT_SECRET = "hHbZxrka2uZ6jB1inYsH";
- function VkApi(accessToken, userId, apiVersion) {
- this.accessToken = accessToken;
- this.userId = userId;
- this.apiVersion = apiVersion || API_VERSION;
- }
- VkApi.prototype = {
- /* Вызывает метод Api */
- apiCall: function(method, callback, params) {
- // foo/bar -> foo/bar/
- var self = this;
- var endpoint = API_URL.replace(/(\/|)$/, '/') + method;
- // При асинхронных запросах не поможет
- post(endpoint, function(data, status, xhr) {
- console.log(xhr);
- callback(data.response, data.error);
- }, params);
- }, // end apiCall
- // Подразумевается, что через графический интерфейс будем работать
- login: function(username, password, captchaKey, captchaSid) {
- var self = this;
- var params = {
- v: self.apiVersion,
- client_id: CLIENT_ID,
- client_secret: CLIENT_SECRET,
- grant_type: "password",
- username: username,
- password: password
- };
- if (captchaKey && captchaSid) {
- params['captcha_key'] = captchaKey;
- params['captcha_sid'] = captchaSid;
- }
- get(AUTH_URL, function(response) {
- console.log(response);
- if (response.error) {
- self.emit("login.fail", response);
- return;
- }
- self.accessToken = response.access_token;
- self.userId = response.user_id;
- // там еще expires_in остался, но он равен 0 для офиц. приложений
- self.emit("login.success");
- }, params)
- }, // end login
- };
- // Добавляем события
- EventEmitter.mixin(VkApi);
- var vk = new VkApi();
- vk.on('login.fail', function(response) {
- // Показываем ошибку
- console.warn("Vk Authentication Error: " + response.error +
- (response.error_description ? ": " + response.error_description : ""));
- });
- vk.on('login.success', function() {
- // Скрываем окно авторизации
- });
- // Вызовет ошибку капчи
- vk.login(1, 1);
- // У Вконтакте существует лимит на отправку запросов в секунду с одного ip,
- // поэтому нам нужно чтобы запросы отправлялись строго по очереди с задержками.
- // var delay = self.apiDelay + self._lastApiRequest - Date.now();
- function ApiQueue(api, delay) {
- this.api = api;
- this.delay = delay || API_DELAY;
- // Очередь запросов
- this._queue = [];
- // Объект с которым мы работаем
- this._current = null;
- this._start = function() {};
- this._finish = function() {};
- this._except = function() {};
- }
- ApiQueue.prototype = {
- // Добавляет вызов метода в очередь
- add: function(method, callback, params) {
- this._queue.push({
- method: method,
- callback: callback,
- params: params,
- });
- return this;
- },
- // Извлекает первый элемент очереди и делает его текущим
- next: function() {
- if (this._queue.length) {
- this._current = this._queue.shift();
- this._execute();
- return;
- }
- // Если очередь закончилась
- this._finish.call(this);
- },
- // Вызвать текущий метод еще раз
- repeat: function() {}
- // Очистить очередь
- clear: function() {
- this._queue = [];
- return this;
- },
- // Выполнится, если очередь закончилась
- finish: function(callback) {
- this._finish = callback;
- return this;
- },
- // Вызовет обработчик ошибки
- error: function() {
- this._except.apply(this, arguments);
- },
- // Установить обработчик ошибок
- except: function(callback) {
- this._except = callback;
- return this;
- },
- _execute: function() {
- //
- },
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement