Power on/off button to control audio

hi,
in order to improve a project, i made this simple tester pen. My purpose is to enable/disable audio according to if the power in on/off.
So i created a power button that toggles a class=“power” onto an element.
Then, if the class value is “power” i play the audio buttons, else I want to disable the audio. I tried to set the muted attribute of

how can I accomplish the task?

https://codepen.io/ranran212/pen/QWpbzrm?editors=1111

I would suggest you rework your JS a little. Right now you are adding a click handler for the buttons every time you turn the power on. So if I keep toggling the power button over and over again there are going to be a ton of click handlers on the buttons, all doing the same thing, which is bad. You could solve this by removing the button click handler when you turn the power off, but I think that is unnecessary work. I think you just need to add the click handler for the buttons once (just like you are doing for the power button) by moving the button click handler code out of the power button click handler.

I think your approach of using a class to determine whether the power is on is fine. Now you just need the button click handler to check for this class to determine whether to play the sound.

hi and thanks for you reply , as you can imagine i am pretty new to coding, so I am aware of writing more (unnecessary) code to go through the “easy” way
However, you mean doing something like this?

<button onclick="myFunction()">Click me</button>

(in the html, of course) and then something like

const myFunction =()=>{
      alert("hi");
}

or 

function myFunction() {
    alert("hallo");
}

in the JS script?
Actually I tried but could not have the button do anything, when I clicked :frowning:

I’m not sure I understand how the code you just pasted relates to the issue you were asking about in the pen you linked to. I’ll try to explain again.

You only want the sounds to play when the power is on. You are defining a click handler for the buttons:

$(".button").click(function () {
  let x = $(this).children("audio");
  x.get(0).play();
});

So you will want to do a check in this function before the sound is played to verify that the power is actually on. You are toggling a class to represent the state of the power button, so you can check for that class and then only play the sound if that class exists. What might be even better is if you create a separate function that just checks if the power is on and then you can call that function, if it returns true then you play the sound, otherwise you don’t.

I see that you are attempting to use the muted attribute on the <audio> element. I haven’t used this attribute before so I’m not sure if it will work the way you want it to in all browsers. Using this method means that you have to update the state of a bunch of elements each time the power is toggled (the power button itself and all the audio elements). Instead, if you use my approach above then you only have to worry about the state of the power button.

My other point was that you are adding the button click handler every time you turn the power on. Instead, create this click handler outside of the power button click handler, then it will only be added once.

$("#power").click(function(){...});
$('.button').click(function(){...});

Here’s a short and easy tutorial for dealing with HTML <audio> using jQuery. I just copy/pasted their toggleMuteAudio function into your code and it worked fine (you don’t even have to check if the power is currently on or off):

Hello francesca.giammichel,

Take note of what bbsmooth said about having a click event being added to the .button when the #power is clicked.

If you want to go down the muting route.
For some reason adding the muted attribute via javascript does not have desired effect.

But it does work by changing the prop for the audio.
Works in chrome, you would have to test other browsers to ensure it works on them too.

$("audio").prop("muted",true);
$("audio").prop("muted",false);

can be set to true or false

Hope that helps out

ok, this is the solution I ended up with, and it eventually works :slight_smile:
Is that what you meant?

$(document).ready(function(){
  //toggle power
  $("#power").click(function(){
    $("#on").toggleClass("powered");  
   });
  
  //button click handler   
      $('.button').click(function(){
        
         if ($("#on").attr("class")=="powered") {
    let x = $(this).children("audio");    
    x.get(0).play();      
         }    
    });
  
  });   

just for my better understanding, if I had created a function to check if power was on, how should I have called it in the button clickhandling?

$(document).ready(function(){

      //toggle power
     $("#power").click(function(){
          $("#on").toggleClass("powered");  
      });
  
      //checking if power is on
        function isPowerOn () {
            return  ($("#on").attr("class")=="powered"; 
        }

      //button click handler   
      $('.button').click(function(){           

             //how i call the isPowerOn? 
             let x = $(this).children("audio");    
             x.get(0).play();      
        
      });
  
  });   

Last, i would beg you to clarify another issue I went through, i.e. the example i was not able to get explained properly. So far I have defined and used the clickhandlers as functions in jquery.
I have sometimes tried to have this clickhandler as attibute in the html, like

<button onclick="myFunction()">Click me</button>

then, of course, I defined the clickhandler function is the js script

const myFunc = () => { //code}

this works ONLY if the myFunc is defined OUTSIDE the $(document).ready(etc). If i place myFunc inside jQuery (i.e. inside the $(document).ready(etc), it is not recognized (when I press the button and I call the clickhandler, it says that myFunc is not defined). But if i place myFunc outside Jquery I cannot target child elements (audio, in this case)…should I then use DOM notation to achive this purpose?
I hope i got myself decently explained ^-^

Hello francesca.giammichel,

This is considered bad practice now-adays.

<button onclick="myFunction()">Click me</button>

myFunc Or myFunction??

In anycase this is due to scope - I wrote a little fiddle to explain it yesterday - let me find it

Made a simple fiddle to try and illustrate:
https://jsfiddle.net/192kguzb/

Here is link which might help out:

i actually followed bbsmooth advices and had it work :slight_smile: …or at least I hope my code was what he meant

but i will definitely take note of the information you kindly passed me . Yesterday i tried to do some search about the audio obj and tried to pass the get(0) attribute and setting “mute” prop to “false”, i.e.

  $("audio").get(0).play();

infact, i struggled also for play() method as I had to google and came to adding .get(0)

where can I find the documentation about that?

yes, my mistake about writing myFunction vs myFunc, sorry :stuck_out_tongue:

a part from being bad practice, if I had defined myFunc as var (as a globla variable) and outside jquery , would I have been able to access it?

thank you very much, this is very interesting, too :slight_smile:

About the .get(), it gets the dom element.
The following will get the same dom element

$(selector)[0];  //vanilla javascript probably faster
$(selector).get(0); //jquery

reference:

I’m not sure about when it is assign to a variable.
I would need to test that out, my coding styleI don’t usually set function to a variable.

But it would work if just a function, ensure global scope:

function myFunc(){
//code here
}

This sounds like an issue with hoisting. When you say that it only works if you move myFunc OUTSIDE of the document.ready callback, are you moving it above or below the rest of the code?

If you define a function like in the following examples, you can place it anywhere in your script. It’ll be available everywhere because it’s being hoisted:

function myFunc(){
    // available everywhere
}

var myFunc = function(){
    // available everywhere
}

var myFunc = () => {
    // available everywhere
}

If you define a function with let or const, it must be defined before you try to access it:

let myFunc = function(){
    // I won't be hoisted to the top
}

const myFunc = () => {
    // I won't be hoisted to the top
}
1 Like

just for my understanding (forgive me if i use improper words or definitions):
i have to consider the audio as an obj, asking for the value of its first key (the audio, i suppose)…
then , there is shoudl be a “muted” prop which is by default false but that i can set to true… i also found the .prop() method vs the .attr() method and that is very very interesting for something else I was planning ^-^
but where can i find the list of properties of the audio element?

google is your friend search

search for “html audio tag”

https://www.w3schools.com/tags/tag_audio.asp

search for “jquery attr vs prop”

yes, there is also a w3s page about .prop() vs .attr() and, for my present level, i often find stackoverflow still too difficult

about the audio, i came to the same page you proposed but, my bad, I didn t realize i had not scrolled to the end :stuck_out_tongue:

regarding the question about the <button onclick=“myFunc()” i tested and yes, it was a matter of hoisting…if a use var it works :slight_smile:

ok - its a long hard road - but the more you do - the easier it gets :slight_smile:

About prop - read this one.
https://api.jquery.com/prop/
read the bit about
Attributes vs. Properties

Happy coding

forgive me, i will abuse of your kindness for one more question, related to scope, since I am a issue on a new project (the JS calculator)
I have a bunch of id-ed button corresponding to the numbers and mathematical operator and when I click one, i have to store the number/operator in a variable.
I have written something like this, so far

$(document).ready(function(){
   let selected = "";
   let arr= [];
   let temp;
   let regex = /\*|\//;
   //clickhandler
   $("button").click(function(){
      selected=$(this).text();          
  })
     console.log(selected);
  
})

this way, the console.log prints nothing. I tried to use var(instead of let) when declaring selected, but I get errors. I also tried to declare it as var outside jquery (as a global variable with no scope/function) but again no results.
According to what I studied, var has no block scope, so it should be available, but outside the handleclick func i cannot get the value I assign to selected inside the handleclick :frowning: