Mercurial > eldonilo > lightstring
comparison lightstring.js @ 17:b7bd814333eb
Move methods to the prototype.
author | Sonny Piers <sonny.piers@gmail.com> |
---|---|
date | Sun, 22 Jan 2012 12:58:45 +0100 |
parents | 6707f450549e |
children | 48bc65a0e0f1 |
comparison
equal
deleted
inserted
replaced
16:6707f450549e | 17:b7bd814333eb |
---|---|
83 this.iqid = 1024; | 83 this.iqid = 1024; |
84 this.getNewId = function() { | 84 this.getNewId = function() { |
85 this.iqid++; | 85 this.iqid++; |
86 return 'sendiq:' + this.iqid; | 86 return 'sendiq:' + this.iqid; |
87 }; | 87 }; |
88 /** | |
89 * @function Create and open a websocket then go though the XMPP authentification process. | |
90 * @param {String} [aJid] The JID (Jabber id) to use. | |
91 * @param {String} [aPassword] The associated password. | |
92 */ | |
93 this.connect = function(aJid, aPassword) { | |
94 this.emit('connecting'); | |
95 if (aJid) | |
96 this.jid = aJid; | |
97 if (this.jid) { | |
98 this.host = this.jid.split('@')[1]; | |
99 this.node = this.jid.split('@')[0]; | |
100 this.resource = this.jid.split('/')[1]; | |
101 } | |
102 if (aPassword) | |
103 this.password = aPassword; | |
104 | |
105 if (!this.jid) | |
106 throw 'Lightstring: Connection.jid is undefined.'; | |
107 if (!this.password) | |
108 throw 'Lightstring: Connection.password is undefined.'; | |
109 if (!this.service) | |
110 throw 'Lightstring: Connection.service is undefined.'; | |
111 | |
112 //"Bug 695635 - tracking bug: unprefix WebSockets" https://bugzil.la/695635 | |
113 try { | |
114 this.socket = new WebSocket(this.service, 'xmpp'); | |
115 } | |
116 catch (error) { | |
117 this.socket = new MozWebSocket(this.service, 'xmpp'); | |
118 } | |
119 | |
120 var that = this; | |
121 this.socket.addEventListener('open', function() { | |
122 if (this.protocol !== 'xmpp') | |
123 console.error('Lightstring: The server located at '+ that.service + ' doesn\'t seems to be XMPP aware.'); | |
124 | |
125 var stream = Lightstring.stanza.stream.open(that.host); | |
126 | |
127 that.socket.send(stream); | |
128 that.emit('XMLOutput', stream); | |
129 }); | |
130 this.socket.addEventListener('error', function(e) { | |
131 that.emit('error', e.data); | |
132 console.log(e.data); | |
133 }); | |
134 this.socket.addEventListener('close', function(e) { | |
135 that.emit('disconnected', e.data); | |
136 }); | |
137 this.socket.addEventListener('message', function(e) { | |
138 that.emit('XMLInput', e.data); | |
139 var elm = Lightstring.xml2dom(e.data); | |
140 that.emit('DOMInput', elm); | |
141 that.emit(elm.tagName, elm); | |
142 | |
143 if (elm.tagName === 'iq') | |
144 that.emit(elm.getAttribute('id'), elm); | |
145 }); | |
146 }; | |
147 /** | |
148 * @function Send a message. | |
149 * @param {String|Object} aStanza The message to send. | |
150 * @param {Function} [aCallback] Executed on answer. (stanza must be iq) | |
151 */ | |
152 this.send = function(aStanza, aCallback) { | |
153 if (typeof aStanza === 'string') { | |
154 var str = aStanza; | |
155 var elm = Lightstring.xml2dom(str); | |
156 } | |
157 else if (aStanza instanceof Element) { | |
158 var elm = aStanza; | |
159 var str = this.dom2xml(elm); | |
160 } | |
161 else { | |
162 this.emit('error', 'Unsupported data type.'); | |
163 return; | |
164 } | |
165 | |
166 | |
167 if (elm.tagName === 'iq') { | |
168 var id = elm.getAttribute('id'); | |
169 if (!id) { | |
170 elm.setAttribute('id', this.getNewId()); | |
171 str = Lightstring.dom2xml(elm); | |
172 } | |
173 if (aCallback) | |
174 this.on(elm.getAttribute('id'), aCallback); | |
175 } | |
176 else if (aCallback) { | |
177 this.emit('warning', 'Callback can\'t be called with non-iq stanza.'); | |
178 } | |
179 | |
180 | |
181 this.socket.send(str); | |
182 this.emit('XMLOutput', str); | |
183 this.emit('DOMOutput', elm); | |
184 }; | |
185 /** | |
186 * @function Closes the XMPP stream and the socket. | |
187 */ | |
188 this.disconnect = function() { | |
189 this.emit('disconnecting'); | |
190 var stream = Lighstring.stanza.stream.close(); | |
191 this.send(stream); | |
192 that.emit('XMLOutput', stream); | |
193 this.socket.close(); | |
194 }; | |
195 /** | |
196 * @function Emits an event. | |
197 * @param {String} aName The event name. | |
198 * @param {Function|Array|Object} [aData] Data about the event. | |
199 */ | |
200 this.emit = function(aName, aData) { | |
201 var handlers = this.handlers[aName]; | |
202 if (!handlers) | |
203 return; | |
204 | |
205 //FIXME Better idea than passing the context as argument? | |
206 for (var i = 0; i < handlers.length; i++) | |
207 handlers[i](aData, this); | |
208 | |
209 if (aName.match('sendiq:')) | |
210 delete this.handlers[aName]; | |
211 }; | |
212 /** | |
213 * @function Register an event handler. | |
214 * @param {String} aName The event name. | |
215 * @param {Function} aCallback The callback to call when the event is emitted. | |
216 */ | |
217 this.on = function(aName, callback) { | |
218 if (!this.handlers[aName]) | |
219 this.handlers[aName] = []; | |
220 this.handlers[aName].push(callback); | |
221 }; | |
222 //FIXME do this! | |
223 //~ this.once = function(name, callback) { | |
224 //~ if(!this.handlers[name]) | |
225 //~ this.handlers[name] = []; | |
226 //~ this.handlers[name].push(callback); | |
227 //~ }; | |
228 this.on('stream:features', function(stanza, that) { | 88 this.on('stream:features', function(stanza, that) { |
229 var nodes = stanza.querySelectorAll('mechanism'); | 89 var nodes = stanza.querySelectorAll('mechanism'); |
230 //SASL/Auth features | 90 //SASL/Auth features |
231 if (nodes.length > 0) { | 91 if (nodes.length > 0) { |
232 that.emit('mechanisms', stanza); | 92 that.emit('mechanisms', stanza); |
352 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" | 212 "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" |
353 + btoa(responseText) + | 213 + btoa(responseText) + |
354 '</response>'); | 214 '</response>'); |
355 }); | 215 }); |
356 }; | 216 }; |
217 Lightstring.Connection.prototype = { | |
218 /** | |
219 * @function Create and open a websocket then go though the XMPP authentification process. | |
220 * @param {String} [aJid] The JID (Jabber id) to use. | |
221 * @param {String} [aPassword] The associated password. | |
222 */ | |
223 connect: function(aJid, aPassword) { | |
224 this.emit('connecting'); | |
225 if (aJid) | |
226 this.jid = aJid; | |
227 if (this.jid) { | |
228 this.host = this.jid.split('@')[1]; | |
229 this.node = this.jid.split('@')[0]; | |
230 this.resource = this.jid.split('/')[1]; | |
231 } | |
232 if (aPassword) | |
233 this.password = aPassword; | |
234 | |
235 if (!this.jid) | |
236 throw 'Lightstring: Connection.jid is undefined.'; | |
237 if (!this.password) | |
238 throw 'Lightstring: Connection.password is undefined.'; | |
239 if (!this.service) | |
240 throw 'Lightstring: Connection.service is undefined.'; | |
241 | |
242 //"Bug 695635 - tracking bug: unprefix WebSockets" https://bugzil.la/695635 | |
243 try { | |
244 this.socket = new WebSocket(this.service, 'xmpp'); | |
245 } | |
246 catch (error) { | |
247 this.socket = new MozWebSocket(this.service, 'xmpp'); | |
248 } | |
249 | |
250 var that = this; | |
251 this.socket.addEventListener('open', function() { | |
252 if (this.protocol !== 'xmpp') | |
253 console.error('Lightstring: The server located at '+ that.service + ' doesn\'t seems to be XMPP aware.'); | |
254 | |
255 var stream = Lightstring.stanza.stream.open(that.host); | |
256 | |
257 that.socket.send(stream); | |
258 that.emit('XMLOutput', stream); | |
259 }); | |
260 this.socket.addEventListener('error', function(e) { | |
261 that.emit('error', e.data); | |
262 console.log(e.data); | |
263 }); | |
264 this.socket.addEventListener('close', function(e) { | |
265 that.emit('disconnected', e.data); | |
266 }); | |
267 this.socket.addEventListener('message', function(e) { | |
268 that.emit('XMLInput', e.data); | |
269 var elm = Lightstring.xml2dom(e.data); | |
270 that.emit('DOMInput', elm); | |
271 that.emit(elm.tagName, elm); | |
272 | |
273 if (elm.tagName === 'iq') | |
274 that.emit(elm.getAttribute('id'), elm); | |
275 }); | |
276 }, | |
277 /** | |
278 * @function Send a message. | |
279 * @param {String|Object} aStanza The message to send. | |
280 * @param {Function} [aCallback] Executed on answer. (stanza must be iq) | |
281 */ | |
282 send: function(aStanza, aCallback) { | |
283 if (typeof aStanza === 'string') { | |
284 var str = aStanza; | |
285 var elm = Lightstring.xml2dom(str); | |
286 } | |
287 else if (aStanza instanceof Element) { | |
288 var elm = aStanza; | |
289 var str = this.dom2xml(elm); | |
290 } | |
291 else { | |
292 this.emit('error', 'Unsupported data type.'); | |
293 return; | |
294 } | |
295 | |
296 | |
297 if (elm.tagName === 'iq') { | |
298 var id = elm.getAttribute('id'); | |
299 if (!id) { | |
300 elm.setAttribute('id', this.getNewId()); | |
301 str = Lightstring.dom2xml(elm); | |
302 } | |
303 if (aCallback) | |
304 this.on(elm.getAttribute('id'), aCallback); | |
305 } | |
306 else if (aCallback) { | |
307 this.emit('warning', 'Callback can\'t be called with non-iq stanza.'); | |
308 } | |
309 | |
310 | |
311 this.socket.send(str); | |
312 this.emit('XMLOutput', str); | |
313 this.emit('DOMOutput', elm); | |
314 }, | |
315 /** | |
316 * @function Closes the XMPP stream and the socket. | |
317 */ | |
318 disconnect: function() { | |
319 this.emit('disconnecting'); | |
320 var stream = Lightstring.stanza.stream.close(); | |
321 this.send(stream); | |
322 this.emit('XMLOutput', stream); | |
323 this.socket.close(); | |
324 }, | |
325 /** | |
326 * @function Emits an event. | |
327 * @param {String} aName The event name. | |
328 * @param {Function|Array|Object} [aData] Data about the event. | |
329 */ | |
330 emit: function(aName, aData) { | |
331 var handlers = this.handlers[aName]; | |
332 if (!handlers) | |
333 return; | |
334 | |
335 //FIXME Better idea than passing the context as argument? | |
336 for (var i = 0; i < handlers.length; i++) | |
337 handlers[i](aData, this); | |
338 | |
339 if (aName.match('sendiq:')) | |
340 delete this.handlers[aName]; | |
341 }, | |
342 /** | |
343 * @function Register an event handler. | |
344 * @param {String} aName The event name. | |
345 * @param {Function} aCallback The callback to call when the event is emitted. | |
346 */ | |
347 on: function(aName, callback) { | |
348 if (!this.handlers[aName]) | |
349 this.handlers[aName] = []; | |
350 this.handlers[aName].push(callback); | |
351 } | |
352 //FIXME do this! | |
353 //~ this.once = function(name, callback) { | |
354 //~ if(!this.handlers[name]) | |
355 //~ this.handlers[name] = []; | |
356 //~ this.handlers[name].push(callback); | |
357 //~ }; | |
358 }; |