text: !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.OperationalTransform=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
  module.exports = _dereq_('./src');
  
  
  
  },{"./src":5}],2:[function(_dereq_,module,exports){
  var Document, OT;
  
  OT = _dereq_('./');
  
  module.exports = Document = (function() {
    function Document() {
      this.text = "";
      this.operations = [];
    }
  
    Document.prototype.apply = function(newOperation, revision) {
      var i, index, missedOperations, missedOperationsPrime, ref, ref1, ref2;
      if (revision > this.operations.length) {
        throw new Error("The operation base revision is greater than the document revision");
      }
      if (revision < this.operations.length) {
        missedOperations = new OT.TextOperation(this.operations[revision].userId);
        missedOperations.targetLength = this.operations[revision].baseLength;
        for (index = i = ref = revision, ref1 = this.operations.length; ref <= ref1 ? i < ref1 : i > ref1; index = ref <= ref1 ? ++i : --i) {
          missedOperations = missedOperations.compose(this.operations[index]);
        }
        ref2 = missedOperations.transform(newOperation), missedOperationsPrime = ref2[0], newOperation = ref2[1];
      }
      this.text = newOperation.apply(this.text);
      this.operations.push(newOperation.clone());
      return newOperation;
    };
  
    return Document;
  
  })();
  
  
  
  },{"./":5}],3:[function(_dereq_,module,exports){
  var TextOp;
  
  module.exports = TextOp = (function() {
    function TextOp(type, attributes) {
      this.type = type;
      this.attributes = attributes;
    }
  
    return TextOp;
  
  })();
  
  
  
  },{}],4:[function(_dereq_,module,exports){
  var OT, TextOperation;
  
  OT = _dereq_('./');
  
  module.exports = TextOperation = (function() {
    function TextOperation(userId) {
      this.userId = userId;
      this.ops = [];
      this.baseLength = 0;
      this.targetLength = 0;
    }
  
    TextOperation.prototype.serialize = function() {
      var i, len, op, ops, ref;
      ops = [];
      ref = this.ops;
      for (i = 0, len = ref.length; i < len; i++) {
        op = ref[i];
        ops.push({
          type: op.type,
          attributes: op.attributes
        });
      }
      return {
        ops: ops,
        userId: this.userId
      };
    };
  
    TextOperation.prototype.deserialize = function(data) {
      var i, len, op, ref;
      if (data == null) {
        return false;
      }
      this.userId = data.userId;
      ref = data.ops;
      for (i = 0, len = ref.length; i < len; i++) {
        op = ref[i];
        switch (op.type) {
          case 'retain':
            this.retain(op.attributes.amount);
            break;
          case 'insert':
            this.insert(op.attributes.text);
            break;
          case 'delete':
            this["delete"](op.attributes.text);
            break;
          default:
            return false;
        }
      }
      return true;
    };
  
    TextOperation.prototype.retain = function(amount) {
      var prevOp;
      if (typeof amount !== 'number' || amount <= 0) {
        return;
      }
      this.baseLength += amount;
      this.targetLength += amount;
      prevOp = this.ops[this.ops.length - 1];
      if ((prevOp != null ? prevOp.type : void 0) === 'retain') {
        prevOp.attributes.amount += amount;
      } else {
        this.ops.push(new OT.TextOp('retain', {
          amount: amount
        }));
      }
    };
  
    TextOperation.prototype.insert = function(text) {
      var prevOp;
      if (typeof text !== 'string' || text === '') {
        return;
      }
      this.targetLength += text.length;
      prevOp = this.ops[this.ops.length - 1];
      if ((prevOp != null ? prevOp.type : void 0) === 'insert') {
        prevOp.attributes.text += text;
      } else {
        this.ops.push(new OT.TextOp('insert', {
          text: text
        }));
      }
    };
  
    TextOperation.prototype["delete"] = function(text) {
      var prevOp;
      if (typeof text !== 'string' || text === '') {
        return;
      }
      this.baseLength += text.length;
      prevOp = this.ops[this.ops.length - 1];
      if ((prevOp != null ? prevOp.type : void 0) === 'delete') {
        prevOp.attributes.text += text;
      } else {
        this.ops.push(new OT.TextOp('delete', {
          text: text
        }));
      }
    };
  
    TextOperation.prototype.apply = function(text) {
      var i, index, len, op, ref;
      if (text.length !== this.baseLength) {
        throw new Error("The operation's base length must be equal to the string's length.");
      }
      index = 0;
      ref = this.ops;
      for (i = 0, len = ref.length; i < len; i++) {
        op = ref[i];
        switch (op.type) {
          case 'retain':
            index += op.attributes.amount;
            break;
          case 'insert':
            text = text.substring(0, index) + op.attributes.text + text.substring(index, text.length);
            index += op.attributes.text.length;
            break;
          case 'delete':
            text = text.substring(0, index) + text.substring(index + op.attributes.text.length, text.length);
        }
      }
      return text;
    };
  
    TextOperation.prototype.invert = function() {
      var i, invertedOperation, len, op, ref;
      invertedOperation = new TextOperation(this.userId);
      ref = this.ops;
      for (i = 0, len = ref.length; i < len; i++) {
        op = ref[i];
        switch (op.type) {
          case 'retain':
            invertedOperation.retain(op.attributes.amount);
            break;
          case 'insert':
            invertedOperation["delete"](op.attributes.text);
            break;
          case 'delete':
            invertedOperation.insert(op.attributes.text);
        }
      }
      return invertedOperation;
    };
  
    TextOperation.prototype.clone = function() {
      var i, len, op, operation, ref;
      operation = new TextOperation(this.userId);
      ref = this.ops;
      for (i = 0, len = ref.length; i < len; i++) {
        op = ref[i];
        switch (op.type) {
          case 'retain':
            operation.retain(op.attributes.amount);
            break;
          case 'insert':
            operation.insert(op.attributes.text);
            break;
          case 'delete':
            operation["delete"](op.attributes.text);
        }
      }
      return operation;
    };
  
    TextOperation.prototype.equal = function(otherOperation) {
      var attribute, i, key, len, op, opIndex, otherOp, ref, ref1;
      if (otherOperation.ops.length !== this.ops.length) {
        return false;
      }
      ref = this.ops;
      for (opIndex = i = 0, len = ref.length; i < len; opIndex = ++i) {
        op = ref[opIndex];
        otherOp = otherOperation.ops[opIndex];
        if (otherOp.type !== op.type) {
          return false;
        }
        ref1 = op.attributes;
        for (key in ref1) {
          attribute = ref1[key];
          if (attribute !== otherOp.attributes[key]) {
            return false;
          }
        }
      }
      return true;
    };
  
  
    /*
    Largely inspired from Firepad
    Compose merges two consecutive operations into one operation, that
    preserves the changes of both. Or, in other words, for each input string S
    and a pair of consecutive operations A and B,
    apply(apply(S, A), B) = apply(S, compose(A, B)) must hold.
     */
  
    TextOperation.prototype.compose = function(operation2) {
      var composedOperation, i1, i2, op1, op2, ops1, ops2;
      if (this.targetLength !== operation2.baseLength) {
        throw new Error('The base length of the second operation has to be the target length of the first operation');
      }
      composedOperation = new TextOperation(this.userId);
      ops1 = this.clone().ops;
      ops2 = operation2.clone().ops;
      i1 = 0;
      i2 = 0;
      op1 = ops1[i1++];
      op2 = ops2[i2++];
      while (true) {
        if ((op1 == null) && (op2 == null)) {
          break;
        }
        if (op2 == null) {
          switch (op1.type) {
            case 'retain':
              composedOperation.retain(op1.attributes.amount);
              break;
            case 'insert':
              composedOperation.insert(op1.attributes.text);
              break;
            case 'delete':
              composedOperation["delete"](op1.attributes.text);
          }
          op1 = ops1[i1++];
          continue;
        }
        if (op1 == null) {
          switch (op2.type) {
            case 'retain':
              composedOperation.retain(op2.attributes.amount);
              break;
            case 'insert':
              composedOperation.insert(op2.attributes.text);
              break;
            case 'delete':
              composedOperation["delete"](op2.attributes.text);
          }
          op2 = ops2[i2++];
          continue;
        }
        if ((op1 != null ? op1.type : void 0) === 'delete') {
          composedOperation["delete"](op1.attributes.text);
          op1 = ops1[i1++];
          continue;
        }
        if ((op2 != null ? op2.type : void 0) === 'insert') {
          composedOperation.insert(op2.attributes.text);
          op2 = ops2[i2++];
          continue;
        }
        if (op1 == null) {
          throw new Error('Cannot transform operations: first operation is too short.');
        }
        if (op2 == null) {
          throw new Error('Cannot transform operations: first operation is too long.');
        }
        if (op1.type === 'retain' && op2.type === 'retain') {
          if (op1.attributes.amount === op2.attributes.amount) {
            composedOperation.retain(op1.attributes.amount);
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else if (op1.attributes.amount > op2.attributes.amount) {
            composedOperation.retain(op2.attributes.amount);
            op1.attributes.amount -= op2.attributes.amount;
            op2 = ops2[i2++];
          } else {
            composedOperation.retain(op1.attributes.amount);
            op2.attributes.amount -= op1.attributes.amount;
            op1 = ops1[i1++];
          }
        } else if (op1.type === 'insert' && op2.type === 'delete') {
          if (op1.attributes.text.length === op2.attributes.text) {
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else if (op1.attributes.text.length > op2.attributes.text.length) {
            op1.attributes.text = op1.attributes.text.slice(op2.attributes.text.length);
            op2 = ops2[i2++];
          } else {
            op2.attributes.text = op2.attributes.text.slice(op1.attributes.text.length);
            op1 = ops1[i1++];
          }
        } else if (op1.type === 'insert' && op2.type === 'retain') {
          if (op1.attributes.text.length > op2.attributes.amount) {
            composedOperation.insert(op1.attributes.text.slice(0, op2.attributes.amount));
            op1.attributes.text = op1.attributes.text.slice(op2.attributes.amount);
            op2 = ops2[i2++];
          } else if (op1.attributes.text.length === op2.attributes.amount) {
            composedOperation.insert(op1.attributes.text);
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else {
            composedOperation.insert(op1.attributes.text);
            op2.attributes.amount -= op1.attributes.text.length;
            op1 = ops1[i1++];
          }
        } else if (op1.type === 'retain' && op2.type === 'delete') {
          if (op1.attributes.amount === op2.attributes.text.length) {
            composedOperation["delete"](op2.attributes.text);
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else if (op1.attributes.amount > op2.attributes.text.length) {
            composedOperation["delete"](op2.attributes.text);
            op1.attributes.amount -= op2.attributes.text.length;
            op2 = ops2[i2++];
          } else {
            composedOperation["delete"](op2.attributes.text.slice(0, op1.attributes.amount));
            op2.attributes.text = op2.attributes.text.slice(op1.attributes.amount);
            op1 = ops1[i1++];
          }
        } else {
          throw new Error("This shouldn't happen: op1: " + JSON.stringify(op1) + ", op2: " + JSON.stringify(op2));
        }
      }
      return composedOperation;
    };
  
  
    /*
    Largely inspired from Firepad
    Transform takes two operations A (this) and B (other) that happened concurrently and
    produces two operations A' and B' (in an array) such that
    `apply(apply(S, A), B') = apply(apply(S, B), A')`.
    This function is the heart of OT.
     */
  
    TextOperation.prototype.transform = function(operation2) {
      var i1, i2, minl, op1, op2, operation1prime, operation2prime, ops1, ops2, text;
      if (this.gotPriority(operation2.userId)) {
        operation1prime = new TextOperation(this.userId);
        operation2prime = new TextOperation(operation2.userId);
        ops1 = this.clone().ops;
        ops2 = operation2.clone().ops;
      } else {
        operation1prime = new TextOperation(operation2.userId);
        operation2prime = new TextOperation(this.userId);
        ops1 = operation2.clone().ops;
        ops2 = this.clone().ops;
      }
      i1 = 0;
      i2 = 0;
      op1 = ops1[i1++];
      op2 = ops2[i2++];
      while (true) {
        if ((op1 == null) && (op2 == null)) {
          break;
        }
        if ((op1 != null ? op1.type : void 0) === 'insert') {
          operation1prime.insert(op1.attributes.text);
          operation2prime.retain(op1.attributes.text.length);
          op1 = ops1[i1++];
          continue;
        }
        if ((op2 != null ? op2.type : void 0) === 'insert') {
          operation1prime.retain(op2.attributes.text.length);
          operation2prime.insert(op2.attributes.text);
          op2 = ops2[i2++];
          continue;
        }
        if (typeof op1 === "undefined") {
          throw new Error("Cannot transform operations: first operation is too short.");
        }
        if (typeof op2 === "undefined") {
          throw new Error("Cannot transform operations: first operation is too long.");
        }
        if (op1.type === 'retain' && op2.type === 'retain') {
          if (op1.attributes.amount === op2.attributes.amount) {
            minl = op2.attributes.amount;
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else if (op1.attributes.amount > op2.attributes.amount) {
            minl = op2.attributes.amount;
            op1.attributes.amount -= op2.attributes.amount;
            op2 = ops2[i2++];
          } else {
            minl = op1.attributes.amount;
            op2.attributes.amount -= op1.attributes.amount;
            op1 = ops1[i1++];
          }
          operation1prime.retain(minl);
          operation2prime.retain(minl);
        } else if (op1.type === 'delete' && op2.type === 'delete') {
          if (op1.attributes.text.length === op2.attributes.text.length) {
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else if (op1.attributes.text.length > op2.attributes.text.length) {
            op1.attributes.text = op1.attributes.text.slice(op2.attributes.text.length);
            op2 = ops2[i2++];
          } else {
            op2.attributes.text = op1.attributes.text.slice(op1.attributes.text.length);
            op1 = ops1[i1++];
          }
        } else if (op1.type === 'delete' && op2.type === 'retain') {
          if (op1.attributes.text.length === op2.attributes.amount) {
            text = op1.attributes.text;
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else if (op1.attributes.text.length > op2.attributes.amount) {
            text = op1.attributes.text.slice(0, op2.attributes.amount);
            op1.attributes.text = op1.attributes.text.slice(op2.attributes.amount);
            op2 = ops2[i2++];
          } else {
            text = op1.attributes.text;
            op2.attributes.amount -= op1.attributes.text.length;
            op1 = ops1[i1++];
          }
          operation1prime["delete"](text);
        } else if (op1.type === 'retain' && op2.type === 'delete') {
          if (op1.attributes.amount === op2.attributes.text.length) {
            text = op2.attributes.text;
            op1 = ops1[i1++];
            op2 = ops2[i2++];
          } else if (op1.attributes.amount > op2.attributes.text.length) {
            text = op2.attributes.text;
            op1.attributes.amount -= op2.attributes.text.length;
            op2 = ops2[i2++];
          } else {
            text = op2.attributes.text.slice(0, op1.attributes.amount);
            op2.attributes.text = op2.attributes.text.slice(op1.attributes.amount);
            op1 = ops1[i1++];
          }
          operation2prime["delete"](text);
        } else {
          throw new Error("The two operations aren't compatible");
        }
      }
      if (this.gotPriority(operation2.userId)) {
        return [operation1prime, operation2prime];
      } else {
        return [operation2prime, operation1prime];
      }
    };
  
    TextOperation.prototype.gotPriority = function(id2) {
      if (this.userId <= id2) {
        return true;
      } else {
        return false;
      }
    };
  
    return TextOperation;
  
  })();
  
  
  
  },{"./":5}],5:[function(_dereq_,module,exports){
  exports.Document = _dereq_('./Document');
  
  exports.TextOperation = _dereq_('./TextOperation');
  
  exports.TextOp = _dereq_('./TextOp');
  
  
  
  },{"./Document":2,"./TextOp":3,"./TextOperation":4}]},{},[1])(1)
  });