         event.stopPropagation()
       val
 
+  keydown: (event) ->
+    if event.keyCode == @KEY_ENTER
+      @parent.activateResult()
+      false
+    else if event.keyCode == @KEY_UP
+      @parent.moveSelection(-1)
+      false
+    else if event.keyCode == @KEY_DOWN
+      @parent.moveSelection(+1)
+      false
+
+  keyup: (event) ->
+    query = event.target.value
+    if query != @old_query
+      if query == ""
+        @parent.setDefaultResults()
+      else if query.length >= @parent.DICTIONARY_KEY_LENGTH
+        @parent.setOrRequestResults(query)
+    @old_query = query
+
+
+
+class OUT.QuickJump.Base
+  DELAY_BEFORE_SERVER_CALL: 300
+  FETCHING_RESULTS: "fetching"
+  DICTIONARY_KEY_LENGTH: 1
+  MAX_RESULTS: 10
+
+  constructor: (@result_callback, @data_url = "/quick_jump_targets.json", selector = "#quick-jump-template") ->
+    @dictionary = new OUT.QuickJump.Dictionary(@DICTIONARY_KEY_LENGTH)
+    @selector = this.cloneModal(selector)
+    @controls = new OUT.QuickJump.Controls(this, @selector, @result_callback)
+    this.setDefaultResults()
+
+    self = this
+    $(@selector).bind "hidden", ->
+      $(self.selector).remove()
+
+    $(@selector).bind "shown", ->
+      $(self.selector+" input").select()
+
+    $(@selector).modal().modal("show")
+
   activateResult: (anchor) ->
     anchor or= this.getActiveResult()
     if anchor?

      expr = '.*' + query.toLowerCase().replace(/\s/g, '.+') + '.*'
      name.match(new RegExp(expr))

  markActiveResult: ->
    if @active_result?
      $(@selector+" .result").removeClass "active"
      this.getActiveResult().addClass "active"
  
  getActiveResult: ->
    if @active_result?
      all = $(@selector+" .result")
      anchor = $(all[@active_result])

OUT.lazyTimerIds = {}
OUT.setLazyTimer = (name, delay, func) ->

    $("body").append(new_modal)
    "##{new_modal_id}"

  getActiveResult: ->
    if @active_result?
      all = $(@selector+" .result")
      anchor = $(all[@active_result])

  hide: ->
    $(@selector).modal("hide")

  highlight: (str, phrases) ->
    str.toString().replace(new RegExp('('+phrases.join('|')+')', 'gi'), '<strong>$1</strong>')

  markActiveResult: ->
    if @active_result?
      $(@selector+" .result").removeClass "active"
      this.getActiveResult().addClass "active"

  moveSelection: (modifier) ->
    max_result = Math.min(@results.length, @MAX_RESULTS)
    @active_result += modifier
