热烈祝贺台州朗动科技的站长论坛隆重上线!(2012-05-28)    热烈庆祝伟大的祖国60周年生日 点击进来我们一起为她祝福吧(2009-09-26)    站长论坛禁止发布广告,一经发现立即删除。谢谢各位合作!.(2009-08-08)    热烈祝贺台州网址导航全面升级,全新版本上线!希望各位一如既往地支持台州网址导航的发展.(2009-03-28)    台州站长论坛恭祝各位新年快乐,牛年行大运!(2009-01-24)    台州Link正式更名为台州网址导航,专业做以台州网址为主的网址导航!(2008-05-23)    热烈祝贺台州Link资讯改名为中国站长资讯!希望在以后日子里得到大家的大力支持和帮助!(2008-04-10)    热烈祝贺台州Link论坛改名为台州站长论坛!希望大家继续支持和鼓励!(2008-04-10)    台州站长论坛原[社会琐碎]版块更名为[生活百科]版块!(2007-09-05)    特此通知:新台州站长论坛的数据信息全部升级成功!">特此通知:新台州站长论坛的数据信息全部升级成功!(2007-09-01)    台州站长论坛对未通过验证的会员进行合理的清除,请您谅解(2007-08-30)    台州网址导航|上网导航诚邀世界各地的网站友情链接和友谊联盟,共同引领网站导航、前进!(2007-08-30)    禁止发广告之类的帖,已发现立即删除!(2007-08-30)    希望各位上传与下载有用资源和最新信息(2007-08-30)    热烈祝贺台州站长论坛全面升级成功,全新上线!(2007-08-30)    
便民网址导航,轻松网上冲浪。
台州维博网络专业开发网站门户平台系统
您当前的位置: 首页 » AJAX编程 » Google Suggest自动下拉完成功能

Google Suggest自动下拉完成功能

论坛链接
  • Google Suggest自动下拉完成功能
  • 发布时间:2009-05-09 12:53:00    浏览数:12431    发布者:superadmin    设置字体【   
JS代码文件共9K多,如果打乱格式应该可以压到6K左右吧。
本程序共三个计时器:输入框onblur后列表隐藏计时、用户按键计时、数据发送后等待结果计时。
— 因为没有任何参考,也没做任何调查,因此所设定的默认时间都是凭个人感觉,如:发送请求后延迟时间隐藏列表项,是在个人感觉保证列表没有闪动的前提下服务器能够返回数据的差不多时间 :)。

演示地址:http://www.hansir.cn/tem/sample/suggest_test.html

调用:
后台数据以 [['关键字符','估计数量'], ['关键字符','估计数量'], ...] 格式输出。
页面onload后调用(因为有body.appendChild方法)
var mySuggest = new hansir.TextSuggest();
mySuggest.add_suggest(inp, url, method, defer, defer2);
除了前两项必填,后三项都是可选的
inp :输入框ID名。
url :ajax请求的后台服务器页面地址。
method :发送方试 get或post,默认post。
defer :按键计时,即用户输入字符多久后请求服务器,默认不计时,用户输入字符后立即发送。
defer2 :服务器返回结果计时,即服务器发送请求后多长时间没有返回数据,列表自动隐藏,默认200ms。
测试说明:
1、数据库存放的是临时数据。
2、可以输入“中华人民共和国”,“中”,”蓝色“ 测试。
3、可以输入一些其他的自定义数据,提交存到表里,然后就可以用刚刚提交的数据测试。
4、我的服务器网速慢,可能有个别卡的现象。
5、迟延:用户输入字符多久后请求服务器,照顾输入快的用户 :)
— 如果服务器速度够快可以考虑迟延,如果慢就无所谓了,反正是一个请求完成才会进行下一个 :)

已知缺陷:
1、下拉提示框位置问题:因为是以BODY为参考,所以位置会随body大小改变(下拉列表显示时拖动窗口大小可看效果)。
— 解决方法:真正用时可以根据input的父元素定位(这样还可以省些资源,即不毕每次显示下拉框都计算位置)。
2、用五笔输入法在FF下输入完成后上下方向键不好使要切换一下输入法才可以,拼音则正常。
— 解决方法:google也有同样问题,所以。。。 :)。

suggest.php

<?php

header('Content-Type:text/html;charset=utf-8');

require('../../admin/include/db_conf.php');

if($_POST['add']){

$keyword = trim($_POST['keyword']);

if(empty($keyword)){

header("LOCATION: suggest.html");

exit;

}

$db = db_connect();

$db->query("set names 'gb2312'");

$sql = "select*from suggest where keyword = '$keyword'";

if($db->query($sql)->num_rows>0){

header("LOCATION: suggest.html");

exit;

}

$num = rand(15, 2008);

$sql = "insert into suggest values(NULL, '$keyword', $num)";

$db->query($sql);

$db = NULL;

header("LOCATION: suggest.html");

exit;

}

$keyword = $_POST['keyword'];

if(empty($keyword)){

echo 'null';

exit;

}

$db = db_connect();

$db->query("set names 'utf8'");

$sql = "select *from suggest where keyword REGEXP '^$keyword' order by id desc limit 0, 15";

$result = $db->query($sql);

if($result->num_rows<1){

echo 'null';

exit;

}

$arr = array();

while($rows=$result->fetch_object()){

$keyword = $rows->keyword;

$arr[]="['$keyword', '$rows->num ".iconv('gb2312','utf-8','结果')."']";

}

$arr = '['.implode(',',$arr).']';

echo $arr;

?>


复制代码


suggest表: CREATE TABLE `suggest` (

`id` int(10) unsigned NOT NULL auto_increment,

`keyword` varchar(50) NOT NULL,

`num` int(10) unsigned NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=MyISAM DEFAULT CHARSET=gb2312 AUTO_INCREMENT=59 ;


复制代码
JS代码: /*

****************************

*** http://www.hansir.cn ***

****************************

*/

String.prototype.ltrim = function(){

return this.replace(/^s*(.+?)$/,'$1');

}

//这里引用prototype的五个方法

function $(){return document.getElementById(arguments[0]);}

Object.extend = function(destination, source){

for(property in source) destination[property] = source[property];

return destination;

}

function $A(iterable) {

var results = [];

for (var i = 0; i < iterable.length; i++)results.push(iterable);

return results;

}

Function.prototype.bindAsEventListener = function(object) {

var __method = this;

return function(event) {

return __method.call(object, event || window.event);

}

}

Function.prototype.bind = function() {

var __method = this, args = $A(arguments), object = args.shift();

return function() {

return __method.apply(object, args.concat($A(arguments)));

}

}

var hansir = {

url: 'http://www.hansir.cn'

}

hansir.AjAx = function(){this.initialize.apply(this, arguments);}

hansir.AjAx.prototype = {

initialize: function(complete, method, url){

this.complete = complete;

this.method = method || 'post';

this.url = url;

if (this.method == 'get') this.url += (this.url.match(/?/) ? '&' : '?');

},

xmlHttp: function(){

var xmlHttp;

if(window.XMLHttpRequest) xmlHttp = new XMLHttpRequest();

else if(window.ActiveXObject)

try{

xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');

}catch(errr){

xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');

}

return xmlHttp;

},

request: function(parameters){

var xmlHttp = this.xmlHttp();

var send_val = null;

this.method=='get' ? this.url += parameters : send_val = parameters;

xmlHttp.open(this.method, this.url, true);

xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');

xmlHttp.onreadystatechange = this.ready_handler.bind(this, xmlHttp);

xmlHttp.send(send_val);

},

ready_handler: function(xmlHttp){

if(xmlHttp.readyState == 4){

if(this.success(xmlHttp)){

this.complete.load_data(xmlHttp);

}

}

},

success: function(xmlHttp){return xmlHttp.status == 0 || xmlHttp.status >= 200 && xmlHttp.status < 300}

}

hansir.TextSuggest = function(){this.initialize.apply(this, arguments);}

hansir.TextSuggest.prototype = {

initialize: function(){},

add_suggest: function(inp, url, method, defer, defer2){

var inp = $(inp);

inp.defer = defer || null;

inp.defer2 = defer2 || 200;

var sw = inp.offsetWidth, sh = inp.offsetHeight;

inp.suggest_list = this.create_list(sw, sh);

inp.suggest_list.par = inp;

inp.xmlHttp = new hansir.AjAx(inp.suggest_list, method, url);

Object.extend(inp, {

requesting : false,

last_result : true,

previous_value : null,

last_value : null,

kt : null,

rt : null,

load_event: function(){

if(this.addEventListener){

this.addEventListener('input', this.keyup_handler.bindAsEventListener(this),false);

}else if(this.attachEvent){

this.attachEvent('onkeyup', this.keyup_handler.bindAsEventListener(this));

}

},

keyup_handler:function(e){

var intKey;

window.event ? intKey = event.keyCode : intKey = e.which;

if(intKey == 38 || intKey == 40 || intKey == 13 || intKey == 37) return;

if(this.requesting) return;

var val = this.value.ltrim();

this.last_value = val;

if(val == this.previous_value) return;

if(val==''){

this.previous_value = '';

this.last_value='';

this.suggest_list.hidden();

this.suggest_list.clear_data();

return;

}

if(new RegExp('^'+this.last_result,'i').test(val)) return;

this.last_result = true;

this.previous_value = val;

if(this.kt) clearTimeout(this.kt);

this.defer?this.kt = setTimeout(this.send_request.bind(this), this.defer):this.send_request();

},

onblur: function(){

setTimeout(this.suggest_list.hidden.bind(this.suggest_list), 100);

},

onkeydown: function(e){ // 上下、回车键事件

if(!this.suggest_list.rows.length) return;

var intKey;

window.event ? intKey = event.keyCode : intKey = e.which;

switch(intKey){

case 38:

if(this.suggest_list.style.visibility=='hidden'){

this.suggest_list.visible();

return;

}

var val = this.suggest_list.select_index(1);

val?this.value=val : this.value = this.last_value;

break;

case 40:

if(this.suggest_list.style.visibility=='hidden'){

this.suggest_list.visible();

return;

}

var val=this.suggest_list.select_index(0);

val?this.value=val : this.value = this.last_value;

break;

case 13:

if(this.suggest_list.cur_tr!=-1){

this.suggest_list.hidden();

break;

}

case 39:

this.suggest_list.hidden();

this.keyup_handler('o');

}

},

send_request: function(){ // 请求数据

this.requesting = true;

var val = this.value;

var parameters = 'keyword=' + val.ltrim();

this.xmlHttp.request(parameters);

this.start_hidden_time();

},

start_hidden_time: function(){

if(this.rt) clearTimeout(this.rt);

this.rt = setTimeout(this.list_hidden.bind(this), this.defer2);

},

list_hidden: function(){

if(this.requesting) this.suggest_list.hidden();

}

});

inp.load_event();

},

create_list: function(w, h){ //创建列表

var table = document.createElement('table');

table.cellSpacing = 0;

document.body.appendChild(table);

table.className = 'tab_suggest';

table.style.width = w + 'px';

table.parh = h-1;



Object.extend(table,{

cur_tr: -1,

set_pos: function(){ // 下垃框位置

var x=0, y=0, inp = this.par;

while(inp != null){x += inp.offsetLeft;y += inp.offsetTop;inp = inp.offsetParent;}

inp = null;

table.style.left = x + 'px';

table.style.top = y+this.parh+ 'px';

},

add: function(str, num){

var n=0;

this.rows.length ? n=this.rows.length : n = 0;

var tr = this.insertRow(n);

var th = document.createElement('th');

var td = document.createElement('td');

th.innerHTML = str, td.innerHTML = num;

tr.appendChild(th), tr.appendChild(td);

tr.num = this.rows.length-1;

tr.par = this;

tr.onmouseover = function(){

var par = this.par;

if(par.cur_tr!=-1 && par.cur_tr!=this.num){

par.rows[par.cur_tr].className='';

this.className = 'cur';

par.cur_tr = this.num;

}else{

this.className = 'cur';

par.cur_tr = this.num;

}

}

tr.onclick = function(){

var par = this.par.par;

par.value = this.cells[0].innerHTML;

}

tr = null, th = null, td = null;

},

load_data: function(xmlHttp){ // 加载列表

var inp = this.par;

if(inp.previous_value != inp.value){

inp.requesting = false;

this.clear_data();

inp.keyup_handler('o');

return;

}

var arr = xmlHttp.responseText;

if(arr.ltrim() == 'null'){

inp.last_result = inp.value;

inp.requesting = false;

inp.suggest_list.hidden();

this.clear_data();

return;

}

var cur_data = eval(arr);

this.clear_data();

for(var i=0; i<cur_data.length; i++)this.add(cur_data[0],cur_data[1]);

this.cur_tr = -1;

this.visible();

inp.requesting = false;

},

clear_data: function(){while(this.rows.length)this.deleteRow(this.rows[0])}, // 清空列表

select_index: function(n){ // 移动选项

if(n){

if(this.cur_tr==0){

this.rows[0].className = '';

this.cur_tr = -1;

return false;

}else{

this.cur_tr==-1?this.cur_tr=this.rows.length : this.rows[this.cur_tr].className = '';

this.cur_tr = this.cur_tr-1;

this.rows[this.cur_tr].className = 'cur';

return this.rows[this.cur_tr].cells[0].innerHTML;

}

}else{

if(this.cur_tr == (this.rows.length-1)){

this.rows[this.cur_tr].className= '';

this.cur_tr = -1;

return false;

}else{

if(this.cur_tr!=-1)this.rows[this.cur_tr].className = '';

this.cur_tr = this.cur_tr+1;

this.rows[this.cur_tr].className = 'cur';

return this.rows[this.cur_tr].cells[0].innerHTML;

}

}

},

hidden: function(){this.style.visibility = 'hidden';}, // 隐

visible: function(){this.set_pos(); this.style.visibility = 'visible';} // 显

});

return table;

}

}


复制代码HTML代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

<style>

*{font: 12px '宋体'}

.tab_suggest{border:1px solid #333; background:#fff; position:absolute; z-index:101; visibility: hidden;}

.tab_suggest th, .tab_suggest td{font:12px '宋体'; font-weight:normal; height:17px; text-align:left; line-height:17px; padding:2px 3px; white-space:nowrap; cursor: default;}

.tab_suggest td{color:#008000; text-align:right;}

.tab_suggest tr.cur{background:#36c; color:#fff}

.tab_suggest tr.cur td{color:#fff}

</style>

<title>无标题文档</title>

<script type="text/javascript" src="js/suggest.js"></script>

<script type="text/javascript">

window.onload=function(){

var mySuggest = new hansir.TextSuggest();

mySuggest.add_suggest('textSuggest', 'suggest.php', 'post');

mySuggest.add_suggest('textSuggest2', 'suggest.php', 'post', 100);

$('textSuggest').focus();

}

</script>

</head>

<body>

<br /><br />

<form action="suggest.php" method="post"><input type="hidden" name="add" value="add" />

没有迟延:<input type="text" id="textSuggest" name="keyword" style="width:300px;" autocomplete="off" /> <input type="submit" value="提 交" />

</form>

<br /><br /><br />

<form action="suggest.php" method="post"><input type="hidden" name="add" value="add" />

迟延100ms:<input type="text" id="textSuggest2" name="keyword" style="width:300px;" autocomplete="off" /> <input type="submit" value="提 交" />

</form>

</body>

</html>

复制代码


代码发布完毕
再看一下演示:http://www.hansir.cn/tem/sample/suggest_test.html

来源:http://bbs.phpchina.com/viewthread.php?tid=85197
      我发现一个问题是用get的时候。不太正常。那this.url累加了.我稍改了一下

这样也可以
...
var url = this.url //用局部变量
this.method=='get' ? url += parameters : send_val = parameters;
xmlHttp.open(this.method, url, true);
...
      谢谢。站长 。不过。我发现一个问题是用get的时候。不太正常。那this.url累加了.

我稍改了一下

request: function(parameters){
var xmlHttp = this.xmlHttp();
var send_val = null;
var oldurl=this.url;
this.method=='get' ? this.url += parameters : send_val = parameters;
xmlHttp.open(this.method, this.url, true);
xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded; charset=utf-8');
xmlHttp.onreadystatechange = this.ready_handler.bind(this, xmlHttp);
xmlHttp.send(send_val);
this.url=oldurl;
},
娱乐休闲专区A 影视预告B 音乐咖啡C 英语阶梯D 生活百科
网页编程专区E AMPZF HTMLG CSSH JSI ASPJ PHPK JSPL MySQLM AJAX
Linux技术区 N 系统管理O 服务器架设P 网络/硬件Q 编程序开发R 内核/嵌入
管理中心专区S 发布网址T 版主议事U 事务处理