仿Gmail中输入多个收件人的Autocomplete组件

完全对比着Gmail的那个输入框来实现功能的,赶紧抢
输入时按,或<Enter>或<Tab>即可自动完成

使用示例
<!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>
	<title>waiting tip</title>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">     
	<script src="autoComplete.js"></script>
	<script>
	function bodyload(){
		var friends = ["james","john", "robert", "michael","juan"];
		var mailTo = document.getElementById("mailTo");
		var panel = document.getElementById("friendlist");
		var autoInput = new AutoInput(mailTo,panel,friends);
	}
	window.onload = bodyload;
	</script>
<body>
<input id="mailTo" type="text" style="width:300px" />
<select id="friendlist" multiple="true" style="width:300px;display:none;" ></select>
</body>
</html>

运行效果

源码
/**
 * 输入自动完成,类GMail中发送到输入框
 * @param {HTML Element} inputControl
 * @param {HTML Element} displayPanel
 * @param {Array} queryData
 */

function AutoInput(inputControl,displayPanel,queryData){
    var Browser = {
        IE:     !!(window.attachEvent && !window.opera),
        Opera:  !!window.opera,
        WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
        Gecko:  navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1,
        MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
    }
    
    var stopEvent = function(event){
        if(Browser.IE){
            try{
                event.cancelBubble = true;
                event.returnValue = false;
            }
            catch(e){
                alert(e);
            }
        }else{
            try{
                event.preventDefault();
                event.stopPropagation(); 
            }
            catch(e){
                alert(e);
            }
        }
    }
	
    var strip = function(string) {
    	return string.replace(/^\s+/, '').replace(/\s+$/, '');
    }	
    
    var inputControl = inputControl; //输入控件(input text或text area)
    var displayPanel = displayPanel; //结果显示面板
    var data = queryData; //搜索数据源 
	
    var results = []; //搜索结果
    var lastSearchText = ""; //最后一次搜索的关键字
	
    var isLastPosition = function(){
        return true;
    }
	
    //是否存在搜索结果
    var hasResults = function (){
        return results.length > 0
    }
	
    //自动完成单词
    var autoComplete = function(){
        var _value = inputControl.value;
        var _searchText = _value;
        var _lastPos = _value.lastIndexOf(',');
        if(_lastPos!=-1){			
            inputControl.value = _value.substr(0, _lastPos + 1) + '"' +  getSelectedText() +  '"' +',';
        }else{
            inputControl.value = '"'+getSelectedText() + '"' + ',';
        }
        clearResults();
        inputControl.focus();
    }
	
    //使输入框得到焦点(在结果显示面板中键入字符时发生)
    var focusInputControl = function(keycode){
        var _char = String.fromCharCode(keycode).toLowerCase();
        inputControl.value += _char;
        clearResults();
        inputControl.focus();
    }	
	
    //获取选中的文本
    var getSelectedText = function (){
        return	displayPanel.options[displayPanel.selectedIndex].text;
    }
	
    //搜索数组--!!!在这里改搜索算法
    var searchArray = function(searchData,searchText){
        var _results = [];
        for(var i=0,l=searchData.length;i<l;i++){
            var regExp = new RegExp("^"+searchText,"i"); //i选项,忽略大小写
            if(searchData[i].match(regExp)){
                _results.push(searchData[i]);
            }
        }
        return _results;
    }	
	
    //获取要作为搜索关键字的部分
    var getSearchText = function(){
        var _value = inputControl.value;
        var _searchText = _value;
        var _pos = _value.lastIndexOf(',');
        if(_pos!=-1){
            _searchText = _value.substr(_pos+1);
        }
        return _searchText;
    }
	
    //搜索并处理结果
    var search = function (){
        //获取搜索关键字
        var _keyword = getSearchText();	
        if(strip(_keyword)==""){
            clearResults();
            return;
        }
		
        //搜索	
        if(hasResults() && _keyword.indexOf(lastSearchText)==0){
            results = searchArray(results,_keyword);
        }else{
            results = searchArray(data,_keyword);
        }
		
        lastSearchText = _keyword;
		
        //处理搜索结果
        if (hasResults()) {
            showResult(results);
        }
        else{
            clearResults();
        }
    }
    
    //获取某个html元素的绝对位置
    var GetAbsoluteLocation = function (element)
    {
        if ( arguments.length != 1 || element == null )
        {
            return null;
        }
        var offsetTop = element.offsetTop;
        var offsetLeft = element.offsetLeft;
        var offsetWidth = element.offsetWidth;
        var offsetHeight = element.offsetHeight;
        while( element = element.offsetParent )
        {
            offsetTop += element.offsetTop;
            offsetLeft += element.offsetLeft;
        }
        return { absoluteTop: offsetTop, absoluteLeft: offsetLeft,
            offsetWidth: offsetWidth, offsetHeight: offsetHeight };
    }
	
    //重设结果显示面板的位置
    var resetPositoin = function(){
        var position = GetAbsoluteLocation(inputControl);
        displayPanel.style.position = "absolute";
        displayPanel.style.top = position.absoluteTop + position.offsetHeight + 5 + 'px';
        displayPanel.style.left = position.absoluteLeft + 'px';		
    }
	
    //显示搜索结果,清空结果面板
    if (Browser.IE) {
        var showResult = function(searchResults){
            clearOptions();
            for (var i = 0; i < searchResults.length; i++) {
                var text = searchResults[i];
                displayPanel.options.add(new Option(text, text));
            }
            resetPositoin();
            displayPanel.style.display = "block";
            displayPanel.options[0].selected = true;
        }
        
        var clearOptions = function(){
            for(var i=0,l=displayPanel.options.length;i<l;i++){
                displayPanel.options.remove(0);
            }
        }

    }
    else {
        var showResult = function(searchResults){
            var _htmls = "<option>" + searchResults.join("</option><option>") + "</option>";
            displayPanel.innerHTML = _htmls;
            resetPositoin();
            displayPanel.style.display = "block";
            displayPanel.options[0].selected = true;
        }
        
        var clearOptions = function(){
            displayPanel.innerHTML = "";
        }
    }
	
    var clearResults = function(){
        clearOptions();
        displayPanel.style.display = "none";
        results = [];
    }	
	
    //处理显示面板keydown
    if (Browser.Opera) {
        var resultsPanel_keydown = function(event){
            if (!hasResults()) 
                return;
            var displayPanel = event.srcElement;
            var _key = event.keyCode;
            if (_key == 188 || _key == 13 || _key == 9) { // , enter tab
                autoComplete();
                stopEvent(event);
            }
            else 
                if (_key == 38) { //up
                    var index = displayPanel.selectedIndex + 0;
                    var newIndex = index - 1;
                    if (index > 0) {
                        displayPanel.options[index].selected = false;
                        displayPanel.options[newIndex].selected = true;
                    }
            }
            else 
                if (_key == 40) { //down
                    var index = displayPanel.selectedIndex + 0;
                    if (index < displayPanel.options.length - 1) {
                        var newIndex = index + 1;
                        displayPanel.options[index].selected = false;
                        displayPanel.options[newIndex].selected = true;
                    }
            }
            else {
                focusInputControl(_key);
            }
        }
    }
    else {
        var resultsPanel_keydown = function(event){
            if (!hasResults()) 
                return;
            var _key = event.keyCode;
            if (_key == 188 || _key == 13 || _key == 9) { // , enter tab
                autoComplete();
                stopEvent(event);
            }
            else 
                if (_key != 38 && _key != 40) {
                    focusInputControl(_key);
                }
        }
    }

    //处理显示面板按下tab键
    function resultsPanel_tabdown(event){
        var _key = event.keyCode;
        if (_key == 9) { //tab
            autoComplete();
            stopEvent(event); //opera未能停止事件
        }
    }
    
	//处理输入控件按下tab键
    function inputControl_tabdown(event){
        var _key = event.keyCode;
        if (_key == 9) { //tab
            if(hasResults()){
              autoComplete();
              stopEvent(event); //opera未能停止事件
            }
        }
    }    
	
    //处理输入控件keydown
    function inputControl_keydown(event){
        if(!isLastPosition())return
        var _key = event.keyCode;
        if(_key==188 || _key==13){ // 按下: 1:, 2:enter 时自动完成
            if (hasResults()) {
                stopEvent(event);
                if(_key==188){
                    var _value = inputControl.value;
                    inputControl.value = _value.substr(0,_value.length-1);
                }
                autoComplete();
            }
        }
        else if(_key==40) // 按下: down(向下箭头)时聚焦到面板显示框,如果存在搜索结果的话
        {
            if (hasResults()) {
                displayPanel.focus();
                if(displayPanel.options[1]){
                    displayPanel.options[0].selected = false;
                    displayPanel.options[1].selected = true;
                }
                stopEvent(event);
            }
        }
        else{ //按下: 其他键		
            search();
        }
    }	
	
    //绑定事件
    var addEventListener = function(element, type, handler,stopEvent){
        if (element.addEventListener) {
            if (stopEvent) {
                element.addEventListener(type, handler, true);
            }else{
                element.addEventListener(type, handler, false);
            }
        }
        else { //ie
            if (stopEvent) {
                element.attachEvent("on" + type, function(event){
                    handler(event);
                    event.cancelBubble = true;
                });
            }else{
                element.attachEvent("on" + type, handler);
            }
        }
    }
	
	
    addEventListener(inputControl, "keyup", inputControl_keydown);
    addEventListener(inputControl, "keydown", inputControl_tabdown);
    addEventListener(displayPanel, "keyup", resultsPanel_keydown);
    addEventListener(displayPanel, "click", autoComplete);	
    addEventListener(displayPanel, "keydown", resultsPanel_tabdown);
}

你可能感兴趣的:(Opera,IE,mobile,webkit,Gmail)