|
Posted on 2011-04-24 03:41 IceWee 阅读(883) 评论(0) 编辑 收藏 所属分类: Javascript
经常用谷歌百度的人会觉得他们自动提示下拉框很酷,而且用来起很方便。最近由于业务需求,我们也需要这样的功能,网络上搜刮了一下,但却遇不到自己满意的,于是决定取长补短,自己重构。由于平常很少写类似控件或小工具的脚本,顶多写点简单的校验脚本,所以写了这个东东花费了我3天时间,当然3天也不全是一直扑到它身上,毕竟还有其他的工作,通过这次练习,自己对protype的熟悉又更近了一步。
这个版本自己还算满意,可自定义的参数也开放了不少,主要是为用着方便着想嘛!没有引用外部css类,而是全写在脚本里,毕竟一个下拉提示框而已,并不是什么复杂的控件,也没必要再单独弄个css文件。
支持动态数据和静态数据两种方式,二者择一,动态数据通过传递url和参数名,静态数据通过传递数组,如果都传递则根据指定的是否是用动态数据参数来决定,如果没有设置该参数则使用静态数据。语言描述比较苍白,代码不多,但我这水平较浅,写出来也费劲心思,呵呵,见笑!下面将HTML和JS代码贴出:
下拉框外观完全仿照谷歌样式,包含边框以及选中项的背景色。至于关键字样式是仿照百度做的,谷歌关键字并没有处理,大家可以打开谷歌和百度比较一下区别。
界面截图:
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元特惠房预订专区', '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}; } } /** * 回调函数 * * @param {Object} id 当为字符串数组时,没有值 * @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, // 必需参数,可为输入框ID或者输入框对象 isDynamicData: false, // 可选参数,默认false,不指定则自动判断给定的数组参数与url,如果指定了动态或静态数据方式则相应参数为必填,如指定了true,则url必须有效,指定了false,则数组不能为空 isObjectArray: false , // 可选参数,默认false,使用的是否是对象数组或字符串数组,如果为对象数组要求属性名为id和name,如果不指定则默认使用字符串数组 dataArray: stringArray, // 与url二选一,字符串数组,如果数组内容不为空,同时又指定了url,则优先使用数组 url: url, // 与dataArray二选一,ajax动态获取数据的url paramName: 'keywords', // 如果动态获取数据为必需参数,否则为可选参数 maxShowRows: 20, // 可选参数,下拉框最大显示行数,超出该值的数据将不被显示,默认值为30 showText: 'Google Search', // 可选参数,默认显示在输入框中的文字,一般用于提示用户,如果不指定则默认为“” showTextOffsetLeft: 7, // 可选参数 ,下拉列表文字内容与左侧的空白距离,默认值为0 showTextColor: '', // 可选参数,默认显示在输入框中的文字的颜色,默认颜色为灰色,值为“#999999” showTextFontStyle: '', // 可选参数,默认显示在输入框中的文字的样式, 默认样式为斜体,值为“italic” focusItemBgColor: '', // 可选参数,鼠标停留(mouseover)下拉框的背景色,同Google,值为“#D5E2FF” blurItemBgColor: '', // 可选参数,鼠标划过(mouseout)下拉框的背景色,默认颜色为白色,值为 “#FFFFFF” suggestBorderColorLT: '', // 可选参数, 下拉框左上的边框颜色,同Google,值为“#A2BFF0”, LT 含义为 left和top suggestBorderColorRB: '', // 可选参数, 下拉框右下的边框颜色,同Google,值为“#558BE3”, RB含义为right和bottom itemFontSize: '', // 可选参数,下拉框每一行的字体大小,如果未指定而且输入框也没设置字体大小则默认值为12pt,如果未指定,但输入框指定了字体大小,则自动使用输入框字体大小 isSortData: '', // 可选参数,是否将数据进行排序显示,默认不排序 callback: callback, // 可选参数,回调函数,参数为id和name,如果为对象数组ID有值,当用户鼠标点击或者按回车选择后触发该函数 isCaseSensitive: true // 可选参数,是否忽略查询英文字母大小写,默认为false,即不忽略,静态数据有效,动态数据该参数无效,而是由服务端处理逻辑决定 } 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">联系作者</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获取模拟数据处理类 * * @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元特惠房预订专区", "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); }
/** * 字符串数组 * * 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("返回数据为字符串数组,内容:" + stringArray); } return stringArray; } /** * 对象数组(如果使用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("返回数据为对象数组,内容:" + 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>
不满意的地方是没有弄好火狐的键盘事件,即上下键或者回车键,都不知道怎么捕捉,网上搜索了下,不过都不怎么好使,就放弃了。
当前默认是使用静态数据,如果部署到Tomcat中后,可将Google.html中的 isDynamicData: false 改为true即可,之后可以观察Tomcat的控制台输出。
欢迎网友们多多交流!
|