Comparing version 1.0.4 to 1.0.5
# Changelog | ||
## 1.0.5 | ||
- Children of `visibility: hidden` elements that themselves have `visibility: visible` are considered tabbable. | ||
## 1.0.4 | ||
@@ -4,0 +8,0 @@ |
53
index.js
module.exports = function(el) { | ||
var basicTabbables = []; | ||
var orderedTabbables = []; | ||
var isHidden = createIsHidden(); | ||
var candidates = el.querySelectorAll('input, select, a[href], textarea, button, [tabindex]'); | ||
// A node is "available" if | ||
// - it's computed style | ||
var isUnavailable = createIsUnavailable(); | ||
var candidateSelectors = [ | ||
'input', | ||
'select', | ||
'a[href]', | ||
'textarea', | ||
'button', | ||
'[tabindex]', | ||
]; | ||
var candidates = el.querySelectorAll(candidateSelectors); | ||
var candidate, candidateIndex; | ||
@@ -17,3 +29,3 @@ for (var i = 0, l = candidates.length; i < l; i++) { | ||
|| candidate.disabled | ||
|| isHidden(candidate) | ||
|| isUnavailable(candidate) | ||
) { | ||
@@ -46,27 +58,44 @@ continue; | ||
function createIsHidden() { | ||
function createIsUnavailable() { | ||
// Node cache must be refreshed on every check, in case | ||
// the content of the element has changed | ||
var nodeCache = []; | ||
var isOffCache = []; | ||
return function isHidden(node) { | ||
// "off" means `display: none;`, as opposed to "hidden", | ||
// which means `visibility: hidden;`. getComputedStyle | ||
// accurately reflects visiblity in context but not | ||
// "off" state, so we need to recursively check parents. | ||
function isOff(node, nodeComputedStyle) { | ||
if (node === document.documentElement) return false; | ||
// Find the cached node (Array.prototype.find not available in IE9) | ||
for (var i = 0, length = nodeCache.length; i < length; i++) { | ||
if (nodeCache[i][0] === node) return nodeCache[i][1]; | ||
for (var i = 0, length = isOffCache.length; i < length; i++) { | ||
if (isOffCache[i][0] === node) return isOffCache[i][1]; | ||
} | ||
nodeComputedStyle = nodeComputedStyle || window.getComputedStyle(node); | ||
var result = false; | ||
var style = window.getComputedStyle(node); | ||
if (style.visibility === 'hidden' || style.display === 'none') { | ||
if (nodeComputedStyle.display === 'none') { | ||
result = true; | ||
} else if (node.parentNode) { | ||
result = isHidden(node.parentNode); | ||
result = isOff(node.parentNode); | ||
} | ||
nodeCache.push([node, result]); | ||
isOffCache.push([node, result]); | ||
return result; | ||
} | ||
return function isUnavailable(node) { | ||
if (node === document.documentElement) return false; | ||
var computedStyle = window.getComputedStyle(node); | ||
if (isOff(node, computedStyle)) return true; | ||
return computedStyle.visibility === 'hidden'; | ||
} | ||
} |
{ | ||
"name": "tabbable", | ||
"version": "1.0.4", | ||
"version": "1.0.5", | ||
"description": "Returns an array of all tabbable DOM nodes within a containing node.", | ||
@@ -8,5 +8,4 @@ "main": "index.js", | ||
"lint": "eslint .", | ||
"test-dev": "zuul --local 8080 -- test/index.js --debug", | ||
"pretest": "npm run lint", | ||
"test": "zuul -- test/index.js" | ||
"test": "karma start && npm run lint", | ||
"debug": "budo -l -d -o test/debug.js -- -t brfs" | ||
}, | ||
@@ -24,12 +23,15 @@ "repository": { | ||
"devDependencies": { | ||
"brfs": "1.4.3", | ||
"browserify": "13.0.1", | ||
"eslint": "2.13.0", | ||
"tape": "4.5.1", | ||
"zuul": "3.10.1", | ||
"zuul-ngrok": "^4.0.0" | ||
}, | ||
"files": [ | ||
"index.js" | ||
] | ||
"brfs": "^1.4.3", | ||
"browserify": "^13.1.1", | ||
"budo": "^9.2.1", | ||
"chai": "^3.5.0", | ||
"eslint": "^3.9.0", | ||
"karma": "^1.3.0", | ||
"karma-browserify": "^5.1.0", | ||
"karma-firefox-launcher": "^1.0.0", | ||
"karma-mocha": "^1.3.0", | ||
"karma-mocha-reporter": "^2.2.1", | ||
"mocha": "^3.2.0", | ||
"watchify": "^3.8.0" | ||
} | ||
} |
# tabbable | ||
[![Build Status](https://travis-ci.org/davidtheclark/tabbable.svg?branch=master)](https://travis-ci.org/davidtheclark/tabbable) | ||
Returns an array of all tabbable DOM nodes within a containing node, *in their actual tab order* (cf. [Sequential focus navigation and the tabindex attribute](http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute)). | ||
@@ -19,2 +21,4 @@ | ||
**Note**: Though browsers allow tabbing into elements marked `contenteditable`, outstanding bugs in the `tabIndex` API prevents `tabbable` from registering them. If you have `contenteditable` elements that you need included in the array, you'll have to additionally specify `tabindex="0"`. | ||
## Goals | ||
@@ -28,8 +32,6 @@ - Accurate | ||
Basically IE9+. See `.zuul.yml` for more details. | ||
Basically IE9+. | ||
Why? It uses [Element.querySelectorAll()](https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelectorAll) and [Window.getComputedStyle()](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle). | ||
Automated testing is done with [zuul](https://github.com/defunctzombie/zuul) and [Open Suace](https://saucelabs.com/opensauce/). | ||
## Installation | ||
@@ -67,7 +69,1 @@ | ||
*Feedback more than welcome!* | ||
## Development | ||
Lint with `npm run lint`. | ||
Test with `npm run test-dev`, which will give you a URL to open in your browser. Look at the console log for TAP output. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
130472
7
104
12
67