client.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // This is the JS file that gets loaded on the client! It's only really used for
  2. // the random track feature right now - the idea is we only use it for stuff
  3. // that cannot 8e done at static-site compile time, 8y its fundamentally
  4. // ephemeral nature.
  5. 'use strict';
  6. let albumData, artistData, flashData;
  7. let officialAlbumData, fandomAlbumData, artistNames;
  8. let ready = false;
  9. function rebase(href) {
  10. const relative = document.documentElement.dataset.rebase;
  11. if (relative) {
  12. return relative + "/" + href;
  13. } else {
  14. return href;
  15. }
  16. }
  17. function pick(array) {
  18. return array[Math.floor(Math.random() * array.length)];
  19. }
  20. function cssProp(el, key) {
  21. return getComputedStyle(el).getPropertyValue(key).trim();
  22. }
  23. function getRefDirectory(ref) {
  24. return ref.split(':')[1];
  25. }
  26. function getAlbum(el) {
  27. const directory = cssProp(el, '--album-directory');
  28. return albumData.find(album => album.directory === directory);
  29. }
  30. function getFlash(el) {
  31. const directory = cssProp(el, '--flash-directory');
  32. return flashData.find(flash => flash.directory === directory);
  33. }
  34. function openAlbum(directory) {
  35. return rebase(`${C.ALBUM_DIRECTORY}/${directory}/`);
  36. }
  37. function openTrack(directory) {
  38. return rebase(`${C.TRACK_DIRECTORY}/${directory}/`);
  39. }
  40. function openArtist(directory) {
  41. return rebase(`${C.ARTIST_DIRECTORY}/${directory}/`);
  42. }
  43. function openFlash(flash) {
  44. return rebase(`${C.FLASH_DIRECTORY}/${flash.directory}/`);
  45. }
  46. /* i implemented these functions but we dont actually use them anywhere lol
  47. function isFlashPage() {
  48. return !!cssProp(document.body, '--flash-directory');
  49. }
  50. function isTrackOrAlbumPage() {
  51. return !!cssProp(document.body, '--album-directory');
  52. }
  53. function isTrackPage() {
  54. return !!cssProp(document.body, '--track-directory');
  55. }
  56. */
  57. function getTrackListAndIndex() {
  58. const album = getAlbum(document.body);
  59. const directory = cssProp(document.body, '--track-directory');
  60. if (!directory && !album) return {};
  61. if (!directory) return {list: album.tracks};
  62. const trackIndex = album.tracks.findIndex(track => track.directory === directory);
  63. return {list: album.tracks, index: trackIndex};
  64. }
  65. function openRandomTrack() {
  66. const { list } = getTrackListAndIndex();
  67. if (!list) return;
  68. return openTrack(pick(list));
  69. }
  70. function getFlashListAndIndex() {
  71. const list = flashData.filter(flash => !flash.act8r8k)
  72. const flash = getFlash(document.body);
  73. if (!flash) return {list};
  74. const flashIndex = list.indexOf(flash);
  75. return {list, index: flashIndex};
  76. }
  77. for (const a of document.body.querySelectorAll('[data-random]')) {
  78. a.addEventListener('click', evt => {
  79. if (!ready) {
  80. evt.preventDefault();
  81. return;
  82. }
  83. setTimeout(() => {
  84. a.href = rebase(C.JS_DISABLED_DIRECTORY);
  85. });
  86. switch (a.dataset.random) {
  87. case 'album': return a.href = openAlbum(pick(albumData).directory);
  88. case 'album-in-fandom': return a.href = openAlbum(pick(fandomAlbumData).directory);
  89. case 'album-in-official': return a.href = openAlbum(pick(officialAlbumData).directory);
  90. case 'track': return a.href = openTrack(getRefDirectory(pick(albumData.map(a => a.tracks).reduce((a, b) => a.concat(b), []))));
  91. case 'track-in-album': return a.href = openTrack(getRefDirectory(pick(getAlbum(a).tracks)));
  92. case 'track-in-fandom': return a.href = openTrack(getRefDirectory(pick(fandomAlbumData.reduce((acc, album) => acc.concat(album.tracks), []))));
  93. case 'track-in-official': return a.href = openTrack(getRefDirectory(pick(officialAlbumData.reduce((acc, album) => acc.concat(album.tracks), []))));
  94. case 'artist': return a.href = openArtist(pick(artistData).directory);
  95. case 'artist-more-than-one-contrib': return a.href = openArtist(pick(artistData.filter(artist => C.getArtistNumContributions(artist) > 1)).directory);
  96. }
  97. });
  98. }
  99. const next = document.getElementById('next-button');
  100. const previous = document.getElementById('previous-button');
  101. const random = document.getElementById('random-button');
  102. const prependTitle = (el, prepend) => {
  103. const existing = el.getAttribute('title');
  104. if (existing) {
  105. el.setAttribute('title', prepend + ' ' + existing);
  106. } else {
  107. el.setAttribute('title', prepend);
  108. }
  109. };
  110. if (next) prependTitle(next, '(Shift+N)');
  111. if (previous) prependTitle(previous, '(Shift+P)');
  112. if (random) prependTitle(random, '(Shift+R)');
  113. document.addEventListener('keypress', event => {
  114. if (event.shiftKey) {
  115. if (event.charCode === 'N'.charCodeAt(0)) {
  116. if (next) next.click();
  117. } else if (event.charCode === 'P'.charCodeAt(0)) {
  118. if (previous) previous.click();
  119. } else if (event.charCode === 'R'.charCodeAt(0)) {
  120. if (random && ready) random.click();
  121. }
  122. }
  123. });
  124. for (const reveal of document.querySelectorAll('.reveal')) {
  125. reveal.addEventListener('click', event => {
  126. if (!reveal.classList.contains('revealed')) {
  127. reveal.classList.add('revealed');
  128. event.preventDefault();
  129. event.stopPropagation();
  130. }
  131. });
  132. }
  133. const elements1 = document.getElementsByClassName('js-hide-once-data');
  134. const elements2 = document.getElementsByClassName('js-show-once-data');
  135. for (const element of elements1) element.style.display = 'block';
  136. fetch(rebase('data.json')).then(data => data.json()).then(data => {
  137. albumData = data.albumData;
  138. artistData = data.artistData;
  139. flashData = data.flashData;
  140. officialAlbumData = albumData.filter(album => album.groups.includes('group:official'));
  141. fandomAlbumData = albumData.filter(album => !album.groups.includes('group:official'));
  142. artistNames = artistData.filter(artist => !artist.alias).map(artist => artist.name);
  143. for (const element of elements1) element.style.display = 'none';
  144. for (const element of elements2) element.style.display = 'block';
  145. ready = true;
  146. });