功能点:
输入、下拉选择、根据输入内容模糊检索、键盘上下键选择
实现思路:
显示隐藏:
input获取焦点显示,失去焦点隐藏
下拉选择:
以父元素为基准,通过绝对定位定位至input输入下方
模糊检索:
监听输入数据的变化,过滤符合要求的数据
键盘上下选择:
监听input的键盘事件,判断keycode值,再出发上下键时,动态计算滚动条滚动的距离
具体实现过程:
1 xxx.directive('inputAndSelect', function ($timeout) { 2 return { 3 restrict: 'AE', 4 replace: true, 5 require: 'ngModel', 6 scope: { 7 'ngModel': '=', 8 'data': '@', 9 'callback': '&' 10 }, 11 template: '<div class="select-box">' + 12 ' <input type="text" ng-focus="inputOnFocus($event)" ng-blur="inputOnBlur()"' + 13 ' ng-model="ngModel" style="z-index: 10;" class="form-control huowu-input"><span class="arrow-down" style="display:inline-block;width: 12px;height: 8px;right: 14px;' + 14 ' border-left: 6px solid transparent;\n' + 15 ' border-right: 6px solid transparent;\n' + 16 ' border-top: 8px solid #818181;"></span>' + 17 ' <div class="select-box-container" style="z-index: 999;background-color: #fff;" ng-show="showSelect">' + 18 ' <div class="select-box-item" ng-click="selectInputItem(item)" ng-repeat="item in dataList">{{item}}</div></div>' + 19 '</div>', 20 link: function(scope, element, attrs) { 21 //显示/隐藏下拉列表 22 scope.showSelect = false; 23 scope.dataList = []; 24 scope.selectIndex = -1; 25 var eleInput = element.find('input'); 26 eleInput.attr('id', attrs.id); 27 //input获取焦点 28 eleInput.unbind('focus').bind('focus',function() { 29 scope.showSelect = true; 30 scope.dataList = JSON.parse(scope.data); 31 element.find('.select-box-container .select-box-item').removeClass('option-active'); 32 $timeout(function () { 33 element.find('.select-box-container').scrollTop(0); 34 }, 0); 35 if (scope.ngModel) { 36 scope.dataList = scope.dataList.filter(function(vv) { 37 return vv.indexOf(scope.ngModel) !== -1; 38 }) 39 } 40 if(attrs.callback) { 41 scope.$parent[attrs.callback](); 42 } 43 }); 44 //选择输入项 45 scope.selectInputItem = function(item) { 46 scope.ngModel = item; 47 scope.showSelect = false; 48 }; 49 50 //input失去焦点 51 scope.inputOnBlur = function() { 52 $timeout(function() { 53 scope.selectIndex = -1; 54 scope.showSelect = false; 55 }, 200) 56 }; 57 //监听输入数据的变化 58 scope.$watch('ngModel', function(newVal) { 59 if(!scope.data) return; 60 var items = JSON.parse(scope.data); 61 if (!newVal && typeof newVal === 'string') { 62 scope.dataList = items; 63 } else { 64 scope.dataList = items.filter(function(vv) { 65 return vv.indexOf(newVal) !== -1; 66 }) 67 } 68 }); 69 //监听键盘按下事件 70 eleInput.unbind('keydown').bind('keydown', ke.utils.throttle(function(e) { 71 //keycode 38 up 40 down 72 var items = element.find('.select-box-container .select-box-item'); 73 var $container = element.find('.select-box-container'); 74 var keycode = e.keyCode; 75 if (keycode === 40) { 76 //按键向下 77 scope.selectIndex++; 78 scope.selectIndex = scope.selectIndex > scope.dataList.length - 1 ? 0 : scope.selectIndex; 79 } else if (keycode === 38) { 80 //按键向上 81 scope.selectIndex--; 82 scope.selectIndex = scope.selectIndex < 0 ? scope.dataList.length - 1 : scope.selectIndex; 83 } else if (keycode === 13) { 84 if (scope.selectIndex !== -1) { 85 scope.ngModel = scope.dataList[scope.selectIndex]; 86 scope.showSelect = false; 87 } 88 element.find('input').blur(); 89 }else { 90 return; 91 } 92 items.removeClass('option-active'); 93 $(items[scope.selectIndex]).addClass('option-active'); 94 if(scope.selectIndex === 0) { 95 $container.scrollTop(0); 96 } 97 $container.scrollTop(scope.selectIndex*25); 98 }, 50)); 99 } 100 } 101 })
效果图: