index.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* eslint-disable promise/prefer-await-to-then */
  2. const methodMap = [
  3. [
  4. 'requestFullscreen',
  5. 'exitFullscreen',
  6. 'fullscreenElement',
  7. 'fullscreenEnabled',
  8. 'fullscreenchange',
  9. 'fullscreenerror',
  10. ],
  11. // New WebKit
  12. [
  13. 'webkitRequestFullscreen',
  14. 'webkitExitFullscreen',
  15. 'webkitFullscreenElement',
  16. 'webkitFullscreenEnabled',
  17. 'webkitfullscreenchange',
  18. 'webkitfullscreenerror',
  19. ],
  20. // Old WebKit
  21. [
  22. 'webkitRequestFullScreen',
  23. 'webkitCancelFullScreen',
  24. 'webkitCurrentFullScreenElement',
  25. 'webkitCancelFullScreen',
  26. 'webkitfullscreenchange',
  27. 'webkitfullscreenerror',
  28. ],
  29. [
  30. 'mozRequestFullScreen',
  31. 'mozCancelFullScreen',
  32. 'mozFullScreenElement',
  33. 'mozFullScreenEnabled',
  34. 'mozfullscreenchange',
  35. 'mozfullscreenerror',
  36. ],
  37. [
  38. 'msRequestFullscreen',
  39. 'msExitFullscreen',
  40. 'msFullscreenElement',
  41. 'msFullscreenEnabled',
  42. 'MSFullscreenChange',
  43. 'MSFullscreenError',
  44. ],
  45. ];
  46. const nativeAPI = (() => {
  47. if (typeof document === 'undefined') {
  48. return false;
  49. }
  50. const unprefixedMethods = methodMap[0];
  51. const returnValue = {};
  52. for (const methodList of methodMap) {
  53. const exitFullscreenMethod = methodList?.[1];
  54. if (exitFullscreenMethod in document) {
  55. for (const [index, method] of methodList.entries()) {
  56. returnValue[unprefixedMethods[index]] = method;
  57. }
  58. return returnValue;
  59. }
  60. }
  61. return false;
  62. })();
  63. const eventNameMap = {
  64. change: nativeAPI.fullscreenchange,
  65. error: nativeAPI.fullscreenerror,
  66. };
  67. // eslint-disable-next-line import/no-mutable-exports
  68. let screenfull = {
  69. // eslint-disable-next-line default-param-last
  70. request(element = document.documentElement, options) {
  71. return new Promise((resolve, reject) => {
  72. const onFullScreenEntered = () => {
  73. screenfull.off('change', onFullScreenEntered);
  74. resolve();
  75. };
  76. screenfull.on('change', onFullScreenEntered);
  77. const returnPromise = element[nativeAPI.requestFullscreen](options);
  78. if (returnPromise instanceof Promise) {
  79. returnPromise.then(onFullScreenEntered).catch(reject);
  80. }
  81. });
  82. },
  83. exit() {
  84. return new Promise((resolve, reject) => {
  85. if (!screenfull.isFullscreen) {
  86. resolve();
  87. return;
  88. }
  89. const onFullScreenExit = () => {
  90. screenfull.off('change', onFullScreenExit);
  91. resolve();
  92. };
  93. screenfull.on('change', onFullScreenExit);
  94. const returnPromise = document[nativeAPI.exitFullscreen]();
  95. if (returnPromise instanceof Promise) {
  96. returnPromise.then(onFullScreenExit).catch(reject);
  97. }
  98. });
  99. },
  100. toggle(element, options) {
  101. return screenfull.isFullscreen ? screenfull.exit() : screenfull.request(element, options);
  102. },
  103. onchange(callback) {
  104. screenfull.on('change', callback);
  105. },
  106. onerror(callback) {
  107. screenfull.on('error', callback);
  108. },
  109. on(event, callback) {
  110. const eventName = eventNameMap[event];
  111. if (eventName) {
  112. document.addEventListener(eventName, callback, false);
  113. }
  114. },
  115. off(event, callback) {
  116. const eventName = eventNameMap[event];
  117. if (eventName) {
  118. document.removeEventListener(eventName, callback, false);
  119. }
  120. },
  121. raw: nativeAPI,
  122. };
  123. Object.defineProperties(screenfull, {
  124. isFullscreen: {
  125. get: () => Boolean(document[nativeAPI.fullscreenElement]),
  126. },
  127. element: {
  128. enumerable: true,
  129. get: () => document[nativeAPI.fullscreenElement] ?? undefined,
  130. },
  131. isEnabled: {
  132. enumerable: true,
  133. // Coerce to boolean in case of old WebKit.
  134. get: () => Boolean(document[nativeAPI.fullscreenEnabled]),
  135. },
  136. });
  137. if (!nativeAPI) {
  138. screenfull = {isEnabled: false};
  139. }
  140. export default screenfull;