0

I have a custom volume bar and mute button in my music player. Muting is very simple, but I want to return the previous volume when the button is clicked for the second time.

Example: Let's say the current volume is at 50%. Clicking the mute button will change it to 0. Clicking it again should get it back to 50%.

This is how I tried it:

var music = document.getElementById('music');
var volumehead = document.getElementById('volume-head');
var volumebar = document.getElementById('volume-bar');
var mute = document.getElementById('mute');

mute.addEventListener("click", muteSound);

function muteSound(){
    if(mute.classList.contains('not-muted')){
        // Save current values before changing them
        var lastHead = volumehead.style.marginLeft;
        var lastVolume = music.volume;

        // Change classname for appearance and next click
        mute.className = "muted";

        // Change values to 0
        volumehead.style.marginLeft = "0px";
        music.volume = 0;
    } else {
        // Change classname for appearance and next click
        mute.className = "not-muted";

        // Use saved values
        volumehead.style.marginLeft = lastHead;
        music.volume = lastVolume;
    }
}

The 2 variables that hold the position of the handler and the volume are given a value within the if-statement, meaning they don't have one in the else-statement.

Declaring them outside of the statements means that the values will be "overwritten" by 0.

Is there a way to save the values and use them for the next click on the button?


Edit (solution): The values that the if-statement assigned to the variables, could only be used by the else-statement if the variables were declared outside of the function.

5
  • 1
    The 2 variables that hold the position of the handler and the volume are declared within the if-statement, meaning they're not accessible in the else-statement - This is not true when using var, they're hoisted to the top of the function. A variable is only scoped to a statement block when using let or const. Anyway, the solution to your issue is to declare the variables outside of the function Commented Aug 2, 2017 at 14:57
  • You need to save the volume in a variable outside the function muteSound, i.e. together where all your other volumebar variables etc. are. Conceptually: you should attach an event handler to the volumebar which updates that volume variable every time it's moved; so volume always contains the currently chosen volume. When mute is clicked you mute the volume and render your UI to indicate a muted volume; you do not change the value of volume. When unmuting you restore the volume and update the UI again. Commented Aug 2, 2017 at 14:59
  • @MikaelLennholm When I console.log the variables both in the if- and else-statements, the ones in the else-statement return undefined. Commented Aug 2, 2017 at 15:31
  • @PeterPrakker Yes, they are never assigned a value, that happens in the if-block. But they ARE declared, thanks to hoisting, otherwise it wouldn't log undefined, it would throw a ReferenceError saying lastHead is not defined. You can see the difference for yourself by changing var to let. Commented Aug 2, 2017 at 15:35
  • @MikaelLennholm Ah, you're right. I edited my statement in the question. Thanks for the explanation! Commented Aug 2, 2017 at 15:41

4 Answers 4

1
var music = document.getElementById('music');
var volumehead = document.getElementById('volume-head');
var volumebar = document.getElementById('volume-bar');
var mute = document.getElementById('mute');

var lastHead, lastVolume;

mute.addEventListener("click", muteSound);

function muteSound() {
    if (mute.classList.contains('not-muted')) {
        // Save current values before changing them
        lastHead = volumehead.style.marginLeft;
        lastVolume = music.volume;

        // Change classname for appearance and next click
        mute.className = "muted";

        // Change values to 0
        volumehead.style.marginLeft = "0px";
        music.volume = 0;
    } else {
        // Change classname for appearance and next click
        mute.className = "not-muted";

        // Use saved values
        volumehead.style.marginLeft = lastHead;
        music.volume = lastVolume;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
1
mute.addEventListener("click", muteSound);
var lastHead = "10px";
var lastVolume = 10;

function muteSound(){
if(mute.classList.contains('not-muted')){
    // Save current values before changing them
    lastHead = volumehead.style.marginLeft;
    lastVolume = music.volume;

    // Change classname for appearance and next click
    mute.className = "muted";

    // Change values to 0
    volumehead.style.marginLeft = "0px";
    music.volume = 0;
} else {
    // Change classname for appearance and next click
    mute.className = "not-muted";

    // Use saved values
    volumehead.style.marginLeft = lastHead;
    music.volume = lastVolume;
}
}

Comments

1

You could use an IIFE (immediately-invoked function expression) with a closure over lastHead and lastVolume;

var muteSound = function () {
    var lastHead, lastVolume;

    return function () {
        if (mute.classList.contains('not-muted')) {
            // Save current values before changing them
            lastHead = volumehead.style.marginLeft;
            lastVolume = music.volume;

            // Change classname for appearance and next click
            mute.className = "muted";

            // Change values to 0
            volumehead.style.marginLeft = "0px";
            music.volume = 0;
        } else {
            // Change classname for appearance and next click
            mute.className = "not-muted";

            // Use saved values
            volumehead.style.marginLeft = lastHead;
            music.volume = lastVolume;
        }
    };
}();

mute.addEventListener("click", muteSound);

1 Comment

@deceze will making the function 'static' solve this problem?
0

Set a global variable outside of your loop and assign it to the volume before it gets set to 0. Then reference that variable in your else statement!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.