博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于prototype的输入自动提示autocomplete
阅读量:6787 次
发布时间:2019-06-26

本文共 10363 字,大约阅读时间需要 34 分钟。

对老外的加了修改,对中文的支持和条数的显示

原作者地址: http://www.devbridge.com/projects/autocomplete/

 

效果:

 autocomplete.jsView Code

 
var
 Autocomplete 
=
 
function
(el, options){
  
this
.el 
=
 $(el);
  
this
.id 
=
 
this
.el.identify();
  
this
.el.setAttribute(
'
autocomplete
'
,
'
off
'
);
  
this
.suggestions 
=
 [];
  
this
.data 
=
 [];
  
this
.badQueries 
=
 [];
  
this
.selectedIndex 
=
 
-
1
;
  
this
.currentValue 
=
 
this
.el.value;
  
this
.intervalId 
=
 
0
;
  
this
.cachedResponse 
=
 [];
  
this
.instanceId 
=
 
null
;
  
this
.onChangeInterval 
=
 
null
;
  
this
.ignoreValueChange 
=
 
false
;
  
this
.serviceUrl 
=
 options.serviceUrl;
  
this
.numbers 
=
 [];
//
条数
  
this
.options 
=
 {
    autoSubmit:
false
,
    minChars:
1
,
    maxHeight:
300
,
    deferRequestBy:
0
,
    width:
0
,
    showNumber:
true
//
是否显示条数
    container:
null
  };
  
if
(options){ Object.extend(
this
.options, options); }
  
if
(Autocomplete.isDomLoaded){
    
this
.initialize();
  }
else
{
    Event.observe(document, 
'
dom:loaded
'
this
.initialize.bind(
this
), 
false
);
  }
};
Autocomplete.instances 
=
 [];
Autocomplete.isDomLoaded 
=
 
false
;
Autocomplete.getInstance 
=
 
function
(id){
  
var
 instances 
=
 Autocomplete.instances;
  
var
 i 
=
 instances.length;
  
while
(i
--
){ 
if
(instances[i].id 
===
 id){ 
return
 instances[i]; }}
};
Autocomplete.highlight 
=
 
function
(value, re){
  
return
 value.replace(re, 
function
(match){ 
return
 
'
<strong>
'
 
+
 match 
+
 
'
<\/strong>
'
 });
};
Autocomplete.prototype 
=
 {
  killerFn: 
null
,
  initialize: 
function
() {
    
var
 me 
=
 
this
;
    
this
.killerFn 
=
 
function
(e) {
      
if
 (
!
$(Event.element(e)).up(
'
.autocomplete
'
)) {
        me.killSuggestions();
        me.disableKillerFn();
      }
    } .bindAsEventListener(
this
);
    
if
 (
!
this
.options.width) { 
this
.options.width 
=
 
this
.el.getWidth(); }
    
var
 div 
=
 
new
 Element(
'
div
'
, { style: 
'
position:absolute;
'
 });
    div.update(
'
<div class="autocomplete-w1"><div class="autocomplete-w2"><div class="autocomplete" id="Autocomplete_
'
 
+
 
this
.id 
+
 
'
" style="display:none; width:
'
 
+
 
this
.options.width 
+
 
'
px;"></div></div></div>
'
);
    
this
.options.container 
=
 $(
this
.options.container);
    
if
 (
this
.options.container) {
      
this
.options.container.appendChild(div);
      
this
.fixPosition 
=
 
function
() { };
    } 
else
 {
      document.body.appendChild(div);
    }
    
this
.mainContainerId 
=
 div.identify();
    
this
.container 
=
 $(
'
Autocomplete_
'
 
+
 
this
.id);
    
this
.fixPosition();
    
    Event.observe(
this
.el, window.opera 
?
 
'
keypress
'
:
'
keydown
'
this
.onKeyPress.bind(
this
));
    Event.observe(
this
.el, 
'
keyup
'
this
.onKeyUp.bind(
this
));
    Event.observe(
this
.el, 
'
blur
'
this
.enableKillerFn.bind(
this
));
    Event.observe(
this
.el, 
'
focus
'
this
.fixPosition.bind(
this
));
    
this
.container.setStyle({ maxHeight: 
this
.options.maxHeight 
+
 
'
px
'
 });
    
this
.instanceId 
=
 Autocomplete.instances.push(
this
-
 
1
;
  },
  fixPosition: 
function
() {
    
var
 offset 
=
 
this
.el.cumulativeOffset();
    $(
this
.mainContainerId).setStyle({ top: (offset.top 
+
 
this
.el.getHeight()) 
+
 
'
px
'
, left: offset.left 
+
 
'
px
'
 });
  },
  enableKillerFn: 
function
() {
    Event.observe(document.body, 
'
click
'
this
.killerFn);
  },
  disableKillerFn: 
function
() {
    Event.stopObserving(document.body, 
'
click
'
this
.killerFn);
  },
  killSuggestions: 
function
() {
    
this
.stopKillSuggestions();
    
this
.intervalId 
=
 window.setInterval(
function
() { 
this
.hide(); 
this
.stopKillSuggestions(); } .bind(
this
), 
300
);
  },
  stopKillSuggestions: 
function
() {
    window.clearInterval(
this
.intervalId);
  },
  onKeyPress: 
function
(e) {
    
if
 (
!
this
.enabled) { 
return
; }
    
switch
 (e.keyCode) {
      
case
 Event.KEY_ESC:
        
this
.el.value 
=
 
this
.currentValue;
        
this
.hide();
        
break
;
      
case
 Event.KEY_TAB:
      
case
 Event.KEY_RETURN:
        
if
 (
this
.selectedIndex 
===
 
-
1
) {
          
this
.hide();
          
return
;
        }
        
this
.select(
this
.selectedIndex);
        
if
 (e.keyCode 
===
 Event.KEY_TAB) { 
return
; }
        
break
;
      
case
 Event.KEY_UP:
        
this
.moveUp();
        
break
;
      
case
 Event.KEY_DOWN:
        
this
.moveDown();
        
break
;
      
default
:
        
return
;
    }
    Event.stop(e);
  },
  onKeyUp: 
function
(e) {
    
switch
 (e.keyCode) {
      
case
 Event.KEY_UP:
      
case
 Event.KEY_DOWN:
        
return
;
    }
    clearInterval(
this
.onChangeInterval);
    
if
 (
this
.currentValue 
!==
 
this
.el.value) {
      
if
 (
this
.options.deferRequestBy 
>
 
0
) {
        
//
 Defer lookup in case when value changes very quickly:
        
this
.onChangeInterval 
=
 setInterval((
function
() {
          
this
.onValueChange();
        }).bind(
this
), 
this
.options.deferRequestBy);
      } 
else
 {
        
this
.onValueChange();
      }
    }
  },
  onValueChange: 
function
() {
    clearInterval(
this
.onChangeInterval);
    
this
.currentValue 
=
 
this
.el.value;
    
this
.selectedIndex 
=
 
-
1
;
    
if
 (
this
.ignoreValueChange) {
      
this
.ignoreValueChange 
=
 
false
;
      
return
;
    }
    
if
 (
this
.currentValue 
===
 
''
 
||
 
this
.currentValue.length 
<
 
this
.options.minChars) {
      
this
.hide();
    } 
else
 {
      
this
.getSuggestions();
    }
  },
  getSuggestions: 
function
() {
    
var
 cr 
=
 
this
.cachedResponse[
this
.currentValue];
    
if
 (cr 
&&
 Object.isArray(cr.suggestions)) {
      
this
.suggestions 
=
 cr.suggestions;
      
this
.data 
=
 cr.data;
      
this
.numbers 
=
 cr.numbers;
      
this
.suggest();
    } 
else
 
if
 (
!
this
.isBadQuery(
this
.currentValue)) {
      
new
 Ajax.Request(
this
.serviceUrl, {
        parameters: { query: 
this
.currentValue },
        onComplete: 
this
.processResponse.bind(
this
),
        method: 
'
get
'
      });
    }
  },
  isBadQuery: 
function
(q) {
    
var
 i 
=
 
this
.badQueries.length;
    
while
 (i
--
) {
      
if
 (q.indexOf(
this
.badQueries[i]) 
===
 
0
) { 
return
 
true
; }
    }
    
return
 
false
;
  },
  hide: 
function
() {
    
this
.enabled 
=
 
false
;
    
this
.selectedIndex 
=
 
-
1
;
    
this
.container.hide();
  },
  suggest: 
function
() {
    
if
 (
this
.suggestions.length 
===
 
0
) {
      
this
.hide();
      
return
;
    }
    
var
 content 
=
 [];
    
var
 re 
=
 
new
 RegExp(
'
\\b
'
 
+
 
this
.currentValue.match(
/
[\u4e00-\u9fa5a-zA-Z0-9]+
/
g).join(
'
|\\b
'
), 
'
gi
'
);
    
var
 numbersContent 
=
 
''
;
    
this
.suggestions.each(
function
(value, i) {
      
if
 (Object.isArray(
this
.numbers) 
&&
 
this
.options.showNumber){
        numbersContent 
=
 
'
 <span class="number">约
'
 
+
 
this
.numbers[i] 
+
 
'
条</span>
'
;
      }
      content.push((
this
.selectedIndex 
===
 i 
?
 
'
<div class="selected"
'
 : 
'
<div
'
), 
'
 title="
'
, value, 
'
" οnclick="Autocomplete.instances[
'
this
.instanceId, 
'
].select(
'
, i, 
'
);" οnmοuseοver="Autocomplete.instances[
'
this
.instanceId, 
'
].activate(
'
, i, 
'
);">
'
, Autocomplete.highlight(value, re), numbersContent, 
'
</div>
'
);
    } .bind(
this
));
    
this
.enabled 
=
 
true
;
    
this
.container.update(content.join(
''
)).show();
  },
  processResponse: 
function
(xhr) {
    
var
 response;
    
try
 {
      response 
=
 xhr.responseText.evalJSON();
      
if
 (
!
Object.isArray(response.data)) { response.data 
=
 []; }
    } 
catch
 (err) { 
return
; }
    
this
.cachedResponse[response.query] 
=
 response;
    
if
 (response.suggestions.length 
===
 
0
) { 
this
.badQueries.push(response.query); }
    
if
 (response.query 
===
 
this
.currentValue) {
      
this
.suggestions 
=
 response.suggestions;
      
this
.data 
=
 response.data;
      
this
.numbers 
=
 response.numbers;
      
this
.suggest(); 
    }
  },
  activate: 
function
(index) {
    
var
 divs 
=
 
this
.container.childNodes;
    
var
 activeItem;
    
//
 Clear previous selection:
    
if
 (
this
.selectedIndex 
!==
 
-
1
 
&&
 divs.length 
>
 
this
.selectedIndex) {
      divs[
this
.selectedIndex].className 
=
 
''
;
    }
    
this
.selectedIndex 
=
 index;
    
if
 (
this
.selectedIndex 
!==
 
-
1
 
&&
 divs.length 
>
 
this
.selectedIndex) {
      activeItem 
=
 divs[
this
.selectedIndex]
      activeItem.className 
=
 
'
selected
'
;
    }
    
return
 activeItem;
  },
  deactivate: 
function
(div, index) {
    div.className 
=
 
''
;
    
if
 (
this
.selectedIndex 
===
 index) { 
this
.selectedIndex 
=
 
-
1
; }
  },
  select: 
function
(i) {
    
var
 selectedValue 
=
 
this
.suggestions[i];
    
if
 (selectedValue) {
      
this
.el.value 
=
 selectedValue;
      
if
 (
this
.options.autoSubmit 
&&
 
this
.el.form) {
        
this
.el.form.submit();
      }
      
this
.ignoreValueChange 
=
 
true
;
      
this
.hide();
      
this
.onSelect(i);
    }
  },
  moveUp: 
function
() {
    
if
 (
this
.selectedIndex 
===
 
-
1
) { 
return
; }
    
if
 (
this
.selectedIndex 
===
 
0
) {
      
this
.container.childNodes[
0
].className 
=
 
''
;
      
this
.selectedIndex 
=
 
-
1
;
      
this
.el.value 
=
 
this
.currentValue;
      
return
;
    }
    
this
.adjustScroll(
this
.selectedIndex 
-
 
1
);
  },
  moveDown: 
function
() {
    
if
 (
this
.selectedIndex 
===
 (
this
.suggestions.length 
-
 
1
)) { 
return
; }
    
this
.adjustScroll(
this
.selectedIndex 
+
 
1
);
  },
  adjustScroll: 
function
(i) {
    
var
 container 
=
 
this
.container;
    
var
 activeItem 
=
 
this
.activate(i);
    
var
 offsetTop 
=
 activeItem.offsetTop;
    
var
 upperBound 
=
 container.scrollTop;
    
var
 lowerBound 
=
 upperBound 
+
 
this
.options.maxHeight 
-
 
25
;
    
if
 (offsetTop 
<
 upperBound) {
      container.scrollTop 
=
 offsetTop;
    } 
else
 
if
 (offsetTop 
>
 lowerBound) {
      container.scrollTop 
=
 offsetTop 
-
 
this
.options.maxHeight 
+
 
25
;
    }
    
this
.el.value 
=
 
this
.suggestions[i];
  },
  onSelect: 
function
(i) {
    (
this
.options.onSelect 
||
 Prototype.emptyFunction)(
this
.suggestions[i], 
this
.data[i]);
  }
};
Event.observe(document, 
'
dom:loaded
'
function
(){ Autocomplete.isDomLoaded 
=
 
true
; }, 
false

 

使用:Event.observe(window, 'load'function() {

    
function
 onAutocompleteSelect(value, data){
            
//
..
    }
    
var
 rand 
=
 
new
 Date().getTime();
    
var
 url 
=
 
'
data.js?r=
'
 
+
 rand;
    
new
 Autocomplete(
'
txtEmployeeNum
'
, { 
        serviceUrl: url, 
        width: 
300
,  
//
可选
        onSelect: onAutocompleteSelect, 
//
可选
        showNumber: 
true
 
//
显示条数
        
//
container: 'ac_container'  //可选
    });
});
<
input type
=
"
text
"
 name
=
"
q
"
 id
=
"
txtEmployeeNum
"
 
/
>
<!--
 
<
div id
=
"
ac_container
"
><
/
div>  -->  

 

data.js 有后台控制,产生json格式数据,如下:

 

//
{query:'z',suggestions:['z','z1','z2','z3']}

//{query:'q',suggestions:['q','q1','q2','q3'],numbers:[99,88,77,66]}

{query:'',suggestions:['','去1','去12','去123'],numbers:[99,88,77,66]}

 

弹出提示层的原型:View Code

 
<
div 
class
="autocomplete-w1"
>
  
<
div 
class
="autocomplete-w2"
>
    
<
div 
style
="width:299px;"
 id
="Autocomplete_query"
 class
="autocomplete"
>
      
<
div 
class
="selected"
><
strong
>
Li
</
strong
>
thuania
<
span 
class
="number"
>
约88个服务
</
span
></
div
>
    
</
div
>
  
</
div
>
</
div

 

 css控制样式自己控制:View Code

 
.autocomplete-w1 
{
 background
:
url(img/shadow.png) no-repeat bottom right
;
 position
:
absolute
;
 top
:
4px
;
 left
:
3px
;
 
/*
 IE6 fix: 
*/
 _background
:
none
;
 _top
:
1px
;
 
}
.autocomplete 
{
 width
:
300px
;
 border
:
1px solid #999
;
 background
:
#FFF
;
 cursor
:
default
;
 text-align
:
left
;
 max-height
:
350px
;
 overflow
:
auto
;
 margin
:
-6px 6px 6px -6px
;
 
/*
 IE specific: 
*/
 _height
:
350px
;
  _margin
:
0px 6px 6px 0
;
 overflow-x
:
hidden
;
 
}
.autocomplete .selected 
{
 background
:
#F0F0F0
;
 
}
.autocomplete div 
{
 padding
:
2px 5px
;
 white-space
:
nowrap
;
 
}
.autocomplete strong 
{
 font-weight
:
normal
;
 color
:
#3399FF
;
 
}
.autocomplete .number 
{
 font-weight
:
normal
;
 color
:
red
;
 

转载于:https://www.cnblogs.com/chthp/archive/2011/07/07/2100269.html

你可能感兴趣的文章
oscache.properties文件配置
查看>>
新建索引的一些原则
查看>>
redis发布了集群版3.0.0 beta
查看>>
使用Gradle在嵌入式Web容器Jetty中运行Web应用
查看>>
100-98
查看>>
Innodb中的事务隔离级别和锁的关系
查看>>
算法:请找出数组中的某个数,它的左侧数字相加之和等于右边。
查看>>
vi / vim文档编辑器画图详解
查看>>
Oracle基本语句实例代码介绍
查看>>
excel表数据导入到mysql数据库中(自己做的练习保留)
查看>>
bash 函数使用,实现模块化编程
查看>>
LVS实现负载均衡
查看>>
LAMP架构下安装Discuz!论坛
查看>>
shell
查看>>
正则表达式
查看>>
我的友情链接
查看>>
spring MVC的第一次记录
查看>>
js获取 X-X-X N 天后 是 X年X月X日
查看>>
我的友情链接
查看>>
神奇的504 Bad Gateway Timeout
查看>>