Prevent subsequent firings after initial .mousedown() event with jQuery - javascript

Description of Problem (Fiddle):
Clicking the #test box multiple times creates layers of audio playing simultaneously and briefly pauses or staggers the .fadeOut() effect with each press. I want to prevent subsequent mousedown events from firing so that the .fadeOut() effect completes seamlessly and doesn't trigger additional audio plays.
Code:
$('#test').mousedown(function() {
var sound = new Audio("http://sounddogs.com/previews/3668/mp3/824357_SOUNDDOGS__ri.mp3");
sound.play();
$('#test').stop(true).fadeOut(2000);
});

This will fire an event a single time: http://api.jquery.com/one/

The easy way:
var clicked = 0;
$('#test').mousedown(function () {
if (clicked == 0) {
clicked = 1;
var sound = new Audio("http://sounddogs.com/previews/3668/mp3/824357_SOUNDDOGS__ri.mp3");
sound.play();
$('#test').stop(true).fadeOut(2000);
setTimeout(function(){clicked = 0;}, 2000);
}
});
http://jsfiddle.net/yxDSL/1/

$('#test').one('click',function() { //would only trigger on first click
var sound = new Audio("http://sounddogs.com/previews/3668/mp3/824357_SOUNDDOGS__ri.mp3");
sound.play();
$('#test').stop(true).fadeOut(2000);
$('#test').click(function(){ // for subsequent click write the function inside this
});
});

This'll do the trick...
$('#test').mousedown(function() {
var sound = new Audio("http://sounddogs.com/previews/3668/mp3/824357_SOUNDDOGS__ri.mp3");
sound.play();
$('#test').unbind("mousedown").stop(true).fadeOut(2000);`
});

Related

Can I trigger a function when a audio object begins to play?

I have an <audio> object that might need to load before it can play, is there a way to trigger a function when either the sound begins after downloading, or when the user clicks the play button?
There is a playing event you can listen to like so.
audio.addEventListener("playing", function() {
console.log("playing");
});
http://w3c.github.io/html/semantics-embedded-content.html#eventdef-media-playing
Yes, there is onplay event for audio and video, you should use <audio> tag to do it
var audio = document.getElementById("Your_audio");
audio.onplay = function() {
//your code
};
with the javascript audio object you can add some event listener, like :
var horn = new Audio('car_horn.wav');
horn.addEventListener('loadeddata', () => {
let duration = horn.duration;
// The duration variable now holds the duration (in seconds) of the audio clip
})
as you can see here : https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement
you can simply add an evenListner like this:
<audio|video onplay="myScript">
e.g. you can do like this:
var aud = document.getElementById("myAudio");
aud.onplay = function() {
alert("The audio has started to play");
};

Catching all audio end events from dynamic content in jquery

I have seen similar questions - but not that fix my problem!
I have audio on my page and when one ends, I want the next to start, but I can't even get the ended to trigger...
I cut the code down to this:
function DaisyChainAudio() {
$().on('ended', 'audio','' ,function () {
alert('done');
});
}
This is called from my page/code (and is executed, setting a break point shows that).
As far as I understand this should set the handler at the document level, so any 'ended' events from any 'audio' tag (even if added dynamically) should be trapped and show me that alert...
But it never fires.
edit
With some borrowing from Çağatay Gürtürk's suggestion so far have this...
function DaisyChainAudio() {
$(function () {
$('audio').on('ended', function (e) {
$(e.target).load();
var next = $(e.target).nextAll('audio');
if (!next.length) next = $(e.target).parent().nextAll().find('audio');
if (!next.length) next = $(e.target).parent().parent().nextAll().find('audio');
if (next.length) $(next[0]).trigger('play');
});
});
}
I'd still like to set this at the document level so I don't need to worry about adding it when dynamic elements are added...
The reason it does not fire is, media events( those specifically belonging to audio or video like play, pause, timeupdate, etc) do not get bubbled. you can find the explanation for that in the answer to this question.
So using their solution, I captured the ended event, and this would allow setting triggers for dynamically added audio elements.
$.createEventCapturing(['ended']); // add all the triggers for which you like to catch.
$('body').on('ended', 'audio', onEnded); // now this would work.
JSFiddle demo
the code for event capturing( taken from the other SO answer):
$.createEventCapturing = (function () {
var special = $.event.special;
return function (names) {
if (!document.addEventListener) {
return;
}
if (typeof names == 'string') {
names = [names];
}
$.each(names, function (i, name) {
var handler = function (e) {
e = $.event.fix(e);
return $.event.dispatch.call(this, e);
};
special[name] = special[name] || {};
if (special[name].setup || special[name].teardown) {
return;
}
$.extend(special[name], {
setup: function () {
this.addEventListener(name, handler, true);
},
teardown: function () {
this.removeEventListener(name, handler, true);
}
});
});
};
})();
Try this:
$('audio').on('ended', function (e) {
alert('done');
var endedTag=e.target; //this gives the ended audio, so you can find the next one and play it.
});
Note that when you create a new audio dynamically, you should assign the events. A quick and dirty solution would be:
function bindEvents(){
$('audio').off('ended').on('ended', function (e) {
alert('done');
var endedTag=e.target; //this gives the ended audio, so you can find the next one and play it.
});
}
and run bindEvents whenever you create/delete an audio element.

How can one <img> tag be used to execute 2 different js functions?

How can I set up one image, that when clicked changes to another image and then when clicked again reverts back to the original image while still carrying out functions independently. In my example I want a Play button that when pressed turns to a pause button. However I need to have both play and pause functionalities when the correct button is pressed. These work on do different buttons but I would like the one button to have all the functionality. I have tried a few things but everytime, one of the play/pause functions are not letting the other work.
$('#startSlider').click(function (){
if (document.getElementById("startSlider").src = "Play.png"){
document.getElementById("startSlider").src = "Pause.png";
scrollSlider();
}
else if (document.getElementById("startSlider").src != "Play.png"){
clearTimeout(tmOt);
document.getElementById("startSlider").src = "Play.png";
}
});
<img src="Play.png" id="startSlider"/>
problem is in your if block,
you are using = not ==
if (document.getElementById("startSlider").src = "Play.png"){// you are assigning here not comparing
you are assigning play.png every times when the click calls on the image.
you are using jquery then why are you not using this to make it more simple.
$('#startSlider').click(function (){
if (this.src == "play.png"){
this.src = "pause.png";
}else{
this.src = "play.png";
}
});
check this fiddle
I like using classes in these situations as it makes the code a little easier to follow:
$('#startSlider').click(function (){
$(this).toggleClass('pause')
if ( $(this).hasClass('pause') ) {
// Button is paused change to play
$(this).attr('src', 'Play.png')
// Pause function goes here
} else {
// Button is play change to pause
$(this).attr('src', 'Pause.png')
//play function goes here
}
})
You can do this with a little state machine. You keep the states inside an object, and handle the next state in the event listener of the button:
var states = {
_next: 'play',
next: function() {
return this[this._next]()
},
play: function() {
img.src = 'pause.jpg'
button.textContent = 'Pause'
this._next = 'pause'
},
pause: function() {
img.src = 'play.jpg'
button.textContent = 'Play'
this._next = 'play'
}
}
button.addEventListener('click', states.next.bind(states))
This is more of a general answer to your problem, that you'd have to adapt to your code.
DEMO: http://jsbin.com/moxoca/1/edit *
* The images might take a second to load.

What HTML5 video event refers to the currentTime of the video being played?

I want the user to have the option to skip the preroll ad after a specified time (say 5 secs into the ad). Then the normal video would play. How can I achieve this? Currently I have something inline of this:
var adManager = function () {
var adSrc = url,
src = "http://media.w3.org/2010/05/sintel/trailer.mp4";
var adEnded = function () {
videoPlayer.removeEventListener("ended", adEnded, false);
videoPlayer.removeEventListener("playing", adPlaying, false);
$("#companionad").hide();
videoPlayer.src = src;
videoPlayer.load();
videoPlayer.play();
console.log(videoPlayer.currentTime);
};
var adPlaying = function () {
var companionad = $(responseXML).find("HTMLResource").text();
$("#companionad").html(companionad);
console.log(videoPlayer.currentTime);
}
return {
init: function () {
videoPlayer.src = adSrc;
videoPlayer.load();
videoPlayer.addEventListener("ended", adEnded, false);
videoPlayer.addEventListener("playing", adPlaying, false);
if (videoPlayer.currentTime > 5) {
$("#skip").show();
}
console.log(videoPlayer.currentTime);
}
};
}();
adManager.init();
What I am trying to do is:
if (videoPlayer.currentTime > 5) {
$("#skip").show();
}
show the skip button and continue to normal video. Is there any event that is continually fired as the video play progresses?
Do your check against the media.currentTime property in a handler for the timeupdate event. See documentation:
The timeupdate event is fired when the time indicated by the
currentTime attribute has been updated.
Just as an aside, this HTML5 video demo page is a really handy reference for playing around with the various properties and events available to you.

Javascript Loop and Button

Hello wonderful web programmers. I need some help, and I believe there must be a simple answer.
The Goal
I need to be able to pause all Vimeo Videos on a WordPress webpage. I would really like it if I could just add a class "pause" to any tag (so I could use a div or anchor rather than just a button) and have that pause all playing videos.
The following code works if I have buttons, but it only works on the first video. Apparently I need to make a loop of some sort to have it work on all of the videos on a page:
The Code
<button class="simple">play</button> <button class="simple">pause</button>
<script>
//HERE IS THE SIMPLE CODE THAT WORKS
var f = $('iframe'),
url = f.attr('src').split('?')[0];
// postMessage
function post(action, value) {
var data = { method: action };
if (value) {
data.value = value;
}
f[0].contentWindow.postMessage(JSON.stringify(data), url);
}
// Play & Pause
$('button').click(function() {
post($(this).text());
});
if (window.addEventListener){
window.addEventListener('message', onMessageReceived, false);
} else { // IE
window.attachEvent('onmessage', onMessageReceived, false);
}
</script>
The Question
Where would the loop go? Also, what should I change so that another element can pause? Here is some other code where a class is used:
/**
* Sets up the actions for the buttons that will perform simple
* api calls to Froogaloop (play, pause, etc.). These api methods
* are actions performed on the player that take no parameters and
* return no values.
*/
function setupSimpleButtons() {
var buttons = container.querySelector('div .simple'),
playBtn = buttons.querySelector('.play'),
pauseBtn = buttons.querySelector('.pause'),
unloadBtn = buttons.querySelector('.unload');
// Call play when play button clicked
addEvent(playBtn, 'click', function() {
froogaloop.api('play');
}, false);
// Call pause when pause button clicked
addEvent(pauseBtn, 'click', function() {
froogaloop.api('pause');
}, false);
// Call unload when unload button clicked
addEvent(unloadBtn, 'click', function() {
froogaloop.api('unload');
}, false);
}
setupSimpleButtons();
setupEventListeners();

Categories

Resources