HTML 5 audio, detect "play" with no errors - javascript

The HTML 5 audio API is super easy, this page tells it all. But I am failing to achieve the following: catch the error (if there was one) and do something else when there are NO errors!
You may think this is easy, and that I should attach event listeners to the "error" and "play" events. But know the following:
The "error" event works only on the sub element "source", not the "audio" tag itself, this of course makes sense, since there could be more than one source.
The "play" event triggers when the file starts playing for the first time and also when the file is paused and played again!
The "play" event is triggered regardless of any errors!
What I am trying to do is simply set both the "error" / "play" events, but prevent the "play" whenever an error occurs.
var player = $('audio#player');
player.find('source').on('error', function(){
alert('Cannot play this file!');
});
player.on('play', function(){
setTheNextSongToPlay(' .... ');
});
Now, the "setTheNextSongToPlay" function is called whether there were any errors or not. How is that possible anyway ?! THE FILES WASN'T PLAYED!

Related

Removing a listener class doesn't stop a sound event associated Jquery Javascript

I'm playing a sound when hovering on an image (this is working fine already) and want to include a button to turn this off if desired. Unfortunately I haven't been able to make it work.
My current code goes like:
For creating the sound
//a bunch of code to generate the audio that ends on
var mouseoversound = createsoundbite('mysound.mp3')
For triggering it
$(".play").mouseover(function() {
mouseoversound.play();
});
The listener element
<%= image_tag "image.png", class:'logo-image play' %>
I thought that the simplest solution for disabling it was to remove the class 'listening' for the event (i.e. '.play') in the element listener, so I tired:
$(".sound").click(function(){
$(".logo-image").removeClass("play");
});
//.sound is the class of the button that's intended to block it.
Although the latter script does successfully remove the class 'play' the sound keeps playing every time I hover over the image. What am I missing? shouldn't the sound just stop playing?
Do you see any other solution to this?
Cheers
The issue is because the event handler is bound to the element. Removing the class after the event is bound does not affect that binding. To affect the event handler, you can call off(), like this:
$(".sound").click(function(){
$(".logo-image").off('mouseover');
});
Alternatively, if you want to toggle the sound functionality based on the class, you can keep your current logic and check that the element still has the class in the mouseover handler:
$(".logo-image").mouseover(function() {
if ($(this).hasClass('play') {
mouseoversound.play();
}
});
$(".sound").click(function(){
$(".logo-image").toggleClass("play");
});

JavaScript function logic to play/pause HTML5 video

I have a script which plays/pauses a HTML5 video based on the window size. When the user enters fullscreen, the video plays. When the user exits fullscreen, the video pauses, as expected. If you enter fullscreen again on the paused video, it will call a play and then pause immediately.
Here's the play/pause script and the console logs:
// Listen for exiting fullscreen, hide video element.
$("#" + m).on("webkitfullscreenchange", function(e) {
this.className = "hide";
if($("#" + m).get(0).paused) {
v.play();
console.log('playing...')
} else {
v.pause();
console.log('pausing...')
}
Here's a CodePen demo with representative HTML and the full script.
What can I do in my logic to prevent the second pause call being made?
I found the origin of your problem.
Here is the general structure of your code :
$(document).ready(function() {
$('.cell').on('click', function() {
// some more code ...
$("#" + m).on("webkitfullscreenchange", function(e) {
// here the code for the event handler that pauses and plays the video
});
)};
)};
You can see that the code that adds the handler on the "webkitfullscreenchange" event... is inside the handler for the .cell click event !
Here what happens : every time you click on the cell, you request the fullscreen, and you add a new event handler on the "webkitfullscreenchange" event (in jQuery, on register a new event handler, it does not replace the previous one if there was one).
The first time you click, you add the handler and you request full screen mode : it emits the event, your single handler gets it and plays the video.
But the second time you click, you request full screen mode and you add a second handler. When the event is emitted, both handlers react : the first one plays the video, and the second... immediately pauses it.
So here's part of the solution : just remove the part where you register more event handlers out of the click event handler (as a rule of thumb, situations when you have to set up handlers inside other handlers are very specific, so do not do it if you don't have any specific reason).
Why part ? Because even if it solves your first problem, it does leave another one: what happens if you click, let the video finish, and then quit full screen mode? The handler will get called, verify if the video is playing, notice that it is not and start playing it... even if you just left full screen.
So here's the final solution: set up your handler so that it checks if you just went in or out of full screen mode(using document.webkitIsFullScreen), and play or pause accordingly, as per #CBroe suggestion in the comments.
$('video').on('webkitfullscreenchange', function(e) {
if(document.webkitIsFullScreen) {
this.play();
} else {
this.className = "hide";
this.pause();
}
});
I forked your CodePen and set up the full solution if you want to have a look.

Delegated event triggering even when it shouldn't

I have the following code:
// Define controls
$('.play-video').click(function(){
// Get the video element
var video = $(this).parent().parent().find('video');
// Play the video
$(video).get(0).play()
// Remove the play class and add the pause class so the same button will pause the video
$(this).removeClass('play-video');
$(this).addClass('pause-video');
// Set pause text
$(this).text('Pause');
});
$(document).on('click','.pause-video',function(){
console.log('pausing...');
// Get the video element
var video = $(this).parent().parent().find('video');
// Play the video
$(video).get(0).pause()
// Remove the play class and add the pause class so the same button will pause the video
$(this).removeClass('pause-video');
$(this).addClass('play-video');
// Set pause text
$(this).text('Play');
});
Problem is, that the second click event should trigger on .pause-video only but also triggers on .play-video
Question is: What did I do wrong?
Thanks in advance,
G3
You've attached the "play" event handler directly to the button instead of using delegation. That handler will continue to fire because of that, even if you change the class.
Delegation works through event bubbling, and the selector you pass in to the .on() call is re-examined with every event. That is not the case with handlers that are directly attached: once those are active, they're active until they're removed or until the DOM element itself is removed. Changing the particulars of the DOM element won't make a difference.
Your problem can therefore be solved by using delegation for both cases.
Your code is close. but your first event handler also needs to be delegated too:
$(document).on('click', '.play-video', click(function(){
try to stop immediage propagation $('.play-video').click
The problem is that jQuery can't track object changes on the fly. Just use one click event, and determine what to do inside this:
$('.play-stop-video').click(function(){
if($(this).hasClass('play')) {
// Current play button code here....
}
if($(this).hasClass('stop')) {
// Current stop button code here....
}
$(this).toggleClass('play').toggleClass('stop');
});
$(something).click( ... will runs when the page loads, and attach the click events to the play and stop buttons. However, you don't have any stop buttons at this time, so the click event for this will be discarded...

window tab pressed event

I want my html5 canvas game to automatically pause when the user opens up another tab inside the browser. What is the name of the event that is fired when a user does this?
$(window).blur( function() {
});
or in js:
window.onblur = function() {
}
There is no "new tab opened" event. But pausing on the blur event will do what you want - whenever the window loses focus the game will pause. You can then resume game in the focus event.
As an alternative to the blur event suggested in another answer, you could use the new window.hidden property of HTML5.
Good places to read up on this are:
https://developer.mozilla.org/en-US/docs/DOM/Using_the_Page_Visibility_API
http://www.html5rocks.com/en/tutorials/pagevisibility/intro/
The biggest problem using this specification today is that you'll have to cater for vendor prefixes to handle it in all browsers. But if you ignore that it really comes down to:
if (!window.hidden) {
// do whatever you normally do to render a frame
}
There are corresponding visibilitychange events in case you'd prefer to keep the detection out of your game loop.

How do I prevent touchend event from apparently being "remembered" by the browser and firing subsequently at inappropriate times?

EDIT
Based on the number of views and the complete lack of responses I have to assume that I did a poor job of communicating my issue. I'm going to try to rectify that now.
I extended the HTMLElement prototype with a new tap method like so:
HTMLElement.prototype.tap = function (func) {
this.addEventListener("touchend", func, false);
};
I also created a custom tap event in jQuery:
$(document).delegate("*", "touchend", function (e) {
$(this).trigger("tap");
});
I also created a jQuery plugin called tap:
$.fn.tap = function (func) {
this.bind("tap", func);
};
If I try to use any of these with a callback function that includes an alert statement the callback executes twice. I tap the element to pop up the alert. I tap the "OK" button in the alert to close it. The next time I tap the screen no matter how long I wait the alert pops up again. This time tapping the "OK" button doesn't seem to set up another repeat.
However if the callback function doesn't include an alert statement (e.g. I use a console.log statement instead) the callback only executes the one time.
Does anyone know a way to deal with this? I'm about to try unhooking the event handler from within itself and then rebinding it afterwards, but that's nothing more than a hack if it's even successful.
I'd rather do things the "right" way. :-)
ORIGINAL
I just finished writing a "tap" function that I can use by extending the HTMLElement or Element prototypes as well as a custom "tap" event and "tap" plugin both for jQuery. I thought I had this in the bag until I decided to use a simple alert statement as test code.
When I use these with some element on my test page, they fire properly when I first "tap" the element, but the problem arises after I touch the alert's "OK" button and then, any amount of time later, tap the screen again at which point the event handler fires a second time.
At first I thought it was my custom code, but when I tried it with the following very basic JavaScript I was able to replicate the exact same issue.
document.getElementById("some-element").ontouchend = function (e) {
alert("Howdy doody!");
};
I imagine it must have something to do with the fact that I have to touch the screen again to execute the "OK" on the alert while still technically "inside" the event handler (since the alert is in effect "blocking" the completion of the handler function).
The fact that the behavior isn't replicated with the following slightly different code seems to support my imagination. :-)
document.getElementById("some-element").ontouchend = function (e) {
console.log("Howdy doody!");
};
If I include the above code in a page and touch that element after the callback fires I won't get a repeated firing of that callback function as opposed to the previous block of code where I'll see the alert pop up a second time the next time I tap the screen after hitting "OK" no matter where on the page I tap.
A strange issue indeed, and I haven't been able to find any information about why this might be happening. Does anyone have an idea what is happening?
I believe the visual, full-page alert being triggered on touch end is interfering with the touch event cycle. Try to call the alert after yielding to the DOM. eg.
setTimeout(function() {
alert('btn clicked');
}, 0);

Categories

Resources