手机
当前位置:查字典教程网 >编程开发 >Javascript教程 >jquery.AutoComplete.js中文修正版(支持firefox)
jquery.AutoComplete.js中文修正版(支持firefox)
摘要:复制代码代码如下:jQuery.autocomplete=function(input,options){//Createalinktose...

复制代码 代码如下:

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("div");

// Create jQuery object for results

var $results = $(results);

$results.hide().addClass(options.resultsClass).css("position", "absolute");

if (options.width > 0) $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;

$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;

};

【jquery.AutoComplete.js中文修正版(支持firefox)】相关文章:

设为首页 加入收藏的js代码

javascript实现可全选、反选及删除表格的方法

js实现鼠标经过表格行变色的方法

Javascript获取统一管理的提示语(message)

jquery.validate使用时遇到的问题

JavaScript中exec函数用法实例分析

Jquery动态添加输入框的方法

文字幻灯片

仿DVBBS下拉菜单效果 jb51修正无错

Node.js 条形码识别程序构建思路详解

精品推荐
分类导航