diff blog.js @ 0:f62b5c395a48

Initial commit.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Sat, 04 Jun 2011 05:02:47 +0200
parents
children 82905edac9d8
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/blog.js
@@ -0,0 +1,243 @@
+//'use strict';
+
+const BOSH_SERVICE = 'http://linkmauve.fr/http-bind/';
+var conn = null;
+var jid = 'blog@linkmauve.fr'; // FIXME: Strophe should accept anonymous connections.
+var password = 'blog';
+var service = 'psgxs.linkmauve.fr';
+var node = 'blog';
+var re = true;
+
+var params = (function() {
+	var vars = {};
+	var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split(';');
+
+	for(var i = 0; i < hashes.length; i++) {
+		var s = hashes[i].indexOf('=');
+		var key = hashes[i].substring(0, s);
+		var value = hashes[i].substring(s+1);
+		vars[key] = value;
+	}
+
+	return vars;
+})();
+
+if (params.jid)
+	service = params.jid;
+
+if (params.node)
+	node = params.node;
+
+var logs = document.getElementById('log');
+if (params.debug)
+	logs.parentNode.hidden = false;
+
+var received = {};
+var messages = document.getElementById('messages');
+
+function log(msg, error) {
+	var p = document.createElementNS(ns.xhtml, 'p');
+	p.appendChild(document.createTextNode(msg));
+
+	if (!error)
+		p.setAttributeNS(null, 'class', 'error');
+
+	logs.appendChild(p);
+}
+
+function rawInput(data) {
+	log('RECV: ' + data, 1);
+}
+
+function rawOutput(data) {
+	log('SENT: ' + data, 1);
+}
+
+var html = function(name, id) {
+	return received[name][id].html;
+}
+
+var date = function(name, id) {
+	return received[name][id].date;
+}
+
+var updateMessage = function(name, id) {
+	var divs = messages.getElementsByTagNameNS(ns.xhtml, 'div');
+	var container = null;
+
+	for (var i in divs) {
+		var div = divs[i]
+		if (typeof div != 'object')
+			continue;
+
+		if (div.getAttributeNS(ns.idq, 'jid') === name) {
+			container = div;
+			break;
+		}
+	}
+
+	if (!container) {
+		var container = document.createElementNS(ns.xhtml, 'div');
+		container.setAttributeNS(ns.idq, 'jid', name);
+		messages.appendChild(container);
+	}
+
+	var articles = container.getElementsByTagNameNS(ns.xhtml, 'article');
+	for (var i in articles) {
+		var article = articles[i];
+		if (typeof article != 'object')
+			continue;
+
+		if (article.getAttributeNS(ns.idq, 'id') === id) {
+			container.replaceChild(html(name, id), article);
+			return;
+		}
+	}
+
+	var article = html(name, id);
+
+	if (!container.firstChild)
+		container.appendChild(article);
+	else {
+		var d = date(name, id);
+		var toInsert;
+		for (var i in articles) {
+			var a = articles[i];
+			if (typeof a != 'object')
+				continue;
+
+			var ad = new Date();
+			ad.set8601(a.getAttributeNS(ns.idq, 'date'));
+
+			if (ad < d) {
+				toInsert = a;
+				break;
+			}
+		}
+
+		if (toInsert)
+			container.insertBefore(article, toInsert);
+		else
+			container.appendChild(article);
+	}
+}
+
+var convert = function(id, xml) {
+	var ns = xml['@xmlns'];
+	if (ns in parsers)
+		return new parsers[ns](id, xml);
+	return new parsers[''](id, xml);
+};
+
+var parsePubSubEvent = function(stanza) {
+	var e = {};
+
+	e.service = stanza.getAttribute('from');
+
+	var pubsub = stanza.getChild('event', ns.pse);
+	if (!pubsub) {
+		pubsub = stanza.getChild('pubsub', ns.ps);
+		if (!pubsub)
+			return;
+	}
+	e.ns = pubsub.getAttribute('xmlns');
+
+	var items = pubsub.getChild('items', e.ns);
+	if (!items)
+		return;
+
+	e.node = items.getAttribute('node');
+	items = items.getChildren('item', e.ns);
+	if (!items)
+		return;
+
+	e.name = e.service + '/' + e.node;
+
+	e.items = {};
+	for (var i in items) {
+		var item = items[i];
+		if (!item.getAttribute)
+			continue;
+
+		var pl = item.getChild();
+		if (!pl)
+			continue;
+
+		var id = item.getAttribute('id');
+
+		e.items[id] = pl;
+	}
+
+	return e;
+}
+
+var onMessages = function(stanza) {
+	conn.addHandler(onMessages, null, 'message', null, null, null);
+
+	log('message');
+	stanza = xml2json(stanza);
+	var e = parsePubSubEvent(stanza);
+
+	if (!received[e.name])
+		received[e.name] = {};
+
+	for (var id in e.items) {
+		received[e.name][id] = convert(id, e.items[id]);
+		updateMessage(e.name, id);
+	}
+}
+
+var onInfo = function(stanza) {
+	log('info');
+	/*var query = stanza.getElementsByTagNameNS(ns.info, 'query')[0];
+	var x = query.getElementsByTagNameNS(ns.data, 'x')[0];
+	var form = forms.parse(x);*/
+}
+
+var onSubscribed = function(stanza) {
+	log('subscribed');
+	var type = stanza.getAttribute('type');
+	if (type !== 'result') {
+		messages.innerHTML = 'Error, impossible to retrieve messages.';
+		conn.disconnect();
+	}
+}
+
+function onConnect(status) {
+	if (status == Strophe.Status.CONNECTING) {
+		log('Strophe is connecting.');
+	} else if (status == Strophe.Status.CONNFAIL) {
+		log('Strophe failed to connect.');
+	} else if (status == Strophe.Status.AUTHENTICATING) {
+		log('Strophe is authenticating.');
+	} else if (status == Strophe.Status.DISCONNECTING) {
+		log('Strophe is disconnecting.');
+	} else if (status == Strophe.Status.DISCONNECTED) {
+		log('Strophe is disconnected.');
+		if (re)
+			conn.connect(jid, password, onConnect);
+	} else if (status == Strophe.Status.CONNECTED) {
+		log('Strophe is connected.');
+		conn.addHandler(onMessages, null, 'message', null, null, null);
+		conn.send($pres().tree());
+		conn.pubsub.subscribe(jid, service, node, undefined, onMessages, onSubscribed);
+		if (params.no === 'server') {
+			conn.pubsub.items(jid, service, node, onMessages);
+			conn.pubsub.info(jid, service, node, onInfo);
+		}
+	} else
+		log('Strophe is '+status+'.');
+}
+
+window.addEventListener('load', function () {
+	conn = new Strophe.Connection(BOSH_SERVICE);
+	conn.rawInput = rawInput;
+	conn.rawOutput = rawOutput;
+	conn.connect(jid, password, onConnect);
+}, false);
+
+window.addEventListener('unload', function (e) {
+	re = false;
+	conn.disconnect();
+	e.preventDefault();
+}, false);