HTMLUtilities.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* *
  2. *
  3. * (c) 2009-2020 Øystein Moseng
  4. *
  5. * Utility functions for accessibility module.
  6. *
  7. * License: www.highcharts.com/license
  8. *
  9. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  10. *
  11. * */
  12. 'use strict';
  13. import U from '../../Core/Utilities.js';
  14. var merge = U.merge;
  15. import H from '../../Core/Globals.js';
  16. var win = H.win, doc = win.document;
  17. /* eslint-disable valid-jsdoc */
  18. /**
  19. * @private
  20. * @param {Highcharts.HTMLDOMElement} el
  21. * @param {string} className
  22. * @return {void}
  23. */
  24. function addClass(el, className) {
  25. if (el.classList) {
  26. el.classList.add(className);
  27. }
  28. else if (el.className.indexOf(className) < 0) {
  29. // Note: Dumb check for class name exists, should be fine for practical
  30. // use cases, but will return false positives if the element has a class
  31. // that contains the className.
  32. el.className += className;
  33. }
  34. }
  35. /**
  36. * @private
  37. * @param {string} str
  38. * @return {string}
  39. */
  40. function escapeStringForHTML(str) {
  41. return str
  42. .replace(/&/g, '&amp;')
  43. .replace(/</g, '&lt;')
  44. .replace(/>/g, '&gt;')
  45. .replace(/"/g, '&quot;')
  46. .replace(/'/g, '&#x27;')
  47. .replace(/\//g, '&#x2F;');
  48. }
  49. /**
  50. * Get an element by ID
  51. * @param {string} id
  52. * @private
  53. * @return {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement|null}
  54. */
  55. function getElement(id) {
  56. return doc.getElementById(id);
  57. }
  58. /**
  59. * Get a fake mouse event of a given type
  60. * @param {string} type
  61. * @private
  62. * @return {global.MouseEvent}
  63. */
  64. function getFakeMouseEvent(type) {
  65. if (typeof win.MouseEvent === 'function') {
  66. return new win.MouseEvent(type);
  67. }
  68. // No MouseEvent support, try using initMouseEvent
  69. if (doc.createEvent) {
  70. var evt = doc.createEvent('MouseEvent');
  71. if (evt.initMouseEvent) {
  72. evt.initMouseEvent(type, true, // Bubble
  73. true, // Cancel
  74. win, // View
  75. type === 'click' ? 1 : 0, // Detail
  76. // Coords
  77. 0, 0, 0, 0,
  78. // Pressed keys
  79. false, false, false, false, 0, // button
  80. null // related target
  81. );
  82. return evt;
  83. }
  84. }
  85. return { type: type };
  86. }
  87. /**
  88. * Remove an element from the DOM.
  89. * @private
  90. * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} [element]
  91. * @return {void}
  92. */
  93. function removeElement(element) {
  94. if (element && element.parentNode) {
  95. element.parentNode.removeChild(element);
  96. }
  97. }
  98. /**
  99. * Utility function. Reverses child nodes of a DOM element.
  100. * @private
  101. * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} node
  102. * @return {void}
  103. */
  104. function reverseChildNodes(node) {
  105. var i = node.childNodes.length;
  106. while (i--) {
  107. node.appendChild(node.childNodes[i]);
  108. }
  109. }
  110. /**
  111. * Set attributes on element. Set to null to remove attribute.
  112. * @private
  113. * @param {Highcharts.HTMLDOMElement|Highcharts.SVGDOMElement} el
  114. * @param {Highcharts.HTMLAttributes|Highcharts.SVGAttributes} attrs
  115. * @return {void}
  116. */
  117. function setElAttrs(el, attrs) {
  118. Object.keys(attrs).forEach(function (attr) {
  119. var val = attrs[attr];
  120. if (val === null) {
  121. el.removeAttribute(attr);
  122. }
  123. else {
  124. var cleanedVal = escapeStringForHTML('' + val);
  125. el.setAttribute(attr, cleanedVal);
  126. }
  127. });
  128. }
  129. /**
  130. * Used for aria-label attributes, painting on a canvas will fail if the
  131. * text contains tags.
  132. * @private
  133. * @param {string} str
  134. * @return {string}
  135. */
  136. function stripHTMLTagsFromString(str) {
  137. return typeof str === 'string' ?
  138. str.replace(/<\/?[^>]+(>|$)/g, '') : str;
  139. }
  140. /**
  141. * Utility function for hiding an element visually, but still keeping it
  142. * available to screen reader users.
  143. * @private
  144. * @param {Highcharts.HTMLDOMElement} element
  145. * @return {void}
  146. */
  147. function visuallyHideElement(element) {
  148. var hiddenStyle = {
  149. position: 'absolute',
  150. width: '1px',
  151. height: '1px',
  152. overflow: 'hidden',
  153. whiteSpace: 'nowrap',
  154. clip: 'rect(1px, 1px, 1px, 1px)',
  155. marginTop: '-3px',
  156. '-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=1)',
  157. filter: 'alpha(opacity=1)',
  158. opacity: '0.01'
  159. };
  160. merge(true, element.style, hiddenStyle);
  161. }
  162. var HTMLUtilities = {
  163. addClass: addClass,
  164. escapeStringForHTML: escapeStringForHTML,
  165. getElement: getElement,
  166. getFakeMouseEvent: getFakeMouseEvent,
  167. removeElement: removeElement,
  168. reverseChildNodes: reverseChildNodes,
  169. setElAttrs: setElAttrs,
  170. stripHTMLTagsFromString: stripHTMLTagsFromString,
  171. visuallyHideElement: visuallyHideElement
  172. };
  173. export default HTMLUtilities;