Thăng bằng.
Tôi có một loạt 0-tabIndexes, tôi muốn điều hướng bằng bàn phím.
Vì trong trường hợp đó, chỉ có THỨ TỰ của các phần tử là quan trọng, tôi đã thực hiện bằng cách sử dụngdocument.createTreeWalker
Vì vậy, trước tiên, bạn tạo bộ lọc (bạn chỉ muốn các phần tử [hiển thị], có thuộc tính "tabIndex" với giá trị NUMERICAL.
Sau đó, bạn đặt nút gốc mà bạn không muốn tìm kiếm. Trong trường hợp của tôi, this.m_tree
là một phần tử ul chứa một cây có thể chuyển đổi. Nếu bạn muốn toàn bộ tài liệu thay thế, chỉ cần thay thế this.m_tree
bằng document.documentElement
.
Sau đó, bạn đặt nút hiện tại thành phần tử hoạt động hiện tại:
ni.currentNode = el; // el = document.activeElement
Sau đó, bạn trở lại ni.nextNode()
hoặc ni.previousNode()
.
Lưu ý:
điều này sẽ KHÔNG trả về các tab theo đúng thứ tự nếu bạn có tabIndices! = 0 và thứ tự phần tử KHÔNG phải là thứ tự tabIndex. Trong trường hợp tabIndex = 0, tabOrder luôn là thứ tự phần tử, đó là lý do tại sao điều này hoạt động (trong trường hợp đó).
protected createFilter(fn?: (node: Node) => number): NodeFilter
{
// Accept all currently filtered elements.
function acceptNode(node: Node): number
{
return NodeFilter.FILTER_ACCEPT;
}
if (fn == null)
fn = acceptNode;
// Work around Internet Explorer wanting a function instead of an object.
// IE also *requires* this argument where other browsers don't.
const safeFilter: NodeFilter = <NodeFilter><any>fn;
(<any>safeFilter).acceptNode = fn;
return safeFilter;
}
protected createTabbingFilter(): NodeFilter
{
// Accept all currently filtered elements.
function acceptNode(node: Node): number
{
if (!node)
return NodeFilter.FILTER_REJECT;
if (node.nodeType !== Node.ELEMENT_NODE)
return NodeFilter.FILTER_REJECT;
if (window.getComputedStyle(<Element>node).display === "none")
return NodeFilter.FILTER_REJECT;
// "tabIndex": "0"
if (!(<Element>node).hasAttribute("tabIndex"))
return NodeFilter.FILTER_SKIP;
let tabIndex = parseInt((<Element>node).getAttribute("tabIndex"), 10);
if (!tabIndex || isNaN(tabIndex) || !isFinite(tabIndex))
return NodeFilter.FILTER_SKIP;
// if ((<Element>node).tagName !== "LI") return NodeFilter.FILTER_SKIP;
return NodeFilter.FILTER_ACCEPT;
}
return this.createFilter(acceptNode);
}
protected getNextTab(el: HTMLElement): HTMLElement
{
let currentNode: Node;
// https://developer.mozilla.org/en-US/docs/Web/API/Document/createNodeIterator
// https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker
// let ni = document.createNodeIterator(el, NodeFilter.SHOW_ELEMENT);
// let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT);
let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT, this.createTabbingFilter(), false);
ni.currentNode = el;
while (currentNode = ni.nextNode())
{
return <HTMLElement>currentNode;
}
return el;
}
protected getPreviousTab(el: HTMLElement): HTMLElement
{
let currentNode: Node;
let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT, this.createTabbingFilter(), false);
ni.currentNode = el;
while (currentNode = ni.previousNode())
{
return <HTMLElement>currentNode;
}
return el;
}
Lưu ý rằng vòng lặp while
while (currentNode = ni.nextNode())
{
// Additional checks here
// if(condition) return currentNode;
// else the loop continues;
return <HTMLElement>currentNode; // everything is already filtered down to what we need here
}
chỉ ở đó nếu bạn muốn nếu bạn có các tiêu chí bổ sung mà bạn không thể lọc trong bộ lọc được chuyển đến createTreeWalker.
Lưu ý rằng đây là TypeScript, bạn cần xóa tất cả các mã thông báo đằng sau dấu hai chấm (:) và giữa các dấu ngoặc nhọn (<>), ví dụ: <Element>
hoặc :(node: Node) => number
để có được JavaScript hợp lệ.
Đây là một dịch vụ, JS được chuyển đổi:
"use strict";
function createFilter(fn) {
// Accept all currently filtered elements.
function acceptNode(node) {
return NodeFilter.FILTER_ACCEPT;
}
if (fn == null)
fn = acceptNode;
// Work around Internet Explorer wanting a function instead of an object.
// IE also *requires* this argument where other browsers don't.
const safeFilter = fn;
safeFilter.acceptNode = fn;
return safeFilter;
}
function createTabbingFilter() {
// Accept all currently filtered elements.
function acceptNode(node) {
if (!node)
return NodeFilter.FILTER_REJECT;
if (node.nodeType !== Node.ELEMENT_NODE)
return NodeFilter.FILTER_REJECT;
if (window.getComputedStyle(node).display === "none")
return NodeFilter.FILTER_REJECT;
// "tabIndex": "0"
if (!node.hasAttribute("tabIndex"))
return NodeFilter.FILTER_SKIP;
let tabIndex = parseInt(node.getAttribute("tabIndex"), 10);
if (!tabIndex || isNaN(tabIndex) || !isFinite(tabIndex))
return NodeFilter.FILTER_SKIP;
// if ((<Element>node).tagName !== "LI") return NodeFilter.FILTER_SKIP;
return NodeFilter.FILTER_ACCEPT;
}
return createFilter(acceptNode);
}
function getNextTab(el) {
let currentNode;
// https://developer.mozilla.org/en-US/docs/Web/API/Document/createNodeIterator
// https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker
// let ni = document.createNodeIterator(el, NodeFilter.SHOW_ELEMENT);
// let ni = document.createTreeWalker(this.m_tree, NodeFilter.SHOW_ELEMENT);
let ni = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_ELEMENT, createTabbingFilter(), false);
ni.currentNode = el;
while (currentNode = ni.nextNode()) {
return currentNode;
}
return el;
}
function getPreviousTab(el) {
let currentNode;
let ni = document.createTreeWalker(document.documentElement, NodeFilter.SHOW_ELEMENT, createTabbingFilter(), false);
ni.currentNode = el;
while (currentNode = ni.previousNode()) {
return currentNode;
}
return el;
}
currentElementId = "";
?