I'm trying to add a class to a random button, but .addClass()
is not working and shows me an error, and when I tried to use Vanilla JS classList.add()
everything is working fine.
const button = $('.btn');
const sound = $('.audio');
const wrongSound = $('.audio-wrong');
let randomNumber = Math.floor(Math.random() * 4);
button.on('click', () => {
startGame();
});
const startGame = () => {
console.log(button);
console.log(randomNumber);
button[randomNumber].toggleClass("pressed");
}
Vanilla JS is working, but jQuery shows me an error.
CodePudding user response:
The toggleClass()
method is used to add or remove a class from an element, depending on whether or not the element already has that class. In your code, you are trying to use toggleClass()
on an element that is selected using an index, rather than a jQuery object.
To fix this issue, you can use the eq()
method to select the element at the specified index as a jQuery object, like this:
button.eq(randomNumber).toggleClass("pressed");
Alternatively, you can use the get()
method to get the element at the specified index as a DOM element, and then use the addClass()
method to add the class:
$(button.get(randomNumber)).addClass("pressed");
Either of these approaches should allow you to add the class to the desired element using jQuery.
CodePudding user response:
jQuery Object vs. Native DOM Object
One important thing to remember about jQuery is that a jQuery Object (ex.$(selectorString)
) is not a native DOM Object (ex. document.querySelector(selectorString)
). This means that jQuery methods and properties will not function with DOM Objects and the same applies to native DOM API methods and properties being incompatible with jQuery Objects. Also, jQuery Objects are collections of elements but are not arrays. As already pointed out in alisait's answer the following line is your culprit:
button[randomNumber].toggleClass("pressed");
This part: button[randomNumber]
is also this: $(".btn")[randomNumber]
. Any time the bracket notation is suffixed to a jQuery Object it becomes dereferenced into a DOM Object, hence .toggleClass()
failed. FYI, there is an alternative way to dereference a jQuery Object as well:
/* Dereferencing jQuery Object into a DOM Object */
$(selectorString)[index]
// OR
$(selectorString).get(index)
One more problem is that randomNumber
is outside of the calling function startGame()
and within a closure so the value of randomNumber
is consistently the same on every call of startGame()
. To get a different number on every call of startGame()
define randomNumber
within startGame()
.
/**
* Bind each .btn to the "click" event
* Convert jQuery Object $(".btn") into an array of .btn
* Generate a random number in the range of 0 to 3
* Get the .btn from the array at the index equal to the random number
* then change the .btn into a jQuery Object
* and toggle the .on and .off classes on the .btn
*/
$(".btn").on("click", function() {
const array = $(".btn").toArray();
let rIDX = Math.floor(Math.random() * array.length);
$(array[rIDX]).toggleClass("on off");
});
button {
display: inline-block;
min-width: 3rem;
font: inherit;
cursor: pointer;
}
.off::before {
content: "OFF";
}
.on::before {
content: "ON";
}
<button ></button>
<button ></button>
<button ></button>
<button ></button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>