// Generated by CoffeeScript 1.4.0 (function() { var Doc, MicroEvent, types, __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; if (typeof WEB === "undefined" || WEB === null) { types = require('../types'); } if (typeof WEB !== "undefined" && WEB !== null) { exports.extendDoc = function(name, fn) { return Doc.prototype[name] = fn; }; } Doc = (function() { function Doc(connection, name, openData) { this.connection = connection; this.name = name; this.shout = __bind(this.shout, this); this.flush = __bind(this.flush, this); openData || (openData = {}); this.version = openData.v; this.snapshot = openData.snaphot; if (openData.type) { this._setType(openData.type); } this.state = 'closed'; this.autoOpen = false; this._create = openData.create; this.inflightOp = null; this.inflightCallbacks = []; this.inflightSubmittedIds = []; this.pendingOp = null; this.pendingCallbacks = []; this.serverOps = {}; } Doc.prototype._xf = function(client, server) { var client_, server_; if (this.type.transformX) { return this.type.transformX(client, server); } else { client_ = this.type.transform(client, server, 'left'); server_ = this.type.transform(server, client, 'right'); return [client_, server_]; } }; Doc.prototype._otApply = function(docOp, isRemote) { var oldSnapshot; oldSnapshot = this.snapshot; this.snapshot = this.type.apply(this.snapshot, docOp); this.emit('change', docOp, oldSnapshot); if (isRemote) { return this.emit('remoteop', docOp, oldSnapshot); } }; Doc.prototype._connectionStateChanged = function(state, data) { switch (state) { case 'disconnected': this.state = 'closed'; if (this.inflightOp) { this.inflightSubmittedIds.push(this.connection.id); } this.emit('closed'); break; case 'ok': if (this.autoOpen) { this.open(); } break; case 'stopped': if (typeof this._openCallback === "function") { this._openCallback(data); } } return this.emit(state, data); }; Doc.prototype._setType = function(type) { var k, v, _ref; if (typeof type === 'string') { type = types[type]; } if (!(type && type.compose)) { throw new Error('Support for types without compose() is not implemented'); } this.type = type; if (type.api) { _ref = type.api; for (k in _ref) { v = _ref[k]; this[k] = v; } return typeof this._register === "function" ? this._register() : void 0; } else { return this.provides = {}; } }; Doc.prototype._onMessage = function(msg) { var callback, docOp, error, oldInflightOp, op, path, response, undo, value, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6; if (msg.open === true) { this.state = 'open'; this._create = false; if (this.created == null) { this.created = !!msg.create; } if (msg.type) { this._setType(msg.type); } if (msg.create) { this.created = true; this.snapshot = this.type.create(); } else { if (this.created !== true) { this.created = false; } if (msg.snapshot !== void 0) { this.snapshot = msg.snapshot; } } if (msg.v != null) { this.version = msg.v; } if (this.inflightOp) { response = { doc: this.name, op: this.inflightOp, v: this.version }; if (this.inflightSubmittedIds.length) { response.dupIfSource = this.inflightSubmittedIds; } this.connection.send(response); } else { this.flush(); } this.emit('open'); return typeof this._openCallback === "function" ? this._openCallback(null) : void 0; } else if (msg.open === false) { if (msg.error) { if (typeof console !== "undefined" && console !== null) { console.error("Could not open document: " + msg.error); } this.emit('error', msg.error); if (typeof this._openCallback === "function") { this._openCallback(msg.error); } } this.state = 'closed'; this.emit('closed'); if (typeof this._closeCallback === "function") { this._closeCallback(); } return this._closeCallback = null; } else if (msg.op === null && error === 'Op already submitted') { } else if ((msg.op === void 0 && msg.v !== void 0) || (msg.op && (_ref = msg.meta.source, __indexOf.call(this.inflightSubmittedIds, _ref) >= 0))) { oldInflightOp = this.inflightOp; this.inflightOp = null; this.inflightSubmittedIds.length = 0; error = msg.error; if (error) { if (this.type.invert) { undo = this.type.invert(oldInflightOp); if (this.pendingOp) { _ref1 = this._xf(this.pendingOp, undo), this.pendingOp = _ref1[0], undo = _ref1[1]; } this._otApply(undo, true); } else { this.emit('error', "Op apply failed (" + error + ") and the op could not be reverted"); } _ref2 = this.inflightCallbacks; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { callback = _ref2[_i]; callback(error); } } else { if (msg.v !== this.version) { throw new Error('Invalid version from server'); } this.serverOps[this.version] = oldInflightOp; this.version++; this.emit('acknowledge', oldInflightOp); _ref3 = this.inflightCallbacks; for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) { callback = _ref3[_j]; callback(null, oldInflightOp); } } return this.flush(); } else if (msg.op) { if (msg.v < this.version) { return; } if (msg.doc !== this.name) { return this.emit('error', "Expected docName '" + this.name + "' but got " + msg.doc); } if (msg.v !== this.version) { return this.emit('error', "Expected version " + this.version + " but got " + msg.v); } op = msg.op; this.serverOps[this.version] = op; docOp = op; if (this.inflightOp !== null) { _ref4 = this._xf(this.inflightOp, docOp), this.inflightOp = _ref4[0], docOp = _ref4[1]; } if (this.pendingOp !== null) { _ref5 = this._xf(this.pendingOp, docOp), this.pendingOp = _ref5[0], docOp = _ref5[1]; } this.version++; return this._otApply(docOp, true); } else if (msg.meta) { _ref6 = msg.meta, path = _ref6.path, value = _ref6.value; switch (path != null ? path[0] : void 0) { case 'shout': return this.emit('shout', value); default: return typeof console !== "undefined" && console !== null ? console.warn('Unhandled meta op:', msg) : void 0; } } else { return typeof console !== "undefined" && console !== null ? console.warn('Unhandled document message:', msg) : void 0; } }; Doc.prototype.flush = function() { if (!(this.connection.state === 'ok' && this.inflightOp === null && this.pendingOp !== null)) { return; } this.inflightOp = this.pendingOp; this.inflightCallbacks = this.pendingCallbacks; this.pendingOp = null; this.pendingCallbacks = []; return this.connection.send({ doc: this.name, op: this.inflightOp, v: this.version }); }; Doc.prototype.submitOp = function(op, callback) { if (this.type.normalize != null) { op = this.type.normalize(op); } this.snapshot = this.type.apply(this.snapshot, op); if (this.pendingOp !== null) { this.pendingOp = this.type.compose(this.pendingOp, op); } else { this.pendingOp = op; } if (callback) { this.pendingCallbacks.push(callback); } this.emit('change', op); return setTimeout(this.flush, 0); }; Doc.prototype.shout = function(msg) { return this.connection.send({ doc: this.name, meta: { path: ['shout'], value: msg } }); }; Doc.prototype.open = function(callback) { var message, _this = this; this.autoOpen = true; if (this.state !== 'closed') { return; } message = { doc: this.name, open: true }; if (this.snapshot === void 0) { message.snapshot = null; } if (this.type) { message.type = this.type.name; } if (this.version != null) { message.v = this.version; } if (this._create) { message.create = true; } this.connection.send(message); this.state = 'opening'; return this._openCallback = function(error) { _this._openCallback = null; return typeof callback === "function" ? callback(error) : void 0; }; }; Doc.prototype.close = function(callback) { this.autoOpen = false; if (this.state === 'closed') { return typeof callback === "function" ? callback() : void 0; } this.connection.send({ doc: this.name, open: false }); this.state = 'closed'; this.emit('closing'); return this._closeCallback = callback; }; return Doc; })(); if (typeof WEB === "undefined" || WEB === null) { MicroEvent = require('./microevent'); } MicroEvent.mixin(Doc); exports.Doc = Doc; }).call(this);