Mercurial > eldonilo > barbecue
view sxe-document.js @ 5:03ef53b969bd
Add XMPP support.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 31 Jan 2012 01:09:41 +0100 |
parents | |
children | 24aa8dccb170 |
line wrap: on
line source
'use strict'; var Document = function(initiator, name, host, domId, prolog) { this.initiator = initiator; this.name = name; this.host = host; this.prolog = prolog || 'data:application/xhtml+xml,%3C%3Fxml%20version%3D%271.0%27%3F%3E%0A%3C%21DOCTYPE%20html%3E%0A'; this.state = 'not-started'; this.records = {}; this.dom = document.getElementById(domId); }; Document.prototype = { add: function(jid, child) { var record = new Record(jid, child); if (record.rid in this.records) console.log('duplicate new'); this.records[record.rid] = record; record.toDOM(this.records, this.dom); }, update: function(jid, child) { var target = child.getAttributeNS(null, 'target'); if (!(target in this.records)) return; // Ignore it. var record = this.records[target]; console.log(record, child); child.setAttributeNS(null, 'rid', target); var version = +child.getAttributeNS(null, 'version'); if (this.state === 'getting-state') record.version = version; else record.version++; if (record.version === version) { var type = child.getAttributeNS(null, 'type'); if (type === 'text' || type === 'attr' || type === 'comment') { var chdata = child.getAttributeNS(null, 'chdata'); var replacefrom = +child.getAttributeNS(null, 'replacefrom'); var replacen = +child.getAttributeNS(null, 'replacen'); if (chdata && replacefrom && replacen) { var string = record.chdata.substr(0, replacefrom); string += chdata; string += record.chdata.substr(replacefrom + replacen); child.removeAttributeNS(null, 'replacefrom'); child.removeAttributeNS(null, 'replacen'); child.setAttributeNS(null, 'chdata', string); } } record.update(jid, child); record.toDOM(this.records, this.dom); } else ; // Not sure I understand correctly. }, remove: function(jid, child) { var rid = child.getAttributeNS(null, 'target'); this.records[rid].remove(this.records); delete this.records[rid]; }, processState: function(jid, elements) { var i = 0; var first = elements[0]; if (first.localName === 'document-begin') { if (this.state !== 'not-started') return; //TODO: the session has already started. i = 1; this.prolog = first.getAttributeNS(null, 'prolog'); this.state = 'getting-session'; } //TODO: if the session isn’t started, should ignore changes? for (; i < elements.length; i++) { var child = elements[i]; var change = child.localName; switch (change) { case 'new': doc.add(jid, child); break; case 'set': doc.update(jid, child); break; case 'remove': doc.remove(jid, child); break; case 'document-end': this.state = 'started'; break; } } }, createState: function(root, parent, state) { var children = root.childNodes; for (var i = 0; i < children.length; i++) { var child = children[i]; var element = document.createElementNS(Lightstring.NS.sxe, 'new'); var rid = Lightstring.newId('GUID'); element.setAttributeNS(null, 'rid', rid); if (parent) element.setAttributeNS(null, 'parent', parent); switch (child.nodeType) { case 1: element.setAttributeNS(null, 'type', 'element'); element.setAttributeNS(null, 'ns', child.namespaceURI); element.setAttributeNS(null, 'name', child.localName); state.push(element); //TODO: move that elsewhere, or make it prettier. var convertAttr = function(attr) { var element = document.createElementNS(Lightstring.NS.sxe, 'new'); var arid = Lightstring.newId('GUID'); element.setAttributeNS(null, 'rid', arid); element.setAttributeNS(null, 'parent', rid); if (attr.namespaceURI) element.setAttributeNS(null, 'ns', attr.namespaceURI); element.setAttributeNS(null, 'name', attr.localName); element.setAttributeNS(null, 'chdata', attr.textContent); state.push(element); }; for (var j = 0; j < child.attributes.length; j++) convertAttr(child.attributes[j]); state = this.createState(child, rid, state); break; case 3: element.setAttributeNS(null, 'type', 'text'); element.setAttributeNS(null, 'chdata', child.textContent); state.push(element); break; case 7: element.setAttributeNS(null, 'type', 'processinginstruction'); element.setAttributeNS(null, 'pitarget', child.target); element.setAttributeNS(null, 'pidata', child.data); state.push(element); break; case 8: element.setAttributeNS(null, 'type', 'comment'); element.setAttributeNS(null, 'chdata', child.textContent); state.push(element); break; } } return state; } };