.jqac-menu{
	font-size: 14px;
	color: black;
	background-color: white;
	border: 1px solid #aaa;
}
.jqac-p{
	
}
.jqac-menu div{
	border-bottom: 1px solid #aaa;
}
.jqac-menu ul{
	list-style: none;
	margin: 1px;
	padding: 1px;
	overflow: hidden;
}

.jqac-menu .jqac-link-1, .jqac-menu .jqac-link-0 {
  cursor: hand; 
  cursor: pointer;
  display: block;
  border: 1px solid #AAA; 
  margin: 5px;
}
.jqac-menu .jqac-link-1 {
  border: 1px solid #AAA; 
}
.jqac-menu .jqac-highlight {
  background-color: #ddf;
}
.jqac-menu .jqac-warning {
  text-align: center;
  font-style: italic;
}
.jqac-menu .jqac-loading {
  text-align: right;
  font-style: italic;
  text-decoration: blink;
}
.jqac-menu em {
    font-style: normal;
    text-decoration: none;
    color: #888;
}
.jqac-menu .jqac-info {
    text-align: right;
    font-style: italic;
    font-size: .75em;
    color: #666;
	padding: 0px 5px 0px 0px;
}
oint("EndToStart",M);
    end=Lp.text.length;
    if(end>obj.value.length)
      end = -1;
  }
  return {'start':start,'end':end};
}
// set caret to
function setCaret(obj,l){
  obj.focus();
  if (obj.setSelectionRange){
    obj.setSelectionRange(l,l);
  }
  else if(obj.createTextRange){
    m = obj.createTextRange();      
    m.moveStart('character',l);
    m.collapse();
    m.select();
  }
}
// prepare array with velued objects
// required properties are id and value
// rest of properties remaines
function prepareArray(jsondata){
  var new_arr = [];
  for(var i=0;i<jsondata.length;i++){
    if(jsondata[i].id != undefined && jsondata[i].value != undefined){
      jsondata[i].id = jsondata[i].id+"";
      jsondata[i].value = jsondata[i].value+"";
      if(jsondata[i].info != undefined)
        jsondata[i].info = jsondata[i].info+"";
      new_arr.push(jsondata[i]);
    }
  }
  return new_arr;
}
// php analogs
function escapearg(s){
  if(s == undefined || !s) return '';
  return s.replace('\\','\\\\').
           replace('*','\\*').
           replace('.','\\.').
           replace('/','\\/');
}
function htmlspecialchars(s){
  if(s == undefined || !s) return '';
  return s.replace('&','&amp;').
           replace('<','&lt;').
           replace('>','&gt;');
}
function ltrim(s){
  if(s == undefined || !s) return '';
  return s.replace(/^\s+/g,'');
}

// extending jQuery
$.fn.autocomplete = function(options){ return this.each(function(){
  // take me
  var me = $(this);
  var me_this = $(this).get(0);

  // test for supported text elements
  if(!me.is('input:text,input:password,textarea'))
  return;

  // get or ajax_get required!
  if(!options && (!$.isFunction(options.get) || !options.ajax_get)){
  return;
  }  
  // check plugin enabled
  if(me.attr('jqac') == 'on') return;

  // plugin on!
  me.attr('jqac','on');

  // no browser's autocomplete!
  me.attr('autocomplete','off');

  // default options
  options = $.extend({ 
                      delay     : 100 ,
                      timeout   : 5000 ,
                      minchars  : 1 ,
                      multi     : false ,
                      cache     : true , 
                      height    : 250 ,
                      autowidth : true ,
                      noresults : 'Sem resultado.'
                      },
                      options);

  // bind key events
  // handle special keys here
  me.keydown(function(ev){
    switch(ev.which){
      // return choose highlighted item or default propogate
	  case ARRDOWN:
		if(!suggestions_menu) callAjaxVal('');
		return false;
      case RETURN:
        if(!suggestions_menu) getSuggestions(getUserInput());
        else setHighlightedValue();
        return false;
      case ARRLEFT:
        if(suggestions_menu && options.page != null){
			goPage(options.page.prior);
			return false;
		}
      case ARRRIGHT:
        if(suggestions_menu && options.page != null){
			goPage(options.page.next);
			return false;
		}
      case ESC:
        clearSuggestions();
        return false;
    }
    return true;
  });
  me.keypress(function(ev){
    // ev.which doesn't work here - it always returns 0
    switch(ev.keyCode){
      case RETURN: case ESC:
        return false;
      // up changes highlight	  
     }
     return true;
  });
  // handle normal characters here
  me.keyup(function(ev) {
    switch(ev.which) {        
		case RETURN: case ESC: case ARRLEFT: case ARRRIGHT:
          return false;
		case ARRUP:
			if(suggestions_menu) changeHighlight(ev.keyCode);
			return false;
			// down changes highlight or open new menu
		case ARRDOWN:
			if(suggestions_menu) changeHighlight(ev.keyCode);
			return false;
		default:
			if (suggestions_menu) getSuggestions(getUserInput());
    }
    return true;
  });
  me.blur(function(ev) {
		canShow = false;
	  if (suggestions_menu) setTimeout(clearSuggestions, 100);
      return true;
  });
  me.focus(function(ev) {
	canShow = true;
     return true;
  });
  me.parent().mousemove(function(ev){
	var p = $(this).offset().left;
	var w = $(this).width();
	var px = ev.pageX;
	if (px > (p + w))
		$(this).css({cursor:'pointer'});
	else
		$(this).css({cursor:'text'});
  });
  me.parent().mousedown(function(ev){
	me.focus();
	var p = $(this).offset().left;
	var w = $(this).width();
	var px = ev.pageX;
	if (px > (p + w)){
		callAjaxVal('');
	}
	//ev.stopPropagation();
	ev.preventDefault();
  });
  // init variables
  var user_input = "";
  var input_chars_size  = 0;
  var suggestions = [];
  var current_highlight = 0;
  
  var canShow = true;
  
  var suggestions_menu = false;
  var suggestions_list = false;
  var loading_indicator = false;
  var clearSuggestionsTimer = false;
  var getSuggestionsTimer = false;
  var showLoadingTimer = false;
  var zIndex = me.css('z-index');

  // get user input
  function getUserInput(){
    var val = me.val();
    if(options.multi){
      var pos = getCaretPosition(me_this);
      var start = pos.start;
      for(;start>0 && val.charAt(start-1) != ',';start--){}
      var end = pos.start;
      for(;end<val.length && val.charAt(end) != ',';end++){}
      var val = val.substr(start,end-start);
    }
    return ltrim(val);
  }
  // set suggestion
  function setSuggestion(val){
    user_input = val;
    if(options.multi){
      var orig = me.val();
      var pos = getCaretPosition(me_this);
      var start = pos.start;
      for(;start>0 && orig.charAt(start-1) != ',';start--){}
      var end = pos.start;
      for(;end<orig.length && orig.charAt(end) != ',';end++){}
      var new_val = orig.substr(0,start) + (start>0?' ':'') + val + orig.substr(end);
      me.val(new_val);
      setCaret(me_this,start + val.length + (start>0?1:0));
    }
    else{
      me_this.focus();
      me.val(val);
    }
  }
  // get suggestions
  function getSuggestions(val){
    // input length is less than the min required to trigger a request
    // reset input string
    // do nothing
    if (val.length < options.minchars){
      clearSuggestions();
      return false;
    }
    // if caching enabled, and user is typing (ie. length of input is increasing)
    // filter results out of suggestions from last request
	if (
		options.cache 
		&& val.length > input_chars_size 
		&& suggestions.length 
		&& val.indexOf(user_input) == 0 
		&& options.page == null
	){
      var arr = [];
      for (var i=0;i<suggestions.length;i++){
        var re = new RegExp("("+escapearg(val)+")",'ig');
        if(re.exec(suggestions[i].value))
          arr.push( suggestions[i] );
      }
      user_input = val;
      input_chars_size = val.length;
      suggestions = arr;
      createList(suggestions);
	  checkOne(suggestions);	  
      return false;
    }
    else{// do new request
      clearTimeout(getSuggestionsTimer);
      user_input = val;
      input_chars_size = val.length;
      getSuggestionsTimer = setTimeout( 
        function(){ 
          suggestions = [];
          // call pre callback, if exists
          if($.isFunction(options.pre_callback))
            options.pre_callback();
          // call get
          if($.isFunction(options.get)){
            suggestions = prepareArray(options.get(val));
            createList(suggestions);
          }
          // call AJAX get
          else if($.isFunction(options.ajax_get)){
				clearTimeout(getSuggestionsTimer);
				getSuggestionsTimer = setTimeout(callAjax,300);
          }
        },
        options.delay );
    }
    return false;
  };
  
  function callAjax(val, page){
		callAjaxVal(getUserInput(), page);
  }
  function callAjaxVal(val, page){
        options.page = null;
		showLoadingTimer = setTimeout(show_loading,options.delay);
		options.ajax_get(val,ajax_continuation, page);
		options.last_val = val;
  }
  
  // AJAX continuation
  function ajax_continuation(jsondata, page){
	hide_loading();
    if (canShow){
		suggestions = prepareArray(jsondata);
		createList(suggestions, page);
		options.page = page;
		checkOne(suggestions, page);
	}
	//alert(current_highlight);
  }
  
	function checkOne(suggestions, page){
	  	if (
			(page == null && suggestions.length == 1)
			|| (page != null && page.size*1 == 1)){
			setHighlight(1);
			setHighlightedValue(2000);
		}
	}
	
  // shows loading indicator
  function show_loading(){
    if(!loading_indicator){
      loading_indicator = $('<div class="jqac-menu"><div class="jqac-loading">Carregando...</div></div>').get(0);
      $(loading_indicator).css('position','absolute');
      var pos = me.offset();
      $(loading_indicator).css('left', pos.left + "px");
      $(loading_indicator).css('top', ( pos.top + me.height() + 2 ) + "px");
	  $(loading_indicator).css('z-index',zIndex + 10);
      if(!options.autowidth)
        $(loading_indicator).width(me.width());
      $('body').append(loading_indicator);
    }
    $(loading_indicator).show();
    setTimeout(hide_loading,10000);
  }
  // hides loading indicator 
  function hide_loading(){
    if(loading_indicator)
      $(loading_indicator).hide();
    clearTimeout(showLoadingTimer);
  }
  // create suggestions list
  function createList(arr, page){
    if(suggestions_menu)
      $(suggestions_menu).remove();
    hide_loading();
    killTimeout();

    // create holding div
    suggestions_menu = $('<div class="jqac-menu"></div>').get(0);
	
    // ovveride some necessary CSS properties 
    $(suggestions_menu).css({'position':'absolute', 'z-index':zIndex});

	if (page != null){
		$(suggestions_menu).append(createLink(page.prior==null?null:page.first, "f"));
		$(suggestions_menu).append(createLink(page.prior, 'p'));
		$(suggestions_menu).append(createLink(page.next, 'n'));
		$(suggestions_menu).append(createLink(page.next==null?null:page.last, 'L'));
		$(suggestions_menu).append('<span class="infp">' + page.begin + ' - ' + page.end + '/' + page.size + '</span>');
		//pg = {'next':next, 'prior':prior, 'last': last, 'first': first, 'begin':obj.ini, 'end':obj.fim, 'size':obj.total};
	}
    // create and populate ul
	var div = $('<div></div>').get(0);
    $(div).css({'max-height':options.height+'px',
                             'overflow-y':'auto'});
							 
    $(suggestions_menu).append(div);
	
    suggestions_list = $('<ul></ul>').get(0);
    // set some CSS's
    $(suggestions_list).
      css('list-style','none').
      css('margin','0px').
      css('padding','2px').
      css('overflow','hidden');
    // regexp for replace 
    var re = new RegExp("("+escapearg(htmlspecialchars(user_input))+")",'ig');
    // loop throught arr of suggestions creating an LI element for each suggestion
    for (var i=0;i<arr.length;i++){
      var val = new String(arr[i].value);
      // using RE
      var output = htmlspecialchars(val).replace(re,'<em>$1</em>');
	 
      var span = $('<span class="jqac-link-' + i%2 + '">'+output+'</span>').get(0);
      if (arr[i].info != undefined && arr[i].info != ""){
        $(span).append($('<div class="jqac-info">'+arr[i].info+'</div>'));
      }

      $(span).attr('name',i+1);
      $(span).click(function () { setHighlightedValue(); });
      $(span).mouseover(function () { setHighlight($(this).attr('name'),true); });

      var li = $('<li></li>').get(0);
      $(li).append(span);

      $(suggestions_list).append(li);
    }

    // no results
    if (arr.length == 0){
      $(suggestions_list).append('<li class="jqac-warning">'+options.noresults+'</li>');
    }

    $(div).append(suggestions_list);
	

    // get position of target textfield
    // position holding div below it
    // set width of holding div to width of field
    var pos = me.offset();

    $(suggestions_menu).css('left', pos.left + "px");
    $(suggestions_menu).css('top', ( pos.top + me.height() + 2 ) + "px");
    if(!options.autowidth)
      $(suggestions_menu).width(me.width());

    // set mouseover functions for div
    // when mouse pointer leaves div, set a timeout to remove the list after an interval
    // when mouse enters div, kill the timeout so the list won't be removed
    $(suggestions_menu).mouseover(function(){ killTimeout() });
    $(suggestions_menu).mouseout(function(){ resetTimeout() });

    // add DIV to document
    $('body').append(suggestions_menu);

    // bgIFRAME support
    if($.fn.bgiframe)
      $(suggestions_menu).bgiframe({height: suggestions_menu.scrollHeight});


    // adjust height: add +20 for scrollbar
    if(suggestions_menu.scrollHeight > options.height){
      $(div).height(options.height);
      $(suggestions_menu).width($(suggestions_menu).width()+20);
    }
	
    // currently no item is highlighted
    current_highlight = 0;

    // remove list after an interval
    //clearSuggestionsTimer = setTimeout(function () { clearSuggestions() }, options.timeout);
  };
  
	function createLink(page, name){
		// 		1-20<span class="jqac-first">f</span><span class="jqac-prior">p</span><span class="jqac-next">n</span><span class="jqac-last">l</span>
		var link = $('<span class="jqac-' + name + '">&nbsp;</span>').get(0);
		var p = page;
		$(link).mousedown(function(ev){
			goPage(p);
			ev.preventDefault();
		});
		return link;
	}
  
	function goPage(page){
		if (page != null)
			callAjaxVal(options.last_val, page);
	}
  
  // set highlighted value
  function setHighlightedValue(timeOut){
    if(current_highlight && suggestions[current_highlight-1]){
      var sugg = suggestions[ current_highlight-1 ];
      if(sugg.affected_value != undefined && sugg.affected_value != '')
        setSuggestion(sugg.affected_value);
      else
        setSuggestion(sugg.value);
      // pass selected object to callback function, if exists
      if ($.isFunction(options.callback))
        options.callback( suggestions[current_highlight-1] );

	  if (suggestions_menu){
			if (timeOut)
				setTimeout(clearSuggestions, timeOut);
			else
				clearSuggestions();
	  }
    }
  };
  // change highlight according to key
  function changeHighlight(key){	
    if(!suggestions_list || suggestions.length == 0) return false;
    var n;
    if (key == ARRDOWN)
      n = current_highlight + 1;
    else if (key == ARRUP)
      n = current_highlight - 1;

    if (n > $(suggestions_list).children().size())
      n = 1;
    if (n < 1)
      n = $(suggestions_list).children().size();
    setHighlight(n);
  };
  // change highlight
  function setHighlight(n,mouse_mode){
    if (!suggestions_list) return false;
    if (current_highlight > 0) clearHighlight();
    current_highlight = Number(n);
    var li = $(suggestions_list).children().get(current_highlight-1);
    li.className = 'jqac-highlight';
    // for mouse mode don't adjust scroll! prevent scrolling jumps
    if(!mouse_mode) adjustScroll(li);
    killTimeout();
  };
  // clear highlight
  function clearHighlight(){
    if (!suggestions_list)return false;
    if (current_highlight > 0){
      $(suggestions_list).children().get(current_highlight-1).className = '';
      current_highlight = 0;
    }
  };
  // clear suggestions list
  function clearSuggestions(){
	    killTimeout();
	    if(suggestions_menu){
	      $(suggestions_menu).fadeOut(200, function(){$(this).remove()});
	      suggestions_menu = false;
	      suggestions_list = false;
	      current_highlight = 0;
	    }
  };
  /* set scroll */
  function adjustScroll(el){
    if(!suggestions_menu) return false;
	
	var div = $(suggestions_menu).find('div:first').get(0);
	
    var viewportHeight = div.clientHeight;        
    var wholeHeight = div.scrollHeight;
    var scrolled = div.scrollTop;
    var elTop = el.offsetTop;
    var elBottom = elTop + el.offsetHeight;
    if(elBottom > scrolled + viewportHeight){
      div.scrollTop = elBottom - viewportHeight;
    }
    else if(elTop < scrolled){
      div.scrollTop = elTop;
    }
    return true; 
  }
  /* timeout funcs*/
  function killTimeout(){
    clearTimeout(clearSuggestionsTimer);
  };
  function resetTimeout(){
    clearTimeout(clearSuggestionsTimer);
    //clearSuggestionsTimer = setTimeout(function () { clearSuggestions() }, 1000);
  };

})};

})($);
.evaluate(obj.alt);
			if(obj.options.type == "number") obj.setStyle("text-align", "right");
			obj.addEvent("mousedown", function(event) {
				event = new Event(event);
				event.stop();
			});
			obj.addEvent("mouseup", function(event) {
				event = new Event(event);
				event.stop();
				_onMouseUp(event, obj);
			}.bind(this));
			obj.addEvent("click", function(event) {
				event = new Event(event);
				event.stop();
			});
			obj.addEvent("keydown", function(event) {
				event = new Event(event);
				_onKeyDown(event, obj);
				this.fireEvent("onKeyDown", obj, 20);
			}.bind(this));
			obj.addEvent("keypress", function(event) {
				event = new Event(event);
				_onKeyPress(event, obj);
			}.bind(this));
			obj.addEvent("focus", function(event) {
				event = new Event(event);
				event.stop();
				_onFocus(event, obj);
				this.fireEvent("onFocus", obj, 20);
			}.bind(this));
			obj.addEvent("blur", function(event) {
				event = new Event(event);
				event.stop();
				_onBlur(event, obj);
				this.fireEvent("onBlur", obj, 20);
			}.bind(this));
		}.bind(this));
	},
*/
	};



})(jQuery);
