高仿Google Suggest & Baidu Suggest
Posted on 2011-04-24 03:41 IceWee 閱讀(895) 評論(0) 編輯 收藏 所屬分類: Javascript經(jīng)常用谷歌百度的人會覺得他們自動提示下拉框很酷,而且用來起很方便。最近由于業(yè)務需求,我們也需要這樣的功能,網(wǎng)絡上搜刮了一下,但卻遇不到自己滿意的,于是決定取長補短,自己重構。由于平常很少寫類似控件或小工具的腳本,頂多寫點簡單的校驗腳本,所以寫了這個東東花費了我3天時間,當然3天也不全是一直撲到它身上,畢竟還有其他的工作,通過這次練習,自己對protype的熟悉又更近了一步。
這個版本自己還算滿意,可自定義的參數(shù)也開放了不少,主要是為用著方便著想嘛!沒有引用外部css類,而是全寫在腳本里,畢竟一個下拉提示框而已,并不是什么復雜的控件,也沒必要再單獨弄個css文件。
支持動態(tài)數(shù)據(jù)和靜態(tài)數(shù)據(jù)兩種方式,二者擇一,動態(tài)數(shù)據(jù)通過傳遞url和參數(shù)名,靜態(tài)數(shù)據(jù)通過傳遞數(shù)組,如果都傳遞則根據(jù)指定的是否是用動態(tài)數(shù)據(jù)參數(shù)來決定,如果沒有設置該參數(shù)則使用靜態(tài)數(shù)據(jù)。語言描述比較蒼白,代碼不多,但我這水平較淺,寫出來也費勁心思,呵呵,見笑!下面將HTML和JS代碼貼出:
下拉框外觀完全仿照谷歌樣式,包含邊框以及選中項的背景色。至于關鍵字樣式是仿照百度做的,谷歌關鍵字并沒有處理,大家可以打開谷歌和百度比較一下區(qū)別。
界面截圖:
Google.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>高仿Google Suggest & Baidu Suggest</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=GBK">
<script type="text/javascript" src="google.suggest.js"></script>
<script type="text/javascript">
<!--
var stringArray = new Array('java', 'JAVA游戲', 'java下載', 'javascript', 'javaeye', 'JAVA教程', 'java游戲下載', 'javascript教程', 'JAVA虛擬機', 'java正則表達式',
'77元廉租房', '77元特惠房', '77元大床房', '77元特惠大床房', '77元 7天', '77元特惠房預訂專區(qū)', '7天77元', '7天連鎖酒店77元',
'程序員', '程序員之家', '程序員考試', '程序員面試寶典', '程序員工資', '程序員的老婆是誰', '程序員論壇', '程序員修煉之道', '程序員雜志', '程序員招聘');
var objectArray = new Array();
var url = 'http://localhost:8080/google.suggest/servlet/getData?dataType=string'; // object or string
function initObjectArray() {
var id;
var name;
for (var i = 0; i < stringArray.length; ++i) {
id = i+1;
name = stringArray[i];
objectArray[i] = {id: id, name: name};
}
}
/**
* 回調(diào)函數(shù)
*
* @param {Object} id 當為字符串數(shù)組時,沒有值
* @param {Object} name
*/
function callback(id, name) {
document.getElementById('span_id_value').innerHTML = id;
document.getElementById('span_name_value').innerHTML = name;
}
window.onload = function() {
var input = document.getElementById('search');
input.blur(); // FireFox想聚焦必須先失去焦點
input.focus();
initObjectArray();
var data = {
input: input, // 必需參數(shù),可為輸入框ID或者輸入框?qū)ο?/span>
isDynamicData: false, // 可選參數(shù),默認false,不指定則自動判斷給定的數(shù)組參數(shù)與url,如果指定了動態(tài)或靜態(tài)數(shù)據(jù)方式則相應參數(shù)為必填,如指定了true,則url必須有效,指定了false,則數(shù)組不能為空
isObjectArray: false , // 可選參數(shù),默認false,使用的是否是對象數(shù)組或字符串數(shù)組,如果為對象數(shù)組要求屬性名為id和name,如果不指定則默認使用字符串數(shù)組
dataArray: stringArray, // 與url二選一,字符串數(shù)組,如果數(shù)組內(nèi)容不為空,同時又指定了url,則優(yōu)先使用數(shù)組
url: url, // 與dataArray二選一,ajax動態(tài)獲取數(shù)據(jù)的url
paramName: 'keywords', // 如果動態(tài)獲取數(shù)據(jù)為必需參數(shù),否則為可選參數(shù)
maxShowRows: 20, // 可選參數(shù),下拉框最大顯示行數(shù),超出該值的數(shù)據(jù)將不被顯示,默認值為30
showText: 'Google Search', // 可選參數(shù),默認顯示在輸入框中的文字,一般用于提示用戶,如果不指定則默認為“”
showTextOffsetLeft: 7, // 可選參數(shù) ,下拉列表文字內(nèi)容與左側(cè)的空白距離,默認值為0
showTextColor: '', // 可選參數(shù),默認顯示在輸入框中的文字的顏色,默認顏色為灰色,值為“#999999”
showTextFontStyle: '', // 可選參數(shù),默認顯示在輸入框中的文字的樣式, 默認樣式為斜體,值為“italic”
focusItemBgColor: '', // 可選參數(shù),鼠標停留(mouseover)下拉框的背景色,同Google,值為“#D5E2FF”
blurItemBgColor: '', // 可選參數(shù),鼠標劃過(mouseout)下拉框的背景色,默認顏色為白色,值為 “#FFFFFF”
suggestBorderColorLT: '', // 可選參數(shù), 下拉框左上的邊框顏色,同Google,值為“#A2BFF0”, LT 含義為 left和top
suggestBorderColorRB: '', // 可選參數(shù), 下拉框右下的邊框顏色,同Google,值為“#558BE3”, RB含義為right和bottom
itemFontSize: '', // 可選參數(shù),下拉框每一行的字體大小,如果未指定而且輸入框也沒設置字體大小則默認值為12pt,如果未指定,但輸入框指定了字體大小,則自動使用輸入框字體大小
isSortData: '', // 可選參數(shù),是否將數(shù)據(jù)進行排序顯示,默認不排序
callback: callback, // 可選參數(shù),回調(diào)函數(shù),參數(shù)為id和name,如果為對象數(shù)組ID有值,當用戶鼠標點擊或者按回車選擇后觸發(fā)該函數(shù)
isCaseSensitive: true // 可選參數(shù),是否忽略查詢英文字母大小寫,默認為false,即不忽略,靜態(tài)數(shù)據(jù)有效,動態(tài)數(shù)據(jù)該參數(shù)無效,而是由服務端處理邏輯決定
}
new googleSuggest(data).go();
}
//-->
</script>
<style type="text/css">
<!--
#search {
background: #FFFFFF;
border-width: 1px;
border-style: solid;
border-color: #CCCCCC #999999 #999999 #CCCCCC;
font-size: 14pt;
margin: 0px;
padding: 5px 8px 0px 3px;
color: #000000;
height: 30px;
}
.lsbb {
background: #eee;
border: solid 1px;
border-color: #ccc #999 #999 #ccc;
height: 30px;
display: inline-block;
}
.lsb {
background: url('nav_logo66.png') bottom;
border: none;
color: #000;
cursor: pointer;
height: 30px;
margin: 0;
outline: 0;
padding: 0 6px;
width: auto;
overflow: visible;
font: 15px arial, sans-serif;
vertical-align: top;
}
//-->
</style>
</HEAD>
<BODY style="margin: 0; background-color: #FFFFFF; color: #000000;">
<table cellSpacing="0" cellPadding="0" width="100%" height="24">
<tr>
<td>
id:[<span id="span_id_value" style="text-align: center; width: 20px;"></span>] name:[<span id="span_name_value" style="text-align: center; width: 150px;"></span>]
</td>
<td></td>
<td>
<DIV style="width: 100%; padding-top: 1px !important; text-align: right;">
<span style="font-style: italic; color: #0000CC; padding-right: 5px;">高仿Google Suggest & Baidu Suggest</span>
</DIV>
</td>
</tr>
</table>
<DIV style="position: absolute; right: 0px; width: 100%; top: 24px; height: 0; border-top: 1px solid #c9d7f1;"></DIV>
<CENTER>
<BR />
<DIV><IMG id="logo" title="Google" border="0" alt="Google" src="logo_cn.png" width="276" height="110"><BR /><BR /></DIV>
<TABLE cellSpacing="0" cellPadding="0">
<TR vAlign="top">
<TD align="center">
<INPUT id="search" title="Google 搜索" size="57" /><BR /><BR /><BR />
<SPAN class="ds">
<SPAN class="lsbb"><INPUT class="lsb" value="Google 搜索" type="button" /></SPAN>
</SPAN>
<SPAN class="ds">
<SPAN class="lsbb"><INPUT class="lsb" value=" 手氣不錯 " type="button" /></SPAN>
</SPAN>
</TD>
</TR>
</TABLE>
<DIV style="font-size: 83%; min-height: 3.5em;"><BR>
<DIV id="als"><FONT id="addlang" size="-1">請輸入以下關鍵字進行測試:java 77元 程序員</FONT><BR /><BR /></DIV>
</DIV>
<SPAN id="footer">
<CENTER id="fctr">
<DIV style="font-size: 10pt;">
<DIV style="margin: 19px auto; text-align: center;" id="fll">
<a style="display: inline-block; margin: 0 12px;" href="mailto:icewee@tom.com?subject=Google Suggest">聯(lián)系作者</a>
<a style="display: inline-block; margin: 0 12px;" href="http://icewee.cnblogs.com" target="_blank">作者博客</a>
</DIV>
</DIV>
<P style="color: rgb(118, 118, 118); font-size: 8pt;">© 2011 - <A href="javascript:void(0)">Icesoft</A></P>
</CENTER>
</SPAN>
</CENTER>
</BODY>
</HTML>
google.suggest.js 第一部分
/**
* This version of Software is free for using in non-commercial applications.
* For commercial use please contact icewee@tom.com to obtain license
* author: IceWee
* blog: http://icewee.cnblogs.com
* Date: 2011-04-25 0:58:54 (Mon, 25 Apri 2011)
*/
function googleSuggest(data) {
this.$settings = {
input: null,
url: null,
paramName: null,
dataArray: new Array(),
maxShowRows: 30,
showText: '',
showTextColor: '#999999',
showTextFontStyle: 'italic',
showTextOffsetLeft: 0,
focusItemBgColor: '#D5E2FF',
blurItemBgColor: '#FFFFFF',
suggestBorderColorLT: '#A2BFF0',
suggestBorderColorRB: '#558BE3',
isDynamicData: false,
itemFontSize: '12pt',
isSortData: true,
isObjectArray: false,
callback: null,
isCaseSensitive: false
}
this.$isIE = true;
this._copySettings(data);
this.$suggest = null; // suggest div
this.$focusItemIndex = -1;
this.$DOWN = '40'; // keyboard keyCode down
this.$UP = '38'; // keyboard keyCode up
this.$ENTER = '13'; // keyboard keyCode Enter
this.$xmlHttp = null; // ajax object
this.$HTTP_STATE_UNINITIALIZED = 0; // xmlHttpRequest object is not be initilaized
this.$HTTP_STATE_LOADING = 1;
this.$HTTP_STATE_LOADED = 2;
this.$HTTP_STATE_INTERACTIVING = 3;
this.$HTTP_STATE_COMPLETED = 4;
this.$HTTP_STATUS_OK = 200;
return this;
}
/**
* @desc: working now!
*/
googleSuggest.prototype.go = function() {
if (this._isCanGo()) {
this._initSuggest();
this._initInput();
} else {
alert('initialize failed!');
}
};
/**
* @desc: copy params that user specified
*
* @param {Object} data
*/
googleSuggest.prototype._copySettings = function(data) {
if (typeof(data.input) == 'string')
this.$settings.input = document.getElementById(data.input);
else
this.$settings.input = data.input;
if (data.isSortData && data.isSortData == true) {
this.$settings.isSortData = true;
} else {
this.$settings.isSortData = false;
}
if (data.isObjectArray && data.isObjectArray == true) {
this.$settings.isObjectArray = true;
} else {
this.$settings.isObjectArray = false;
}
if (data.isCaseSensitive && data.isCaseSensitive == true) {
this.$settings.isCaseSensitive = true;
} else {
this.$settings.isCaseSensitive = false;
}
if (data.isDynamicData && data.isDynamicData == true) { // dynamic data
this.$settings.isDynamicData = true;
if (this._isNotBlank(data.url))
this.$settings.url = data.url;
if (this._isNotBlank(data.paramName))
this.$settings.paramName = data.paramName;
} else {
this.$settings.isDynamicData = false;
if (data.dataArray && data.dataArray.constructor == Array && data.dataArray.length > 0) {
this.$settings.dataArray = data.dataArray;
this._sortArray(); // sort the array or not
}
}
if (this._isNotBlank(data.focusItemBgColor))
this.$settings.focusItemBgColor = data.focusItemBgColor;
if (this._isNotBlank(data.blurItemBgColor))
this.$settings.blurItemBgColor = data.blurItemBgColor;
if (this._isNotBlank(data.showText))
this.$settings.showText = this._trim(data.showText);
if (this._isNotBlank(data.showTextColor))
this.$settings.showTextColor = data.showTextColor;
if (this._isNotBlank(data.showTextFontStyle))
this.$settings.showTextFontStyle = data.showTextFontStyle;
if (this._isValidNum(data.maxShowRows))
this.$settings.maxShowRows = data.maxShowRows;
if (this._isValidNum(data.showTextOffsetLeft))
this.$settings.showTextOffsetLeft = data.showTextOffsetLeft;
if (this._isNotBlank(data.suggestBorderColorLT))
this.$settings.suggestBorderColorLT = data.suggestBorderColorLT;
if (this._isNotBlank(data.suggestBorderColorRB))
this.$settings.suggestBorderColorRB = data.suggestBorderColorRB;
if (this.$settings.input) {
if (this._isNotBlank(data.itemFontSize))
this.$settings.itemFontSize = data.itemFontSize;
else if (this._isNotBlank(this._getInput().style.fontSize))
this.$settings.itemFontSize = this._getInput().style.fontSize;
}
if (typeof(data.callback) == 'function'){
this.$settings.callback = data.callback;;
}else{
if (this._isNotBlank(data.callback))
this.$settings.callback = eval(data.callback);
}
this.$isIE = ((document.all) ? true : false) || navigator.userAgent.indexOf('MSIE') > 0;
};
/**
* @desc: validate important params, whether can run script
*
* @return true or false
*/
googleSuggest.prototype._isCanGo = function() {
if (!this._getInput()) // invalid input
return false;
if (this.$settings.isDynamicData) { // dynamic data
if (this._isBlank(this.$settings.url) || this._isBlank(this.$settings.paramName))
return false;
} else { // static data
if (this.$settings.dataArray.length == 0) {
return false;
} else {
// object array, formater eg:[{id: '1', name: 'java'}], only accept/process id and name property
if (this.$settings.isObjectArray) {
// here only validate the first element of array, so... I do not say whatever you know
if (!this.$settings.dataArray[0].id || !this.$settings.dataArray[0].name)
return false;
}
}
}
return true;
};
/**
* @dese: sort the data array
*/
googleSuggest.prototype._sortArray = function() {
if (this.$settings.isSortData) {
if (!this.$settings.isObjectArray) { // string array
this.$settings.dataArray.sort(function(a, b) { // sort the array
if (a.length > b.length)
return 1;
else if (a.length == b.length)
return a.localeCompare(b);
else
return -1;
});
} else { // object array
if (this.$settings.dataArray[0].id && this.$settings.dataArray[0].name) {
this.$settings.dataArray.sort(function(a, b) { // sort the array
if (a.name.length > b.name.length)
return 1;
else if (a.name.length == b.name.length)
return a.name.localeCompare(b.name);
else
return -1;
});
}
}
}
};
/**
* @desc: get current input
*
* @return current input object
*/
googleSuggest.prototype._getInput = function() {
return this.$settings.input;
};
/**
* @desc: force blur the input
*/
googleSuggest.prototype._forceBlurInput = function() {
this._getInput().blur();
};
/**
* @desc: initinalize the suggest
*/
googleSuggest.prototype._initSuggest = function() {
var input = this._getInput();
var left = this._getAbsolutePosition(input)[0];
var top = this._getAbsolutePosition(input)[1];
var width = this._getWidthAndHeight(input)[0];
var height = this._getWidthAndHeight(input)[1];
this.$suggest = document.createElement('div');
document.body.appendChild(this.$suggest);
this.$suggest.style.position = 'absolute';
this.$suggest.style.borderWidth = '1px';
this.$suggest.style.borderStyle = 'solid';
this.$suggest.style.borderLeftColor = this.$settings.suggestBorderColorLT;
this.$suggest.style.borderTopColor = this.$settings.suggestBorderColorLT;
this.$suggest.style.borderRightColor = this.$settings.suggestBorderColorRB;
this.$suggest.style.borderBottomColor = this.$settings.suggestBorderColorRB;
if (this.$isIE)
this.$suggest.style.width = width + 'px';
else
this.$suggest.style.width = width - 2 + 'px';
this.$suggest.style.left = left + 'px';
this.$suggest.style.top = top + height - 1 + 'px';
this.$suggest.style.display = 'none';
};
/**
* @desc: init input and bind mouse and keyboard event
*/
googleSuggest.prototype._initInput = function() {
var input = this._getInput();
input.suggest = this;
input.value = this.$settings.showText;
input.style.color = this.$settings.showTextColor;
input.style.fontStyle = this.$settings.showTextFontStyle;
input.onfocus = this._displaySuggest;
input.onblur = this._inputBlur;
input.onkeyup = this._catchKeyCode;
};
/**
* @desc: current object may be input or suggest
*/
googleSuggest.prototype._displaySuggest = function() {
var o;
if (this.$suggest) { // suggest
o = this;
} else {
o = this.suggest; // input
}
if (!o.$settings.isDynamicData) // static data
o._staticSuggest();
else
o._dynamicSuggest();
};
/**
* @desc: create suggest with the static data array
*/
googleSuggest.prototype._staticSuggest = function() {
this.$focusItemIndex = -1;
var inputVal = this._getInput().value;
inputVal = this._trim(inputVal);
if (this._isNotBlank(inputVal)) {
if (inputVal != this.$settings.showText) {
this._getInput().style.color = '#000000';
this._getInput().style.fontStyle = 'normal';
this.$suggest.innerHTML = '';
this._createSuggestItems(inputVal);
if (this.$suggest.children.length > 0)
this._showSuggest();
else
this._hideSuggest();
} else {
this._getInput().style.color = this.$settings.showTextColor;
this._getInput().style.fontStyle = this.$settings.showTextFontStyle;
this._getInput().value = '';
this._hideSuggest();
}
} else {
this._hideSuggest();
}
}
/**
* @desc: create suggest, with the url to get dynamic data array
*/
googleSuggest.prototype._dynamicSuggest = function() {
this.$focusItemIndex = -1;
var inputVal = this._getInput().value;
inputVal = this._trim(inputVal);
if (this._isNotBlank(inputVal) ) {
if (inputVal != this.$settings.showText) {
this._getInput().style.color = '#000000';
this._getInput().style.fontStyle = 'normal';
this.$suggest.innerHTML = '';
var url = this._constructUrl() + inputVal;
var xmlHttp = this._getAjax();
xmlHttp.suggest = this;
xmlHttp.onreadystatechange = function() {
try{
if (xmlHttp.readyState == this.suggest.$HTTP_STATE_COMPLETED) {
if (xmlHttp.status == this.suggest.$HTTP_STATUS_OK) {
var array = xmlHttp.responseText;
if (this.suggest._isNotBlank(array)) {
this.suggest.$settings.dataArray = eval(array);
this.suggest._sortArray(); // sort or not
var size = 0;
if (this.suggest.$settings.dataArray > this.suggest.$settings.maxShowRows + 1)
size = this.suggest.$settings.maxShowRows + 1;
else
size = this.suggest.$settings.dataArray.length;
var o, item;
if (this.suggest.$settings.isObjectArray) {
for (var i = 0; i < size; i++) {
o = this.suggest.$settings.dataArray[i];
if (typeof(o) == 'object') {
if (!o.id && !o.name) {
alert('Invalid format! The object must has id and name property, eg: [{id: 1, name: \'peter\'}, ...]');
this.suggest._forceBlurInput();
break;
} else {
item = this.suggest._createSuggestItem(o.name, inputVal);
this.suggest.$suggest.appendChild(item);
}
} else {
alert('Invalid format! Correct format is like this [{id: 1, name: \'peter\'}, {id: \'admin\', name: \'administrator\'}]');
this.suggest._forceBlurInput();
break;
}
}
} else { // string array
for (var i = 0; i < size; i++) {
o = this.suggest.$settings.dataArray[i];
if (typeof(o) == 'string') {
item = this.suggest._createSuggestItem(o, inputVal);
this.suggest.$suggest.appendChild(item);
} else {
alert('Invalid format! Correct format is like this [\'java\', \'javascript\', \'javaeye\']');
this.suggest._forceBlurInput();
break;
}
}
}
if (this.suggest.$suggest.children.length > 0)
this.suggest._showSuggest();
else
this.suggest._hideSuggest();
} else {
this.suggest._hideSuggest();
}
}
}
} catch (e) {alert(e);}
}
xmlHttp.open('GET', url, true);
xmlHttp.send(null);
} else {
this._getInput().style.color = this.$settings.showTextColor;
this._getInput().style.fontStyle = this.$settings.showTextFontStyle;
this._getInput().value = '';
this._hideSuggest();
}
} else {
this._hideSuggest();
}
}
google.suggest.js 第二部分
/**
* @desc: create the items show in the suggest, this method is used to static data, js fiter
*
* @param {Object} inputVal, input keywords
*/
googleSuggest.prototype._createSuggestItems = function(inputVal) {
var size = 0;
if (this.$settings.dataArray > this.$settings.maxShowRows + 1)
size = this.$settings.maxShowRows + 1;
else
size = this.$settings.dataArray.length;
var reg = this._getRegExps(inputVal);
var o, item;
if (this.$settings.isObjectArray) {
for (var i = 0; i < size; i++) {
o = this.$settings.dataArray[i];
if (typeof(o) == 'object') {
if (!o.id && !o.name) {
alert('Invalid format! The object must has id and name property, eg: [{id: 1, name: \'peter\'}, ...]');
this._forceBlurInput();
break;
} else {
item = this._createSuggestItem(o.name, inputVal);
this.$suggest.appendChild(item);
}
} else {
alert('Invalid format! Correct format is like this [{id: 1, name: \'peter\'}, {id: \'admin\', name: \'administrator\'}]');
this._forceBlurInput();
break;
}
}
} else { // string array
for (var i = 0; i < size; i++) {
o = this.$settings.dataArray[i];
if (typeof(o) == 'string') {
if (o.match(reg)) {
item = this._createSuggestItem(o, inputVal);
this.$suggest.appendChild(item);
}
} else {
alert('Invalid format! Correct format is like this [\'java\', \'javascript\', \'javaeye\']');
this._forceBlurInput();
break;
}
}
}
};
/**
* @desc: create a item that show in suggest
*
* @param {Object} value, one value of the data array
* @param {Object} inputVal, input keywords
* @return item
*/
googleSuggest.prototype._createSuggestItem = function(value, inputVal) {
var v = value.replace(inputVal, '<span style="font-weight: normal;">' + inputVal + '</span>');
var item = document.createElement('div');
item.innerHTML = v;
item.style.color = '#000000';
item.style.backgroundColor = this.$settings.blurItemBgColor;
item.style.fontWeight = 'bold';
item.style.fontSize = this.$settings.itemFontSize;
item.style.paddingLeft = this.$settings.showTextOffsetLeft + 'px';
item.onmouseover = this._focusItem;
item.onmouseout = this._blurItem;
item.onmousedown = this._returnSelectedItem;
item.suggest = this;
return item;
};
/**
* @desc: current object is suggest item(eg:<div>java</div>)
*/
googleSuggest.prototype._focusItem = function() {
this.style.backgroundColor = this.suggest.$settings.focusItemBgColor;
};
/**
* @desc: return a Regular Expressions used to match keywords
*
* @param {Object} value, string
* @return regexps
*/
googleSuggest.prototype._getRegExps = function(value) {
if (this.$settings.isCaseSensitive)
return new RegExp(value, 'i');
else
return new RegExp(value);
};
/**
* @desc: current object is suggest item(eg:<div>xxx</div>)
*/
googleSuggest.prototype._blurItem = function() {
this.style.backgroundColor = this.suggest.$settings.blurItemBgColor;
};
/**
* @desc: current object is suggest item(eg:<div>javascript</div>)
*/
googleSuggest.prototype._returnSelectedItem = function() {
var name = this.innerHTML;
var breg = new RegExp('<span style="font-weight: normal;">', 'i'); // <META content="IE=9" http-equiv="X-UA-Compatible">
var mreg = new RegExp('<span style="font-weight: normal">', 'i'); // common, must remove ';'
var ereg = new RegExp('</span>', 'i');
name = name.replace(breg, '');
name = name.replace(mreg, '');
name = name.replace(ereg, '');
this.suggest._getInput().value = name;
var id = this.suggest._getIdbyName(name);
if (this.suggest.$settings.callback) // callback function
this.suggest.$settings.callback(id, name);
this.suggest._forceBlurInput();
this.suggest._hideSuggest();
};
/**
* @desc: whether the suggest is hide
*
* @return true of false
*/
googleSuggest.prototype._isSuggestHide = function() {
return this.$suggest.style.display == 'none';
};
/**
* @desc: current object may be input or suggest, show the suggest
*/
googleSuggest.prototype._showSuggest = function() {
if (this.$suggest) // suggest
this.$suggest.style.display = 'block';
else // input
this.suggest.$suggest.style.display = 'block';
};
/**
* @desc: current object may be input or suggest, hide the suggest
*/
googleSuggest.prototype._hideSuggest = function() {
var o;
if (this.$suggest) { // suggest
o = this;
} else { // input
o = this.suggest;
}
o.$suggest.style.display = 'none';
};
/**
* @desc: current object is input, when the input is blur that should be do?
*/
googleSuggest.prototype._inputBlur = function() {
this.suggest._hideSuggest();
var inputVal = this.value;
if (this.suggest._isBlank(inputVal)) {
this.value = this.suggest.$settings.showText;
this.style.color = this.suggest.$settings.showTextColor;
this.style.fontStyle = this.suggest.$settings.showTextFontStyle;
}
};
/**
* @desc: current object is input, catch the keyboard event, judge to show or hide suggest
*/
googleSuggest.prototype._catchKeyCode = function() {
var keyCode = 0;
if (this.suggest.$isIE) {
var keyCode = event.keyCode;
if (keyCode == this.suggest.$DOWN || keyCode == this.suggest.$UP) { // down or up
var isUp = true;
if (keyCode == this.suggest.$DOWN) // down
isUp = false;
this.suggest._changeFocusItem(isUp);
} else if (keyCode == this.suggest.$ENTER) {
this.suggest._catchEnter();
} else {
this.suggest._displaySuggest();
}
} else {
this.suggest._displaySuggest();
}
};
/**
* @desc: used to catch enter event
*/
googleSuggest.prototype._catchEnter = function() {
var name = this._getInput().value;
var id = this._getIdbyName(name);
if (this.$settings.callback) // callback function
this.$settings.callback(id, name);
this._forceBlurInput();
this._hideSuggest();
}
/**
* @desc: change the focus item and change the input text's style that show in the suggest
*
* @param {Object} isUp, keyboard event, up or down
*/
googleSuggest.prototype._changeFocusItem = function(isUp) {
if (this._isSuggestHide()) {
this._showSuggest();
} else {
if (isUp)
this.$focusItemIndex--;
else
this.$focusItemIndex++;
}
var maxIndex = this.$suggest.children.length - 1;
if (this.$focusItemIndex < 0) {
this.$focusItemIndex = maxIndex;
}
if (this.$focusItemIndex > maxIndex) {
this.$focusItemIndex = 0;
}
var breg = new RegExp('<span style="font-weight: normal;">', 'i'); // <META content="IE=9" http-equiv="X-UA-Compatible">
var mreg = new RegExp('<span style="font-weight: normal">', 'i'); // common, must remove ';'
var ereg = new RegExp('</span>', 'i');
var text;
for (var i = 0; i <= maxIndex; i++) {
if (i == this.$focusItemIndex) {
text = this.$suggest.children[i].innerHTML;
text = text.replace(breg, '');
text = text.replace(mreg, '');
text = text.replace(ereg, '');
this._getInput().value = text;
this.$suggest.children[i].style.backgroundColor = this.$settings.focusItemBgColor;
} else {
this.$suggest.children[i].style.backgroundColor = this.$settings.blurItemBgColor;
}
}
};
/**
* @desc: get a html element's absolute position
*
* @param {Object} o, html element
* @return array, value 1 is x coordinate and value 2 is y coordinate
*/
googleSuggest.prototype._getAbsolutePosition = function(o) {
var array = new Array();
var top = 0, left = 0;
do {
top += o.offsetTop;
left += o.offsetLeft;
} while (o = o.offsetParent);
array[0] = left;
array[1] = top;
return array;
};
/**
* @desc: get a html element's width and height
*
* @param {Object} o, html element
* @return array that first value is width and second value is height
*/
googleSuggest.prototype._getWidthAndHeight = function(o) {
var array = new Array();
array[0] = o.offsetWidth;
array[1] = o.offsetHeight;
return array;
};
/**
* @desc: trim a string
*
* @param {Object} string
* @return string that remove the left space and right space, space(space and tab)
*/
googleSuggest.prototype._trim = function(string) {
return string.replace(/(^\s*)|(\s*$)/g, '');
};
/**
* @desc: validate a string is null or ''
*
* @param {Object} string
* @return true if is not '' or undefined, else false
*/
googleSuggest.prototype._isValidString = function(string) {
if (string && this._trim(string))
return true;
return false;
}
/**
* @desc: validate number
*
* @param {Object} num
* @return true if is valid number, else false
*/
googleSuggest.prototype._isValidNum = function(num) {
if (!isNaN(parseInt(num)))
return true;
return false;
}
/**
* @desc: get an ajax object
*
* @return ajax object, this.$xmlHttp or new XMLHttpRequest
*/
googleSuggest.prototype._getAjax = function() {
if (!this.$xmlHttp) {
this.$xmlHttp = this._getXMLHttpRequest();
}
if (this.$xmlHttp.readyState != this.$HTTP_STATE_COMPLETED) {
return this._getXMLHttpRequest();
}
return this.$xmlHttp;
};
/**
* @desc: create a XMLHttpRequest object
*
* @return a new XMLHttpRequest object
*/
googleSuggest.prototype._getXMLHttpRequest = function() {
var xmlHttp;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else if (window.ActiveXobject) {
try {
xmlHttp = new ActiveXobject('MSXML2XMLHTTP');
} catch (e){
try {
xmlHttp = new ActiveXobject('Microsoft.XMLHttp');
} catch (e){}
}
}
return xmlHttp;
}
/**
* @desc: construct the full url with the user specified url and param name
*
* @return full url
*/
googleSuggest.prototype._constructUrl = function() {
var url = this.$settings.url;
var paramName = this.$settings.paramName;
if (url.indexOf('?') == -1)
url += '?' + paramName + '=';
else
url += '&' + paramName + '=';
return url;
};
/**
* @desc: so... name must be unique, else will be wrong, see below you will be understand
*
* @param {Object} name, object array name
* @return object array id value
*/
googleSuggest.prototype._getIdbyName = function(name) {
var id = null;
var array = this.$settings.dataArray;
for (var i = 0; i < array.length; ++i) {
if (array[i].name == name)
return array[i].id;
}
return id;
}
/**
* blank means null/undefined/''/tab
*
* @param {Object} string
* @return true or false
*/
googleSuggest.prototype._isBlank = function(string) {
if (string == undefined) // null or un init
return true;
if (this._trim(string) == '')
return true;
return false;
}
/**
* not blank
*
* @param {Object} string
* @return true or false
*/
googleSuggest.prototype._isNotBlank = function(string) {
return !this._isBlank(string);
}
GetDataServlet.java
package bing;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Ajax獲取模擬數(shù)據(jù)處理類
*
* @author Bing
* @date 2011-4-22
*
*/
public class GetDataServlet extends HttpServlet {
private static final long serialVersionUID = -5467391979358615867L;
private String[] datas = { "JAVA", "JAVA游戲", "JAVA下載", "javascript",
"javaeye", "JAVA教程", "java游戲下載", "javascript教程", "JAVA虛擬機",
"JAVA正則表達式", "77元廉租房", "77元特惠房", "77元大床房", "77元特惠大床房", "77元 7天",
"77元特惠房預訂專區(qū)", "7天77元", "7天連鎖酒店77元", "程序員", "程序員之家", "程序員考試",
"程序員面試寶典", "程序員工資", "程序員的老婆是誰", "程序員論壇", "程序員修煉之道", "程序員雜志",
"程序員招聘" };
private List<Bean> beans = new ArrayList<Bean>();
public GetDataServlet() {
super();
initializeBeans();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=GBK");
response.setCharacterEncoding("GBK");
String dataType = request.getParameter("dataType");
String keywords = request.getParameter("keywords");
String dataString = "";
if ("object".equals(dataType)) {
dataString = getObjectArray(keywords);
}else {
dataString = getStringArray(keywords);
}
response.getWriter().print(dataString);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
* 字符串數(shù)組
*
* format: ['java', 'javascript', 'javaeye']
*
* @param keywords
* @return
*/
private String getStringArray(String keywords) {
System.out.println("keywords: [" + keywords + "]");
String stringArray = "";
if (keywords != null && !"".equals(keywords)) {
keywords = keywords.toLowerCase();
StringBuffer buffer = new StringBuffer();
for (String data : datas) {
data = data.toLowerCase();
if (data.indexOf(keywords) != -1)
buffer.append("'").append(data).append("'").append(", ");
}
stringArray = buffer.toString();
if (!"".equals(stringArray)) {
stringArray = stringArray.substring(0, stringArray.lastIndexOf(", "));
stringArray = "[" + stringArray + "]";
}
System.out.println("返回數(shù)據(jù)為字符串數(shù)組,內(nèi)容:" + stringArray);
}
return stringArray;
}
/**
* 對象數(shù)組(如果使用JSON就方便多了)
*
* format: [{id: '1', name: 'java'}, {id: '2', name: 'javascript'}]
*
* @param keywords
* @return
*/
private String getObjectArray(String keywords) {
keywords = keywords.toLowerCase();
StringBuffer buffer = new StringBuffer();
for (Bean bean : beans) {
String id = bean.getId();
String name = bean.getName();
String temp = bean.getName().toLowerCase();
if (temp.indexOf(keywords) != -1)
buffer.append("{").append("id: '").append(id).append("', name: '").append(name).append("'}, ");
}
String objectArray = buffer.toString();
if (!"".equals(objectArray)) {
objectArray = objectArray.substring(0, objectArray.lastIndexOf(", "));
objectArray = "[" + objectArray + "]";
}
System.out.println("返回數(shù)據(jù)為對象數(shù)組,內(nèi)容:" + objectArray);
return objectArray;
}
private void initializeBeans () {
for (int i = 0; i < datas.length; i++) {
beans.add(new Bean(String.valueOf(i), datas[i]));
}
}
}
Bean.java
package bing;
public class Bean {
private String id;
private String name;
public Bean() {
super();
}
public Bean(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<description>get Google suggest data</description>
<display-name>GetData</display-name>
<servlet-name>GetDataServlet</servlet-name>
<servlet-class>bing.GetDataServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetDataServlet</servlet-name>
<url-pattern>/servlet/getData</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>Google.html</welcome-file>
</welcome-file-list>
</web-app>
不滿意的地方是沒有弄好火狐的鍵盤事件,即上下鍵或者回車鍵,都不知道怎么捕捉,網(wǎng)上搜索了下,不過都不怎么好使,就放棄了。
當前默認是使用靜態(tài)數(shù)據(jù),如果部署到Tomcat中后,可將Google.html中的 isDynamicData: false 改為true即可,之后可以觀察Tomcat的控制臺輸出。
歡迎網(wǎng)友們多多交流!