功能点:

    输入、下拉选择、根据输入内容模糊检索、键盘上下键选择

  实现思路:

    显示隐藏:

      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. })

   效果图:

  

input模拟输入下拉框的更多相关文章

  1. Chrome浏览器取消INPUT自动记忆下拉框

    项目中有一个搜索框,每次聚焦就会出现如下图自动记忆框,遮挡了项目的搜索列表 差了很多资料想要去掉它,最后发现在input上加上autocomplete="off"就可以了!

  2. 树形下拉框ztree、获取ztree所有父节点,ztree的相关方法

    参考:jQuery树形控件zTree使用小结 需求 添加.修改的终端需要选择组织,组织是多级架构(树状图显示). 思路 1.因为下拉框需要树状图显示,所以排除使用select做下拉框,改用input  ...

  3. 用div,ul,input模拟select下拉框

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  4. struts2 jsp表单提交后保留表单中输入框中的值 下拉框select与input

    原文地址:struts2 jsp表单提交后保留表单中输入框中的值 下拉框select与input jsp页面 1     function dosearch() {2         if ($(&q ...

  5. input+div 下拉选择框

    前台html页面 <html> <head> <meta name="viewport" content="width=device-wid ...

  6. Bootstrap modal模态框关闭时,combobox input下拉框仍然保留在页面上

    问题描述: 当点击模态框的关闭按钮时,下拉框中的内容没有消失,而是移动到了页面左上角 分析:这个问题的定位在于是用的哪种模态框,bootstrap和easyui都可以实现模态框,但是两个方法实现的模态 ...

  7. 使用jquery-combobox实现select下拉框多选之后,如何将下拉框的值传给input隐藏域

    我在之前的一篇博文中eaeyui-combobox实现组合查询(即实现多个值得搜索)地址:http://www.cnblogs.com/dushan/p/4778897.html 实现了select下 ...

  8. 【jQuery获取下拉框select、单选框radio、input普通框的值和checkbox选中的个数】

    radio单选框:name属性相同 <input type="radio" id="sp_type" name="p_type" va ...

  9. jquery.editable-select 可编辑下拉框之获取select值和input值

    使用jquery.editable-select可以实现可编辑下拉框的功能,但需要先导入jquery.js,jquery.editable-select.css,jquery.editable-sel ...

随机推荐

  1. python并发编程之多进程1-----------互斥锁与进程间的通信

    一.互斥锁 进程之间数据隔离,但是共享一套文件系统,因而可以通过文件来实现进程直接的通信,但问题是必须自己加锁处理. 注意:加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行 ...

  2. 量化投资与Python

    目录: 一.量化投资第三方相关模块 NumPy:数组批量计算 Pandas:表计算与数据分析 Matplotlib:图表绘制 二.IPython的介绍 IPython:和Python一样 三.如何使用 ...

  3. C#关于线程的问题

    1.通过System.threading.Thread类可以创建新的线程,并在线程堆栈中运行静态和动态的实例,可以通过Thread类的构造方法传递一个无参数,并且不返回的委托, class Progr ...

  4. base64解密

    问题 : base64解密 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个 ...

  5. ES6 Promise 全面总结

    转载:点击查看原文 ES6 Promise对象 ES6中,新增了Promise对象,它主要用于处理异步回调代码,让代码不至于陷入回调嵌套的死路中. @-v-@ 1. Promise本质 Promise ...

  6. C++ GetModuleFileName()

    关于GetModuleFileName function,参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms683197(v= ...

  7. jQuery核心方法

    1.$(document.body).css( "background", "black" ); 2.$(myForm.elements).hide():隐藏表 ...

  8. IEDA序列化设置

  9. OpenCV-Python入门教程7-PyQt编写GUI界面

    前面一直都是使用命令行运行代码,不够人性化.这篇用Python编写一个GUI界面,使用PyQt5编写图像处理程序.包括:打开.关闭摄像头,捕获图片,读取本地图片,灰度化和Otsu自动阈值分割的功能. ...

  10. Python推荐系统库--Surprise实战

    一.使用movieLens数据集 from surprise import KNNBasic, SVD from surprise import Dataset from surprise impor ...