AudioPlaylist
An instance of AudioPlaylist manages a list of audio tracks which are played by an instance of AudioPlayer.
- Responder
- View
- AudioPlaylist
- View
Click on the name of a track in the list to load it in the player.
Press the play button to start playing the audio. Press the pause button to pause it. Move the slider or click in the progression bar to jump forward or backward in the audio. Turn on or off playing the audio in a loop. NOTE: The player moves automatically to the next track if playing in a loop is turned off.
In the console of the browser, load a track in the player:
audioplaylist.currentTrack=4
Add a time in milliseconds to wait between tracks:
audioplaylist.gap=2000
Turn off playing in a loop:
audioplayer.loop=false
Start the player:
audioplayer.play()
- function AudioPlaylist(player, tracks) {
- View.call(this);
- player.addListener(this);
- this._player = player;
- this._tracks = tracks;
- this._currentTrack = 1;
- this._gap = 0;
- this._timer = null;
- }
- AudioPlaylist.prototype = Object.create(View.prototype);
- Object.defineProperty(AudioPlaylist.prototype, 'constructor', { value: AudioPlaylist, enumerable: false, writable: true });
The AudioPlaylist class inherits from the View class.
player
is an instance of AudioPlayer.
tracks
is an array which lists the audio tracks managed by the instance.
Each track in the list is an object with a field title
, a character string, the title of the track, and a field url
, a character string, a URL which points to the audio file.
- Object.defineProperty(AudioPlaylist.prototype, 'currentTrack', {
- get: function() {
- return this._currentTrack;
- },
- set: function(n) {
- if (!Number.isInteger(n))
- throw new TypeError();
- if (n < 1 || n > this._tracks.length)
- n = this._tracks.length;
- if (this._tracks[this._currentTrack-1].widget)
- this._tracks[this._currentTrack-1].widget.classList.remove('selected');
- this._currentTrack = n;
- if (this._tracks[this._currentTrack-1].widget)
- this._tracks[this._currentTrack-1].widget.classList.add('selected');
- this._player.src = this._tracks[n-1].url;
- }
- });
currentTrack
is an accessor which returns or changes the track loaded in the audio player managed by this
.
currentTrack
returns or accepts in argument a track number.
A track number starts at 1.
If the track number in argument is smaller than 1 or larger than the number of tracks managed by this
, currentTrack
loads the last track.
- Object.defineProperty(AudioPlaylist.prototype, 'gap', {
- get: function() {
- return this._gap;
- },
- set: function(ms) {
- if (!Number.isInteger(ms))
- throw new TypeError();
- if (ms < 0)
- throw new RangeError();
- this._gap = ms;
- }
- });
- AudioPlaylist.prototype.audioEnded = function(sender) {
- if (this._currentTrack == this._tracks.length)
- this.currentTrack = 1;
- else {
- this.nextTrack();
- if (this._gap > 0)
- this._timer = setTimeout(() => { this._timer = null; this._player.play(); }, this._gap);
- else
- this._player.play();
- }
- };
- AudioPlaylist.prototype.audioPlayed = function(sender) {
- if (this._timer) {
- clearTimeout(this._timer);
- this._timer = null;
- }
- };
- AudioPlaylist.prototype.nextTrack = function() {
- return this.currentTrack = this._currentTrack == this._tracks.length ? 1 : this._currentTrack + 1;
- };
- AudioPlaylist.prototype.previousTrack = function() {
- return this.currentTrack = this._currentTrack == 1 ? this._tracks.length : this._currentTrack - 1;
- };
- AudioPlaylist.prototype.setWidget = function(w) {
- if (! (w.tagName == 'OL' || w.tagName == 'UL'))
- throw new TypeError();
- w.querySelectorAll('li > span').forEach((e, i) => {
- this._tracks[i].widget = e;
- e.onclick = () => this.currentTrack = i + 1;
- });
- View.prototype.setWidget.call(this, w);
- return this;
- };
- AudioPlaylist.prototype.createWidget = function() {
- const playlist = [];
- for (let trackdata of this._tracks)
- playlist.push(`<li><span>${trackdata.title}</span></li>`);
- const html = '<ol class="ojs_playlist">' + '\n' + playlist.join('\n') + '\n' + '</ol>';
- let template = document.createElement('template');
- template.innerHTML = html;
- let widget = template.content.children[0];
- this.setWidget(widget);
- return this;
- };
- AudioPlaylist.prototype.destroyWidget = function() {
- View.prototype.destroyWidget.call(this);
- for (let trackdata of this._tracks)
- delete trackdata.widget;
- return this;
- };
Test
The audio tracks by djduppy are available on Freesound.
- <?php $debug=true; ?>
Setting $debug
to true
gives access in the console of the navigator to the variables audioplayer
, the instance of the AudioPlayer, and audioplaylist
, the instance of the AudioPlaylist.
If $debug
is false
, all the code in JavaScript is protected by a closure function.
- <?php $ojs_audiolistdir='/files/sounds/djduppy'; ?>
- <?php $ojs_audiolist=array('bigbeat', 'electro', 'garage', 'hardtrance', 'hipfunk', 'ragga'); ?>
Defines the list of audio tracks read by the player, i. e. their file names and the folder on the server which contains them. Depending on the type of audio file the browser can read, the code adds the extension .ogg or .mp3 to the name of a track.
- <?php $id=uniqid('id'); ?>
Defines the identifier of the <div>
which surrounds the HTML of the audio player.
- .ojs_playlist {
- columns: 2;
- }
- .ojs_playlist li span:hover, .ojs_playlist li span.selected {
- color: #3bc;
Displays the list of audio tracks in 2 columns. Changes the color of the selected title.
- <div id="<?php echo $id; ?>" class="noprint">
- <div class="ojs_audio">
- <span class="audiocontrols">
- <span class="audioplay"><i class="fas fa-3x fa-play-circle"></i></span>
- <span class="audiopause"><i class="fas fa-3x fa-pause-circle"></i></span>
- <input class="audiobar" type="range" min="0" max="100" step="1" value="0"/>
- <span class="audiotime">00:00:00</span>
- <span class="audioloop"><i class="fas fa-sm fa-sync-alt"></i></span>
- </span>
- </div>
- </div>
Creates the widgets of the interface.
- <?php head('javascript', '/objectivejs/Objective.js'); ?>
- <?php head('javascript', '/objectivejs/Responder.js'); ?>
- <?php head('javascript', '/objectivejs/View.js'); ?>
- <?php head('javascript', '/objectivejs/AudioPlayer.js'); ?>
- <?php head('javascript', '/objectivejs/AudioPlaylist.js'); ?>
Includes the code of all the necessary classes.
REMINDER: The function head
of the iZend library adds a tag such as <script src="/objectivejs/Objective.js"></script>
to the <head>
section of the document in HTML. Adapt the code to your development environment.
- <?php if (!$debug): ?>
- (function() {
- <?php endif; ?>
Isolates all the code in JavaScript in a closure function if $debug
is false
.
- const audioplayer = new AudioPlayer();
- const container = document.querySelector('#<?php echo $id; ?>');
- audioplayer.setManagedWidget(container.querySelector('.ojs_audio'));
- audioplayer.loop = true;
- const dirname = '<?php echo $ojs_audiolistdir; ?>';
- const filelist = [<?php echo implode(',', array_map(function($s) { return "'$s'"; }, $ojs_audiolist)); ?>];
- const filetype = audioplayer.canPlayType('audio/ogg') ? '.ogg' : '.mp3';
- const audiotracks = [];
- for (let filename of filelist)
- audiotracks.push({title: filename, url: `${dirname}/${filename}${filetype}`});
- const audioplaylist = new AudioPlaylist(audioplayer, audiotracks);
- audioplaylist.createManagedWidget(container);
- audioplaylist.currentTrack = 1;
- <?php if (!$debug): ?>
- })();
- <?php endif; ?>
Closes the function which isolates the code in JavaScript if $debug
is false
.
Comments