Javascript Sound Start/Stop and Image Change Part2 - javascript

I want to have a small image that when clicked plays a sound and changes to a different image. When the button is then clicked again it changes back to previous image ans stops the sound.
You can think of it as a button that says "start". when "start" is clicked it loops the sound and changes to "stop" and when "stop" is clicked it goes back to start and the sound ceases playing.
I tried using this code and it works perfectly for the images, but i can not seem to get the different sounds to play for the 2 images.
Javascript Sound Start/Stop and Image Change
I also found seperate code to play and stop sound with this script:
<script>
$(document).ready(function() {
var playing = false;
$('a#button').click(function() {
$(this).toggleClass("down");
if (playing == false) {
document.getElementById('player').play();
playing = true;
$(this).text("stop sound");
} else {
document.getElementById('player').pause();
playing = false;
$(this).text("restart sound");
}
});
});
</script>
<div>
<a id="button">play sound</a>
<audio id="player" src="mysound.mp3" preload="auto"></audio>
Which also works...
Can I combine the 2 together? Or am I not using the first javascript code correctly?
Any help would be much appreciated.

If you want to play a sound and change the image and vice versa, the following would work just fine:
HTML
<p>
<i class="fa fa-play fa-lg" aria-hidden="true"></i>
</p>
<audio id="player" src="http://soundbible.com/mp3/kids-record-player-daniel_simon.mp3" preload="auto"></audio>
JS
var playing = false;
$('#button').click(function() {
if (playing == false) {
document.getElementById('player').play();
playing = true;
$(this).find('i').removeClass('fa-play');
$(this).find('i').addClass('fa-pause');
} else {
document.getElementById('player').pause();
playing = false;
$(this).find('i').removeClass('fa-pause');
$(this).find('i').addClass('fa-play');
}
});
The idea is basically this: If the sound is playing, then swap classes. This example could be expanded to toggling the hide and show of images.
Refer to this working example.
Hope it helps.
EDIT
f I would want to use this for more than one image on the same webpage. Do I just add more add & remove classes? Or do I make a new function for every image?
Actually you can use that function for any number of images. We just need to generalize a few things and we are good to go.
The first thing I did was to change the jQuery selector for the click event. Previously we searched specifically for the element with the unique id #button. In order to bind to multiple buttons, I gave them the same name: $('[name=button]').
The variable playing helped us keep track whether or not the user played the button. In order to control whether or not the button was clicked, I had to move the variable playing to the audio element as an attribute. This way every audio element "knows" its current state (playing or paused);
HTML
<audio name="player" src="http://soundbible.com/mp3/kids-record-player-daniel_simon.mp3" preload="auto" data-playing="false"></audio>
Notice the data-playing="false" attribute
JS
var $button = $(this), // get the button
$player = $button.next('[name=player]'); // button and player are siblings
if ($player.data('playing') == false) {
$player[0].play();
$player.data('playing', true);
...
} else {
$player[0].pause();
$player.data('playing', false);
...
}
The trick here is to update the playing attribute to ensure we know the user clicked play or pause
Please refer to this updated version of the previous example.

Related

How to DUPLICATE the [Play] & [Pause] button for audio playback on the very same page?

Im having trouble firing up the audio (playback+pause) on the same page.
My standard HTML5 audio player works perfect and has standard controlls like this:
<play title="Play spoken audio for the visually impaired">▶</play>
<pause title="Pause audio, and press again to resume play">❚❚</pause>
Now imagine you would like to have a simplified alternative play/pause controls elsewhere on the same page. Good idea right? Now my problem is, that if I add a separate more minimalistic play / pause control elsewhere on the page, then the first play/pause buttons dissappear entirely!
<play>▶</play>
<pause>❚❚</pause>
All that I want is to duplicate the functionality of the first play/pause and place them elsewhere on the page, allowing users on mobile to have the play/pause on another location of the page for ease of use.
So in summary, I would like to allow the user to controll the playback from two different places simultaneously. The main one has fancier layout, while the alternative one in location 2 has only play and pause toggle. Both should toggle if either one is pressed. (when play is pressed it shows as a pause button and when pause is pressed it becomes a play button).
What must I change in html and or javascript to achieve this? Thanks in advance!
The javascript looks like this:
window.onload = function(){
var myAudio = document.getElementsByTagName('audio')[0];
var play = document.getElementsByTagName('play')[0];
var pause = document.getElementsByTagName('pause')[0];
function displayControls() {
play.style.display = "block";
}
// check that the media is ready before displaying the controls
if (myAudio.paused) {
displayControls();
} else {
// not ready yet - wait for canplay event
myAudio.addEventListener('canplay', function() {
displayControls();
});
}
play.addEventListener('click', function() {
myAudio.play();
play.style.display = "none";
pause.style.display = "block";
});
pause.addEventListener('click', function() {
myAudio.pause();
pause.style.display = "none";
play.style.display = "block";
});
}
DEMO
So you have the following code...
var myAudio = document.getElementsByTagName('audio')[0];
var play = document.getElementsByTagName('play')[0];
var pause = document.getElementsByTagName('pause')[0];
Step-by-step breakdown...
document.getElementsByTagName('audio')[0]
Get the 0th (1st) element in the document that has the tag name audio.
document.getElementsByTagName('play')[0]
Get the 0th (1st) element in the document that has the tag name play.
Problem #1. You only register the first play button for the code. You must add code for the second play button.
document.getElementsByTagName('pause')[0]
Get the 0th (1st) element in the document that has the tag name pause.
Problem #2. Same problem as #1.
So the solution is:
var audio;
window.onload=function(){
audio=document.getElementsByTagName("audio")[0];
//YOU MUST REGISTER AN EVENT LISTENER FOR EVERY PLAY AND PAUSE BUTTON.
document.getElementsByClassName("playpause")[0].addEventListener("click",playpause);
document.getElementsByClassName("playpause")[1].addEventListener("click",playpause);
}
function playpause(){
var state;
if(audio.paused){
audio.play();
state="Pause";
}else{
audio.pause();
state="Play";
}
for(var i=0;i<document.getElementsByClassName("playpause").length;i++){
document.getElementsByClassName("playpause")[i].innerHTML=state;
}
}
<audio>
<source src="http://www.kozco.com/tech/32.mp3" type="audio/mpeg">
</audio>
<button class="playpause">Play</button>
<button class="playpause">Play</button>

Media play/pause toggling without using too many if statements?

I am creating a playlist of songs for a website that looks like this:
However, I am struggling to figure out the proper way to implement all of the possible case statements that a user may go through while toggling the buttons such as:
toggling one play button on and off
toggling one play button on, and then clicking another play button so that the previous has to toggle off
and so on.
Right now my code (below) works for every case EXCEPT for when a user toggles a play button on and off, and then clicks a different play button. This specific case causes both of the icons to toggle to the pause button instead of just the most recently clicked. I know why this happens, it is because an ID of lastPlayed is left on the old play button, thus triggering the toggle if statment.
My question is, is there an easier way to set up play button toggling that covers all of these cases without having to make a specific if statement for every possible outcome?
Either finding a better solution or fixing my one bug works, but cleaner code is always preferred, thanks for any help!
var playCounter = 0;
function clickSongPlay(artist, title, url, imageURL, element) {
//debugger;
player.playlist.push(
{
title: title,
artist: artist,
file: url,
imageURL: imageURL,
howl: null
}
);
//check to see if we need to resume the song
if ($(element).hasClass("resumeSong") && $(".music-control").hasClass("ion-ios-play")) {
console.log("resuming");
/////////LINE BELOW RESUMES THE TRACK FROM CURRENT POSITION////////
player.play();
$(element).toggleClass("ion-ios-play ion-ios-pause");
$(".resumeSong").removeClass("resumeSong");
return;
}
//if a song is playing and the pause button is clicked, pause the track
if ($(element).hasClass("ion-ios-pause")) {
console.log("pausing");
player.pause();
$(element).toggleClass("ion-ios-pause ion-ios-play");
$(element).addClass("resumeSong");
return;
}
//start playing a new song
if ($(element).hasClass("ion-ios-play") && !$(element).hasClass("resumeSong")) {
if ($("#lastPlayed") && !playCounter == 0) {
console.log("here is a new song");
$("#lastPlayed").toggleClass("ion-ios-pause ion-ios-play")
$(".music-control").removeAttr("id", "lastPlayed");
}
console.log("new song");
///////LINE BELOW LOADS THE NEW SONG//////////////
player.skipTo(player.playlist.length - 1);
$(element).toggleClass("ion-ios-play ion-ios-pause");
$(element).attr("id", "lastPlayed");
playCounter += 1;
return;
}
}
Here is the HTML for a specific song div:
<div><i class="icon ion-ios-play music-control" onclick="clickSongPlay('#song.Artist','#song.Title','#song.URL','#song.Album.ImageURL', this);"></i></div>
Well, as I can see it, there are two problems here.
One, you need to pause any song that is currently playing, whenever an element is clicked. The step that is missing from your code is the position at which we the playing song is advanced so far. I'd record this into a data-offset property of the element itself. So later, we can continue playback from where it left...
Two, find out if the clicked element is on pause or not. If it is - resume, else play from the beginning.
So here is UNTESTED code sample, which might set you on the right track:
function clickSongPlay(artist, title, url, imageURL, element) {
var nowPlaying = $(element).siblings(".ion-ios-pause")
if (nowPlaying) {
player.pause();
nowPlaying.data("offset") = player.seek();
nowPlaying.toggleClass("ion-ios-pause ion-ios-play");
nowPlaying.addClass("resumeSong");
}
player.src(url);
player.seek($(element).data("offset"));
if ($(element).hasClass("resumeSong")) {
console.log("resuming");
$(element).removeData("offset");
$(element).toggleClass("ion-ios-play ion-ios-pause");
$(element).removeClass("resumeSong");
}
player.play();
}

Simple pause with vimeo api Froogaloop

Trying to call the vimeo api to pause video on a click event to hide it. And, on clicking to reveal the video again, play the video from its paused position.
There are various related questions on here, I can't find an answer to the simple "how to pause". I'm a jquery novice and can't make heads or tails of the froogaloop documentation.
Here's a FIDDLE, and my current jquery script to hide the video
$(document).click(function (event) {
if (!$(event.target).hasClass('click')) {
$('#video').hide();
}
});
which hides it when an element without the "click" class is clicked. But the video plays on in the background. Froogaloop is loaded in the fiddle. Thanks everyone
Here's an updated FIDDLE that makes pause/play work as I'd imagined. Click the image to play the video; click outside or on empty space (you control this with classes) to pause it; click image again to play from paused position. Simple, no buttons, no excess jquery or froogaloop code.
Putting this here for those who might benefit from it. And a +1 to mbrrw for getting me started.
var iframe = $('#video iframe')[0];
var player = $f(iframe);
$('.showvideo').on('click', function(){
$('#video').show();
$('.image').hide();
player.api('play');
});
$(document).click(function (event) {
if (!$(event.target).hasClass('click')) { //if what was clicked does not have the class 'click' (ie. any empty space)
$('#video').hide();
$('.image').show();
player.api('pause');
}
});
Remember to append api=1 to the vimeo link. And the url must be https, not http.
froogaloop can be a pain in the arse.
The code to get you started is here:
https://developer.vimeo.com/player/js-api#universal-with-froogaloop
I've adapted that to get it working i think how you expect here:
https://jsfiddle.net/fLe5xs4v/
Setting it up like so:
var iframe = $('#video iframe')[0];
var player = $f(iframe);
Note that if you change the text in the play and pause buttons you will break this code:
$('button').bind('click', function() {
player.api($(this).text().toLowerCase());
});
Give it a shot it should get you going in the right direction at least. Good luck!

SoundJS music clips should toggle each other on/off

I have a bunch of sounds on a page, similar to the sound grid example. Some of these tracks are music tracks and I'd like to treat them differently. Most of the sounds can play over each other and that is the intent, however, no music track should be able to play over another music track. Think radio buttons.
I've got some very woolly code that detects if the other track is playing when clicked and stops the track, and switches that track's css (play icons and such). But now, adding a 3rd or 4th track to the mix becomes unruly.
sounds are loaded and stored in a hash of reusable sound instances that look like:
mySounds["sound1"]= createjs.Sound.createInstance("sound1");
...
when the button in the html is clicked on (I'm not currently using the data-type attribute, that was from an earlier attempt but I thought it might be useful):
<button type="button" class="btn btn-vol btn-sm" data-type="music" data-track="music1" onclick="play(this)">
<span class="glyphicon glyphicon-play bplay"></span></button>
I currently do:
function play(target) {
//define some stuff from html
musicTrack = $(target).attr('data-track');
music1 = $('button[data-track="music1"]');
music2 = $('button[data-track="music2"]');
myInstance = mySounds[id] //id is defined elsewhere
toggle = $(target).find('span.bplay'); //this is where I have the play/pause icons
//For all cases, not just music I find the play icon and swap it.
if(toggle.hasClass('glyphicon-play')){ //the sound is ready to play. if it had a stop icon it would mean it was already playing
toggle.removeClass('glyphicon-play');
toggle.addClass('glyphicon-stop')
//special case for music Tracks
if(musicTrack == "music1") { //If I clicked on music track 1
if(mySounds[musicTrack2].position !=0){ //if it isn't 0, it's playing!
music2.find('span.bplay).removeClass('glyphicon-stop');
music2.find('span.bplay').addClass('glyphicon-play');
mySounds[musicTrack2].stop();
}
else {
//do nothing because track 2 isn't playing
}
} else if (musicTrack=="music2"){ //If I clicked on music track 2
if(mySounds[musicTrack2].position !=0){
music1.find('span.bplay').removeClass('glyphicon-stop');
music1.find('span.bplay').addClass('glyphicon-play');
mySounds[musicTrack1].stop();
}
else {
//do nothing because track 1 isn't playing
}
myInstance.play(); // play the clicked on instance
}
else {
//if the glyphicon does not say play (says stop) then we stop the sound etc..
toggle.removeClass('glyphicon-stop');
toggle.addClass('glyphicon-play');
myInstance.stop();
}
}
I haven't checked the above for syntax as I copied it by hand from my code, keeping only the relevant bits, but all this works. I click on music1, if music 2 isn't playing - it plays. If music 2 is playing, it stops music 2, switches it's stop icon to play and plays music 1. My actual code does some tweening of the sounds before it stops so they crossfade nicely.
I'm not a programmer but I'd love to be able to do this in a more efficient/elegant manner. Surely there is a way!
A better way to do this would be give the music buttons a different click handling function, and using a app / global variable to track the currently playing music. Then use the icon to determine behavior. You'd need to add a way to get the currently playing music, possible another variable. Something like this:
var currentMusic;
function playMusic(target) {
//define some stuff from html
musicTrack = $(target).attr('data-track');
myInstance = mySounds[id]; //id is defined elsewhere
toggle = $(target).find('span.bplay'); //this is where I have the play/pause icons
//For all cases, not just music I find the play icon and swap it.
if(toggle.hasClass('glyphicon-stop')){
toggle.removeClass('glyphicon-stop');
toggle.addClass('glyphicon-play');
currentMusic = null;
myInstance.stop();
}
else {
if(currentMusic) {
// get current instance and call stop
currentMusic.addClass('glyphicon-play');
currentMusic.removeClass('glyphicon-stop');
}
toggle.removeClass('glyphicon-play');
toggle.addClass('glyphicon-stop');
currentMusic = toggle;
myInstance.play();
}
}

script to check if a video is playing and not restart

Okay, that's phrased awkwardly, but what I'm looking for is a script that checks, onclick if a video is playing, and if it is, don't start playing it again. It's for a page that has six thumbs in an array that each play a video, and you're not supposed to be able to restart the video(which means its acting like its not selected)how would I be able to do this?
To prevent clicking from doing anything to the video you can do this:
$("video").click(function(e) {
e.preventDefault();
return false;
});
To determine if the video is playing or not you can read this previous question:
Detect if HTML5 Video element is playing
So you'll want to read that and then do something like:
$("video").click(function(e) {
if (videoStatus === "playing") {
e.preventDefault();
return false;
}
});
Let me know if you're not using jQuery and I'll update my answer to use getElementsByTagName.

Categories

Resources