Jquery. AutoComplete. js Chinese version (firefox supported) _ jquery

Source: Internet
Author: User
Jquery. AutoComplete. js Chinese version (firefox is supported). Note that it fixes some bugs in Chinese Input. You can test them if you need them. The Code is as follows:


JQuery. autocomplete = function (input, options ){
// Create a link to self
Var me = this;
// Create jQuery object for input element
Var $ input = $ (input). attr ("autocomplete", "off ");
// Apply inputClass if necessary
If (options. inputClass) $ input. addClass (options. inputClass );
// Create results
Var results = document. createElement ("p ");
// Create jQuery object for results
Var $ results = $ (results );
Using results.hide().addclass(options.resultsclass).css ("position", "absolute ");
If (options. width> 0) Then results.css ("width", options. width );
// Add to body element
$ ("Body"). append (results );
Input. autocompleter = me;
Var timeout = null;
Var prev = "";
Var active =-1;
Var cache = {};
Var keyb = false;
Var hasFocus = false;
Var lastKeyPressCode = null;
// Flush cache
Function flushCache (){
Cache = {};
Cache. data = {};
Cache. length = 0;
};
// Flush cache
FlushCache ();
// If there is a data array supplied
If (options. data! = Null ){
Var sFirstChar = "", stMatchSets ={}, row = [];
// No url was specified, we need to adjust the cache length to make sure it fits the local data store
If (typeof options. url! = "String") options. cacheLength = 1;
// Loop through the array and create a lookup structure
For (var I = 0; I <options. data. length; I ++ ){
// If row is a string, make an array otherwise just reference the array
Row = (typeof options. data [I] = "string ")? [Options. data [I]: options. data [I]);
// If the length is zero, don't add to list
If (row [0]. length> 0 ){
// Get the first character
SFirstChar = row [0]. substring (0, 1). toLowerCase ();
// If no lookup array for this character exists, look it up now
If (! StMatchSets [sFirstChar]) stMatchSets [sFirstChar] = [];
// If the match is a string
StMatchSets [sFirstChar]. push (row );
}
}
// Add the data items to the cache
For (var k in stMatchSets ){
// Increase the cache size
Options. cacheLength ++;
// Add to the cache
AddToCache (k, stMatchSets [k]);
}
}
$ Input
. Keydown (function (e ){
// Track last key pressed
LastKeyPressCode = e. keyCode;
Switch (e. keyCode ){
Case 38: // up
E. preventDefault ();
MoveSelect (-1 );
Break;
Case 40: // down
E. preventDefault ();
MoveSelect (1 );
Break;
Case 9: // tab
Case 13: // return
If (selectCurrent ()){
// Make sure to blur off the current field
$ Input. get (0). blur ();
E. preventDefault ();
}
Break;
Default:
Active =-1;
If (timeout) clearTimeout (timeout );
Timeout = setTimeout (function () {onChange () ;}, options. delay );
Break;
}
})
. Focus (function (){
// Track whether the field has focus, we shouldn't process any results if the field no longer has focus
HasFocus = true;
})
. Blur (function (){
// Track whether the field has focus
HasFocus = false;
HideResults ();
})
. Bind ("input", function (){
// @ Hack: support for inputing chinese characters in firefox
OnChange (0, true );
});
HideResultsNow ();
Function onChange (){
// Ignore if the following keys are pressed: [del] [shift] [capslock]
If (lastKeyPressCode = 46 | (lastKeyPressCode> 8 & lastKeyPressCode <32) return $ results. hide ();
Var v = $ input. val ();
If (v = prev) return;
Prev = v;
If (v. length> = options. minChars ){
$ Input. addClass (options. loadingClass );
RequestData (v );
} Else {
$ Input. removeClass (options. loadingClass );
$ Results. hide ();
}
};
Function moveSelect (step ){
Var lis = $ ("li", results );
If (! Lis) return;
Active + = step;
If (active <0 ){
Active = 0;
} Else if (active> = lis. size ()){
Active = lis. size ()-1;
}
Lis. removeClass ("ac_over ");
$ (Lis [active]). addClass ("ac_over ");
// Weird behaviour in IE
// If (lis [active] & lis [active]. scrollIntoView ){
// Lis [active]. scrollIntoView (false );
//}
};
Function selectCurrent (){
Var li = $ ("li. ac_over", results) [0];
If (! Li ){
Var $ li = $ ("li", results );
If (options. selectOnly ){
If ($ li. length = 1) li = $ li [0];
} Else if (options. selectFirst ){
Li = $ li [0];
}
}
If (li ){
SelectItem (li );
Return true;
} Else {
Return false;
}
};
Function selectItem (li ){
If (! Li ){
Li = document. createElement ("li ");
Li. extra = [];
Li. selectValue = "";
}
Var v = $. trim (li. selectValue? Li. selectValue: li. innerHTML );
Input. lastSelected = v;
Prev = v;
Optional results.html ("");
$ Input. val (v );
HideResultsNow ();
If (options. onItemSelect) setTimeout (function () {options. onItemSelect (li)}, 1 );
};
// Selects a portion of the input string
Function createSelection (start, end ){
// Get a reference to the input element
Var field = $ input. get (0 );
If (field. createTextRange ){
Var selRange = field. createTextRange ();
SelRange. collapse (true );
SelRange. moveStart ("character", start );
SelRange. moveEnd ("character", end );
SelRange. select ();
} Else if (field. setSelectionRange ){
Field. setSelectionRange (start, end );
} Else {
If (field. selectionStart ){
Field. selectionStart = start;
Field. selectionEnd = end;
}
}
Field. focus ();
};
// Fills in the input box w/the first match (assumed to be the best match)
Function autoFill (sValue ){
// If the last user key pressed was backspace, don't autofill
If (lastKeyPressCode! = 8 ){
// Fill in the value (keep the case the user has typed)
$ Input. val ($ input. val () + sValue. substring (prev. length ));
// Select the portion of the value not typed by the user (so the next character will erase)
CreateSelection (prev. length, sValue. length );
}
};
Function showResults (){
// Get the position of the input field right now (in case the DOM is shifted)
Var pos = findPos (input );
// Either use the specified width, or autocalculate based on form element
Var iWidth = (options. width> 0 )? Options. width: $ input. width ();
// Reposition
$Results.css ({
Width: parseInt (iWidth) + "px ",
Top: (pos. y + input. offsetHeight) + "px ",
Left: pos. x + "px"
}). Show ();
};
Function hideResults (){
If (timeout) clearTimeout (timeout );
Timeout = setTimeout (hideResultsNow, 200 );
};
Function hideResultsNow (){
If (timeout) clearTimeout (timeout );
$ Input. removeClass (options. loadingClass );
If ($ results. is (": visible ")){
$ Results. hide ();
}
If (options. mustMatch ){
Var v = $ input. val ();
If (v! = Input. lastSelected ){
SelectItem (null );
}
}
};
Function receiveData (q, data ){
If (data ){
$ Input. removeClass (options. loadingClass );
Results. innerHTML = "";
// If the field no longer has focus or if there are no matches, do not display the drop down
If (! HasFocus | data. length = 0) return hideResultsNow ();
If ($. browser. msie ){
// We put a styled iframe behind the calendar so html select elements don't show through
$ Results. append (document. createElement ('iframe '));
}
Results. appendChild (dataToDom (data ));
// Autofill in the complete box w/the first match as long as the user hasn' t entered in more data
If (options. autoFill & ($ input. val (). toLowerCase () = q. toLowerCase () autoFill (data [0] [0]);
ShowResults ();
} Else {
HideResultsNow ();
}
};
Function parseData (data ){
If (! Data) return null;
Var parsed = [];
Var rows = data. split (options. lineSeparator );
For (var I = 0; I <rows. length; I ++ ){
Var row = $. trim (rows [I]);
If (row ){
Parsed [parsed. length] = row. split (options. cellSeparator );
}
}
Return parsed;
};
Function dataToDom (data ){
Var ul = document. createElement ("ul ");
Var num = data. length;
// Limited results to a max number
If (options. maxItemsToShow> 0) & (options. maxItemsToShow <num) num = options. maxItemsToShow;
For (var I = 0; I <num; I ++ ){
Var row = data [I];
If (! Row) continue;
Var li = document. createElement ("li ");
If (options. formatItem ){
Li. innerHTML = options. formatItem (row, I, num );
Li. selectValue = row [0];
} Else {
Li. innerHTML = row [0];
Li. selectValue = row [0];
}
Var extra = null;
If (row. length> 1 ){
Extra = [];
For (var j = 1; j <row. length; j ++ ){
Extra [extra. length] = row [j];
}
}
Li. extra = extra;
Ul. appendChild (li );
$ (Li). hover (
Function () {$ ("li", ul ). removeClass ("ac_over"); $ (this ). addClass ("ac_over"); active = $ ("li", ul ). indexOf ($ (this ). get (0 ));},
Function () {$ (this). removeClass ("ac_over ");}
). Click (function (e) {e. preventDefault (); e. stopPropagation (); selectItem (this )});
}
Return ul;
};
Function requestData (q ){
If (! Options. matchCase) q = q. toLowerCase ();
Var data = options. cacheLength? LoadFromCache (q): null;
// Recieve the cached data
If (data ){
ReceiveData (q, data );
// If an AJAX url has been supplied, try loading the data now
} Else if (typeof options. url = "string") & (options. url. length> 0 )){
$. Get (makeUrl (q), function (data ){
Data = parseData (data );
AddToCache (q, data );
ReceiveData (q, data );
});
// If there's been no data found, remove the loading class
} Else {
$ Input. removeClass (options. loadingClass );
}
};
Function makeUrl (q ){
Var url = options. url + "? Q = "+ escape (q );
For (var I in options. extraParams ){
Url + = "&" + I + "=" + escape (options. extraParams [I]);
}
Return url;
};
Function loadFromCache (q ){
If (! Q) return null;
If (cache. data [q]) return cache. data [q];
If (options. matchSubset ){
For (var I = q. length-1; I> = options. minChars; I --){
Var qs = q. substr (0, I );
Var c = cache. data [qs];
If (c ){
Var csub = [];
For (var j = 0; j <c. length; j ++ ){
Var x = c [j];
Var x0 = x [0];
If (matchSubset (x0, q )){
Csub [csub. length] = x;
}
}
Return csub;
}
}
}
Return null;
};
Function matchSubset (s, sub ){
If (! Options. matchCase) s = s. toLowerCase ();
Var I = s. indexOf (sub );
If (I =-1) return false;
Return I = 0 | options. matchContains;
};
This. flushCache = function (){
FlushCache ();
};
This. setExtraParams = function (p ){
Options. extraParams = p;
};
This. findValue = function (){
Var q = $ input. val ();
If (! Options. matchCase) q = q. toLowerCase ();
Var data = options. cacheLength? LoadFromCache (q): null;
If (data ){
FindValueCallback (q, data );
} Else if (typeof options. url = "string") & (options. url. length> 0 )){
$. Get (makeUrl (q), function (data ){
Data = parseData (data)
AddToCache (q, data );
FindValueCallback (q, data );
});
} Else {
// No matches
FindValueCallback (q, null );
}
}
Function findValueCallback (q, data ){
If (data) $ input. removeClass (options. loadingClass );
Var num = (data )? Data. length: 0;
Var li = null;
For (var I = 0; I <num; I ++ ){
Var row = data [I];
If (row [0]. toLowerCase () = q. toLowerCase ()){
Li = document. createElement ("li ");
If (options. formatItem ){
Li. innerHTML = options. formatItem (row, I, num );
Li. selectValue = row [0];
} Else {
Li. innerHTML = row [0];
Li. selectValue = row [0];
}
Var extra = null;
If (row. length> 1 ){
Extra = [];
For (var j = 1; j <row. length; j ++ ){
Extra [extra. length] = row [j];
}
}
Li. extra = extra;
}
}
If (options. onFindValue) setTimeout (function () {options. onFindValue (li)}, 1 );
}
Function addToCache (q, data ){
If (! Data |! Q |! Options. cacheLength) return;
If (! Cache. length | cache. length> options. cacheLength ){
FlushCache ();
Cache. length ++;
} Else if (! Cache [q]) {
Cache. length ++;
}
Cache. data [q] = data;
};
Function findPos (obj ){
Var curleft = obj. offsetLeft | 0;
Var curtop = obj. offsetTop | 0;
While (obj = obj. offsetParent ){
Curleft + = obj. offsetLeft
Curtop + = obj. offsetTop
}
Return {x: curleft, y: curtop };
}
}
JQuery. fn. autocomplete = function (url, options, data ){
// Make sure options exists
Options = options | {};
// Set url as option
Options. url = url;
// Set some bulk local data
Options. data = (typeof data = "object") & (data. constructor = Array ))? Data: null;
// Set default values for required options
Options. inputClass = options. inputClass | "ac_input ";
Options. resultsClass = options. resultsClass | "ac_results ";
Options. lineSeparator = options. lineSeparator | "\ n ";
Options. cellSeparator = options. cellSeparator | "| ";
Options. minChars = options. minChars | 1;
Options. delay = options. delay | 400;
Options. matchCase = options. matchCase | 0;
Options. matchSubset = options. matchSubset | 1;
Options. matchContains = options. matchContains | 0;
Options. cacheLength = options. cacheLength | 1;
Options. mustMatch = options. mustMatch | 0;
Options. extraParams = options. extraParams || {};
Options. loadingClass = options. loadingClass | "ac_loading ";
Options. selectFirst = options. selectFirst | false;
Options. selectOnly = options. selectOnly | false;
Options. maxItemsToShow = options. maxItemsToShow |-1;
Options. autoFill = options. autoFill | false;
Options. width = parseInt (options. width, 10) | 0;
This. each (function (){
Var input = this;
New jQuery. autocomplete (input, options );
});
// Don't break the chain
Return this;
}
JQuery. fn. autocompleteArray = function (data, options ){
Return this. autocomplete (null, options, data );
}
JQuery. fn. indexOf = function (e ){
For (var I = 0; I <this. length; I ++ ){
If (this [I] = e) return I;
}
Return-1;
};

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.