     console.assert(_.isEqual(composed, newDelta), oldDelta, delta, composed, newDelta)
 
   deleteAt: (index, length, emitEvent = true) ->
-    delta = this.trackDelta( =>
-      @selection.preserve( =>
-        this.keepNormalized( =>
-          @doc.deleteText(index, length)
-        )
-      )
-    , emitEvent)
+    this.doSilently( =>
+      delta = this.trackDelta( =>
+        @selection.preserve( =>
+          this.keepNormalized( =>
+            @doc.deleteText(index, length)
+          )
+        )
+      , emitEvent)
+    )
     this.emit(TandemEditor.events.TEXT_CHANGE, delta) if emitEvent
+
+  doSilently: (fn) ->
+    oldIgnoreDomChange = @ignoreDomChanges
+    @ignoreDomChanges = true
+    fn()
+    @ignoreDomChanges = oldIgnoreDomChange
 
   getAt: (index, length) ->
     # - Returns array of {text: "", attr: {}}

    TandemEditor.editors.push(this)

  disable: ->
    this.trackDelta( =>
      @doc.root.setAttribute('contenteditable', false)
    , false)

  enable: ->
    if !@doc.root.getAttribute('contenteditable')
      this.trackDelta( =>
        @doc.root.setAttribute('contenteditable', true)
      , false)
      #@doc.root.focus()
      #position = Tandem.Position.makePosition(this, @options.cursor)
      #start = new Tandem.Range(this, position, position)
      #this.setSelection(start)

  initListeners: ->
    modified = false

    return @selection.getRange()

  insertAt: (index, text, emitEvent = true) ->
    this.doSilently( =>
      delta = this.trackDelta( =>
        @selection.preserve( =>
          this.keepNormalized( =>
            @doc.insertText(index, text)
          )
        )
      , emitEvent)
    )
    this.emit(TandemEditor.events.TEXT_CHANGE, delta) if emitEvent

  setSelection: (range) ->
    @selection.setRange(range)

  trackDelta: (fn) ->
    oldDelta = @doc.toDelta()
    fn()
    newDelta = @doc.toDelta()
    decompose = JetSync.decompose(oldDelta, newDelta)
    compose = JetSync.compose(oldDelta, decompose)
    console.assert(_.isEqual(compose, newDelta), oldDelta, newDelta, decompose, compose)
    return delta

  update: ->
    this.doSilently( =>
      delta = this.trackDelta( =>
        @selection.preserve( =>
          Tandem.Document.normalizeHtml(@doc.root)
          lines = @doc.lines.toArray()
          lineNode = @doc.root.firstChild
          _.each(lines, (line, index) =>
            while line.node != lineNode
              if line.node.parentNode == @doc.root
                newLine = @doc.insertLineBefore(lineNode, line)
                lineNode = lineNode.nextSibling
              else
                @doc.removeLine(line)
                return
            @doc.updateLine(line)
            lineNode = lineNode.nextSibling
          )
          while lineNode != null
            newLine = @doc.appendLine(lineNode)
            lineNode = lineNode.nextSibling
        )
        @selection.update(true)
      , true)
    )
    return delta


