no-autoplay-audio-evaluate.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. function noAutoplayAudioEvaluate(node, options) {
  2. /**
  3. * if duration cannot be read, this means `preloadMedia` has failed
  4. */
  5. if (!node.duration) {
  6. console.warn(`axe.utils.preloadMedia did not load metadata`);
  7. return undefined;
  8. }
  9. /**
  10. * Compute playable duration and verify if it within allowed duration
  11. */
  12. const { allowedDuration = 3 } = options;
  13. const playableDuration = getPlayableDuration(node);
  14. if (playableDuration <= allowedDuration && !node.hasAttribute('loop')) {
  15. return true;
  16. }
  17. /**
  18. * if media element does not provide controls mechanism
  19. * -> fail
  20. */
  21. if (!node.hasAttribute('controls')) {
  22. return false;
  23. }
  24. return true;
  25. /**
  26. * Compute playback duration
  27. * @param {HTMLMediaElement} elm media element
  28. */
  29. function getPlayableDuration(elm) {
  30. if (!elm.currentSrc) {
  31. return 0;
  32. }
  33. const playbackRange = getPlaybackRange(elm.currentSrc);
  34. if (!playbackRange) {
  35. return Math.abs(elm.duration - (elm.currentTime || 0));
  36. }
  37. if (playbackRange.length === 1) {
  38. return Math.abs(elm.duration - playbackRange[0]);
  39. }
  40. return Math.abs(playbackRange[1] - playbackRange[0]);
  41. }
  42. /**
  43. * Get playback range from a media elements source, if specified
  44. * See - https://developer.mozilla.org/de/docs/Web/HTML/Using_HTML5_audio_and_video#Specifying_playback_range
  45. *
  46. * Eg:
  47. * src='....someMedia.mp3#t=8'
  48. * -> should yeild [8]
  49. * src='....someMedia.mp3#t=10,12'
  50. * -> should yeild [10,12]
  51. * @param {String} src media src
  52. * @returns {Array|undefined}
  53. */
  54. function getPlaybackRange(src) {
  55. const match = src.match(/#t=(.*)/);
  56. if (!match) {
  57. return;
  58. }
  59. const [, value] = match;
  60. const ranges = value.split(',');
  61. return ranges.map(range => {
  62. // range is denoted in HH:MM:SS -> convert to seconds
  63. if (/:/.test(range)) {
  64. return convertHourMinSecToSeconds(range);
  65. }
  66. return parseFloat(range);
  67. });
  68. }
  69. /**
  70. * Add HH, MM, SS to seconds
  71. * @param {String} hhMmSs time expressed in HH:MM:SS
  72. */
  73. function convertHourMinSecToSeconds(hhMmSs) {
  74. const parts = hhMmSs.split(':');
  75. let secs = 0;
  76. let mins = 1;
  77. while (parts.length > 0) {
  78. secs += mins * parseInt(parts.pop(), 10);
  79. mins *= 60;
  80. }
  81. return parseFloat(secs);
  82. }
  83. }
  84. export default noAutoplayAudioEvaluate;