From f7c4fd2fedf56d733a87db7077d1d1d88f24bf67 Mon Sep 17 00:00:00 2001 From: lilia Date: Thu, 14 Jan 2016 14:07:00 -0800 Subject: [PATCH] DRY up event target implementations Dedupe event target code and make it extensible. // FREEBIE --- Gruntfile.js | 1 + js/libtextsecure.js | 202 +++++++++++++----------------- libtextsecure/event_target.js | 79 ++++++++++++ libtextsecure/message_receiver.js | 61 +-------- libtextsecure/sync_request.js | 61 +-------- 5 files changed, 176 insertions(+), 228 deletions(-) create mode 100644 libtextsecure/event_target.js diff --git a/Gruntfile.js b/Gruntfile.js index ea0ec37ff..576447eb4 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -54,6 +54,7 @@ module.exports = function(grunt) { 'libtextsecure/websocket-resources.js', 'libtextsecure/helpers.js', 'libtextsecure/stringview.js', + 'libtextsecure/event_target.js', 'libtextsecure/api.js', 'libtextsecure/account_manager.js', 'libtextsecure/message_receiver.js', diff --git a/js/libtextsecure.js b/js/libtextsecure.js index 79fe86a64..8d0ce4637 100644 --- a/js/libtextsecure.js +++ b/js/libtextsecure.js @@ -36181,6 +36181,86 @@ window.textsecure.utils = function() { }; }()); +/* + * vim: ts=4:sw=4:expandtab + * + * Implements EventTarget + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget + * + */ + +;(function () { + 'use strict'; + window.textsecure = window.textsecure || {}; + + function EventTarget() { + } + + EventTarget.prototype = { + constructor: EventTarget, + dispatchEvent: function(ev) { + if (!(ev instanceof Event)) { + throw new Error('Expects an event'); + } + if (this.listeners === null || typeof this.listeners !== 'object') { + this.listeners = {}; + } + var listeners = this.listeners[ev.type]; + if (typeof listeners === 'object') { + for (var i=0; i < listeners.length; ++i) { + if (typeof listeners[i] === 'function') { + listeners[i].call(null, ev); + } + } + } + }, + addEventListener: function(eventName, callback) { + if (typeof eventName !== 'string') { + throw new Error('First argument expects a string'); + } + if (typeof callback !== 'function') { + throw new Error('Second argument expects a function'); + } + if (this.listeners === null || typeof this.listeners !== 'object') { + this.listeners = {}; + } + var listeners = this.listeners[eventName]; + if (typeof listeners !== 'object') { + listeners = []; + } + listeners.push(callback); + this.listeners[eventName] = listeners; + }, + removeEventListener: function(eventName, callback) { + if (typeof eventName !== 'string') { + throw new Error('First argument expects a string'); + } + if (typeof callback !== 'function') { + throw new Error('Second argument expects a function'); + } + if (this.listeners === null || typeof this.listeners !== 'object') { + this.listeners = {}; + } + var listeners = this.listeners[eventName]; + for (var i=0; i < listeners.length; ++ i) { + if (listeners[i] === callback) { + listeners.splice(i, 1); + return; + } + } + this.listeners[eventName] = listeners; + }, + extend: function(obj) { + for (var prop in obj) { + this[prop] = obj[prop]; + } + return this; + } + }; + + textsecure.EventTarget = EventTarget; +}()); + /* * vim: ts=4:sw=4:expandtab */ @@ -36745,7 +36825,9 @@ function MessageReceiver(url, username, password, signalingKey, attachment_serve this.number = unencoded[0]; this.deviceId = unencoded[1]; } -MessageReceiver.prototype = { + +MessageReceiver.prototype = new textsecure.EventTarget(); +MessageReceiver.prototype.extend({ constructor: MessageReceiver, connect: function() { if (this.socket && this.socket.readyState !== WebSocket.CLOSED) { @@ -37103,63 +37185,8 @@ MessageReceiver.prototype = { return Promise.all(promises).then(function() { return decrypted; }); - }, - - /* Implements EventTarget */ - dispatchEvent: function(ev) { - if (!(ev instanceof Event)) { - throw new Error('Expects an event'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[ev.type]; - if (typeof listeners === 'object') { - for (var i=0; i < listeners.length; ++i) { - if (typeof listeners[i] === 'function') { - listeners[i].call(null, ev); - } - } - } - }, - addEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - if (typeof listeners !== 'object') { - listeners = []; - } - listeners.push(callback); - this.listeners[eventName] = listeners; - }, - removeEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - for (var i=0; i < listeners.length; ++ i) { - if (listeners[i] === callback) { - listeners.splice(i, 1); - return; - } - } - this.listeners[eventName] = listeners; } - -}; +}); window.textsecure = window.textsecure || {}; @@ -37698,10 +37725,11 @@ textsecure.MessageSender.prototype = { sender.sendRequestContactSyncMessage().then(function() { sender.sendRequestGroupSyncMessage(); }); - this.timeout = setTimout(this.onTimeout.bind(this), 60000); + this.timeout = setTimeout(this.onTimeout.bind(this), 60000); } - SyncRequest.prototype = { + SyncRequest.prototype = new textsecure.EventTarget(); + SyncRequest.prototype.extend({ constructor: SyncRequest, onContactSyncComplete: function() { this.contactSync = true; @@ -37726,62 +37754,8 @@ textsecure.MessageSender.prototype = { this.receiver.removeEventListener('contactsync', this.oncontact); this.receiver.removeEventListener('groupSync', this.ongroup); delete this.listeners; - }, - - /* Implements EventTarget */ /// TODO: Dedupe this same code in MessageReceiver - dispatchEvent: function(ev) { - if (!(ev instanceof Event)) { - throw new Error('Expects an event'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[ev.type]; - if (typeof listeners === 'object') { - for (var i=0; i < listeners.length; ++i) { - if (typeof listeners[i] === 'function') { - listeners[i].call(null, ev); - } - } - } - }, - addEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - if (typeof listeners !== 'object') { - listeners = []; - } - listeners.push(callback); - this.listeners[eventName] = listeners; - }, - removeEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - for (var i=0; i < listeners.length; ++ i) { - if (listeners[i] === callback) { - listeners.splice(i, 1); - return; - } - } - this.listeners[eventName] = listeners; } - }; + }); textsecure.SyncRequest = function(sender, receiver) { var syncRequest = new SyncRequest(sender, receiver); diff --git a/libtextsecure/event_target.js b/libtextsecure/event_target.js new file mode 100644 index 000000000..e3833d631 --- /dev/null +++ b/libtextsecure/event_target.js @@ -0,0 +1,79 @@ +/* + * vim: ts=4:sw=4:expandtab + * + * Implements EventTarget + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget + * + */ + +;(function () { + 'use strict'; + window.textsecure = window.textsecure || {}; + + function EventTarget() { + } + + EventTarget.prototype = { + constructor: EventTarget, + dispatchEvent: function(ev) { + if (!(ev instanceof Event)) { + throw new Error('Expects an event'); + } + if (this.listeners === null || typeof this.listeners !== 'object') { + this.listeners = {}; + } + var listeners = this.listeners[ev.type]; + if (typeof listeners === 'object') { + for (var i=0; i < listeners.length; ++i) { + if (typeof listeners[i] === 'function') { + listeners[i].call(null, ev); + } + } + } + }, + addEventListener: function(eventName, callback) { + if (typeof eventName !== 'string') { + throw new Error('First argument expects a string'); + } + if (typeof callback !== 'function') { + throw new Error('Second argument expects a function'); + } + if (this.listeners === null || typeof this.listeners !== 'object') { + this.listeners = {}; + } + var listeners = this.listeners[eventName]; + if (typeof listeners !== 'object') { + listeners = []; + } + listeners.push(callback); + this.listeners[eventName] = listeners; + }, + removeEventListener: function(eventName, callback) { + if (typeof eventName !== 'string') { + throw new Error('First argument expects a string'); + } + if (typeof callback !== 'function') { + throw new Error('Second argument expects a function'); + } + if (this.listeners === null || typeof this.listeners !== 'object') { + this.listeners = {}; + } + var listeners = this.listeners[eventName]; + for (var i=0; i < listeners.length; ++ i) { + if (listeners[i] === callback) { + listeners.splice(i, 1); + return; + } + } + this.listeners[eventName] = listeners; + }, + extend: function(obj) { + for (var prop in obj) { + this[prop] = obj[prop]; + } + return this; + } + }; + + textsecure.EventTarget = EventTarget; +}()); diff --git a/libtextsecure/message_receiver.js b/libtextsecure/message_receiver.js index f17a79001..f2612b140 100644 --- a/libtextsecure/message_receiver.js +++ b/libtextsecure/message_receiver.js @@ -13,7 +13,9 @@ function MessageReceiver(url, username, password, signalingKey, attachment_serve this.number = unencoded[0]; this.deviceId = unencoded[1]; } -MessageReceiver.prototype = { + +MessageReceiver.prototype = new textsecure.EventTarget(); +MessageReceiver.prototype.extend({ constructor: MessageReceiver, connect: function() { if (this.socket && this.socket.readyState !== WebSocket.CLOSED) { @@ -371,63 +373,8 @@ MessageReceiver.prototype = { return Promise.all(promises).then(function() { return decrypted; }); - }, - - /* Implements EventTarget */ - dispatchEvent: function(ev) { - if (!(ev instanceof Event)) { - throw new Error('Expects an event'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[ev.type]; - if (typeof listeners === 'object') { - for (var i=0; i < listeners.length; ++i) { - if (typeof listeners[i] === 'function') { - listeners[i].call(null, ev); - } - } - } - }, - addEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - if (typeof listeners !== 'object') { - listeners = []; - } - listeners.push(callback); - this.listeners[eventName] = listeners; - }, - removeEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - for (var i=0; i < listeners.length; ++ i) { - if (listeners[i] === callback) { - listeners.splice(i, 1); - return; - } - } - this.listeners[eventName] = listeners; } - -}; +}); window.textsecure = window.textsecure || {}; diff --git a/libtextsecure/sync_request.js b/libtextsecure/sync_request.js index 240eadac0..3d81039b9 100644 --- a/libtextsecure/sync_request.js +++ b/libtextsecure/sync_request.js @@ -19,10 +19,11 @@ sender.sendRequestContactSyncMessage().then(function() { sender.sendRequestGroupSyncMessage(); }); - this.timeout = setTimout(this.onTimeout.bind(this), 60000); + this.timeout = setTimeout(this.onTimeout.bind(this), 60000); } - SyncRequest.prototype = { + SyncRequest.prototype = new textsecure.EventTarget(); + SyncRequest.prototype.extend({ constructor: SyncRequest, onContactSyncComplete: function() { this.contactSync = true; @@ -47,62 +48,8 @@ this.receiver.removeEventListener('contactsync', this.oncontact); this.receiver.removeEventListener('groupSync', this.ongroup); delete this.listeners; - }, - - /* Implements EventTarget */ /// TODO: Dedupe this same code in MessageReceiver - dispatchEvent: function(ev) { - if (!(ev instanceof Event)) { - throw new Error('Expects an event'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[ev.type]; - if (typeof listeners === 'object') { - for (var i=0; i < listeners.length; ++i) { - if (typeof listeners[i] === 'function') { - listeners[i].call(null, ev); - } - } - } - }, - addEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - if (typeof listeners !== 'object') { - listeners = []; - } - listeners.push(callback); - this.listeners[eventName] = listeners; - }, - removeEventListener: function(eventName, callback) { - if (typeof eventName !== 'string') { - throw new Error('First argument expects a string'); - } - if (typeof callback !== 'function') { - throw new Error('Second argument expects a function'); - } - if (this.listeners === null || typeof this.listeners !== 'object') { - this.listeners = {}; - } - var listeners = this.listeners[eventName]; - for (var i=0; i < listeners.length; ++ i) { - if (listeners[i] === callback) { - listeners.splice(i, 1); - return; - } - } - this.listeners[eventName] = listeners; } - }; + }); textsecure.SyncRequest = function(sender, receiver) { var syncRequest = new SyncRequest(sender, receiver);