I know this is probably a very novice question but I can't seem to find the answer online anywhere and I can't see why this is happening. So, at the risk of getting downvoted... I was hoping to find an answer here.
I almost have my code to work as I want it to, but I do not want to be using any global variables. However, whenever I put this variable into any of my function, the code stops working..
I would greatly appreciate some insight. Sorry if this question has been asked a thousand times. They way that I understand global/local binding - this shouldn't be happening?
Here is my code with comments out wherever I tried to place the variable instead of at the top of the function.
Thanks in advance.
<body>
<div class="style" onclick="typeWriter()">
<p id="remove">Hide Me</p>
<p id="type"></p>
</div>
</body>
//Javascript
let letCounter = 0; //Do not want this as a global variable
function hideInitText() {
let hide = document.getElementById("remove");
hide.classList.add("hide");
//let letCounter = 0; //I tried here
}
hideInitText();
function typeWriter() {
//let letCounter = 0; //I tried here
let cycle, classCounter; //establish the cycle and counter
cycle = document.querySelectorAll("#type"); //cycle includes the .type class
for (classCounter = 0; classCounter < cycle.length; classCounter++) { //for loop that actually cycles
//let letCounter = 0; //I tried here
typeOut();
}
function typeOut() {
//let letCounter = 0; //I tried here
let speed = 50; //speed in milliseconds
let typewriter = "Type me out"; //document.querySelectorAll(".type");
if (letCounter < typewriter.length) {
//let letCounter = 0; //I tried here
//hide.classList.remove("hide"); //unhide the text
cycle[classCounter].innerHTML += typewriter.charAt(letCounter);
letCounter++;
setTimeout(typeWriter, speed);
}
}
};
One problem is
<div class="style" onclick="typeWriter()">
An inline handler will require either the referenced function to be global (or to be inside some with
scopes, which should not be used). You'll need to attach the event listener with Javascript instead.
document.querySelector('div').addEventListener('click', typeWriter);
If you want letCounter
to be scoped just to your script, you can put it (and everything else) inside an IIFE. That way, the scope of the letCounter
is constrained to your module, and isn't global:
(() => { let letCounter = 0; function hideInitText() { let hide = document.getElementById("remove"); hide.classList.add("hide"); } hideInitText(); function typeWriter() { let cycle, classCounter; //establish the cycle and counter cycle = document.querySelectorAll("#type"); //cycle includes the.type class for (classCounter = 0; classCounter < cycle.length; classCounter++) { //for loop that actually cycles typeOut(); } function typeOut() { let speed = 50; //speed in milliseconds let typewriter = "Type me out"; //document.querySelectorAll(".type"); if (letCounter < typewriter.length) { //hide.classList.remove("hide"); //unhide the text cycle[classCounter].innerHTML += typewriter.charAt(letCounter); letCounter++; setTimeout(typeWriter, speed); } } } document.querySelector('div').addEventListener('click', typeWriter); })();
<div class="style"> <p id="remove">Hide Me</p> <p id="type"></p> </div>
It looks like the letCounter
variable is only being used inside the typeWriter
function, so you could go further and scope letCounter
to only inside that function. (It's usually a good idea to constrain variable scope as much as possible, after all)
(() => { function hideInitText() { let hide = document.getElementById("remove"); hide.classList.add("hide"); } hideInitText(); const typeWriter = (() => { let letCounter = 0; return () => { let cycle, classCounter; //establish the cycle and counter cycle = document.querySelectorAll("#type"); //cycle includes the.type class for (classCounter = 0; classCounter < cycle.length; classCounter++) { //for loop that actually cycles typeOut(); } function typeOut() { let speed = 50; //speed in milliseconds let typewriter = "Type me out"; //document.querySelectorAll(".type"); if (letCounter < typewriter.length) { //hide.classList.remove("hide"); //unhide the text cycle[classCounter].innerHTML += typewriter.charAt(letCounter); letCounter++; setTimeout(typeWriter, speed); } } }; })(); document.querySelector('div').addEventListener('click', typeWriter); })();
<div class="style"> <p id="remove">Hide Me</p> <p id="type"></p> </div>
Functions need a global variable for the scenario you're doing where you want to increment the value each time.
The more complicated solution to this is change an attribute called “value” in your html and read it and set it each time treating it like a global variable.
You can add the letCounter into the DOM like this
const element = document.getElementById('counter'); let letCounter = element.dataset.count;
<div id="counter" data-count="0"></div>
I dislike the use of onclick="" method calls so i prefer the use of on eventListener.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.