initial commit
This commit is contained in:
387
app/webroot/cdn/js/jquery.autocomplete.js
Normal file
387
app/webroot/cdn/js/jquery.autocomplete.js
Normal file
@@ -0,0 +1,387 @@
|
||||
/**
|
||||
* Extending jQuery with autocomplete
|
||||
* Version: 1.0
|
||||
*/
|
||||
(function($) {
|
||||
|
||||
var RETURN = 13;
|
||||
var TAB = 9;
|
||||
var ESC = 27;
|
||||
var ARRUP = 38;
|
||||
var ARRDN = 40;
|
||||
|
||||
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};
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.autocomplete =
|
||||
function(options){
|
||||
if(!options && (!$.isFunction(options.get) || !options.ajax_get)){
|
||||
return $(this);
|
||||
}
|
||||
// options
|
||||
options = $.extend({
|
||||
delay : 500 ,
|
||||
timeout : 5000 ,
|
||||
minchars : 3 ,
|
||||
multi : false ,
|
||||
cache : true ,
|
||||
height : 150 ,
|
||||
noresults : 'No results'
|
||||
},
|
||||
options);
|
||||
// take me
|
||||
var me = $(this);
|
||||
var me_this = $(this).get(0);
|
||||
// bind key events
|
||||
me.keypress(function(ev){
|
||||
var key = ev.which;
|
||||
switch(key){
|
||||
case RETURN:
|
||||
if(!current_highlight) getSuggestions(getUserInput());
|
||||
else setHighlightedValue();
|
||||
return false;
|
||||
case ESC:
|
||||
clearSuggestions();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
me.keyup(function(ev){
|
||||
var key = ev.which;
|
||||
// set responses to keydown events in the field
|
||||
// this allows the user to use the arrow keys to scroll through the results
|
||||
switch(key){
|
||||
case ESC: case RETURN: return false;
|
||||
case ARRUP:
|
||||
changeHighlight(key);
|
||||
return false;
|
||||
case ARRDN:
|
||||
changeHighlight(key);
|
||||
return false;
|
||||
default:
|
||||
getSuggestions(getUserInput());
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// no autocomplete!
|
||||
me.attr("autocomplete","off");
|
||||
|
||||
// init variables
|
||||
var user_input = "";
|
||||
var input_chars_size = 0;
|
||||
var suggestions = [];
|
||||
var current_highlight = 0;
|
||||
var suggestions_menu = null;
|
||||
var suggestions_list = null;
|
||||
var clearSuggestionsTimer = false;
|
||||
var ajaxTimer = false;
|
||||
|
||||
// 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,pos.start-start);
|
||||
$('#info').text("start "+start+" end "+end+" pos "+pos.start+" "+val);
|
||||
}
|
||||
return 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) + val + orig.substr(end);
|
||||
me.val(new_val);
|
||||
$('#info').text("set "+(start+val.length));
|
||||
setCaret(me_this,start+val.length);
|
||||
}
|
||||
else{
|
||||
me_this.focus();
|
||||
me.val(val);
|
||||
}
|
||||
}
|
||||
// get suggestions
|
||||
function getSuggestions(val){
|
||||
if (val == user_input) return false;
|
||||
// input length is less than the min required to trigger a request
|
||||
// reset input string
|
||||
// do nothing
|
||||
if (val.length < options.minchars){
|
||||
clearSuggestions();
|
||||
user_input = false;
|
||||
return false;
|
||||
}
|
||||
// if caching enabled, and user is typing (ie. length of input is increasing)
|
||||
// filter results out of suggestions from last request
|
||||
if (val.length > input_chars_size && suggestions.length && options.cache){
|
||||
var arr = [];
|
||||
for (var i=0;i<suggestions.length;i++){
|
||||
if(suggestions[i].value.substr(0,val.length).toLowerCase() == val.toLowerCase())
|
||||
arr.push( suggestions[i] );
|
||||
}
|
||||
|
||||
user_input = val;
|
||||
input_chars_size = val.length;
|
||||
suggestions = arr;
|
||||
createList(suggestions);
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
// do new request
|
||||
user_input = val;
|
||||
input_chars_size = val.length;
|
||||
clearTimeout(ajaxTimer);
|
||||
ajaxTimer = setTimeout(
|
||||
function(){
|
||||
//try{
|
||||
suggestions = [];
|
||||
// call pre callback, if exists
|
||||
if($.isFunction(options.pre_callback))
|
||||
options.pre_callback();
|
||||
// call get
|
||||
if($.isFunction(options.get)){
|
||||
var jsondata = options.get(val);
|
||||
for(var i=0;i<jsondata.length;i++){
|
||||
suggestions.push(jsondata[i]);
|
||||
}
|
||||
createList(suggestions);
|
||||
}
|
||||
if($.isFunction(options.ajax_get)){
|
||||
options.ajax_get(val,function(jsondata){
|
||||
for(var i=0;i<jsondata.length;i++){
|
||||
suggestions.push(jsondata[i]);
|
||||
}
|
||||
createList(suggestions);
|
||||
});
|
||||
}
|
||||
|
||||
//}catch(e){
|
||||
// alert('Error when AJAX call: '+e);
|
||||
//}
|
||||
},
|
||||
options.delay );
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// create suggestions list
|
||||
function createList(arr){
|
||||
// get rid of old list
|
||||
// and clear the list removal timeout
|
||||
if(suggestions_menu) $(suggestions_menu).remove();
|
||||
killTimeout();
|
||||
|
||||
// create holding div
|
||||
suggestions_menu = $('<div class="jqac-menu"></div>').get(0);
|
||||
|
||||
// ovveride some necessary CSS properties
|
||||
$(suggestions_menu).css('position','absolute');
|
||||
$(suggestions_menu).css('max-height',options.height+'px');
|
||||
$(suggestions_menu).css('overflow-y','auto');
|
||||
|
||||
// create and populate ul
|
||||
suggestions_list = $('<ul></ul>').get(0);
|
||||
|
||||
// loop throught arr of suggestions
|
||||
// creating an LI element for each suggestion
|
||||
for (var i=0;i<arr.length;i++){
|
||||
// format output with the input enclosed in a EM element
|
||||
// (as HTML, not DOM)
|
||||
var val = new String(arr[i].value);
|
||||
// using RE
|
||||
var re = new RegExp("("+user_input+")",'ig');
|
||||
var output = val.replace(re,'<em>$1</em>');
|
||||
// using substr
|
||||
//var st = val.toLowerCase().indexOf( user_input.toLowerCase() );
|
||||
//var len = user_input.length;
|
||||
//var output = val.substring(0,st)+"<em>"+val.substring(st,st+len)+"</em>"+val.substring(st+len);
|
||||
|
||||
var span = $('<span class="jqac-link">'+output+'</span>').get(0);
|
||||
if (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')); });
|
||||
|
||||
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>');
|
||||
}
|
||||
|
||||
$(suggestions_menu).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");
|
||||
$(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() });
|
||||
$(suggestions_menu).ready(function(){
|
||||
|
||||
});
|
||||
|
||||
// add DIV to document
|
||||
$('body').append(suggestions_menu);
|
||||
|
||||
// adjust height
|
||||
if($(suggestions_menu).height() > options.height){
|
||||
$(suggestions_menu).height(options.height);
|
||||
}
|
||||
|
||||
// currently no item is highlighted
|
||||
current_highlight = 0;
|
||||
|
||||
// remove list after an interval
|
||||
clearSuggestionsTimer = setTimeout(function () { clearSuggestions() }, options.timeout);
|
||||
};
|
||||
// set highlighted value
|
||||
function setHighlightedValue(){
|
||||
if(current_highlight && suggestions[current_highlight-1]){
|
||||
setSuggestion(suggestions[ current_highlight-1 ].value);
|
||||
// pass selected object to callback function, if exists
|
||||
if ($.isFunction(options.callback))
|
||||
options.callback( suggestions[current_highlight-1] );
|
||||
|
||||
clearSuggestions();
|
||||
}
|
||||
};
|
||||
// change highlight according to key
|
||||
function changeHighlight(key){
|
||||
if(!suggestions_list) return false;
|
||||
var n;
|
||||
if (key == ARRDN)
|
||||
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){
|
||||
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';
|
||||
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).remove();
|
||||
suggestions_menu = null;
|
||||
current_highlight = 0;
|
||||
user_input = false;
|
||||
}
|
||||
};
|
||||
// set scroll
|
||||
function adjustScroll(el){
|
||||
if(!suggestions_menu) return false;
|
||||
var viewportHeight = suggestions_menu.clientHeight;
|
||||
var wholeHeight = suggestions_menu.scrollHeight;
|
||||
var scrolled = suggestions_menu.scrollTop;
|
||||
var elTop = el.offsetTop;
|
||||
var elBottom = elTop + el.offsetHeight
|
||||
if(elBottom > scrolled + viewportHeight){
|
||||
suggestions_menu.scrollTop = elBottom - viewportHeight;
|
||||
}
|
||||
else if(elTop < scrolled){
|
||||
suggestions_menu.scrollTop = elTop;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// timeout funcs
|
||||
function killTimeout(){
|
||||
clearTimeout(clearSuggestionsTimer);
|
||||
};
|
||||
function resetTimeout(){
|
||||
clearTimeout(clearSuggestionsTimer);
|
||||
clearSuggestionsTimer = setTimeout(function () { clearSuggestions() }, 1000);
|
||||
};
|
||||
|
||||
return $(this);
|
||||
|
||||
};
|
||||
|
||||
})($);
|
||||
Reference in New Issue
Block a user