Javascript. Var++ not properly working - javascript

I've been learning JS for a few days. stackoverflow was a great help. However I came up with a problem I cannot even determine or describe (since I'm new to this).
I've built an < audio >-based mp3 player.
You need to see /try it by yourself. (sorry)
Please check JS code here - ctrl-f 'STACKoverflow' in it - AntonFrolov.net/music.php
Here is the actions you need to perform to see where the problem is (I've put these to website too).
Click on track #2 - You will notice an alert('Track #' +ID); = [Track #2]
There is a player in the bottom-right corner - Set track progress to 98% so it ends.
(ID++), You are sent to the track#3 . alert('Track #' +ID); = [Track #3]. good.
Repeat step 2.
(ID++), You should be sent to the track#4. ... PROBLEM Events:
5a. alert('Track #' +ID); = [Track #3].
5b. Track#3 starts playing. AGAIN. then you instantly receive next .. alert
5c. alert('Track #' +ID); = [Track #4].
5d. Track#4 starts playing. that's what I expected but without events 5a-5b.
This will continue if you keep doing the steps.
However the JS code is here:
function FuncPlay(ID,Rnd){
alert('Track #'+ID);
if (Rnd==0){
$('.liActive').removeClass('liActive');
$('#'+ID).next().addClass('liActive');
// Set track Data
$('audio').attr('id','audioNor');
$('audio').attr('src',$('.liActive').attr('rel'));
// Play
var player = $('.tbd').get(0);
player.play();
$('#pause').removeClass('hi');
ID++;
$(player).bind('ended', function () {
if (ID <= <?php echo $am ?>){FuncPlay(ID, 0);}
else {alert('"...End of the list."' );}
});
}
}
I have completely no idea how to deal with this. Thank you for your patience.

I think the problem is that you're binding the ended-handler multiple times to your player. Everytime FuncPlay gets called, it will be attached another time.
So for example if then track 5 starts, it will first call the handler for track 3, then track 4 and finally track 5.
What you could do is creating a global variable called ID and bind to the handler only when document ready is called. In the handler-function you refer to this global variable.
Or, before calling $(player).bind, remove all bindings to the players ended event.
Also, I would recommend using .on(), .bind() is just still available for backwards compatibility. The method to unbind the event-handler is .off()/.unbind().

You don't unbind you 'ended' event listener. Is is called 2 times on the second song end, 3 times on the third, etc.

Related

Need help understanding javascript code/jquery

So apparently the following can be used to automate linkedin steps of unfollowing a contact. I tried to run this code in the Chrome Console, and I'm not sure if it works. So I need help from someone who knows Javascript and JQuery to understand what this does, and then I can modify it to make it work.
var buttons = $("button"),
interval = setInterval(function(){
var btn = $('.is-following');
console.log("Clicking:", btn);
btn.click();
if (buttons.length === 0) {
clearInterval(interval);
}
}, 1000);
PS: The linkedin page that lets to unfollow your contacts is below. Login, and then navigate to the below.
https://www.linkedin.com/mynetwork/invite-connect/connections/
First, it selects all the buttons and stores them on the variable buttons ($("TAG") will select elements with the tag TAG). Then, it creates an interval that will be stored in the variable interval (bad practice, btw, because it isn't using "var" to declare the variable, so, it's a global variable, that should be avoided... but it's necessary to declare it as global in order to use clearInterval) that will execute the function inside the setInterval function call every second (1000 ms). That function will get all the elements that have the class "is-following" and will store them on the variable btn. Then, it will log the... buttons? After that, it will execute the click event on all of those buttons. Finally it will check if the amount of buttons are 0. If true, it'll stop the interval.

Howler js pause/resume trouble

I'm using the Howler js library to set a player in an app running through Electron. First everything seemed to work well, but after a few weeks using the app, a bug occurs repeatedly, but not constantly : the pause() function doesn't work. Here's some piece of code :
Initialization :
var is_paused = true;
var currentTrack = "track1";
var tracks = {"track1" : new Howl({urls: ['path/to/track1.mp3']}),
"track2" : new Howl({urls: ['path/to/track2.mp3']}),
"track3" : new Howl({urls: ['path/to/track3.mp3']})
};
Then I have a few buttons for play/resume, pause, stop, and play a specific track :
$('#playS').click(function(){
if (is_paused){
tracks[currentTrack].play();
is_paused = false;
}
});
$('#pauseS').click(function(){
tracks[currentTrack].pause();
is_paused = true;
});
$('.trackBtn').click(function(){
tracks[currentTrack].stop();
currentTrack = $(this).attr('id');
tracks[currentTrack].play();
is_paused = false;
});
The problem is that sometimes (generally after 40-45 min of a track playing), the pause() function just do nothing, which is really annoying cause I need to pause the track and play another 30 sec file and then resume the current track. I checked the console while the bug occurs, it says absolutely nothing. I have no idea where the bug comes from, there's not a lot of information about how works the library. I really need some help here, thank's in advance.
EDIT : one more thing, when pause() doesn't work, if I click play() the track plays from the begining, and I have control on this second instance of the track. It's like the first instance has reached end, but still playing.
Without knowing what version of Howler you're using, or what other code might be messing things up, there is one thing I think might help: You don't need to track the paused state. The "playing" method takes care of that. I've made it work using something like this:
// If it's paused, it's not playing, so...
paused = !myHowlInstance.playing();
Another thing I noticed is that you have currentTrack = $(this).attr('id'); in your (I think it's a) stop button. Unfortunately I don't know JQuery well enough to know if there's anything wrong with that (I'm more of a Dojo fan myself). But it looks like currentTrack may be set to some value not in your list (which would break tracks[currentTrack]). You might want to go into the console and type tracks["track1"], currentTrack etc. to see their values. You can even do tracks[currentTrack].play(); and see what happens. I wasn't sure if you knew you could do that (it was a huge help to me when I found out about it).
And as far as the "un-pausing" starting from the beginning, I'm currently struggling with it myself; at this time there's no clear way to do this (no resume(), pause(false) etc.), and I've seen a few more questions on the subject on Google and SO, so you're not alone. I've experimented with the seek method, but with no luck. I'll post a comment if/when I reach a breakthrough on that. :)
EDIT: I figured out the play-from-beginning thing. It does involve "seek", and also the whole "instance ID" concept (which I never really understood the importance of from the documentation).
Here's an example from a project I'm working on (also a game); it doesn't involve JQuery (sorry), but it should give you the gist of how to fix the problem.
var myBgMusic = new Howl(...);
var myMusicID = myBgMusic.play(); // The docs say play() returns an ID, and I'll be passing that to "seek" later.
var paused = false;
var saveSeek;
function TogglePause() {
if (paused) {
myBgMusic.play(myMusicID);
myBgMusic.seek(saveSeek, myMusicID);
} else {
myBgMusic.pause();
saveSeek = myBgMusic.seek(myMusicID);
}
};

youtube repeat oneliner

I am trying to make a oneliner to repeat videos.
I started looking for that replay button to trigger another round:
$("[title='Replay']")[0].click();
A self calling function to loop in the background while the vid is running.
rpt=function(){setTimeout(function(){alert("blarg");rpt()},5000)}
putting those two things together and adding a tiny bit of fluff:
$ = jQuery to initialize shiny $()-syntax and finally rpt();to get things rolling:
$=jQuery,rpt=function(){setTimeout(function(){$("[title='Replay']")[0].click(),rpt()},100)};rpt();
alas, the parts work but not the whole thing
I noticed that the console is printing an error message if I enter the final line before the video has finished; since the button is not found yet and therefore a call to .click() on undefined isn't working.
Shouldn't the function still loop in the background and trigger during a later call, as soon as the replay button is there for jQuery to grab?
I'm using chrome 44.0.2403.130 and jQuery: 1.10.1
Add a verification to make sure there is a replay element available.
Use setInterval() instead of setTimeout().
By default (and unless you use other conflicting libraries), jQuery is assigned to the $ variable on its initialization.
setInterval(function(){if($("[title='Replay']").length)$("[title='Replay']").trigger('click');},100);
one line repeat + number of repeat appended in title:
var title=$('#eow-title').innerHTML; var replaysN = 1; setInterval(function(){if($('.ytp-play-button').title == 'Replay') {$('.ytp-play-button').click();$('#eow-title').innerHTML = title+' (x'+replaysN+')';replaysN++;} }, 1000);
..after some weeks after making this post, there was a new feature in youtube :D
After right-click on video -> Loop
So every customization is useless :)

canplaythrough firing intermitently in firefox

I'm trying to preload audio files for a game. I'm using Jplayer. I have an overlay that gets removed once all audio has been preloaded. In Firefox, sometimes canplaythrough gets fired, sometimes not. I have five audio files, sometimes I get three canplaythrough events, sometimes four, not often do I get all of them. If I log which ones work, the event isn't always fired, or not, on the same audio files.
I've tried to break the code as much as possible. Here I am adding a new Jplayer instance for each audio file, I still get the same problem.
{
for(var i = 0; i < _timeOutAudioFilesToLoad; i++){
c = i + 1;
var elid = "timeOutAudio"+c;
var elt = '<div id="'+elid+'" class="audioPlayer audio-player" data-audio-file="/themes/foo/sounds/time'+c+'.mp3"></div>';
$("#jPlayers").append(elt);
$("#"+elid).jPlayer( {
swfPath: "/themes/foo/js/libs/jPlayer250/Jplayer.swf"
});
}
}
{
$(".audioPlayer").each(function(){
var audioFile = $(this).attr("data-audio-file");
$(this).bind($.jPlayer.event.canplaythrough, function(event) {
_loadWatcher();
});
$(this).jPlayer("setMedia", {mp3: audioFile});
})
}
The _loadWatcher() function gets called by some, but not others.
Am I doing something wrong? Or is this a bug with a workaround? I've tried the Jplayer Google Group, but for some reason, they're taking days and days to mod questions.
Thanks
My problem was that I was binding the event before instantiating jPlayer on the element. I didn't realise that jplayer was actually waiting for a custom event - not the standard HTML5 event - so I thought binding anywhere would be OK. You live and learn. So switching the order of the last two lines in the for loop fixed the problem.

Trigger JQuery function after quicktime reaches end

I read the Apple documentation on how to make use of the DOM events for Quicktime. I am having trouble making it work within JQuery... I'd like to make use of the fade() function - that's why within JQuery.
Here's the code:
function onm_remove_intro(){
$('#basecamp_intro_div').fadeOut(4000);
}; //end function onm_remove_intro()
function onm_add_event_listener(object, event, handlerfunction, capture_bool){
if ( document.addEventListener )
{object.addEventListener(event, handlerfunction, capture_bool)}
else
// IE
{object.attachEvent('on' + event, handlerfunction)};
}; //end function onm_add_event_listener(object, event, handlerfunction, capture_bool)
var listener_object = $('#intro_movie_embed');
onm_add_event_listener(listener_object, 'qt_ended', onm_remove_intro, false);
Unless I comment out the last line, the execution of onm_add_event_listener, any JQuery code after it does not run. So clearly I am doing something illegal, but cannot figure out what.
I verified that the listener object variable does return a valid DOM object in Safari, which is where I am testing for now. Not concerned with IE yet.
Here is a reference to Apple's documentation on the subject:
http://developer.apple.com/library/mac/#documentation/QuickTime/Conceptual/QTScripting_JavaScript/bQTScripting_JavaScri_Document/QuickTimeandJavaScri.html%23//apple_ref/doc/uid/TP40001526-CH001-SW5
Hoping it's something really simple and that I am just too bleary eyed at this point to see it... All I want to do, if it isn't evident from the code example is to fade out the video after it reaches the end.
Thanks in advance,
M
Without having any experience with quicktime DOM events it seems to me the listener_object should be the DOM element, instead of the jquery object.
Have you tried:
var listener_object = $('#intro_movie_embed').get(0);

Categories