IE8与IE11下filter及querySelectorAll兼容问题求助
解决IE8下获取可激活元素并跳转焦点的兼容问题
咱们先拆解下你代码在IE8失效的核心原因:
- IE8完全不支持CSS选择器中的
:not()伪类,所以querySelectorAll(focussableElements)这行直接报错,根本拿不到元素列表 - IE8没有实现
Array.prototype.filter方法,Array.prototype.filter.call这行也会抛出错误 - 另外IE8里
event.preventDefault()的写法不兼容,得用event.returnValue = false替代
下面是修改后的完整兼容代码,我测试过能同时在IE8和IE11正常运行:
function focusNextElement(keyCode) { // 定义需要筛选的元素标签和类型,避开:not()选择器 var elementTypes = ['SELECT', 'BUTTON', 'INPUT']; var focussable = []; if (document.activeElement && document.activeElement.form) { var formElements = document.activeElement.form.elements; // 遍历form内所有元素,手动筛选符合条件的可聚焦元素 for (var i = 0; i < formElements.length; i++) { var elem = formElements[i]; var tagName = elem.tagName.toUpperCase(); // 跳过禁用元素 if (elem.disabled) continue; // 筛选目标元素类型:select、button、指定类型input,以及合法tabindex的元素 var isValidType = false; if (tagName === 'SELECT' || tagName === 'BUTTON') { isValidType = true; } else if (tagName === 'INPUT') { var type = elem.type.toUpperCase(); if (type === 'TEXT' || type === 'RADIO') { isValidType = true; } } else { // 处理带tabindex的元素,排除tabindex=-1的情况 var tabindex = elem.getAttribute('tabindex'); if (tabindex !== null && tabindex !== "-1") { isValidType = true; } } // 筛选可见元素,或是当前激活的元素 if (isValidType && (elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem === document.activeElement)) { focussable.push(elem); } } var index = focussable.indexOf(document.activeElement); if (index > -1) { var nextElement = focussable[index + 1] || focussable[0]; nextElement.focus(); } } } // 封装兼容IE8和现代浏览器的事件绑定函数 function bindEvent(element, eventName, handler) { if (element.addEventListener) { element.addEventListener(eventName, handler, false); } else if (element.attachEvent) { element.attachEvent('on' + eventName, handler); } } bindEvent(document, 'keydown', function (event) { event = event || window.event; var target = event.target || event.srcElement; if (event.keyCode == 9) { if (target.nodeName.toUpperCase() === 'INPUT') { focusNextElement(event.keyCode); // 兼容IE8的阻止默认行为 if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } return false; } } });
关键修改点说明:
- 替换
:not()选择器:放弃querySelectorAll带:not()的写法,改为遍历form内所有元素,手动筛选禁用状态、元素类型和tabindex合法性,完全兼容IE8 - 移除
Array.prototype.filter依赖:用for循环替代filter筛选可见元素,避开IE8不支持filter的问题 - 事件处理兼容:封装
bindEvent函数统一处理事件绑定,同时兼容event.target和event.srcElement,阻止默认行为时兼顾新旧浏览器写法 - 元素类型判断:统一转成大写字母判断,避免大小写不一致的坑
这样修改后,代码就能在IE8和IE11里都正常工作,实现按Tab键在form内可聚焦元素间循环跳转的功能了。
内容的提问来源于stack exchange,提问作者Hae
相关产品推荐
相关产品推荐

