I'm trying to create a checkbox ($('#button')) the action of which changes depending on the state of player (whether the audio is playing or not) using Tone.js and jQuery.
So, the logic is that if the audio is already started, then the action of the checkbox is simply to mute (or unmute) the audio. However, if the audio is not already started then I want the checkbox to start player (with the default player.mute == false) and change its own action to mute/unmuting. This will mean that, once the player.state == started you cannot change it , only toggle whether it is muted or not.
I've managed to get a function together that toggles the state or the mute value, but not one where the action of the checkbox itself is conditioned by the state. The code I have below is my attempt at this but it doesn't seem to work âšī¸ â any help would be really appreciated.
const button = $('#button');
if(player.state == 'started') {
$(button).attr('checked', true);
} else if(player.state == 'stopped') {
$(button).attr('checked', false);
}
if(player.state == 'started') {
$(button).change(function(){
if(player.mute == true) {
player.mute == false;
$(this).attr('checked', true);
} else if(player.mute == false) {
player.mute == true;
$(this).attr('checked', false);
}
});
} else if(player.state == 'stopped') {
$(button).change(function(){
player.start();
$(this).attr('checked', true);
});
}
Just for context: This is all because whether autoplay is allowed or not varies between browsers. In some an autoplay function I have earlier in the script means that the player begins on the page load (đđŧ), in others an explicit user action is required (đđŧ).
What i understood is, the desired behavior is as follows:-
Whenever the player.state === 'started'
Clicking on the button should mute the audio and again clicking on it should unmute the audio. and keep on toggling till the player.state === 'started'
If player.state === 'stopped', clicking on button should start the audio and then keepo toggling the mute/unmute till the player is in started state.
Below is the implementation of the same.
const button = $('#button');
//First set the button state to checked on unchecked depending on state
if(player.state == 'started') {
button.attr('checked', true); //this means now the player is playing musing and is unmute.
} else if(player.state == 'stopped') {
button.attr('checked', false); //this means now the player is stopped and is also mute
}
button.change(function(){
if(player.state === 'started') {
if(player.mute) {
player.mute = false;
button.attr('checked', false);
} else {
player.mute = true;
$(this).attr('checked', true);
}
} else if (player.state === 'stopped') { //button was clicked and player is in stopped state. so start the player and turn on the checkbox so it displays that it is playing and is unmute
player.start();
button.attr('checked', true);
}
});
//with this implementation, on checkbox implies unmute and started state.
//off checkbox implies stopped or started+mute state.
Related
I am trying to save to local storage the state of both a checkbox (checked/unchecked) and audio (play/pause). The default state of the checkbox is checked and audio is playing (looping) as seen in the code below.
So if the checkbox is checked, audio is playing and both should be saved to local storage (checkbox checked and audio playing).
Else if the checkbox is unchecked, audio is paused and both should be saved to local storage (checkbox unchecked and audio paused).
The problem I have is with saving the state of the checkbox and audio after it's been checked again.
Steps in reproducing the issue:
1) uncheck checkbox > audio stops > refresh browser > works
2) check checkbox > audio playing > refresh browser > not working, checkbox unchecked and audio not playing
Here is the javascript:
if (window.localStorage.getItem("musicState") != null) {
var music = window.localStorage.getItem("musicState");
if (music == "true") {
status = 'pause';
$("audio").trigger(status);
}
else {
status = 'pause';
$("audio").trigger(status);
$("input:checkbox[name='music']").removeAttr("checked");
}
}
$("input:checkbox[name='music']").click(function () {
var visMusic = "play";
if (status == 'pause') {
status = 'play';
} else {
status = 'pause';
}
$("audio").trigger(status);
window.localStorage.setItem("musicState", visMusic)
});
here is the HTML:
<audio autoplay loop>
<source src="audio/music.mp3" type="audio/mpeg">
</audio>
<label><input type="checkbox" name="music" checked></label>
In your checkbox's click callback you are setting visMusic as "play". You never update it before storing it in localStorage as "musicState". This means that no matter what you do, "musicState" is always going to equal "play".
In your if-statement at the top (where you are retrieving from localStorage) you are testing if what you stored is "true". It is not, and never will be, because it is always "play". Your code is always going to your else which pauses the music and unchecks the box.
Here is an updated version that should work:
if (window.localStorage.getItem("musicState") != null) {
var music = window.localStorage.getItem("musicState");
if (music == "true") {
status = 'play';
$("audio").trigger(status);
}
else {
status = 'pause';
$("audio").trigger(status);
$("input:checkbox[name='music']").removeAttr("checked");
}
}
$("input:checkbox[name='music']").click(function () {
var visMusic = "false";
if (status == 'pause') {
status = 'play';
visMusic = "true";
} else {
status = 'pause';
}
$("audio").trigger(status);
window.localStorage.setItem("musicState", visMusic)
});
I'm using flickity, which is a bit irrelevant, and on first load and for each 'change' of a slide I'll search the slide for any videos that have audio enabled (set as a data attribute via PHP via CMS) and then it'll autoplay the video and if the user clicks an unmute button then it'll unmute and vice versa.
This worked fine going forward but going back once the mute button is clicked, the eventListener for the click will fire every time it's existed. I'm guessing the eventListener is being added to each time but I can't work out how to remove the eventListener.
Any help on how to prevent the muteButton.addEventListener('click') from being fired more than once?
//
playVideo = function(index) {
var videos, video, muteButton = null, hasAudio = false;
// Pause all other slide video content if it was playing
flkty.cells.forEach(function(cell, i) {
videos = cell.element.querySelectorAll('video.--autoplay');
videos.forEach(function(video) {
if (video !== null && typeof video !== 'undefined') {
if (!video.paused) {
video.pause();
}
}
});
});
// For current slide
if (index == flkty.selectedIndex) {
videos = flkty.selectedElement.querySelectorAll('video.--autoplay');
muteButton = flkty.selectedElement.querySelector('a.button__mute');
// If videos exist on the current slide
if (videos.length) {
videos.forEach(function(video, index) {
if (video !== null && typeof video !== 'undefined') {
video.play();
if (muteButton !== null && typeof muteButton !== 'undefined' && index == 0) { // Only fire this once per video (as mute = mute all)
console.log(muteButton);
muteButton.addEventListener('click', function(e) {
e.preventDefault();
console.log('clicked'); // TOFIX; fires multiple times
muteVideo(videos, video, muteButton, true);
});
}
}
return;
});
}
}
};
flkty.on('select', function(event, index) {
if (index === 0) {
playVideo(index);
return false;
}
});
flkty.on('change', function(index) {
playVideo(index);
});
//
muteVideo = function(videos, video, muteButton, hasAudio) {
console.log('hasAudio');
if (videos.length > 1) {
videos.forEach(function(video, index) {
if (video.muted == true) {
video.muted = false;
if (index == 0) {
$(muteButton).text('mute');
}
} else {
video.muted = true;
if (index == 0) {
$(muteButton).text('unmute');
}
}
});
} else {
if (video.muted == true) {
$(muteButton).text('mute');
video.muted = false;
} else {
$(muteButton).text('unmute');
video.muted = true;
}
}
};
Just use removeEventListener().
To remove event handlers, the function specified with the addEventListener() method must be an external function.
Anonymous functions, like yours, will not work.
As for only attaching it once: Just set a flag to be checked before adding the eventhandler in the first place.
Don't use removeEventListener() in this case. The real problem is that you are adding event listeners each time your playVideo() function is called. So the problem you should solve is to make sure you only add the event listeners once, probably when the page initializes or something.
Here is what I would do:
Extract the "add event listener code" into a separate function, addButtonListeners() by removing that piece of code from the playVideo(). Then call the addButtonListeners() once when your page is loaded.
My code partially works. When I click play it changes to paused, but when I click pause right after it just stays as pause and doesn't change back to play?
var playOrPause = function (id, button) {
var pp = document.getElementById(id);
if(pp.paused) {
button.textContent = 'Play';
} else if(!pp.paused) {
button.textContent = 'Pause';
}
};
I just figured out my problem. I coded one of my event listeners wrong lol Thank you guys for the help!!
$('.player_audio').click(function() {if (this.paused == false) { this.pause();
alert('music paused'); } else { this.play();alert('music playing');}});
This will help you
I am trying to figure out how when the page loads the game is "paused" and the user has to hit enter to play and when the user does so the game starts.
Here are the current keystates to control the player when the game is active. I feel like I'm almost there (correct me if I'm wrong), but I just can't get what makes the canvas "pause" when the page is loaded and how to make it "play" when the enter button is pushed.
keystate = {};
document.addEventListener('enter', function(evt){
keystate[evt.keyCode] = true;
});
document.addEventListener('keydown', function(evt){
keystate[evt.keyCode] = true;
});
document.addEventListener('keyup', function(evt){
delete keystate[evt.keyCode];
});
I have two ways,
One simple, but not so nice
One hard, can be nice
The first ay is just alerting something with comfirm(text).
Here is the code for that way :
var gameBrightness = 10;
function pause() {
var pause = confirm("You paused the game, click 'OK' to continue your game and the other button to go to options");
if (pause == false) { //Didn't click on OK
var options = confirm("Click on 'Ok' to not change brigthness, but the other one to change the brightness to a random value");
if (options == true) { //Clicked on OK
ReDopause();
return;
}
else { //Didn't click on OK
brightness = Math.floor(Math.random() * 20);
document.getElementById("brightness").innerHTML = brightness;
ReDopause();
return;
}
}
}
var ReDopause = function() {
pause();
}
<button onclick="pause()">Pause</button>
<span id="brightness">brigthness : 10</span>
The second way I havn't made but it is in each movements or timers add an if statment. Like this:
var pause = false;
setInerval(tick, 100);
function tick() {
if (pause == false) {
....
}
}
At the bginnning you should have a canvas which isn't visible which is the pause menu. Here gow you do the CSS for that:
#pause {
display: none;
...
}
When you pause set pause to true, set your main canvas to document.getElementById("mainCanvas").style.display = "none" this will make the canvas dissapear but still with all it's drawings. Then show the pause canvas like this : document.getElementById("mainCanvas").style.display = "initial". The when "Continue" is clicked: set pause to false and to the contrary of this.
My goal: Press and HOLD space key while an effect occurs (to simulate a fingerprint scan). If user releases key before effect finishes, I want to display a confirm message. The keydown part works fine and proceeds to function "process", but no error message is displayed on keyup if it is released before the effect finishes. This is what I have...
var active = false;
$(document).one("keydown", function(e) {
if ((e.keyCode == 32) && (active == false)) {
active = true;
$(".panel_1").slideDown(5000, function() {
active = false;
$(".panel_1").slideUp(2000, function() {process(); })
});
}
});
$(document).one("keyup",function(e) {
if ((e.keyCode == 32) && (active == true)) {
var r=confirm("Oops! You must HOLD down the space key until scan is complete. Press OK to try again, or Cancel to return to homepage.");
if (r==true) {
reset();
}
else {
window.location.replace("home.html");
}
}
});
Verify that you are releasing the key during the first slideDown animation. According to your code, once it starts to slide up your active gets set to false and then makes it so the keyup event will not trigger.
Also as a side note I'd recommend using triple = in JavaScript.
Your code seems to work here: http://jsfiddle.net/D52eq/ but note that the confirmation message occurs only if the space bar is released during the .slideDown() phase of the effect - you're setting active = false; before the .slideUp() call.
If you want the confirmation if the space bar is released before completion of the entire animation and process() call then try this:
$(document).one("keydown", function(e) {
if ((e.keyCode == 32) && (!active)) {
active = true;
$(".panel_1").slideDown(5000).slideUp(2000, function() {
process();
active = false;
})
}
});
Note that then you can just chain the .slideDown() and .slideUp(), you don't need to supply a callback function to .slideDown(). Also I've replaced active == false with !active.
Demo: http://jsfiddle.net/D52eq/1/