话说上个月客户提出需求,希望输入铃音编号时能够即时返回该编号对应的详细信息。顺带要求两条:一是页面无刷新、二是要显示在气球提示框里。接到case之后,本着能不改就不改、能少改就少改的原则,跟人家解释说:首先,这个tooltip(甲方:说中文。偶:就是您提到的气球提示框)一般来说是光标悬停在某个控件上才会显示的;其次,每次按键都会发送新的请求,会对服务器造成很大压力滴。。。
挂上电话,我在google中敲入关键字jquery tootip,耳边回荡着你的声音——“需求不变,周五之前完成”,按下回车:恩,jquery的插件果然怒多,试了几个,果然不出我之所料,只支持mousehover事件,而且可配置性不高。最后,我找到了BeautyTips(以下简称bt)。
根据BeautyTips项目主页 上的介绍:该插件高度可配置,并能被多种事件所触发。在线Demo 很有诚意,22个例子外加源码和讲解,基本涵盖了所有的功能。
回到本文的主题,对实际项目进行抽象后,我写了一个小demo,与官方demo 12 中的异步获取静态页面不同,我这里接收server生成的动态页面。
IDE我用的是netbeans 6.7,对jquery(应该说是所有的js类库)的支持相当好。将附件中的beautytips_demo.zip 解压后,netbeans打开该项目,按F6键运行,在“铃音编号”中随便输入点东西,弹出提示框,如图:
除了页面中引入的js文件外,项目中就两个jsp而已。一个index.jsp就是前台页面啦,再一个data.jsp生成并提供前台异步获取所需的动态内容。我们先来看index.jsp的核心部分:
$(document).ready(function () { jQuery.bt.defaults.ajaxCache = false; $("#ringindex").bt({ ajaxPath: "${pageContext.request.contextPath}/data.jsp", trigger: ["keypress", "blur"], spikeLength: 40, spikeGirth: 40, cornerRadius: 40, fill: "rgba(0, 0, 0, .8)", strokeWidth: 3, strokeStyle: "#CC0", cssStyles: {color: "#FFF", fontWeight: "bold"} }) });
- 第2行的jQuery.bt.defaults.ajaxCache是一个预设的全局变量,默认值是true,在这里为了避免ajax请求同一个url时从缓存中取值,我们把它置为false。从这一点可以看出bt作者还是很体贴的,有了这个参数我们就不用在url后面挂上一堆随机数了。需要指出的是,像ajaxCache这样全局变量的详细列表,都可以在jquery.bt.js(不要去看无注释压缩版的jquery.bt.min.js阿)文件的结尾部分查到。
- 第4行的ajaxPath所对应的data.jsp就是我们之前提到的数据源。
- 第5行的trigger表示keypress事件使tooltip显示,blur事件使其隐藏。
- 第6-12行定义tooltip的外观,从官方demo 6抄过来的。
下面我们来看看data.jsp的源码:
<%
Object[][] data = new Object [][] {
{ "630565", "相识非偶然", "谭咏麟", 200 },
{ "630566", "上街", "蔡依林", 200 },
{ "630567", "芥末不辣", "江美琪", 200 },
{ "630568", "没道理", "刘若英", 200 },
{ "630569", "一生所爱", "徐小凤", 200 },
{ "630571", "风的季节", "黎瑞恩", 200 },
{ "630572", "风中有朵雨做的云", "孟庭苇", 200 },
{ "630573", "秋天以后的故事", "侯湘婷", 200 },
{ "630575", "带我去寻找", "王啸坤", 200 },
{ "630576", "齐齐唱首歌", "许冠杰", 200 },
{ "630578", "明天话今天", "叶丽仪", 200 },
{ "630579", "迫我绝情", "张学友", 200 },
{ "630580", "走不掉", "张学友", 200 },
{ "630581", "旧情绵绵", "张学友", 200 },
{ "630582", "珍重", "谭咏麟", 200 },
{ "630583", "天使之恋", "黄莺莺", 200 },
{ "630585", "瞬间移动", "方力申", 200 },
{ "630586", "抵抗夜寒", "张学友", 200 },
{ "630587", "不像个大人", "张惠妹", 200 },
{ "630588", "解药", "陈奕迅", 200 }
};
java.util.Random random = new java.util.Random();
int index = random.nextInt(data.length);
StringBuffer result = new StringBuffer("<div id=\"content\">");
result.append("<h4>铃音编号:");
result.append(data[index][0]);
result.append("</h4><hr/><ul><li>铃音: ");
result.append(data[index][1]);
result.append("</li><li>歌手: ");
result.append(data[index][2]);
result.append("</li><li>价格: ");
result.append(data[index][3]);
result.append("</li></ul>");
result.append("</div>");
response.reset();
response.setContentType("text/html;charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write(result.toString());
%>
赫赫,大家都看出来了,我这个数据源完全是糊弄事儿,根本就无视来自客户端的输入,先定义了一堆Object二维数组,然后随机取一个向量中的各个字段,拼出一个div来写响应,这个div就是tooltip中要显示的内容,既包含了数据、也有结构、还有样式。根据bt作者的说法,严格的讲,这里使用的技术不是AJAX,而是AHAH(Asynchronous HTML and HTTP )。也有用户给作者留言,要求提供AJAX方式以方便使用handler,但被婉拒。