效果以下:javascript
廢話很少說,看代碼:css
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="UTF-8"> <title>下拉搜索</title> <script data-require="angular.js@1.2.25" data-semver="1.2.25" src="https://code.angularjs.org/1.2.25/angular.js"></script> <style type="text/css"> .wapper { width: 600px; height: 500px; background-color: #FFFFFF; padding: 30px; margin: 0 auto; } .select-wapper { margin: 0 auto; width: 200px; height: 30px; position: relative; } .select-wapper>input { width: 100%; height: 100%; border: 1px solid #CCCCCC; padding: 0 10px 0 0; box-sizing: border-box; border-radius: 4px; padding: 5px; -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075); box-shadow: inset 0 1px 1px rgba(0,0,0,.075); -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s; } .select-wapper>input:focus { border: 1px solid rgb(102,175,233); -webkit-box-shadow: inset 0 1px 1px rgba(102,175,233, .075); box-shadow: inset 0 1px 1px rgba(122,156,211, .075); outline: none; } .select-wapper:after { content: ''; width: 0; height: 0; border-top: 8px solid #77705d; border-right: 5px solid transparent; border-left: 5px solid transparent; display: inline; position: absolute; right: 8px; top: 11px; } .select-wapper .select-content-panel { width: 100%; height: auto; max-height: 300px; position: absolute; top: 100%; left: 0; border: 1px solid rgb(122,156,211); margin-top: 0; padding: 0; overflow-y: auto; box-sizing: border-box; background-color: white; } .select-wapper .select-content-panel li { display: block; list-style: none; padding: 2px 10px; font-size: 14px; border: 0 !important; } .select-wapper .select-content-panel li:hover { background-color: rgb(30, 144, 255); color: white !important; } .select-wapper .select-content-panel li:active { background-color: rgb(30, 144, 255); color: white !important; } .select-wapper .item-bg { background-color: rgb(30, 144, 255); color: white !important; } .select-wapper .hidden-cls { display: none; } </style> </head> <body ng-controller="mainCtrl"> <div class="wapper"> <div class="select-wapper"> <input type="text" ng-model="inValue_display" id="select-input-mark" placeholder="請選擇" input-search/> <ul class="select-content-panel hidden-cls" input-select> <li ng-repeat="item in dataList" ng-bind="item.name"></li> </ul> </div> </div> <script type="text/javascript"> angular.module('myApp', []) .controller('mainCtrl', ['$scope', function ($scope) { $scope.inValue = ''; $scope.inValue_display = ''; $scope.dataList = [{ name: '二哈1號' },{ name: '二哈2號' },{ name: '二哈3號' },{ name: '二哈4號' },{ name: '二哈5號' },{ name: '二哈6號' },{ name: '二哈7號' },{ name: '二哈8號' },{ name: '二哈9號' },{ name: '二哈10號' },{ name: '二哈11號' },{ name: '二哈12號' },{ name: '二哈13號' },{ name: '二哈14號' },{ name: '二哈15號' },{ name: '二哈16號' },{ name: '二哈17號' },{ name: '二哈18號' },{ name: '二哈19號' },{ name: '二哈20號' },{ name: '二哈21號' },{ name: '二哈22號' },{ name: '二哈23號' },{ name: '二哈24號' },{ name: '二哈25號' },{ name: '二哈26號' }] $scope.initList = $scope.dataList; $scope.$on('selectInput', function(evt, inputObj){ if('select-input-mark' == inputObj.inputId){ $scope.inValue = ''; $scope.inValue_display = inputObj.inputText; $scope.fuzzyQuery(); } }); $scope.fuzzyQuery = function(){ $scope.dataList = []; angular.forEach($scope.initList, function(item){ if(-1 != item.name.indexOf($scope.inValue_display)){ $scope.dataList.push(item); } }) } }]) .directive('inputSelect', function() { return { link: function(scope, element, attr) { element.on('click', function(evt) { evt.target.parentElement.previousElementSibling.value = evt.target.textContent; scope.inValue = evt.target.textContent; if(evt.target.parentElement.getElementsByClassName('item-bg').length){ angular.element(evt.target.parentElement.getElementsByClassName('item-bg')[0]).removeClass('item-bg'); } angular.element(evt.target).addClass('item-bg'); angular.element(evt.target.parentElement).addClass('hidden-cls'); return true; }); } }; }) .directive('inputSearch', function() { return { link: function(scope, element, attr) { var isFocus = true; var isOver = false; element.on('focus', function(){ angular.element(this.nextElementSibling).removeClass('hidden-cls'); }) element.on('keydown', function(evt){ if(!this.nextElementSibling.children.length){ return false; } if(isFocus){ var currentLi = this.parentElement.getElementsByClassName('item-bg')[0]; if(38 == evt.keyCode && currentLi && currentLi.previousElementSibling){//向上 var currentLi = this.parentElement.getElementsByClassName('item-bg')[0], liHeight = currentLi ? currentLi.clientHeight : '', offTop = liHeight; angular.element(currentLi).removeClass('item-bg'); angular.element(currentLi.previousElementSibling).addClass('item-bg'); for(var i = 0, len = this.nextElementSibling.children.length; i < len; i++){ if(this.nextElementSibling.children[i] == currentLi){ break; } offTop = offTop + liHeight; } offTop = Math.max(0, offTop - 2 * liHeight); if(this.nextElementSibling.scrollTop > offTop){ this.nextElementSibling.scrollTop = offTop; } }else if(40 == evt.keyCode){//向下 var currentLi = this.parentElement.getElementsByClassName('item-bg')[0], liHeight = currentLi ? currentLi.clientHeight : '', offTop = liHeight; if(!currentLi){ angular.element(this.nextElementSibling.firstElementChild).addClass('item-bg'); return true; } if(currentLi.nextElementSibling){ angular.element(currentLi).removeClass('item-bg'); angular.element(currentLi.nextElementSibling).addClass('item-bg'); } for(var i = 0, len = this.nextElementSibling.children.length; i < len; i++){ if(this.nextElementSibling.children[i] == currentLi){ break; } offTop = offTop + liHeight; } if(this.nextElementSibling.scrollTop > offTop){ return false; } if(this.nextElementSibling.clientHeight < offTop && this.nextElementSibling.scrollTop + this.nextElementSibling.clientHeight - liHeight < offTop){ this.nextElementSibling.scrollTop = offTop - this.nextElementSibling.clientHeight + liHeight; } }else if(13 == evt.keyCode && currentLi){ var isHidden = angular.element(evt.target.nextElementSibling).hasClass('hidden-cls'); if(isHidden){ angular.element(evt.target.nextElementSibling).removeClass('hidden-cls'); }else{ evt.target.value = currentLi.innerText; angular.element(currentLi.parentElement).addClass('hidden-cls'); scope.inValue = evt.target.value; } } } }) element.on('input',function(evt){ if(angular.element(this.nextElementSibling).hasClass('hidden-cls')){ angular.element(this.nextElementSibling).removeClass('hidden-cls') } if(this.nextElementSibling.children.length){ angular.element(this.nextElementSibling.getElementsByClassName('item-bg')[0]).removeClass('item-bg'); angular.element(this.nextElementSibling.children[0]).addClass('item-bg'); } scope.$emit('selectInput', { inputId: evt.target.id, inputText: evt.target.value }); }); angular.element(element[0].nextElementSibling).on('mousemove', function(){ isOver = true; }) angular.element(element[0].nextElementSibling).on('mouseleave', function(){ isOver = false; }) element.on('blur',function(evt){ if(!isOver){ angular.element(this.nextElementSibling).addClass('hidden-cls'); } }); } }; }) </script> </body> </html>