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: '
' + 12 ' 13 ' ng-model="ngModel" style="z-index: 10;" class="form-control huowu-input"> 14 ' border-left: 6px solid transparent;\n' + 15 ' border-right: 6px solid transparent;\n' + 16 ' border-top: 8px solid #818181;">' + 17 '
' + 18 '
{{item}}
' + 19 '
', 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 })

   效果图:

  input模拟输入下拉框_第1张图片

 

你可能感兴趣的:(input模拟输入下拉框)