input模拟输入下拉框

    功能点:

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

  实现思路:

    显示隐藏:

      input获取焦点显示,失去焦点隐藏

    下拉选择:

      以父元素为基准,通过绝对定位定位至input输入下方

    模糊检索:

      监听输入数据的变化,过滤符合要求的数据

    键盘上下选择:

      监听input的键盘事件,判断keycode值,再触发上下键时,动态计算滚动条滚动的距离

    控制事件触发频率,采用函数节流

  具体实现过程:

    节流函数:

 function throttle(func, wait, options) {//函数节流
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function() {
var now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
}
}

功能代码:

 xxx.directive('inputAndSelect', function ($timeout) {
return {
restrict: 'AE',
replace: true,
require: 'ngModel',
scope: {
'ngModel': '=',
'data': '@',
'callback': '&'
},
template: '<div class="select-box">' +
' <input type="text" ng-focus="inputOnFocus($event)" ng-blur="inputOnBlur()"' +
' 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;' +
' border-left: 6px solid transparent;\n' +
' border-right: 6px solid transparent;\n' +
' border-top: 8px solid #818181;"></span>' +
' <div class="select-box-container" style="z-index: 999;background-color: #fff;" ng-show="showSelect">' +
' <div class="select-box-item" ng-click="selectInputItem(item)" ng-repeat="item in dataList">{{item}}</div></div>' +
'</div>',
link: function(scope, element, attrs) {
//显示/隐藏下拉列表
scope.showSelect = false;
scope.dataList = [];
scope.selectIndex = -1;
var eleInput = element.find('input');
eleInput.attr('id', attrs.id);
//input获取焦点
eleInput.unbind('focus').bind('focus',function() {
scope.showSelect = true;
scope.dataList = JSON.parse(scope.data);
element.find('.select-box-container .select-box-item').removeClass('option-active');
$timeout(function () {
element.find('.select-box-container').scrollTop(0);
}, 0);
if (scope.ngModel) {
scope.dataList = scope.dataList.filter(function(vv) {
return vv.indexOf(scope.ngModel) !== -1;
})
}
if(attrs.callback) {
scope.$parent[attrs.callback]();
}
});
//选择输入项
scope.selectInputItem = function(item) {
scope.ngModel = item;
scope.showSelect = false;
}; //input失去焦点
scope.inputOnBlur = function() {
$timeout(function() {
scope.selectIndex = -1;
scope.showSelect = false;
}, 200)
};
//监听输入数据的变化
scope.$watch('ngModel', function(newVal) {
if(!scope.data) return;
var items = JSON.parse(scope.data);
if (!newVal && typeof newVal === 'string') {
scope.dataList = items;
} else {
scope.dataList = items.filter(function(vv) {
return vv.indexOf(newVal) !== -1;
})
}
});
//监听键盘按下事件
eleInput.unbind('keydown').bind('keydown', throttle(function(e) {
//keycode 38 up 40 down
var items = element.find('.select-box-container .select-box-item');
var $container = element.find('.select-box-container');
var keycode = e.keyCode;
if (keycode === 40) {
//按键向下
scope.selectIndex++;
scope.selectIndex = scope.selectIndex > scope.dataList.length - 1 ? 0 : scope.selectIndex;
} else if (keycode === 38) {
//按键向上
scope.selectIndex--;
scope.selectIndex = scope.selectIndex < 0 ? scope.dataList.length - 1 : scope.selectIndex;
} else if (keycode === 13) {
if (scope.selectIndex !== -1) {
scope.ngModel = scope.dataList[scope.selectIndex];
scope.showSelect = false;
}
element.find('input').blur();
}else {
return;
}
items.removeClass('option-active');
$(items[scope.selectIndex]).addClass('option-active');
if(scope.selectIndex === 0) {
$container.scrollTop(0);
}
$container.scrollTop(scope.selectIndex*25);
}, 50));
}
}
})

   效果图:

  input模拟输入下拉框

上一篇:JavaScript要点汇总——The Most Important


下一篇:centos 7.x设置守护进程的文件数量限制