/* -- 名称:实现自动完成功能的jQuery插件 -- 功能:仿google搜索输入关键字即自动显示下拉框。 -- 作者:HXW(http://mrhgw.cnblogs.com, mrhgw@sohu.com) -- 使用:在$().ready(function() { //在此处加入以下代码初始化 }); $('#txtAutoComplete').autocomplete_HXW('http://localhost:1628/WebHR2009/Utils/GetSearchKeywords.aspx', { width: 450 //设置显示宽度。 }); 提示:参数设置见 $.fn.autocomplete_HXW.defaults 方法。 */ (function($) { $.fn.extend({ autocomplete_HXW: function(urlOrData, options) { var isURL = null != urlOrData && typeof urlOrData == "string"; options = $.extend({}, $.fn.autocomplete_HXW.defaults, { data: isURL ? null : urlOrData, ajaxURL: isURL ? urlOrData : null }, options); return this.each(function() { var ins = new $.Autocomplete_HXW($(this), options); //保存实例。 $.fn.autocomplete_HXW.addIns($(this).attr("id"), ins); }); } }); //创建一个自动完成的实例。 $.Autocomplete_HXW = function(_ol, _options) { //表示用jQuery获取的文本框对象。 var ol = _ol; //表示参数对象。 var options = _options; //当前对象实例名。 var instanceName = _ol.attr("id"); //下拉层。 var divPanel = null; //鼠标是否位于自动完成的层上。 var mouseInPanel = false; //用于缓存通过ajax载入的数据容器。 var dataCacher = new Array(); //ajax数据是否正在请求中。 var isBusy = false; //最后一次请求的网址。 var lastRequestUrl = null; //设置ajax请求的URL。 this.setAjaxURL = function(ajaxURL) { options.ajaxURL = ajaxURL; } //初始化下拉层。 if (null == divPanel) { var divPanelID = "div_autocomplete_HXW_" + instanceName; var _divPanel = $("#" + divPanelID); if (null == _divPanel[0]) { $("body").append(""); divPanel = $("#" + divPanelID); var w = undefined == options.width ? ol[0].offsetWidth : options.width; divPanel.css("width", w - 8); divPanel.css("left", ol.offset().left + "px"); divPanel.css("top", ol.offset().top + ol[0].offsetHeight + 1 + "px"); divPanel.bind("mouseover", function() { mouseInPanel = true; }); divPanel.bind("mouseout", function() { mouseInPanel = false; }); } else { divPanel = _divPanel; } } $().ready(function() { if ($.browser.msie) //ie浏览器 { document.getElementById(instanceName).onpropertychange = beginShowPanel; } else {//非ie浏览器,比如Firefox document.getElementById(instanceName).addEventListener("input", beginShowPanel, false); } $().unbind("keydown"); $().bind("keydown", function(e) { ALkeyAction(e) }); $("#" + instanceName).bind("click", beginShowPanel); }); //向上(38)或向下按键处理。 function ALkeyAction(e) { var ev = window.event || e; if (divPanel[0].style.display != "none") { if (ev.keyCode == 38 || ev.keyCode == 40) { var _currentIndex = $.fn.autocomplete_HXW.getCurrentIndex(instanceName); var c = ev.keyCode == 38 ? -1 : 1; _currentIndex = Number(_currentIndex) + Number(c * 1); if (_currentIndex <= -1) _currentIndex = -1; else if (_currentIndex > 0 && null == document.getElementById(divPanelID + "_item_" + _currentIndex)) _currentIndex = Number(_currentIndex) - 1; if (_currentIndex == -1) { $.fn.autocomplete_HXW.blurElement(instanceName, divPanel); } else { $.fn.autocomplete_HXW.setCurrentIndex(instanceName, _currentIndex); $.fn.autocomplete_HXW.focusElement(document.getElementById(divPanelID + "_item_" + _currentIndex), instanceName); } } else if (ev.keyCode == 13) { $.fn.autocomplete_HXW.clickElement(document.getElementById(divPanelID + "_item_" + $.fn.autocomplete_HXW.getCurrentIndex(instanceName)), instanceName); } } else { if (ev.keyCode == 13 && document.activeElement.id == instanceName) { //header.simpleSearch(); } } } //绑定一个鼠标事件。 ol.bind("mouseover", function() { $.fn.autocomplete_HXW.blurElement(instanceName, divPanel); }); //文档点击时关闭自动提示。 $().bind("click", function() { if (document.activeElement.id != instanceName) divPanel.hide(); }); //准备显示自动完成列表。 function beginShowPanel() { //获取关键词。 var v = $.trim(ol.val()); //判断当前输入框是否有焦点。 if (null == document.activeElement || document.activeElement.id != instanceName) return; //判断关键词是否为空。 if (v.length == 0) { divPanel.hide(); return; } //设置最后的关键词。 lastRequestUrl = null; if (isBusy) { lastRequestUrl = header.getSearchUrl(true); return; } var data = null; divPanel.html(""); //显示或获取数据。 if (v.length == 0 && null != options.defaultData) { //获取默认数据。 bindData(options.defaultData, false); } else if (null != options.data) { //如果设置了数据源,则直接显示。 bindData(options.data, true); } else { //从缓存中查找。 //获取区域。 var ajaxUrl = ""; try { ajaxUrl = header.getSearchUrl(true); } catch (e) { } var cacheKey = ajaxUrl.toLowerCase(); if (options.cacheData) { $.each(dataCacher, function(i, item) { if (item.key == cacheKey) { data = item.value; } }); if (null != data) { bindData(data); return; } } //没有缓存,则通过ajax从服务器上获取数据。 getJSON(ajaxUrl); } } //从服务器上获取JSON格式的数据。 function getJSON(ajaxUrl) { isBusy = true; $.ajax({ type: "GET", url: ajaxUrl, dataType: "json", cache: true, error: function() { isBusy = false; }, success: function(data) { //设置繁忙状态。 isBusy = false; //缓存数据。 if (options.cacheData) { var item = new Object(); item.key = ajaxUrl.toLowerCase(); item.value = data; dataCacher.push(item); } //如果有最后的关键词,则再次调用ajax。 if (null != lastRequestUrl && lastRequestUrl.length > 0) { var _l = lastRequestUrl; lastRequestUrl = null; getJSON(_l); return; } //绑定数据。 bindData(data, false); } }); } //绑定数据。 function bindData(data, filter) { //如果没有数据,退出。 if (null == data || data.length == 0) { divPanel.hide(); return; } //显示数据。 var s = ""; var index = 0; $.each(data, function(i, item) { //过滤数据。 if (filter && $.trim(item.Name).indexOf($.trim(ol.val())) != 0) return; var js_onclick = "javascript:var ol = $(\"#\" + this.getAttribute(\"myOLID\")); ol.val(this.getAttribute(\"myValue\"));"; var itemStyle = index % 2 == 0 ? $.fn.autocomplete_HXW.itembaseStyle : $.fn.autocomplete_HXW.itembaseStyle + $.fn.autocomplete_HXW.alternatItemStyle; s += "
" + item.Name + "
" + item.Value + "
\n"; index += 1; }); if (index <= 11) { divPanel.css("height", 20 * index + "px"); } else { divPanel.css({ "height": "200px", "overflow": "auto", "overfolw-y": "hidden" }); } divPanel.html(s); $.fn.autocomplete_HXW.setCurrentIndex(instanceName, -1); divPanel.show(); } } //默认参数设置。 $.fn.autocomplete_HXW.defaults = { data: null, //主数据源数组 ajaxURL: "", //ajax方式获取主数据源HTTP的URL(ajax数据格式为JSON,格式为:[{Name:'文员',Value:'500个结果'},{Name:'c#',Value:'1000个结果'}]) defaultData: null, //当文本框中没有任何字符串时显示的数据(数据格式为JSON,格式为:[{Name:'文员',Value:'500个结果'},{Name:'c#',Value:'1000个结果'}]) width: null, //下拉框的宽度,如果为null,则与文本框的宽度一致 cacheData: true //是否缓存数据 }; //-------------------------------供外部供用的方法(start)------------------------------------// //用于保存对象实例的数组。 var ac_global_instances_2597452690585 = new Array(); //添加对象实例。 $.fn.autocomplete_HXW.addIns = function(jqElementID, ins) { var obj = new Object(); obj.olID = jqElementID; obj.ins = ins; ac_global_instances_2597452690585.push(obj); } //根据对象ID获取实例对象。 $.fn.autocomplete_HXW.getInstance = function(jqElementID) { var ins = null; $.each(ac_global_instances_2597452690585, function(i, item) { if (item.olID == jqElementID) { ins = item.ins; } }); if (null == ins) alert("对不起,不存在ID为 " + jqElementID + " 的autocomplete_HXW对象。"); return ins; } //设置ajax请求的地址。 $.fn.autocomplete_HXW.setAjaxURL = function(jqElementID, ajaxURL) { var ins = $.fn.autocomplete_HXW.getInstance(jqElementID); ins.setAjaxURL(ajaxURL); } //获取当前实例的序号。 $.fn.autocomplete_HXW.getCurrentIndex = function(jqElementID) { return $.fn.autocomplete_HXW.getInstance(jqElementID).currentIndex; } //设置当前实例的序号。 $.fn.autocomplete_HXW.setCurrentIndex = function(jqElementID, value) { $.fn.autocomplete_HXW.getInstance(jqElementID).currentIndex = value; } //设置样式。 $.fn.autocomplete_HXW.itembaseStyle = "background-color:white; color:#5E5E5E; height:18px; padding-top:2px; FONT-SIZE: 12px; letter-spacing: 1px;FONT-FAMILY: verdana,宋体, lucida grande, arial, sans-serif; cursor:default; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;"; $.fn.autocomplete_HXW.alternatItemStyle = "color:#5E5E5E; background-color:#EEEEEE;"; //当某一项处于焦点状态时。 $.fn.autocomplete_HXW.focusElement = function(ol, jqElementID) { if (null == ol) return; var currentIndex = $(ol).attr("myIndex"); $.fn.autocomplete_HXW.setCurrentIndex(jqElementID, currentIndex); var focusedStyle = "color:white; background-color:#0A246A"; $.each(ol.parentNode.getElementsByTagName("div"), function(i, item) { if (null != item.getAttribute("myIndex")) $(item).attr("style", i % 2 == 0 ? $.fn.autocomplete_HXW.itembaseStyle : $.fn.autocomplete_HXW.itembaseStyle + $.fn.autocomplete_HXW.alternatItemStyle); }); var style = currentIndex % 2 == 0 ? $.fn.autocomplete_HXW.itembaseStyle : $.fn.autocomplete_HXW.itembaseStyle + $.fn.autocomplete_HXW.alternatItemStyle; $(ol).attr("style", style + " " + focusedStyle); } //当不选择任何一项时。 $.fn.autocomplete_HXW.blurElement = function(jqElementID, divPanel) { $.fn.autocomplete_HXW.setCurrentIndex(jqElementID, -1); $.each(divPanel[0].getElementsByTagName("div"), function(i, item) { if (null != item.getAttribute("myIndex")) $(item).attr("style", i % 2 == 0 ? $.fn.autocomplete_HXW.itembaseStyle : $.fn.autocomplete_HXW.itembaseStyle + $.fn.autocomplete_HXW.alternatItemStyle); }); } //当单击某一项时。 $.fn.autocomplete_HXW.clickElement = function(ol, jqElementID) { if (null != ol) document.getElementById(jqElementID).value = $(ol).attr("myValue"); //开始搜索(本站专用)。 header.search(); } //-------------------------------供外部供用的方法(end)------------------------------------// })(jQuery);