     setValue: (newValue) ->
       @selectChoiceByValue newValue
       @getValue()
+
+    # destroy this instance of the plugin
+    destroy: ->
+      #remove event listeners
+      @element.off 'keyup change search', @doQuery
+      @element.off 'keydown', @doSelection
+      @element.off 'blur', @revert
+      $(window).off 'resize', @reposition
+
+      @queryResultArea.remove() # removes query result area and all related event listeners
+      $.removeData @element[0], "plugin_#{pluginName}" # remove reference to plugin instance
 
   $.fn[pluginName] = (options) ->
     args = Array.prototype.slice.call(arguments, 1)

        highlightedChoice.removeClass 'active'
        $(@).addClass 'active'

      @element.on 'keyup change search', =>
        query = @element.val()
        if @_val isnt query # user has changed input value, do a search and display the search results
          @_val = query
          if query is ''
            @hideResults()
          else
            filteredChoices = (@choices.filter @options.filterFn query)
            truncatedChoices = filteredChoices[0...@options.maxResults]
            difference = filteredChoices.length - truncatedChoices.length
            results = truncatedChoices.map (choice) -> "<li class='choice' data-value='#{esc choice.value}'>#{esc choice.text}</li>"
            info = if difference > 0
              "<p class='moreinfo'>showing #{addCommas truncatedChoices.length} of #{addCommas filteredChoices.length}</p>"
            else if results.length is 0
              "<p class='noresults'>no matches</p>"
            else
              ''
            @queryResultArea.html "<ul>#{results.join '\n'}</ul>#{info}"
            @queryResultArea.find('li.choice:first').addClass 'active'
            @showResults()

      @element.on 'keydown', (e) =>
        if @queryResultArea.is(':visible')
          switch e.which
            when 9 # tab
              @selectHighlightedChoice()
            when 13 # enter
              e.preventDefault() # prevent form from submitting (i think; test this!)
              @selectHighlightedChoice()
            when 38 # up
              e.preventDefault() # prevent cursor from moving
              @highlightPreviousChoice()
            when 40 # down
              e.preventDefault() # prevent cursor from moving
              @highlightNextChoice()

      @element.on 'blur', =>
        if @queryResultArea.is(':visible')
          @display()
          @hideResults()
        else if @element.val() is ''
          @selectChoiceByValue null

      $(window).on 'resize', =>
        if @queryResultArea.is(':visible')
          @positionResultsArea()

    positionResultsArea: ->


        @selectedChoice = null
      @display()

    ####################
    # "public" methods #
    ####################

    publicMethods: ['getChoices', 'setChoices', 'getValue', 'setValue', 'destroy']

    # return array of choices
    getChoices: ->
      @choices
