(function($) {
  /**
   * Highlight a DOM element with a list of keywords.
   */
  $.fn.hilite = function(to_watch) { 
    var drugs        = this,
        search_event = $.browser.safari ? 'search' : 'keyup';
  
    // Setup index
    var index = drugs.map(function() {
      var elem = $(this);
      return { elem: elem, content: elem.html(), text: $.trim(elem.text()).toLowerCase() };
    });
  
    // Don't let this field submit the form
    $(to_watch).keypress(function(event) {
      return (event.which != 13);
    });

    $(to_watch).bind(search_event, function() {
      var search = $.trim($(this).val()),
          regex  = new RegExp('(' + search.replace(' ', '|') + ')', 'gi');
      
      $.each(index, function() {
        if (search.length <= 2)
          this.elem.html(this.content).show();
        else if (this.text.match(regex))
          this.elem.html(hiliteHTML(this.content, regex)).show();
        else
          this.elem.hide();
      });

      var results = drugs.is(':visible') ? 'hide' : 'show';
      $('#nothing')[results]();
    });
    
    return this;
  
    /**
     * Highlight a HTML string with a list of keywords.
     */
    function hiliteHTML(html, query) {
      var re = query;
      var subs = '<span class="highlight">$1</span>';

      var last = 0;
      var tag = '<';
      var skip = false;
      var skipre = new RegExp('^(script|style|textarea)', 'gi');
      var part = null;
      var result = '';

      while (last >= 0) {
        var pos = html.indexOf(tag, last);
        if (pos < 0) {
          part = html.substring(last);
          last = -1;
        } else {
          part = html.substring(last, pos);
          last = pos+1;
        }

        if (tag == '<') {
          if (!skip)
            part = part.replace(re, subs);
          else
            skip = false;
        } else if (part.match(skipre))
          skip = true;

        result += part + (pos < 0 ? '' : tag);
        tag = tag == '<' ? '>' : '<';
      }

      return result;
    }
  }
})(jQuery);