您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a audio player to listen audio without leaving current page.
当前为
// ==UserScript== // @name audio player // @namespace http://tampermonkey.net/ // @version 0.41 // @description Add a audio player to listen audio without leaving current page. // @author oshibuki // @match https://t-nagano.com/projects/JapaneseGenki3rdEdAudio/ // @icon https://www.google.com/s2/favicons?sz=64&domain=t-nagano.com // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // Your CSS code here var style = document.createElement('style'); style.type = "text/css"; var content = ` *, *::before, *::after { box-sizing: border-box; } body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; font-size: 14px; } pre, code { font-family: Consolas, Courier, monospace; font-size: inherit; color: #333; background: #fafafa; } pre { padding: 1rem; border: 1px solid #eee; overflow: auto; } .container-fluid { padding-bottom:50px; } /*----------------------- Audio Player - AP ------------------------*/ .ap { position: fixed; left: 0; right: 0; bottom: 0; width: 100%; height: 50px; font-family: inherit; font-size: 14px; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; border-top: 1px solid #ccc; background: #f2f2f2; box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1); z-index: 99999; } .ap__inner { display: flex; max-width: 1440px; margin: auto; } .ap__item { display: flex; flex: 1; justify-content: center; align-items: center; } .ap__item--playback > .ap__controls, .ap__item--settings > .ap__controls { flex: 0 25%; } @-webkit-keyframes fs { 0% { opacity: 0; transform: scale(0.5); } 100% { opacity: 1; transform: scale(1); } } @keyframes fs { 0% { opacity: 0; transform: scale(0.5); } 100% { opacity: 1; transform: scale(1); } } .ap__item--track { flex: 1 40%; padding: 0 20px; } .track { position: relative; width: 100%; align-self: flex-start; padding: 5px 0 0; } .track__title { position: absolute; width: 100%; overflow: hidden; padding-right: 80px; text-align: left; white-space: nowrap; text-overflow: ellipsis; } .track__time { position: absolute; top: 5px; right: 0; } .progress-container { position: relative; padding: 7px 0; margin-top: 15px; overflow: hidden; cursor: pointer; } .progress-container:hover .progress__bar:after { opacity: 1; } .progress { height: 3px; border-radius: 3px; background: #ddd; } .progress__bar, .progress__preload { position: absolute; width: 0; height: 3px; border-radius: 3px 0 0 3px; } .progress__bar { background: steelblue; z-index: 1; } .progress__bar:after { position: absolute; top: 0; right: -10px; width: 10px; height: 10px; margin-top: -3px; content: ""; border-radius: 6px; background: steelblue; opacity: 0; transition: opacity 0.3s ease; } .progress__bar--active:after { transform: scale(1.4); } .progress__preload { background: #c4c4c4; z-index: 0; } .ap__controls, .ap button { margin: 0; padding: 0; border: 0; outline: 0; background: transparent; position: relative; display: block; height: 50px; text-align: center; cursor: pointer; transition: background 0.3s ease; } .ap__controls:active, .ap button:active { background: rgba(0, 0, 0, 0.1); } .ap__controls:hover, .ap button:hover { opacity: 1; } .ap__controls--playlist { display: none; } .icon-play > path { transition: all 0.3s ease; } .is-playing .icon-play { fill: steelblue; } .volume-btn { display: block; text-align: center; width: 100%; } .volume { position: absolute; left: 50%; bottom: 45px; width: 40px; margin-left: -20px; height: 120px; opacity: 0; visibility: hidden; transform: translateY(10px); transition: all 0.3s cubic-bezier(0.17, 0.72, 0.26, 1.23); background: #f2f2f2; border: 1px solid #ccc; border-radius: 1px; z-index: 88888; } .volume::before, .volume::after { content: ""; position: absolute; bottom: -12px; border: 7px solid transparent; border-top: 7px solid #f2f2f2; left: 50%; margin-left: -7px; } .volume::after { bottom: -14px; z-index: -1; border-top: 7px solid #ccc; } .volume-container:hover .volume { opacity: 1; transform: translateY(0); visibility: visible; } .volume__track { position: relative; display: block; width: 3px; height: 100px; margin: 10px auto; background: #ddd; border-radius: 3px; overflow: hidden; } .volume__bar { position: absolute; left: 0; right: 0; bottom: 0; background: steelblue; height: 50%; } .icon-volume-off { display: none; } .has-muted .icon-volume-on { display: none; } .has-muted .icon-volume-off { display: inline; opacity: 0.7; } .ap__controls.is-active > svg { fill: steelblue; filter: drop-shadow(0 0 3px rgba(70, 130, 180, 0.4)); } @media (max-width: 1024px) { .ap__item > .ap__controls { flex: 1; } } @media (max-width: 580px) { .ap { min-width: 250px; } .ap, .ap__inner { height: auto; } .ap__inner { flex-wrap: wrap; } .ap__item--track { margin-bottom: 10px; padding: 0 20px; order: 1; flex: 1 1 100%; } .ap__item--playback, .ap__item--settings { flex: 1 1 50%; order: 2; } } /*----------------------- Playlist Player - PL ------------------------*/ .pl-container { display: none; position: fixed; top: 0; right: 0; bottom: 50px; left: 0; overflow: auto; font-family: inherit; font-size: 14px; background: #fff; z-index: 77777; } .pl-ul { width: 100%; max-width: 550px; margin: 0 auto; padding: 30px 10px 100px 10px; } .pl-list { display: flex; align-items: center; height: 40px; line-height: 40px; } .pl-list svg { fill: steelblue; } .pl-list + .pl-list { border-top: 1px solid #eee; } .pl-list:not(.pl-list--current):hover { background: #f6f6f6; } .pl-list__track, .pl-list__remove { flex: 0 50px; text-align: center; } .pl-list__icon { display: inline-block; width: 0; height: 0; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-left: 8px solid #555; } .pl-list__title { overflow: hidden; padding-right: 10px; cursor: pointer; text-align: left; white-space: nowrap; text-overflow: ellipsis; flex: 1; } .pl-list__remove { height: 100%; background: transparent; border: 0; outline: 0; cursor: pointer; opacity: 0; transition: opacity 0.2s ease; } .pl-list__remove > svg { width: 16px; height: 16px; } .pl-list__eq { display: none; } .pl-list--current { background: steelblue; color: #fff; } .pl-list--current svg { fill: #fff; } .pl-list--current .pl-list__eq { display: block; } .pl-list--current .pl-list__icon { display: none; } .pl-list:hover .pl-list__remove, .pl-list--current .pl-list__remove { opacity: 1; } .pl-list--current .pl-list__remove:hover { background: #3f75a2; } .pl-list--empty { position: absolute; top: 50%; left: 50%; font-size: 2rem; transform: translate(-50%, -50%); letter-spacing: 2px; color: #ccc; } @-webkit-keyframes eq { 0% { height: 3px; } 50% { height: 20px; } 100% { height: 3px; } } @keyframes eq { 0% { height: 3px; } 50% { height: 20px; } 100% { height: 3px; } } .eq { display: flex; width: 20px; height: 20px; margin: 0 auto; justify-content: space-between; align-items: flex-end; } .eq__bar { width: 4px; background: #fff; filter: drop-shadow(0 0 5px #fff); } .eq__bar:nth-child(1) { -webkit-animation: eq 0.8s ease-in-out infinite 0s; animation: eq 0.8s ease-in-out infinite 0s; } .eq__bar:nth-child(2) { -webkit-animation: eq 0.8s ease-in-out infinite 0.2s; animation: eq 0.8s ease-in-out infinite 0.2s; } .eq__bar:nth-child(3) { -webkit-animation: eq 0.8s ease-in-out infinite 0.4s; animation: eq 0.8s ease-in-out infinite 0.4s; } .h-hide { display: none; } .h-show { display: block; } `; if (style.styleSheet) { style.styleSheet.cssText = content; } else { style.appendChild(document.createTextNode(content)); } document.head.append(style); var myDiv = document.createElement('div'); myDiv.innerHTML = ` <!-- Audio player --> <div class="ap" id="ap"> <div class="ap__inner"> <div class="ap__item ap__item--playback"> <button class="ap__controls ap__controls--prev"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#333" width="24" height="24" viewBox="0 0 24 24"> <path d="M9.516 12l8.484-6v12zM6 6h2.016v12h-2.016v-12z"></path> </svg> </button> <button class="ap__controls ap__controls--toggle"> <svg class="icon-play" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#333" width="36" height="36" viewBox="0 0 36 36" data-play="M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z" data-pause="M 12,26 16.33,26 16.33,10 12,10 z M 20.66,26 25,26 25,10 20.66,10 z"> <path d="M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z"></path> </svg> </button> <button class="ap__controls ap__controls--next"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#333" width="24" height="24" viewBox="0 0 24 24"> <path d="M15.984 6h2.016v12h-2.016v-12zM6 18v-12l8.484 6z"></path> </svg> </button> </div> <div class="ap__item ap__item--track"> <div class="track"> <div class="track__title">Queue is empty</div> <div class="track__time"> <span class="track__time--current">--</span> <span> / </span> <span class="track__time--duration">--</span> </div> <div class="progress-container"> <div class="progress"> <div class="progress__bar"></div> <div class="progress__preload"></div> </div> </div> </div> </div> <div class="ap__item ap__item--settings"> <div class="ap__controls volume-container"> <button class="volume-btn"> <svg class="icon-volume-on" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#333" width="24" height="24" viewBox="0 0 24 24"> <path d="M14.016 3.234q3.047 0.656 5.016 3.117t1.969 5.648-1.969 5.648-5.016 3.117v-2.063q2.203-0.656 3.586-2.484t1.383-4.219-1.383-4.219-3.586-2.484v-2.063zM16.5 12q0 2.813-2.484 4.031v-8.063q2.484 1.219 2.484 4.031zM3 9h3.984l5.016-5.016v16.031l-5.016-5.016h-3.984v-6z"></path> </svg> <svg class="icon-volume-off" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#333" width="24" height="24" viewBox="0 0 24 24"> <path d="M12 3.984v4.219l-2.109-2.109zM4.266 3l16.734 16.734-1.266 1.266-2.063-2.063q-1.734 1.359-3.656 1.828v-2.063q1.172-0.328 2.25-1.172l-4.266-4.266v6.75l-5.016-5.016h-3.984v-6h4.734l-4.734-4.734zM18.984 12q0-2.391-1.383-4.219t-3.586-2.484v-2.063q3.047 0.656 5.016 3.117t1.969 5.648q0 2.25-1.031 4.172l-1.5-1.547q0.516-1.266 0.516-2.625zM16.5 12q0 0.422-0.047 0.609l-2.438-2.438v-2.203q2.484 1.219 2.484 4.031z"></path> </svg> </button> <div class="volume"> <div class="volume__track"> <div class="volume__bar"></div> </div> </div> </div> <button class="ap__controls ap__controls--repeat"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#333" width="24" height="24" viewBox="0 0 24 24"> <path d="M17.016 17.016v-4.031h1.969v6h-12v3l-3.984-3.984 3.984-3.984v3h10.031zM6.984 6.984v4.031h-1.969v-6h12v-3l3.984 3.984-3.984 3.984v-3h-10.031z"></path> </svg> </button> <button class="ap__controls ap__controls--playlist" style="display:none;"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#333" width="24" height="24" viewBox="0 0 24 24"> <path d="M17.016 12.984l4.969 3-4.969 3v-6zM2.016 15v-2.016h12.984v2.016h-12.984zM18.984 5.016v1.969h-16.969v-1.969h16.969zM18.984 9v2.016h-16.969v-2.016h16.969z"></path> </svg> </button> </div> </div> </div> `; var mainContent = document.getElementById('page-content-wrapper') mainContent.appendChild(myDiv); (function(window, undefined) { 'use strict'; var AudioPlayer = (function() { // Player vars! var docTitle = document.title, player = document.getElementById('ap'), playBtn, playSvg, playSvgPath, prevBtn, nextBtn, plBtn, repeatBtn, volumeBtn, progressBar, preloadBar, curTime, durTime, trackTitle, audio, index = 0, playList, volumeBar, wheelVolumeValue = 0, volumeLength, repeating = false, seeking = false, seekingVol = false, rightClick = false, apActive = false, // playlist vars pl, plUl, plLi, tplList = '<li class="pl-list" data-track="{count}">'+ '<div class="pl-list__track">'+ '<div class="pl-list__icon"></div>'+ '<div class="pl-list__eq">'+ '<div class="eq">'+ '<div class="eq__bar"></div>'+ '<div class="eq__bar"></div>'+ '<div class="eq__bar"></div>'+ '</div>'+ '</div>'+ '</div>'+ '<div class="pl-list__title">{title}</div>'+ '<button class="pl-list__remove">'+ '<svg fill="#000000" height="20" viewBox="0 0 24 24" width="20" xmlns="http://www.w3.org/2000/svg">'+ '<path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>'+ '<path d="M0 0h24v24H0z" fill="none"/>'+ '</svg>'+ '</button>'+ '</li>', // settings settings = { volume : 0.1, changeDocTitle: true, confirmClose : true, autoPlay : false, buffered : true, notification : true, playList : [] }; function init(options) { if(!('classList' in document.documentElement)) { return false; } if(apActive || player === null) { return 'Player already init'; } settings = extend(settings, options); // get player elements playBtn = player.querySelector('.ap__controls--toggle'); playSvg = playBtn.querySelector('.icon-play'); playSvgPath = playSvg.querySelector('path'); prevBtn = player.querySelector('.ap__controls--prev'); nextBtn = player.querySelector('.ap__controls--next'); repeatBtn = player.querySelector('.ap__controls--repeat'); volumeBtn = player.querySelector('.volume-btn'); plBtn = player.querySelector('.ap__controls--playlist'); curTime = player.querySelector('.track__time--current'); durTime = player.querySelector('.track__time--duration'); trackTitle = player.querySelector('.track__title'); progressBar = player.querySelector('.progress__bar'); preloadBar = player.querySelector('.progress__preload'); volumeBar = player.querySelector('.volume__bar'); playList = settings.playList; playBtn.addEventListener('click', playToggle, false); volumeBtn.addEventListener('click', volumeToggle, false); repeatBtn.addEventListener('click', repeatToggle, false); progressBar.closest('.progress-container').addEventListener('mousedown', handlerBar, false); progressBar.closest('.progress-container').addEventListener('mousemove', seek, false); document.documentElement.addEventListener('mouseup', seekingFalse, false); volumeBar.closest('.volume').addEventListener('mousedown', handlerVol, false); volumeBar.closest('.volume').addEventListener('mousemove', setVolume); volumeBar.closest('.volume').addEventListener(wheel(), setVolume, false); prevBtn.addEventListener('click', prev, false); nextBtn.addEventListener('click', next, false); apActive = true; // Create playlist renderPL(); plBtn.addEventListener('click', plToggle, false); // Create audio object audio = new Audio(); audio.volume = settings.volume; audio.preload = 'auto'; audio.id='audio' audio.addEventListener('error', errorHandler, false); audio.addEventListener('timeupdate', timeUpdate, false); audio.addEventListener('ended', doEnd, false); volumeBar.style.height = audio.volume * 100 + '%'; volumeLength = volumeBar.css('height'); if(settings.confirmClose) { window.addEventListener("beforeunload", beforeUnload, false); } if(isEmptyList()) { return false; } audio.src = playList[index].file; trackTitle.innerHTML = playList[index].title; document.body.append(audio) if(settings.autoPlay) { audio.play(); playBtn.classList.add('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-pause')); plLi[index].classList.add('pl-list--current'); notify(playList[index].title, { icon: playList[index].icon, body: 'Now playing' }); } } function changeDocumentTitle(title) { if(settings.changeDocTitle) { if(title) { document.title = title; } else { document.title = docTitle; } } } function beforeUnload(evt) { if(!audio.paused) { var message = 'Music still playing'; evt.returnValue = message; return message; } } function errorHandler(evt) { if(isEmptyList()) { return; } var mediaError = { '1': 'MEDIA_ERR_ABORTED', '2': 'MEDIA_ERR_NETWORK', '3': 'MEDIA_ERR_DECODE', '4': 'MEDIA_ERR_SRC_NOT_SUPPORTED' }; audio.pause(); curTime.innerHTML = '--'; durTime.innerHTML = '--'; progressBar.style.width = 0; preloadBar.style.width = 0; playBtn.classList.remove('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-play')); plLi[index] && plLi[index].classList.remove('pl-list--current'); changeDocumentTitle(); throw new Error('Houston we have a problem: ' + mediaError[evt.target.error.code]); } /** * UPDATE PL */ function updatePL(addList) { if(!apActive) { return 'Player is not yet initialized'; } if(!Array.isArray(addList)) { return; } if(addList.length === 0) { return; } var count = playList.length; var html = []; playList = addList audio.src = playList[index].file; trackTitle.innerHTML = playList[index].title; audio.currentTime = 0 audio.pause() playToggle() } /** * PlayList methods */ function renderPL() { var html = []; playList.forEach(function(item, i) { html.push( tplList.replace('{count}', i).replace('{title}', item.title) ); }); pl = create('div', { 'className': 'pl-container', 'id': 'pl', 'innerHTML': '<ul class="pl-ul">' + (!isEmptyList() ? html.join('') : '<li class="pl-list--empty">PlayList is empty</li>') + '</ul>' }); player.parentNode.insertBefore(pl, player.nextSibling); plUl = pl.querySelector('.pl-ul'); plLi = plUl.querySelectorAll('li'); pl.addEventListener('click', listHandler, false); } function listHandler(evt) { evt.preventDefault(); if(evt.target.matches('.pl-list__title') || evt.target.matches('.pl-list__track')) { var current = parseInt(evt.target.closest('.pl-list').getAttribute('data-track'), 10); if(index !== current) { index = current; play(current); } else { playToggle(); } } else { if(!!evt.target.closest('.pl-list__remove')) { var parentEl = evt.target.closest('.pl-list'); var isDel = parseInt(parentEl.getAttribute('data-track'), 10); playList.splice(isDel, 1); parentEl.closest('.pl-ul').removeChild(parentEl); plLi = pl.querySelectorAll('li'); [].forEach.call(plLi, function(el, i) { el.setAttribute('data-track', i); }); if(!audio.paused) { if(isDel === index) { play(index); } } else { if(isEmptyList()) { clearAll(); } else { if(isDel === index) { if(isDel > playList.length - 1) { index -= 1; } audio.src = playList[index].file; trackTitle.innerHTML = playList[index].title; progressBar.style.width = 0; } } } if(isDel < index) { index--; } } } } function plActive() { if(audio.paused) { plLi[index].classList.remove('pl-list--current'); return; } var current = index; for(var i = 0, len = plLi.length; len > i; i++) { plLi[i].classList.remove('pl-list--current'); } plLi[current].classList.add('pl-list--current'); } /** * Player methods */ function play(currentIndex) { if(isEmptyList()) { return clearAll(); } index = 0; audio.src = playList[index].file; trackTitle.innerHTML = playList[index].title; // Change document title changeDocumentTitle(playList[index].title); // Audio play audio.play(); // Show notification notify(playList[index].title, { icon: playList[index].icon, body: 'Now playing', tag: 'music-player' }); // Toggle play button playBtn.classList.add('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-pause')); // Set active song playlist plActive(); } function prev() { play(index - 1); } function next() { play(index + 1); } function isEmptyList() { return playList.length === 0; } function clearAll() { audio.pause(); audio.src = ''; trackTitle.innerHTML = 'queue is empty'; curTime.innerHTML = '--'; durTime.innerHTML = '--'; progressBar.style.width = 0; preloadBar.style.width = 0; playBtn.classList.remove('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-play')); if(!plUl.querySelector('.pl-list--empty')) { plUl.innerHTML = '<li class="pl-list--empty">PlayList is empty</li>'; } changeDocumentTitle(); } function playToggle() { if(isEmptyList()) { return; } if(audio.paused) { if(audio.currentTime === 0) { notify(playList[index].title, { icon: playList[index].icon, body: 'Now playing' }); } changeDocumentTitle(playList[index].title); audio.play(); playBtn.classList.add('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-pause')); } else { changeDocumentTitle(); audio.pause(); playBtn.classList.remove('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-play')); } plActive(); } function volumeToggle() { if(audio.muted) { if(parseInt(volumeLength, 10) === 0) { volumeBar.style.height = settings.volume * 100 + '%'; audio.volume = settings.volume; } else { volumeBar.style.height = volumeLength; } audio.muted = false; volumeBtn.classList.remove('has-muted'); } else { audio.muted = true; volumeBar.style.height = 0; volumeBtn.classList.add('has-muted'); } } function repeatToggle() { if(repeatBtn.classList.contains('is-active')) { repeating = false; repeatBtn.classList.remove('is-active'); } else { repeating = true; repeatBtn.classList.add('is-active'); } } function plToggle() { plBtn.classList.toggle('is-active'); pl.classList.toggle('h-show'); } function timeUpdate() { if(audio.readyState === 0 || seeking) return; var barlength = Math.round(audio.currentTime * (100 / audio.duration)); progressBar.style.width = barlength + '%'; var curMins = Math.floor(audio.currentTime / 60), curSecs = Math.floor(audio.currentTime - curMins * 60), mins = Math.floor(audio.duration / 60), secs = Math.floor(audio.duration - mins * 60); (curSecs < 10) && (curSecs = '0' + curSecs); (secs < 10) && (secs = '0' + secs); curTime.innerHTML = curMins + ':' + curSecs; durTime.innerHTML = mins + ':' + secs; if(settings.buffered) { var buffered = audio.buffered; if(buffered.length) { var loaded = Math.round(100 * buffered.end(0) / audio.duration); preloadBar.style.width = loaded + '%'; } } } /** * TODO shuffle */ function shuffle() { if(shuffle) { index = Math.round(Math.random() * playList.length); } } function doEnd() { if(index === playList.length - 1) { if(!repeating) { audio.pause(); plActive(); playBtn.classList.remove('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-play')); return; } else { play(0); } } else { play(index + 1); } } function moveBar(evt, el, dir) { var value; if(dir === 'horizontal') { value = Math.round( ((evt.clientX - el.offset().left) + window.pageXOffset) * 100 / el.parentNode.offsetWidth); el.style.width = value + '%'; return value; } else { if(evt.type === wheel()) { value = parseInt(volumeLength, 10); var delta = evt.deltaY || evt.detail || -evt.wheelDelta; value = (delta > 0) ? value - 10 : value + 10; } else { var offset = (el.offset().top + el.offsetHeight) - window.pageYOffset; value = Math.round((offset - evt.clientY)); } if(value > 100) value = wheelVolumeValue = 100; if(value < 0) value = wheelVolumeValue = 0; volumeBar.style.height = value + '%'; return value; } } function handlerBar(evt) { rightClick = (evt.which === 3) ? true : false; seeking = true; !rightClick && progressBar.classList.add('progress__bar--active'); seek(evt); } function handlerVol(evt) { rightClick = (evt.which === 3) ? true : false; seekingVol = true; setVolume(evt); } function seek(evt) { evt.preventDefault(); if(seeking && rightClick === false && audio.readyState !== 0) { window.value = moveBar(evt, progressBar, 'horizontal'); } } function seekingFalse() { if(seeking && rightClick === false && audio.readyState !== 0) { audio.currentTime = audio.duration * (window.value / 100); progressBar.classList.remove('progress__bar--active'); } seeking = false; seekingVol = false; } function setVolume(evt) { evt.preventDefault(); volumeLength = volumeBar.css('height'); if(seekingVol && rightClick === false || evt.type === wheel()) { var value = moveBar(evt, volumeBar.parentNode, 'vertical') / 100; if(value <= 0) { audio.volume = 0; audio.muted = true; volumeBtn.classList.add('has-muted'); } else { if(audio.muted) audio.muted = false; audio.volume = value; volumeBtn.classList.remove('has-muted'); } } } function notify(title, attr) { if(!settings.notification) { return; } if(window.Notification === undefined) { return; } attr.tag = 'AP music player'; } /* Destroy method. Clear All */ function destroy() { if(!apActive) return; if(settings.confirmClose) { window.removeEventListener('beforeunload', beforeUnload, false); } playBtn.removeEventListener('click', playToggle, false); volumeBtn.removeEventListener('click', volumeToggle, false); repeatBtn.removeEventListener('click', repeatToggle, false); plBtn.removeEventListener('click', plToggle, false); progressBar.closest('.progress-container').removeEventListener('mousedown', handlerBar, false); progressBar.closest('.progress-container').removeEventListener('mousemove', seek, false); document.documentElement.removeEventListener('mouseup', seekingFalse, false); volumeBar.closest('.volume').removeEventListener('mousedown', handlerVol, false); volumeBar.closest('.volume').removeEventListener('mousemove', setVolume); volumeBar.closest('.volume').removeEventListener(wheel(), setVolume); document.documentElement.removeEventListener('mouseup', seekingFalse, false); prevBtn.removeEventListener('click', prev, false); nextBtn.removeEventListener('click', next, false); audio.removeEventListener('error', errorHandler, false); audio.removeEventListener('timeupdate', timeUpdate, false); audio.removeEventListener('ended', doEnd, false); // Playlist pl.removeEventListener('click', listHandler, false); pl.parentNode.removeChild(pl); audio.pause(); apActive = false; index = 0; playBtn.classList.remove('is-playing'); playSvgPath.setAttribute('d', playSvg.getAttribute('data-play')); volumeBtn.classList.remove('has-muted'); plBtn.classList.remove('is-active'); repeatBtn.classList.remove('is-active'); // Remove player from the DOM if necessary // player.parentNode.removeChild(player); } /** * Helpers */ function wheel() { var wheel; if ('onwheel' in document) { wheel = 'wheel'; } else if ('onmousewheel' in document) { wheel = 'mousewheel'; } else { wheel = 'MozMousePixelScroll'; } return wheel; } function extend(defaults, options) { for(var name in options) { if(defaults.hasOwnProperty(name)) { defaults[name] = options[name]; } } return defaults; } function create(el, attr) { var element = document.createElement(el); if(attr) { for(var name in attr) { if(element[name] !== undefined) { element[name] = attr[name]; } } } return element; } Element.prototype.offset = function() { var el = this.getBoundingClientRect(), scrollLeft = window.pageXOffset || document.documentElement.scrollLeft, scrollTop = window.pageYOffset || document.documentElement.scrollTop; return { top: el.top + scrollTop, left: el.left + scrollLeft }; }; Element.prototype.css = function(attr) { if(typeof attr === 'string') { return getComputedStyle(this, '')[attr]; } else if(typeof attr === 'object') { for(var name in attr) { if(this.style[name] !== undefined) { this.style[name] = attr[name]; } } } }; // matches polyfill window.Element && function(ElementPrototype) { ElementPrototype.matches = ElementPrototype.matches || ElementPrototype.matchesSelector || ElementPrototype.webkitMatchesSelector || ElementPrototype.msMatchesSelector || function(selector) { var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1; while (nodes[++i] && nodes[i] != node); return !!nodes[i]; }; }(Element.prototype); // closest polyfill window.Element && function(ElementPrototype) { ElementPrototype.closest = ElementPrototype.closest || function(selector) { var el = this; while (el.matches && !el.matches(selector)) el = el.parentNode; return el.matches ? el : null; }; }(Element.prototype); /** * Public methods */ return { init: init, update: updatePL, destroy: destroy, playToggle:playToggle }; })(); window.AP = AudioPlayer; })(window); // TEST: image for web notifications var iconImage = 'http://funkyimg.com/i/21pX5.png'; AP.init({ playList: [ {'icon': iconImage, 'title': 'JWS-01', 'file': 'https://tnagano-web.s3.amazonaws.com/2021/JapaneseGenki3rdEdExerciseFiles_audios/Genki3rdEdAudio_JWS-01.mp3'} ] }); $(".container-fluid").click(function(event) { var target = $(event.target); if (target.is("a")) { event.preventDefault(); let newAudio = [ {'icon': iconImage, 'title': target.text(), 'file':target.attr('href')} ] AP.update(newAudio) } }); $(document).on('keyup', function(e) { e.preventDefault(); if (e.keyCode === 32) { AP.playToggle() } }); })();