diff --git a/HTMLCS.Util.js b/HTMLCS.Util.js index ab10fdde..d698614e 100644 --- a/HTMLCS.Util.js +++ b/HTMLCS.Util.js @@ -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; @@ -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} @@ -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} */ @@ -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. @@ -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. @@ -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, }; } @@ -1290,4 +1304,4 @@ _global.HTMLCS.util = function() { }; return self; -}(); \ No newline at end of file +}(); diff --git a/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3.js b/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3.js index 97677e07..da1f8093 100644 --- a/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3.js +++ b/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3.js @@ -39,7 +39,7 @@ _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; @@ -47,13 +47,14 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3 = { 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) { @@ -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); diff --git a/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3_Contrast.js b/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3_Contrast.js index 77380f2a..33149c3e 100644 --- a/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3_Contrast.js +++ b/Standards/WCAG2AAA/Sniffs/Principle1/Guideline1_4/1_4_3_Contrast.js @@ -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]; } @@ -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; } @@ -86,6 +91,7 @@ _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; } @@ -93,15 +99,56 @@ _global.HTMLCS_WCAG2AAA_Sniffs_Principle1_Guideline1_4_1_4_3_Contrast = { 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, @@ -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, diff --git a/Tests/WCAG2/1_4_3_Contrast.html b/Tests/WCAG2/1_4_3_Contrast.html index fae3759a..46cf3da4 100644 --- a/Tests/WCAG2/1_4_3_Contrast.html +++ b/Tests/WCAG2/1_4_3_Contrast.html @@ -15,6 +15,8 @@
Sample: I am 14pt bold text and should pass
+Warning: I am 14pt bold text on a transparent background and should generate a warning
+