MediaWiki:AudioPlayer.js
Jump to navigation
Jump to search
Note: After publishing, you may have to bypass your browser's cache to see the changes.
- Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
- Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
- Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
- Opera: Press Ctrl-F5.
(function() {
function addScript( src, callback ) {
var s = document.createElement( 'script' );
s.setAttribute( 'src', src );
s.onload=callback;
document.body.appendChild( s );
}
function getTimeCodeFromNum(num) {
let seconds = parseInt(num);
let minutes = parseInt(seconds / 60);
seconds -= minutes * 60;
const hours = parseInt(minutes / 60);
minutes -= hours * 60;
if (hours === 0) return `${minutes}:${String(seconds % 60).padStart(2, 0)}`;
return `${String(hours).padStart(2, 0)}:${minutes}:${String(
seconds % 60
).padStart(2, 0)}`;
}
function audioInit() {
groups = {};
$(".audio-player").each(function(index, audioPlayer) {
const dataSet = audioPlayer.dataset;
const audioGroup = dataSet.group;
const shouldLoop = dataSet.loop === "true";
const loopStart = parseFloat(dataSet.loopStart);
const loopEnd = parseFloat(dataSet.loopEnd);
const isPauseButton = dataSet.pauseButton;
const playerId = "audio" + index;
const playButton = audioPlayer.querySelector(".toggle-play");
const progressBar = audioPlayer.querySelector(".progress");
const timeline = audioPlayer.querySelector(".timeline");
const volumeButton = audioPlayer.querySelector(".volume-button");
const volumeButtonIcon = audioPlayer.querySelector(".volume");
const volumeSlider = audioPlayer.querySelector(".controls .volume-slider");
const volumePercentage = audioPlayer.querySelector(".controls .volume-percentage");
const audioTime = audioPlayer.querySelector(".time");
const audioCurrentTime = audioPlayer.querySelector(".current");
const audioDivider = audioPlayer.querySelector(".divider");
const audioLength = audioPlayer.querySelector(".length");
if (isPauseButton && isPauseButton === "true") {
playButton.addEventListener("click", function() {
groups[audioGroup].pause();
});
return;
}
let muted = false;
function pauseAudioIcon() {
playButton.classList.remove("pause");
playButton.classList.add("play");
}
const howler = new Howl({
src: [dataSet.src],
onpause: pauseAudioIcon,
onplay: function() {
playButton.classList.remove("play");
playButton.classList.add("pause");
},
onend: function() {
if (shouldLoop) {
howler.seek(0);
howler.play();
} else {
pauseAudioIcon();
}
},
onload: function() {
if (audioTime) {
audioCurrentTime.innerText = "0:00";
audioDivider.innerText = "/";
audioLength.innerText = getTimeCodeFromNum(howler.duration());
}
},
onvolume: function() {
if (volumePercentage) {
volumePercentage.style.width = howler.volume() * 100 + '%';
}
},
});
howler.volume(parseFloat(dataSet.volume));
function checkBGMLoop() {
const seek = howler.seek();
if (seek >= loopEnd && seek - loopEnd < 0.5) {
howler.seek(loopStart);
// seek will trigger update progress, so exit immediately for progress to be updated by next call
return;
}
}
if (shouldLoop && loopEnd !== 0) {
setInterval(checkBGMLoop, 20);
}
let lastSeek = 0;
updateProgress = function() {
const seek = howler.seek();
if (seek === lastSeek) {
return;
}
lastSeek = seek;
if (progressBar) {
progressBar.style.width = (seek / howler.duration() * 100) + "%";
}
if (audioCurrentTime) {
audioCurrentTime.innerText = getTimeCodeFromNum(seek);
}
};
howler.on("seek", updateProgress);
// update progress in every set interval
if ((shouldLoop && loopEnd !== 0) || progressBar || audioCurrentTime) {
setInterval(updateProgress, 100);
}
// controls playing and pausing
playButton.addEventListener("click", function() {
if (howler.playing()) {
howler.pause();
} else {
if (audioGroup && audioGroup !== "concurrent") {
const previousPlaying = groups[audioGroup];
if (previousPlaying) {
previousPlaying.pause();
}
groups[audioGroup] = howler;
}
howler.play();
}
});
// seek whenever the timeline is clicked
if (timeline) {
timeline.addEventListener("click", e => {
const timelineWidth = window.getComputedStyle(timeline).width;
const timeToSeek = e.offsetX / parseInt(timelineWidth) * howler.duration();
howler.seek(timeToSeek);
});
}
// controls volume button: either mute or unmute
if (volumeButton) {
volumeButton.addEventListener("click", function() {
if (muted) {
howler.mute(false);
volumeButtonIcon.classList.remove("icon-muted");
volumeButtonIcon.classList.add("icon-volume-medium");
} else {
howler.mute(true);
volumeButtonIcon.classList.add("icon-muted");
volumeButtonIcon.classList.remove("icon-volume-medium");
}
muted = !muted;
});
}
// controls volume slider
if (volumeSlider) {
volumeSlider.addEventListener('click', e => {
const sliderWidth = window.getComputedStyle(volumeSlider).width;
const newVolume = e.offsetX / parseInt(sliderWidth);
howler.volume(newVolume);
});
}
});
}
addScript("https://cdn.jsdelivr.net/npm/howler@2.2.4/dist/howler.min.js", audioInit);
})();