     @_callOnComplete value
 
   _maskedValue: (input) ->
+    for i in [0...@props.mask.length]
+      break if @_buffer[i] isnt input[i]
+
+    originalCursorPos = @_cursorPos = @_getSelection().begin
+    inputPos = i
+    for bufferPos in [i...@props.mask.length]
+      pattern = @_getPattern(bufferPos)
+      if pattern?
+        @_buffer[bufferPos] = @_getFormatChar(bufferPos)
+        while inputPos < input.length
+          c = input[inputPos++]
+          if pattern.test(c)
+            @_buffer[bufferPos] = c
+            break
+          else if @_cursorPos > bufferPos
+            @_cursorPos--
+            # @_cursorPos ?= i
+
+        if inputPos >= input.length
+          @_resetBuffer(bufferPos + 1, @props.mask.length)
+          break
+
+      else
+        @_cursorPos++ if inputPos <= originalCursorPos
+        if @_buffer[bufferPos] is input[inputPos]
+          inputPos++
+
+    @_buffer.join('')
+
+  _maskedValue2: (input) ->
+    @_cursorPos = @_getSelection().begin
+    start = 0
+    diffs = jsdiff.diffChars(@state.value, input)
+
+    for diff, i in diffs
+      break if diff.added || diff.removed
+      start += diff.value.length # count?
+
+    for i in [i...diffs.length]
+      diff = diffs[i]
+
+      continue if diff.removed
+      start = @_something(start, diff.value, diff.added)
+      # start += diff.value.length
+
+    @_buffer.join('')
+
+  _something: (start, input, added) ->
     pos = 0
-    for i in [0...@props.mask.length]
+    for i in [start...@props.mask.length]
       pattern = @_getPattern(i)
       if pattern?
         @_buffer[i] = @_getFormatChar(i)

    format: '_'

  getInitialState: ->
    return null unless @props.mask?

    @_buffer =

    <input {...@props} {...props} />

  _getSelection: ->
    return {begin: 0, end: 0} unless @isMounted()

    node = @getDOMNode()
    if node.setSelectionRange?
      begin = node.selectionStart
