Why event is triggered more than once? - javascript

I'm trying to add an event handler for an audio Javascript plugin using the SoundManager2. This is the function that plays a song and wait for the end of the song to execute the function again:
function songPlay (newSrc) {
htmlSound.src = newSrc;
htmlSound.load();
thisPlayer.find( ".total-position-scrubber" ).bind( "slide", function(event, ui) {
htmlSound.currentTime = ui.value;
});
var currentArtist = currentRow.find(".total-artist").text();
var currentTitle = currentRow.find(".total-title").text();
thisPlayer.find(".total-playing-artist").html(currentArtist);
thisPlayer.find(".total-playing-title").html(currentTitle);
htmlSound.addEventListener("timeupdate", function() {
var newVolume = thisPlayer.find( ".total-volume-slider" ).slider("option", "value");
htmlSound.volume = newVolume;
var duration = htmlSound.duration * 1000;
var durationTime = convertMilliseconds(duration, "mm:ss");
thisPlayer.find(".total-song-duration").html(durationTime.clock );
var position = htmlSound.currentTime * 1000;
var positionTime = convertMilliseconds(position, "mm:ss");
thisPlayer.find(".total-song-position").html(positionTime.clock );
thisPlayer.find( ".total-position-scrubber" ).slider("option", "max", duration/1000);
thisPlayer.find( ".total-position-scrubber" ).slider("option", "value", position/1000);
});
htmlSound.addEventListener("ended", function() {
// Find next checked song
currentRow = currentRow.nextAll(".can-play:first");
// If checked song exists after current song, load it
if(currentRow.length > 0)
{
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
else
{
// If no checked song exists after current song, load the first checked song in playlist
if(thisPlayer.find(".can-play").length > 0)
{
currentRow = thisPlayer.find(".can-play:first");
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
// Change pause button to play button
else
{
thisPlayer.find(".total-play").removeClass("total-pause");
}
}
// If song is playing while next button is clicked play next song
if(thisPlayer.find(".total-pause").length > 0)
{
htmlSound.play();
}
});
thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
currentRow.find(".total-not-playing").addClass("total-playing");
}
The only problem is that the "ended" event is triggered more than once every time that a song finishes. After the "ended" event, the function is executed, and then the songPlay() function is executed again (this is the expected behavior), but then, the "ended" event is triggered again, before the song is finished, while it should wait for the end of the song. Any idea of the cause of that behavior?
The newSrc variable has always the right value.
This is the "ended" event definition in SoundManager2:
_html5_events = {
// HTML5 event-name-to-handler map
...
ended: _html5_event(function() {
var t = this._t;
_s._wD(_h5+'ended: '+t.sID);
t._onfinish();
}),
...
}
Edit:
Surprisingly, it worked just replacing the anonymous function with a declared function like this:
function eventListenerFunction() {
// Find next checked song
currentRow = currentRow.nextAll(".can-play:first");
// If checked song exists after current song, load it
if(currentRow.length > 0)
{
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
else
{
// If no checked song exists after current song, load the first checked song in playlist
if(thisPlayer.find(".can-play").length > 0)
{
currentRow = thisPlayer.find(".can-play:first");
var newSrc = currentRow.find("[src]").attr("src");
songPlay(newSrc);
}
// Change pause button to play button
else
{
thisPlayer.find(".total-play").removeClass("total-pause");
}
}
// If song is playing while next button is clicked play next song
if(thisPlayer.find(".total-pause").length > 0)
{
htmlSound.play();
}
});
function songPlay (newSrc) {
htmlSound.src = newSrc;
htmlSound.load();
thisPlayer.find( ".total-position-scrubber" ).bind( "slide", function(event, ui) {
htmlSound.currentTime = ui.value;
});
var currentArtist = currentRow.find(".total-artist").text();
var currentTitle = currentRow.find(".total-title").text();
thisPlayer.find(".total-playing-artist").html(currentArtist);
thisPlayer.find(".total-playing-title").html(currentTitle);
htmlSound.addEventListener("timeupdate", function() {
var newVolume = thisPlayer.find( ".total-volume-slider" ).slider("option", "value");
htmlSound.volume = newVolume;
var duration = htmlSound.duration * 1000;
var durationTime = convertMilliseconds(duration, "mm:ss");
thisPlayer.find(".total-song-duration").html(durationTime.clock );
var position = htmlSound.currentTime * 1000;
var positionTime = convertMilliseconds(position, "mm:ss");
thisPlayer.find(".total-song-position").html(positionTime.clock );
thisPlayer.find( ".total-position-scrubber" ).slider("option", "max", duration/1000);
thisPlayer.find( ".total-position-scrubber" ).slider("option", "value", position/1000);
});
htmlSound.addEventListener("ended", eventListenerFunction)
thisPlayer.find(".total-row .total-not-playing").removeClass("total-playing");
currentRow.find(".total-not-playing").addClass("total-playing");
}
However, I guess I should use $('body').off("ended") after the triggered function to remove the event listener, as #Fallenreaper has suggested.

you call songplay inside of a listener, which applies it another time.... and another time and another time.
recursion.
>_>

Related

TypeError: player.bind is not a function - jQuery

I cant seem to get this to work, all I am trying to do is make it so that this div's width increases as the audio player is playing so it acts as a progress bar. Everytime I run the script I get this in the console:
TypeError: player.bind is not a function
Here is my Javascript:
var player = document.getElementById('audio_player');
var progress = document.getElementsByClassName('progress-bar');
$(".play_btn").click(function() {
if(player.paused) {
player.play();
} else {
player.pause();
}
$(this).toggleClass('pause');
});
$(function() {
var check,
reached25 = false,
reached50 = false,
reached75 = false;
player.bind("play", function(event) {
var duration = player.get(0).duration;
check = setInterval(function() {
var current = player.get(0).currentTime,
perc = (current / duration * 100).toFixed(2);
if (Math.floor(perc) >= 25 &&! reached25) {
console.log("25% reached");
reached25 = true;
}
console.log(perc);
}, 500);
});
player.bind("ended pause", function(event) {
clearInterval(check);
});
});
You should use jQuery wrapper when call jquery methods on elements:
$(player).bind...

Shuffle song when it ends - javascript html5

I have this code that randomizes and play a song from a list of them:
var sounds = [
"sounds/royksopp.mp3",
"sounds/9thwonder.mp3",
"sounds/thisbeat.mp3",
"sounds/mosdef.mp3",
"sounds/bewater.mp3",
"sounds/boutdre.mp3",
"sounds/masterflash.mp3",
"sounds/2ep.mp3",
"sounds/drewestcoast.mp3",
"sounds/poetry.mp3",
"sounds/mfdoom.mp3",
"sounds/dreams.mp3",
"sounds/oizo.mp3", ];
function StartOrStop(audioFile) {
srcAudio = sounds[Math.floor(Math.random() * sounds.length)];
var audie = document.getElementById("myAudio");
audie.addEventListener('ended', function() {
this.currentTime = 0;
this.play();
}, false);
if (audie.paused == false) {
audie.pause();
} else {
audie.src = srcAudio;
audie.play();
}
}
When the song stops playing, it restarts with th same one. How can I make it so when the music ends, it will grab a new song from my list and automatically play it?
The problem is that you are simply calling this.play() in your ended event listener. Instead, you should be updating the src attribute with the random choice of song with this.src = srcAudio, similar to how you are for the initial selection:
function StartOrStop(audioFile) {
srcAudio = sounds[Math.floor(Math.random() * sounds.length)];
var audie = document.getElementById("myAudio");
audie.addEventListener('ended', function() {
this.currentTime = 0;
this.src = srcAudio;
this.play();
}, false);
if (audie.paused == false) {
audie.pause();
} else {
audie.src = srcAudio;
audie.play();
}
}
Hope this helps! :)

audio currentTime returning 0 and not the current time

I'm having an issue where I'm using this plugin:
I have created an abstract with the following code, and trying to read from the default <audio> and not the plugin. The plugin puts a visibility:hidden on the <audio> tag but I don't think that should affect anything.
Here's my code, it's for a slideshow, displaying images at certain intervals in the audio file:
var audio = $("audio");
audio.audioPlayer();
// Slideshow
var slideshowAudio = audio.data("slideshow"),
slideshowAudioId = document.getElementById("audio-default");
if (slideshowAudio == "1") {
var audioTime = Math.floor(slideshowAudioId.currentTime);
// console.log("Current Time: " + currentTime);
var slideshow = [];
$(".slideshow li").each(function () {
var id = $(this).data("slideshow-id"),
time = $(this).data("slideshow-time");
slideshow.push(time);
});
console.log(slideshow);
$(".audioplayer-playpause").on("touchend click", function () {
setInterval(function() {
alert("show " + audioTime);
for (i = 0; i < slideshow.length; i++) {
if (slideshow[i] == currentTime) {
}
}
}, 1000);
});
}

javascript code written in separate to the html markup

what's wrong with this code, i have included the file but when i run it doesn't give the result i intended(customized design of video player),any one who is aware about javascript can help.......
function dofirst() {
//get values of buttons
var movie = document.getElementById("movie");
var playOrpause = document.getElementById("playOrpause");
var mute = document.getElementById("mute");
var fullscreen = document.getElementById("fullscreen");
//get values of sliders
var seekbar = document.getElementById("seekbar");
var myvolume = document.getElementById("volume");
//add the event listeners to buttons
playOrpause.addEventListener('click', playme, false);
mute.addEventListener('click', mute_me, false);
fullscreen.addEventListener('click', scree_full, false);
//add the event listener to sliders
seekbar.addEventListener('change', change_me, false);
seekbar.addEventListener('timeupdate', update_me, false);
seekbar.addEventListener('mousedown', mous_down, false);
seekbar.addEventListener('mouseup', mous_up, false);
myvolume.addEventListener('change', volume_up, false);
}
//the functions of play button
function playme() {
if (movie.paused == true) {
movie.play();
//update button status
playOrpause.innerHTML = 'pause';
else {
movie.pause();
//update button status
playOrpause.innerHTML = 'play';
}
}
}
//the functions of mute button
function mute_me() {
if (movie.muted == false) {
movie.muted = true;
//update button status
mute.innerHTML = 'unmute';
} else {
movie.muted = false;
//update button status
mute.innerHTML = 'mute';
}
}
//the functions of fullscreen button
function scree_full() {
if (movie.requestFullscreen) {
movie.requestFullscreen();
}
//for mozilla firefox browser
else if (movie.mozRequestFullscreen) {
movie.mozRequestFullscreen();
}
//for google chrome browsers
else if (movie.webkitRequestFullscreen) {
movie.webkitRequestFullscreen();
}
}
//the functions for seekbar
function change_me() {
//calculate current time of the video
var time = movie.duration * (seekbar.value / 100);
//update the current time of the video
movie.currentTime = time;
}
//update the seekbar when the video plays
function update_me() {
var size = movie.currentTime * (100 / movie.duration);
//update the size of the seekbar
seekbar.value = size;
}
//pause the video when the seekbar is dragged
function mous_down() {
movie.pause();
}
//play the video when the seekbar is dropped
function mous_up() {
movie.play();
}
//the function for the volume bar
function volume_up() {
movie.volume = myvolume.value;
}
window.addEventListener("load", dofirst, false);
Make sure that there are no syntax errors in your code....For instance, you seem to be using 'mous_up()' instead of 'mouse_up()'. From my own experience, javascript code doesn't run when there are any syntax errors.

jQuery interval won't restart after hover out

After calling a PHP function, which generates the HTML,
I call the function below for the specific slider id.
That works fine, hover pauses the slideshow, also ok.
But when I am hovering out of the section, firebug gives the following error:
TypeError: o.handler.apply is not a function
And the slideshow won't continue.
Thanks in advance.
function CallSlider(sliderid){
var $slider = $('#'+sliderid);
var $slide = 'li';
var $transition_time = 1000; // 1 second
var $time_between_slides = 2000; // 4 seconds
function slides(){
return $slider.find($slide);
}
slides().fadeOut();
// set active classes
slides().first().addClass('active');
slides().first().fadeIn($transition_time);
$('#'+sliderid).hover(function() {
clearInterval(sliderid);
}, sliderid = setInterval(
function(){
var $i = $slider.find($slide + '.active').index();
//alert('test');
slides().eq($i).removeClass('active');
slides().eq($i).fadeOut($transition_time);
if (slides().length == $i + 1) $i = -1; // loop to start
slides().eq($i + 1).fadeIn($transition_time);
slides().eq($i + 1).addClass('active');
}
, $transition_time + $time_between_slides
)
);
}
I believe that error is related to the fact that hover() expects parameters to be functions.
Type: Function() - A function to execute when the mouse pointer enters/leaves the element.
http://api.jquery.com/hover/
I suggest putting your "hover off" code in its own function, like so:
$('#'+sliderid).hover(
function() {
// hover over
clearInterval(sliderid);
},
function () {
// hover off
sliderid = setInterval(...);
}
);
EDIT:
Here's an example, based on the code you provided, of how to keep things flexible (i.e. for dynamic lists).
var slide = 'li';
var transition_time = 1000; // 1 second
var time_between_slides = 2000; // 4 seconds
function startCycle($slider, $slides) {
return setInterval(
function () {
var $thisslide=jQuery(slide+'.active',$slider);
var $nextslide=($thisslide.next(slide).length?$thisslide.next(slide):$slides.eq(0));
$thisslide.removeClass('active').fadeOut(transition_time);
$nextslide.fadeIn(transition_time).addClass('active');
}, transition_time + time_between_slides
);
}
jQuery('ul.slider').each(function () {
var sliderid;
var $slider = jQuery(this);
var $slides = $slider.find(slide);
$slides.fadeOut();
// set active classes
$slides.first().addClass('active').fadeIn(transition_time);
$slider.hover(
function () {
// hover over
clearInterval(this.sliderid);
},
function () {
// hover off
this.sliderid = startCycle($slider, $slides);
}
);
this.sliderid = startCycle($slider, $slides);
});
http://jsfiddle.net/gk74V/1/

Categories