-
Notifications
You must be signed in to change notification settings - Fork 779
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #450 from dequelabs/sd/region-check
Sd/region check
- Loading branch information
Showing
6 changed files
with
182 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,57 @@ | ||
//jshint latedef: false | ||
const { dom, aria } = axe.commons; | ||
|
||
var landmarkRoles = axe.commons.aria.getRolesByType('landmark'), | ||
firstLink = node.querySelector('a[href]'); | ||
|
||
function isSkipLink(n) { | ||
return firstLink && | ||
axe.commons.dom.isFocusable(axe.commons.dom.getElementByReference(firstLink, 'href')) && | ||
firstLink === n; | ||
// Return the skplink, if any | ||
function getSkiplink (virtualNode) { | ||
const firstLink = axe.utils.querySelectorAll(virtualNode, 'a[href]')[0]; | ||
if (firstLink && axe.commons.dom.getElementByReference(firstLink.actualNode, 'href')) { | ||
return firstLink.actualNode; | ||
} | ||
} | ||
|
||
function isLandmark(n) { | ||
var role = n.getAttribute('role'); | ||
return role && (landmarkRoles.indexOf(role) !== -1); | ||
const skipLink = getSkiplink(virtualNode); | ||
const landmarkRoles = aria.getRolesByType('landmark'); | ||
|
||
// Create a list of nodeNames that have a landmark as an implicit role | ||
const implicitLandmarks = landmarkRoles | ||
.reduce((arr, role) => arr.concat(aria.implicitNodes(role)), []) | ||
.filter(r => r !== null).map(r => r.toUpperCase()); | ||
|
||
// Check if the current element is the skiplink | ||
function isSkipLink (node) { | ||
return skipLink && skipLink === node; | ||
} | ||
|
||
function checkRegion(n) { | ||
if (isLandmark(n)) { return null; } | ||
if (isSkipLink(n)) { return getViolatingChildren(n); } | ||
if (axe.commons.dom.isVisible(n, true) && | ||
(axe.commons.text.visible(n, true, true) || axe.commons.dom.isVisualContent(n))) { return n; } | ||
return getViolatingChildren(n); | ||
// Check if the current element is a landmark | ||
function isLandmark (node) { | ||
if (node.hasAttribute('role')) { | ||
return landmarkRoles.includes(node.getAttribute('role').toLowerCase()); | ||
} else { | ||
return implicitLandmarks.includes(node.nodeName.toUpperCase()); | ||
} | ||
} | ||
function getViolatingChildren(n) { | ||
var children = axe.commons.utils.toArray(n.children); | ||
if (children.length === 0) { return []; } | ||
return children.map(checkRegion) | ||
.filter(function (c) { return c !== null; }) | ||
.reduce(function (a, b) { return a.concat(b); }, []); | ||
|
||
/** | ||
* Find all visible elements not wrapped inside a landmark or skiplink | ||
*/ | ||
function findRegionlessElms (virtualNode) { | ||
const node = virtualNode.actualNode; | ||
// End recursion if the element is a landmark, skiplink, or hidden content | ||
if (isLandmark(node) || isSkipLink(node) || !dom.isVisible(node, true)) { | ||
return []; | ||
|
||
// Return the node is a content element | ||
} else if (dom.hasContent(node, /* noRecursion: */ true)) { | ||
return [node]; | ||
|
||
// Recursively look at all child elements | ||
} else { | ||
return virtualNode.children.filter(({ actualNode }) => actualNode.nodeType === 1) | ||
.map(findRegionlessElms) | ||
.reduce((a, b) => a.concat(b), []); // flatten the results | ||
} | ||
} | ||
|
||
var v = getViolatingChildren(node); | ||
this.relatedNodes(v); | ||
return !v.length; | ||
var regionlessNodes = findRegionlessElms(virtualNode); | ||
this.relatedNodes(regionlessNodes); | ||
|
||
return regionlessNodes.length === 0; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,20 @@ | ||
/*global dom */ | ||
|
||
dom.getElementByReference = function (node, attr) { | ||
'use strict'; | ||
|
||
var candidate, | ||
fragment = node.getAttribute(attr), | ||
doc = document; | ||
let fragment = node.getAttribute(attr); | ||
|
||
if (fragment && fragment.charAt(0) === '#') { | ||
fragment = fragment.substring(1); | ||
|
||
candidate = doc.getElementById(fragment); | ||
let candidate = document.getElementById(fragment); | ||
if (candidate) { | ||
return candidate; | ||
} | ||
|
||
candidate = doc.getElementsByName(fragment); | ||
candidate = document.getElementsByName(fragment); | ||
if (candidate.length) { | ||
return candidate[0]; | ||
} | ||
|
||
} | ||
|
||
return null; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters