Mercurial > eldonilo > lightstring
changeset 12:9fbd0e3678b5
add comments, jsdoc syntax + move the parser and the serializer to the Lightstring namespace so they don't get recreated at every new Lightstring.Connection
author | Sonny Piers <sonny.piers@gmail.com> |
---|---|
date | Sun, 15 Jan 2012 03:47:28 +0100 |
parents | efe98c3634e4 |
children | 9aeb0750b9d1 |
files | lightstring.js |
diffstat | 1 files changed, 86 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/lightstring.js +++ b/lightstring.js @@ -16,27 +16,66 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +/** + * @namespace No code from lightstring should be callable outside this namespace/scope. + */ var Lightstring = { + /** + * @namespace Holds XMPP namespaces. + * + */ NS: {}, + /** + * @namespace Holds XMPP stanza builders. + * + */ stanza: {}, + /** + * @private + */ + parser: new DOMParser(), + /** + * @private + */ + serializer: new XMLSerializer(), + /** + * @function Transforms a XML string to a DOM object. + * @param {String} aString XML string + * @returns {Object} Domified XML. + */ + xml2dom: function(aString) { + return this.parser.parseFromString(aString, 'text/xml').documentElement; + }, + /** + * @function Transforms a DOM object to a XML string. + * @param {Object} aString DOM object + * @returns {String} Stringified DOM. + */ + dom2xml: function(aElement) { + return this.serializer.serializeToString(aElement); + }, }; +/** + * @constructor Creates a new Lightstring connection + * @param {String} [aService] The Websocket service URL. + * @memberOf Lightstring + */ Lightstring.Connection = function (aService) { - var parser = new DOMParser(); - var serializer = new XMLSerializer(); - this.service = aService; + if(aService) + this.service = aService; this.handlers = {}; this.iqid = 1024; this.getNewId = function() { this.iqid++; return 'sendiq:'+this.iqid; }; - this.parse = function(str) { - return parser.parseFromString(str, 'text/xml').documentElement; - }; - this.serialize = function(elm) { - return serializer.serializeToString(elm); - }; + /** + * @function Create and open a websocket then go though the XMPP authentification process. + * @param {String} [aJid] The JID (Jabber id) to use. + * @param {String} [aPassword] The associated password. + */ this.connect = function(aJid, aPassword) { this.emit('connecting'); if(aJid) @@ -68,17 +107,13 @@ Lightstring.Connection = function (aServ this.socket.addEventListener('open', function() { if(this.protocol !== 'xmpp') throw "Lightstring: The server located at "+that.service+" is not XMPP aware."; + //FIXME no ending "/" - node-xmpp-bosh bug var stream = "<stream:stream to='"+that.domain+"'\ xmlns='jabber:client'\ xmlns:stream='http://etherx.jabber.org/streams'\ version='1.0'/>"; - //FIXME should be this but doesn't works with node-xmpp-bosh - //~ var stream = - //~ "<stream:stream to='"+that.domain+"'\ - xmlns='jabber:client'\ - xmlns:stream='http://etherx.jabber.org/streams'\ - version='1.0'/>"; + that.socket.send(stream) that.emit('XMLOutput', stream); }); @@ -90,7 +125,7 @@ Lightstring.Connection = function (aServ }); this.socket.addEventListener('message', function(e) { that.emit('XMLInput', e.data); - var elm = that.parse(e.data); + var elm = Lightstring.xml2dom(e.data); that.emit('DOMInput', elm); that.emit(elm.tagName, elm); @@ -98,14 +133,19 @@ Lightstring.Connection = function (aServ that.emit(elm.getAttribute('id'), elm); }); }; + /** + * @function Send a message. + * @param {String|Object} aStanza The message to send. + * @param {Function} [aCallback] A callback that will be called when the answer will answer. + */ this.send = function(aStanza, aCallback) { if(typeof aStanza === 'string') { var str = aStanza; - var elm = this.parse(str); + var elm = Lightstring.xml2dom(str); } else if(aStanza instanceof Element) { var elm = aStanza; - var str = this.serialize(elm); + var str = this.dom2xml(elm); } else { that.emit('error', 'Unsupported data type.'); @@ -116,7 +156,7 @@ Lightstring.Connection = function (aServ var id = elm.getAttribute('id'); if(!id) { elm.setAttribute('id', this.getNewId()) - str = this.serialize(elm) + str = Lightstring.dom2xml(elm) } if(aCallback) this.on(elm.getAttribute('id'), aCallback); @@ -130,35 +170,47 @@ Lightstring.Connection = function (aServ this.emit('XMLOutput', str); this.emit('DOMOutput', elm); }; + /** + * @function Close the XMPP stream and the socket. + */ this.disconnect = function() { this.emit('disconnecting'); this.send('</stream:stream>'); this.socket.close(); }; - this.emit = function(name, data) { - var handlers = this.handlers[name]; + /** + * @function Emit an event. + * @param {String} aName The event name. + * @param {Function|Array|Object} [aData] Data about the event. + */ + this.emit = function(aName, aData) { + var handlers = this.handlers[aName]; if(!handlers) return; //FIXME Better idea than passing the context as argument? for(var i=0; i<handlers.length; i++) - handlers[i](data, this); + handlers[i](aData, this); - if(name.match('sendiq:')) - delete this.handlers[name]; + if(aName.match('sendiq:')) + delete this.handlers[aName]; }; - this.on = function(name, callback) { - if(!this.handlers[name]) - this.handlers[name] = []; - this.handlers[name].push(callback); + /** + * @function Register an event handler. + * @param {String} aName The event name. + * @param {Function} aCallback The callback to call when the event is emitted. + */ + this.on = function(aName, callback) { + if(!this.handlers[aName]) + this.handlers[aName] = []; + this.handlers[aName].push(callback); }; //FIXME do this! - this.once = function(name, callback) { - if(!this.handlers[name]) - this.handlers[name] = []; - this.handlers[name].push(callback); - }; - //Internal + //~ this.once = function(name, callback) { + //~ if(!this.handlers[name]) + //~ this.handlers[name] = []; + //~ this.handlers[name].push(callback); + //~ }; this.on('stream:features', function(stanza, that) { var nodes = stanza.querySelectorAll('mechanism'); //SASL/Auth features @@ -210,7 +262,6 @@ Lightstring.Connection = function (aServ }); } }); - //Internal this.on('success', function(stanza, that) { that.send( "<stream:stream to='"+that.domain+"'\ @@ -219,11 +270,9 @@ Lightstring.Connection = function (aServ version='1.0' />" ); }); - //Internal this.on('failure', function(stanza, that) { that.emit('conn-error', stanza.firstChild.tagName); }); - //Internal this.on('challenge', function(stanza, that) { //FIXME this is mostly Strophe code