elevenlabs_field-1.0.0-beta7/js/elevenlabs-widget.js
js/elevenlabs-widget.js
(function (Drupal) {
Drupal.behaviors.elevenlabsJsPlayer = {
players: {},
intervals: {},
timings: {},
currentCandidate: {},
nextCandidate: {},
attach: function (context, settings) {
// We always take over the play buttons click.
context.querySelectorAll('.elevenlabs-global-play').forEach((item) => {
let id = item.id;
let playerData = drupalSettings.elevenlabs[id];
// Wait until all audios are loaded, before allowing to play them.
let counter = 0;
if (playerData.state == 'loading') {
playerData.state = 'stopped';
for (let a of playerData.items) {
document.getElementById(a.id).addEventListener('canplaythrough', () => {
counter++;
if (counter == playerData.totalItems) {
document.getElementById(id).removeAttribute('disabled');
this.calculateTimings(id);
drupalSettings.elevenlabs[id]['item'] = item;
this.setEvents(id, item, playerData);
}
});
}
}
})
},
setEvents(id, item, playerData) {
// Play button.
if (!item.getAttribute('listener')) {
item.setAttribute('listener', 'true');
item.addEventListener('click', (e) => {
if (playerData.state == 'stopped') {
this.startPlaying(id, item, playerData);
} else {
this.pausePlaying(id, item, playerData);
}
return false;
});
}
// Seeker.
let seeker = document.querySelector('#' + id).parentElement.querySelector('#seek-slider');
if (!seeker.getAttribute('listener')) {
seeker.setAttribute('listener', 'true');
seeker.addEventListener('input', (e) => {
this.pauseAllPlayers(id, true);
clearInterval(this.intervals[id]);
playerData.currentTime = seeker.value * (playerData.totalTime / 1000);
this.updateTimings(id, true);
this.resetCandidates(id);
if (playerData.state == 'started') {
this.playTrack(id);
}
});
}
},
startPlaying(id, item, playerData) {
item.classList.add('pause');
playerData.state = 'started';
if ('id' in this.currentCandidate) {
document.getElementById(this.currentCandidate.id).play();
}
this.playTrack(id);
},
pausePlaying(id, item, playerData) {
playerData.state = 'stopped';
this.stopTrack(id);
item.classList.remove('pause');
},
playTrack(id) {
if (!('startTime' in this.currentCandidate)) {
this.getNextCandidate(id);
this.currentCandidate = this.nextCandidate;
}
this.intervals[id] = setInterval(() => {
Drupal.behaviors.elevenlabsJsPlayer.updateTimings(id, false);
}, 10);
this.updateTimings(id, false)
},
resetCandidates(id) {
this.resetCurrentCandidate(id);
this.getNextCandidate(id);
},
stopTrack(id) {
clearInterval(this.intervals[id]);
this.pauseAllPlayers(id, false);
},
updateTimings(id, force) {
let playerData = drupalSettings.elevenlabs[id];
if (!force && 'startTime' in this.nextCandidate &&
playerData.currentTime >= this.nextCandidate.startTime) {
this.currentCandidate = this.nextCandidate;
}
if (!force && 'startTime' in this.nextCandidate &&
playerData.currentTime >= this.currentCandidate.startTime &&
playerData.currentTime <= (this.currentCandidate.startTime + this.currentCandidate.duration)) {
document.getElementById(this.currentCandidate.id).play();
this.getNextCandidate(id);
}
playerData.currentTime = (Math.round(playerData.currentTime / 10) * 10) + 10;
if (playerData.currentTime >= playerData.totalTime) {
this.resetPlayer(id);
}
if ((playerData.currentTime % 1000 === 0) || force) {
document.querySelector('#audio-player-container #current-time').innerHTML = (this.calculateTime((playerData.currentTime / 1000)));
}
if ((playerData.currentTime % 10 === 0) || force) {
document.getElementById('audio-player-container').style.setProperty('--seek-before-width', playerData.currentTime / playerData.totalTime * 100 + '%');
document.getElementById('seek-slider').value = (playerData.currentTime / playerData.totalTime * 1000);
}
},
calculateTimings(id) {
let playerData = drupalSettings.elevenlabs[id];
if (!(id in this.timings)) {
this.timings[id] = {};
let startTime = 0;
for (let a of playerData.items) {
let audio = document.getElementById(a.id);
a.duration = audio.duration*1000;
a.startTime = startTime + parseInt(a.timePadding);
startTime += a.duration + parseInt(a.timePadding);
}
playerData.totalTime = startTime;
document.querySelector('#audio-player-container #duration').innerHTML = (this.calculateTime((startTime/1000)));
}
},
getNextCandidate(id) {
let playerData = drupalSettings.elevenlabs[id];
for (let a of playerData.items) {
if (playerData.currentTime <= a.startTime &&
this.currentCandidate != a) {
this.nextCandidate = a;
return;
}
}
},
resetCurrentCandidate(id) {
let playerData = drupalSettings.elevenlabs[id];
for (let a of playerData.items) {
if (playerData.currentTime <= (a.startTime + a.duration) &&
playerData.currentTime >= a.startTime) {
this.currentCandidate = a;
// Also scrub to correct place.
let time = (playerData.currentTime - a.startTime) / 1000;
document.getElementById(a.id).currentTime = time;
return;
}
}
},
pauseAllPlayers(id, reset) {
let playerData = drupalSettings.elevenlabs[id];
for (let x of playerData.items) {
let player = document.getElementById(x.id);
player.pause();
if (reset) {
player.currentTime = 0;
}
}
},
resetPlayer(id) {
let playerData = drupalSettings.elevenlabs[id];
playerData.item.classList.remove('pause');
clearInterval(this.intervals[id]);
playerData.currentTime = 0;
this.nextCandidate = {};
this.currentCandidate = {};
playerData.state = 'stopped'
},
calculateTime(secs) {
const minutes = Math.floor(secs / 60);
const seconds = Math.floor(secs % 60);
const returnedSeconds = seconds < 10 ? `0${seconds}` : `${seconds}`;
return `${minutes}:${returnedSeconds}`;
}
};
})(Drupal);
