Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add warnings to output for alpha levels in contrast check #223

Merged
merged 2 commits into from
Jul 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 24 additions & 10 deletions HTMLCS.Util.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,15 @@ _global.HTMLCS.util = function() {
*
* @returns {Object}
*/
self.style = function(element) {
self.style = function(element, pseudo) {
var computedStyle = null;
var window = self.getElementWindow(element);
var pseudo = pseudo || null;

if (element.currentStyle) {
computedStyle = element.currentStyle;
} else if (window.getComputedStyle) {
computedStyle = window.getComputedStyle(element, null);
computedStyle = window.getComputedStyle(element, pseudo);
}

return computedStyle;
Expand Down Expand Up @@ -240,7 +241,7 @@ _global.HTMLCS.util = function() {
* Returns true if the element is deliberately hidden from Accessibility APIs using ARIA hidden.
*
* Not: This is separate to isAccessibilityHidden() due to a need to check specifically for aria hidden.
*
*
* @param {Node} element The element to check.
*
* @return {Boolean}
Expand Down Expand Up @@ -397,7 +398,7 @@ _global.HTMLCS.util = function() {
* Returns all elements that are visible to the accessibility API.
*
* @param {Node} element The parent element to search.
* @param {String} selector Optional selector to pass to
* @param {String} selector Optional selector to pass to
*
* @return {Array}
*/
Expand Down Expand Up @@ -533,10 +534,9 @@ _global.HTMLCS.util = function() {
}

/**
* Convert a colour string to a structure with red/green/blue elements.
* Convert a colour string to a structure with red/green/blue/alpha elements.
*
* Supports rgb() and hex colours (3 or 6 hex digits, optional "#").
* rgba() also supported but the alpha channel is currently ignored.
* Supports rgb() and hex colours (3, 4, 6 or 8 hex digits, optional "#").
* Each red/green/blue element is in the range [0.0, 1.0].
*
* @param {String} colour The colour to convert.
Expand All @@ -552,7 +552,11 @@ _global.HTMLCS.util = function() {
colour = {
red: (matches[1] / 255),
green: (matches[2] / 255),
blue: (matches[3] / 255)
blue: (matches[3] / 255),
alpha: 1.0
};
if (matches[4]) {
colour.alpha = parseFloat(/^,\s*(.*)$/.exec(matches[4])[1]);
}
} else {
// Hex digit format.
Expand All @@ -564,10 +568,20 @@ _global.HTMLCS.util = function() {
colour = colour.replace(/^(.)(.)(.)$/, '$1$1$2$2$3$3');
}

if (colour.length === 4) {
colour = colour.replace(/^(.)(.)(.)(.)$/, '$1$1$2$2$3$3$4$4');
}

var alpha = 1; // Default if alpha is not specified
if (colour.length === 8) {
alpha = parseInt(colour.substr(6, 2), 16) / 255;
}

colour = {
red: (parseInt(colour.substr(0, 2), 16) / 255),
green: (parseInt(colour.substr(2, 2), 16) / 255),
blue: (parseInt(colour.substr(4, 2), 16) / 255)
blue: (parseInt(colour.substr(4, 2), 16) / 255),
alpha: alpha,
};
}

Expand Down Expand Up @@ -1290,4 +1304,4 @@ _global.HTMLCS.util = function() {
};

return self;
}();
}();
8 changes: 6 additions & 2 deletions Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,22 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3 = {

for (var i = 0; i < failures.length; i++) {
var element = failures[i].element;

var decimals = 2;
var value = (Math.round(failures[i].value * Math.pow(10, decimals)) / Math.pow(10, decimals));
var required = failures[i].required;
var recommend = failures[i].recommendation;
var hasBgImg = failures[i].hasBgImage || false;
var bgColour = failures[i].bgColour || false;
var isAbsolute = failures[i].isAbsolute || false;
var hasAlpha = failures[i].hasAlpha || false;

// If the values would look identical, add decimals to the value.
while (required === value) {
decimals++;
value = (Math.round(failures[i].value * Math.pow(10, decimals)) / Math.pow(10, decimals));
}

if (required === 4.5) {
var code = 'G18';
} else if (required === 3.0) {
Expand All @@ -80,6 +81,9 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3 = {
} else if (hasBgImg === true) {
code += '.BgImage';
HTMLCS.addMessage(HTMLCS.WARNING, element, _global.HTMLCS.getTranslation("1_4_3_G18_or_G145.BgImage").replace(/\{\{required\}\}/g, required), code);
} else if (hasAlpha === true) {
code += '.Alpha';
HTMLCS.addMessage(HTMLCS.WARNING, element, _global.HTMLCS.getTranslation("1_4_3_G18_or_G145.Alpha").replace(/\{\{required\}\}/g, required), code);
} else {
code += '.Fail';
HTMLCS.addMessage(HTMLCS.ERROR, element, _global.HTMLCS.getTranslation("1_4_3_G18_or_G145.Fail").replace(/\{\{required\}\}/g, required).replace(/\{\{value\}\}/g, value) + recommendText, code);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3_Contrast = {
var failures = [];

if (!top.ownerDocument) {
var toProcess = [top.getElementsByTagName('body')[0]];
var toProcess = [];
var body = top.getElementsByTagName('body');
if (body.length) {
// SVG objects will not have a body element. Don't check them.
var toProcess = [body[0]];
}
} else {
var toProcess = [top];
}
Expand Down Expand Up @@ -52,11 +57,11 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3_Contrast = {
var bgElement = node;
var hasBgImg = false;
var isAbsolute = false;
if (style.backgroundImage !== 'none') {

if (style.backgroundImage !== 'none') {
hasBgImg = true;
}

if (style.position == 'absolute') {
isAbsolute = true;
}
Expand Down Expand Up @@ -86,22 +91,64 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3_Contrast = {

var parentStyle = HTMLCS.util.style(parent);
var bgColour = parentStyle.backgroundColor;
var bgElement = parent;
if (parentStyle.backgroundImage !== 'none') {
hasBgImg = true;
}
if (parentStyle.position == 'absolute') {
isAbsolute = true;
}

// Search for the smooth scrolling willChange: 'transform' background hack
// See http://fourkitchens.com/blog/article/fix-scrolling-performance-css-will-change-property
var beforeStyle = HTMLCS.util.style(parent, ':before');
if (
beforeStyle
&& beforeStyle.position == 'fixed'
&& beforeStyle.willChange == 'transform'
//Make sure it is trying to cover the entire content area
&& beforeStyle.width == parentStyle.width
&& parseInt(beforeStyle.height, 10) <= parseInt(parentStyle.height, 10)
//And finally it needs a background image
&& beforeStyle.backgroundImage !== 'none'
) {
hasBgImg = true;
break;
}

parent = parent.parentNode;
}//end while

if (hasBgImg === true) {
if (bgColour && HTMLCS.util.colourStrToRGB(bgColour).alpha < 1.0) {
// If we have a rgba background colour, skip the contrast ratio checks,
// and push a warning instead.
failures.push({
element: node,
colour: foreColour,
bgColour: bgColour,
value: undefined,
required: reqRatio,
hasAlpha: true,
});
continue;
} else if (foreColour && HTMLCS.util.colourStrToRGB(foreColour).alpha < 1.0) {
// If we have a rgba fore colour, skip the contrast ratio checks,
// and push a warning instead.
failures.push({
element: node,
colour: foreColour,
bgColour: foreColour,
value: undefined,
required: reqRatio,
hasAlpha: true
});
continue;
} else if (hasBgImg === true) {
// If we have a background image, skip the contrast ratio checks,
// and push a warning instead.
failures.push({
element: node,
colour: style.color,
colour: foreColour,
bgColour: undefined,
value: undefined,
required: reqRatio,
Expand All @@ -125,9 +172,10 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3_Contrast = {
continue;
}

var contrastRatio = HTMLCS.util.contrastRatio(bgColour, style.color);
var contrastRatio = HTMLCS.util.contrastRatio(bgColour, foreColour);

if (contrastRatio < reqRatio) {
var recommendation = this.recommendColour(bgColour, style.color, reqRatio);
var recommendation = this.recommendColour(bgColour, foreColour, reqRatio);

failures.push({
element: node,
Expand Down
2 changes: 2 additions & 0 deletions Tests/WCAG2/1_4_3_Contrast.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

<p>Sample: <span id="issue155" style="color: #7c7cff; background-color: #ffffff; font-size: 14pt; font-weight: bold;">I am 14pt bold text and should pass</span></p>

<p>Warning: <span id="pr134" style="color: #7c7cff; background-color: #0000000C; font-size: 14pt; font-weight: bold;">I am 14pt bold text on a transparent background and should generate a warning</span></p>

</body>
</html>

Expand Down
1 change: 1 addition & 0 deletions Translations/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ _global.translation['en'] = {
//1_4_3.js
,"1_4_3_G18_or_G145.Abs" : 'This element is absolutely positioned and the background color can not be determined. Ensure the contrast ratio between the text and all covered parts of the background are at least {{required}}:1.'
,"1_4_3_G18_or_G145.BgImage" : 'This element\'s text is placed on a background image. Ensure the contrast ratio between the text and all covered parts of the image are at least {{required}}:1.'
,"1_4_3_G18_or_G145.Alpha" : 'This element\'s text or background contains transparency. Ensure the contrast ratio between the text and background are at least {{required}}:1.'
,"1_4_3_G18_or_G145.Fail" : 'This element has insufficient contrast at this conformance level. Expected a contrast ratio of at least {{required}}:1, but text in this element has a contrast ratio of {{value}}:1.'
,"1_4_3_G18_or_G145.Fail.Recomendation" : 'Recommendation: change'
,"1_4_3_G18_or_G145.Fail.Recomendation.Text" : 'text colour to'
Expand Down