audiofield-8.x-1.x-dev/js/wavesurfer.builder.es6.js
js/wavesurfer.builder.es6.js
/**
* @file
* Audiofield build Wavesurfer audio player.
*/
(($, Drupal, once) => {
'use strict';
Drupal.AudiofieldWavesurfer = {};
/**
* Generate a wavesurfer player.
*
* @param {jQuery} context
* The Drupal context for which we are finding and generating this player.
* @param {array} file
* The audio file for which we are generating a player.
* @param {jQuery} settings
* The Drupal settings for this player..
*/
Drupal.AudiofieldWavesurfer.generate = (context, file, settings) => {
const elements = once('generate-waveform', `#${file.id}`, context);
$.each(elements, (index, wavecontainer) => {
// Create waveform.
const wavesurfer = WaveSurfer.create({
container: `#${$(wavecontainer).attr('id')} .waveform`,
backend: settings.backend,
audioRate: settings.audioRate,
autoCenter: settings.autoCenter,
barGap: settings.barGap,
barHeight: settings.barHeight,
barWidth: settings.barWidth,
cursorColor: settings.cursorColor,
cursorWidth: settings.cursorWidth,
forceDecode: settings.forceDecode,
normalize: settings.normalize,
progressColor: settings.progressColor,
responsive: settings.responsive,
waveColor: settings.waveColor,
});
// Check if a peak file has been provided.
if (typeof file.peakpath !== 'undefined') {
// Fetch the provided file.
fetch(file.peakpath)
.then(response => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.then(peaks => {
// Normalize the provided peaks data.
Drupal.AudiofieldWavesurfer.normalizePeaks(peaks);
// Load the file.
wavesurfer.load(file.path, peaks.data);
$(wavecontainer).find('.player-button.playpause').html('Play');
})
.catch((e) => {
// Failed to load peaks, just load file normally.
wavesurfer.load(file.path);
console.error('error', e);
});
}
else {
// Load file without peaks.
wavesurfer.load(file.path);
}
// Set the default volume.
wavesurfer.setVolume(settings.volume);
// Handle play/pause.
$(wavecontainer).find('.player-button.playpause').on('click', (event) => {
Drupal.AudiofieldWavesurfer.PlayPause(wavecontainer, wavesurfer);
});
// Handle volume change.
$(wavecontainer).find('.volume').on('change', (event) => {
wavesurfer.setVolume(($(event.currentTarget).val() / 10));
});
// Handle autoplay.
if (!!settings.autoplay) {
wavesurfer.on('ready', wavesurfer.play.bind(wavesurfer));
}
Drupal.AudiofieldWavesurfer.instance = wavesurfer;
});
};
/**
* Normalize a peak file
*
* @param {jQuery} peaks
* The Wavesurfer peaks data for which we are normalizing data.
*/
Drupal.AudiofieldWavesurfer.normalizePeaks = function (peaks) {
var max = peaks.data[0], min = peaks.data[0];
var X, scale;
for (X = 1; X < peaks.data.length; X++) {
if (max < peaks.data[X]) {
max = peaks.data[X];
}
if (min > peaks.data[X]) {
min = peaks.data[X];
}
}
scale = 1.0 / Math.max(Math.abs(min), Math.abs(max));
for (X = 0; X < peaks.data.length; X++) {
peaks.data[X] *= scale;
}
}
/**
* Generate a wavesurfer playlist player.
*
* @param {jQuery} context
* The Drupal context for which we are finding and generating this player.
* @param {jQuery} settings
* The Drupal settings for this player.
*/
Drupal.AudiofieldWavesurfer.generatePlaylist = (context, settings) => {
const elements = once('generate-waveform', `#wavesurfer_playlist-${settings.unique_id}`, context);
$.each(elements, (index, wavecontainer) => {
// Create waveform.
const wavesurfer = WaveSurfer.create({
container: `#${$(wavecontainer).attr('id')} .waveform`,
audioRate: settings.audioRate,
autoCenter: settings.autoCenter,
barGap: settings.barGap,
barHeight: settings.barHeight,
barWidth: settings.barWidth,
cursorColor: settings.cursorColor,
cursorWidth: settings.cursorWidth,
forceDecode: settings.forceDecode,
normalize: settings.normalize,
progressColor: settings.progressColor,
responsive: settings.responsive,
waveColor: settings.waveColor,
});
// Set the default volume.
wavesurfer.setVolume(settings.volume);
// Load the first file.
const first = $(wavecontainer).find('.playlist .track').first();
// Get the label and update it with the first filename.
const label = $(wavecontainer).find('label').first();
label.html(`Playing: ${first.html()}`);
// Set the playing class on the first element.
first.addClass('playing');
// Load the file.
Drupal.AudiofieldWavesurfer.Load(wavecontainer, wavesurfer, first, false);
// Handle play/pause.
$(wavecontainer).find('.player-button.playpause').on('click', (event) => {
Drupal.AudiofieldWavesurfer.PlayPause(wavecontainer, wavesurfer);
});
// Handle next/previous.
$(wavecontainer).find('.player-button.next').on('click', (event) => {
Drupal.AudiofieldWavesurfer.Next(wavecontainer, wavesurfer);
});
$(wavecontainer).find('.player-button.previous').on('click', (event) => {
Drupal.AudiofieldWavesurfer.Previous(wavecontainer, wavesurfer);
});
// Handle clicking track.
$(wavecontainer).find('.playlist .track').on('click', (event) => {
// Check if the track is already playing.
if ($(this).hasClass('playing')) {
// Play/pause the track if it is already loaded.
Drupal.AudiofieldWavesurfer.PlayPause(wavecontainer, wavesurfer);
}
else {
// Load the track.
Drupal.AudiofieldWavesurfer.Load(wavecontainer, wavesurfer, $(event.currentTarget));
}
});
// Handle volume change.
$(wavecontainer).find('.volume').on('change', (event) => {
wavesurfer.setVolume(($(event.currentTarget).val() / 10));
});
// Handle autoplay.
if (!!settings.autoplay) {
wavesurfer.on('ready', wavesurfer.play.bind(wavesurfer));
}
// Handle track finishing.
if (settings.autoplayNextTrack) {
wavesurfer.on('finish', (event) => {
Drupal.AudiofieldWavesurfer.Next(wavecontainer, wavesurfer);
});
}
Drupal.AudiofieldWavesurfer.instance = wavesurfer;
});
};
/**
* Play or pause the wavesurfer and set appropriate classes.
*
* @param {jQuery} wavecontainer
* The container of the wavesurfer element we are accessing.
* @param {jQuery} wavesurfer
* The wavesurfer player we are accessing.
*/
Drupal.AudiofieldWavesurfer.PlayPause = (wavecontainer, wavesurfer) => {
wavesurfer.playPause();
const button = $(wavecontainer).find('.player-button.playpause');
if (wavesurfer.isPlaying()) {
$(wavecontainer).addClass('playing');
button.html('Pause');
}
else {
$(wavecontainer).removeClass('playing');
button.html('Play');
}
};
/**
* Load track on wavesurfer and set appropriate classes.
*
* @param {jQuery} wavecontainer
* The container of the wavesurfer element we are accessing.
* @param {jQuery} wavesurfer
* The wavesurfer player we are accessing.
* @param {jQuery} track
* The track being loaded into the player.
*/
Drupal.AudiofieldWavesurfer.Load = (wavecontainer, wavesurfer, track, playonload = true) => {
// Check for peak file.
const peakpath = track.attr('data-peakpath');
if (peakpath !== '') {
// Fetch the peak file.
fetch(peakpath)
.then(response => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.then(peaks => {
// Normalize the peaks.
Drupal.AudiofieldWavesurfer.normalizePeaks(peaks);
// Load the file with peaks data.
wavesurfer.load(track.attr('data-src'), peaks.data);
})
.catch((e) => {
// Error loading peaks, load file normally.
wavesurfer.load(track.attr('data-src'));
console.error('error', e);
});
}
else {
// Load the track normally.
wavesurfer.load(track.attr('data-src'));
}
wavesurfer.on('ready', (event) => {
if (playonload) {
$(wavecontainer).removeClass('playing');
$(wavecontainer).addClass('playing');
$(wavecontainer).find('.player-button.playpause').html('Pause');
wavesurfer.play();
}
});
// Remove playing from all other tracks.
$(wavecontainer).find('.track').removeClass('playing');
// Set the class on this track.
track.addClass('playing');
// Show what's playing.
$(wavecontainer).find('label').first().html(`Playing: ${track.html()}`);
};
/**
* Skip track forward on wavesurfer and set appropriate classes.
*
* @param {jQuery} wavecontainer
* The container of the wavesurfer element we are accessing.
* @param {jQuery} wavesurfer
* The wavesurfer player we are accessing.
*/
Drupal.AudiofieldWavesurfer.Next = (wavecontainer, wavesurfer) => {
if (wavesurfer.isPlaying()) {
Drupal.AudiofieldWavesurfer.PlayPause(wavecontainer, wavesurfer);
}
// Find the next track.
let track = $(wavecontainer).find('.track.playing').next();
if (typeof track.attr('data-src') === 'undefined') {
track = $(wavecontainer).find('.track').first();
}
// Load the track.
Drupal.AudiofieldWavesurfer.Load(wavecontainer, wavesurfer, track);
};
/**
* Skip track back on wavesurfer and set appropriate classes.
*
* @param {jQuery} wavecontainer
* The container of the wavesurfer element we are accessing.
* @param {jQuery} wavesurfer
* The wavesurfer player we are accessing.
*/
Drupal.AudiofieldWavesurfer.Previous = (wavecontainer, wavesurfer) => {
if (wavesurfer.isPlaying()) {
Drupal.AudiofieldWavesurfer.PlayPause(wavecontainer, wavesurfer);
}
// Find the next track.
let track = $(wavecontainer).find('.track.playing').prev();
if (typeof track.attr('data-src') === 'undefined') {
track = $(wavecontainer).find('.track').last();
}
// Load the track.
Drupal.AudiofieldWavesurfer.Load(wavecontainer, wavesurfer, track);
};
/**
* Attach the behaviors to generate the audio player.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Attaches generation of Wavesurfer audio players.
*/
Drupal.behaviors.audiofieldwavesurfer = {
attach: (context, settings) => {
$.each(settings.audiofieldwavesurfer, (key, settingEntry) => {
// Default audio player.
if (settingEntry.playertype === 'default') {
// Loop over the files.
$.each(settingEntry.files, (key2, file) => {
Drupal.AudiofieldWavesurfer.generate(context, file, settingEntry);
});
}
else if (settingEntry.playertype === 'playlist') {
Drupal.AudiofieldWavesurfer.generatePlaylist(context, settingEntry);
}
});
},
};
})(jQuery, Drupal, once);
