- commit
- 5199cd518f15867d6a59e190226a91fae6658c1c
- parent
- 3d70b8b1eefe06c3c0e120cb3cc97b86d856b7f9
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2025-08-06 21:43
build
Diffstat
| M | babel.js | 4878 | ++----------------------------------------------------------- |
1 files changed, 83 insertions, 4795 deletions
diff --git a/babel.js b/babel.js
@@ -264,4695 +264,6 @@ exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : 264 264 }; 265 265 }).call(this)}).call(this,require("timers").setImmediate,require("timers").clearImmediate) 266 266 },{"process/browser.js":1,"timers":2}],3:[function(require,module,exports){267 -1 // Copyright 2012 Google Inc.268 -1 //269 -1 // Licensed under the Apache License, Version 2.0 (the "License");270 -1 // you may not use this file except in compliance with the License.271 -1 // You may obtain a copy of the License at272 -1 //273 -1 // http://www.apache.org/licenses/LICENSE-2.0274 -1 //275 -1 // Unless required by applicable law or agreed to in writing, software276 -1 // distributed under the License is distributed on an "AS IS" BASIS,277 -1 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.278 -1 // See the License for the specific language governing permissions and279 -1 // limitations under the License.280 -1281 -1 goog.require('axs.browserUtils');282 -1 goog.require('axs.color');283 -1 goog.require('axs.color.Color');284 -1 goog.require('axs.constants');285 -1 goog.require('axs.dom');286 -1287 -1 goog.provide('axs.utils');288 -1289 -1 /**290 -1 * @const291 -1 * @type {string}292 -1 */293 -1 axs.utils.FOCUSABLE_ELEMENTS_SELECTOR =294 -1 'input:not([type=hidden]):not([disabled]),' +295 -1 'select:not([disabled]),' +296 -1 'textarea:not([disabled]),' +297 -1 'button:not([disabled]),' +298 -1 'a[href],' +299 -1 'iframe,' +300 -1 '[tabindex]';301 -1302 -1 /**303 -1 * Elements that can have labels: https://html.spec.whatwg.org/multipage/forms.html#category-label304 -1 * @const305 -1 * @type {string}306 -1 */307 -1 axs.utils.LABELABLE_ELEMENTS_SELECTOR =308 -1 'button,' +309 -1 'input:not([type=hidden]),' +310 -1 'keygen,' +311 -1 'meter,' +312 -1 'output,' +313 -1 'progress,' +314 -1 'select,' +315 -1 'textarea';316 -1317 -1318 -1 /**319 -1 * @param {Element} element320 -1 * @return {boolean}321 -1 */322 -1 axs.utils.elementIsTransparent = function(element) {323 -1 return element.style.opacity == '0';324 -1 };325 -1326 -1 /**327 -1 * @param {Element} element328 -1 * @return {boolean}329 -1 */330 -1 axs.utils.elementHasZeroArea = function(element) {331 -1 var rect = element.getBoundingClientRect();332 -1 var width = rect.right - rect.left;333 -1 var height = rect.top - rect.bottom;334 -1 if (!width || !height)335 -1 return true;336 -1 return false;337 -1 };338 -1339 -1 /**340 -1 * @param {Element} element341 -1 * @return {boolean}342 -1 */343 -1 axs.utils.elementIsOutsideScrollArea = function(element) {344 -1 var parent = axs.dom.parentElement(element);345 -1346 -1 var defaultView = element.ownerDocument.defaultView;347 -1 while (parent != defaultView.document.body) {348 -1 if (axs.utils.isClippedBy(element, parent))349 -1 return true;350 -1351 -1 if (axs.utils.canScrollTo(element, parent) && !axs.utils.elementIsOutsideScrollArea(parent))352 -1 return false;353 -1354 -1 parent = axs.dom.parentElement(parent);355 -1 }356 -1357 -1 return !axs.utils.canScrollTo(element, defaultView.document.body);358 -1 };359 -1360 -1 /**361 -1 * Checks whether it's possible to scroll to the given element within the given container.362 -1 * Assumes that |container| is an ancestor of |element|.363 -1 * If |container| cannot be scrolled, returns True if the element is within its bounding client364 -1 * rect.365 -1 * @param {Element} element366 -1 * @param {Element} container367 -1 * @return {boolean} True iff it's possible to scroll to |element| within |container|.368 -1 */369 -1 axs.utils.canScrollTo = function(element, container) {370 -1 var rect = element.getBoundingClientRect();371 -1 var containerRect = container.getBoundingClientRect();372 -1 if (container == container.ownerDocument.body) {373 -1 var absoluteTop = containerRect.top;374 -1 var absoluteLeft = containerRect.left;375 -1 } else {376 -1 var absoluteTop = containerRect.top - container.scrollTop;377 -1 var absoluteLeft = containerRect.left - container.scrollLeft;378 -1 }379 -1 var containerScrollArea =380 -1 { top: absoluteTop,381 -1 bottom: absoluteTop + container.scrollHeight,382 -1 left: absoluteLeft,383 -1 right: absoluteLeft + container.scrollWidth };384 -1385 -1 if (rect.right < containerScrollArea.left || rect.bottom < containerScrollArea.top ||386 -1 rect.left > containerScrollArea.right || rect.top > containerScrollArea.bottom) {387 -1 return false;388 -1 }389 -1390 -1 var defaultView = element.ownerDocument.defaultView;391 -1 var style = defaultView.getComputedStyle(container);392 -1393 -1 if (rect.left > containerRect.right || rect.top > containerRect.bottom) {394 -1 return (style.overflow == 'scroll' || style.overflow == 'auto' ||395 -1 container instanceof defaultView.HTMLBodyElement);396 -1 }397 -1398 -1 return true;399 -1 };400 -1401 -1 /**402 -1 * Checks whether the given element is clipped by the given container.403 -1 * Assumes that |container| is an ancestor of |element|.404 -1 * @param {Element} element405 -1 * @param {Element} container406 -1 * @return {boolean} True iff |element| is clipped by |container|.407 -1 */408 -1 axs.utils.isClippedBy = function(element, container) {409 -1 var rect = element.getBoundingClientRect();410 -1 var containerRect = container.getBoundingClientRect();411 -1 var containerTop = containerRect.top;412 -1 var containerLeft = containerRect.left;413 -1 var containerScrollArea =414 -1 { top: containerTop - container.scrollTop,415 -1 bottom: containerTop - container.scrollTop + container.scrollHeight,416 -1 left: containerLeft - container.scrollLeft,417 -1 right: containerLeft - container.scrollLeft + container.scrollWidth };418 -1419 -1 var defaultView = element.ownerDocument.defaultView;420 -1 var style = defaultView.getComputedStyle(container);421 -1422 -1 if ((rect.right < containerRect.left || rect.bottom < containerRect.top ||423 -1 rect.left > containerRect.right || rect.top > containerRect.bottom) &&424 -1 style.overflow == 'hidden') {425 -1 return true;426 -1 }427 -1428 -1 if (rect.right < containerScrollArea.left || rect.bottom < containerScrollArea.top)429 -1 return (style.overflow != 'visible');430 -1431 -1 return false;432 -1 };433 -1434 -1 /**435 -1 * @param {Node} ancestor A potential ancestor of |node|.436 -1 * @param {Node} node437 -1 * @return {boolean} true if |ancestor| is an ancestor of |node| (including438 -1 * |ancestor| === |node|).439 -1 */440 -1 axs.utils.isAncestor = function(ancestor, node) {441 -1 if (node == null)442 -1 return false;443 -1 if (node === ancestor)444 -1 return true;445 -1446 -1 var parentNode = axs.dom.composedParentNode(node);447 -1 return axs.utils.isAncestor(ancestor, parentNode);448 -1 };449 -1450 -1 /**451 -1 * @param {Element} element452 -1 * @return {Array.<Element>} An array of any non-transparent elements which453 -1 * overlap the given element.454 -1 */455 -1 axs.utils.overlappingElements = function(element) {456 -1 if (axs.utils.elementHasZeroArea(element))457 -1 return null;458 -1459 -1 var overlappingElements = [];460 -1 var clientRects = element.getClientRects();461 -1 for (var i = 0; i < clientRects.length; i++) {462 -1 var rect = clientRects[i];463 -1 var center_x = (rect.left + rect.right) / 2;464 -1 var center_y = (rect.top + rect.bottom) / 2;465 -1 var elementAtPoint = document.elementFromPoint(center_x, center_y);466 -1467 -1 if (elementAtPoint == null || elementAtPoint == element ||468 -1 axs.utils.isAncestor(elementAtPoint, element) ||469 -1 axs.utils.isAncestor(element, elementAtPoint)) {470 -1 continue;471 -1 }472 -1473 -1 var overlappingElementStyle = window.getComputedStyle(elementAtPoint, null);474 -1 if (!overlappingElementStyle)475 -1 continue;476 -1477 -1 var overlappingElementBg = axs.utils.getBgColor(overlappingElementStyle,478 -1 elementAtPoint);479 -1 if (overlappingElementBg && overlappingElementBg.alpha > 0 &&480 -1 overlappingElements.indexOf(elementAtPoint) < 0) {481 -1 overlappingElements.push(elementAtPoint);482 -1 }483 -1 }484 -1485 -1 return overlappingElements;486 -1 };487 -1488 -1 /**489 -1 * @param {Element} element490 -1 * @return {boolean}491 -1 */492 -1 axs.utils.elementIsHtmlControl = function(element) {493 -1 var defaultView = element.ownerDocument.defaultView;494 -1495 -1 // HTML control496 -1 if (element instanceof defaultView.HTMLButtonElement)497 -1 return true;498 -1 if (element instanceof defaultView.HTMLInputElement)499 -1 return true;500 -1 if (element instanceof defaultView.HTMLSelectElement)501 -1 return true;502 -1 if (element instanceof defaultView.HTMLTextAreaElement)503 -1 return true;504 -1505 -1 return false;506 -1 };507 -1508 -1 /**509 -1 * @param {Element} element510 -1 * @return {boolean}511 -1 */512 -1 axs.utils.elementIsAriaWidget = function(element) {513 -1 if (element.hasAttribute('role')) {514 -1 var roleValue = element.getAttribute('role');515 -1 // TODO is this correct?516 -1 if (roleValue) {517 -1 var role = axs.constants.ARIA_ROLES[roleValue];518 -1 if (role && 'widget' in role['allParentRolesSet'])519 -1 return true;520 -1 }521 -1 }522 -1 return false;523 -1 };524 -1525 -1 /**526 -1 * @param {Element} element527 -1 * @return {boolean}528 -1 */529 -1 axs.utils.elementIsVisible = function(element) {530 -1 if (axs.utils.elementIsTransparent(element))531 -1 return false;532 -1 if (axs.utils.elementHasZeroArea(element))533 -1 return false;534 -1 if (axs.utils.elementIsOutsideScrollArea(element))535 -1 return false;536 -1537 -1 var overlappingElements = axs.utils.overlappingElements(element);538 -1 if (overlappingElements.length)539 -1 return false;540 -1541 -1 return true;542 -1 };543 -1544 -1 /**545 -1 * @param {CSSStyleDeclaration} style546 -1 * @return {boolean}547 -1 */548 -1 axs.utils.isLargeFont = function(style) {549 -1 var fontSize = style.fontSize;550 -1 var bold = style.fontWeight == 'bold';551 -1 var matches = fontSize.match(/(\d+)px/);552 -1 if (matches) {553 -1 var fontSizePx = parseInt(matches[1], 10);554 -1 var bodyStyle = window.getComputedStyle(document.body, null);555 -1 var bodyFontSize = bodyStyle.fontSize;556 -1 matches = bodyFontSize.match(/(\d+)px/);557 -1 if (matches) {558 -1 var bodyFontSizePx = parseInt(matches[1], 10);559 -1 var boldLarge = bodyFontSizePx * 1.2;560 -1 var large = bodyFontSizePx * 1.5;561 -1 } else {562 -1 var boldLarge = 19.2;563 -1 var large = 24;564 -1 }565 -1 return (bold && fontSizePx >= boldLarge || fontSizePx >= large);566 -1 }567 -1 matches = fontSize.match(/(\d+)em/);568 -1 if (matches) {569 -1 var fontSizeEm = parseInt(matches[1], 10);570 -1 if (bold && fontSizeEm >= 1.2 || fontSizeEm >= 1.5)571 -1 return true;572 -1 return false;573 -1 }574 -1 matches = fontSize.match(/(\d+)%/);575 -1 if (matches) {576 -1 var fontSizePercent = parseInt(matches[1], 10);577 -1 if (bold && fontSizePercent >= 120 || fontSizePercent >= 150)578 -1 return true;579 -1 return false;580 -1 }581 -1 matches = fontSize.match(/(\d+)pt/);582 -1 if (matches) {583 -1 var fontSizePt = parseInt(matches[1], 10);584 -1 if (bold && fontSizePt >= 14 || fontSizePt >= 18)585 -1 return true;586 -1 return false;587 -1 }588 -1 return false;589 -1 };590 -1591 -1 /**592 -1 * @param {CSSStyleDeclaration} style593 -1 * @param {Element} element594 -1 * @return {?axs.color.Color}595 -1 */596 -1 axs.utils.getBgColor = function(style, element) {597 -1 var bgColorString = style.backgroundColor;598 -1 var bgColor = axs.color.parseColor(bgColorString);599 -1 if (!bgColor)600 -1 return null;601 -1602 -1 if (style.opacity < 1)603 -1 bgColor.alpha = bgColor.alpha * style.opacity;604 -1605 -1 if (bgColor.alpha < 1) {606 -1 var parentBg = axs.utils.getParentBgColor(element);607 -1 if (parentBg == null)608 -1 return null;609 -1610 -1 bgColor = axs.color.flattenColors(bgColor, parentBg);611 -1 }612 -1 return bgColor;613 -1 };614 -1615 -1 /**616 -1 * Gets the effective background color of the parent of |element|.617 -1 * @param {Element} element618 -1 * @return {?axs.color.Color}619 -1 */620 -1 axs.utils.getParentBgColor = function(element) {621 -1 /** @type {Element} */ var parent = element;622 -1 var bgStack = [];623 -1 var foundSolidColor = null;624 -1 while ((parent = axs.dom.parentElement(parent))) {625 -1 var computedStyle = window.getComputedStyle(parent, null);626 -1 if (!computedStyle)627 -1 continue;628 -1629 -1 var parentBg = axs.color.parseColor(computedStyle.backgroundColor);630 -1 if (!parentBg)631 -1 continue;632 -1633 -1 if (computedStyle.opacity < 1)634 -1 parentBg.alpha = parentBg.alpha * computedStyle.opacity;635 -1636 -1 if (parentBg.alpha == 0)637 -1 continue;638 -1639 -1 bgStack.push(parentBg);640 -1641 -1 if (parentBg.alpha == 1) {642 -1 foundSolidColor = true;643 -1 break;644 -1 }645 -1 }646 -1647 -1 if (!foundSolidColor)648 -1 bgStack.push(new axs.color.Color(255, 255, 255, 1));649 -1650 -1 var bg = bgStack.pop();651 -1 while (bgStack.length) {652 -1 var fg = bgStack.pop();653 -1 bg = axs.color.flattenColors(fg, bg);654 -1 }655 -1 return bg;656 -1 };657 -1658 -1 /**659 -1 * @param {CSSStyleDeclaration} style660 -1 * @param {Element} element661 -1 * @param {axs.color.Color} bgColor The background color, which may come from662 -1 * another element (such as a parent element), for flattening into the663 -1 * foreground color.664 -1 * @return {?axs.color.Color}665 -1 */666 -1 axs.utils.getFgColor = function(style, element, bgColor) {667 -1 var fgColorString = style.color;668 -1 var fgColor = axs.color.parseColor(fgColorString);669 -1 if (!fgColor)670 -1 return null;671 -1672 -1 if (fgColor.alpha < 1)673 -1 fgColor = axs.color.flattenColors(fgColor, bgColor);674 -1675 -1 if (style.opacity < 1) {676 -1 var parentBg = axs.utils.getParentBgColor(element);677 -1 fgColor.alpha = fgColor.alpha * style.opacity;678 -1 fgColor = axs.color.flattenColors(fgColor, parentBg);679 -1 }680 -1681 -1 return fgColor;682 -1 };683 -1684 -1 /**685 -1 * @param {Element} element686 -1 * @return {?number}687 -1 */688 -1 axs.utils.getContrastRatioForElement = function(element) {689 -1 var style = window.getComputedStyle(element, null);690 -1 return axs.utils.getContrastRatioForElementWithComputedStyle(style, element);691 -1 };692 -1693 -1 /**694 -1 * @param {CSSStyleDeclaration} style695 -1 * @param {Element} element696 -1 * @return {?number}697 -1 */698 -1 axs.utils.getContrastRatioForElementWithComputedStyle = function(style, element) {699 -1 if (axs.utils.isElementHidden(element))700 -1 return null;701 -1702 -1 var bgColor = axs.utils.getBgColor(style, element);703 -1 if (!bgColor)704 -1 return null;705 -1706 -1 var fgColor = axs.utils.getFgColor(style, element, bgColor);707 -1 if (!fgColor)708 -1 return null;709 -1710 -1 return axs.color.calculateContrastRatio(fgColor, bgColor);711 -1 };712 -1713 -1 /**714 -1 * @param {Element} element715 -1 * @return {boolean}716 -1 */717 -1 axs.utils.isNativeTextElement = function(element) {718 -1 var tagName = element.tagName.toLowerCase();719 -1 var type = element.type ? element.type.toLowerCase() : '';720 -1 if (tagName == 'textarea')721 -1 return true;722 -1 if (tagName != 'input')723 -1 return false;724 -1725 -1 switch (type) {726 -1 case 'email':727 -1 case 'number':728 -1 case 'password':729 -1 case 'search':730 -1 case 'text':731 -1 case 'tel':732 -1 case 'url':733 -1 case '':734 -1 return true;735 -1 default:736 -1 return false;737 -1 }738 -1 };739 -1740 -1 /**741 -1 * @param {number} contrastRatio742 -1 * @param {CSSStyleDeclaration} style743 -1 * @param {boolean=} opt_strict Whether to use AA (false) or AAA (true) level744 -1 * @return {boolean}745 -1 */746 -1 axs.utils.isLowContrast = function(contrastRatio, style, opt_strict) {747 -1 // Round to nearest 0.1748 -1 var roundedContrastRatio = (Math.round(contrastRatio * 10) / 10);749 -1 if (!opt_strict) {750 -1 return roundedContrastRatio < 3.0 ||751 -1 (!axs.utils.isLargeFont(style) && roundedContrastRatio < 4.5);752 -1 } else {753 -1 return roundedContrastRatio < 4.5 ||754 -1 (!axs.utils.isLargeFont(style) && roundedContrastRatio < 7.0);755 -1 }756 -1 };757 -1758 -1 /**759 -1 * @param {Element} element760 -1 * @return {boolean}761 -1 */762 -1 axs.utils.hasLabel = function(element) {763 -1 var tagName = element.tagName.toLowerCase();764 -1 var type = element.type ? element.type.toLowerCase() : '';765 -1766 -1 if (element.hasAttribute('aria-label'))767 -1 return true;768 -1 if (element.hasAttribute('title'))769 -1 return true;770 -1 if (tagName == 'img' && element.hasAttribute('alt'))771 -1 return true;772 -1 if (tagName == 'input' && type == 'image' && element.hasAttribute('alt'))773 -1 return true;774 -1 if (tagName == 'input' && (type == 'submit' || type == 'reset'))775 -1 return true;776 -1777 -1 // There's a separate audit that makes sure this points to an actual element or elements.778 -1 if (element.hasAttribute('aria-labelledby'))779 -1 return true;780 -1781 -1 if (element.hasAttribute('id')) {782 -1 var labelsFor = document.querySelectorAll('label[for="' + element.id + '"]');783 -1 if (labelsFor.length > 0)784 -1 return true;785 -1 }786 -1787 -1 var parent = axs.dom.parentElement(element);788 -1 while (parent) {789 -1 if (parent.tagName.toLowerCase() == 'label') {790 -1 var parentLabel = /** HTMLLabelElement */ parent;791 -1 if (parentLabel.control == element)792 -1 return true;793 -1 }794 -1 parent = axs.dom.parentElement(parent);795 -1 }796 -1 return false;797 -1 };798 -1799 -1 /**800 -1 * Determine if this element natively supports being disabled (i.e. via the `disabled` attribute.801 -1 * Disabled here means that the element should be considered disabled according to specification.802 -1 * This element may or may not be effectively disabled in practice as this is dependent on implementation.803 -1 *804 -1 * @param {Element} element An element to check.805 -1 * @return {boolean} true If the element supports being natively disabled.806 -1 */807 -1 axs.utils.isNativelyDisableable = function(element) {808 -1 var tagName = element.tagName.toUpperCase();809 -1 return (tagName in axs.constants.NATIVELY_DISABLEABLE);810 -1 };811 -1812 -1 /**813 -1 * Determine if this element is disabled directly or indirectly by a disabled ancestor.814 -1 * Disabled here means that the element should be considered disabled according to specification.815 -1 * This element may or may not be effectively disabled in practice as this is dependent on implementation.816 -1 *817 -1 * @param {Element} element An element to check.818 -1 * @param {boolean=} ignoreAncestors If true do not check for disabled ancestors.819 -1 * @return {boolean} true if the element or one of its ancestors is disabled.820 -1 */821 -1 axs.utils.isElementDisabled = function(element, ignoreAncestors) {822 -1 var selector = ignoreAncestors ? '[aria-disabled=true]' : '[aria-disabled=true], [aria-disabled=true] *';823 -1 if (axs.browserUtils.matchSelector(element, selector)) {824 -1 return true;825 -1 }826 -1 if (!axs.utils.isNativelyDisableable(element) ||827 -1 axs.browserUtils.matchSelector(element, 'fieldset>legend:first-of-type *')) {828 -1 return false;829 -1 }830 -1 for (var next = element; next !== null; next = axs.dom.parentElement(next)) {831 -1 if (next.hasAttribute('disabled')) {832 -1 return true;833 -1 }834 -1 if (ignoreAncestors) {835 -1 return false;836 -1 }837 -1 }838 -1 return false;839 -1 };840 -1841 -1 /**842 -1 * @param {Element} element An element to check.843 -1 * @return {boolean} True if the element is hidden from accessibility.844 -1 */845 -1 axs.utils.isElementHidden = function(element) {846 -1 if (!(element instanceof element.ownerDocument.defaultView.HTMLElement))847 -1 return false;848 -1849 -1 if (element.hasAttribute('chromevoxignoreariahidden'))850 -1 var chromevoxignoreariahidden = true;851 -1852 -1 var style = window.getComputedStyle(element, null);853 -1 if (style.display == 'none' || style.visibility == 'hidden')854 -1 return true;855 -1856 -1 if (element.hasAttribute('aria-hidden') &&857 -1 element.getAttribute('aria-hidden').toLowerCase() == 'true') {858 -1 return !chromevoxignoreariahidden;859 -1 }860 -1861 -1 return false;862 -1 };863 -1864 -1 /**865 -1 * @param {Element} element An element to check.866 -1 * @return {boolean} True if the element or one of its ancestors is867 -1 * hidden from accessibility.868 -1 */869 -1 axs.utils.isElementOrAncestorHidden = function(element) {870 -1 if (axs.utils.isElementHidden(element))871 -1 return true;872 -1873 -1 if (axs.dom.parentElement(element))874 -1 return axs.utils.isElementOrAncestorHidden(axs.dom.parentElement(element));875 -1 else876 -1 return false;877 -1 };878 -1879 -1 /**880 -1 * @param {Element} element An element to check881 -1 * @return {boolean} True if the given element is an inline element, false882 -1 * otherwise.883 -1 */884 -1 axs.utils.isInlineElement = function(element) {885 -1 var tagName = element.tagName.toUpperCase();886 -1 return axs.constants.InlineElements[tagName];887 -1 };888 -1889 -1 /**890 -1 *891 -1 * Gets role details from an element.892 -1 * @param {Element} element The DOM element whose role we want.893 -1 * @param {boolean=} implicit if true then implicit semantics will be considered if there is no role attribute.894 -1 *895 -1 * @return {Object}896 -1 */897 -1 axs.utils.getRoles = function(element, implicit) {898 -1 if (!element || element.nodeType !== Node.ELEMENT_NODE || (!element.hasAttribute('role') && !implicit))899 -1 return null;900 -1 var roleValue = element.getAttribute('role');901 -1 if (!roleValue && implicit)902 -1 roleValue = axs.properties.getImplicitRole(element);903 -1 if (!roleValue) // role='' or implicit role came up empty904 -1 return null;905 -1 var roleNames = roleValue.split(' ');906 -1 var result = { roles: [], valid: false };907 -1 for (var i = 0; i < roleNames.length; i++) {908 -1 var role = roleNames[i];909 -1 var ariaRole = axs.constants.ARIA_ROLES[role];910 -1 var roleObject = { 'name': role };911 -1 if (ariaRole && !ariaRole.abstract) {912 -1 roleObject.details = ariaRole;913 -1 if (!result.applied) {914 -1 result.applied = roleObject;915 -1 }916 -1 roleObject.valid = result.valid = true;917 -1 } else {918 -1 roleObject.valid = false;919 -1 }920 -1 result.roles.push(roleObject);921 -1 }922 -1923 -1 return result;924 -1 };925 -1926 -1 /**927 -1 * @param {!string} propertyName928 -1 * @param {!string} value929 -1 * @param {!Element} element930 -1 * @return {!Object}931 -1 */932 -1 axs.utils.getAriaPropertyValue = function(propertyName, value, element) {933 -1 var propertyKey = propertyName.replace(/^aria-/, '');934 -1 var property = axs.constants.ARIA_PROPERTIES[propertyKey];935 -1 var result = { 'name': propertyName, 'rawValue': value };936 -1 if (!property) {937 -1 result.valid = false;938 -1 result.reason = '"' + propertyName + '" is not a valid ARIA property';939 -1 return result;940 -1 }941 -1942 -1 var propertyType = property.valueType;943 -1 if (!propertyType) {944 -1 result.valid = false;945 -1 result.reason = '"' + propertyName + '" is not a valid ARIA property';946 -1 return result;947 -1 }948 -1949 -1 switch (propertyType) {950 -1 case "idref":951 -1 var isValid = axs.utils.isValidIDRefValue(value, element);952 -1 result.valid = isValid.valid;953 -1 result.reason = isValid.reason;954 -1 result.idref = isValid.idref;955 -1 // falls through956 -1 case "idref_list":957 -1 var idrefValues = value.split(/\s+/);958 -1 result.valid = true;959 -1 for (var i = 0; i < idrefValues.length; i++) {960 -1 var refIsValid = axs.utils.isValidIDRefValue(idrefValues[i], element);961 -1 if (!refIsValid.valid)962 -1 result.valid = false;963 -1 if (result.values)964 -1 result.values.push(refIsValid);965 -1 else966 -1 result.values = [refIsValid];967 -1 }968 -1 return result;969 -1 case "integer":970 -1 var validNumber = axs.utils.isValidNumber(value);971 -1 if (!validNumber.valid) {972 -1 result.valid = false;973 -1 result.reason = validNumber.reason;974 -1 return result;975 -1 }976 -1 if (Math.floor(validNumber.value) !== validNumber.value) {977 -1 result.valid = false;978 -1 result.reason = '' + value + ' is not a whole integer';979 -1 } else {980 -1 result.valid = true;981 -1 result.value = validNumber.value;982 -1 }983 -1 return result;984 -1 case "decimal":985 -1 case "number":986 -1 var validNumber = axs.utils.isValidNumber(value);987 -1 result.valid = validNumber.valid;988 -1 if (!validNumber.valid) {989 -1 result.reason = validNumber.reason;990 -1 return result;991 -1 }992 -1 result.value = validNumber.value;993 -1 return result;994 -1 case "string":995 -1 result.valid = true;996 -1 result.value = value;997 -1 return result;998 -1 case "token":999 -1 var validTokenValue = axs.utils.isValidTokenValue(propertyName, value.toLowerCase());1000 -1 if (validTokenValue.valid) {1001 -1 result.valid = true;1002 -1 result.value = validTokenValue.value;1003 -1 return result;1004 -1 } else {1005 -1 result.valid = false;1006 -1 result.value = value;1007 -1 result.reason = validTokenValue.reason;1008 -1 return result;1009 -1 }1010 -1 // falls through1011 -1 case "token_list":1012 -1 var tokenValues = value.split(/\s+/);1013 -1 result.valid = true;1014 -1 for (var i = 0; i < tokenValues.length; i++) {1015 -1 var validTokenValue = axs.utils.isValidTokenValue(propertyName, tokenValues[i].toLowerCase());1016 -1 if (!validTokenValue.valid) {1017 -1 result.valid = false;1018 -1 if (result.reason) {1019 -1 result.reason = [ result.reason ];1020 -1 result.reason.push(validTokenValue.reason);1021 -1 } else {1022 -1 result.reason = validTokenValue.reason;1023 -1 result.possibleValues = validTokenValue.possibleValues;1024 -1 }1025 -1 }1026 -1 // TODO (more structured result)1027 -1 if (result.values)1028 -1 result.values.push(validTokenValue.value);1029 -1 else1030 -1 result.values = [validTokenValue.value];1031 -1 }1032 -1 return result;1033 -1 case "tristate":1034 -1 var validTristate = axs.utils.isPossibleValue(value.toLowerCase(), axs.constants.MIXED_VALUES, propertyName);1035 -1 if (validTristate.valid) {1036 -1 result.valid = true;1037 -1 result.value = validTristate.value;1038 -1 } else {1039 -1 result.valid = false;1040 -1 result.value = value;1041 -1 result.reason = validTristate.reason;1042 -1 }1043 -1 return result;1044 -1 case "boolean":1045 -1 var validBoolean = axs.utils.isValidBoolean(value);1046 -1 if (validBoolean.valid) {1047 -1 result.valid = true;1048 -1 result.value = validBoolean.value;1049 -1 } else {1050 -1 result.valid = false;1051 -1 result.value = value;1052 -1 result.reason = validBoolean.reason;1053 -1 }1054 -1 return result;1055 -1 }1056 -1 result.valid = false;1057 -1 result.reason = 'Not a valid ARIA property';1058 -1 return result;1059 -1 };1060 -11061 -1 /**1062 -1 * @param {string} propertyName The name of the property.1063 -1 * @param {string} value The value to check.1064 -1 * @return {!Object}1065 -1 */1066 -1 axs.utils.isValidTokenValue = function(propertyName, value) {1067 -1 var propertyKey = propertyName.replace(/^aria-/, '');1068 -1 var propertyDetails = axs.constants.ARIA_PROPERTIES[propertyKey];1069 -1 var possibleValues = propertyDetails.valuesSet;1070 -1 return axs.utils.isPossibleValue(value, possibleValues, propertyName);1071 -1 };1072 -11073 -1 /**1074 -1 * @param {string} value1075 -1 * @param {Object.<string, boolean>} possibleValues1076 -1 * @param {string} propertyName The name of the property.1077 -1 * @return {!Object}1078 -1 */1079 -1 axs.utils.isPossibleValue = function(value, possibleValues, propertyName) {1080 -1 if (!possibleValues[value])1081 -1 return { 'valid': false,1082 -1 'value': value,1083 -1 'reason': '"' + value + '" is not a valid value for ' + propertyName,1084 -1 'possibleValues': Object.keys(possibleValues) };1085 -1 return { 'valid': true, 'value': value };1086 -1 };1087 -11088 -1 /**1089 -1 * @param {string} value1090 -1 * @return {!Object}1091 -1 */1092 -1 axs.utils.isValidBoolean = function(value) {1093 -1 try {1094 -1 var parsedValue = JSON.parse(value);1095 -1 } catch (e) {1096 -1 parsedValue = '';1097 -1 }1098 -1 if (typeof(parsedValue) != 'boolean')1099 -1 return { 'valid': false,1100 -1 'value': value,1101 -1 'reason': '"' + value + '" is not a true/false value' };1102 -1 return { 'valid': true, 'value': parsedValue };1103 -1 };1104 -11105 -1 /**1106 -1 * @param {string} value1107 -1 * @param {!Element} element1108 -1 * @return {!Object}1109 -1 */1110 -1 axs.utils.isValidIDRefValue = function(value, element) {1111 -1 if (value.length == 0)1112 -1 return { 'valid': true, 'idref': value };1113 -1 if (!element.ownerDocument.getElementById(value))1114 -1 return { 'valid': false,1115 -1 'idref': value,1116 -1 'reason': 'No element with ID "' + value + '"' };1117 -1 return { 'valid': true, 'idref': value };1118 -1 };1119 -11120 -1 /**1121 -1 * Tests if a number is real number for a11y purposes.1122 -1 * Must be a real, numerical, decimal value; heavily inspired by1123 -1 * http://www.w3.org/TR/wai-aria/states_and_properties#valuetype_number1124 -1 * @param {string} value1125 -1 * @return {!Object}1126 -1 */1127 -1 axs.utils.isValidNumber = function(value) {1128 -1 var failResult = {1129 -1 'valid': false,1130 -1 'value': value,1131 -1 'reason': '"' + value + '" is not a number'1132 -1 };1133 -1 if (!value) {1134 -1 return failResult;1135 -1 }1136 -1 if (/^0x/i.test(value)) {1137 -1 failResult.reason = '"' + value + '" is not a decimal number'; // hex is not accepted1138 -1 return failResult;1139 -1 }1140 -1 var parsedValue = value * 1;1141 -1 if (!isFinite(parsedValue)) {1142 -1 return failResult;1143 -1 }1144 -1 return { 'valid': true, 'value': parsedValue };1145 -1 };1146 -11147 -1 /**1148 -1 * @param {Element} element1149 -1 * @return {boolean}1150 -1 */1151 -1 axs.utils.isElementImplicitlyFocusable = function(element) {1152 -1 var defaultView = element.ownerDocument.defaultView;1153 -11154 -1 if (element instanceof defaultView.HTMLAnchorElement ||1155 -1 element instanceof defaultView.HTMLAreaElement)1156 -1 return element.hasAttribute('href');1157 -1 if (element instanceof defaultView.HTMLInputElement ||1158 -1 element instanceof defaultView.HTMLSelectElement ||1159 -1 element instanceof defaultView.HTMLTextAreaElement ||1160 -1 element instanceof defaultView.HTMLButtonElement ||1161 -1 element instanceof defaultView.HTMLIFrameElement)1162 -1 return !element.disabled;1163 -1 return false;1164 -1 };1165 -11166 -1 /**1167 -1 * Returns an array containing the values of the given JSON-compatible object.1168 -1 * (Simply ignores any function values.)1169 -1 * @param {Object} obj1170 -1 * @return {Array}1171 -1 */1172 -1 axs.utils.values = function(obj) {1173 -1 var values = [];1174 -1 for (var key in obj) {1175 -1 if (obj.hasOwnProperty(key) && typeof obj[key] != 'function')1176 -1 values.push(obj[key]);1177 -1 }1178 -1 return values;1179 -1 };1180 -11181 -1 /**1182 -1 * Returns an object containing the same keys and values as the given1183 -1 * JSON-compatible object. (Simply ignores any function values.)1184 -1 * @param {Object} obj1185 -1 * @return {Object}1186 -1 */1187 -1 axs.utils.namedValues = function(obj) {1188 -1 var values = {};1189 -1 for (var key in obj) {1190 -1 if (obj.hasOwnProperty(key) && typeof obj[key] != 'function')1191 -1 values[key] = obj[key];1192 -1 }1193 -1 return values;1194 -1 };1195 -11196 -1 /**1197 -1 * Escapes a given ID to be used in a CSS selector1198 -1 *1199 -1 * @private1200 -1 * @param {!string} id The ID to be escaped1201 -1 * @return {string} The escaped ID1202 -1 */1203 -1 function escapeId(id) {1204 -1 return id.replace(/[^a-zA-Z0-9_-]/g,function(match) { return '\\' + match; });1205 -1 }1206 -11207 -1 /** Gets a CSS selector text for a DOM object.1208 -1 * @param {Node} obj The DOM object.1209 -1 * @return {string} CSS selector text for the DOM object.1210 -1 */1211 -1 axs.utils.getQuerySelectorText = function(obj) {1212 -1 if (obj == null || obj.tagName == 'HTML') {1213 -1 return 'html';1214 -1 } else if (obj.tagName == 'BODY') {1215 -1 return 'body';1216 -1 }1217 -11218 -1 if (obj.hasAttribute) {1219 -1 if (obj.id) {1220 -1 return '#' + escapeId(obj.id);1221 -1 }1222 -11223 -1 if (obj.className) {1224 -1 var selector = '';1225 -1 for (var i = 0; i < obj.classList.length; i++)1226 -1 selector += '.' + obj.classList[i];1227 -11228 -1 var total = 0;1229 -1 if (obj.parentNode) {1230 -1 for (i = 0; i < obj.parentNode.children.length; i++) {1231 -1 var similar = obj.parentNode.children[i];1232 -1 if (axs.browserUtils.matchSelector(similar, selector))1233 -1 total++;1234 -1 if (similar === obj)1235 -1 break;1236 -1 }1237 -1 } else {1238 -1 total = 1;1239 -1 }1240 -11241 -1 if (total == 1) {1242 -1 return axs.utils.getQuerySelectorText(obj.parentNode) +1243 -1 ' > ' + selector;1244 -1 }1245 -1 }1246 -11247 -1 if (obj.parentNode) {1248 -1 var similarTags = obj.parentNode.children;1249 -1 var total = 1;1250 -1 var i = 0;1251 -1 while (similarTags[i] !== obj) {1252 -1 if (similarTags[i].tagName == obj.tagName) {1253 -1 total++;1254 -1 }1255 -1 i++;1256 -1 }1257 -11258 -1 var next = '';1259 -1 if (obj.parentNode.tagName != 'BODY') {1260 -1 next = axs.utils.getQuerySelectorText(obj.parentNode) +1261 -1 ' > ';1262 -1 }1263 -11264 -1 if (total == 1) {1265 -1 return next +1266 -1 obj.tagName;1267 -1 } else {1268 -1 return next +1269 -1 obj.tagName +1270 -1 ':nth-of-type(' + total + ')';1271 -1 }1272 -1 }1273 -11274 -1 } else if (obj.selectorText) {1275 -1 return obj.selectorText;1276 -1 }1277 -11278 -1 return '';1279 -1 };1280 -11281 -1 /**1282 -1 * Gets elements that refer to this element in an ARIA attribute that takes an ID reference list or1283 -1 * single ID reference.1284 -1 * @param {Element} element a potential referent.1285 -1 * @param {string=} opt_attributeName Name of an ARIA attribute to limit the results to, e.g. 'aria-owns'.1286 -1 * @return {NodeList} The elements that refer to this element or null.1287 -1 */1288 -1 axs.utils.getAriaIdReferrers = function(element, opt_attributeName) {1289 -1 var propertyToSelector = function(propertyKey) {1290 -1 var propertyDetails = axs.constants.ARIA_PROPERTIES[propertyKey];1291 -1 if (propertyDetails) {1292 -1 if (propertyDetails.valueType === ('idref')) {1293 -1 return '[aria-' + propertyKey + '=\'' + id + '\']';1294 -1 } else if (propertyDetails.valueType === ('idref_list')) {1295 -1 return '[aria-' + propertyKey + '~=\'' + id + '\']';1296 -1 }1297 -1 }1298 -1 return '';1299 -1 };1300 -1 if (!element)1301 -1 return null;1302 -1 var id = element.id;1303 -1 if (!id)1304 -1 return null;1305 -1 id = id.replace(/'/g, "\\'"); // make it safe to use in a selector1306 -11307 -1 if (opt_attributeName) {1308 -1 var propertyKey = opt_attributeName.replace(/^aria-/, '');1309 -1 var referrerQuery = propertyToSelector(propertyKey);1310 -1 if (referrerQuery) {1311 -1 return element.ownerDocument.querySelectorAll(referrerQuery);1312 -1 }1313 -1 } else {1314 -1 var selectors = [];1315 -1 for (var propertyKey in axs.constants.ARIA_PROPERTIES) {1316 -1 var referrerQuery = propertyToSelector(propertyKey);1317 -1 if (referrerQuery) {1318 -1 selectors.push(referrerQuery);1319 -1 }1320 -1 }1321 -1 return element.ownerDocument.querySelectorAll(selectors.join(','));1322 -1 }1323 -1 return null;1324 -1 };1325 -11326 -1 /**1327 -1 * Gets elements that refer to this element in an HTML attribute that takes an ID reference list or1328 -1 * single ID reference.1329 -1 * @param {Element} element a potential referent.1330 -1 * @return {NodeList} The elements that refer to this element.1331 -1 */1332 -1 axs.utils.getHtmlIdReferrers = function(element) {1333 -1 if (!element)1334 -1 return null;1335 -1 var id = element.id;1336 -1 if (!id)1337 -1 return null;1338 -1 id = id.replace(/'/g, "\\'"); // make it safe to use in a selector1339 -1 var selectorTemplates = [1340 -1 '[contextmenu=\'{id}\']',1341 -1 '[itemref~=\'{id}\']',1342 -1 'button[form=\'{id}\']',1343 -1 'button[menu=\'{id}\']',1344 -1 'fieldset[form=\'{id}\']',1345 -1 'input[form=\'{id}\']',1346 -1 'input[list=\'{id}\']',1347 -1 'keygen[form=\'{id}\']',1348 -1 'label[for=\'{id}\']',1349 -1 'label[form=\'{id}\']',1350 -1 'menuitem[command=\'{id}\']',1351 -1 'object[form=\'{id}\']',1352 -1 'output[for~=\'{id}\']',1353 -1 'output[form=\'{id}\']',1354 -1 'select[form=\'{id}\']',1355 -1 'td[headers~=\'{id}\']',1356 -1 'textarea[form=\'{id}\']',1357 -1 'tr[headers~=\'{id}\']'];1358 -1 var selectors = selectorTemplates.map(function(selector) {1359 -1 return selector.replace('\{id\}', id);1360 -1 });1361 -1 return element.ownerDocument.querySelectorAll(selectors.join(','));1362 -1 };1363 -11364 -1 /**1365 -1 * Gets a list of all IDs this element references in either ARIA or HTML attributes.1366 -1 *1367 -1 * @param {Element} element The element to check for idref attributes.1368 -1 * @returns {Array.<string>} Any IDs this element references.1369 -1 */1370 -1 axs.utils.getReferencedIds = function(element) {1371 -1 var result = [];1372 -1 var addResult = function(ids) {1373 -1 if (ids) {1374 -1 if (ids.indexOf(' ') > 0) {1375 -1 result = result.concat(attrib.value.split(' '));1376 -1 } else {1377 -1 result.push(ids);1378 -1 }1379 -1 }1380 -1 };1381 -1 for (var i = 0; i < element.attributes.length; i++) {1382 -1 var tagName = element.tagName.toLowerCase();1383 -1 var attrib = element.attributes[i];1384 -1 if (attrib.specified) {1385 -1 var attribName = attrib.name;1386 -1 var ariaAttr = attribName.match(/aria-(.+)/);1387 -1 if (ariaAttr) {1388 -1 var details = axs.constants.ARIA_PROPERTIES[ariaAttr[1]];1389 -1 if (details && (details.valueType === ('idref') || details.valueType === ('idref_list'))) {1390 -1 addResult(attrib.value);1391 -1 }1392 -1 continue;1393 -1 }1394 -1 switch (attribName) {1395 -1 case 'contextmenu':1396 -1 case 'itemref':1397 -1 addResult(attrib.value);1398 -1 break;1399 -1 case 'form':1400 -1 if (tagName == 'button' || tagName == 'fieldset' || tagName == 'input' ||1401 -1 tagName == 'keygen' || tagName == 'label' || tagName == 'object' ||1402 -1 tagName == 'output' || tagName == 'select' || tagName == 'textarea') {1403 -1 addResult(attrib.value);1404 -1 }1405 -1 break;1406 -1 case 'for':1407 -1 if (tagName == 'label' || tagName == 'output') {1408 -1 addResult(attrib.value);1409 -1 }1410 -1 break;1411 -1 case 'menu':1412 -1 if (tagName == 'button') {1413 -1 addResult(attrib.value);1414 -1 }1415 -1 break;1416 -1 case 'list':1417 -1 if (tagName == 'input') {1418 -1 addResult(attrib.value);1419 -1 }1420 -1 break;1421 -1 case 'command':1422 -1 if (tagName == 'menuitem') {1423 -1 addResult(attrib.value);1424 -1 }1425 -1 break;1426 -1 case 'headers':1427 -1 if (tagName == 'td' || tagName == 'tr') {1428 -1 addResult(attrib.value);1429 -1 }1430 -1 break;1431 -1 }1432 -1 }1433 -1 }1434 -1 return result;1435 -1 };1436 -11437 -1 /**1438 -1 * Gets elements that refer to this element in an attribute that takes an ID reference list or1439 -1 * single ID reference.1440 -1 * @param {Element} element a potential referent.1441 -1 * @return {Array<Element>} The elements that refer to this element.1442 -1 */1443 -1 axs.utils.getIdReferrers = function(element) {1444 -1 var result = [];1445 -1 var referrers = axs.utils.getHtmlIdReferrers(element);1446 -1 if (referrers) {1447 -1 result = result.concat(Array.prototype.slice.call(referrers));1448 -1 }1449 -1 referrers = axs.utils.getAriaIdReferrers(element);1450 -1 if (referrers) {1451 -1 result = result.concat(Array.prototype.slice.call(referrers));1452 -1 }1453 -1 return result;1454 -1 };1455 -11456 -1 /**1457 -1 * Gets elements which this element refers to in the given attribute.1458 -1 * @param {!string} attributeName Name of an ARIA attribute, e.g. 'aria-owns'.1459 -1 * @param {Element} element The DOM element which has the ARIA attribute.1460 -1 * @return {!Array.<Element>} An array of elements that are referred to by this element.1461 -1 * @example1462 -1 * var owner = document.body.appendChild(document.createElement("div"));1463 -1 * var owned = document.body.appendChild(document.createElement("div"));1464 -1 * owner.setAttribute("aria-owns", "kungfu");1465 -1 * owned.setAttribute("id", "kungfu");1466 -1 * console.log(axs.utils.getIdReferents("aria-owns", owner)[0] === owned); // This will log 'true'1467 -1 */1468 -1 axs.utils.getIdReferents = function(attributeName, element) {1469 -1 var result = [];1470 -1 var propertyKey = attributeName.replace(/^aria-/, '');1471 -1 var property = axs.constants.ARIA_PROPERTIES[propertyKey];1472 -1 if (!property || !element.hasAttribute(attributeName))1473 -1 return result;1474 -1 var propertyType = property.valueType;1475 -1 if (propertyType === 'idref_list' || propertyType === 'idref') {1476 -1 var ownerDocument = element.ownerDocument;1477 -1 var ids = element.getAttribute(attributeName);1478 -1 ids = ids.split(/\s+/);1479 -1 for (var i = 0, len = ids.length; i < len; i++) {1480 -1 var next = ownerDocument.getElementById(ids[i]);1481 -1 if (next) {1482 -1 result[result.length] = next;1483 -1 }1484 -1 }1485 -1 }1486 -1 return result;1487 -1 };1488 -11489 -1 /**1490 -1 * Gets a subset of 'axs.constants.ARIA_PROPERTIES' filtered by 'valueType'.1491 -1 * @param {!Array.<string>} valueTypes Types to match, e.g. ['idref_list'].1492 -1 * @return {Object.<string, Object>} axs.constants.ARIA_PROPERTIES which match.1493 -1 */1494 -1 axs.utils.getAriaPropertiesByValueType = function(valueTypes) {1495 -1 var result = {};1496 -1 for (var propertyName in axs.constants.ARIA_PROPERTIES) {1497 -1 var property = axs.constants.ARIA_PROPERTIES[propertyName];1498 -1 if (property && valueTypes.indexOf(property.valueType) >= 0) {1499 -1 result[propertyName] = property;1500 -1 }1501 -1 }1502 -1 return result;1503 -1 };1504 -11505 -1 /**1506 -1 * Builds a selector that matches an element with any of these ARIA properties.1507 -1 * @param {Object.<string, Object>} ariaProperties axs.constants.ARIA_PROPERTIES1508 -1 * @return {!string} The selector.1509 -1 */1510 -1 axs.utils.getSelectorForAriaProperties = function(ariaProperties) {1511 -1 var propertyNames = Object.keys(/** @type {!Object} */(ariaProperties));1512 -1 var result = propertyNames.map(function(propertyName) {1513 -1 return '[aria-' + propertyName + ']';1514 -1 });1515 -1 result.sort(); // facilitates reading long selectors and unit testing1516 -1 return result.join(',');1517 -1 };1518 -11519 -1 /**1520 -1 * Finds descendants of this element which implement the given ARIA role.1521 -1 * Will look for descendants with implicit or explicit role.1522 -1 * @param {Element} element an HTML DOM element.1523 -1 * @param {string} role The role you seek.1524 -1 * @return {!Array.<Element>} An array of matching elements.1525 -1 * @example1526 -1 * var container = document.createElement("div");1527 -1 * var button = document.createElement("button");1528 -1 * var span = document.createElement("span");1529 -1 * span.setAttribute("role", "button");1530 -1 * container.appendChild(button);1531 -1 * container.appendChild(span);1532 -1 * var result = axs.utils.findDescendantsWithRole(container, "button"); // result is an array containing both 'button' and 'span'1533 -1 */1534 -1 axs.utils.findDescendantsWithRole = function(element, role) {1535 -1 if (!(element && role))1536 -1 return [];1537 -1 var selector = axs.properties.getSelectorForRole(role);1538 -1 if (!selector)1539 -1 return [];1540 -1 var result = element.querySelectorAll(selector);1541 -1 if (result) { // Convert NodeList to Array; methinks 80/20 that's what callers want.1542 -1 result = Array.prototype.map.call(result, function(item) { return item; });1543 -1 } else {1544 -1 return [];1545 -1 }1546 -1 return result;1547 -1 };1548 -11549 -1 },{}],4:[function(require,module,exports){1550 -1 // Copyright 2013 Google Inc.1551 -1 //1552 -1 // Licensed under the Apache License, Version 2.0 (the "License");1553 -1 // you may not use this file except in compliance with the License.1554 -1 // You may obtain a copy of the License at1555 -1 //1556 -1 // http://www.apache.org/licenses/LICENSE-2.01557 -1 //1558 -1 // Unless required by applicable law or agreed to in writing, software1559 -1 // distributed under the License is distributed on an "AS IS" BASIS,1560 -1 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.1561 -1 // See the License for the specific language governing permissions and1562 -1 // limitations under the License.1563 -11564 -1 goog.provide('axs.browserUtils');1565 -11566 -1 /**1567 -1 * Use Webkit matcher when matches() is not supported.1568 -1 * Use Firefox matcher when Webkit is not supported.1569 -1 * Use IE matcher when neither webkit nor Firefox supported.1570 -1 * @param {Element} element1571 -1 * @param {string} selector1572 -1 * @return {boolean} true if the element matches the selector1573 -1 */1574 -1 axs.browserUtils.matchSelector = function(element, selector) {1575 -1 if (element.matches)1576 -1 return element.matches(selector);1577 -1 if (element.webkitMatchesSelector)1578 -1 return element.webkitMatchesSelector(selector);1579 -1 if (element.mozMatchesSelector)1580 -1 return element.mozMatchesSelector(selector);1581 -1 if (element.msMatchesSelector)1582 -1 return element.msMatchesSelector(selector);1583 -1 return false;1584 -1 };1585 -11586 -1 },{}],5:[function(require,module,exports){1587 -1 // Copyright 2015 Google Inc.1588 -1 //1589 -1 // Licensed under the Apache License, Version 2.0 (the "License");1590 -1 // you may not use this file except in compliance with the License.1591 -1 // You may obtain a copy of the License at1592 -1 //1593 -1 // http://www.apache.org/licenses/LICENSE-2.01594 -1 //1595 -1 // Unless required by applicable law or agreed to in writing, software1596 -1 // distributed under the License is distributed on an "AS IS" BASIS,1597 -1 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.1598 -1 // See the License for the specific language governing permissions and1599 -1 // limitations under the License.1600 -11601 -1 goog.provide('axs.color');1602 -1 goog.provide('axs.color.Color');1603 -11604 -1 /**1605 -1 * @constructor1606 -1 * @param {number} red1607 -1 * @param {number} green1608 -1 * @param {number} blue1609 -1 * @param {number} alpha1610 -1 */1611 -1 axs.color.Color = function(red, green, blue, alpha) {1612 -1 /** @type {number} */1613 -1 this.red = red;1614 -11615 -1 /** @type {number} */1616 -1 this.green = green;1617 -11618 -1 /** @type {number} */1619 -1 this.blue = blue;1620 -11621 -1 /** @type {number} */1622 -1 this.alpha = alpha;1623 -1 };1624 -11625 -1 /**1626 -1 * @constructor1627 -1 * See https://en.wikipedia.org/wiki/YCbCr for more information.1628 -1 * @param {Array.<number>} coords The YCbCr values as a 3 element array, in the order [luma, Cb, Cr].1629 -1 * All numbers are in the range [0, 1].1630 -1 */1631 -1 axs.color.YCbCr = function(coords) {1632 -1 /** @type {number} */1633 -1 this.luma = this.z = coords[0];1634 -11635 -1 /** @type {number} */1636 -1 this.Cb = this.x = coords[1];1637 -11638 -1 /** @type {number} */1639 -1 this.Cr = this.y = coords[2];1640 -1 };1641 -11642 -1 axs.color.YCbCr.prototype = {1643 -1 /**1644 -1 * @param {number} scalar1645 -1 * @return {axs.color.YCbCr} This color multiplied by the given scalar1646 -1 */1647 -1 multiply: function(scalar) {1648 -1 var result = [ this.luma * scalar, this.Cb * scalar, this.Cr * scalar ];1649 -1 return new axs.color.YCbCr(result);1650 -1 },1651 -11652 -1 /**1653 -1 * @param {axs.color.YCbCr} other1654 -1 * @return {axs.color.YCbCr} This plus other1655 -1 */1656 -1 add: function(other) {1657 -1 var result = [ this.luma + other.luma, this.Cb + other.Cb, this.Cr + other.Cr ];1658 -1 return new axs.color.YCbCr(result);1659 -1 },1660 -11661 -1 /**1662 -1 * @param {axs.color.YCbCr} other1663 -1 * @return {axs.color.YCbCr} This minus other1664 -1 */1665 -1 subtract: function(other) {1666 -1 var result = [ this.luma - other.luma, this.Cb - other.Cb, this.Cr - other.Cr ];1667 -1 return new axs.color.YCbCr(result);1668 -1 }1669 -11670 -1 };1671 -11672 -11673 -1 /**1674 -1 * Calculate the contrast ratio between the two given colors. Returns the ratio1675 -1 * to 1, for example for two two colors with a contrast ratio of 21:1, this1676 -1 * function will return 21.1677 -1 * @param {axs.color.Color} fgColor1678 -1 * @param {axs.color.Color} bgColor1679 -1 * @return {!number}1680 -1 */1681 -1 axs.color.calculateContrastRatio = function(fgColor, bgColor) {1682 -1 if (fgColor.alpha < 1)1683 -1 fgColor = axs.color.flattenColors(fgColor, bgColor);1684 -11685 -1 var fgLuminance = axs.color.calculateLuminance(fgColor);1686 -1 var bgLuminance = axs.color.calculateLuminance(bgColor);1687 -1 var contrastRatio = (Math.max(fgLuminance, bgLuminance) + 0.05) /1688 -1 (Math.min(fgLuminance, bgLuminance) + 0.05);1689 -1 return contrastRatio;1690 -1 };1691 -11692 -1 /**1693 -1 * Calculate the luminance of the given color using the WCAG algorithm.1694 -1 * @param {axs.color.Color} color1695 -1 * @return {number}1696 -1 */1697 -1 axs.color.calculateLuminance = function(color) {1698 -1 /* var rSRGB = color.red / 255;1699 -1 var gSRGB = color.green / 255;1700 -1 var bSRGB = color.blue / 255;1701 -11702 -1 var r = rSRGB <= 0.03928 ? rSRGB / 12.92 : Math.pow(((rSRGB + 0.055)/1.055), 2.4);1703 -1 var g = gSRGB <= 0.03928 ? gSRGB / 12.92 : Math.pow(((gSRGB + 0.055)/1.055), 2.4);1704 -1 var b = bSRGB <= 0.03928 ? bSRGB / 12.92 : Math.pow(((bSRGB + 0.055)/1.055), 2.4);1705 -11706 -1 return 0.2126 * r + 0.7152 * g + 0.0722 * b; */1707 -1 var ycc = axs.color.toYCbCr(color);1708 -1 return ycc.luma;1709 -1 };1710 -11711 -1 /**1712 -1 * Compute the luminance ratio between two luminance values.1713 -1 * @param {number} luminance11714 -1 * @param {number} luminance21715 -1 */1716 -1 axs.color.luminanceRatio = function(luminance1, luminance2) {1717 -1 return (Math.max(luminance1, luminance2) + 0.05) /1718 -1 (Math.min(luminance1, luminance2) + 0.05);1719 -1 };1720 -11721 -1 /**1722 -1 * @param {string} colorString The color string from CSS.1723 -1 * @return {?axs.color.Color}1724 -1 */1725 -1 axs.color.parseColor = function(colorString) {1726 -1 if (colorString === "transparent") {1727 -1 return new axs.color.Color(0, 0, 0, 0);1728 -1 }1729 -1 var rgbRegex = /^rgb\((\d+), (\d+), (\d+)\)$/;1730 -1 var match = colorString.match(rgbRegex);1731 -11732 -1 if (match) {1733 -1 var r = parseInt(match[1], 10);1734 -1 var g = parseInt(match[2], 10);1735 -1 var b = parseInt(match[3], 10);1736 -1 var a = 1;1737 -1 return new axs.color.Color(r, g, b, a);1738 -1 }1739 -11740 -1 var rgbaRegex = /^rgba\((\d+), (\d+), (\d+), (\d*(\.\d+)?)\)/;1741 -1 match = colorString.match(rgbaRegex);1742 -1 if (match) {1743 -1 var r = parseInt(match[1], 10);1744 -1 var g = parseInt(match[2], 10);1745 -1 var b = parseInt(match[3], 10);1746 -1 var a = parseFloat(match[4]);1747 -1 return new axs.color.Color(r, g, b, a);1748 -1 }1749 -11750 -1 return null;1751 -1 };1752 -11753 -1 /**1754 -1 * @param {number} value The value of a color channel, 0 <= value <= 0xFF1755 -1 * @return {!string}1756 -1 */1757 -1 axs.color.colorChannelToString = function(value) {1758 -1 value = Math.round(value);1759 -1 if (value <= 0xF)1760 -1 return '0' + value.toString(16);1761 -1 return value.toString(16);1762 -1 };1763 -11764 -1 /**1765 -1 * @param {axs.color.Color} color1766 -1 * @return {!string}1767 -1 */1768 -1 axs.color.colorToString = function(color) {1769 -1 if (color.alpha == 1) {1770 -1 return '#' + axs.color.colorChannelToString(color.red) +1771 -1 axs.color.colorChannelToString(color.green) + axs.color.colorChannelToString(color.blue);1772 -1 }1773 -1 else1774 -1 return 'rgba(' + [color.red, color.green, color.blue, color.alpha].join(',') + ')';1775 -1 };1776 -11777 -1 /**1778 -1 * Compute a desired luminance given a given luminance and a desired contrast ratio.1779 -1 * @param {number} luminance The given luminance.1780 -1 * @param {number} contrast The desired contrast ratio.1781 -1 * @param {boolean} higher Whether the desired luminance is higher or lower than the given luminance.1782 -1 * @return {number} The desired luminance.1783 -1 */1784 -1 axs.color.luminanceFromContrastRatio = function(luminance, contrast, higher) {1785 -1 if (higher) {1786 -1 var newLuminance = (luminance + 0.05) * contrast - 0.05;1787 -1 return newLuminance;1788 -1 } else {1789 -1 var newLuminance = (luminance + 0.05) / contrast - 0.05;1790 -1 return newLuminance;1791 -1 }1792 -1 };1793 -11794 -1 /**1795 -1 * Given a color in YCbCr format and a desired luminance, pick a new color with the desired luminance which is1796 -1 * as close as possible to the original color.1797 -1 * @param {axs.color.YCbCr} ycc The original color in YCbCr form.1798 -1 * @param {number} luma The desired luminance1799 -1 * @return {!axs.color.Color} A new color in RGB.1800 -1 */1801 -1 axs.color.translateColor = function(ycc, luma) {1802 -1 var endpoint = (luma > ycc.luma) ? axs.color.WHITE_YCC : axs.color.BLACK_YCC;1803 -1 var cubeFaces = (endpoint == axs.color.WHITE_YCC) ? axs.color.YCC_CUBE_FACES_WHITE1804 -1 : axs.color.YCC_CUBE_FACES_BLACK;1805 -11806 -1 var a = new axs.color.YCbCr([0, ycc.Cb, ycc.Cr]);1807 -1 var b = new axs.color.YCbCr([1, ycc.Cb, ycc.Cr]);1808 -1 var line = { a: a, b: b };1809 -11810 -1 var intersection = null;1811 -1 for (var i = 0; i < cubeFaces.length; i++) {1812 -1 var cubeFace = cubeFaces[i];1813 -1 intersection = axs.color.findIntersection(line, cubeFace);1814 -1 // If intersection within [0, 1] in Z axis, it is within the cube.1815 -1 if (intersection.z >= 0 && intersection.z <= 1)1816 -1 break;1817 -1 }1818 -1 if (!intersection) {1819 -1 // Should never happen1820 -1 throw "Couldn't find intersection with YCbCr color cube for Cb=" + ycc.Cb + ", Cr=" + ycc.Cr + ".";1821 -1 }1822 -1 if (intersection.x != ycc.x || intersection.y != ycc.y) {1823 -1 // Should never happen1824 -1 throw "Intersection has wrong Cb/Cr values.";1825 -1 }1826 -11827 -1 // If intersection.luma is closer to endpoint than desired luma, then luma is inside cube1828 -1 // and we can immediately return new value.1829 -1 if (Math.abs(endpoint.luma - intersection.luma) < Math.abs(endpoint.luma - luma)) {1830 -1 var translatedColor = [luma, ycc.Cb, ycc.Cr];1831 -1 return axs.color.fromYCbCrArray(translatedColor);1832 -1 }1833 -11834 -1 // Otherwise, translate from intersection towards white/black such that luma is correct.1835 -1 var dLuma = luma - intersection.luma;1836 -1 var scale = dLuma / (endpoint.luma - intersection.luma);1837 -1 var translatedColor = [ luma,1838 -1 intersection.Cb - (intersection.Cb * scale),1839 -1 intersection.Cr - (intersection.Cr * scale) ];1840 -11841 -1 return axs.color.fromYCbCrArray(translatedColor);1842 -1 };1843 -11844 -1 /** @typedef {{fg: string, bg: string, contrast: string}} */1845 -1 axs.color.SuggestedColors;1846 -11847 -1 /**1848 -1 * @param {axs.color.Color} bgColor1849 -1 * @param {axs.color.Color} fgColor1850 -1 * @param {Object.<string, number>} desiredContrastRatios A map of label to desired contrast ratio.1851 -1 * @return {Object.<string, axs.color.SuggestedColors>}1852 -1 */1853 -1 axs.color.suggestColors = function(bgColor, fgColor, desiredContrastRatios) {1854 -1 var colors = {};1855 -1 var bgLuminance = axs.color.calculateLuminance(bgColor);1856 -1 var fgLuminance = axs.color.calculateLuminance(fgColor);1857 -11858 -1 var fgLuminanceIsHigher = fgLuminance > bgLuminance;1859 -1 var fgYCbCr = axs.color.toYCbCr(fgColor);1860 -1 var bgYCbCr = axs.color.toYCbCr(bgColor);1861 -1 for (var desiredLabel in desiredContrastRatios) {1862 -1 var desiredContrast = desiredContrastRatios[desiredLabel];1863 -11864 -1 var desiredFgLuminance = axs.color.luminanceFromContrastRatio(bgLuminance, desiredContrast + 0.02, fgLuminanceIsHigher);1865 -1 if (desiredFgLuminance <= 1 && desiredFgLuminance >= 0) {1866 -1 var newFgColor = axs.color.translateColor(fgYCbCr, desiredFgLuminance);1867 -1 var newContrastRatio = axs.color.calculateContrastRatio(newFgColor, bgColor);1868 -1 var suggestedColors = {};1869 -1 suggestedColors.fg = /** @type {!string} */ (axs.color.colorToString(newFgColor));1870 -1 suggestedColors.bg = /** @type {!string} */ (axs.color.colorToString(bgColor));1871 -1 suggestedColors.contrast = /** @type {!string} */ (newContrastRatio.toFixed(2));1872 -1 colors[desiredLabel] = /** @type {axs.color.SuggestedColors} */ (suggestedColors);1873 -1 continue;1874 -1 }1875 -11876 -1 var desiredBgLuminance = axs.color.luminanceFromContrastRatio(fgLuminance, desiredContrast + 0.02, !fgLuminanceIsHigher);1877 -1 if (desiredBgLuminance <= 1 && desiredBgLuminance >= 0) {1878 -1 var newBgColor = axs.color.translateColor(bgYCbCr, desiredBgLuminance);1879 -1 var newContrastRatio = axs.color.calculateContrastRatio(fgColor, newBgColor);1880 -1 var suggestedColors = {};1881 -1 suggestedColors.bg = /** @type {!string} */ (axs.color.colorToString(newBgColor));1882 -1 suggestedColors.fg = /** @type {!string} */ (axs.color.colorToString(fgColor));1883 -1 suggestedColors.contrast = /** @type {!string} */ (newContrastRatio.toFixed(2));1884 -1 colors[desiredLabel] = /** @type {axs.color.SuggestedColors} */ (suggestedColors);1885 -1 }1886 -1 }1887 -1 return colors;1888 -1 };1889 -11890 -1 /**1891 -1 * Combine the two given color according to alpha blending.1892 -1 * @param {axs.color.Color} fgColor1893 -1 * @param {axs.color.Color} bgColor1894 -1 * @return {axs.color.Color}1895 -1 */1896 -1 axs.color.flattenColors = function(fgColor, bgColor) {1897 -1 var alpha = fgColor.alpha;1898 -1 var r = ((1 - alpha) * bgColor.red) + (alpha * fgColor.red);1899 -1 var g = ((1 - alpha) * bgColor.green) + (alpha * fgColor.green);1900 -1 var b = ((1 - alpha) * bgColor.blue) + (alpha * fgColor.blue);1901 -1 var a = fgColor.alpha + (bgColor.alpha * (1 - fgColor.alpha));1902 -11903 -1 return new axs.color.Color(r, g, b, a);1904 -1 };1905 -11906 -1 /**1907 -1 * Multiply the given vector by the given matrix.1908 -1 * @param {Array.<Array.<number>>} matrix A 3x3 matrix1909 -1 * @param {Array.<number>} vector A 3-element vector1910 -1 * @return {Array.<number>} A 3-element vector1911 -1 */1912 -1 axs.color.multiplyMatrixVector = function(matrix, vector) {1913 -1 var a = matrix[0][0];1914 -1 var b = matrix[0][1];1915 -1 var c = matrix[0][2];1916 -1 var d = matrix[1][0];1917 -1 var e = matrix[1][1];1918 -1 var f = matrix[1][2];1919 -1 var g = matrix[2][0];1920 -1 var h = matrix[2][1];1921 -1 var k = matrix[2][2];1922 -11923 -1 var x = vector[0];1924 -1 var y = vector[1];1925 -1 var z = vector[2];1926 -11927 -1 return [1928 -1 a*x + b*y + c*z,1929 -1 d*x + e*y + f*z,1930 -1 g*x + h*y + k*z1931 -1 ];1932 -1 };1933 -11934 -1 /**1935 -1 * Convert a given RGB color to YCbCr.1936 -1 * @param {axs.color.Color} color1937 -1 * @return {axs.color.YCbCr}1938 -1 */1939 -1 axs.color.toYCbCr = function(color) {1940 -1 var rSRGB = color.red / 255;1941 -1 var gSRGB = color.green / 255;1942 -1 var bSRGB = color.blue / 255;1943 -11944 -1 var r = rSRGB <= 0.03928 ? rSRGB / 12.92 : Math.pow(((rSRGB + 0.055)/1.055), 2.4);1945 -1 var g = gSRGB <= 0.03928 ? gSRGB / 12.92 : Math.pow(((gSRGB + 0.055)/1.055), 2.4);1946 -1 var b = bSRGB <= 0.03928 ? bSRGB / 12.92 : Math.pow(((bSRGB + 0.055)/1.055), 2.4);1947 -11948 -1 return new axs.color.YCbCr(axs.color.multiplyMatrixVector(axs.color.YCC_MATRIX, [r, g, b]));1949 -1 };1950 -11951 -1 /**1952 -1 * @param {axs.color.YCbCr} ycc1953 -1 * @return {!axs.color.Color}1954 -1 */1955 -1 axs.color.fromYCbCr = function(ycc) {1956 -1 return axs.color.fromYCbCrArray([ycc.luma, ycc.Cb, ycc.Cr]);1957 -1 };1958 -11959 -1 /**1960 -1 * Convert a color from a YCbCr color (as a vector) to an RGB color1961 -1 * @param {Array.<number>} yccArray1962 -1 * @return {!axs.color.Color}1963 -1 */1964 -1 axs.color.fromYCbCrArray = function(yccArray) {1965 -1 var rgb = axs.color.multiplyMatrixVector(axs.color.INVERTED_YCC_MATRIX, yccArray);1966 -11967 -1 var r = rgb[0];1968 -1 var g = rgb[1];1969 -1 var b = rgb[2];1970 -1 var rSRGB = r <= 0.00303949 ? (r * 12.92) : (Math.pow(r, (1/2.4)) * 1.055) - 0.055;1971 -1 var gSRGB = g <= 0.00303949 ? (g * 12.92) : (Math.pow(g, (1/2.4)) * 1.055) - 0.055;1972 -1 var bSRGB = b <= 0.00303949 ? (b * 12.92) : (Math.pow(b, (1/2.4)) * 1.055) - 0.055;1973 -11974 -1 var red = Math.min(Math.max(Math.round(rSRGB * 255), 0), 255);1975 -1 var green = Math.min(Math.max(Math.round(gSRGB * 255), 0), 255);1976 -1 var blue = Math.min(Math.max(Math.round(bSRGB * 255), 0), 255);1977 -11978 -1 return new axs.color.Color(red, green, blue, 1);1979 -1 };1980 -11981 -1 /**1982 -1 * Returns an RGB to YCbCr conversion matrix for the given kR, kB constants.1983 -1 * @param {number} kR1984 -1 * @param {number} kB1985 -1 * @return {Array.<Array.<number>>}1986 -1 */1987 -1 axs.color.RGBToYCbCrMatrix = function(kR, kB) {1988 -1 return [1989 -1 [1990 -1 kR,1991 -1 (1 - kR - kB),1992 -1 kB1993 -1 ],1994 -1 [1995 -1 -kR/(2 - 2*kB),1996 -1 (kR + kB - 1)/(2 - 2*kB),1997 -1 (1 - kB)/(2 - 2*kB)1998 -1 ],1999 -1 [2000 -1 (1 - kR)/(2 - 2*kR),2001 -1 (kR + kB - 1)/(2 - 2*kR),2002 -1 -kB/(2 - 2*kR)2003 -1 ]2004 -1 ];2005 -1 };2006 -12007 -1 /**2008 -1 * Return the inverse of the given 3x3 matrix.2009 -1 * @param {Array.<Array.<number>>} matrix2010 -1 * @return Array.<Array.<number>> The inverse of the given matrix.2011 -1 */2012 -1 axs.color.invert3x3Matrix = function(matrix) {2013 -1 var a = matrix[0][0];2014 -1 var b = matrix[0][1];2015 -1 var c = matrix[0][2];2016 -1 var d = matrix[1][0];2017 -1 var e = matrix[1][1];2018 -1 var f = matrix[1][2];2019 -1 var g = matrix[2][0];2020 -1 var h = matrix[2][1];2021 -1 var k = matrix[2][2];2022 -12023 -1 var A = (e*k - f*h);2024 -1 var B = (f*g - d*k);2025 -1 var C = (d*h - e*g);2026 -1 var D = (c*h - b*k);2027 -1 var E = (a*k - c*g);2028 -1 var F = (g*b - a*h);2029 -1 var G = (b*f - c*e);2030 -1 var H = (c*d - a*f);2031 -1 var K = (a*e - b*d);2032 -12033 -1 var det = a * (e*k - f*h) - b * (k*d - f*g) + c * (d*h - e*g);2034 -1 var z = 1/det;2035 -12036 -1 return axs.color.scalarMultiplyMatrix([2037 -1 [ A, D, G ],2038 -1 [ B, E, H ],2039 -1 [ C, F, K ]2040 -1 ], z);2041 -1 };2042 -12043 -1 /** @typedef {{ a: axs.color.YCbCr, b: axs.color.YCbCr }} */2044 -1 axs.color.Line;2045 -12046 -1 /** @typedef {{ p0: axs.color.YCbCr, p1: axs.color.YCbCr, p2: axs.color.YCbCr }} */2047 -1 axs.color.Plane;2048 -12049 -1 /**2050 -1 * Find the intersection between a line and a plane using2051 -1 * http://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection#Parametric_form2052 -1 * @param {axs.color.Line} l2053 -1 * @param {axs.color.Plane} p2054 -1 * @return {axs.color.YCbCr}2055 -1 */2056 -1 axs.color.findIntersection = function(l, p) {2057 -1 var lhs = [ l.a.x - p.p0.x, l.a.y - p.p0.y, l.a.z - p.p0.z ];2058 -12059 -1 var matrix = [ [ l.a.x - l.b.x, p.p1.x - p.p0.x, p.p2.x - p.p0.x ],2060 -1 [ l.a.y - l.b.y, p.p1.y - p.p0.y, p.p2.y - p.p0.y ],2061 -1 [ l.a.z - l.b.z, p.p1.z - p.p0.z, p.p2.z - p.p0.z ] ];2062 -1 var invertedMatrix = axs.color.invert3x3Matrix(matrix);2063 -12064 -1 var tuv = axs.color.multiplyMatrixVector(invertedMatrix, lhs);2065 -1 var t = tuv[0];2066 -12067 -1 var result = l.a.add(l.b.subtract(l.a).multiply(t));2068 -1 return result;2069 -1 };2070 -12071 -1 /**2072 -1 * Multiply a matrix by a scalar.2073 -1 * @param {Array.<Array.<number>>} matrix A 3x3 matrix.2074 -1 * @param {number} scalar2075 -1 * @return {Array.<Array.<number>>}2076 -1 */2077 -1 axs.color.scalarMultiplyMatrix = function(matrix, scalar) {2078 -1 var result = [];2079 -12080 -1 for (var i = 0; i < 3; i++)2081 -1 result[i] = axs.color.scalarMultiplyVector(matrix[i], scalar);2082 -12083 -1 return result;2084 -1 };2085 -12086 -1 /**2087 -1 * Multiply a vector by a scalar.2088 -1 * @param {Array.<number>} vector2089 -1 * @param {number} scalar2090 -1 * @return {Array.<number>} vector2091 -1 */2092 -1 axs.color.scalarMultiplyVector = function(vector, scalar) {2093 -1 var result = [];2094 -1 for (var i = 0; i < vector.length; i++)2095 -1 result[i] = vector[i] * scalar;2096 -1 return result;2097 -1 };2098 -12099 -1 axs.color.kR = 0.2126;2100 -1 axs.color.kB = 0.0722;2101 -1 axs.color.YCC_MATRIX = axs.color.RGBToYCbCrMatrix(axs.color.kR, axs.color.kB);2102 -1 axs.color.INVERTED_YCC_MATRIX = axs.color.invert3x3Matrix(axs.color.YCC_MATRIX);2103 -12104 -1 axs.color.BLACK = new axs.color.Color(0, 0, 0, 1.0);2105 -1 axs.color.BLACK_YCC = axs.color.toYCbCr(axs.color.BLACK);2106 -1 axs.color.WHITE = new axs.color.Color(255, 255, 255, 1.0);2107 -1 axs.color.WHITE_YCC = axs.color.toYCbCr(axs.color.WHITE);2108 -1 axs.color.RED = new axs.color.Color(255, 0, 0, 1.0);2109 -1 axs.color.RED_YCC = axs.color.toYCbCr(axs.color.RED);2110 -1 axs.color.GREEN = new axs.color.Color(0, 255, 0, 1.0);2111 -1 axs.color.GREEN_YCC = axs.color.toYCbCr(axs.color.GREEN);2112 -1 axs.color.BLUE = new axs.color.Color(0, 0, 255, 1.0);2113 -1 axs.color.BLUE_YCC = axs.color.toYCbCr(axs.color.BLUE);2114 -1 axs.color.CYAN = new axs.color.Color(0, 255, 255, 1.0);2115 -1 axs.color.CYAN_YCC = axs.color.toYCbCr(axs.color.CYAN);2116 -1 axs.color.MAGENTA = new axs.color.Color(255, 0, 255, 1.0);2117 -1 axs.color.MAGENTA_YCC = axs.color.toYCbCr(axs.color.MAGENTA);2118 -1 axs.color.YELLOW = new axs.color.Color(255, 255, 0, 1.0);2119 -1 axs.color.YELLOW_YCC = axs.color.toYCbCr(axs.color.YELLOW);2120 -12121 -1 axs.color.YCC_CUBE_FACES_BLACK = [ { p0: axs.color.BLACK_YCC, p1: axs.color.RED_YCC, p2: axs.color.GREEN_YCC },2122 -1 { p0: axs.color.BLACK_YCC, p1: axs.color.GREEN_YCC, p2: axs.color.BLUE_YCC },2123 -1 { p0: axs.color.BLACK_YCC, p1: axs.color.BLUE_YCC, p2: axs.color.RED_YCC } ];2124 -1 axs.color.YCC_CUBE_FACES_WHITE = [ { p0: axs.color.WHITE_YCC, p1: axs.color.CYAN_YCC, p2: axs.color.MAGENTA_YCC },2125 -1 { p0: axs.color.WHITE_YCC, p1: axs.color.MAGENTA_YCC, p2: axs.color.YELLOW_YCC },2126 -1 { p0: axs.color.WHITE_YCC, p1: axs.color.YELLOW_YCC, p2: axs.color.CYAN_YCC } ];2127 -12128 -1 },{}],6:[function(require,module,exports){2129 -1 // Copyright 2012 Google Inc.2130 -1 //2131 -1 // Licensed under the Apache License, Version 2.0 (the "License");2132 -1 // you may not use this file except in compliance with the License.2133 -1 // You may obtain a copy of the License at2134 -1 //2135 -1 // http://www.apache.org/licenses/LICENSE-2.02136 -1 //2137 -1 // Unless required by applicable law or agreed to in writing, software2138 -1 // distributed under the License is distributed on an "AS IS" BASIS,2139 -1 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.2140 -1 // See the License for the specific language governing permissions and2141 -1 // limitations under the License.2142 -12143 -1 goog.provide('axs.constants');2144 -1 goog.provide('axs.constants.AuditResult');2145 -1 goog.provide('axs.constants.Severity');2146 -12147 -1 /** @type {Object.<string, Object>} */2148 -1 axs.constants.ARIA_ROLES = {2149 -1 "alert": {2150 -1 "namefrom": [ "author" ],2151 -1 "parent": [ "region" ]2152 -1 },2153 -1 "alertdialog": {2154 -1 "namefrom": [ "author" ],2155 -1 "namerequired": true,2156 -1 "parent": [ "alert", "dialog" ]2157 -1 },2158 -1 "application": {2159 -1 "namefrom": [ "author" ],2160 -1 "namerequired": true,2161 -1 "parent": [ "landmark" ]2162 -1 },2163 -1 "article": {2164 -1 "namefrom": [ "author" ],2165 -1 "parent": [ "document", "region" ]2166 -1 },2167 -1 "banner": {2168 -1 "namefrom": [ "author" ],2169 -1 "parent": [ "landmark" ]2170 -1 },2171 -1 "button": {2172 -1 "childpresentational": true,2173 -1 "namefrom": [ "contents", "author" ],2174 -1 "namerequired": true,2175 -1 "parent": [ "command" ],2176 -1 "properties": [ "aria-expanded", "aria-pressed" ]2177 -1 },2178 -1 "checkbox": {2179 -1 "namefrom": [ "contents", "author" ],2180 -1 "namerequired": true,2181 -1 "parent": [ "input" ],2182 -1 "requiredProperties": [ "aria-checked" ],2183 -1 "properties": [ "aria-checked" ]2184 -1 },2185 -1 "columnheader": {2186 -1 "namefrom": [ "contents", "author" ],2187 -1 "namerequired": true,2188 -1 "parent": [ "gridcell", "sectionhead", "widget" ],2189 -1 "properties": [ "aria-sort" ],2190 -1 "scope": [ "row" ]2191 -1 },2192 -1 "combobox": {2193 -1 "mustcontain": [ "listbox", "textbox" ],2194 -1 "namefrom": [ "author" ],2195 -1 "namerequired": true,2196 -1 "parent": [ "select" ],2197 -1 "requiredProperties": [ "aria-expanded" ],2198 -1 "properties": [ "aria-expanded", "aria-autocomplete", "aria-required" ]2199 -1 },2200 -1 "command": {2201 -1 "abstract": true,2202 -1 "namefrom": [ "author" ],2203 -1 "parent": [ "widget" ]2204 -1 },2205 -1 "complementary": {2206 -1 "namefrom": [ "author" ],2207 -1 "parent": [ "landmark" ]2208 -1 },2209 -1 "composite": {2210 -1 "abstract": true,2211 -1 "childpresentational": false,2212 -1 "namefrom": [ "author" ],2213 -1 "parent": [ "widget" ],2214 -1 "properties": [ "aria-activedescendant" ]2215 -1 },2216 -1 "contentinfo": {2217 -1 "namefrom": [ "author" ],2218 -1 "parent": [ "landmark" ]2219 -1 },2220 -1 "definition": {2221 -1 "namefrom": [ "author" ],2222 -1 "parent": [ "section" ]2223 -1 },2224 -1 "dialog": {2225 -1 "namefrom": [ "author" ],2226 -1 "namerequired": true,2227 -1 "parent": [ "window" ]2228 -1 },2229 -1 "directory": {2230 -1 "namefrom": [ "contents", "author" ],2231 -1 "parent": [ "list" ]2232 -1 },2233 -1 "document": {2234 -1 "namefrom": [ " author" ],2235 -1 "namerequired": true,2236 -1 "parent": [ "structure" ],2237 -1 "properties": [ "aria-expanded" ]2238 -1 },2239 -1 "form": {2240 -1 "namefrom": [ "author" ],2241 -1 "parent": [ "landmark" ]2242 -1 },2243 -1 "grid": {2244 -1 "mustcontain": [ "row", "rowgroup" ],2245 -1 "namefrom": [ "author" ],2246 -1 "namerequired": true,2247 -1 "parent": [ "composite", "region" ],2248 -1 "properties": [ "aria-level", "aria-multiselectable", "aria-readonly" ]2249 -1 },2250 -1 "gridcell": {2251 -1 "namefrom": [ "contents", "author" ],2252 -1 "namerequired": true,2253 -1 "parent": [ "section", "widget" ],2254 -1 "properties": [ "aria-readonly", "aria-required", "aria-selected" ],2255 -1 "scope": [ "row" ]2256 -1 },2257 -1 "group": {2258 -1 "namefrom": [ " author" ],2259 -1 "parent": [ "section" ],2260 -1 "properties": [ "aria-activedescendant" ]2261 -1 },2262 -1 "heading": {2263 -1 "namerequired": true,2264 -1 "parent": [ "sectionhead" ],2265 -1 "properties": [ "aria-level" ]2266 -1 },2267 -1 "img": {2268 -1 "childpresentational": true,2269 -1 "namefrom": [ "author" ],2270 -1 "namerequired": true,2271 -1 "parent": [ "section" ]2272 -1 },2273 -1 "input": {2274 -1 "abstract": true,2275 -1 "namefrom": [ "author" ],2276 -1 "parent": [ "widget" ]2277 -1 },2278 -1 "landmark": {2279 -1 "abstract": true,2280 -1 "namefrom": [ "contents", "author" ],2281 -1 "namerequired": false,2282 -1 "parent": [ "region" ]2283 -1 },2284 -1 "link": {2285 -1 "namefrom": [ "contents", "author" ],2286 -1 "namerequired": true,2287 -1 "parent": [ "command" ],2288 -1 "properties": [ "aria-expanded" ]2289 -1 },2290 -1 "list": {2291 -1 "mustcontain": [ "group", "listitem" ],2292 -1 "namefrom": [ "author" ],2293 -1 "parent": [ "region" ]2294 -1 },2295 -1 "listbox": {2296 -1 "mustcontain": [ "option" ],2297 -1 "namefrom": [ "author" ],2298 -1 "namerequired": true,2299 -1 "parent": [ "list", "select" ],2300 -1 "properties": [ "aria-multiselectable", "aria-required" ]2301 -1 },2302 -1 "listitem": {2303 -1 "namefrom": [ "contents", "author" ],2304 -1 "namerequired": true,2305 -1 "parent": [ "section" ],2306 -1 "properties": [ "aria-level", "aria-posinset", "aria-setsize" ],2307 -1 "scope": [ "list" ]2308 -1 },2309 -1 "log": {2310 -1 "namefrom": [ " author" ],2311 -1 "namerequired": true,2312 -1 "parent": [ "region" ]2313 -1 },2314 -1 "main": {2315 -1 "namefrom": [ "author" ],2316 -1 "parent": [ "landmark" ]2317 -1 },2318 -1 "marquee": {2319 -1 "namerequired": true,2320 -1 "parent": [ "section" ]2321 -1 },2322 -1 "math": {2323 -1 "childpresentational": true,2324 -1 "namefrom": [ "author" ],2325 -1 "parent": [ "section" ]2326 -1 },2327 -1 "menu": {2328 -1 "mustcontain": [2329 -1 "group",2330 -1 "menuitemradio",2331 -1 "menuitem",2332 -1 "menuitemcheckbox"2333 -1 ],2334 -1 "namefrom": [ "author" ],2335 -1 "namerequired": true,2336 -1 "parent": [ "list", "select" ]2337 -1 },2338 -1 "menubar": {2339 -1 "namefrom": [ "author" ],2340 -1 "parent": [ "menu" ]2341 -1 },2342 -1 "menuitem": {2343 -1 "namefrom": [ "contents", "author" ],2344 -1 "namerequired": true,2345 -1 "parent": [ "command" ],2346 -1 "scope": [ "menu", "menubar" ]2347 -1 },2348 -1 "menuitemcheckbox": {2349 -1 "namefrom": [ "contents", "author" ],2350 -1 "namerequired": true,2351 -1 "parent": [ "checkbox", "menuitem" ],2352 -1 "scope": [ "menu", "menubar" ]2353 -1 },2354 -1 "menuitemradio": {2355 -1 "namefrom": [ "contents", "author" ],2356 -1 "namerequired": true,2357 -1 "parent": [ "menuitemcheckbox", "radio" ],2358 -1 "scope": [ "menu", "menubar" ]2359 -1 },2360 -1 "navigation": {2361 -1 "namefrom": [ "author" ],2362 -1 "parent": [ "landmark" ]2363 -1 },2364 -1 "note": {2365 -1 "namefrom": [ "author" ],2366 -1 "parent": [ "section" ]2367 -1 },2368 -1 "option": {2369 -1 "namefrom": [ "contents", "author" ],2370 -1 "namerequired": true,2371 -1 "parent": [ "input" ],2372 -1 "properties": [2373 -1 "aria-checked",2374 -1 "aria-posinset",2375 -1 "aria-selected",2376 -1 "aria-setsize"2377 -1 ]2378 -1 },2379 -1 "presentation": {2380 -1 "parent": [ "structure" ]2381 -1 },2382 -1 "progressbar": {2383 -1 "childpresentational": true,2384 -1 "namefrom": [ "author" ],2385 -1 "namerequired": true,2386 -1 "parent": [ "range" ]2387 -1 },2388 -1 "radio": {2389 -1 "namefrom": [ "contents", "author" ],2390 -1 "namerequired": true,2391 -1 "parent": [ "checkbox", "option" ]2392 -1 },2393 -1 "radiogroup": {2394 -1 "mustcontain": [ "radio" ],2395 -1 "namefrom": [ "author" ],2396 -1 "namerequired": true,2397 -1 "parent": [ "select" ],2398 -1 "properties": [ "aria-required" ]2399 -1 },2400 -1 "range": {2401 -1 "abstract": true,2402 -1 "namefrom": [ "author" ],2403 -1 "parent": [ "widget" ],2404 -1 "properties": [2405 -1 "aria-valuemax",2406 -1 "aria-valuemin",2407 -1 "aria-valuenow",2408 -1 "aria-valuetext"2409 -1 ]2410 -1 },2411 -1 "region": {2412 -1 "namefrom": [ " author" ],2413 -1 "parent": [ "section" ]2414 -1 },2415 -1 "roletype": {2416 -1 "abstract": true,2417 -1 "properties": [2418 -1 "aria-atomic",2419 -1 "aria-busy",2420 -1 "aria-controls",2421 -1 "aria-describedby",2422 -1 "aria-disabled",2423 -1 "aria-dropeffect",2424 -1 "aria-flowto",2425 -1 "aria-grabbed",2426 -1 "aria-haspopup",2427 -1 "aria-hidden",2428 -1 "aria-invalid",2429 -1 "aria-label",2430 -1 "aria-labelledby",2431 -1 "aria-live",2432 -1 "aria-owns",2433 -1 "aria-relevant"2434 -1 ]2435 -1 },2436 -1 "row": {2437 -1 "mustcontain": [ "columnheader", "gridcell", "rowheader" ],2438 -1 "namefrom": [ "contents", "author" ],2439 -1 "parent": [ "group", "widget" ],2440 -1 "properties": [ "aria-level", "aria-selected" ],2441 -1 "scope": [ "grid", "rowgroup", "treegrid" ]2442 -1 },2443 -1 "rowgroup": {2444 -1 "mustcontain": [ "row" ],2445 -1 "namefrom": [ "contents", "author" ],2446 -1 "parent": [ "group" ],2447 -1 "scope": [ "grid" ]2448 -1 },2449 -1 "rowheader": {2450 -1 "namefrom": [ "contents", "author" ],2451 -1 "namerequired": true,2452 -1 "parent": [ "gridcell", "sectionhead", "widget" ],2453 -1 "properties": [ "aria-sort" ],2454 -1 "scope": [ "row" ]2455 -1 },2456 -1 "search": {2457 -1 "namefrom": [ "author" ],2458 -1 "parent": [ "landmark" ]2459 -1 },2460 -1 "section": {2461 -1 "abstract": true,2462 -1 "namefrom": [ "contents", "author" ],2463 -1 "parent": [ "structure" ],2464 -1 "properties": [ "aria-expanded" ]2465 -1 },2466 -1 "sectionhead": {2467 -1 "abstract": true,2468 -1 "namefrom": [ "contents", "author" ],2469 -1 "parent": [ "structure" ],2470 -1 "properties": [ "aria-expanded" ]2471 -1 },2472 -1 "select": {2473 -1 "abstract": true,2474 -1 "namefrom": [ "author" ],2475 -1 "parent": [ "composite", "group", "input" ]2476 -1 },2477 -1 "separator": {2478 -1 "childpresentational": true,2479 -1 "namefrom": [ "author" ],2480 -1 "parent": [ "structure" ],2481 -1 "properties": [ "aria-expanded", "aria-orientation" ]2482 -1 },2483 -1 "scrollbar": {2484 -1 "childpresentational": true,2485 -1 "namefrom": [ "author" ],2486 -1 "namerequired": false,2487 -1 "parent": [ "input", "range" ],2488 -1 "requiredProperties": [2489 -1 "aria-controls",2490 -1 "aria-orientation",2491 -1 "aria-valuemax",2492 -1 "aria-valuemin",2493 -1 "aria-valuenow"2494 -1 ],2495 -1 "properties": [2496 -1 "aria-controls",2497 -1 "aria-orientation",2498 -1 "aria-valuemax",2499 -1 "aria-valuemin",2500 -1 "aria-valuenow"2501 -1 ]2502 -1 },2503 -1 "slider": {2504 -1 "childpresentational": true,2505 -1 "namefrom": [ "author" ],2506 -1 "namerequired": true,2507 -1 "parent": [ "input", "range" ],2508 -1 "requiredProperties": [ "aria-valuemax", "aria-valuemin", "aria-valuenow" ],2509 -1 "properties": [2510 -1 "aria-valuemax",2511 -1 "aria-valuemin",2512 -1 "aria-valuenow",2513 -1 "aria-orientation"2514 -1 ]2515 -1 },2516 -1 "spinbutton": {2517 -1 "namefrom": [ "author" ],2518 -1 "namerequired": true,2519 -1 "parent": [ "input", "range" ],2520 -1 "requiredProperties": [ "aria-valuemax", "aria-valuemin", "aria-valuenow" ],2521 -1 "properties": [2522 -1 "aria-valuemax",2523 -1 "aria-valuemin",2524 -1 "aria-valuenow",2525 -1 "aria-required"2526 -1 ]2527 -1 },2528 -1 "status": {2529 -1 "parent": [ "region" ]2530 -1 },2531 -1 "structure": {2532 -1 "abstract": true,2533 -1 "parent": [ "roletype" ]2534 -1 },2535 -1 "tab": {2536 -1 "namefrom": [ "contents", "author" ],2537 -1 "parent": [ "sectionhead", "widget" ],2538 -1 "properties": [ "aria-selected" ],2539 -1 "scope": [ "tablist" ]2540 -1 },2541 -1 "tablist": {2542 -1 "mustcontain": [ "tab" ],2543 -1 "namefrom": [ "author" ],2544 -1 "parent": [ "composite", "directory" ],2545 -1 "properties": [ "aria-level" ]2546 -1 },2547 -1 "tabpanel": {2548 -1 "namefrom": [ "author" ],2549 -1 "namerequired": true,2550 -1 "parent": [ "region" ]2551 -1 },2552 -1 "textbox": {2553 -1 "namefrom": [ "author" ],2554 -1 "namerequired": true,2555 -1 "parent": [ "input" ],2556 -1 "properties": [2557 -1 "aria-activedescendant",2558 -1 "aria-autocomplete",2559 -1 "aria-multiline",2560 -1 "aria-readonly",2561 -1 "aria-required"2562 -1 ]2563 -1 },2564 -1 "timer": {2565 -1 "namefrom": [ "author" ],2566 -1 "namerequired": true,2567 -1 "parent": [ "status" ]2568 -1 },2569 -1 "toolbar": {2570 -1 "namefrom": [ "author" ],2571 -1 "parent": [ "group" ]2572 -1 },2573 -1 "tooltip": {2574 -1 "namerequired": true,2575 -1 "parent": [ "section" ]2576 -1 },2577 -1 "tree": {2578 -1 "mustcontain": [ "group", "treeitem" ],2579 -1 "namefrom": [ "author" ],2580 -1 "namerequired": true,2581 -1 "parent": [ "select" ],2582 -1 "properties": [ "aria-multiselectable", "aria-required" ]2583 -1 },2584 -1 "treegrid": {2585 -1 "mustcontain": [ "row" ],2586 -1 "namefrom": [ "author" ],2587 -1 "namerequired": true,2588 -1 "parent": [ "grid", "tree" ]2589 -1 },2590 -1 "treeitem": {2591 -1 "namefrom": [ "contents", "author" ],2592 -1 "namerequired": true,2593 -1 "parent": [ "listitem", "option" ],2594 -1 "scope": [ "group", "tree" ]2595 -1 },2596 -1 "widget": {2597 -1 "abstract": true,2598 -1 "parent": [ "roletype" ]2599 -1 },2600 -1 "window": {2601 -1 "abstract": true,2602 -1 "namefrom": [ " author" ],2603 -1 "parent": [ "roletype" ],2604 -1 "properties": [ "aria-expanded" ]2605 -1 }2606 -1 };2607 -12608 -1 axs.constants.WIDGET_ROLES = {};2609 -12610 -1 /**2611 -1 * Squashes the parent hierarchy on to role object.2612 -1 * @param {Object} role2613 -1 * @param {Object} set2614 -1 * @private2615 -1 */2616 -1 axs.constants.addAllParentRolesToSet_ = function(role, set) {2617 -1 if (!role['parent'])2618 -1 return;2619 -1 var parents = role['parent'];2620 -1 for (var j = 0; j < parents.length; j++) {2621 -1 var parentRoleName = parents[j];2622 -1 set[parentRoleName] = true;2623 -1 axs.constants.addAllParentRolesToSet_(2624 -1 axs.constants.ARIA_ROLES[parentRoleName], set);2625 -1 }2626 -1 };2627 -12628 -1 /**2629 -1 * Adds all properties and requiredProperties from parent hierarchy.2630 -1 * @param {Object} role2631 -1 * @param {string} propertiesName2632 -1 * @param {Object} propertiesSet2633 -1 * @private2634 -1 */2635 -1 axs.constants.addAllPropertiesToSet_ = function(role, propertiesName,2636 -1 propertiesSet) {2637 -1 var properties = role[propertiesName];2638 -1 if (properties) {2639 -1 for (var i = 0; i < properties.length; i++)2640 -1 propertiesSet[properties[i]] = true;2641 -1 }2642 -1 if (role['parent']) {2643 -1 var parents = role['parent'];2644 -1 for (var j = 0; j < parents.length; j++) {2645 -1 var parentRoleName = parents[j];2646 -1 axs.constants.addAllPropertiesToSet_(2647 -1 axs.constants.ARIA_ROLES[parentRoleName], propertiesName,2648 -1 propertiesSet);2649 -1 }2650 -1 }2651 -1 };2652 -12653 -1 // TODO make a AriaRole object etc.2654 -1 for (var roleName in axs.constants.ARIA_ROLES) {2655 -1 var role = axs.constants.ARIA_ROLES[roleName];2656 -12657 -1 var propertiesSet = {};2658 -1 axs.constants.addAllPropertiesToSet_(role, 'properties', propertiesSet);2659 -1 role['propertiesSet'] = propertiesSet;2660 -12661 -1 var requiredPropertiesSet = {};2662 -1 axs.constants.addAllPropertiesToSet_(role, 'requiredProperties', requiredPropertiesSet);2663 -1 role['requiredPropertiesSet'] = requiredPropertiesSet;2664 -1 var parentRolesSet = {};2665 -1 axs.constants.addAllParentRolesToSet_(role, parentRolesSet);2666 -1 role['allParentRolesSet'] = parentRolesSet;2667 -1 if ('widget' in parentRolesSet)2668 -1 axs.constants.WIDGET_ROLES[roleName] = role;2669 -1 }2670 -12671 -1 // BEGIN ARIA_PROPERTIES_AUTOGENERATED2672 -1 /** @type {Object.<string, Object>} */2673 -1 axs.constants.ARIA_PROPERTIES = {2674 -1 "activedescendant": {2675 -1 "type": "property",2676 -1 "valueType": "idref"2677 -1 },2678 -1 "atomic": {2679 -1 "defaultValue": "false",2680 -1 "type": "property",2681 -1 "valueType": "boolean"2682 -1 },2683 -1 "autocomplete": {2684 -1 "defaultValue": "none",2685 -1 "type": "property",2686 -1 "valueType": "token",2687 -1 "values": [2688 -1 "inline",2689 -1 "list",2690 -1 "both",2691 -1 "none"2692 -1 ]2693 -1 },2694 -1 "busy": {2695 -1 "defaultValue": "false",2696 -1 "type": "state",2697 -1 "valueType": "boolean"2698 -1 },2699 -1 "checked": {2700 -1 "defaultValue": "undefined",2701 -1 "type": "state",2702 -1 "valueType": "token",2703 -1 "values": [2704 -1 "true",2705 -1 "false",2706 -1 "mixed",2707 -1 "undefined"2708 -1 ]2709 -1 },2710 -1 "controls": {2711 -1 "type": "property",2712 -1 "valueType": "idref_list"2713 -1 },2714 -1 "describedby": {2715 -1 "type": "property",2716 -1 "valueType": "idref_list"2717 -1 },2718 -1 "disabled": {2719 -1 "defaultValue": "false",2720 -1 "type": "state",2721 -1 "valueType": "boolean"2722 -1 },2723 -1 "dropeffect": {2724 -1 "defaultValue": "none",2725 -1 "type": "property",2726 -1 "valueType": "token_list",2727 -1 "values": [2728 -1 "copy",2729 -1 "move",2730 -1 "link",2731 -1 "execute",2732 -1 "popup",2733 -1 "none"2734 -1 ]2735 -1 },2736 -1 "expanded": {2737 -1 "defaultValue": "undefined",2738 -1 "type": "state",2739 -1 "valueType": "token",2740 -1 "values": [2741 -1 "true",2742 -1 "false",2743 -1 "undefined"2744 -1 ]2745 -1 },2746 -1 "flowto": {2747 -1 "type": "property",2748 -1 "valueType": "idref_list"2749 -1 },2750 -1 "grabbed": {2751 -1 "defaultValue": "undefined",2752 -1 "type": "state",2753 -1 "valueType": "token",2754 -1 "values": [2755 -1 "true",2756 -1 "false",2757 -1 "undefined"2758 -1 ]2759 -1 },2760 -1 "haspopup": {2761 -1 "defaultValue": "false",2762 -1 "type": "property",2763 -1 "valueType": "boolean"2764 -1 },2765 -1 "hidden": {2766 -1 "defaultValue": "false",2767 -1 "type": "state",2768 -1 "valueType": "boolean"2769 -1 },2770 -1 "invalid": {2771 -1 "defaultValue": "false",2772 -1 "type": "state",2773 -1 "valueType": "token",2774 -1 "values": [2775 -1 "grammar",2776 -1 "false",2777 -1 "spelling",2778 -1 "true"2779 -1 ]2780 -1 },2781 -1 "label": {2782 -1 "type": "property",2783 -1 "valueType": "string"2784 -1 },2785 -1 "labelledby": {2786 -1 "type": "property",2787 -1 "valueType": "idref_list"2788 -1 },2789 -1 "level": {2790 -1 "type": "property",2791 -1 "valueType": "integer"2792 -1 },2793 -1 "live": {2794 -1 "defaultValue": "off",2795 -1 "type": "property",2796 -1 "valueType": "token",2797 -1 "values": [2798 -1 "off",2799 -1 "polite",2800 -1 "assertive"2801 -1 ]2802 -1 },2803 -1 "multiline": {2804 -1 "defaultValue": "false",2805 -1 "type": "property",2806 -1 "valueType": "boolean"2807 -1 },2808 -1 "multiselectable": {2809 -1 "defaultValue": "false",2810 -1 "type": "property",2811 -1 "valueType": "boolean"2812 -1 },2813 -1 "orientation": {2814 -1 "defaultValue": "vertical",2815 -1 "type": "property",2816 -1 "valueType": "token",2817 -1 "values": [2818 -1 "horizontal",2819 -1 "vertical"2820 -1 ]2821 -1 },2822 -1 "owns": {2823 -1 "type": "property",2824 -1 "valueType": "idref_list"2825 -1 },2826 -1 "posinset": {2827 -1 "type": "property",2828 -1 "valueType": "integer"2829 -1 },2830 -1 "pressed": {2831 -1 "defaultValue": "undefined",2832 -1 "type": "state",2833 -1 "valueType": "token",2834 -1 "values": [2835 -1 "true",2836 -1 "false",2837 -1 "mixed",2838 -1 "undefined"2839 -1 ]2840 -1 },2841 -1 "readonly": {2842 -1 "defaultValue": "false",2843 -1 "type": "property",2844 -1 "valueType": "boolean"2845 -1 },2846 -1 "relevant": {2847 -1 "defaultValue": "additions text",2848 -1 "type": "property",2849 -1 "valueType": "token_list",2850 -1 "values": [2851 -1 "additions",2852 -1 "removals",2853 -1 "text",2854 -1 "all"2855 -1 ]2856 -1 },2857 -1 "required": {2858 -1 "defaultValue": "false",2859 -1 "type": "property",2860 -1 "valueType": "boolean"2861 -1 },2862 -1 "selected": {2863 -1 "defaultValue": "undefined",2864 -1 "type": "state",2865 -1 "valueType": "token",2866 -1 "values": [2867 -1 "true",2868 -1 "false",2869 -1 "undefined"2870 -1 ]2871 -1 },2872 -1 "setsize": {2873 -1 "type": "property",2874 -1 "valueType": "integer"2875 -1 },2876 -1 "sort": {2877 -1 "defaultValue": "none",2878 -1 "type": "property",2879 -1 "valueType": "token",2880 -1 "values": [2881 -1 "ascending",2882 -1 "descending",2883 -1 "none",2884 -1 "other"2885 -1 ]2886 -1 },2887 -1 "valuemax": {2888 -1 "type": "property",2889 -1 "valueType": "decimal"2890 -1 },2891 -1 "valuemin": {2892 -1 "type": "property",2893 -1 "valueType": "decimal"2894 -1 },2895 -1 "valuenow": {2896 -1 "type": "property",2897 -1 "valueType": "decimal"2898 -1 },2899 -1 "valuetext": {2900 -1 "type": "property",2901 -1 "valueType": "string"2902 -1 }2903 -1 };2904 -1 // END ARIA_PROPERTIES_AUTOGENERATED2905 -12906 -1 (function() {2907 -1 // pull values lists into sets2908 -1 for (var propertyName in axs.constants.ARIA_PROPERTIES) {2909 -1 var propertyDetails = axs.constants.ARIA_PROPERTIES[propertyName];2910 -1 if (!propertyDetails.values)2911 -1 continue;2912 -1 var valuesSet = {};2913 -1 for (var i = 0; i < propertyDetails.values.length; i++)2914 -1 valuesSet[propertyDetails.values[i]] = true;2915 -1 propertyDetails.valuesSet = valuesSet;2916 -1 }2917 -1 })();2918 -12919 -1 /**2920 -1 * All of the states and properties which apply globally.2921 -1 * @type {Object<!string, !boolean>}2922 -1 */2923 -1 axs.constants.GLOBAL_PROPERTIES = axs.constants.ARIA_ROLES['roletype'].propertiesSet;2924 -12925 -1 /**2926 -1 * A constant indicating no role name.2927 -1 * @type {string}2928 -1 */2929 -1 axs.constants.NO_ROLE_NAME = ' ';2930 -12931 -1 /**2932 -1 * A mapping from ARIA role names to their message ids.2933 -1 * Copied from ChromeVox:2934 -1 * http://code.google.com/p/google-axs-chrome/source/browse/trunk/chromevox/common/aria_util.js2935 -1 * @type {Object.<string, string>}2936 -1 */2937 -1 axs.constants.WIDGET_ROLE_TO_NAME = {2938 -1 'alert' : 'aria_role_alert',2939 -1 'alertdialog' : 'aria_role_alertdialog',2940 -1 'button' : 'aria_role_button',2941 -1 'checkbox' : 'aria_role_checkbox',2942 -1 'columnheader' : 'aria_role_columnheader',2943 -1 'combobox' : 'aria_role_combobox',2944 -1 'dialog' : 'aria_role_dialog',2945 -1 'grid' : 'aria_role_grid',2946 -1 'gridcell' : 'aria_role_gridcell',2947 -1 'link' : 'aria_role_link',2948 -1 'listbox' : 'aria_role_listbox',2949 -1 'log' : 'aria_role_log',2950 -1 'marquee' : 'aria_role_marquee',2951 -1 'menu' : 'aria_role_menu',2952 -1 'menubar' : 'aria_role_menubar',2953 -1 'menuitem' : 'aria_role_menuitem',2954 -1 'menuitemcheckbox' : 'aria_role_menuitemcheckbox',2955 -1 'menuitemradio' : 'aria_role_menuitemradio',2956 -1 'option' : axs.constants.NO_ROLE_NAME,2957 -1 'progressbar' : 'aria_role_progressbar',2958 -1 'radio' : 'aria_role_radio',2959 -1 'radiogroup' : 'aria_role_radiogroup',2960 -1 'rowheader' : 'aria_role_rowheader',2961 -1 'scrollbar' : 'aria_role_scrollbar',2962 -1 'slider' : 'aria_role_slider',2963 -1 'spinbutton' : 'aria_role_spinbutton',2964 -1 'status' : 'aria_role_status',2965 -1 'tab' : 'aria_role_tab',2966 -1 'tabpanel' : 'aria_role_tabpanel',2967 -1 'textbox' : 'aria_role_textbox',2968 -1 'timer' : 'aria_role_timer',2969 -1 'toolbar' : 'aria_role_toolbar',2970 -1 'tooltip' : 'aria_role_tooltip',2971 -1 'treeitem' : 'aria_role_treeitem'2972 -1 };2973 -12974 -12975 -1 /**2976 -1 * @type {Object.<string, string>}2977 -1 * Copied from ChromeVox:2978 -1 * http://code.google.com/p/google-axs-chrome/source/browse/trunk/chromevox/common/aria_util.js2979 -1 */2980 -1 axs.constants.STRUCTURE_ROLE_TO_NAME = {2981 -1 'article' : 'aria_role_article',2982 -1 'application' : 'aria_role_application',2983 -1 'banner' : 'aria_role_banner',2984 -1 'columnheader' : 'aria_role_columnheader',2985 -1 'complementary' : 'aria_role_complementary',2986 -1 'contentinfo' : 'aria_role_contentinfo',2987 -1 'definition' : 'aria_role_definition',2988 -1 'directory' : 'aria_role_directory',2989 -1 'document' : 'aria_role_document',2990 -1 'form' : 'aria_role_form',2991 -1 'group' : 'aria_role_group',2992 -1 'heading' : 'aria_role_heading',2993 -1 'img' : 'aria_role_img',2994 -1 'list' : 'aria_role_list',2995 -1 'listitem' : 'aria_role_listitem',2996 -1 'main' : 'aria_role_main',2997 -1 'math' : 'aria_role_math',2998 -1 'navigation' : 'aria_role_navigation',2999 -1 'note' : 'aria_role_note',3000 -1 'region' : 'aria_role_region',3001 -1 'rowheader' : 'aria_role_rowheader',3002 -1 'search' : 'aria_role_search',3003 -1 'separator' : 'aria_role_separator'3004 -1 };3005 -13006 -13007 -1 /**3008 -1 * @type {Array.<Object>}3009 -1 * Copied from ChromeVox:3010 -1 * http://code.google.com/p/google-axs-chrome/source/browse/trunk/chromevox/common/aria_util.js3011 -1 */3012 -1 axs.constants.ATTRIBUTE_VALUE_TO_STATUS = [3013 -1 { name: 'aria-autocomplete', values:3014 -1 {'inline' : 'aria_autocomplete_inline',3015 -1 'list' : 'aria_autocomplete_list',3016 -1 'both' : 'aria_autocomplete_both'} },3017 -1 { name: 'aria-checked', values:3018 -1 {'true' : 'aria_checked_true',3019 -1 'false' : 'aria_checked_false',3020 -1 'mixed' : 'aria_checked_mixed'} },3021 -1 { name: 'aria-disabled', values:3022 -1 {'true' : 'aria_disabled_true'} },3023 -1 { name: 'aria-expanded', values:3024 -1 {'true' : 'aria_expanded_true',3025 -1 'false' : 'aria_expanded_false'} },3026 -1 { name: 'aria-invalid', values:3027 -1 {'true' : 'aria_invalid_true',3028 -1 'grammar' : 'aria_invalid_grammar',3029 -1 'spelling' : 'aria_invalid_spelling'} },3030 -1 { name: 'aria-multiline', values:3031 -1 {'true' : 'aria_multiline_true'} },3032 -1 { name: 'aria-multiselectable', values:3033 -1 {'true' : 'aria_multiselectable_true'} },3034 -1 { name: 'aria-pressed', values:3035 -1 {'true' : 'aria_pressed_true',3036 -1 'false' : 'aria_pressed_false',3037 -1 'mixed' : 'aria_pressed_mixed'} },3038 -1 { name: 'aria-readonly', values:3039 -1 {'true' : 'aria_readonly_true'} },3040 -1 { name: 'aria-required', values:3041 -1 {'true' : 'aria_required_true'} },3042 -1 { name: 'aria-selected', values:3043 -1 {'true' : 'aria_selected_true',3044 -1 'false' : 'aria_selected_false'} }3045 -1 ];3046 -13047 -1 /**3048 -1 * Copied from ChromeVox:3049 -1 * http://code.google.com/p/google-axs-chrome/source/browse/trunk/chromevox/common/dom_util.js3050 -1 * @type {Object}3051 -1 */3052 -1 axs.constants.INPUT_TYPE_TO_INFORMATION_TABLE_MSG = {3053 -1 'button' : 'input_type_button',3054 -1 'checkbox' : 'input_type_checkbox',3055 -1 'color' : 'input_type_color',3056 -1 'datetime' : 'input_type_datetime',3057 -1 'datetime-local' : 'input_type_datetime_local',3058 -1 'date' : 'input_type_date',3059 -1 'email' : 'input_type_email',3060 -1 'file' : 'input_type_file',3061 -1 'image' : 'input_type_image',3062 -1 'month' : 'input_type_month',3063 -1 'number' : 'input_type_number',3064 -1 'password' : 'input_type_password',3065 -1 'radio' : 'input_type_radio',3066 -1 'range' : 'input_type_range',3067 -1 'reset' : 'input_type_reset',3068 -1 'search' : 'input_type_search',3069 -1 'submit' : 'input_type_submit',3070 -1 'tel' : 'input_type_tel',3071 -1 'text' : 'input_type_text',3072 -1 'url' : 'input_type_url',3073 -1 'week' : 'input_type_week'3074 -1 };3075 -13076 -13077 -1 /**3078 -1 * Copied from ChromeVox:3079 -1 * http://code.google.com/p/google-axs-chrome/source/browse/trunk/chromevox/common/dom_util.js3080 -1 * @type {Object}3081 -1 */3082 -1 axs.constants.TAG_TO_INFORMATION_TABLE_VERBOSE_MSG = {3083 -1 'A' : 'tag_link',3084 -1 'BUTTON' : 'tag_button',3085 -1 'H1' : 'tag_h1',3086 -1 'H2' : 'tag_h2',3087 -1 'H3' : 'tag_h3',3088 -1 'H4' : 'tag_h4',3089 -1 'H5' : 'tag_h5',3090 -1 'H6' : 'tag_h6',3091 -1 'LI' : 'tag_li',3092 -1 'OL' : 'tag_ol',3093 -1 'SELECT' : 'tag_select',3094 -1 'TEXTAREA' : 'tag_textarea',3095 -1 'UL' : 'tag_ul',3096 -1 'SECTION' : 'tag_section',3097 -1 'NAV' : 'tag_nav',3098 -1 'ARTICLE' : 'tag_article',3099 -1 'ASIDE' : 'tag_aside',3100 -1 'HGROUP' : 'tag_hgroup',3101 -1 'HEADER' : 'tag_header',3102 -1 'FOOTER' : 'tag_footer',3103 -1 'TIME' : 'tag_time',3104 -1 'MARK' : 'tag_mark'3105 -1 };3106 -13107 -1 /**3108 -1 * Copied from ChromeVox:3109 -1 * http://code.google.com/p/google-axs-chrome/source/browse/trunk/chromevox/common/dom_util.js3110 -1 * @type {Object}3111 -1 */3112 -1 axs.constants.TAG_TO_INFORMATION_TABLE_BRIEF_MSG = {3113 -1 'BUTTON' : 'tag_button',3114 -1 'SELECT' : 'tag_select',3115 -1 'TEXTAREA' : 'tag_textarea'3116 -1 };3117 -13118 -1 axs.constants.MIXED_VALUES = {3119 -1 "true": true,3120 -1 "false": true,3121 -1 "mixed": true3122 -1 };3123 -13124 -1 /** @enum {string} */3125 -1 axs.constants.Severity = {3126 -1 INFO: 'Info',3127 -1 WARNING: 'Warning',3128 -1 SEVERE: 'Severe'3129 -1 };3130 -13131 -1 /** @enum {string} */3132 -1 axs.constants.AuditResult = {3133 -1 PASS: 'PASS',3134 -1 FAIL: 'FAIL',3135 -1 NA: 'NA'3136 -1 };3137 -13138 -1 /** @enum {boolean} */3139 -1 axs.constants.InlineElements = {3140 -1 // fontstyle3141 -1 'TT': true,3142 -1 'I': true,3143 -1 'B': true,3144 -1 'BIG': true,3145 -1 'SMALL': true,3146 -13147 -1 // phrase3148 -1 'EM': true,3149 -1 'STRONG': true,3150 -1 'DFN': true,3151 -1 'CODE': true,3152 -1 'SAMP': true,3153 -1 'KBD': true,3154 -1 'VAR': true,3155 -1 'CITE': true,3156 -1 'ABBR': true,3157 -1 'ACRONYM': true,3158 -13159 -1 // special3160 -1 'A': true,3161 -1 'IMG': true,3162 -1 'OBJECT': true,3163 -1 'BR': true,3164 -1 'SCRIPT': true,3165 -1 'MAP': true,3166 -1 'Q': true,3167 -1 'SUB': true,3168 -1 'SUP': true,3169 -1 'SPAN': true,3170 -1 'BDO': true,3171 -13172 -1 // formctrl3173 -1 'INPUT': true,3174 -1 'SELECT': true,3175 -1 'TEXTAREA': true,3176 -1 'LABEL': true,3177 -1 'BUTTON': true3178 -1 };3179 -13180 -1 /** @enum {boolean} */3181 -1 axs.constants.NATIVELY_DISABLEABLE = {3182 -1 // W3C and WHATWG https://html.spec.whatwg.org/#enabling-and-disabling-form-controls:-the-disabled-attribute3183 -1 'BUTTON': true,3184 -1 'INPUT': true,3185 -1 'SELECT': true,3186 -1 'TEXTAREA': true,3187 -1 'FIELDSET': true,3188 -13189 -1 // W3C http://www.w3.org/TR/html5/disabled-elements.html#disabled-elements3190 -1 'OPTGROUP': true,3191 -1 'OPTION': true3192 -1 };3193 -13194 -1 /**3195 -1 * Maps ARIA attributes to their exactly equivalent HTML attributes.3196 -1 * @type {Object.<string, string>}3197 -1 */3198 -1 axs.constants.ARIA_TO_HTML_ATTRIBUTE = {3199 -1 'aria-checked' : 'checked',3200 -1 'aria-disabled' : 'disabled',3201 -1 'aria-hidden' : 'hidden',3202 -1 'aria-expanded' : 'open',3203 -1 'aria-valuemax' : 'max',3204 -1 'aria-valuemin' : 'min',3205 -1 'aria-readonly' : 'readonly',3206 -1 'aria-required' : 'required',3207 -1 'aria-selected' : 'selected',3208 -1 'aria-valuenow' : 'value'3209 -1 };3210 -13211 -1 /**3212 -1 * Holds information about implicit ARIA semantics for a given HTML element type.3213 -1 * This object has the following properties:3214 -1 * <ul>3215 -1 * <li>`role` will contain the implicit role if it exists, otherwise empty string.</li>3216 -1 * <li>`allowed` contains the roles that can reasonably be applied to this element.3217 -1 * Note: A tag that can take any role is signified by a '*' wildcard in the array. It is not3218 -1 * an error if the array contains other roles but currently this has no meaning. In future it may3219 -1 * be used to indicate recommended roles.3220 -1 * </li>3221 -1 * <li>`selector` is present if this is a 'subclass' of the base HTML element, i.e. its semantics are3222 -1 * modified by context or attributes. It can be used with the selectors API to find and/or match3223 -1 * elements.3224 -1 * </li>3225 -1 * <li>`reserved` will be true if this is a semantically strong element that you may not modify with any3226 -1 * ARIA attributes, including role or global attributes.3227 -1 * </li>3228 -1 * </ul>3229 -1 *3230 -1 * @typedef {{ role: string,3231 -1 * allowed: Array.<string>,3232 -1 * selector: string,3233 -1 * reserved: boolean }}3234 -1 */3235 -1 axs.constants.HtmlInfo;3236 -1 /**3237 -1 * A lookup table which maps uppercase tagName to information about implicit ARIA semantics.3238 -1 * This table is based on the document: http://w3c.github.io/aria-in-html/3239 -1 * It is not complete and never can be. Complex scenarios require specific handling not provided here.3240 -1 * Any element not listed here:3241 -1 * - has no implicit role3242 -1 * - can take any role3243 -1 * e.g. em,strong,small,s,cite,q,dfn,abbr,time,code,var,samp,kbd,sub and sup,i,b,u,mark ,ruby,rt,rp,bdi,bdo,br,wbr3244 -1 *3245 -1 * Where there is any ambiguity this table will endeavor to provide for the most broad case (to avoid3246 -1 * false failures in conformance checking).3247 -1 *3248 -1 * For example 'table' can take any role however in practice it should only be given the role 'grid' when3249 -1 * being used as a data grid or 'presentation' when used for layout. This lookup ignores these nuances and3250 -1 * allows all roles.3251 -1 *3252 -1 * @type {Object.<string, Array.<axs.constants.HtmlInfo>>}3253 -1 */3254 -1 axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO = {3255 -1 'A': [{3256 -1 role: 'link',3257 -1 allowed: [3258 -1 'button',3259 -1 'checkbox',3260 -1 'menuitem',3261 -1 'menuitemcheckbox',3262 -1 'menuitemradio',3263 -1 'tab',3264 -1 'treeitem'],3265 -1 selector: 'a[href]'3266 -1 }],3267 -1 'ADDRESS': [{3268 -1 role: '',3269 -1 allowed: [3270 -1 'contentinfo',3271 -1 'presentation']3272 -1 }],3273 -1 'AREA': [{3274 -1 role: 'link',3275 -1 selector: 'area[href]'3276 -1 }],3277 -1 'ARTICLE': [{3278 -1 role: 'article',3279 -1 allowed: [3280 -1 'presentation',3281 -1 'article',3282 -1 'document',3283 -1 'application',3284 -1 'main']3285 -1 }],3286 -1 'ASIDE': [{3287 -1 role: 'complementary',3288 -1 allowed: [3289 -1 'note',3290 -1 'complementary',3291 -1 'search',3292 -1 'presentation']3293 -1 }],3294 -1 'AUDIO': [{3295 -1 role: '',3296 -1 allowed: ['application', 'presentation']3297 -1 }],3298 -1 'BASE': [{3299 -1 role: '',3300 -1 reserved: true3301 -1 }],3302 -1 'BODY': [{3303 -1 role: 'document',3304 -1 allowed: ['presentation']3305 -1 }],3306 -1 'BUTTON': [{3307 -1 role: 'button',3308 -1 allowed: [3309 -1 'link',3310 -1 'menuitem',3311 -1 'menuitemcheckbox',3312 -1 'menuitemradio',3313 -1 'radio'],3314 -1 selector: 'button:not([aria-pressed]):not([type="menu"])'3315 -1 }, {3316 -1 role: 'button',3317 -1 allowed: ['button'],3318 -1 selector: 'button[aria-pressed]'3319 -1 }, {3320 -1 role: 'button',3321 -1 attributes: {3322 -1 'aria-haspopup': true3323 -1 },3324 -1 allowed: [3325 -1 'link',3326 -1 'menuitem',3327 -1 'menuitemcheckbox',3328 -1 'menuitemradio',3329 -1 'radio'],3330 -1 selector: 'button[type="menu"]'3331 -1 }],3332 -1 'CAPTION': [{3333 -1 role: '',3334 -1 allowed: ['presentation']3335 -1 }],3336 -1 'COL': [{3337 -1 role: '',3338 -1 reserved: true3339 -1 }],3340 -1 'COLGROUP': [{3341 -1 role: '',3342 -1 reserved: true3343 -1 }],3344 -1 'DATALIST': [{3345 -1 role: 'listbox',3346 -1 attributes: {3347 -1 'aria-multiselectable': false3348 -1 },3349 -1 allowed: ['presentation']3350 -1 }],3351 -1 'DEL': [{3352 -1 role: '',3353 -1 allowed: ['*']3354 -1 }],3355 -1 'DD': [{3356 -1 role: '',3357 -1 allowed: ['presentation']3358 -1 }],3359 -1 'DT': [{3360 -1 role: '',3361 -1 allowed: ['presentation']3362 -1 }],3363 -1 'DETAILS': [{3364 -1 role: 'group',3365 -1 allowed: [3366 -1 'group',3367 -1 'presentation']3368 -1 }],3369 -1 'DIALOG': [{ // updated 'allowed' from: http://www.w3.org/html/wg/drafts/html/master/interactive-elements.html#the-dialog-element3370 -1 role: 'dialog',3371 -1 allowed: ['dialog', 'alert', 'alertdialog', 'application', 'log', 'marquee', 'status'],3372 -1 selector: 'dialog[open]'3373 -1 }, {3374 -1 role: 'dialog',3375 -1 attributes: {3376 -1 'aria-hidden': true3377 -1 },3378 -1 allowed: ['dialog', 'alert', 'alertdialog', 'application', 'log', 'marquee', 'status'],3379 -1 selector: 'dialog:not([open])'3380 -1 }],3381 -1 'DIV': [{3382 -1 role: '',3383 -1 allowed: ['*']3384 -1 }],3385 -1 'DL': [{3386 -1 role: 'list',3387 -1 allowed: ['presentation']3388 -1 }],3389 -1 'EMBED': [{3390 -1 role: '',3391 -1 allowed: [3392 -1 'application',3393 -1 'document',3394 -1 'img',3395 -1 'presentation']3396 -1 }],3397 -1 'FIGURE': [{3398 -1 role: '',3399 -1 allowed: ['*']3400 -1 }],3401 -1 'FOOTER': [{3402 -1 role: '',3403 -1 allowed: ['contentinfo', 'presentation']3404 -1 }],3405 -1 'FORM': [{3406 -1 role: 'form',3407 -1 allowed: ['presentation']3408 -1 }],3409 -1 'P': [{3410 -1 role: '',3411 -1 allowed: ['*']3412 -1 }],3413 -1 'PRE': [{3414 -1 role: '',3415 -1 allowed: ['*']3416 -1 }],3417 -1 'BLOCKQUOTE': [{3418 -1 role: '',3419 -1 allowed: ['*']3420 -1 }],3421 -1 H1: [{3422 -1 role: 'heading'3423 -1 }],3424 -1 H2: [{3425 -1 role: 'heading'3426 -1 }],3427 -1 H3: [{3428 -1 role: 'heading'3429 -1 }],3430 -1 H4: [{3431 -1 role: 'heading'3432 -1 }],3433 -1 H5: [{3434 -1 role: 'heading'3435 -1 }],3436 -1 H6: [{3437 -1 role: 'heading'3438 -1 }],3439 -1 'HEAD': [{3440 -1 role: '',3441 -1 reserved: true3442 -1 }],3443 -1 'HEADER': [{3444 -1 role: '',3445 -1 allowed: [3446 -1 'banner',3447 -1 'presentation']3448 -1 }],3449 -1 'HR': [{3450 -1 role: 'separator',3451 -1 allowed: ['presentation']3452 -1 }],3453 -1 'HTML': [{3454 -1 role: '',3455 -1 reserved: true3456 -1 }],3457 -1 'IFRAME': [{3458 -1 role: '',3459 -1 allowed: [3460 -1 'application',3461 -1 'document',3462 -1 'img',3463 -1 'presentation'],3464 -1 selector: 'iframe:not([seamless])'3465 -1 }, {3466 -1 role: '',3467 -1 allowed: [3468 -1 'application',3469 -1 'document',3470 -1 'img',3471 -1 'presentation',3472 -1 'group'],3473 -1 selector: 'iframe[seamless]'3474 -1 }],3475 -1 'IMG': [{3476 -1 role: 'presentation',3477 -1 reserved: true,3478 -1 selector: 'img[alt=""]'3479 -1 }, {3480 -1 role: 'img',3481 -1 allowed: ['*'],3482 -1 selector: 'img[alt]:not([alt=""])'3483 -1 }],3484 -1 'INPUT': [{3485 -1 role: 'button',3486 -1 allowed: [3487 -1 'link',3488 -1 'menuitem',3489 -1 'menuitemcheckbox',3490 -1 'menuitemradio',3491 -1 'radio'],3492 -1 selector: 'input[type="button"]:not([aria-pressed])'3493 -1 }, {3494 -1 role: 'button',3495 -1 allowed: ['button'],3496 -1 selector: 'input[type="button"][aria-pressed]'3497 -1 }, {3498 -1 role: 'checkbox',3499 -1 allowed: ['checkbox'],3500 -1 selector: 'input[type="checkbox"]'3501 -1 }, {3502 -1 role: '',3503 -1 selector: 'input[type="color"]'3504 -1 }, {3505 -1 role: '',3506 -1 selector: 'input[type="date"]'3507 -1 }, {3508 -1 role: '',3509 -1 selector: 'input[type="datetime"]'3510 -1 }, {3511 -1 role: 'textbox',3512 -1 selector: 'input[type="email"]:not([list])'3513 -1 }, {3514 -1 role: '',3515 -1 selector: 'input[type="file"]'3516 -1 }, {3517 -1 role: '',3518 -1 reserved: true,3519 -1 selector: 'input[type="hidden"]'3520 -1 }, {3521 -1 role: 'button',3522 -1 allowed: ['button'],3523 -1 selector: 'input[type="image"][aria-pressed]'3524 -1 }, {3525 -1 role: 'button',3526 -1 allowed: [3527 -1 'link',3528 -1 'menuitem',3529 -1 'menuitemcheckbox',3530 -1 'menuitemradio',3531 -1 'radio'],3532 -1 selector: 'input[type="image"]:not([aria-pressed])'3533 -1 }, {3534 -1 role: '',3535 -1 selector: 'input[type="month"]'3536 -1 }, {3537 -1 role: '',3538 -1 selector: 'input[type="number"]'3539 -1 }, {3540 -1 role: 'textbox',3541 -1 selector: 'input[type="password"]'3542 -1 }, {3543 -1 role: 'radio',3544 -1 allowed: ['menuitemradio'],3545 -1 selector: 'input[type="radio"]'3546 -1 }, {3547 -1 role: 'slider',3548 -1 selector: 'input[type="range"]'3549 -1 }, {3550 -1 role: 'button',3551 -1 selector: 'input[type="reset"]'3552 -1 }, {3553 -1 role: 'combobox', // aria-owns is set to the same value as the list attribute3554 -1 selector: 'input[type="search"][list]'3555 -1 }, {3556 -1 role: 'textbox',3557 -1 selector: 'input[type="search"]:not([list])'3558 -1 }, {3559 -1 role: 'button',3560 -1 selector: 'input[type="submit"]'3561 -1 }, {3562 -1 role: 'combobox', // aria-owns is set to the same value as the list attribute3563 -1 selector: 'input[type="tel"][list]'3564 -1 }, {3565 -1 role: 'textbox',3566 -1 selector: 'input[type="tel"]:not([list])'3567 -1 }, {3568 -1 role: 'combobox', // aria-owns is set to the same value as the list attribute3569 -1 selector: 'input[type="text"][list]'3570 -1 }, {3571 -1 role: 'textbox',3572 -1 selector: 'input[type="text"]:not([list])'3573 -1 }, {3574 -1 role: 'textbox',3575 -1 selector: 'input:not([type])'3576 -1 }, {3577 -1 role: '',3578 -1 selector: 'input[type="time"]'3579 -1 }, {3580 -1 role: 'combobox', // aria-owns is set to the same value as the list attribute3581 -1 selector: 'input[type="url"][list]'3582 -1 }, {3583 -1 role: 'textbox',3584 -1 selector: 'input[type="url"]:not([list])'3585 -1 }, {3586 -1 role: '',3587 -1 selector: 'input[type="week"]'3588 -1 }],3589 -1 'INS': [{3590 -1 role: '',3591 -1 allowed: ['*']3592 -1 }],3593 -1 'KEYGEN': [{3594 -1 role: ''3595 -1 }],3596 -1 'LABEL': [{3597 -1 role: '',3598 -1 allowed: ['presentation']3599 -1 }],3600 -1 'LI': [{3601 -1 role: 'listitem',3602 -1 allowed: [3603 -1 'menuitem',3604 -1 'menuitemcheckbox',3605 -1 'menuitemradio',3606 -1 'option',3607 -1 'tab',3608 -1 'treeitem',3609 -1 'presentation'],3610 -1 selector: 'ol:not([role="presentation"])>li, ul:not([role="presentation"])>li'3611 -1 }, {3612 -1 role: 'listitem',3613 -1 allowed: [3614 -1 'listitem',3615 -1 'menuitem',3616 -1 'menuitemcheckbox',3617 -1 'menuitemradio',3618 -1 'option',3619 -1 'tab',3620 -1 'treeitem',3621 -1 'presentation'],3622 -1 selector: 'ol[role="presentation"]>li, ul[role="presentation"]>li'3623 -1 }],3624 -1 'LINK': [{3625 -1 role: 'link',3626 -1 reserved: true,3627 -1 selector: 'link[href]'3628 -1 }],3629 -1 'MAIN': [{3630 -1 role: '',3631 -1 allowed: [3632 -1 'main',3633 -1 'presentation']3634 -1 }],3635 -1 'MAP': [{3636 -1 role: '',3637 -1 reserved: true3638 -1 }],3639 -1 'MATH': [{3640 -1 role: '',3641 -1 allowed: ['presentation']3642 -1 }],3643 -1 'MENU': [{3644 -1 role: 'toolbar',3645 -1 selector: 'menu[type="toolbar"]'3646 -1 }],3647 -1 'MENUITEM': [{3648 -1 role: 'menuitem',3649 -1 selector: 'menuitem[type="command"]'3650 -1 }, {3651 -1 role: 'menuitemcheckbox',3652 -1 selector: 'menuitem[type="checkbox"]'3653 -1 }, {3654 -1 role: 'menuitemradio',3655 -1 selector: 'menuitem[type="radio"]'3656 -1 }],3657 -1 'META': [{3658 -1 role: '',3659 -1 reserved: true3660 -1 }],3661 -1 'METER': [{3662 -1 role: 'progressbar',3663 -1 allowed: ['presentation']3664 -1 }],3665 -1 'NAV': [{3666 -1 role: 'navigation',3667 -1 allowed: ['navigation', 'presentation']3668 -1 }],3669 -1 'NOSCRIPT': [{3670 -1 role: '',3671 -1 reserved: true3672 -1 }],3673 -1 'OBJECT': [{3674 -1 role: '',3675 -1 allowed: ['application', 'document', 'img', 'presentation']3676 -1 }],3677 -1 'OL': [{3678 -1 role: 'list',3679 -1 allowed: ['directory', 'group', 'listbox', 'menu', 'menubar', 'tablist', 'toolbar', 'tree', 'presentation']3680 -1 }],3681 -1 'OPTGROUP': [{3682 -1 role: '',3683 -1 allowed: ['presentation']3684 -1 }],3685 -1 'OPTION': [{3686 -1 role: 'option'3687 -1 }],3688 -1 'OUTPUT': [{3689 -1 role: 'status',3690 -1 allowed: ['*']3691 -1 }],3692 -1 'PARAM': [{3693 -1 role: '',3694 -1 reserved: true3695 -1 }],3696 -1 'PICTURE': [{3697 -1 role: '',3698 -1 reserved: true3699 -1 }],3700 -1 'PROGRESS': [{3701 -1 role: 'progressbar',3702 -1 allowed: ['presentation']3703 -1 }],3704 -1 'SCRIPT': [{3705 -1 role: '',3706 -1 reserved: true3707 -1 }],3708 -1 'SECTION': [{3709 -1 role: 'region',3710 -1 allowed: [3711 -1 'alert',3712 -1 'alertdialog',3713 -1 'application',3714 -1 'contentinfo',3715 -1 'dialog',3716 -1 'document',3717 -1 'log',3718 -1 'marquee',3719 -1 'search',3720 -1 'status',3721 -1 'presentation']3722 -1 }],3723 -1 'SELECT': [{3724 -1 role: 'listbox'3725 -1 }],3726 -1 'SOURCE': [{3727 -1 role: '',3728 -1 reserved: true3729 -1 }],3730 -1 'SPAN': [{3731 -1 role: '',3732 -1 allowed: ['*']3733 -1 }],3734 -1 'STYLE': [{3735 -1 role: '',3736 -1 reserved: true3737 -1 }],3738 -1 'SVG': [{3739 -1 role: '',3740 -1 allowed: [3741 -1 'application',3742 -1 'document',3743 -1 'img',3744 -1 'presentation']3745 -1 }],3746 -1 'SUMMARY': [{3747 -1 role: '',3748 -1 allowed: ['presentation']3749 -1 }],3750 -1 'TABLE': [{3751 -1 role: '',3752 -1 allowed: ['*']3753 -1 }],3754 -1 'TEMPLATE': [{3755 -1 role: '',3756 -1 reserved: true3757 -1 }],3758 -1 'TEXTAREA': [{3759 -1 role: 'textbox'3760 -1 }],3761 -1 'TBODY': [{3762 -1 role: 'rowgroup',3763 -1 allowed: ['*']3764 -1 }],3765 -1 'THEAD': [{3766 -1 role: 'rowgroup',3767 -1 allowed: ['*']3768 -1 }],3769 -1 'TFOOT': [{3770 -1 role: 'rowgroup',3771 -1 allowed: ['*']3772 -1 }],3773 -1 'TITLE': [{3774 -1 role: '',3775 -1 reserved: true3776 -1 }],3777 -1 'TD': [{3778 -1 role: '',3779 -1 allowed: ['*']3780 -1 }],3781 -1 'TH': [{3782 -1 role: '',3783 -1 allowed: ['*']3784 -1 }],3785 -1 'TR': [{3786 -1 role: '',3787 -1 allowed: ['*']3788 -1 }],3789 -1 'TRACK': [{3790 -1 role: '',3791 -1 reserved: true3792 -1 }],3793 -1 'UL': [{3794 -1 role: 'list',3795 -1 allowed: [3796 -1 'directory',3797 -1 'group',3798 -1 'listbox',3799 -1 'menu',3800 -1 'menubar',3801 -1 'tablist',3802 -1 'toolbar',3803 -1 'tree',3804 -1 'presentation']3805 -1 }],3806 -1 'VIDEO': [{3807 -1 role: '',3808 -1 allowed: ['application', 'presentation']3809 -1 }]3810 -1 };3811 -13812 -1 },{}],7:[function(require,module,exports){3813 -1 // Copyright 2015 Google Inc.3814 -1 //3815 -1 // Licensed under the Apache License, Version 2.0 (the "License");3816 -1 // you may not use this file except in compliance with the License.3817 -1 // You may obtain a copy of the License at3818 -1 //3819 -1 // http://www.apache.org/licenses/LICENSE-2.03820 -1 //3821 -1 // Unless required by applicable law or agreed to in writing, software3822 -1 // distributed under the License is distributed on an "AS IS" BASIS,3823 -1 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.3824 -1 // See the License for the specific language governing permissions and3825 -1 // limitations under the License.3826 -13827 -1 goog.provide('axs.dom');3828 -13829 -1 /**3830 -1 * Returns the nearest ancestor which is an Element.3831 -1 * @param {Node} node3832 -1 * @return {?Element}3833 -1 */3834 -1 axs.dom.parentElement = function(node) {3835 -1 if (!node)3836 -1 return null;3837 -13838 -1 var parentNode = axs.dom.composedParentNode(node);3839 -1 if (!parentNode)3840 -1 return null;3841 -13842 -1 switch (parentNode.nodeType) {3843 -1 case Node.ELEMENT_NODE:3844 -1 return /** @type {Element} */ (parentNode);3845 -1 default:3846 -1 return axs.dom.parentElement(parentNode);3847 -1 }3848 -1 };3849 -13850 -1 /**3851 -1 * Returns the shadow host of a document fragment if it is a Shadow DOM fragment3852 -1 * otherwise returns `null`.3853 -1 * @param {DocumentFragment} fragment3854 -1 * @return {?Element}3855 -1 */3856 -1 axs.dom.shadowHost = function(fragment) {3857 -1 // If host exists, this is a Shadow DOM fragment.3858 -1 if ('host' in fragment)3859 -1 return fragment.host;3860 -1 else3861 -1 return null;3862 -1 };3863 -13864 -1 /**3865 -1 * Returns the given Node's parent in the composed tree.3866 -1 * @param {Node} node3867 -1 * @return {?Node}3868 -1 */3869 -1 axs.dom.composedParentNode = function(node) {3870 -1 if (!node)3871 -1 return null;3872 -1 if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE)3873 -1 return axs.dom.shadowHost(/** @type {DocumentFragment} */ (node));3874 -13875 -1 var parentNode = node.parentNode;3876 -1 if (!parentNode)3877 -1 return null;3878 -13879 -1 if (parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE)3880 -1 return axs.dom.shadowHost(/** @type {DocumentFragment} */ (parentNode));3881 -13882 -1 if (!parentNode.shadowRoot)3883 -1 return parentNode;3884 -13885 -1 // Shadow DOM v13886 -1 if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE) {3887 -1 var assignedSlot = node.assignedSlot;3888 -1 if (HTMLSlotElement && assignedSlot instanceof HTMLSlotElement)3889 -1 return axs.dom.composedParentNode(assignedSlot);3890 -1 }3891 -13892 -1 // Shadow DOM v03893 -1 if (typeof node.getDestinationInsertionPoints === 'function') {3894 -1 var insertionPoints = node.getDestinationInsertionPoints();3895 -1 if (insertionPoints.length > 0)3896 -1 return axs.dom.composedParentNode(insertionPoints[insertionPoints.length - 1]);3897 -1 }3898 -13899 -1 return null;3900 -1 };3901 -13902 -1 /**3903 -1 * Return the corresponding element for the given node.3904 -1 * @param {Node} node3905 -1 * @return {Element}3906 -1 * @suppress {checkTypes}3907 -1 */3908 -1 axs.dom.asElement = function(node) {3909 -1 /** @type {Element} */ var element;3910 -1 switch (node.nodeType) {3911 -1 case Node.COMMENT_NODE:3912 -1 return null; // Skip comments3913 -1 case Node.ELEMENT_NODE:3914 -1 element = /** (@type {Element}) */ node;3915 -1 if (element.localName == 'script' ||3916 -1 element.localName == 'template')3917 -1 return null; // Skip script-supporting elements3918 -1 return element;3919 -1 case Node.DOCUMENT_FRAGMENT_NODE:3920 -1 return node.host;3921 -1 case Node.TEXT_NODE:3922 -1 return axs.dom.parentElement(node);3923 -1 default:3924 -1 console.warn('Unhandled node type: ', node.nodeType);3925 -1 }3926 -1 return null;3927 -1 };3928 -13929 -1 /**3930 -1 * Recursively walk the composed tree from |node|, aborting if |end| is encountered.3931 -1 * @param {Node} node3932 -1 * @param {?Node} end3933 -1 * @param {{preorder: (function (Node, Object):boolean|undefined),3934 -1 * postorder: (function (Node, Object)|undefined)}} callbacks3935 -1 * Callbacks to be called for each element traversed, excluding3936 -1 * |end|. Possible callbacks are |preorder|, called before descending into3937 -1 * child nodes, and |postorder| called after all child nodes have been3938 -1 * traversed. If |preorder| returns false, its child nodes will not be3939 -1 * traversed.3940 -1 * @param {Object} parentFlags3941 -1 * @param {ShadowRoot=} opt_shadowRoot The nearest ShadowRoot ancestor, if any.3942 -1 * @return {boolean} Whether |end| was found, if provided.3943 -1 */3944 -1 axs.dom.composedTreeSearch = function(node, end, callbacks, parentFlags, opt_shadowRoot) {3945 -1 if (node === end)3946 -1 return true;3947 -13948 -1 if (node.nodeType == Node.ELEMENT_NODE)3949 -1 var element = /** @type {Element} */ (node);3950 -13951 -1 var found = false;3952 -1 var flags = Object.create(parentFlags);3953 -13954 -1 // Descend into node:3955 -1 // If it has a ShadowRoot, ignore all child elements - these will be picked3956 -1 // up by the <content> or <shadow> elements. Descend straight into the3957 -1 // ShadowRoot.3958 -1 if (element) {3959 -1 var localName = element.localName;3960 -1 if (flags.collectIdRefs) {3961 -1 flags.idrefs = axs.utils.getReferencedIds(element);3962 -1 }3963 -1 if (!flags.disabled || (localName === 'legend') && axs.browserUtils.matchSelector(element, 'fieldset>legend:first-of-type')) {3964 -1 flags.disabled = axs.utils.isElementDisabled(element, true);3965 -1 }3966 -1 if (!flags.hidden) {3967 -1 flags.hidden = axs.utils.isElementHidden(element);3968 -1 }3969 -1 if (callbacks.preorder) {3970 -1 if (!callbacks.preorder(element, flags))3971 -1 return found;3972 -1 }3973 -1 // NOTE: grunt qunit DOES NOT support Shadow DOM, so if changing this3974 -1 // code, be sure to run the tests in the browser before committing.3975 -1 var shadowRoot = element.shadowRoot || element.webkitShadowRoot;3976 -1 if (shadowRoot) {3977 -1 flags.level++;3978 -1 found = axs.dom.composedTreeSearch(shadowRoot,3979 -1 end,3980 -1 callbacks,3981 -1 flags,3982 -1 shadowRoot);3983 -1 if (element && callbacks.postorder && !found)3984 -1 callbacks.postorder(element, flags);3985 -1 return found;3986 -1 }3987 -13988 -1 // If it is a <content> element, descend into distributed elements - these3989 -1 // are elements from outside the shadow root which are rendered inside the3990 -1 // shadow DOM.3991 -1 if (localName == 'content' && typeof element.getDistributedNodes === 'function') {3992 -1 var content = /** @type {HTMLContentElement} */ (element);3993 -1 var distributedNodes = content.getDistributedNodes();3994 -1 for (var i = 0; i < distributedNodes.length && !found; i++) {3995 -1 found = axs.dom.composedTreeSearch(distributedNodes[i],3996 -1 end,3997 -1 callbacks,3998 -1 flags,3999 -1 opt_shadowRoot);4000 -1 }4001 -1 if (callbacks.postorder && !found)4002 -1 callbacks.postorder.call(null, element, flags);4003 -1 return found;4004 -1 }4005 -1 }4006 -14007 -14008 -14009 -1 // If it is neither the parent of a ShadowRoot, a <content> element, nor4010 -1 // a <shadow> element recurse normally.4011 -1 var child = node.firstChild;4012 -1 while (child != null && !found) {4013 -1 found = axs.dom.composedTreeSearch(child,4014 -1 end,4015 -1 callbacks,4016 -1 flags,4017 -1 opt_shadowRoot);4018 -1 child = child.nextSibling;4019 -1 }4020 -14021 -1 if (element && callbacks.postorder && !found)4022 -1 callbacks.postorder.call(null, element, flags);4023 -1 return found;4024 -1 };4025 -14026 -1 },{}],8:[function(require,module,exports){4027 -1 // Copyright 2012 Google Inc.4028 -1 //4029 -1 // Licensed under the Apache License, Version 2.0 (the "License");4030 -1 // you may not use this file except in compliance with the License.4031 -1 // You may obtain a copy of the License at4032 -1 //4033 -1 // http://www.apache.org/licenses/LICENSE-2.04034 -1 //4035 -1 // Unless required by applicable law or agreed to in writing, software4036 -1 // distributed under the License is distributed on an "AS IS" BASIS,4037 -1 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.4038 -1 // See the License for the specific language governing permissions and4039 -1 // limitations under the License.4040 -14041 -1 goog.require('axs.browserUtils');4042 -1 goog.require('axs.color');4043 -1 goog.require('axs.dom');4044 -1 goog.require('axs.utils');4045 -14046 -1 goog.provide('axs.properties');4047 -14048 -1 /**4049 -1 * @const4050 -1 * @type {string}4051 -1 */4052 -1 axs.properties.TEXT_CONTENT_XPATH = './/text()[normalize-space(.)!=""]/parent::*[name()!="script"]';4053 -14054 -1 /**4055 -1 * @param {Element} element4056 -1 * @return {Object.<string, Object>}4057 -1 */4058 -1 axs.properties.getFocusProperties = function(element) {4059 -1 var focusProperties = {};4060 -1 var tabindex = element.getAttribute('tabindex');4061 -1 if (tabindex != undefined) {4062 -1 focusProperties['tabindex'] = { value: tabindex, valid: true };4063 -1 } else {4064 -1 if (axs.utils.isElementImplicitlyFocusable(element))4065 -1 focusProperties['implicitlyFocusable'] = { value: true, valid: true };4066 -1 }4067 -1 if (Object.keys(focusProperties).length == 0)4068 -1 return null;4069 -1 var transparent = axs.utils.elementIsTransparent(element);4070 -1 var zeroArea = axs.utils.elementHasZeroArea(element);4071 -1 var outsideScrollArea = axs.utils.elementIsOutsideScrollArea(element);4072 -1 var overlappingElements = axs.utils.overlappingElements(element);4073 -1 if (transparent || zeroArea || outsideScrollArea || overlappingElements.length > 0) {4074 -1 var hidden = axs.utils.isElementOrAncestorHidden(element);4075 -1 var visibleProperties = { value: false,4076 -1 valid: hidden };4077 -1 if (transparent)4078 -1 visibleProperties['transparent'] = true;4079 -1 if (zeroArea)4080 -1 visibleProperties['zeroArea'] = true;4081 -1 if (outsideScrollArea)4082 -1 visibleProperties['outsideScrollArea'] = true;4083 -1 if (overlappingElements && overlappingElements.length > 0)4084 -1 visibleProperties['overlappingElements'] = overlappingElements;4085 -1 var hiddenProperties = { value: hidden, valid: hidden };4086 -1 if (hidden)4087 -1 hiddenProperties['reason'] = axs.properties.getHiddenReason(element);4088 -1 visibleProperties['hidden'] = hiddenProperties;4089 -1 focusProperties['visible'] = visibleProperties;4090 -1 } else {4091 -1 focusProperties['visible'] = { value: true, valid: true };4092 -1 }4093 -14094 -1 return focusProperties;4095 -1 };4096 -14097 -1 /**4098 -1 * @typedef {{ property: string,4099 -1 * on: Element }}4100 -1 *4101 -1 * property examples: 'display: none', 'visibility: hidden', 'aria-hidden'4102 -1 */4103 -1 axs.properties.hiddenReason;4104 -14105 -1 /**4106 -1 * Determine the reason an element is not visible.4107 -1 * Will give the CSS rule or attribute and the element/ancestor it is set on.4108 -1 * @param {Element} element4109 -1 * @return {?axs.properties.hiddenReason}4110 -1 */4111 -1 axs.properties.getHiddenReason = function(element) {4112 -1 if (!element || !(element instanceof element.ownerDocument.defaultView.HTMLElement))4113 -1 return null;4114 -14115 -1 if (element.hasAttribute('chromevoxignoreariahidden'))4116 -1 var chromevoxignoreariahidden = true;4117 -14118 -1 var style = window.getComputedStyle(element, null);4119 -1 if (style.display == 'none')4120 -1 return { 'property': 'display: none',4121 -1 'on': element };4122 -14123 -1 if (style.visibility == 'hidden')4124 -1 return { 'property': 'visibility: hidden',4125 -1 'on': element };4126 -14127 -1 if (element.hasAttribute('aria-hidden') &&4128 -1 element.getAttribute('aria-hidden').toLowerCase() == 'true') {4129 -1 if (!chromevoxignoreariahidden)4130 -1 return { 'property': 'aria-hidden',4131 -1 'on': element };4132 -1 }4133 -14134 -1 return axs.properties.getHiddenReason(axs.dom.parentElement(element));4135 -1 };4136 -14137 -14138 -1 /**4139 -1 * @param {Element} element4140 -1 * @return {Object.<string, Object>}4141 -1 */4142 -1 axs.properties.getColorProperties = function(element) {4143 -1 var colorProperties = {};4144 -1 var contrastRatioProperties =4145 -1 axs.properties.getContrastRatioProperties(element);4146 -1 if (contrastRatioProperties)4147 -1 colorProperties['contrastRatio'] = contrastRatioProperties;4148 -1 if (Object.keys(colorProperties).length == 0)4149 -1 return null;4150 -1 return colorProperties;4151 -1 };4152 -14153 -1 /**4154 -1 * Determines whether the given element has a text node as a direct descendant.4155 -1 * @param {Element} element4156 -1 * @return {boolean}4157 -1 */4158 -1 axs.properties.hasDirectTextDescendant = function(element) {4159 -1 var ownerDocument;4160 -1 if (element.nodeType == Node.DOCUMENT_NODE)4161 -1 ownerDocument = element;4162 -1 else4163 -1 ownerDocument = element.ownerDocument;4164 -1 if (ownerDocument.evaluate) {4165 -1 return hasDirectTextDescendantXpath();4166 -1 }4167 -1 return hasDirectTextDescendantTreeWalker();4168 -14169 -1 /**4170 -1 * Determines whether element has a text node as a direct descendant.4171 -1 * This method uses XPath on HTML DOM which is not universally supported.4172 -1 * @return {boolean}4173 -1 */4174 -1 function hasDirectTextDescendantXpath() {4175 -1 var selectorResults = ownerDocument.evaluate(axs.properties.TEXT_CONTENT_XPATH,4176 -1 element,4177 -1 null,4178 -1 XPathResult.ANY_TYPE,4179 -1 null);4180 -1 for (var resultElement = selectorResults.iterateNext();4181 -1 resultElement != null;4182 -1 resultElement = selectorResults.iterateNext()) {4183 -1 if (resultElement !== element)4184 -1 continue;4185 -1 return true;4186 -1 }4187 -1 return false;4188 -1 }4189 -14190 -1 /**4191 -1 * Determines whether element has a text node as a direct descendant.4192 -1 * This method uses TreeWalker as a fallback (at time of writing no version4193 -1 * of IE (including IE11) supports XPath in the HTML DOM).4194 -1 * @return {boolean}4195 -1 */4196 -1 function hasDirectTextDescendantTreeWalker() {4197 -1 var treeWalker = ownerDocument.createTreeWalker(element,4198 -1 NodeFilter.SHOW_TEXT,4199 -1 null,4200 -1 false);4201 -1 while (treeWalker.nextNode()) {4202 -1 var resultElement = treeWalker.currentNode;4203 -1 var parent = resultElement.parentNode;4204 -1 // Handle elements hosted in <template>.content.4205 -1 parent = parent.host || parent;4206 -1 var tagName = parent.tagName.toLowerCase();4207 -1 var value = resultElement.nodeValue.trim();4208 -1 if (value && tagName !== 'script' && element !== resultElement)4209 -1 return true;4210 -1 }4211 -1 return false;4212 -1 }4213 -1 };4214 -14215 -1 /**4216 -1 * @param {Element} element4217 -1 * @return {Object.<string, Object>}4218 -1 */4219 -1 axs.properties.getContrastRatioProperties = function(element) {4220 -1 if (!axs.properties.hasDirectTextDescendant(element))4221 -1 return null;4222 -14223 -1 var contrastRatioProperties = {};4224 -1 var style = window.getComputedStyle(element, null);4225 -1 var bgColor = axs.utils.getBgColor(style, element);4226 -1 if (!bgColor)4227 -1 return null;4228 -14229 -1 contrastRatioProperties['backgroundColor'] = axs.color.colorToString(bgColor);4230 -1 var fgColor = axs.utils.getFgColor(style, element, bgColor);4231 -1 contrastRatioProperties['foregroundColor'] = axs.color.colorToString(fgColor);4232 -1 var contrast = axs.utils.getContrastRatioForElementWithComputedStyle(style, element);4233 -1 if (!contrast)4234 -1 return null;4235 -1 contrastRatioProperties['value'] = contrast.toFixed(2);4236 -1 if (axs.utils.isLowContrast(contrast, style))4237 -1 contrastRatioProperties['alert'] = true;4238 -14239 -1 var levelAAContrast = axs.utils.isLargeFont(style) ? 3.0 : 4.5;4240 -1 var levelAAAContrast = axs.utils.isLargeFont(style) ? 4.5 : 7.0;4241 -1 var desiredContrastRatios = {};4242 -1 if (levelAAContrast > contrast)4243 -1 desiredContrastRatios['AA'] = levelAAContrast;4244 -1 if (levelAAAContrast > contrast)4245 -1 desiredContrastRatios['AAA'] = levelAAAContrast;4246 -14247 -1 if (!Object.keys(desiredContrastRatios).length)4248 -1 return contrastRatioProperties;4249 -14250 -1 var suggestedColors = axs.color.suggestColors(bgColor, fgColor, desiredContrastRatios);4251 -1 if (suggestedColors && Object.keys(suggestedColors).length)4252 -1 contrastRatioProperties['suggestedColors'] = suggestedColors;4253 -1 return contrastRatioProperties;4254 -1 };4255 -14256 -1 /**4257 -1 * @param {Node} node4258 -1 * @param {!Object} textAlternatives The properties object to fill in4259 -1 * @param {boolean=} opt_recursive Whether this is a recursive call or not4260 -1 * @param {boolean=} opt_force Whether to return text alternatives for this4261 -1 * element regardless of its hidden state.4262 -1 * @return {?string} The calculated text alternative for the given element4263 -1 */4264 -1 axs.properties.findTextAlternatives = function(node, textAlternatives, opt_recursive, opt_force) {4265 -1 var recursive = opt_recursive || false;4266 -14267 -1 /** @type {Element} */ var element = axs.dom.asElement(node);4268 -1 if (!element)4269 -1 return null;4270 -14271 -1 // 1. Skip hidden elements unless the author specifies to use them via an aria-labelledby or4272 -1 // aria-describedby being used in the current computation.4273 -1 if (!opt_force && axs.utils.isElementOrAncestorHidden(element))4274 -1 return null;4275 -14276 -1 // if this is a text node, just return text content.4277 -1 if (node.nodeType == Node.TEXT_NODE) {4278 -1 var textContentValue = {};4279 -1 textContentValue.type = 'text';4280 -1 textContentValue.text = node.textContent;4281 -1 textContentValue.lastWord = axs.properties.getLastWord(textContentValue.text);4282 -1 textAlternatives['content'] = textContentValue;4283 -14284 -1 return node.textContent;4285 -1 }4286 -14287 -1 var computedName = null;4288 -14289 -1 if (!recursive) {4290 -1 // 2A. The aria-labelledby attribute takes precedence as the element's text alternative4291 -1 // unless this computation is already occurring as the result of a recursive aria-labelledby4292 -1 // declaration.4293 -1 computedName = axs.properties.getTextFromAriaLabelledby(element, textAlternatives);4294 -1 }4295 -14296 -1 // 2A. If aria-labelledby is empty or undefined, the aria-label attribute, which defines an4297 -1 // explicit text string, is used.4298 -1 if (element.hasAttribute('aria-label')) {4299 -1 var ariaLabelValue = {};4300 -1 ariaLabelValue.type = 'text';4301 -1 ariaLabelValue.text = element.getAttribute('aria-label');4302 -1 ariaLabelValue.lastWord = axs.properties.getLastWord(ariaLabelValue.text);4303 -1 if (computedName)4304 -1 ariaLabelValue.unused = true;4305 -1 else if (!(recursive && axs.utils.elementIsHtmlControl(element)))4306 -1 computedName = ariaLabelValue.text;4307 -1 textAlternatives['ariaLabel'] = ariaLabelValue;4308 -1 }4309 -14310 -1 // 2A. If aria-labelledby and aria-label are both empty or undefined, and if the element is not4311 -1 // marked as presentational (role="presentation", check for the presence of an equivalent host4312 -1 // language attribute or element for associating a label, and use those mechanisms to determine4313 -1 // a text alternative.4314 -1 if (!element.hasAttribute('role') || element.getAttribute('role') != 'presentation') {4315 -1 computedName = axs.properties.getTextFromHostLanguageAttributes(element,4316 -1 textAlternatives,4317 -1 computedName,4318 -1 recursive);4319 -1 }4320 -14321 -1 // 2B (HTML version).4322 -1 if (recursive && axs.utils.elementIsHtmlControl(element)) {4323 -1 var defaultView = element.ownerDocument.defaultView;4324 -14325 -1 // include the value of the embedded control as part of the text alternative in the4326 -1 // following manner:4327 -1 if (element instanceof defaultView.HTMLInputElement) {4328 -1 // If the embedded control is a text field, use its value.4329 -1 var inputElement = /** @type {HTMLInputElement} */ (element);4330 -1 if (inputElement.type == 'text') {4331 -1 if (inputElement.value && inputElement.value.length > 0)4332 -1 textAlternatives['controlValue'] = { 'text': inputElement.value };4333 -1 }4334 -1 // If the embedded control is a range (e.g. a spinbutton or slider), use the value of the4335 -1 // aria-valuetext attribute if available, or otherwise the value of the aria-valuenow4336 -1 // attribute.4337 -1 if (inputElement.type == 'range')4338 -1 textAlternatives['controlValue'] = { 'text': inputElement.value };4339 -1 }4340 -1 // If the embedded control is a menu, use the text alternative of the chosen menu item.4341 -1 // If the embedded control is a select or combobox, use the chosen option.4342 -1 if (element instanceof defaultView.HTMLSelectElement) {4343 -1 var inputElement = /** @type {HTMLSelectElement} */ (element);4344 -1 textAlternatives['controlValue'] = { 'text': inputElement.value };4345 -1 }4346 -14347 -1 if (textAlternatives['controlValue']) {4348 -1 var controlValue = textAlternatives['controlValue'];4349 -1 if (computedName)4350 -1 controlValue.unused = true;4351 -1 else4352 -1 computedName = controlValue.text;4353 -1 }4354 -1 }4355 -14356 -1 // 2B (ARIA version).4357 -1 if (recursive && axs.utils.elementIsAriaWidget(element)) {4358 -1 var role = element.getAttribute('role');4359 -1 // If the embedded control is a text field, use its value.4360 -1 if (role == 'textbox') {4361 -1 if (element.textContent && element.textContent.length > 0)4362 -1 textAlternatives['controlValue'] = { 'text': element.textContent };4363 -1 }4364 -1 // If the embedded control is a range (e.g. a spinbutton or slider), use the value of the4365 -1 // aria-valuetext attribute if available, or otherwise the value of the aria-valuenow4366 -1 // attribute.4367 -1 if (role == 'slider' || role == 'spinbutton') {4368 -1 if (element.hasAttribute('aria-valuetext'))4369 -1 textAlternatives['controlValue'] = { 'text': element.getAttribute('aria-valuetext') };4370 -1 else if (element.hasAttribute('aria-valuenow'))4371 -1 textAlternatives['controlValue'] = { 'value': element.getAttribute('aria-valuenow'),4372 -1 'text': '' + element.getAttribute('aria-valuenow') };4373 -1 }4374 -1 // If the embedded control is a menu, use the text alternative of the chosen menu item.4375 -1 if (role == 'menu') {4376 -1 var menuitems = element.querySelectorAll('[role=menuitemcheckbox], [role=menuitemradio]');4377 -1 var selectedMenuitems = [];4378 -1 for (var i = 0; i < menuitems.length; i++) {4379 -1 if (menuitems[i].getAttribute('aria-checked') == 'true')4380 -1 selectedMenuitems.push(menuitems[i]);4381 -1 }4382 -1 if (selectedMenuitems.length > 0) {4383 -1 var selectedMenuText = '';4384 -1 for (var i = 0; i < selectedMenuitems.length; i++) {4385 -1 selectedMenuText += axs.properties.findTextAlternatives(selectedMenuitems[i], {}, true);4386 -1 if (i < selectedMenuitems.length - 1)4387 -1 selectedMenuText += ', ';4388 -1 }4389 -1 textAlternatives['controlValue'] = { 'text': selectedMenuText };4390 -1 }4391 -1 }4392 -1 // If the embedded control is a select or combobox, use the chosen option.4393 -1 if (role == 'combobox' || role == 'select') {4394 -1 // TODO4395 -1 textAlternatives['controlValue'] = { 'text': 'TODO' };4396 -1 }4397 -14398 -1 if (textAlternatives['controlValue']) {4399 -1 var controlValue = textAlternatives['controlValue'];4400 -1 if (computedName)4401 -1 controlValue.unused = true;4402 -1 else4403 -1 computedName = controlValue.text;4404 -1 }4405 -1 }4406 -14407 -1 // 2C. Otherwise, if the attributes checked in rules A and B didn't provide results, text is4408 -1 // collected from descendant content if the current element's role allows "Name From: contents."4409 -1 var hasRole = element.hasAttribute('role');4410 -1 var canGetNameFromContents = true;4411 -1 if (hasRole) {4412 -1 var roleName = element.getAttribute('role');4413 -1 // if element has a role, check that it allows "Name From: contents"4414 -1 var role = axs.constants.ARIA_ROLES[roleName];4415 -1 if (role && (!role.namefrom || role.namefrom.indexOf('contents') < 0))4416 -1 canGetNameFromContents = false;4417 -1 }4418 -1 var textFromContent = axs.properties.getTextFromDescendantContent(element, opt_force);4419 -1 if (textFromContent && canGetNameFromContents) {4420 -1 var textFromContentValue = {};4421 -1 textFromContentValue.type = 'text';4422 -1 textFromContentValue.text = textFromContent;4423 -1 textFromContentValue.lastWord = axs.properties.getLastWord(textFromContentValue.text);4424 -1 if (computedName)4425 -1 textFromContentValue.unused = true;4426 -1 else4427 -1 computedName = textFromContent;4428 -1 textAlternatives['content'] = textFromContentValue;4429 -1 }4430 -14431 -1 // 2D. The last resort is to use text from a tooltip attribute (such as the title attribute in4432 -1 // HTML). This is used only if nothing else, including subtree content, has provided results.4433 -1 if (element.hasAttribute('title')) {4434 -1 var titleValue = {};4435 -1 titleValue.type = 'string';4436 -1 titleValue.valid = true;4437 -1 titleValue.text = element.getAttribute('title');4438 -1 titleValue.lastWord = axs.properties.getLastWord(titleValue.lastWord);4439 -1 if (computedName)4440 -1 titleValue.unused = true;4441 -1 else4442 -1 computedName = titleValue.text;4443 -1 textAlternatives['title'] = titleValue;4444 -1 }4445 -14446 -1 if (Object.keys(textAlternatives).length == 0 && computedName == null)4447 -1 return null;4448 -14449 -1 return computedName;4450 -1 };4451 -14452 -1 /**4453 -1 * @param {Element} element4454 -1 * @param {boolean=} opt_force Whether to return text alternatives for this4455 -1 * element regardless of its hidden state.4456 -1 * @return {?string}4457 -1 */4458 -1 axs.properties.getTextFromDescendantContent = function(element, opt_force) {4459 -1 var children = element.childNodes;4460 -1 var childrenTextContent = [];4461 -1 for (var i = 0; i < children.length; i++) {4462 -1 var childTextContent = axs.properties.findTextAlternatives(children[i], {}, true, opt_force);4463 -1 if (childTextContent)4464 -1 childrenTextContent.push(childTextContent.trim());4465 -1 }4466 -1 if (childrenTextContent.length) {4467 -1 var result = '';4468 -1 // Empty children are allowed, but collapse all of them4469 -1 for (var i = 0; i < childrenTextContent.length; i++)4470 -1 result = [result, childrenTextContent[i]].join(' ').trim();4471 -1 return result;4472 -1 }4473 -1 return null;4474 -1 };4475 -14476 -1 /**4477 -1 * @param {Element} element4478 -1 * @param {Object} textAlternatives4479 -1 * @return {?string}4480 -1 */4481 -1 axs.properties.getTextFromAriaLabelledby = function(element, textAlternatives) {4482 -1 var computedName = null;4483 -1 if (!element.hasAttribute('aria-labelledby'))4484 -1 return computedName;4485 -14486 -1 var labelledbyAttr = element.getAttribute('aria-labelledby');4487 -1 var labelledbyIds = labelledbyAttr.split(/\s+/);4488 -1 var labelledbyValue = {};4489 -1 labelledbyValue.valid = true;4490 -1 var labelledbyText = [];4491 -1 var labelledbyValues = [];4492 -1 for (var i = 0; i < labelledbyIds.length; i++) {4493 -1 var labelledby = {};4494 -1 labelledby.type = 'element';4495 -1 var labelledbyId = labelledbyIds[i];4496 -1 labelledby.value = labelledbyId;4497 -1 var labelledbyElement = document.getElementById(labelledbyId);4498 -1 if (!labelledbyElement) {4499 -1 labelledby.valid = false;4500 -1 labelledbyValue.valid = false;4501 -1 labelledby.errorMessage = { 'messageKey': 'noElementWithId', 'args': [labelledbyId] };4502 -1 } else {4503 -1 labelledby.valid = true;4504 -1 labelledby.text = axs.properties.findTextAlternatives(labelledbyElement, {}, true, true);4505 -1 labelledby.lastWord = axs.properties.getLastWord(labelledby.text);4506 -1 labelledbyText.push(labelledby.text);4507 -1 labelledby.element = labelledbyElement;4508 -1 }4509 -1 labelledbyValues.push(labelledby);4510 -1 }4511 -1 if (labelledbyValues.length > 0) {4512 -1 labelledbyValues[labelledbyValues.length - 1].last = true;4513 -1 labelledbyValue.values = labelledbyValues;4514 -1 labelledbyValue.text = labelledbyText.join(' ');4515 -1 labelledbyValue.lastWord = axs.properties.getLastWord(labelledbyValue.text);4516 -1 computedName = labelledbyValue.text;4517 -1 textAlternatives['ariaLabelledby'] = labelledbyValue;4518 -1 }4519 -14520 -1 return computedName;4521 -1 };4522 -14523 -14524 -1 /**4525 -1 * Determine the text description/label for an element.4526 -1 * For example will attempt to find the alt text for an image or label text for a form control.4527 -1 * @param {!Element} element4528 -1 * @param {!Object} textAlternatives An object that will be updated with information.4529 -1 * @param {?string} existingComputedname4530 -1 * @param {boolean} recursive Whether this method is being called recursively as described in4531 -1 * http://www.w3.org/TR/wai-aria/roles#textalternativecomputation section 2A.4532 -1 * @return {Object}4533 -1 */4534 -1 axs.properties.getTextFromHostLanguageAttributes = function(element,4535 -1 textAlternatives,4536 -1 existingComputedname,4537 -1 recursive) {4538 -1 var computedName = existingComputedname;4539 -1 if (axs.browserUtils.matchSelector(element, 'img') && element.hasAttribute('alt')) {4540 -1 var altValue = {};4541 -1 altValue.type = 'string';4542 -1 altValue.valid = true;4543 -1 altValue.text = element.getAttribute('alt');4544 -1 if (computedName)4545 -1 altValue.unused = true;4546 -1 else4547 -1 computedName = altValue.text;4548 -1 textAlternatives['alt'] = altValue;4549 -1 }4550 -14551 -1 var controlsSelector = ['input:not([type="hidden"]):not([disabled])',4552 -1 'select:not([disabled])',4553 -1 'textarea:not([disabled])',4554 -1 'button:not([disabled])',4555 -1 'video:not([disabled])'].join(', ');4556 -1 if (axs.browserUtils.matchSelector(element, controlsSelector) && !recursive) {4557 -1 if (element.hasAttribute('id')) {4558 -1 var labelForQuerySelector = 'label[for="' + element.id + '"]';4559 -1 var labelsFor = document.querySelectorAll(labelForQuerySelector);4560 -1 var labelForValue = {};4561 -1 var labelForValues = [];4562 -1 var labelForText = [];4563 -1 for (var i = 0; i < labelsFor.length; i++) {4564 -1 var labelFor = {};4565 -1 labelFor.type = 'element';4566 -1 var label = labelsFor[i];4567 -1 var labelText = axs.properties.findTextAlternatives(label, {}, true);4568 -1 if (labelText && labelText.trim().length > 0) {4569 -1 labelFor.text = labelText.trim();4570 -1 labelForText.push(labelText.trim());4571 -1 }4572 -1 labelFor.element = label;4573 -1 labelForValues.push(labelFor);4574 -1 }4575 -1 if (labelForValues.length > 0) {4576 -1 labelForValues[labelForValues.length - 1].last = true;4577 -1 labelForValue.values = labelForValues;4578 -1 labelForValue.text = labelForText.join(' ');4579 -1 labelForValue.lastWord = axs.properties.getLastWord(labelForValue.text);4580 -1 if (computedName)4581 -1 labelForValue.unused = true;4582 -1 else4583 -1 computedName = labelForValue.text;4584 -1 textAlternatives['labelFor'] = labelForValue;4585 -1 }4586 -1 }4587 -14588 -1 var parent = axs.dom.parentElement(element);4589 -1 var labelWrappedValue = {};4590 -1 while (parent) {4591 -1 if (parent.tagName.toLowerCase() == 'label') {4592 -1 var parentLabel = /** @type {HTMLLabelElement} */ (parent);4593 -1 if (parentLabel.control == element) {4594 -1 labelWrappedValue.type = 'element';4595 -1 labelWrappedValue.text = axs.properties.findTextAlternatives(parentLabel, {}, true);4596 -1 labelWrappedValue.lastWord = axs.properties.getLastWord(labelWrappedValue.text);4597 -1 labelWrappedValue.element = parentLabel;4598 -1 break;4599 -1 }4600 -1 }4601 -1 parent = axs.dom.parentElement(parent);4602 -1 }4603 -1 if (labelWrappedValue.text) {4604 -1 if (computedName)4605 -1 labelWrappedValue.unused = true;4606 -1 else4607 -1 computedName = labelWrappedValue.text;4608 -1 textAlternatives['labelWrapped'] = labelWrappedValue;4609 -1 }4610 -1 // If all else fails input of type image can fall back to its alt text4611 -1 if (axs.browserUtils.matchSelector(element, 'input[type="image"]') && element.hasAttribute('alt')) {4612 -1 var altValue = {};4613 -1 altValue.type = 'string';4614 -1 altValue.valid = true;4615 -1 altValue.text = element.getAttribute('alt');4616 -1 if (computedName)4617 -1 altValue.unused = true;4618 -1 else4619 -1 computedName = altValue.text;4620 -1 textAlternatives['alt'] = altValue;4621 -1 }4622 -1 if (!Object.keys(textAlternatives).length)4623 -1 textAlternatives['noLabel'] = true;4624 -1 }4625 -1 return computedName;4626 -1 };4627 -14628 -1 /**4629 -1 * @param {?string} text4630 -1 * @return {?string}4631 -1 */4632 -1 axs.properties.getLastWord = function(text) {4633 -1 if (!text)4634 -1 return null;4635 -14636 -1 // TODO: this makes a lot of assumptions.4637 -1 var lastSpace = text.lastIndexOf(' ') + 1;4638 -1 var MAXLENGTH = 10;4639 -1 var cutoff = text.length - MAXLENGTH;4640 -1 var wordStart = lastSpace > cutoff ? lastSpace : cutoff;4641 -1 return text.substring(wordStart);4642 -1 };4643 -14644 -1 /**4645 -1 * @param {Node} node4646 -1 * @return {Object}4647 -1 */4648 -1 axs.properties.getTextProperties = function(node) {4649 -1 var textProperties = {};4650 -1 var computedName = axs.properties.findTextAlternatives(node, textProperties, false, true);4651 -14652 -1 if (Object.keys(textProperties).length == 0) {4653 -1 /** @type {Element} */ var element = axs.dom.asElement(node);4654 -1 if (element && axs.browserUtils.matchSelector(element, 'img')) {4655 -1 var altValue = {};4656 -1 altValue.valid = false;4657 -1 altValue.errorMessage = 'No alt value provided';4658 -1 textProperties['alt'] = altValue;4659 -14660 -1 var src = element.src;4661 -1 if (typeof src == 'string') {4662 -1 var parts = src.split('/');4663 -1 var filename = parts.pop();4664 -1 var filenameValue = { text: filename };4665 -1 textProperties['filename'] = filenameValue;4666 -1 computedName = filename;4667 -1 }4668 -1 }4669 -14670 -1 if (!computedName)4671 -1 return null;4672 -1 }4673 -14674 -1 textProperties.hasProperties = Boolean(Object.keys(textProperties).length);4675 -1 textProperties.computedText = computedName;4676 -1 textProperties.lastWord = axs.properties.getLastWord(computedName);4677 -1 return textProperties;4678 -1 };4679 -14680 -1 /**4681 -1 * Finds any ARIA attributes (roles, states and properties) explicitly set on this element.4682 -1 * @param {Element} element4683 -1 * @return {Object}4684 -1 */4685 -1 axs.properties.getAriaProperties = function(element) {4686 -1 var ariaProperties = {};4687 -1 var statesAndProperties = axs.properties.getGlobalAriaProperties(element);4688 -14689 -1 for (var property in axs.constants.ARIA_PROPERTIES) {4690 -1 var attributeName = 'aria-' + property;4691 -1 if (element.hasAttribute(attributeName)) {4692 -1 var propertyValue = element.getAttribute(attributeName);4693 -1 statesAndProperties[attributeName] =4694 -1 axs.utils.getAriaPropertyValue(attributeName, propertyValue, element);4695 -1 }4696 -1 }4697 -1 if (Object.keys(statesAndProperties).length > 0)4698 -1 ariaProperties['properties'] = axs.utils.values(statesAndProperties);4699 -14700 -1 var roles = axs.utils.getRoles(element);4701 -1 if (!roles) {4702 -1 if (Object.keys(ariaProperties).length)4703 -1 return ariaProperties;4704 -1 return null;4705 -1 }4706 -1 ariaProperties['roles'] = roles;4707 -1 if (!roles.valid || !roles['roles'])4708 -1 return ariaProperties;4709 -14710 -1 var roleDetails = roles['roles'];4711 -1 for (var i = 0; i < roleDetails.length; i++) {4712 -1 var role = roleDetails[i];4713 -1 if (!role.details || !role.details.propertiesSet)4714 -1 continue;4715 -1 for (var property in role.details.propertiesSet) {4716 -1 if (property in statesAndProperties)4717 -1 continue;4718 -1 if (element.hasAttribute(property)) {4719 -1 var propertyValue = element.getAttribute(property);4720 -1 statesAndProperties[property] =4721 -1 axs.utils.getAriaPropertyValue(property, propertyValue, element);4722 -1 if ('values' in statesAndProperties[property]) {4723 -1 var values = statesAndProperties[property].values;4724 -1 values[values.length - 1].isLast = true;4725 -1 }4726 -1 } else if (role.details.requiredPropertiesSet[property]) {4727 -1 statesAndProperties[property] =4728 -1 { 'name': property, 'valid': false, 'reason': 'Required property not set' };4729 -1 }4730 -1 }4731 -1 }4732 -1 if (Object.keys(statesAndProperties).length > 0)4733 -1 ariaProperties['properties'] = axs.utils.values(statesAndProperties);4734 -1 if (Object.keys(ariaProperties).length > 0)4735 -1 return ariaProperties;4736 -1 return null;4737 -1 };4738 -14739 -1 /**4740 -1 * Gets the ARIA properties found on this element which apply to all elements, not just elements with ARIA roles.4741 -1 * @param {Element} element4742 -1 * @return {!Object}4743 -1 */4744 -1 axs.properties.getGlobalAriaProperties = function(element) {4745 -1 var globalProperties = {};4746 -1 for (var property in axs.constants.GLOBAL_PROPERTIES) {4747 -1 if (element.hasAttribute(property)) {4748 -1 var propertyValue = element.getAttribute(property);4749 -1 globalProperties[property] =4750 -1 axs.utils.getAriaPropertyValue(property, propertyValue, element);4751 -1 }4752 -1 }4753 -1 return globalProperties;4754 -1 };4755 -14756 -1 /**4757 -1 * @param {Element} element4758 -1 * @return {Object.<string, Object>}4759 -1 */4760 -1 axs.properties.getVideoProperties = function(element) {4761 -1 var videoSelector = 'video';4762 -1 if (!axs.browserUtils.matchSelector(element, videoSelector))4763 -1 return null;4764 -1 var videoProperties = {};4765 -1 videoProperties['captionTracks'] = axs.properties.getTrackElements(element, 'captions');4766 -1 videoProperties['descriptionTracks'] = axs.properties.getTrackElements(element, 'descriptions');4767 -1 videoProperties['chapterTracks'] = axs.properties.getTrackElements(element, 'chapters');4768 -1 // error if no text alternatives?4769 -1 return videoProperties;4770 -1 };4771 -14772 -1 /**4773 -1 * @param {Element} element4774 -1 * @param {string} kind4775 -1 * @return {Object}4776 -1 */4777 -1 axs.properties.getTrackElements = function(element, kind) {4778 -1 // error if resource is not available4779 -1 var trackElements = element.querySelectorAll('track[kind=' + kind + ']');4780 -1 var result = {};4781 -1 if (!trackElements.length) {4782 -1 result.valid = false;4783 -1 result.reason = { 'messageKey': 'noTracksProvided', 'args': [[kind]] };4784 -1 return result;4785 -1 }4786 -1 result.valid = true;4787 -1 var values = [];4788 -1 for (var i = 0; i < trackElements.length; i++) {4789 -1 var trackElement = {};4790 -1 var src = trackElements[i].getAttribute('src');4791 -1 var srcLang = trackElements[i].getAttribute('srcLang');4792 -1 var label = trackElements[i].getAttribute('label');4793 -1 if (!src) {4794 -1 trackElement.valid = false;4795 -1 trackElement.reason = { 'messageKey': 'noSrcProvided' };4796 -1 } else {4797 -1 trackElement.valid = true;4798 -1 trackElement.src = src;4799 -1 }4800 -1 var name = '';4801 -1 if (label) {4802 -1 name += label;4803 -1 if (srcLang)4804 -1 name += ' ';4805 -1 }4806 -1 if (srcLang)4807 -1 name += '(' + srcLang + ')';4808 -1 if (name == '')4809 -1 name = '[' + { 'messageKey': 'unnamed' } + ']';4810 -1 trackElement.name = name;4811 -1 values.push(trackElement);4812 -1 }4813 -1 result.values = values;4814 -1 return result;4815 -1 };4816 -14817 -1 /**4818 -1 * @param {Node} node4819 -1 * @return {Object.<string, Object>}4820 -1 */4821 -1 axs.properties.getAllProperties = function(node) {4822 -1 /** @type {Element} */ var element = axs.dom.asElement(node);4823 -1 if (!element)4824 -1 return {};4825 -14826 -1 var allProperties = {};4827 -1 allProperties['ariaProperties'] = axs.properties.getAriaProperties(element);4828 -1 allProperties['colorProperties'] = axs.properties.getColorProperties(element);4829 -1 allProperties['focusProperties'] = axs.properties.getFocusProperties(element);4830 -1 allProperties['textProperties'] = axs.properties.getTextProperties(node);4831 -1 allProperties['videoProperties'] = axs.properties.getVideoProperties(element);4832 -1 return allProperties;4833 -1 };4834 -14835 -1 (function() {4836 -1 /**4837 -1 * Helper for implicit semantic functionality.4838 -1 * Can be made part of the public API if need be.4839 -1 * @param {Element} element4840 -1 * @return {?axs.constants.HtmlInfo}4841 -1 */4842 -1 function getHtmlInfo(element) {4843 -1 if (!element)4844 -1 return null;4845 -1 var tagName = element.tagName;4846 -1 if (!tagName)4847 -1 return null;4848 -1 tagName = tagName.toUpperCase();4849 -1 var infos = axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO[tagName];4850 -1 if (!infos || !infos.length)4851 -1 return null;4852 -1 var defaultInfo = null; // will contain the info with no specific selector if no others match4853 -1 for (var i = 0, len = infos.length; i < len; i++) {4854 -1 var htmlInfo = infos[i];4855 -1 if (htmlInfo.selector) {4856 -1 if (axs.browserUtils.matchSelector(element, htmlInfo.selector))4857 -1 return htmlInfo;4858 -1 } else {4859 -1 defaultInfo = htmlInfo;4860 -1 }4861 -1 }4862 -1 return defaultInfo;4863 -1 }4864 -14865 -1 /**4866 -1 * @param {Element} element4867 -1 * @return {string} role4868 -1 */4869 -1 axs.properties.getImplicitRole = function(element) {4870 -1 var htmlInfo = getHtmlInfo(element);4871 -1 if (htmlInfo)4872 -1 return htmlInfo.role;4873 -1 return '';4874 -1 };4875 -14876 -1 /**4877 -1 * Determine if this element can take ANY ARIA attributes including roles, state and properties.4878 -1 * If false then even global attributes should not be used.4879 -1 * @param {Element} element4880 -1 * @return {boolean}4881 -1 */4882 -1 axs.properties.canTakeAriaAttributes = function(element) {4883 -1 var htmlInfo = getHtmlInfo(element);4884 -1 if (htmlInfo)4885 -1 return !htmlInfo.reserved;4886 -1 return true;4887 -1 };4888 -1 })();4889 -14890 -1 /**4891 -1 * This lists the ARIA attributes that are supported implicitly by native properties of this element.4892 -1 *4893 -1 * @param {Element} element The element to check.4894 -1 * @return {!Array.<string>} An array of ARIA attributes.4895 -1 *4896 -1 * example:4897 -1 * var element = document.createElement("input");4898 -1 * element.setAttribute("type", "range");4899 -1 * var supported = axs.properties.getNativelySupportedAttributes(element); // an array of ARIA attributes4900 -1 * console.log(supported.indexOf("aria-valuemax") >=0); // logs 'true'4901 -1 */4902 -1 axs.properties.getNativelySupportedAttributes = function(element) {4903 -1 var result = [];4904 -1 if (!element) {4905 -1 return result;4906 -1 }4907 -1 var testElement = element.cloneNode(false); // gets rid of expandos4908 -1 var ariaAttributes = Object.keys(/** @type {!Object} */(axs.constants.ARIA_TO_HTML_ATTRIBUTE));4909 -1 for (var i = 0; i < ariaAttributes.length; i++) {4910 -1 var ariaAttribute = ariaAttributes[i];4911 -1 var nativeAttribute = axs.constants.ARIA_TO_HTML_ATTRIBUTE[ariaAttribute];4912 -1 if (nativeAttribute in testElement) {4913 -1 result[result.length] = ariaAttribute;4914 -1 }4915 -1 }4916 -1 return result;4917 -1 };4918 -14919 -1 (function() {4920 -1 var roleToSelectorCache = {}; // performance optimization, cache results from getSelectorForRole4921 -14922 -1 /**4923 -1 * Build a selector that will match elements which implicity or explicitly have this role.4924 -1 * Note that the selector will probably not look elegant but it will work.4925 -1 * @param {string} role4926 -1 * @return {string} selector4927 -1 */4928 -1 axs.properties.getSelectorForRole = function(role) {4929 -1 if (!role)4930 -1 return '';4931 -1 if (roleToSelectorCache[role] && roleToSelectorCache.hasOwnProperty(role))4932 -1 return roleToSelectorCache[role];4933 -1 var selectors = ['[role="' + role + '"]'];4934 -1 var tagNames = Object.keys(/** @type {!Object} */(axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO));4935 -1 tagNames.forEach(function(tagName) {4936 -1 var htmlInfos = axs.constants.TAG_TO_IMPLICIT_SEMANTIC_INFO[tagName];4937 -1 if (htmlInfos && htmlInfos.length) {4938 -1 for (var i = 0; i < htmlInfos.length; i++) {4939 -1 var htmlInfo = htmlInfos[i];4940 -1 if (htmlInfo.role === role) {4941 -1 if (htmlInfo.selector) {4942 -1 selectors[selectors.length] = htmlInfo.selector;4943 -1 } else {4944 -1 selectors[selectors.length] = tagName; // Selectors API is not case sensitive.4945 -1 break; // No need to continue adding selectors since we will match the tag itself.4946 -1 }4947 -1 }4948 -1 }4949 -1 }4950 -1 });4951 -1 return (roleToSelectorCache[role] = selectors.join(','));4952 -1 };4953 -1 })();4954 -14955 -1 },{}],9:[function(require,module,exports){4956 267 (function (global, factory) { 4957 268 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 4958 269 typeof define === 'function' && define.amd ? define(['exports'], factory) : @@ -6247,10 +1558,10 @@ axs.properties.getNativelySupportedAttributes = function(element) { 6247 1558 6248 1559 })); 6249 15606250 -1 },{}],10:[function(require,module,exports){-1 1561 },{}],4:[function(require,module,exports){ 6251 1562 (function (process,setImmediate){(function (){6252 -1 /*! axe v4.10.26253 -1 * Copyright (c) 2015 - 2024 Deque Systems, Inc.-1 1563 /*! axe v4.10.3 -1 1564 * Copyright (c) 2015 - 2025 Deque Systems, Inc. 6254 1565 * 6255 1566 * Your use of this Source Code Form is subject to the terms of the Mozilla Public 6256 1567 * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -6273,7 +1584,7 @@ axs.properties.getNativelySupportedAttributes = function(element) { 6273 1584 }, _typeof(o); 6274 1585 } 6275 1586 var axe = axe || {};6276 -1 axe.version = '4.10.2';-1 1587 axe.version = '4.10.3'; 6277 1588 if (typeof define === 'function' && define.amd) { 6278 1589 define('axe-core', [], function() { 6279 1590 return axe; @@ -13194,6 +8505,9 @@ axs.properties.getNativelySupportedAttributes = function(element) { 13194 8505 parseStylesheet: function parseStylesheet() { 13195 8506 return parse_stylesheet_default; 13196 8507 }, -1 8508 parseTabindex: function parseTabindex() { -1 8509 return parse_tabindex_default; -1 8510 }, 13197 8511 performanceTimer: function performanceTimer() { 13198 8512 return performance_timer_default; 13199 8513 }, @@ -16550,9 +11864,8 @@ axs.properties.getNativelySupportedAttributes = function(element) { 16550 11864 var nodeAndDescendents = query_selector_all_default(virtualNode, '*'); 16551 11865 var tabbableElements = nodeAndDescendents.filter(function(vNode) { 16552 11866 var isFocusable2 = vNode.isFocusable;16553 -1 var tabIndex = vNode.actualNode.getAttribute('tabindex');16554 -1 tabIndex = tabIndex && !isNaN(parseInt(tabIndex, 10)) ? parseInt(tabIndex) : null;16555 -1 return tabIndex ? isFocusable2 && tabIndex >= 0 : isFocusable2;-1 11867 var tabIndex = parse_tabindex_default(vNode.actualNode.getAttribute('tabindex')); -1 11868 return tabIndex !== null ? isFocusable2 && tabIndex >= 0 : isFocusable2; 16556 11869 }); 16557 11870 return tabbableElements; 16558 11871 } @@ -16595,18 +11908,15 @@ axs.properties.getNativelySupportedAttributes = function(element) { 16595 11908 } else if (is_natively_focusable_default(vNode)) { 16596 11909 return true; 16597 11910 }16598 -1 var tabindex = vNode.attr('tabindex');16599 -1 if (tabindex && !isNaN(parseInt(tabindex, 10))) {16600 -1 return true;16601 -1 }16602 -1 return false;-1 11911 var tabindex = parse_tabindex_default(vNode.attr('tabindex')); -1 11912 return tabindex !== null; 16603 11913 } 16604 11914 function _isInTabOrder(el) { 16605 11915 var _nodeLookup6 = _nodeLookup(el), vNode = _nodeLookup6.vNode; 16606 11916 if (vNode.props.nodeType !== 1) { 16607 11917 return false; 16608 11918 }16609 -1 var tabindex = parseInt(vNode.attr('tabindex', 10));-1 11919 var tabindex = parse_tabindex_default(vNode.attr('tabindex')); 16610 11920 if (tabindex <= -1) { 16611 11921 return false; 16612 11922 } @@ -17507,7 +12817,7 @@ axs.properties.getNativelySupportedAttributes = function(element) { 17507 12817 superclassRole: [ 'composite' ] 17508 12818 }, 17509 12819 tabpanel: {17510 -1 type: 'widget',-1 12820 type: 'structure', 17511 12821 allowedAttrs: [ 'aria-expanded' ], 17512 12822 superclassRole: [ 'section' ], 17513 12823 accessibleNameRequired: false @@ -18086,7 +13396,7 @@ axs.properties.getNativelySupportedAttributes = function(element) { 18086 13396 }, { 18087 13397 hasAccessibleName: true 18088 13398 } ],18089 -1 allowedRoles: [ 'button', 'checkbox', 'link', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'meter', 'option', 'progressbar', 'radio', 'scrollbar', 'separator', 'slider', 'switch', 'tab', 'treeitem', 'doc-cover' ]-1 13399 allowedRoles: [ 'button', 'checkbox', 'link', 'math', 'menuitem', 'menuitemcheckbox', 'menuitemradio', 'meter', 'option', 'progressbar', 'radio', 'scrollbar', 'separator', 'slider', 'switch', 'tab', 'treeitem', 'doc-cover' ] 18090 13400 }, 18091 13401 usemap: { 18092 13402 matches: '[usemap]', @@ -20144,7 +15454,7 @@ axs.properties.getNativelySupportedAttributes = function(element) { 20144 15454 }); 20145 15455 } 20146 15456 function insertedIntoFocusOrder(el) {20147 -1 var tabIndex = parseInt(el.getAttribute('tabindex'), 10);-1 15457 var tabIndex = parse_tabindex_default(el.getAttribute('tabindex')); 20148 15458 return tabIndex > -1 && _isFocusable(el) && !is_natively_focusable_default(el); 20149 15459 } 20150 15460 var inserted_into_focus_order_default = insertedIntoFocusOrder; @@ -24867,12 +20177,8 @@ axs.properties.getNativelySupportedAttributes = function(element) { 24867 20177 }; 24868 20178 } 24869 20179 function frameFocusable(frame) {24870 -1 var tabIndex = frame.getAttribute('tabindex');24871 -1 if (!tabIndex) {24872 -1 return true;24873 -1 }24874 -1 var _int = parseInt(tabIndex, 10);24875 -1 return isNaN(_int) || _int >= 0;-1 20180 var tabIndex = parse_tabindex_default(frame.getAttribute('tabindex')); -1 20181 return tabIndex === null || tabIndex >= 0; 24876 20182 } 24877 20183 function getBoundingSize(domNode) { 24878 20184 var width = parseInt(domNode.getAttribute('width'), 10); @@ -25447,6 +20753,17 @@ axs.properties.getNativelySupportedAttributes = function(element) { 25447 20753 }); 25448 20754 } 25449 20755 var parse_crossorigin_stylesheet_default = parseCrossOriginStylesheet; -1 20756 function parseTabindex(value) { -1 20757 if (typeof value !== 'string') { -1 20758 return null; -1 20759 } -1 20760 var match = value.trim().match(/^([-+]?\d+)/); -1 20761 if (match) { -1 20762 return Number(match[1]); -1 20763 } -1 20764 return null; -1 20765 } -1 20766 var parse_tabindex_default = parseTabindex; 25450 20767 var performanceTimer = function() { 25451 20768 function now() { 25452 20769 if (window.performance && window.performance) { @@ -25752,8 +21069,14 @@ axs.properties.getNativelySupportedAttributes = function(element) { 25752 21069 } 25753 21070 function preloadMedia(_ref74) { 25754 21071 var _ref74$treeRoot = _ref74.treeRoot, treeRoot = _ref74$treeRoot === void 0 ? axe._tree[0] : _ref74$treeRoot;25755 -1 var mediaVirtualNodes = query_selector_all_filter_default(treeRoot, 'video, audio', function(_ref75) {-1 21072 var mediaVirtualNodes = query_selector_all_filter_default(treeRoot, 'video[autoplay], audio[autoplay]', function(_ref75) { 25756 21073 var actualNode = _ref75.actualNode; -1 21074 if (actualNode.preload === 'none' && actualNode.readyState === 0 && actualNode.networkState !== actualNode.NETWORK_LOADING) { -1 21075 return false; -1 21076 } -1 21077 if (actualNode.hasAttribute('paused') || actualNode.hasAttribute('muted')) { -1 21078 return false; -1 21079 } 25757 21080 if (actualNode.hasAttribute('src')) { 25758 21081 return !!actualNode.getAttribute('src'); 25759 21082 } @@ -31109,16 +26432,20 @@ axs.properties.getNativelySupportedAttributes = function(element) { 31109 26432 } 31110 26433 var css_orientation_lock_evaluate_default = cssOrientationLockEvaluate; 31111 26434 function noAutoplayAudioEvaluate(node, options) { -1 26435 var hasControls = node.hasAttribute('controls'); -1 26436 if (node.hasAttribute('loop')) { -1 26437 return hasControls; -1 26438 } 31112 26439 if (!node.duration) { 31113 26440 console.warn('axe.utils.preloadMedia did not load metadata'); 31114 26441 return void 0; 31115 26442 } 31116 26443 var _options$allowedDurat = options.allowedDuration, allowedDuration = _options$allowedDurat === void 0 ? 3 : _options$allowedDurat; 31117 26444 var playableDuration = getPlayableDuration(node);31118 -1 if (playableDuration <= allowedDuration && !node.hasAttribute('loop')) {-1 26445 if (playableDuration <= allowedDuration) { 31119 26446 return true; 31120 26447 }31121 -1 if (!node.hasAttribute('controls')) {-1 26448 if (!hasControls) { 31122 26449 return false; 31123 26450 } 31124 26451 return true; @@ -31673,8 +27000,8 @@ axs.properties.getNativelySupportedAttributes = function(element) { 31673 27000 } 31674 27001 var alt_space_value_evaluate_default = altSpaceValueEvaluate; 31675 27002 function tabindexEvaluate(node, options, virtualNode) {31676 -1 var tabIndex = parseInt(virtualNode.attr('tabindex'), 10);31677 -1 return isNaN(tabIndex) ? true : tabIndex <= 0;-1 27003 var tabIndex = parse_tabindex_default(virtualNode.attr('tabindex')); -1 27004 return tabIndex === null || tabIndex <= 0; 31678 27005 } 31679 27006 var tabindex_evaluate_default = tabindexEvaluate; 31680 27007 function noFocusableContentEvaluate(node, options, virtualNode) { @@ -31718,8 +27045,8 @@ axs.properties.getNativelySupportedAttributes = function(element) { 31718 27045 return retVal; 31719 27046 } 31720 27047 function usesUnreliableHidingStrategy(vNode) {31721 -1 var tabIndex = parseInt(vNode.attr('tabindex'), 10);31722 -1 return !isNaN(tabIndex) && tabIndex < 0;-1 27048 var tabIndex = parse_tabindex_default(vNode.attr('tabindex')); -1 27049 return tabIndex !== null && tabIndex < 0; 31723 27050 } 31724 27051 function landmarkIsTopLevelEvaluate(node) { 31725 27052 var landmarks = get_aria_roles_by_type_default('landmark'); @@ -31791,9 +27118,7 @@ axs.properties.getNativelySupportedAttributes = function(element) { 31791 27118 } 31792 27119 var focusable_not_tabbable_evaluate_default = focusableNotTabbableEvaluate; 31793 27120 function focusableNoNameEvaluate(node, options, virtualNode) {31794 -1 var tabIndex = virtualNode.attr('tabindex');31795 -1 var inFocusOrder = _isFocusable(virtualNode) && tabIndex > -1;31796 -1 if (!inFocusOrder) {-1 27121 if (!_isInTabOrder(virtualNode)) { 31797 27122 return false; 31798 27123 } 31799 27124 try { @@ -32355,7 +27680,8 @@ axs.properties.getNativelySupportedAttributes = function(element) { 32355 27680 navigation: true, 32356 27681 region: true, 32357 27682 search: false,32358 -1 status: true-1 27683 status: true, -1 27684 tabpanel: true 32359 27685 }; 32360 27686 function validScrollableTagName(node) { 32361 27687 var nodeName2 = node.nodeName.toUpperCase(); @@ -33258,8 +28584,8 @@ axs.properties.getNativelySupportedAttributes = function(element) { 33258 28584 } 33259 28585 var no_role_matches_default = noRoleMatches; 33260 28586 function noNegativeTabindexMatches(node, virtualNode) {33261 -1 var tabindex = parseInt(virtualNode.attr('tabindex'), 10);33262 -1 return isNaN(tabindex) || tabindex >= 0;-1 28587 var tabindex = parse_tabindex_default(virtualNode.attr('tabindex')); -1 28588 return tabindex === null || tabindex >= 0; 33263 28589 } 33264 28590 var no_negative_tabindex_matches_default = noNegativeTabindexMatches; 33265 28591 function noNamingMethodMatches(node, virtualNode) { @@ -33589,14 +28915,14 @@ axs.properties.getNativelySupportedAttributes = function(element) { 33589 28915 return false; 33590 28916 } 33591 28917 var role = virtualNode.attr('role');33592 -1 var tabIndex = virtualNode.attr('tabindex');33593 -1 if (tabIndex === '-1' && role) {-1 28918 var tabIndex = parse_tabindex_default(virtualNode.attr('tabindex')); -1 28919 if (tabIndex < 0 && role) { 33594 28920 var roleDef = standards_default.ariaRoles[role]; 33595 28921 if (roleDef === void 0 || roleDef.type !== 'widget') { 33596 28922 return false; 33597 28923 } 33598 28924 }33599 -1 if (tabIndex === '-1' && virtualNode.actualNode && !_isVisibleOnScreen(virtualNode) && !_isVisibleToScreenReaders(virtualNode)) {-1 28925 if (tabIndex < 0 && virtualNode.actualNode && !_isVisibleOnScreen(virtualNode) && !_isVisibleToScreenReaders(virtualNode)) { 33600 28926 return false; 33601 28927 } 33602 28928 return true; @@ -34087,16 +29413,18 @@ axs.properties.getNativelySupportedAttributes = function(element) { 34087 29413 }); 34088 29414 }); 34089 29415 });34090 -1 q.defer(function(res) {34091 -1 return setTimeout(res, 0);34092 -1 });34093 -1 if (options.performanceTimer) {34094 -1 this._logRulePerformance();34095 -1 }34096 29416 q.then(function() {34097 -1 return resolve(ruleResult);-1 29417 if (options.performanceTimer) { -1 29418 _this9._logRulePerformance(); -1 29419 } -1 29420 setTimeout(function() { -1 29421 resolve(ruleResult); -1 29422 }, 0); 34098 29423 })['catch'](function(error) {34099 -1 return reject(error);-1 29424 if (options.performanceTimer) { -1 29425 _this9._logRulePerformance(); -1 29426 } -1 29427 reject(error); 34100 29428 }); 34101 29429 }; 34102 29430 Rule.prototype.runSync = function runSync2(context) { @@ -36511,7 +31839,7 @@ axs.properties.getNativelySupportedAttributes = function(element) { 36511 31839 impact: 'critical', 36512 31840 messages: { 36513 31841 pass: 'The multimedia element has a captions track',36514 -1 incomplete: 'Check that captions is available for the element'-1 31842 incomplete: 'Check that captions are available for the element' 36515 31843 } 36516 31844 }, 36517 31845 'frame-tested': { @@ -38953,7 +34281,7 @@ axs.properties.getNativelySupportedAttributes = function(element) { 38953 34281 }); 38954 34282 })(typeof window === 'object' ? window : this); 38955 34283 }).call(this)}).call(this,require('_process'),require("timers").setImmediate)38956 -1 },{"_process":1,"timers":2}],11:[function(require,module,exports){-1 34284 },{"_process":1,"timers":2}],5:[function(require,module,exports){ 38957 34285 "use strict"; 38958 34286 38959 34287 exports.__esModule = true; @@ -38999,7 +34327,7 @@ function computeAccessibleDescription(root) { 38999 34327 return description; 39000 34328 } 39001 3432939002 -1 },{"./accessible-name-and-description":12,"./util":20}],12:[function(require,module,exports){-1 34330 },{"./accessible-name-and-description":6,"./util":14}],6:[function(require,module,exports){ 39003 34331 "use strict"; 39004 34332 39005 34333 exports.__esModule = true; @@ -39562,7 +34890,7 @@ function computeTextAlternative(root) { 39562 34890 })); 39563 34891 } 39564 3489239565 -1 },{"./polyfills/SetLike":18,"./polyfills/array.from":19,"./util":20}],13:[function(require,module,exports){-1 34893 },{"./polyfills/SetLike":12,"./polyfills/array.from":13,"./util":14}],7:[function(require,module,exports){ 39566 34894 "use strict"; 39567 34895 39568 34896 exports.__esModule = true; @@ -39590,7 +34918,7 @@ function computeAccessibleName(root) { 39590 34918 return (0, _accessibleNameAndDescription.computeTextAlternative)(root, options); 39591 34919 } 39592 3492039593 -1 },{"./accessible-name-and-description":12,"./util":20}],14:[function(require,module,exports){-1 34921 },{"./accessible-name-and-description":6,"./util":14}],8:[function(require,module,exports){ 39594 34922 "use strict"; 39595 34923 39596 34924 exports.__esModule = true; @@ -39783,7 +35111,7 @@ function getExplicitRole(element) { 39783 35111 return null; 39784 35112 } 39785 3511339786 -1 },{"./util":20}],15:[function(require,module,exports){-1 35114 },{"./util":14}],9:[function(require,module,exports){ 39787 35115 "use strict"; 39788 35116 39789 35117 exports.__esModule = true; @@ -39811,7 +35139,7 @@ var _isDisabled = require("./is-disabled"); 39811 35139 exports.isDisabled = _isDisabled.isDisabled; 39812 35140 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 39813 3514139814 -1 },{"./accessible-description":11,"./accessible-name":13,"./getRole":14,"./is-disabled":16,"./is-inaccessible":17}],16:[function(require,module,exports){-1 35142 },{"./accessible-description":5,"./accessible-name":7,"./getRole":8,"./is-disabled":10,"./is-inaccessible":11}],10:[function(require,module,exports){ 39815 35143 "use strict"; 39816 35144 39817 35145 exports.__esModule = true; @@ -39832,7 +35160,7 @@ function isDisabled(element) { 39832 35160 return elementsSupportingDisabledAttribute.has(localName) && element.hasAttribute("disabled") ? true : element.getAttribute("aria-disabled") === "true"; 39833 35161 } 39834 3516239835 -1 },{"./getRole":14}],17:[function(require,module,exports){-1 35163 },{"./getRole":8}],11:[function(require,module,exports){ 39836 35164 "use strict"; 39837 35165 39838 35166 exports.__esModule = true; @@ -39901,7 +35229,7 @@ function isSubtreeInaccessible(element) { 39901 35229 return false; 39902 35230 } 39903 3523139904 -1 },{}],18:[function(require,module,exports){-1 35232 },{}],12:[function(require,module,exports){ 39905 35233 "use strict"; 39906 35234 39907 35235 exports.__esModule = true; @@ -39965,7 +35293,7 @@ var SetLike = /*#__PURE__*/function () { 39965 35293 }(); 39966 35294 var _default = exports.default = typeof Set === "undefined" ? Set : SetLike; 39967 3529539968 -1 },{}],19:[function(require,module,exports){-1 35296 },{}],13:[function(require,module,exports){ 39969 35297 "use strict"; 39970 35298 39971 35299 exports.__esModule = true; @@ -40057,7 +35385,7 @@ function arrayFrom(arrayLike, mapFn) { 40057 35385 return A; 40058 35386 } 40059 3538740060 -1 },{}],20:[function(require,module,exports){-1 35388 },{}],14:[function(require,module,exports){ 40061 35389 "use strict"; 40062 35390 40063 35391 function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } @@ -40162,7 +35490,7 @@ function hasAnyConcreteRoles(node, roles) { 40162 35490 return false; 40163 35491 } 40164 3549240165 -1 },{"./getRole":14}],21:[function(require,module,exports){-1 35493 },{"./getRole":8}],15:[function(require,module,exports){ 40166 35494 /*@license 40167 35495 CalcNames: The AccName Computation Prototype, compute the Name and Description property values for a DOM node 40168 35496 Returns an object with 'name' and 'desc' properties. @@ -40179,7 +35507,7 @@ Distributed under the terms of the Open Source Initiative OSI - MIT License 40179 35507 window[nameSpace] = {}; 40180 35508 nameSpace = window[nameSpace]; 40181 35509 }40182 -1 nameSpace.getAccNameVersion = "2.62";-1 35510 nameSpace.getAccNameVersion = "2.64"; 40183 35511 // AccName Computation Prototype 40184 35512 nameSpace.getAccName = nameSpace.calcNames = function ( 40185 35513 node, @@ -40726,7 +36054,8 @@ Plus roles extended for the Role Parity project. 40726 36054 false; 40727 36055 40728 36056 var nAlt =40729 -1 rolePresentation && nTag === "img"-1 36057 (btnType !== "image" && nTag !== "img" && nTag !== "area") || -1 36058 (rolePresentation && nTag === "img") 40730 36059 ? "" 40731 36060 : trim(node.alt || node.getAttribute("alt")); 40732 36061 @@ -41869,36 +37198,10 @@ Plus roles extended for the Role Parity project. 41869 37198 } 41870 37199 })(); 41871 3720041872 -1 },{}],22:[function(require,module,exports){41873 -1 (function (global){(function (){41874 -1 global.goog = {41875 -1 provide: function() {},41876 -1 require: function() {},41877 -1 };41878 -1 global.axs = {41879 -1 browserUtils: {},41880 -1 color: {},41881 -1 constants: {},41882 -1 dom: {},41883 -1 utils: {},41884 -1 properties: {},41885 -1 };41886 -141887 -1 require('accessibility-developer-tools/src/js/Constants');41888 -1 require('accessibility-developer-tools/src/js/AccessibilityUtils');41889 -1 require('accessibility-developer-tools/src/js/BrowserUtils');41890 -1 require('accessibility-developer-tools/src/js/Color');41891 -1 require('accessibility-developer-tools/src/js/DOMUtils');41892 -1 require('accessibility-developer-tools/src/js/Properties');41893 -141894 -1 module.exports = global.axs;41895 -141896 -1 }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})41897 -1 },{"accessibility-developer-tools/src/js/AccessibilityUtils":3,"accessibility-developer-tools/src/js/BrowserUtils":4,"accessibility-developer-tools/src/js/Color":5,"accessibility-developer-tools/src/js/Constants":6,"accessibility-developer-tools/src/js/DOMUtils":7,"accessibility-developer-tools/src/js/Properties":8}],23:[function(require,module,exports){41898 -1 var ariaApi = require('aria-api');-1 37201 },{}],16:[function(require,module,exports){ -1 37202 var ariaApi = require('aria-api/dist/aria.js'); 41899 37203 var accdc = require('w3c-alternative-text-computation'); 41900 37204 var axe = require('axe-core');41901 -1 var axs = require('./axs');41902 37205 var domAccessibilityApi = require('dom-accessibility-api'); 41903 37206 41904 37207 var form = document.querySelector('#ba-form'); @@ -41924,7 +37227,7 @@ var implementations = [{ 41924 37227 }; 41925 37228 }, 41926 37229 }, {41927 -1 name: 'WhatSock (2.62)',-1 37230 name: 'WhatSock (2.64)', 41928 37231 url: 'https://github.com/WhatSock/w3c-alternative-text-computation', 41929 37232 fn: accdc.calcNames, 41930 37233 }, { @@ -41938,7 +37241,7 @@ var implementations = [{ 41938 37241 }; 41939 37242 }, 41940 37243 }, {41941 -1 name: 'axe (4.10.2)',-1 37244 name: 'axe (4.10.3)', 41942 37245 url: 'https://github.com/dequelabs/axe-core', 41943 37246 fn: function(el) { 41944 37247 axe._tree = axe.utils.getFlattenedTree(document.body); @@ -41948,21 +37251,6 @@ var implementations = [{ 41948 37251 role: ex(axe.commons.aria.getRole, [el]), 41949 37252 }; 41950 37253 },41951 -1 }, {41952 -1 name: 'axs (2.12.0)',41953 -1 url: 'https://github.com/GoogleChrome/accessibility-developer-tools',41954 -1 fn: function(el) {41955 -1 return {41956 -1 name: ex(axs.properties.findTextAlternatives, [el, {}]),41957 -1 desc: '-',41958 -1 role: ex(function() {41959 -1 var roles = axs.utils.getRoles(el, true);41960 -1 if (roles) {41961 -1 return roles.roles.map(x => x.name).join(' ');41962 -1 }41963 -1 }),41964 -1 };41965 -1 },41966 37254 }]; 41967 37255 41968 37256 var createTd = function(text, url) { @@ -42022,4 +37310,4 @@ try { 42022 37310 }); 42023 37311 } 42024 3731242025 -1 },{"./axs":22,"aria-api":9,"axe-core":10,"dom-accessibility-api":15,"w3c-alternative-text-computation":21}]},{},[23]);-1 37313 },{"aria-api/dist/aria.js":3,"axe-core":4,"dom-accessibility-api":9,"w3c-alternative-text-computation":15}]},{},[16]);