UNPKG

html_codesniffer

Version:

HTML_CodeSniffer is a client-side JavaScript that checks a HTML document or source code, and detects violations of a defined coding standard.

176 lines (155 loc) 8.09 kB
/** * +--------------------------------------------------------------------+ * | This HTML_CodeSniffer file is Copyright (c) | * | Squiz Australia Pty Ltd ABN 53 131 581 247 | * +--------------------------------------------------------------------+ * | IMPORTANT: Your use of this Software is subject to the terms of | * | the Licence provided in the file licence.txt. If you cannot find | * | this file please contact Squiz (www.squiz.com.au) so we may | * | provide you a copy. | * +--------------------------------------------------------------------+ * */ _global.HTMLCS_Section508_Sniffs_L = { /** * Determines the elements to register for processing. * * Each element of the returned array can either be an element name, or "_top" * which is the top element of the tested code. * * @returns {Array} The list of elements. */ register: function() { return ['_top']; }, /** * Process the registered element. * * @param {DOMNode} element The element registered. * @param {DOMNode} top The top element of the tested code. */ process: function(element, top) { if (element === top) { this.addProcessLinksMessages(top); this.testKeyboard(top); } }, addProcessLinksMessages: function(top) { var errors = this.processLinks(top); for (var i = 0; i < errors.emptyNoId.length; i++) { HTMLCS.addMessage(HTMLCS.ERROR, errors.emptyNoId[i], 'Anchor element found with no link content and no name and/or ID attribute.', 'EmptyAnchorNoId'); } for (var i = 0; i < errors.placeholder.length; i++) { HTMLCS.addMessage(HTMLCS.WARNING, errors.placeholder[i], 'Anchor element found with link content, but no href, ID, or name attribute has been supplied.', 'PlaceholderAnchor'); } for (var i = 0; i < errors.noContent.length; i++) { HTMLCS.addMessage(HTMLCS.ERROR, errors.noContent[i], 'Anchor element found with a valid href attribute, but no link content has been supplied.', 'NoContentAnchor'); } }, processLinks: function(top) { var errors = { empty: [], emptyWithName: [], emptyNoId: [], noHref: [], placeholder: [], noContent: [] }; var elements = HTMLCS.util.getAllElements(top, 'a'); for (var el = 0; el < elements.length; el++) { var element = elements[el]; var hrefFound = false; var content = HTMLCS.util.getElementTextContent(element); /* var nameFound = false; if ((element.hasAttribute('title') === true) && (/^\s*$/.test(element.getAttribute('title')) === false)) { nameFound = true; } else if (/^\s*$/.test(content) === false) { nameFound = true; } */ if ((element.hasAttribute('href') === true) && (/^\s*$/.test(element.getAttribute('href')) === false)) { hrefFound = true; } if (hrefFound === false) { // No href. We don't want these because, although they are commonly used // to create targets, they can be picked up by screen readers and // displayed to the user as empty links. A elements are defined by H91 as // having an (ARIA) role of "link", and using them as targets are // essentially misusing them. Place an ID on a parent element instead. if (/^\s*$/.test(content) === true) { // Also no content. (eg. <a id=""></a> or <a name=""></a>) if (element.hasAttribute('id') === true) { errors.empty.push(element); } else if (element.hasAttribute('name') === true) { errors.emptyWithName.push(element); } else { errors.emptyNoId.push(element); } } else { // Giving a benefit of the doubt here - if a link has text and also // an ID, but no href, it might be because it is being manipulated by // a script. if ((element.hasAttribute('id') === true) || (element.hasAttribute('name') === true)) { errors.noHref.push(element); } else { // HTML5 allows A elements with text but no href, "for where a // link might otherwise have been placed, if it had been relevant". // Hence, thrown as a warning, not an error. errors.placeholder.push(element); } }//end if } else { if (/^\s*$/.test(content) === true) { // Href provided, but no content. // We only fire this message when there are no images in the content. // A link around an image with no alt text is already covered in SC // 1.1.1 (test H30). if (element.querySelectorAll('img').length === 0) { errors.noContent.push(element); } }//end if }//end if }//end for return errors; }, /** * Process mouse-specific functions. * * @param {DOMNode} top The top element of the tested code. */ testKeyboard: function(top) { // Testing for elements that have explicit attributes for mouse-specific // events. Note: onclick is considered keyboard accessible, as it is actually // tied to the default action of a link or button - not merely a click. var dblClickEls = HTMLCS.util.getAllElements(top, '*[ondblclick]'); for (var i = 0; i < dblClickEls.length; i++) { HTMLCS.addMessage(HTMLCS.WARNING, dblClickEls[i], 'Ensure the functionality provided by double-clicking on this element is available through the keyboard.', 'DblClick'); } var mouseOverEls = HTMLCS.util.getAllElements(top, '*[onmouseover]'); for (var i = 0; i < mouseOverEls.length; i++) { HTMLCS.addMessage(HTMLCS.WARNING, mouseOverEls[i], 'Ensure the functionality provided by mousing over this element is available through the keyboard; for instance, using the focus event.', 'MouseOver'); } var mouseOutEls = HTMLCS.util.getAllElements(top, '*[onmouseout]'); for (var i = 0; i < mouseOutEls.length; i++) { HTMLCS.addMessage(HTMLCS.WARNING, mouseOutEls[i], 'Ensure the functionality provided by mousing out of this element is available through the keyboard; for instance, using the blur event.', 'MouseOut'); } var mouseMoveEls = HTMLCS.util.getAllElements(top, '*[onmousemove]'); for (var i = 0; i < mouseMoveEls.length; i++) { HTMLCS.addMessage(HTMLCS.WARNING, mouseMoveEls[i], 'Ensure the functionality provided by moving the mouse on this element is available through the keyboard.', 'MouseMove'); } var mouseDownEls = HTMLCS.util.getAllElements(top, '*[onmousedown]'); for (var i = 0; i < mouseDownEls.length; i++) { HTMLCS.addMessage(HTMLCS.WARNING, mouseDownEls[i], 'Ensure the functionality provided by mousing down on this element is available through the keyboard; for instance, using the keydown event.', 'MouseDown'); } var mouseUpEls = HTMLCS.util.getAllElements(top, '*[onmouseup]'); for (var i = 0; i < mouseUpEls.length; i++) { HTMLCS.addMessage(HTMLCS.WARNING, mouseUpEls[i], 'Ensure the functionality provided by mousing up on this element is available through the keyboard; for instance, using the keyup event.', 'MouseUp'); } } };