script.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. Example: https://setstori.blogspot.com/2016/01/nightmareside.html
  3. */
  4. // Multiple events to a listener
  5. function addEventListener_multi(element, eventNames, handler) {
  6. var events = eventNames.split(' ');
  7. events.forEach(e => element.addEventListener(e, handler, false));
  8. }
  9. // Random numbers in a specific range
  10. function getRandom(min, max) {
  11. min = Math.ceil(min);
  12. max = Math.floor(max);
  13. return Math.floor(Math.random() * (max - min + 1)) + min;
  14. }
  15. // Position element inside element
  16. function getRelativePos(elm) {
  17. var pPos = elm.parentNode.getBoundingClientRect(); // parent pos
  18. var cPos = elm.getBoundingClientRect(); // target pos
  19. var pos = {};
  20. pos.top = cPos.top - pPos.top + elm.parentNode.scrollTop,
  21. pos.right = cPos.right - pPos.right,
  22. pos.bottom = cPos.bottom - pPos.bottom,
  23. pos.left = cPos.left - pPos.left;
  24. return pos;
  25. }
  26. function formatTime(val) {
  27. var h = 0, m = 0, s;
  28. val = parseInt(val, 10);
  29. if (val > 60 * 60) {
  30. h = parseInt(val / (60 * 60), 10);
  31. val -= h * 60 * 60;
  32. }
  33. if (val > 60) {
  34. m = parseInt(val / 60, 10);
  35. val -= m * 60;
  36. }
  37. s = val;
  38. val = (h > 0)? h + ':' : '';
  39. val += (m > 0)? ((m < 10 && h > 0)? '0' : '') + m + ':' : '0:';
  40. val += ((s < 10)? '0' : '') + s;
  41. return val;
  42. }
  43. function simp_initTime() {
  44. simp_controls.querySelector('.start-time').innerHTML = formatTime(simp_audio.currentTime); //calculate current value time
  45. if (!simp_isStream) {
  46. simp_controls.querySelector('.end-time').innerHTML = formatTime(simp_audio.duration); //calculate total value time
  47. simp_progress.value = simp_audio.currentTime / simp_audio.duration * 100; //progress bar
  48. }
  49. // ended of the audio
  50. if (simp_audio.currentTime == simp_audio.duration) {
  51. simp_controls.querySelector('.simp-plause').classList.remove('fa-pause');
  52. simp_controls.querySelector('.simp-plause').classList.add('fa-play');
  53. simp_audio.removeEventListener('timeupdate', simp_initTime);
  54. if (simp_isNext) { //auto load next audio
  55. var elem;
  56. simp_a_index++;
  57. if (simp_a_index == simp_a_url.length) { //repeat all audio
  58. simp_a_index = 0;
  59. elem = simp_a_url[0];
  60. } else {
  61. elem = simp_a_url[simp_a_index];
  62. }
  63. simp_changeAudio(elem);
  64. simp_setAlbum(simp_a_index);
  65. } else {
  66. simp_isPlaying = false;
  67. }
  68. }
  69. }
  70. function simp_initAudio() {
  71. // if readyState more than 2, audio file has loaded
  72. simp_isLoaded = simp_audio.readyState == 4 ? true : false;
  73. simp_isStream = simp_audio.duration == 'Infinity' ? true : false;
  74. simp_controls.querySelector('.simp-plause').disabled = false;
  75. simp_progress.disabled = simp_isStream ? true : false;
  76. if (!simp_isStream) {
  77. simp_progress.parentNode.classList.remove('simp-load', 'simp-loading');
  78. simp_controls.querySelector('.end-time').innerHTML = formatTime(simp_audio.duration);
  79. }
  80. simp_audio.addEventListener('timeupdate', simp_initTime); //tracking load progress
  81. if (simp_isLoaded && simp_isPlaying) simp_audio.play();
  82. // progress bar click event
  83. addEventListener_multi(simp_progress, 'touchstart mousedown', function (e) {
  84. if (simp_isStream) {
  85. e.stopPropagation();
  86. return false;
  87. }
  88. if (simp_audio.readyState == 4) {
  89. simp_audio.removeEventListener('timeupdate', simp_initTime);
  90. simp_audio.pause();
  91. }
  92. });
  93. addEventListener_multi(simp_progress, 'touchend mouseup', function (e) {
  94. if (simp_isStream) {
  95. e.stopPropagation();
  96. return false;
  97. }
  98. if (simp_audio.readyState == 4) {
  99. simp_audio.currentTime = simp_progress.value * simp_audio.duration / 100;
  100. simp_audio.addEventListener('timeupdate', simp_initTime);
  101. if (simp_isPlaying) simp_audio.play();
  102. }
  103. });
  104. // Ajout du gestionnaire d'événements pour passer à la piste suivante
  105. simp_audio.addEventListener('ended', playNextTrack);
  106. }
  107. function playNextTrack() {
  108. simp_a_index++;
  109. if (simp_a_index >= simp_a_url.length) {
  110. simp_a_index = 0; // Répéter la playlist depuis le début
  111. }
  112. // Charger la piste suivante
  113. simp_changeAudio(simp_a_url[simp_a_index]);
  114. simp_setAlbum(simp_a_index);
  115. // Rejouer la piste suivante
  116. simp_audio.play();
  117. simp_isPlaying = true;
  118. simp_controls.querySelector('.simp-plause').classList.remove('fa-play');
  119. simp_controls.querySelector('.simp-plause').classList.add('fa-pause');
  120. }
  121. function simp_changeAudio(elem) {
  122. simp_isLoaded = false;
  123. simp_controls.querySelector('.simp-prev').disabled = simp_a_index == 0 ? true : false;
  124. simp_controls.querySelector('.simp-plause').disabled = simp_auto_load ? true : false;
  125. simp_controls.querySelector('.simp-next').disabled = simp_a_index == simp_a_url.length - 1 ? true : false;
  126. simp_progress.parentNode.classList.add('simp-load');
  127. simp_progress.disabled = true;
  128. simp_progress.value = 0;
  129. simp_controls.querySelector('.start-time').innerHTML = '00:00';
  130. simp_controls.querySelector('.end-time').innerHTML = '00:00';
  131. elem = simp_isRandom && simp_isNext ? simp_a_url[getRandom(0, simp_a_url.length - 1)] : elem;
  132. // playlist, audio is running
  133. for (var i = 0; i < simp_a_url.length; i++) {
  134. simp_a_url[i].parentNode.classList.remove('simp-active');
  135. if (simp_a_url[i] == elem) {
  136. simp_a_index = i;
  137. simp_a_url[i].parentNode.classList.add('simp-active');
  138. }
  139. }
  140. // scrolling to element inside element
  141. var simp_active = getRelativePos(simp_source[simp_a_index]);
  142. simp_source[simp_a_index].parentNode.scrollTop = simp_active.top;
  143. // Charger le nouvel élément audio
  144. simp_loadAudio(elem);
  145. if (simp_isPlaying) {
  146. simp_controls.querySelector('.simp-plause').classList.remove('fa-play');
  147. simp_controls.querySelector('.simp-plause').classList.add('fa-pause');
  148. }
  149. }
  150. function simp_loadAudio(elem) {
  151. simp_progress.parentNode.classList.add('simp-loading');
  152. simp_controls.querySelector('.simp-plause').disabled = true;
  153. simp_audio.querySelector('source').src = elem.dataset.src;
  154. simp_audio.load();
  155. simp_audio.volume = parseFloat(simp_v_num / 100); //based on valume input value
  156. simp_audio.addEventListener('canplaythrough', simp_initAudio); //play audio without stop for buffering
  157. // if audio fails to load, only IE/Edge 9.0 or above
  158. simp_audio.addEventListener('error', function() {
  159. alert('Please reload the page.');
  160. });
  161. }
  162. function simp_setAlbum(index) {
  163. simp_cover.innerHTML = simp_a_url[index].dataset.cover ? '<div style="background:url(' + simp_a_url[index].dataset.cover + ') no-repeat;background-size:cover;width:80px;height:80px;"></div>' : '<i class="fa fa-music fa-5x"></i>';
  164. simp_title.innerHTML = simp_source[index].querySelector('.simp-source').innerHTML;
  165. simp_artist.innerHTML = simp_source[index].querySelector('.simp-desc') ? simp_source[index].querySelector('.simp-desc').innerHTML : '';
  166. }
  167. function simp_changeAudio(elem) {
  168. simp_isLoaded = false;
  169. simp_controls.querySelector('.simp-prev').disabled = simp_a_index == 0 ? true : false;
  170. simp_controls.querySelector('.simp-plause').disabled = simp_auto_load ? true : false;
  171. simp_controls.querySelector('.simp-next').disabled = simp_a_index == simp_a_url.length-1 ? true : false;
  172. simp_progress.parentNode.classList.add('simp-load');
  173. simp_progress.disabled = true;
  174. simp_progress.value = 0;
  175. simp_controls.querySelector('.start-time').innerHTML = '00:00';
  176. simp_controls.querySelector('.end-time').innerHTML = '00:00';
  177. elem = simp_isRandom && simp_isNext ? simp_a_url[getRandom(0, simp_a_url.length-1)] : elem;
  178. // playlist, audio is running
  179. for (var i = 0; i < simp_a_url.length; i++) {
  180. simp_a_url[i].parentNode.classList.remove('simp-active');
  181. if (simp_a_url[i] == elem) {
  182. simp_a_index = i;
  183. simp_a_url[i].parentNode.classList.add('simp-active');
  184. }
  185. }
  186. // scrolling to element inside element
  187. var simp_active = getRelativePos(simp_source[simp_a_index]);
  188. simp_source[simp_a_index].parentNode.scrollTop = simp_active.top;
  189. if (simp_auto_load || simp_isPlaying) simp_loadAudio(elem);
  190. if (simp_isPlaying) {
  191. simp_controls.querySelector('.simp-plause').classList.remove('fa-play');
  192. simp_controls.querySelector('.simp-plause').classList.add('fa-pause');
  193. }
  194. }
  195. function simp_startScript() {
  196. ap_simp = document.querySelector('#simp');
  197. simp_audio = ap_simp.querySelector('#audio');
  198. simp_album = ap_simp.querySelector('.simp-album');
  199. simp_cover = simp_album.querySelector('.simp-cover');
  200. simp_title = simp_album.querySelector('.simp-title');
  201. simp_artist = simp_album.querySelector('.simp-artist');
  202. simp_controls = ap_simp.querySelector('.simp-controls');
  203. simp_progress = simp_controls.querySelector('.simp-progress');
  204. simp_volume = simp_controls.querySelector('.simp-volume');
  205. simp_v_slider = simp_volume.querySelector('.simp-v-slider');
  206. simp_v_num = simp_v_slider.value; //default volume
  207. simp_others = simp_controls.querySelector('.simp-others');
  208. simp_auto_load = simp_config.auto_load; //auto load audio file
  209. if (simp_config.shide_top) simp_album.parentNode.classList.toggle('simp-hide');
  210. if (simp_config.shide_btm) {
  211. simp_playlist.classList.add('simp-display');
  212. simp_playlist.classList.toggle('simp-hide');
  213. }
  214. if (simp_a_url.length <= 1) {
  215. simp_controls.querySelector('.simp-prev').style.display = 'none';
  216. simp_controls.querySelector('.simp-next').style.display = 'none';
  217. simp_others.querySelector('.simp-plext').style.display = 'none';
  218. simp_others.querySelector('.simp-random').style.display = 'none';
  219. }
  220. // Playlist listeners
  221. simp_source.forEach(function(item, index) {
  222. if (item.classList.contains('simp-active')) simp_a_index = index; //playlist contains '.simp-active'
  223. item.addEventListener('click', function() {
  224. simp_audio.removeEventListener('timeupdate', simp_initTime);
  225. simp_a_index = index;
  226. simp_changeAudio(this.querySelector('.simp-source'));
  227. simp_setAlbum(simp_a_index);
  228. });
  229. });
  230. // FIRST AUDIO LOAD =======
  231. simp_changeAudio(simp_a_url[simp_a_index]);
  232. simp_setAlbum(simp_a_index);
  233. // FIRST AUDIO LOAD =======
  234. // Controls listeners
  235. simp_controls.querySelector('.simp-plauseward').addEventListener('click', function(e) {
  236. var eles = e.target.classList;
  237. if (eles.contains('simp-plause')) {
  238. if (simp_audio.paused) {
  239. if (!simp_isLoaded) simp_loadAudio(simp_a_url[simp_a_index]);
  240. simp_audio.play();
  241. simp_isPlaying = true;
  242. eles.remove('fa-play');
  243. eles.add('fa-pause');
  244. } else {
  245. simp_audio.pause();
  246. simp_isPlaying = false;
  247. eles.remove('fa-pause');
  248. eles.add('fa-play');
  249. }
  250. } else {
  251. if (eles.contains('simp-prev') && simp_a_index != 0) {
  252. simp_a_index = simp_a_index-1;
  253. e.target.disabled = simp_a_index == 0 ? true : false;
  254. } else if (eles.contains('simp-next') && simp_a_index != simp_a_url.length-1) {
  255. simp_a_index = simp_a_index+1;
  256. e.target.disabled = simp_a_index == simp_a_url.length-1 ? true : false;
  257. }
  258. simp_audio.removeEventListener('timeupdate', simp_initTime);
  259. simp_changeAudio(simp_a_url[simp_a_index]);
  260. simp_setAlbum(simp_a_index);
  261. }
  262. });
  263. // Audio volume
  264. simp_volume.addEventListener('click', function(e) {
  265. var eles = e.target.classList;
  266. if (eles.contains('simp-mute')) {
  267. if (eles.contains('fa-volume-up')) {
  268. eles.remove('fa-volume-up');
  269. eles.add('fa-volume-off');
  270. simp_v_slider.value = 0;
  271. } else {
  272. eles.remove('fa-volume-off');
  273. eles.add('fa-volume-up');
  274. simp_v_slider.value = simp_v_num;
  275. }
  276. } else {
  277. simp_v_num = simp_v_slider.value;
  278. if (simp_v_num != 0) {
  279. simp_controls.querySelector('.simp-mute').classList.remove('fa-volume-off');
  280. simp_controls.querySelector('.simp-mute').classList.add('fa-volume-up');
  281. }
  282. }
  283. simp_audio.volume = parseFloat(simp_v_slider.value / 100);
  284. });
  285. // Others
  286. simp_others.addEventListener('click', function(e) {
  287. var eles = e.target.classList;
  288. if (eles.contains('simp-plext')) {
  289. simp_isNext = simp_isNext && !simp_isRandom ? false : true;
  290. if (!simp_isRandom) simp_isRanext = simp_isRanext ? false : true;
  291. eles.contains('simp-active') && !simp_isRandom ? eles.remove('simp-active') : eles.add('simp-active');
  292. } else if (eles.contains('simp-random')) {
  293. simp_isRandom = simp_isRandom ? false : true;
  294. if (simp_isNext && !simp_isRanext) {
  295. simp_isNext = false;
  296. simp_others.querySelector('.simp-plext').classList.remove('simp-active');
  297. } else {
  298. simp_isNext = true;
  299. simp_others.querySelector('.simp-plext').classList.add('simp-active');
  300. }
  301. eles.contains('simp-active') ? eles.remove('simp-active') : eles.add('simp-active');
  302. } else if (eles.contains('simp-shide-top')) {
  303. simp_album.parentNode.classList.toggle('simp-hide');
  304. } else if (eles.contains('simp-shide-bottom')) {
  305. simp_playlist.classList.add('simp-display');
  306. simp_playlist.classList.toggle('simp-hide');
  307. }
  308. });
  309. }
  310. // Start simple player
  311. if (document.querySelector('#simp')) {
  312. var simp_auto_load, simp_audio, simp_album, simp_cover, simp_title, simp_artist, simp_controls, simp_progress, simp_volume, simp_v_slider, simp_v_num, simp_others;
  313. var ap_simp = document.querySelector('#simp');
  314. var simp_playlist = ap_simp.querySelector('.simp-playlist');
  315. var simp_source = simp_playlist.querySelectorAll('li');
  316. var simp_a_url = simp_playlist.querySelectorAll('[data-src]');
  317. var simp_a_index = 0;
  318. var simp_isPlaying = false;
  319. var simp_isNext = false; //auto play
  320. var simp_isRandom = false; //play random
  321. var simp_isRanext = false; //check if before random starts, simp_isNext value is true
  322. var simp_isStream = false; //radio streaming
  323. var simp_isLoaded = false; //audio file has loaded
  324. var simp_config = ap_simp.dataset.config ? JSON.parse(ap_simp.dataset.config) : {
  325. shide_top: false, //show/hide album
  326. shide_btm: false, //show/hide playlist
  327. auto_load: false //auto load audio file
  328. };
  329. var simp_elem = '';
  330. simp_elem += '<audio id="audio" preload><source src="" type="audio/mpeg"></audio>';
  331. simp_elem += '<div class="simp-display"><div class="simp-album w-full flex-wrap"><div class="simp-cover"><i class="fa fa-music fa-5x"></i></div><div class="simp-info"><div class="simp-title">Title</div><div class="simp-artist">Artist</div></div></div></div>';
  332. simp_elem += '<div class="simp-controls flex-wrap flex-align">';
  333. simp_elem += '<div class="simp-plauseward flex flex-align"><button type="button" class="simp-prev fa fa-backward" disabled></button><button type="button" class="simp-plause fa fa-play" disabled></button><button type="button" class="simp-next fa fa-forward" disabled></button></div>';
  334. simp_elem += '<div class="simp-tracker simp-load"><input class="simp-progress" type="range" min="0" max="100" value="0" disabled/><div class="simp-buffer"></div></div>';
  335. simp_elem += '<div class="simp-time flex flex-align"><span class="start-time">00:00</span><span class="simp-slash">&#160;/&#160;</span><span class="end-time">00:00</span></div>';
  336. simp_elem += '<div class="simp-volume flex flex-align"><button type="button" class="simp-mute fa fa-volume-up"></button><input class="simp-v-slider" type="range" min="0" max="100" value="100"/></div>';
  337. simp_elem += '<div class="simp-others flex flex-align"><button type="button" class="simp-plext fa fa-play-circle" title="Auto Play"></button><button type="button" class="simp-random fa fa-random" title="Random"></button><div class="simp-shide"><button type="button" class="simp-shide-top fa fa-caret-up" title="Show/Hide Album"></button><button type="button" class="simp-shide-bottom fa fa-caret-down" title="Show/Hide Playlist"></button></div></div>';
  338. simp_elem += '</div>'; //simp-controls
  339. var simp_player = document.createElement('div');
  340. simp_player.classList.add('simp-player');
  341. simp_player.innerHTML = simp_elem;
  342. ap_simp.insertBefore(simp_player, simp_playlist);
  343. simp_startScript();
  344. }