I'm trying to develop a simple mp3 player with play/pause toggle functionality where the play button turns to a "||" icon when music is playing and reverts to the play button when the music is paused by using purely vanilla Javascript. I have viewed other posts regarding this matter, but none of them have helped me with the way I currently have my code structured.
var playButton = document.querySelector('#play-button');
var firstSong = new Audio('CloudDance.mp3');
var trackList = [firstSong];
function currentSong() {
for(var i=0; i<trackList.length; i++) {
var songID = document.querySelector('#stateicon');
if (trackList[i].paused) {
songID.id = 'fas fa-pause';
trackList[i].play();
} else {
songID.addEventListener('click', ) = 'fas fa-play';
trackList[i].pause();
}
}
}
<body>
<div class="screen">
<div class="song-info-text">
<p class="song-artist">Some text</p>
<p class="song-name">Some more text</p>
</div>
</div>
<div class="mp3-buttons">
<button class="button" type="button" name="button"><i class="fas fa-step-backward"></i></button>
<button id="play-button" onclick="currentSong()" type="button" name="button"><i id="stateicon" class="fas fa-play"></i></button>
<button class="button" type="button" name="button"><i class="fas fa-step-forward"></i></button>
</div>
<script src="index.js" charset="utf-8"></script>
</body>
All you need to do is set the class name depending on what you want. Here is your example with the fix.
songID.className = 'fas fa-pause';
Here is the sample code used in the JSFiddle link below
var playButton = document.querySelector('#play-button');
var firstSong = new
Audio('https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3');
var trackList = [firstSong];
function currentSong() {
for(var i=0; i<trackList.length; i++) {
var songID = document.querySelector('#stateicon');
if (trackList[i].paused) {
songID.className = 'fas fa-pause'; // Notice how we set className
trackList[i].play();
} else {
songID.className = 'fas fa-play'; // Notice how we set className
trackList[i].pause();
}
}
}
I also updated font-awesome css url in html to make sure the fonts would work properly. This is another part of the fix
<header>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"/>
</header>
JSFiddle Working Example
NOTE: You may end up running into issues later as you will end up playing multiple files at the same time with the way you have the for loop. So just keep in mind that you need to know which song it's currently playing so that you can properly pause or play that same song. And switch the current song when hit forward or backwards depending on the button pressed.
Related
I am currently developing a music streaming platform, if you can call it that, for my final year project. I started to redeisgn a few components and wanted to make a better audio player and this is where the problem(s) started to arise. I have my content wrapped around a for loop like so
{{for song in songs}}
{{endfor}}
After that I have the following HTML section that I'm trying to get to work
<img id="playAudio" src="https://fypkmpsr.s3.eu-west-1.amazonaws.com/{{song.artwork}}" class="img-fluid" alt="{{song}}">
<audio id="audio" src="/play/{{song.id}}" type="audio/wav"></audio>
<audio controls src="/play/{{song.id}}" type="audio/wav"></audio>
<progress min="0" max="100" value="0"></progress>
<div class="controls"></div>
<button type="button" class="btn btn-secondary-outline" onclick="playPauseAudio()">
<i class="bi bi-play"></i> | <i class="bi bi-pause"></i>
</button>
<button type="button" class="btn btn-secondary-outline" onclick="muteAudio()">
<i class="bi bi-volume-mute"></i>
</button>
<input type="range" class="form-range" id="customRange1" onclick="changeVolume()">
And my accompanying JavasScript code
<script>
source = document.getElementById('source').value;
function playPauseAudio() {
var audio = document.getElementById("audio");
if (audio.paused) {
audio.play();
} else {
audio.pause();
}
}
function muteAudio() {
var audio = document.getElementById("audio");
if (audio.muted) {
audio.muted = false;
} else {
audio.muted = true;
}
}
function changeVolume() {
var audio = document.getElementById("audio");
audio.volume = document.getElementById("customRange1").value / 100;
}
var audio = document.querySelector("audio");
var progressBar = document.querySelector("progress");
progressBar.addEventListener("click", seek);
function seek(e) {
var percent = e.offsetX / this.offsetWidth;
audio.currentTime = percent * audio.duration;
progressBar.value = percent / 100;
}
</script>
And I will also supply another cause as it is related to this problem
{% for song in songs %}
<h1>{{song.title}}</h1>
<input type="hidden" id="source" name="source" value="https://fypkmpsr.s3.eu-west-1.amazonaws.com/{{song.source}}">
<div id="waveform"></div>
<button class="btn btn-primary" onclick="wavesurfer.playPause()">
<i class="fa fa-play"></i>
Play
/
<i class="fa fa-pause"></i>
Pause
</button>
<script type=text/javascript>
var wavesurfer = WaveSurfer.create({
container: '#waveform',
waveColor: 'violet',
progressColor: 'purple'
});
var element = document.getElementById('source').value;
wavesurfer.load("https://fypkmpsr.s3.eu-west-1.amazonaws.com/{{song.source}}");
</script>
{% endfor %}
The problem from all of the above code is when I started to implement wavesurfer, a audio waveform visualizer. The code misbehaved for me as it created all the waveforms under one song heading / id. And it either played the last song or the first song in the database, depending on how I passed in my song source. The same applied to my own music player from the first snippet. No matter on what song I clicked on to play the audio file, it always plays the newest song i.e. the newest added id.
I've tried to break the code down and get the following as desired. I'd like to assume the problem persists from how I pass my data through and not making it unique but I'm not too sure if this is the case and where do I start from here.
The audio visualizations are meant to be under each heading and not under the newest song.
I am trying to add play/pause toggle functionality to a single button for an mp3 player project where the play button will turn to a "||" icon when music is playing and will revert to the play button when the music is paused by only using vanilla JavaScript. I have tried implementing an if-else statement which seems to be commonly used for this type of functionality, but the icon will only change to the "||" icon when the song is played, but will not pause and change to the play icon when clicked again. I have tried creating a separate function for the task of pausing the song, but still not getting the desired result.
var playButton = document.querySelector('#play-button');
var songArtist = document.querySelector('.song-artist');
var songTitle = document.querySelector('.song-name');
var stateIcon = document.querySelector('#stateicon');
var trackList = [ {
'Songartist': 'Artist1',
'Songtitle': 'Dance',
'songfile': 'Dance.mp3'
},
{
'Songartist': 'Artist2',
'Songtitle': 'Fight',
'songfile': 'Battle.mp3'
}
];
var currentSong = 0;
var song = new Audio();
function playSong() {
song.src = trackList[currentSong].songfile;
songArtist.innerText = trackList[currentSong].Songartist;
songTitle.innerText = trackList[currentSong].Songtitle;
if (song.paused) {
stateIcon.className = 'fas fa-pause';
song.play();
} else {
stateIcon.className = 'fas fa-play';
song.pause();
}
}
<body>
<div class="screen">
<div class="song-info-text">
<p class="song-artist">Some text</p>
<p class="song-name">Some more text</p>
</div>
</div>
<div class="mp3-buttons">
<button class="button" type="button" name="button"><i class="fas fa-step-backward"></i></button>
<button id="play-button" onclick="playSong()"><i id="stateicon" class="fas fa-play"></i></button>
<button onclick="nextSong()" class="button" type="button" name="button"><i class="fas fa-step-forward"></i></button>
</div>
<script src="index.js" charset="utf-8"></script>
</body>
The snipped provided is incomplete (no element has the class "song-artist", for one). I'd suggest looking at your javascript dev console for any errors, first. Otherwise, it could be that setting the src of your audio element is resetting your audio's play state. You could try only setting the src if it's different from that of the current track.
Is it possible to play a song using a font awesome icon, for example on the left will be the song name(mp3) and just to right of the track name will be a play font awesome icon, is it possible for a user to click on the play icon and the track starts playing and they can pause it and stop it
There will be about 10 tracks in the list
Has anyone got a sample code or a link to something similar please? I am guessing it will need some sort of javascript for the icons to be able to play, pause and stop
I found this code: http://jsfiddle.net/7341jxv6/2/ but am trying to amend it to use the font awesome play and pause icons instead of the text play and pause
My updated code is below
<audio id="audio1" src="tracks/ub40-ska/kingston-town.mp3"></audio>
<audio id="audio2" src="tracks/ub40-ska/homely-girl.mp3"></audio>
<audio id="audio3" src="tracks/ub40-ska/red-red-wine.mp3"></audio>
<audio id="audio4" src="tracks/ub40-ska/one-in-ten.mp3"></audio>
<div class="play" id="btn1"><i class="fa fa-play-circle" aria-hidden="true"></i></div>
<div class="play" id="btn2"><i class="fa fa-play-circle" aria-hidden="true"></i></div>
<div class="play" id="btn3"><i class="fa fa-play-circle" aria-hidden="true"></i></div>
<div class="play" id="btn4"><i class="fa fa-play-circle" aria-hidden="true"></i></div>
<script>
$('.play').click(function(){
var $this = $(this);
var id = $this.attr('id').replace(/btn/, '');
$this.toggleClass('active');
if($this.hasClass('active')){
$this.addClass('fa-pause-circle');
$('audio[id^="audio"]')[id-1].play();
} else {
$this.removeClass('fa-play-circle');
$('audio[id^="audio"]')[id-1].pause();
}
});
</script>
If I click on the play icon, it does play but the icon then disappears but if I click in the same place, it does pause the music
You can write click listener for the fa-icon;
DOM looks like this
<div class="play-tab">
<div class="track-name">Some Track Name<div>
<span class="icons"><i class="fa fa-play"/><span>
<div>"
JQuery
$(".play-tab").on("click" , "i", function(e){//fetch song id and play})
if you use the same button then you need a function that will change the icon and stop/play music
var myAudio = document.getElementById('media_audio');
var icon = document.getElementById('toglePlayPause');
var togglePlayPauseButton = document.getElementById('media_controls_play-pause-button');
//Event listener for the play button
togglePlayPauseButton.addEventListener("click", function() {
if ( myAudio.paused || myAudio.ended) {
if ( myAudio ) {
myAudio.title = 'Play';
icon.className = "fa fa-play";
}
myAudio.play();
} else {
if ( myAudio ) {
myAudio.title = 'Pause';
icon.className = "fa fa-pause";
}
myAudio.pause();
}
});
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="media_player">
<audio id="media_audio" >
Your browser does not support the audio tag.
</audio>
<div id='media_controls' >
<button
id="media_controls_play-pause-button"
class='icon'
title="Pause">
<i id="toglePlayPause" class="fa fa-pause"></i>
</button>
</div>
</div>
I have updated the code above as getting bit closer but got the issue of the icon disappearing after clicking play
You try to change icon on button element but the icon is on "i" tag.
To fix the bug you need to add a small fixes to your code
$('.play').click(function(){
var $this = $(this);
var id = $this.attr('id').replace(/btn/, '');
$this.toggleClass('active');
if($this.hasClass('active')){
$this.find("i").removeClass('fa-play-circle');
$this.find("i").addClass('fa-pause-circle');
$('audio[id^="audio"]')[id-1].play();
} else {
$this.find("i").removeClass('fa-pause-circle');
$this.find("i").addClass('fa-play-circle');
$('audio[id^="audio"]')[id-1].pause();
}
});
I want to create a basic page in html that displays a single image.
I also added two buttons Previous and Next. These buttons should allow the user to move forward or backward. Have 6 images in total. When the user reaches the end (or beginning when clicking on the back button) of the slide show, the slide show should not wrap around to the beginning (or end).
button onclick function for both the cases is not working. Its only getting displayed the first image as what mentioned in the img src attribute.
This is what I have done so far. I put all the images into an array and try to travel the array forward and backward side based on the button click.
<body>
<img src="img1.jpg" id="demo" style="width:400px;height:600px"/img>
<br/>
<input type="button" onclick="preImage()" value="Previous
">
<input type="button" onclick = "nextImage()" value="Next
">
<script>
var slider_content = document.getElementById("demo");
var image = ['img1','img2','img3','img4','img5','img6'];
var i = image.length;
function nextImage(){
if(i<image.length){
i=i+1;
}else{
i=1;
}
slider_content.innerHTML="<img src="+image[i-1]+".jpg>";
}
function preImage(){
if(i<image.length+1 && i>1){
i=i-1;
}else{
i=image.length;
}
slide_content.innerHTML = "<img src="+image[i-1]+".jpg">
}
</script>
</body>
Create a wrapper div to your image and change the innerHTML of the div.
<div id="demo" style="width:400px;height:600px">
<img src="img1.jpg">
</div>
An error needs to be corrected in the preImage function:
slide_content.innerHTML = "<img src="+image[i-1]+".jpg">
to
slider_content.innerHTML = "<img src="+image[i-1]+".jpg>";
and also what Daniel said.
When setting this up I did not initially notice that the third var declaration had an incorrect method call. The page functioned as I hoped and all was well.
Later I noticed that there was an error clocked in the inspector. I take out the offending line and all should be good- but the script does not work anymore. Strange. So I fix it and change getElementId('close') to the correct getElementById('close') and it the script as a whole still does not work.
This indicates that the script needs the broken component to properly function.
Be aware that the part that does not work anymore is openModal(). The audio.setAttribute() and audio.play() are in the same block and still work, so that is good.
I do not actually need a var close since the closeFunc() is called automatically onclick.
My html:
<div id='myModal' class='modal'>
<div id='modal-content'>
<span onclick='closeFunc()' id='close'>close x</span>
<object id='pdf-enter' data='' type='application/pdf'><p id='fallback-text'>Your browser does not support this media. You can download it <a id='dl-link' href=''>here.</p></a></object>
</div>
</div>
<div class='aud'>
<audio id='paudio' src='../../music/Available Now.mp3' controls='controls' preload="metadata">Your browser does not support the <code>audio</code>element.</audio>
<p id='audio-metadata'></p>
</div>
. . .
<li><a href='#0' class='title'>Sassthefrass <i onclick='audiosass()' class="fa fa-play-circle-o fa-fw" aria-label='Listen to music.'></i> <i onclick='openModal(), sass()' class='fa fa-file-pdf-o fa-fw' aria-label='View the sheet music.'></i></a>
</li>
and the javascript
<script defer async>
var modal = document.getElementById('myModal');
var here = document.getElementById('dl-link');
var close = document.getElementId('close');
var pdf = document.getElementById('pdf-enter');
function openModal() {
modal.style.display = "block";
}
function sass() {
pdf.setAttribute('data', '../../scores/Sassthefrass Perusal.pdf');
here.setAttribute('href', '../../scores/Sassthefrass Perusal.pdf');
}
function closeFunc() {
modal.style.display = "none";
}
</script>
When correctly working, clicking on the pdf FA icon opens a modal with a pdf showing the sheet music. When the code is 'error free', it does not do this anymore.
This is a reduced version, but you can see the entire thing in action at cortlandmahoney.com/pages/comp/acoustic.html. Be aware the site is still in development, but is near completion.
Close is not defined as an ID.
You have to define as 'close x'
and at your javascript you can assign function like :
document.getElementById('foo').onclick=function(){
alert("You have clicked close");
};
I looked at your website link and there is one more exception regarding jquery.
In jquery you have to define as $('#id').onclick() function to assign onclick function.
Your code worked fine on my end with a little modification. Unless I don't I understand you.
<div id='myModal' class='modal'>
<div id='modal-content'>
<span onclick='closeFunc()'>close x</span>
<object id='pdf-enter' data='' type='application/pdf'><p id='fallback-text'>Your browser does not support this media. You can download it <a id='dl-link' href=''>here.</p></a></object>
</div>
</div>
<div class='aud'>
<audio id='paudio' src='../../music/Available Now.mp3' controls='controls' preload="metadata">Your browser does not support the <code>audio</code>element.</audio>
<p id='audio-metadata'></p>
</div>
. . .
<li><i onclick='audiosass()' class="fa fa-play-circle-o fa-fw" aria-label='Listen to music.'>audiosass</i> <i onclick='openModal(), audiosass()' class='fa fa-file-pdf-o fa-fw' aria-label='View the sheet music.'>open</i>
</li>
<script defer async>
var modal = document.getElementById('myModal');
var here = document.getElementById('dl-link');
var close = document.getElementById('close');
var pdf = document.getElementById('pdf-enter');
function openModal() {
modal.style.display = "block";
}
function audiosass() {
pdf.setAttribute('data', '../../scores/Sassthefrass Perusal.pdf');
here.setAttribute('href', '../../scores/Sassthefrass Perusal.pdf');
}
function closeFunc() {
modal.style.display = "none";
}
</script>