input模拟输入下拉框
功能点:
输入、下拉选择、根据输入内容模糊检索、键盘上下键选择
实现思路:
显示隐藏:
input获取焦点显示,失去焦点隐藏
下拉选择:
以父元素为基准,通过绝对定位定位至input输入下方
模糊检索:
监听输入数据的变化,过滤符合要求的数据
键盘上下选择:
监听input的键盘事件,判断keycode值,再触发上下键时,动态计算滚动条滚动的距离
控制事件触发频率,采用函数节流
具体实现过程:
节流函数:
1 function throttle(func, wait, options) {//函数节流 2 var context, args, result; 3 var timeout = null; 4 var previous = 0; 5 if (!options) options = {}; 6 var later = function() { 7 previous = options.leading === false ? 0 : new Date().getTime(); 8 timeout = null; 9 result = func.apply(context, args); 10 if (!timeout) context = args = null; 11 }; 12 return function() { 13 var now = new Date().getTime(); 14 if (!previous && options.leading === false) previous = now; 15 var remaining = wait - (now - previous); 16 context = this; 17 args = arguments; 18 if (remaining <= 0 || remaining > wait) { 19 if (timeout) { 20 clearTimeout(timeout); 21 timeout = null; 22 } 23 previous = now; 24 result = func.apply(context, args); 25 if (!timeout) context = args = null; 26 } else if (!timeout && options.trailing !== false) { 27 timeout = setTimeout(later, remaining); 28 } 29 return result; 30 } 31 }
功能代码:
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', 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 })
效果图:
本文为原创文章,如有转载,烦请注明出处,谢谢!