为上一篇服务的autocomplete.js
/** * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * � Copyright 2005 Richard Heyes */ /** * Global vars */ __AutoComplete = new Array(); // Basic UA detection isIE = document.all ? true : false; isGecko = navigator.userAgent.toLowerCase().indexOf('gecko') != -1; isOpera = navigator.userAgent.toLowerCase().indexOf('opera') != -1; /** * Attachs the autocomplete object to a form element. Sets * onkeypress event on the form element. * * @param string formElement Name of form element to attach to * @param array data Array of strings of which to use as the autocomplete data */ function AutoComplete_Create (id, data) { __AutoComplete[id] = {'data':data, 'isVisible':false, 'element':document.getElementById(id), 'dropdown':null, 'highlighted':null}; __AutoComplete[id]['element'].setAttribute('autocomplete', 'off'); __AutoComplete[id]['element'].onkeydown = function(e) {return AutoComplete_KeyDown(this.getAttribute('id'), e);} __AutoComplete[id]['element'].onkeyup = function(e) {return AutoComplete_KeyUp(this.getAttribute('id'), e);} __AutoComplete[id]['element'].onkeypress = function(e) {if (!e) e = window.event; if (e.keyCode == 13 || isOpera) return false;} __AutoComplete[id]['element'].ondblclick = function() {AutoComplete_ShowDropdown(this.getAttribute('id'));} __AutoComplete[id]['element'].onclick = function(e) {if (!e) e = window.event; e.cancelBubble = true; e.returnValue = false;} // Hides the dropdowns when document clicked var docClick = function() { for (id in __AutoComplete) { AutoComplete_HideDropdown(id); } } if (document.addEventListener) { document.addEventListener('click', docClick, false); } else if (document.attachEvent) { document.attachEvent('onclick', docClick, false); } // Max number of items shown at once if (arguments[2] != null) { __AutoComplete[id]['maxitems'] = arguments[2]; __AutoComplete[id]['firstItemShowing'] = 0; __AutoComplete[id]['lastItemShowing'] = arguments[2] - 1; } AutoComplete_CreateDropdown(id); // Prevent select dropdowns showing thru if (isIE) { __AutoComplete[id]['iframe'] = document.createElement('iframe'); __AutoComplete[id]['iframe'].id = id +'_iframe'; __AutoComplete[id]['iframe'].style.position = 'absolute'; __AutoComplete[id]['iframe'].style.top = '0'; __AutoComplete[id]['iframe'].style.left = '0'; __AutoComplete[id]['iframe'].style.width = '0px'; __AutoComplete[id]['iframe'].style.height = '0px'; __AutoComplete[id]['iframe'].style.zIndex = '98'; __AutoComplete[id]['iframe'].style.visibility = 'hidden'; __AutoComplete[id]['element'].parentNode.insertBefore(__AutoComplete[id]['iframe'], __AutoComplete[id]['element']); } } /** * Creates the dropdown layer * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_CreateDropdown(id) { var left = AutoComplete_GetLeft(__AutoComplete[id]['element']); var top = AutoComplete_GetTop(__AutoComplete[id]['element']) + __AutoComplete[id]['element'].offsetHeight; var width = __AutoComplete[id]['element'].offsetWidth; __AutoComplete[id]['dropdown'] = document.createElement('div'); __AutoComplete[id]['dropdown'].className = 'autocomplete'; // Don't use setAttribute() __AutoComplete[id]['element'].parentNode.insertBefore(__AutoComplete[id]['dropdown'], __AutoComplete[id]['element']); // Position it __AutoComplete[id]['dropdown'].style.left = left + 'px'; __AutoComplete[id]['dropdown'].style.top = top + 'px'; __AutoComplete[id]['dropdown'].style.width = width + 'px'; __AutoComplete[id]['dropdown'].style.zIndex = '99'; __AutoComplete[id]['dropdown'].style.visibility = 'hidden'; } /** * Gets left coord of given element * * @param object element The element to get the left coord for */ function AutoComplete_GetLeft(element) { var curNode = element; var left = 0; do { left += curNode.offsetLeft; curNode = curNode.offsetParent; } while(curNode.tagName.toLowerCase() != 'body'); return left; } /** * Gets top coord of given element * * @param object element The element to get the top coord for */ function AutoComplete_GetTop(element) { var curNode = element; var top = 0; do { top += curNode.offsetTop; curNode = curNode.offsetParent; } while(curNode.tagName.toLowerCase() != 'body'); return top; } /** * Shows the dropdown layer * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_ShowDropdown(id) { AutoComplete_HideAll(); var value = __AutoComplete[id]['element'].value; var toDisplay = new Array(); var newDiv = null; var text = null; var numItems = __AutoComplete[id]['dropdown'].childNodes.length; // Remove all child nodes from dropdown while (__AutoComplete[id]['dropdown'].childNodes.length > 0) { __AutoComplete[id]['dropdown'].removeChild(__AutoComplete[id]['dropdown'].childNodes[0]); } // Go thru data searching for matches for (i=0; i<__AutoComplete[id]['data'].length; ++i) { if (__AutoComplete[id]['data'][i].substr(0, value.length) == value) { toDisplay[toDisplay.length] = __AutoComplete[id]['data'][i]; } } // No matches? if (toDisplay.length == 0) { AutoComplete_HideDropdown(id); return; } // Add data to the dropdown layer for (i=0; i__AutoComplete[id]['maxitems'] && navigator.userAgent.indexOf('MSIE') == -1) { newDiv.style.width = __AutoComplete[id]['element'].offsetWidth - 22 + 'px'; } newDiv.onmouseover = function() {AutoComplete_HighlightItem(__AutoComplete[id]['element'].getAttribute('id'), this.getAttribute('index'));}; newDiv.onclick = function() {AutoComplete_SetValue(__AutoComplete[id]['element'].getAttribute('id')); AutoComplete_HideDropdown(__AutoComplete[id]['element'].getAttribute('id'));} text = document.createTextNode(toDisplay[i]); newDiv.appendChild(text); __AutoComplete[id]['dropdown'].appendChild(newDiv); } // Too many items? if (toDisplay.length > __AutoComplete[id]['maxitems']) { __AutoComplete[id]['dropdown'].style.height = (__AutoComplete[id]['maxitems'] * 15) + 2 + 'px'; } else { __AutoComplete[id]['dropdown'].style.height = ''; } /** * Set left/top in case of document movement/scroll/window resize etc */ __AutoComplete[id]['dropdown'].style.left = AutoComplete_GetLeft(__AutoComplete[id]['element']); __AutoComplete[id]['dropdown'].style.top = AutoComplete_GetTop(__AutoComplete[id]['element']) + __AutoComplete[id]['element'].offsetHeight; // Show the iframe for IE if (isIE) { __AutoComplete[id]['iframe'].style.top = __AutoComplete[id]['dropdown'].style.top; __AutoComplete[id]['iframe'].style.left = __AutoComplete[id]['dropdown'].style.left; __AutoComplete[id]['iframe'].style.width = __AutoComplete[id]['dropdown'].offsetWidth; __AutoComplete[id]['iframe'].style.height = __AutoComplete[id]['dropdown'].offsetHeight; __AutoComplete[id]['iframe'].style.visibility = 'visible'; } // Show dropdown if (!__AutoComplete[id]['isVisible']) { __AutoComplete[id]['dropdown'].style.visibility = 'visible'; __AutoComplete[id]['isVisible'] = true; } // If now showing less items than before, reset the highlighted value if (__AutoComplete[id]['dropdown'].childNodes.length != numItems) { __AutoComplete[id]['highlighted'] = null; } } /** * Hides the dropdown layer * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_HideDropdown(id) { if (__AutoComplete[id]['iframe']) { __AutoComplete[id]['iframe'].style.visibility = 'hidden'; } __AutoComplete[id]['dropdown'].style.visibility = 'hidden'; __AutoComplete[id]['highlighted'] = null; __AutoComplete[id]['isVisible'] = false; } /** * Hides all dropdowns */ function AutoComplete_HideAll() { for (id in __AutoComplete) { AutoComplete_HideDropdown(id); } } /** * Highlights a specific item * * @param string id The form elements id. Used to identify the correct dropdown. * @param int index The index of the element in the dropdown to highlight */ function AutoComplete_HighlightItem(id, index) { if (__AutoComplete[id]['dropdown'].childNodes[index]) { for (var i=0; i<__AutoComplete[id]['dropdown'].childNodes.length; ++i) { if (__AutoComplete[id]['dropdown'].childNodes[i].className == 'autocomplete_item_highlighted') { __AutoComplete[id]['dropdown'].childNodes[i].className = 'autocomplete_item'; } } __AutoComplete[id]['dropdown'].childNodes[index].className = 'autocomplete_item_highlighted'; __AutoComplete[id]['highlighted'] = index; } } /** * Highlights the menu item with the given index * * @param string id The form elements id. Used to identify the correct dropdown. * @param int index The index of the element in the dropdown to highlight */ function AutoComplete_Highlight(id, index) { // Out of bounds checking if (index == 1 && __AutoComplete[id]['highlighted'] == __AutoComplete[id]['dropdown'].childNodes.length - 1) { __AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']].className = 'autocomplete_item'; __AutoComplete[id]['highlighted'] = null; } else if (index == -1 && __AutoComplete[id]['highlighted'] == 0) { __AutoComplete[id]['dropdown'].childNodes[0].className = 'autocomplete_item'; __AutoComplete[id]['highlighted'] = __AutoComplete[id]['dropdown'].childNodes.length; } // Nothing highlighted at the moment if (__AutoComplete[id]['highlighted'] == null) { __AutoComplete[id]['dropdown'].childNodes[0].className = 'autocomplete_item_highlighted'; __AutoComplete[id]['highlighted'] = 0; } else { if (__AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']]) { __AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']].className = 'autocomplete_item'; } var newIndex = __AutoComplete[id]['highlighted'] + index; if (__AutoComplete[id]['dropdown'].childNodes[newIndex]) { __AutoComplete[id]['dropdown'].childNodes[newIndex].className = 'autocomplete_item_highlighted'; __AutoComplete[id]['highlighted'] = newIndex; } } } /** * Sets the input to a given value * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_SetValue(id) { __AutoComplete[id]['element'].value = __AutoComplete[id]['dropdown'].childNodes[__AutoComplete[id]['highlighted']].innerHTML; } /** * Checks if the dropdown needs scrolling * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_ScrollCheck(id) { // Scroll down, or wrapping around from scroll up if (__AutoComplete[id]['highlighted'] > __AutoComplete[id]['lastItemShowing']) { __AutoComplete[id]['firstItemShowing'] = __AutoComplete[id]['highlighted'] - (__AutoComplete[id]['maxitems'] - 1); __AutoComplete[id]['lastItemShowing'] = __AutoComplete[id]['highlighted']; } // Scroll up, or wrapping around from scroll down if (__AutoComplete[id]['highlighted'] < __AutoComplete[id]['firstItemShowing']) { __AutoComplete[id]['firstItemShowing'] = __AutoComplete[id]['highlighted']; __AutoComplete[id]['lastItemShowing'] = __AutoComplete[id]['highlighted'] + (__AutoComplete[id]['maxitems'] - 1); } __AutoComplete[id]['dropdown'].scrollTop = __AutoComplete[id]['firstItemShowing'] * 15; } /** * Function which handles the keypress event * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_KeyDown(id) { // Mozilla if (arguments[1] != null) { event = arguments[1]; } var keyCode = event.keyCode; switch (keyCode) { // Return/Enter case 13: if (__AutoComplete[id]['highlighted'] != null) { AutoComplete_SetValue(id); AutoComplete_HideDropdown(id); } event.returnValue = false; event.cancelBubble = true; break; // Escape case 27: AutoComplete_HideDropdown(id); event.returnValue = false; event.cancelBubble = true; break; // Up arrow case 38: if (!__AutoComplete[id]['isVisible']) { AutoComplete_ShowDropdown(id); } AutoComplete_Highlight(id, -1); AutoComplete_ScrollCheck(id, -1); return false; break; // Tab case 9: if (__AutoComplete[id]['isVisible']) { AutoComplete_HideDropdown(id); } return; // Down arrow case 40: if (!__AutoComplete[id]['isVisible']) { AutoComplete_ShowDropdown(id); } AutoComplete_Highlight(id, 1); AutoComplete_ScrollCheck(id, 1); return false; break; } } /** * Function which handles the keyup event * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_KeyUp(id) { // Mozilla if (arguments[1] != null) { event = arguments[1]; } var keyCode = event.keyCode; switch (keyCode) { case 13: event.returnValue = false; event.cancelBubble = true; break; case 27: AutoComplete_HideDropdown(id); event.returnValue = false; event.cancelBubble = true; break; case 38: case 40: return false; break; default: AutoComplete_ShowDropdown(id); break; } } /** * Returns whether the dropdown is visible * * @param string id The form elements id. Used to identify the correct dropdown. */ function AutoComplete_isVisible(id) { return __AutoComplete[id]['dropdown'].style.visibility == 'visible'; }
这是在网上下载的别人成熟的js文件