在做下拉框时,一直以来处理下拉选项失去焦点的显示隐藏,都是通过document监听指定的事件来控制,但是这可能会造成事件重复绑定,即使用了别名,这样维护起来也比较麻烦,特别是在有特定内部框架的情况下,你无法保证document绑定的事件别名是不是没被用过。
于是就想通过失去焦点的方式处理,但是show()和hide()表现得有点违和,巧合下发现div可以通过添加属性“ tabindex='-1' ”来控制键盘上tab键对该下拉框的焦点获取,也因为这个属性,使得整个下拉框看起来像是一个整体一样。在下拉框最外成div绑定的事件如下(当然这里我稍微修改了一下,把框架内的东西去掉了,浅显易懂些):
showUl: function () { // 这里监听整个控件失去焦点时,点击其它任何地方隐藏下拉选项 $('div.dropdown_container').on('blur.showUl', function (event) { event.stopPropagation(); $(this).find('div.dropdown_select').slideUp('slow'); // 收起下拉选项 }); // 这里监听点击事件,并且阻止失去焦点事件 $('div.dropdown_container').on('click.showUl', function (event) { event.stopImmediatePropagation(); $(this).find('div.dropdown_select').slideToggle('slow'); // 点击事件下切换显示隐藏下拉选项 }); }
处理完之后,就可以对下拉选项绑定事件了,我这里是用ul、li模拟的选项
ulEvent: function () { var that = this; $('div.dropdown_select').on('click.selectLi', function (event) { // 阻止父级的点击和失去焦点事件 event.stopPropagation(); var target = event.target; if (!$(target).is('li') && $(target).parent('li').length == 0) // 由于事件是绑定在ul的父元素div上的,所以这里做了判断 return; // ......业务处理..... }); }
如果在与ul同级下,有个文本框是打算来搜索的,如果不对其事件进行处理,那么在点击文本框的时候,由于焦点这个时候被文本框拿到了,而不是在下拉框了,下拉框就隐藏起来了,但这个不是我们要的效果,要想不被隐藏,尝试下面这么做,成功:
inputEvent: function () { var that = this; // 文本框会抢走焦点,处理方式:先在mousedown的时候,注销div.dropdown_container的两个事件,在失去焦点的时候再恢复其事件的绑定,同时,执行一次点击事件, $('div.input-group input').on('mousedown.stopDCEvent', function (event) { $('div.dropdown_container').off('blur.showUl'); $('div.dropdown_container').off('click.showUl'); }); $('div.input-group input').on('mouseup.restoreDCEvent', function (event) { showUl(); $('div.dropdown_container').click(); // 这里点击一下的目的是为了让下拉框拿到焦点,相当于把焦点交还给下拉框 }); }
如果下拉选项有多选框呢,处理方式比较简单,将多选框的选中事件给去掉,然后在业务逻辑,即ulEvent()方法中处理即可:
optionsCbEvent: function () { $('ul.dropdown_ul li input[type="checkbox"]').on('mousedown.stopClick', function (event) { return false; }); }