     arr.splice s, s - e, data
     # console.log 'inserted', narr
     @value = arr.join ''
+    @el.selectionStart = @el.selectionEnd = s + data.length
   ### public ###
   init: ->
     super()

  ### static ###
  @create: (cfg) -> super @, cfg
  ### private ###
  _onpaste: (e) -> # paste images
    items = [].slice.call e.clipboardData.items
    # console.log JSON.stringify items # will give you the mime types
    blob = null
    for item in items
      if item.kind is 'file' and /image\/(?:png|jpeg|qjpeg|gif|bmp)/.test item.type
        blob = item.getAsFile()
        @_insertImage blob if blob
        return
    return
  _insertImage: (blob) ->
    if blob.size > 512 * 1024 # 512 K
      @channel.system 'The image you pasted is too large.' 
      return
    reader = new FileReader
    reader.onload = (e) =>
      dataurl = e.target.result
      @_insertText "<img src=\"#{dataurl}\"/>" # todo: match mode
      return
    reader.readAsDataURL blob
    return false

    @on event: 'blur', handler: -> @placeholder = '_'
    # paste image
    @on event: 'paste', handler: (e) => @_onpaste e
    # drop image
    # @on event: 'dragenter', handler: (e) -> 
    # @on event: 'dragleave', handler: (e) -> 
    @on event: 'dragover', handler: (e) ->
      e.stopPropagation()
      e.preventDefault()
      console.log 'dragover', e
      e.dataTransfer.dropEffect = 'copy' # Explicitly show this is a copy.
      false
    @on event: 'drop', handler: (e) => @_ondrop e
    # auto save on exit
    @on el: window, event: 'unload', handler: =>
        sessionStorage.auto_save = @value or ''
