the teacher asked us to design a website to teach children letters, when I click the generate button, it generates letters in a random way, and when I click on a letter, an image of something that starts with this letter is displayed. The problem is when I click on another letter, it displays an image of something that starts with this letter, but The old image of the other letter is still present on the page and is not deleted. What I want is when I click on a letter it displays an image of something that begins with this letter and when I click on another letter I want it to delete the old image and display only the image that begins with this letter
this is my JS code
var div2 = document.getElementById("div2");
var div3 = document.getElementById("div3");
var generate = document.getElementById("generate");
var input = document.getElementById("input");
var letters = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
// here to add the path of the each img to array to store it becuase we will need it leter
litterImg = [];
for (let i = 0;i < 26;i++) {
litterImg[i] = 'img\\'+i+'.jpg';
};
var randomLetter = [];
var getRandomLetter = [];
var linkImg = [];
var numberOfLitters;
generate.addEventListener("click",function(e){
numberOfLitters = input.valueAsNumber;
for (let index = 0; index < numberOfLitters; index++) {
let x = randomNumbers();
randomLetter[index] = document.createElement("input");
randomLetter[index].setAttribute("type","button");
randomLetter[index].setAttribute("value",letters[x]);
randomLetter[index].setAttribute("id", x);
randomLetter[index].setAttribute("class",x);
div2.appendChild(randomLetter[index]);
}});
// event to add the images when i click on a litter
div2.addEventListener("click",function(e){
for (let index = 0; index < 26; index++) {
if (e.target.id == index) {
linkImg[index] = document.createElement("img");
linkImg[index].setAttribute("src",litterImg[index]);
linkImg[index].setAttribute("width","1080px");
linkImg[index].setAttribute("height","720px");
div3.appendChild(linkImg[index]);
}
}
});
and this is my html code
<html>
<head>
<meta>
<title>Alphabet Learner</title>
</head>
<body>
<div id="div" class="div" style="text-align : center;">
<h1>Learn the English Litters </h1><br>
<label >Number of Litters: </label>
<input type="number" class="input" id="input" >
<input type="button" class="generate" id="generate" value="Generate">
<br><br>
<div id="div2" class="div2">
</div><br>
<div id="div3" class="div3"></div>
</div>
<script src="script.js"></script>
</body>
</html>
I have changed the script a bit more than it was needed, sorry for that. Anyway, it works!
The main part was to add the removal of element before the addition of a new one.
const generate = document.getElementById("generate");
const input = document.getElementById("input");
const div2 = document.getElementById("div2");
const div3 = document.getElementById("div3");
const letters = [
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
];
// here to add the path of the each img to array to store it becuase we will need it leter
const letterImg = [];
for (let i = 0; i < 26; i++) {
letterImg[i] = "img\\" + i + ".jpg";
}
generate.addEventListener("click", function () {
const numberOfLetters = input.valueAsNumber;
for (let i = 0; i < numberOfLetters; i++) {
const x = randomNumber();
const randomLetter = document.createElement("input");
randomLetter.setAttribute("type", "button");
randomLetter.setAttribute("value", letters[x]);
randomLetter.setAttribute("id", x);
randomLetter.setAttribute("class", x);
div2.appendChild(randomLetter);
}
});
function randomNumber() {
return Math.floor(Math.random() * 26);
}
// event to add the images when i click on a litter
div2.addEventListener("click", function (e) {
const index = e.target.id;
const linkImg = document.createElement("img");
linkImg.setAttribute("src", letterImg[index]);
linkImg.setAttribute("width", "1080px");
linkImg.setAttribute("height", "720px");
// remove old image
const old = document.querySelector('#div3 img');
old && old.remove();
// add new image
div3.appendChild(linkImg);
});
<body>
<div id="div" class="div" style="text-align: center;">
<h1>Learn the English Letters </h1><br>
<label>Number of Letters: </label>
<input type="number" class="input" id="input">
<input type="button" class="generate" id="generate" value="Generate">
<br><br>
<div id="div2" class="div2"></div>
<br>
<div id="div3" class="div3"></div>
</div>
</body>
Related
var draftloc = { ans: ["a", "b", "c"] };
for (var i = 0; i < draftloc.ans["length"]; i++) {
//draftloc.length === draftloc["length"]
console.log("draftloc for loop works");
//rcnounk is a element(div)
rcnounk.innerHTML += `<div class="ml-negative-20 mt-9">
<div class="ui check checkbox">
<input type="checkbox" name="example">
<label>${draftloc.ans[i]}</label>
</div>
</div>`;
}
for loop is working everything is defined but inner html not working
You need to get the DIV-elem from rcnounk.
rcnounk=document.getElementById('rcnounk');
With this it seems to work.
var draftloc = { ans: ["a", "b", "c"] };
for (var i = 0; i < draftloc.ans["length"]; i++) {
//draftloc.length === draftloc["length"]
console.log("draftloc for loop works");
rcnounk=document.getElementById('rcnounk');
//rcnounk is a element(div)
rcnounk.innerHTML += `<div class="ml-negative-20 mt-9">
<div class="ui check checkbox">
<input type="checkbox" name="example">
<label>${draftloc.ans[i]}</label>
</div>
</div>`;
}
<div id='rcnounk'>RC</div>
The idea is to make a OTP(one time pad) encoder and later also a decoder. This is the implementation - two input boxes. One contains key and one a message. There is also a box which displays "OTPencrypt". If you click on the OTP button it does the function called initialize and displays the result in the output box. I don't know how to make the OTPencrypt button and output box "connected".
My code in HTML:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input type="text" name="Input" value="Sisend">
</body>
<script type = "text/javascript">
function initialaize() {
var message = document.getElementById("Input").value;
var key = document.getElementById("Key").value;
var end_message = "";
var chipertext = "";
var alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
var alphamap = new Map();
for (i = 0; i < alphabet.lenght, i++) {
alphamap.set(alphabet[i], i);
}
for (a = 0; i < key.lenght; i++) {
var value_original = alphamap.get(message[a]) ;
var value_key = alphamap.get(key[a]);
var value = getByValue(alphamap, ((value_original + value_key) % 26));
chipertext += value;
}
function getByValue(map, searchValue) {
for (let [key, value] of map.entries()) {
if (value === searchValue) {
return key;
}
}
}
return chipertext;
}
</script>
<body>
<input type="text" name="Key" value="Key(kui vaja)">
</body>
<body>
<button id="OTPencrypt">OTPencrypt</button>
</body>
<body>
<input type="text" name="result" value=result readonly="true">
</body>
</html>
I want the result to display the initialaize result if OTPencrypt is pressed. How do i go about this?
You must add an onClick event listener to the #OTPencrypt button, to set the textbox's value to the output of your function
Add the following to the JS code:
document.getElementById("OTPencrypt").addEventListener("click",()=>{
document.getElementsByName("result")[0].value=initialaize()
})
You need to add an event listener to the button and tell it to run initialize when it's been clicked, this is how your code would look like..
run the snippet and see the results
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<input id="Input" type="text" name="Input" value="sisend">
<input id="Key" type="text" name="Key" value="kuiva">
<button id="OTPencrypt">OTPencrypt</button>
<input type="text" id="result" name="result" placeholder=result readonly="true">
<script type="text/javascript">
document.getElementById('OTPencrypt').addEventListener('click', () => {
document.getElementById('result').value = initialaize();
});
function initialaize() {
var message = document.getElementById("Input").value;
var key = document.getElementById("Key").value;
var end_message = "";
var chipertext = "";
var alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
var alphamap = new Map();
for (var i = 0; i < alphabet.length; i++) {
alphamap.set(alphabet[i], i);
}
for (var a = 0; a < key.length; a++) {
var value_original = alphamap.get(message[a]);
var value_key = alphamap.get(key[a]);
var value = getByValue(alphamap, ((value_original + value_key) % 26));
chipertext += value;
}
return chipertext;
}
function getByValue(map, searchValue) {
for (let [key, value] of map.entries()) {
if (value === searchValue) {
return key;
}
}
}
</script>
</body>
</html>
Please Note that you need to twerk some of the logic in the function to cover every input possibility..
hope that helps.
I've been trying to debug my JS program but I am unable to remedy the issue. I have tracked down the location of the bug. Two of my variables are not getting the input from an HTML form. I have checked the syntax and tried everything I can think of. When I console.log my input variables they are an empty string. When I hard code the input into the program it works as intended. The issue seems to be grabbing the input from the HTML document.
Heres my HTML Markup:
<form>
<label for="message">Enter Your Message to be Encrypted:</label>
<input type="text" name="message" id="msg">
<label for="key">Enter Your Encryption Key:</label>
<input type="text" name="key" placeholder="Value Between 1-26" id="encrypt-key">
<button type="button">Encrypt</button>
</form>
Heres my JS code:
(function(){
let aplhabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
let msg = document.getElementById('msg').value;
let encryptKey = document.getElementById('encrypt-key').value;
//let msg = "ab ab";
//let encryptKey = "1";
let msgArray = msg.split(' ');
let encryptedMsgArr = [];
function encryptWord() {
msgArray.forEach(word => {
let i;
let array = [];
for (i = 0; i < word.length; i++) {
var encryptedLetter;
let letter = word.charAt(i);
let aplhabetNum = aplhabet.indexOf(letter);
let e = aplhabetNum + parseInt(encryptKey);
if ( e > 25) {
e = e - 25;
encryptedLetter = aplhabet[e];
} else {
encryptedLetter = aplhabet[e];
}
array.push(encryptedLetter);
}
let newWord = array.join('');
encryptedMsgArr.push(newWord);
});
let encryptedMsg = encryptedMsgArr.join(' ');
console.log(msg);
alert(`The encrypted message is "${encryptedMsg}" and the decryption key is ${encryptKey}.`)
}
document.querySelector('button').addEventListener('click', encryptWord);
})()
Thanks in advance for you guys help!
That is because you are assigning the values for the variables msg, encryptKey, and msgArray outside the function. This means that their values are assigned at runtime (when your IIFE is evaluated) and not when the button is clicked.
Simply move these three let declarations/assignment into the function itself and your problem is solved:
(function() {
let aplhabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"];
let encryptedMsgArr = [];
function encryptWord() {
// These three variables have been moved into the function
let msg = document.getElementById('msg').value;
let msgArray = msg.split(' ');
let encryptKey = document.getElementById('encrypt-key').value;
msgArray.forEach(word => {
let i;
let array = [];
for (i = 0; i < word.length; i++) {
var encryptedLetter;
let letter = word.charAt(i);
let aplhabetNum = aplhabet.indexOf(letter);
let e = aplhabetNum + parseInt(encryptKey);
if (e > 25) {
e = e - 25;
encryptedLetter = aplhabet[e];
} else {
encryptedLetter = aplhabet[e];
}
array.push(encryptedLetter);
}
let newWord = array.join('');
encryptedMsgArr.push(newWord);
});
let encryptedMsg = encryptedMsgArr.join(' ');
console.log(msg);
console.log(`The encrypted message is "${encryptedMsg}" and the decryption key is ${encryptKey}.`)
}
document.querySelector('button').addEventListener('click', encryptWord);
})()
<form>
<label for="message">Enter Your Message to be Encrypted:</label>
<input type="text" name="message" id="msg">
<label for="key">Enter Your Encryption Key:</label>
<input type="text" name="key" placeholder="Value Between 1-26" id="encrypt-key">
<button type="button">Encrypt</button>
</form>
I have a code, in which I try to achieve needed string("Hey!") by randomizing characters (brute-forcing the string), and to display all steps in a <p>(next step overwrites previous one). The problem is, however, that in the #first, there is only displayed the final step of permutations ("Hey!").
Why doesn't it displays all steps one after one, only the last one? I will appreciate any help on that problem.
Note: in the console, all steps are logged. I also tried outputting string in <p> with timeout; nothing changed.
Example of what has to be: https://i.imgur.com/fNjhjUS.gif
Here's my Javascript code and HTML:
var fline = ["H", "e", "y", "!"];
temp_fline = [" ", " ", " ", " "],
index = 0,
possible = "!abc!defghijklmnopqrstuvwxyz!ABCDEFGHIJKLMNOPQRSTUVWXYZ!";
while (index < 4)
{
if (fline[index] != temp_fline[index])
temp_fline[index] = possible[Math.round(Math.random() * 57)];
if (fline[index] == temp_fline[index])
++index;
var tempString = "";
for (var i = 0; i < 4; ++i)
tempString += temp_fline[i];
console.log(tempString);
document.getElementById("fline").innerHTML = '> ' + tempString;
}
<html>
<body>
<div id="first">
<br>
<p id="fline"></p>
<br><br><br>
<p id="sline"></p>
<br><br><br>
<p id="tline"></p>
<br><br><br>
<p id="fhline"></p>
</div>
</body>
</html>
Want like that?
var fline = ["L", "i", "k", "e", " ", "t", "h", "i", "s", "?"], count = 0, index = 0, flist = [],
possible = "!abc!?defghijklmnopqrstuvwxyz!ABCDEFGHIJKLMNOPQRSTUVWXYZ! ";
let found = document.getElementById("found");
let checking = document.getElementById("checking");
let timer = setInterval(function ()
{
if (index >= fline.length)
{
console.log(flist);
clearInterval(timer);
checking.innerText = "";
flist = [];
}
else
{
if (fline[index] == possible[count])
{
found.innerText += possible[count];
flist.push(possible[count]);
index++; count = 0;
}
else
{
checking.innerText = possible[count];
count++;
}
}
}, 24);
<div><b id="found"></b><i id="checking"></i></div>
You are overwriting the innerHTML in every iteration of loop rather than adding to it
Try changing
document.getElementById("fline").innerHTML = '> ' + tempString;
To
document.getElementById("fline").innerHTML += '> ' + tempString;
// ^^ concatenate instead of reassign
I'm trying to write a function (in JavaScript) that would write a sentence in a <p> tag by writing its letters one by one with a 300ms pause between each letter, for exmaple. I've written the following:
var text = ["H", "e", "l", "l", "o", " ", "h", "o", "w", " ", "a", "r", "e", "y", "o", "u", "?"]
function typeText() {
var i = 0;
var interval = setInterval(function () {
var parag = document.getElementById("theParagraph");
var paragOldText = parag.innerText;
parag.innerText = paragOldText + text[i];
i++;
if (text.length == i)
clearInterval(interval);
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
As you can see, there are some " " (empty space) characters in the array; the problem is that it doesn't write those empty spaces, so the sentence would be like this: "Hellohowareyou". How do I solve this?
Don't use presentation as data. Store the current content as a separate string, don't pull it from the DOM. This way you're not dependent on how the browser stores the element's text content.
var text = ["H", "e", "l", "l", "o", " ", "h", "o", "w", " ", "a", "r", "e", "y", "o", "u", "?"]
function typeText() {
var i = 0;
var paragText = "";
var interval = setInterval(function () {
var parag = document.getElementById("theParagraph");
paragText += text[i];
parag.innerText = paragText;
i++;
if (text.length == i)
clearInterval(interval);
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
As a side note, the same thing could be made a lot simpler:
var text = "Hello how are you?";
function typeText() {
var i = 0;
var interval = setInterval(function () {
var parag = document.getElementById("theParagraph");
parag.innerText = text.substr(0, i);
if (text.length == i)
clearInterval(interval);
i++;
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
What about using textContent?
var text = ["H", "e", "l", "l", "o", " ", "h", "o", "w", " ", "a", "r", "e", " ","y", "o", "u", "?"]
function typeText() {
var i = 0;
var interval = setInterval(function() {
var parag = document.getElementById("theParagraph");
var paragOldText = parag.textContent;
parag.textContent = paragOldText + text[i];
i++;
if (text.length == i)
clearInterval(interval);
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
You can also use innerHTML:
var text = ["H", "e", "l", "l", "o", " ", "h", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", "?"]
function typeText() {
var i = 0;
var interval = setInterval(function() {
var parag = document.getElementById("theParagraph");
var paragOldText = parag.innerHTML;
parag.innerHTML = paragOldText + text[i];
i++;
if (text.length == i)
clearInterval(interval);
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
innerText was introduced by IE and, as we all know, nothing good comes from IE. Joking apart, this is a good explanation about it: "The poor, misunderstood innerText".
The other answers address the issues with your code, but I'd like to address issues with your whole plan.
Do you really want to be defining an array of characters? Long sentences are going to be hell. And what if you want variable text? Use this instead:
var input = "Hello how are you?";
var text = input.split(""); // split into array of characters
Speaking of longer sentences, your "typewriter" will fill out the current line, realise it doesn't have room, and then bump the last word down to the next line to finish it. This is not a good look! You can get around this with a clever trick:
<p><span id="visible_text">Hello how a</span><span id="remaining_text">re you?</span></p>
<style>#remaining_text {visibility:hidden}</style>
Not only will this handle word wrapping very nicely, it will also "reserve" the necessary space ahead of time so that you don't end up with it pushing the content below the typewriter further down the page as new lines arise.
You can easily achieve this effect by counting which character position you are at, then splitting the input string into two pieces at that offset. Put the first piece in the first <span>, the rest in the second, and you're golden.
Source: I use this technique in my "RPG cutscene"-style code. Actually a more advanced version, as mine also supports HTML rather than just plain text!
You need to introduce the space using and use innerHTML instead of innerText
var paragOldText = parag.innerHTML;
parag.innerHTML = paragOldText + ( text[i].trim().length ? text[i] : " " ) ;
Edit
isn't required with innerHTML
var paragOldText = parag.innerHTML;
parag.innerHTML = paragOldText + text[i] ;
Demo
var text = ["H", "e", "l", "l", "o", " ", "h", "o", "w", " ", "a", "r", "e", "y", "o", "u", "?"]
function typeText() {
var i = 0;
var interval = setInterval(function() {
var parag = document.getElementById("theParagraph");
var paragOldText = parag.innerHTML;
parag.innerHTML = paragOldText + text[i];
i++;
if (text.length == i)
clearInterval(interval);
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
I've modified your code to show how you can use the slice method for shorter, more elegant code.
var text = "Hello how are you?"
function typeText() {
var i = 0;
var parag = document.getElementById("theParagraph");
var interval = setInterval(function () {
i++;
parag.innerText = text.slice(0, i);
if (i == text.length)
clearInterval(interval);
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
Short answer: Use textContent attribute instead of innerText attribute and you'll be able to add spaces.
e.g.
var text = ["H", "e", "l", "l", "o", " ", "h", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", "?"] // Added missing space after "are"
function typeText() {
var i = 0;
var interval = setInterval(function() {
var parag = document.getElementById("theParagraph");
var paragOldText = parag.textContent; // Replaced "parag.innerText" with "parag.textContent"
parag.textContent = paragOldText + text[i]; // Did it again.
i++;
if (text.length == i)
clearInterval(interval);
}, 200)
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
</body>
Also, please note that Konrad Rudolph and bergi answered the why in comments directly on the question.
This problem is a great candidate for an MVC pattern. I discuss this exact problem in my blog. I've provided an MVC for this problem below. (Please excuse the shameless self-promotion.)
const Model = function(){
const self = this;
self.index = 0;
self.text = ["H", "e", "l", "l", "o", " ", "h", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", "?"];
self.textString = "",
self.accumulate = function(){
const length = self.text.length;
self.textString = self.textString + self.text[self.index];
self.index = ++self.index % length;
}
}
const Controller = function(model, elem, milsec){
const self = this;
self.elem = elem;
self.start = function(){
const interval = setInterval( function(){
if(model.index===model.text.length-1){
clearInterval(interval);
}
model.accumulate();
self.elem.innerText = model.textString;
}, milsec);
}
}
const typeText = function(){
const model = new Model();
const theParagraph = document.getElementById('theParagraph');
const controller = new Controller(model, theParagraph, 200);
controller.start();
}
<body>
<p id="theParagraph"></p>
<button id="typeButton" onclick="typeText()" style="padding:15px">Start typing the sentence</button>
<p>
I invite you to go to my <a target='_top' href="https://www.monilito.com/blog/Never-Use-Presentational-Structures-to-Store-State">blog article</a> for an interesting take on this problem.
</p>
</body>