index.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.suppressOthers = exports.supportsInert = exports.inertOthers = exports.hideOthers = void 0;
  4. var getDefaultParent = function (originalTarget) {
  5. if (typeof document === 'undefined') {
  6. return null;
  7. }
  8. var sampleTarget = Array.isArray(originalTarget) ? originalTarget[0] : originalTarget;
  9. return sampleTarget.ownerDocument.body;
  10. };
  11. var counterMap = new WeakMap();
  12. var uncontrolledNodes = new WeakMap();
  13. var markerMap = {};
  14. var lockCount = 0;
  15. var unwrapHost = function (node) {
  16. return node && (node.host || unwrapHost(node.parentNode));
  17. };
  18. var correctTargets = function (parent, targets) {
  19. return targets
  20. .map(function (target) {
  21. if (parent.contains(target)) {
  22. return target;
  23. }
  24. var correctedTarget = unwrapHost(target);
  25. if (correctedTarget && parent.contains(correctedTarget)) {
  26. return correctedTarget;
  27. }
  28. console.error('aria-hidden', target, 'in not contained inside', parent, '. Doing nothing');
  29. return null;
  30. })
  31. .filter(function (x) { return Boolean(x); });
  32. };
  33. /**
  34. * Marks everything except given node(or nodes) as aria-hidden
  35. * @param {Element | Element[]} originalTarget - elements to keep on the page
  36. * @param [parentNode] - top element, defaults to document.body
  37. * @param {String} [markerName] - a special attribute to mark every node
  38. * @param {String} [controlAttribute] - html Attribute to control
  39. * @return {Undo} undo command
  40. */
  41. var applyAttributeToOthers = function (originalTarget, parentNode, markerName, controlAttribute) {
  42. var targets = correctTargets(parentNode, Array.isArray(originalTarget) ? originalTarget : [originalTarget]);
  43. if (!markerMap[markerName]) {
  44. markerMap[markerName] = new WeakMap();
  45. }
  46. var markerCounter = markerMap[markerName];
  47. var hiddenNodes = [];
  48. var elementsToKeep = new Set();
  49. var elementsToStop = new Set(targets);
  50. var keep = function (el) {
  51. if (!el || elementsToKeep.has(el)) {
  52. return;
  53. }
  54. elementsToKeep.add(el);
  55. keep(el.parentNode);
  56. };
  57. targets.forEach(keep);
  58. var deep = function (parent) {
  59. if (!parent || elementsToStop.has(parent)) {
  60. return;
  61. }
  62. Array.prototype.forEach.call(parent.children, function (node) {
  63. if (elementsToKeep.has(node)) {
  64. deep(node);
  65. }
  66. else {
  67. var attr = node.getAttribute(controlAttribute);
  68. var alreadyHidden = attr !== null && attr !== 'false';
  69. var counterValue = (counterMap.get(node) || 0) + 1;
  70. var markerValue = (markerCounter.get(node) || 0) + 1;
  71. counterMap.set(node, counterValue);
  72. markerCounter.set(node, markerValue);
  73. hiddenNodes.push(node);
  74. if (counterValue === 1 && alreadyHidden) {
  75. uncontrolledNodes.set(node, true);
  76. }
  77. if (markerValue === 1) {
  78. node.setAttribute(markerName, 'true');
  79. }
  80. if (!alreadyHidden) {
  81. node.setAttribute(controlAttribute, 'true');
  82. }
  83. }
  84. });
  85. };
  86. deep(parentNode);
  87. elementsToKeep.clear();
  88. lockCount++;
  89. return function () {
  90. hiddenNodes.forEach(function (node) {
  91. var counterValue = counterMap.get(node) - 1;
  92. var markerValue = markerCounter.get(node) - 1;
  93. counterMap.set(node, counterValue);
  94. markerCounter.set(node, markerValue);
  95. if (!counterValue) {
  96. if (!uncontrolledNodes.has(node)) {
  97. node.removeAttribute(controlAttribute);
  98. }
  99. uncontrolledNodes.delete(node);
  100. }
  101. if (!markerValue) {
  102. node.removeAttribute(markerName);
  103. }
  104. });
  105. lockCount--;
  106. if (!lockCount) {
  107. // clear
  108. counterMap = new WeakMap();
  109. counterMap = new WeakMap();
  110. uncontrolledNodes = new WeakMap();
  111. markerMap = {};
  112. }
  113. };
  114. };
  115. /**
  116. * Marks everything except given node(or nodes) as aria-hidden
  117. * @param {Element | Element[]} originalTarget - elements to keep on the page
  118. * @param [parentNode] - top element, defaults to document.body
  119. * @param {String} [markerName] - a special attribute to mark every node
  120. * @return {Undo} undo command
  121. */
  122. var hideOthers = function (originalTarget, parentNode, markerName) {
  123. if (markerName === void 0) { markerName = 'data-aria-hidden'; }
  124. var targets = Array.from(Array.isArray(originalTarget) ? originalTarget : [originalTarget]);
  125. var activeParentNode = parentNode || getDefaultParent(originalTarget);
  126. if (!activeParentNode) {
  127. return function () { return null; };
  128. }
  129. // we should not hide ariaLive elements - https://github.com/theKashey/aria-hidden/issues/10
  130. targets.push.apply(targets, Array.from(activeParentNode.querySelectorAll('[aria-live]')));
  131. return applyAttributeToOthers(targets, activeParentNode, markerName, 'aria-hidden');
  132. };
  133. exports.hideOthers = hideOthers;
  134. /**
  135. * Marks everything except given node(or nodes) as inert
  136. * @param {Element | Element[]} originalTarget - elements to keep on the page
  137. * @param [parentNode] - top element, defaults to document.body
  138. * @param {String} [markerName] - a special attribute to mark every node
  139. * @return {Undo} undo command
  140. */
  141. var inertOthers = function (originalTarget, parentNode, markerName) {
  142. if (markerName === void 0) { markerName = 'data-inert-ed'; }
  143. var activeParentNode = parentNode || getDefaultParent(originalTarget);
  144. if (!activeParentNode) {
  145. return function () { return null; };
  146. }
  147. return applyAttributeToOthers(originalTarget, activeParentNode, markerName, 'inert');
  148. };
  149. exports.inertOthers = inertOthers;
  150. /**
  151. * @returns if current browser supports inert
  152. */
  153. var supportsInert = function () {
  154. return typeof HTMLElement !== 'undefined' && HTMLElement.prototype.hasOwnProperty('inert');
  155. };
  156. exports.supportsInert = supportsInert;
  157. /**
  158. * Automatic function to "suppress" DOM elements - _hide_ or _inert_ in the best possible way
  159. * @param {Element | Element[]} originalTarget - elements to keep on the page
  160. * @param [parentNode] - top element, defaults to document.body
  161. * @param {String} [markerName] - a special attribute to mark every node
  162. * @return {Undo} undo command
  163. */
  164. var suppressOthers = function (originalTarget, parentNode, markerName) {
  165. if (markerName === void 0) { markerName = 'data-suppressed'; }
  166. return ((0, exports.supportsInert)() ? exports.inertOthers : exports.hideOthers)(originalTarget, parentNode, markerName);
  167. };
  168. exports.suppressOthers = suppressOthers;