/**
* Extending jQuery with autocomplete
* Version: 1.4.2
* Author: Yanik Gleyzer (clonyara)
*/
(function($) {
// some key codes
var RETURN = 13;
var TAB = 9;
var ESC = 27;
var ARRLEFT = 37;
var ARRUP = 38;
var ARRRIGHT = 39;
var ARRDOWN = 40;
var BACKSPACE = 8;
var DELETE = 46;
function debug(s){
$('#info').append(htmlspecialchars(s)+'
');
}
// getting caret position obj: {start,end}
function getCaretPosition(obj){
var start = -1;
var end = -1;
if(typeof obj.selectionStart != "undefined"){
start = obj.selectionStart;
end = obj.selectionEnd;
}
else if(document.selection&&document.selection.createRange){
var M=document.selection.createRange();
var Lp;
try{
Lp = M.duplicate();
Lp.moveToElementText(obj);
}catch(e){
Lp=obj.createTextRange();
}
Lp.setEndPoint("EndToStart",M);
start=Lp.text.length;
if(start>obj.value.length)
start = -1;
Lp.setEndPoint("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','>');
}
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 : 500 ,
timeout : 5000 ,
minchars : 3 ,
multi : false ,
cache : true ,
height : 150 ,
autowidth : false ,
noresults : 'No results'
},
options);
// bind key events
// handle special keys here
me.keydown(function(ev){
switch(ev.which){
// return choose highlighted item or default propogate
case RETURN:
if(!suggestions_menu) return true;
else setHighlightedValue();
return false;
// escape clears menu
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
case ARRUP:
changeHighlight(ev.keyCode);
return false;
// down changes highlight or open new menu
case ARRDOWN:
if(!suggestions_menu) getSuggestions(getUserInput());
else changeHighlight(ev.keyCode);
return false;
}
return true;
});
// handle normal characters here
me.keyup(function(ev) {
switch(ev.which) {
case RETURN: case ESC: case ARRLEFT: case ARRRIGHT: case ARRUP: case ARRDOWN:
return false;
default:
getSuggestions(getUserInput());
}
return true;
});
// init variables
var user_input = "";
var input_chars_size = 0;
var suggestions = [];
var current_highlight = 0;
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(;end0 && orig.charAt(start-1) != ',';start--){}
var end = pos.start;
for(;end0?' ':'') + 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){
var arr = [];
for (var i=0;i