效果图:
- >
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
- <META HTTP-EQUIV="Cache-Control" CONTENT="no-cache">
- <META HTTP-EQUIV="Expires" CONTENT="0">
- <title>AutoComplete DEMOtitle>
- <style type="text/css">
- /*****************************************************************************/
- /* reset css */
- /*****************************************************************************/
- html,body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td {
- margin: 0;
- padding: 0;
- }
- img,body,html {
- border: 0;
- }
- address,caption,cite,code,dfn,em,th,var {
- font-style: normal;
- font-weight: normal;
- }
- ol,ul {
- list-style: none;
- }
- caption,th {
- text-align: left;
- }
- h1,h2,h3,h4,h5,h6 {
- font-size: 100%;
- }
- h1 {
- font-size: 18px;
- }
- h2 {
- font-size: 16px;
- }
- h3 {
- font-size: 14px;
- }
- q:before,q:after {
- content: '';
- }
- sup {
- vertical-align: text-top;
- }
- sub {
- vertical-align: text-bottom;
- }
- input,button,textarea,select {
- font-family: inherit;
- font-size: inherit;
- font-weight: inherit;
- }
- input,button,textarea,select {
- *font-size: 100%;
- }
- select,input,button,textarea {
- font: 100% tahoma, helvetica, arial, sans-serif;
- }
- table {
- font-size: inherit;
- font: 100%;
- }
- pre,code,kbd,samp,tt {
- font-family: 'courier new', courier, monospace;
- }
- small {
- font-size: 100%;
- }
- a {
- color: #028ef0;
- text-decoration: none;
- }
- a:hover {
- color: #f60;
- text-decoration: underline;
- }
- abbr,acronym {
- border-bottom: 1px dotted;
- cursor: help;
- }
- ins {
- text-decoration: none;
- }
- del {
- text-decoration: line-through;
- }
- hr {
- color: #d1d7dc;
- background-color: #d1d7dc;
- border: none;
- height: 1px;
- }
- /* 让浏览器默认也显示垂直滚动条,防止因滚动条引起的闪烁 */
- html {
- overflow-y: scroll;
- }
- body {
- font: 12px/ 1.5 Tahoma, Arial, '宋体', sans-serif;
- background-color: #fff;
- }
- .clearfix:after {
- visibility: hidden;
- display: block;
- font-size: 0;
- content: " ";
- clear: both;
- height: 0;
- }
- .clearfix{
- *zoom:1;
- }
- /*****************************************************************************/
- /* autocompelete css */
- /*****************************************************************************/
- .k-autocomplete-txt{
- outline: none;
- padding: 0px;
- background: none;
- }
- .k-autocomplete-wrapper{
- position:absolute;
- z-index: 9999;
- }
- .k-autocomplete-wrapper li{
- padding:0px;
- margin:0px;
- display: block;
- padding:2px 5px;
- font-size: 12px;
- height:18px;
- line-height: 18px;
- cursor: default;
- }
- .k-autocomplete-key{
- }
- .k-autocomplete-val{
- display: block;
- float: right;
- color:green;
- }
- .k-autocomplete-wrapper li.sel{
- background: #227AFF;
- color:#fff;
- }
- .k-autocomplete-wrapper li.sel .k-autocomplete-val{
- color:#fff;
- }
- .k-autocomplete-tip{
- position: absolute;
- z-index: -1;
- text-indent: 4px;
- color:#ccc;
- }
- /*****************************************************************************/
- /* other css */
- /*****************************************************************************/
- .txt{
- width:400px;
- margin-left: 200px;
- margin-top: 100px;
- text-indent: 2px;
- height:20px;
- border: 1px solid #ccc;
- line-height: 20px;
- }
- .btn{
- width:100px;
- height:24px;
- }
- style>
- head>
- <body>
- <input type="text" id="demo" value="" class='txt'/><input type="button" class='btn' value="搜索"/>
- <script src="http://a.tbcdn.cn/s/kissy/1.2.0/kissy.js">script>
- <script type="text/javascript" src='js/kissy-autocomplete.js'>
- /**
- * AutoComplete V0.1
- * @author huxiaoqi
- */
- (function(S){
- var $ = S.all,
- Event = S.Event,
- IO = S.IO,
- UA = S.UA;
- /**
- * TODO 定义全局变量
- * @param $WRAPPER 容器对象
- * @param PREFIX 组件前缀
- * @param WRAPPER_CLS Wrapper类名
- * @param WRAPPER_TPL Wrapper模板
- * @param TXT_CLS 文本框类名
- * @param TIP_CLS 提示框类名
- * @param $TIP_TPL 提示框模板对象
- * @param CONFIG 默认配置
- * @param KEY_MAP 按钮配置
- * @returns AutoComplete
- */
- S.add("AutoComplete",function(){
- var $WRAPPER,PREFIX = "k-autocomplete-",
- WRAPPER_CLS = PREFIX+"wrapper";
- WRAPPER_TPL = "
+WRAPPER_CLS+">ul>",
- TXT_CLS = PREFIX+"txt",
- TIP_CLS = PREFIX+"tip",
- $TIP_TPL = $("<div class="+TIP_CLS+">div>"),
- KEY_CLS = PREFIX+"key",
- VAL_CLS = PREFIX+"val";
- //定义初始配置
- CONFIG = {
- tip:"input some thing",
- url:"",
- type:"get",
- target:"",
- triggerLenth:2,
- itemSize:5,
- autoSubmit:true
- },
- //定义按键
- KEY_MAP = {
- ENTER:13,
- UP:38,
- DOWN:40,
- LEFT:37,
- RIGHT:39,
- BACKSPACE:8,
- SPACE:32
- };
- function AutoComplete(cfg){
- var self = this;
- if(!(self instanceof AutoComplete)){ //确保this指向AutoComplete实例
- return new AutoComplete();
- }
- self.version = "0.1";
- //配置合并
- self.config = S.mix(CONFIG,cfg);
- //获取渲染对象
- self.target = typeof self.config.target === "string" ? $(self.config.target) : self.config.target;
- //初始化
- self._init();
- //获取wrapper 全局
- $WRAPPER = self._render();
- //绑定事件
- self._bindEvent();
- }
- //将属性放入prototype
- S.augment(AutoComplete,{
- /**
- * TODO 初始化 tip 提示
- */
- _init:function(){
- var self = this,
- target = self.target,
- position = target.offset(),
- lineHeight;
- target.addClass(TXT_CLS).val("");
- //IE 3px bug
- lineHeight = UA.shell === "ie" ? target.height()+3+"px" : target.height()+"px";
- $TIP_TPL.html(self.config.tip)
- .css({
- 'left':position.left,
- 'top':position.top,
- 'height':target.height(),
- 'width':target.width(),
- 'line-height':lineHeight
- })
- .insertBefore(target);
- },
- /**
- * TODO 渲染提示框
- * @returns NodeList
- */
- _render:function(){
- var self = this,
- target = self.target,
- position = target.offset();
- //将wrapper放入页面
- $(WRAPPER_TPL).width(target.width())
- .css({
- "left":position.left,
- "top":position.top+target.height()
- })
- .insertBefore(target);
- return $("."+WRAPPER_CLS);
- },
- /**
- * TODO 绑定事件
- * @returns null
- */
- _bindEvent:function(){
- var self = this,$curItem,curIndex = -1;
- //给文本框绑定事件
- Event.on(self.target,"focus blur keyup",function(e){
- var eeevtType = e.type,
- keyCode = e.keyCode;
- self.toggleTipHandler(e);
- //触发弹出层事件
- Event.fire($WRAPPER,"keyup",e);
- if(self.target.val() === "" || evtType === "blur"){
- self.clear();
- }
- });
- //绑定弹出层事件
- Event.on($WRAPPER,"keyup",function(e){
- var eeevtType = e.type,
- keyCode = e.keyCode,
- eeevtTarget = e.target,
- triggerLenth = self.config.triggerLenth;
- if(evtType == "keyup" && self.target.val().length >= triggerLenth){
- if(self.isAlphaKey(keyCode) || self.isNumberKey(keyCode) || keyCode == KEY_MAP.BACKSPACE || keyCode == KEY_MAP.SPACE){
- self.autoCompleteHandler(e);
- }else if(self.isDirectionKey(e.keyCode)){
- !self.isNotNull() ? self.autoCompleteHandler(e) : null;
- //判定为方向键
- var $items = $WRAPPER.children(),
- size = $items.length;
- //获取当前选中索引
- curIndex = self.getSelectedItem();
- if(keyCode == KEY_MAP.DOWN){
- curIndexcurIndexcurIndex = curIndex >= size-1 ?0 : curIndex+1;
- }else if(keyCode == KEY_MAP.UP){
- curIndexcurIndexcurIndex = curIndex <= 0 ? size-1 : curIndex-1;
- }
- $curItem = self.selectItem($items[curIndex]);
- //回车选中当前选项
- $curItem.all('span')[0]?self.target.val($curItem.all('span')[0].innerHTML):self.target.val($curItem.text());
- }else if(keyCode == KEY_MAP.ENTER && $curItem){
- //清空内容
- self.clear();
- }
- }
- });
- },
- /**
- * TODO 返回数据后绑定mouseenter mousedown事件
- * @returns null
- */
- _bindItemEvent:function(){
- var self = this;
- return function(){
- Event.on($WRAPPER.children(),"mouseenter mousedown",function(e){
- var eeevtType = e.type,
- eeevtTarget = e.target;
- $(evtTarget).addClass('sel').siblings().removeClass('sel');
- if(evtType == "mousedown"){
- $(evtTarget).all('span')[0]?self.target.val($(evtTarget).all('span')[0].innerHTML):self.target.val($(evtTarget).text());
- self.clear();
- }
- });
- };
- },
- /**
- * TODO 处理提示文本
- * 仅通过color属性toggle
- * @returns null
- */
- toggleTipHandler:function(e){
- var self = this,
- target = self.target,
- eeevtType = e.type;
- if(evtType == "focus"){
- $TIP_TPL.css({"color":"#fff"});
- }
- else if(evtType == "blur" && self.target.val() == ""){
- $TIP_TPL.css({"color":"#ccc"});
- }
- },
- /**
- * TODO 处理获取的数据 remote||local
- * @returns null
- */
- autoCompleteHandler:function(e){
- var self = this,
- config = self.config,
- data = config.data;
- url = config.url,
- type = config.type,
- itemSize = config.itemSize;
- //若url不为空 则默认为 remote数据 否则为local数据
- if(url != ""){
- IO({
- url:url,
- type:type,
- data:{itemSize:itemSize,queryData:self.target.val()},
- success:function(data){
- self.createDom(data,self._bindItemEvent());
- }
- });
- }else{
- self.createDom(data,self._bindItemEvent());
- }
- },
- /**
- * TODO 获取自动生成的dom内容
- * @param data,callback
- * @returns null
- */
- createDom:function(data,callback){
- var self = this,
- queryTxt = self.target.val(),
- html = "";
- if(data){
- data = typeof data === "string"? eval("("+data+")"):data;
- if(queryTxt !="" && data.items){
- S.each(data.items,function(item){
- if(typeof item === "object" && item.key && item.val){
- html += "<li><span class="+KEY_CLS+">"+item.key+"span><span class="+VAL_CLS+">"+item.val+"span>li>";
- }else{
- html += "<li>"+item+"li>";
- }
- });
- }
- if(html != ""){
- $WRAPPER.html(html).css({"border":"1px solid #ccc","border-top":"none"});
- callback();
- }else{
- this.clear();
- }
- }
- },
- /**
- * TODO 方向键控制选中的内容
- * @returns Node
- */
- selectItem:function(item){
- $(item).addClass('sel').siblings().removeClass('sel');
- return $(item);
- },
- /**
- * TODO 获取当前选中的内容
- * @returns int
- */
- getSelectedItem:function(){
- var self = this,
- $items = $WRAPPER.children(),
- index = -1;
- S.each($items,function(item,i){
- if(item.className == "sel"){
- iiindex = i;
- }
- });
- return index;
- },
- /**
- * TODO 判断是否为方向键
- * @param keyCode
- * @returns boolean
- */
- isDirectionKey:function(keyCode){
- var keyMap = KEY_MAP;
- if(keyCode == keyMap.UP || keyCode == keyMap.DOWN || keyCode == keyMap.LEFT || keyCode == keyMap.RIGHT){
- return true;
- }
- return false;
- },
- /**
- * TODO 判断是否为字母键
- * @param keyCode
- * @returns boolean
- */
- isAlphaKey:function(keyCode){
- return keyCode >= 65 && keyCode <=90 ? true:false;
- },
- /**
- * TODO 判断是否为数字键
- * @param keyCode
- * @returns boolean
- */
- isNumberKey:function(keyCode){
- return (keyCode >= 48 && keyCode <= 57) || (keyCode >= 96 && keyCode <= 105) ? true:false;
- },
- clear:function(){
- $WRAPPER.html("").css({"border":"none"});
- },
- /**
- * TODO 判断提示是否为空
- * @returns boolean
- */
- isNotNull:function(){
- return $WRAPPER.html() != "";
- }
- });
- return AutoComplete;
- });
- })(KISSY);
- script>
- <script type="text/javascript">
- (function(S){
- S.use("AutoComplete",function(S,AutoComplete){
- var auto = new AutoComplete({
- tip:"请输入内容",
- url:"",
- target:"#demo",
- triggerLenth:1,
- /**
- * items 可为 {key:"",val:""}的形式 也可为 string
- */
- data:{
- items:[
- {key:"aaaa",val:"约1000条记录"},
- {key:'试试看',val:"约50条记录"},
- {key:'java',val:"约2000条记录"},
- {key:'这个是中文',val:"约1300条记录"},
- {key:'javascript',val:"约200条记录"},
- {key:'kissy',val:"约11200条记录"},
- {key:'jquery',val:"约1000条记录"},
- {key:'java开发指南',val:"约1200条记录"},
- {key:'java文档',val:"约100条记录"},
- {key:'1234',val:"约400条记录"},
- "这个是string"
- ]}
- });
- });
- })(KISSY);
- script>
- body>
- html>