/* $Date: Sun Mar  8 02:06:36 2009 by mgb$ 
 *
 */

;(function($) {
  $.fn.suggest = function(options) {
    var $this = $(this);
    var options = $.extend({},$.fn.suggest.defaults,options);

    return $.each($this,function() {
      var self = $(this);
      var o = $.extend({},options,{self:self});
      $(this).suggest.init(o);
    });
  };
  $.fn.suggest.init = function(o) {
    if(typeof(o.input) == 'string') {
      o.input = $(o.input,o.self);
    }
    if(!o.input || !$(o.input).is(":text")) {
      o.input = $('<input type="text" class="searchbox" />').
      appendTo(o.self);
    }
    if(o.itext) { o.input.val(o.itext); }
    else {o.itext = o.input.val();}

    o.input.
      bind("focus",function() { if(o.itext && o.itext == $(this).val()) {$(this).val('');} o.input.addClass("active"); }).
      bind("blur",function() { if(o.itext && $(this).val() == '') {$(this).val(o.itext);} o.input.removeClass("active"); });


    o.self.bind("mouseleave",function() {
      o.hide(o); if(o.input.hasClass("active")) { o.input.trigger("blur"); }
    });

    if(!o.hits || !$(o.hits).is("div."+o.rclass)) {
      o.hits = $("<div />").hide().addClass(o.rclass).css({zIndex:o.zindex}).appendTo(o.self);
    }


    var value = o.input.val();;
    o.input.bind("keyup click", function(e) {
        o.value = o.input.val();
        if(o.value.length >= o.minchar) {
          if (e.keyCode == 27 ) { // if escape key
            o.hide(o);
          }
          else if(e.keyCode == 13 ) { // if enter key
            return o.select(o);
          }
          else if (e.keyCode == 40) { // if down arrow
            var $hit = $("."+o.hclass,o.hits);
            if($hit) {
              var $next = $hit.removeClass(o.hclass).next();
              if($next.hasClass(o.sclass)) { $next.addClass(o.hclass); }
              else { $("."+o.sclass+":first",o.hits).addClass(o.hclass); }
            }
          }
          else if (e.keyCode == 38) { // if up arrow
            var $hit = $("."+o.hclass,o.hits);
            if($hit) {
              var $prev = $hit.removeClass(o.hclass).prev();
              if($prev.hasClass(o.sclass)) { $prev.addClass(o.hclass); }
              else { $("."+o.sclass+":last",o.hits).addClass(o.hclass); }
            }
          }
          else if(o.value == value) {
            o.show(o);
          }
          else if(o.value != value) {
            value = o.value;
            o.hide(o);
            o.ltoggle(o);
            setTimeout(function () {
              o.filter(o);
              o.ltoggle(o);
              o.show(o);
            },o.delay);
          }
        } else if (e.keyCode == 13 ) { // if enter key to start search manually
            value = o.value;
            o.hide(o);
            o.ltoggle(o);
            setTimeout(function () {
              o.filter(o);
              o.ltoggle(o);
              o.show(o);
            },o.delay);
        }
        else {
          o.hide(o);
        }
        value = o.value;
    });
  };
  $.fn.suggest.defaults = {
    minchar: 4,
    opacity: 1.0,
    zindex: 20000,
    delay: 250,
    input: false,
    hits: false,
    rclass: "hits",
    sclass: "hit",
    hclass: "hhit",
    itext: false,
    select: function(o) { return $("."+o.hclass,o.hits); },
    filter: function(o) { o.hits.html("filter function is not defined"); },
    ltoggle: function(o) { o.input.toggleClass("loading"); },
    show: function(o) { o.hits.show(); },
    hide: function(o) { o.hits.hide(); }
  };
})(jQuery);

