Empty spaces are ignored by the InnerText property - javascript
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>
Related
Javascript user input password generator?
For school, I am tasked with creating a password generator that prompts the user via a confirm as to whether they want uppercase, lowercase, numbers and symbols in there password as well as between 8-128 characters. Thus far, I have created arrays for uppercase, lowercase, numbers and symbols. var uppercase = ["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 lowercase = ["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 numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; var symbols = ["!", "#", "$", "&", "%", "'", "(", ")", "*", "+", "-", "/", ":", ";", "<", "=", ">", "?", "#", "^", "_", "~", "`", "{", "|", "}", "."]; Beyond that, I have created confirm messages for them as well, but am unsure how to connect the two and then randomly generate a password based on their responses.
Sample code for generation password: function gen_pass() { var uppercase = document.getElementById("uppercase").checked === true ? true : false; var lowercase = document.getElementById("lowercase").checked === true ? true : false; var numbers = document.getElementById("numbers").checked === true ? true : false; var symbols = document.getElementById("symbols").checked === true ? true : false; var len = document.getElementById("len").value; var str= [ ["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"], ["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"], ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"], ["!", "#", "$", "&", "%", "'", "(", ")", "*", "+", "-", "/", ":", ";", "<", "=", ">", "?", "#", "^", "_", "~", "`", "{", "|", "}", "."]]; var str_user; uppercase===true ? str_user=str[0] :0; lowercase===true ? str_user+=str[1] :0; numbers===true ? str_user+=str[2] :0; symbols===true ? str_user+=str[3] :0; if(str_user){ let len_str = str_user.length; var v= Math.floor(Math.random() * str_user.length); var password = str_user[v]; for (let i = 0 ; i<len ; i++ ) { v= Math.floor(Math.random() * str_user.length); console.log(v); password += str_user[v]; } console.log(password); document.getElementById("password").value =password; }else{ alert('Minmum check mark 1 option for generation password'); } } <html> <body> uppercase: <input type="checkbox" id="uppercase"> <br> lowercase: <input type="checkbox" id="lowercase"> <br> numbers: <input type="checkbox" id="numbers"> <br> symbols: <input type="checkbox" id="symbols"> <br> <input type="number" id="len" value="8" > <br> <button onclick="gen_pass()">Genrate Password</button> <br><br> <input type="text" id="password" value=""> </body> </html>
Let's try to make a plan: You have 4 collections of characters. You have user's answers. Based on his answers you'll try to fill an array of available collections. Let's call it availableCollections. This array will contains the other arrays you already have if the user wants this set of characters. The user wants uppercase characters ? Push the uppercase array in your availableCollections. Do the same for the other arrays. Then let's define a empty string to store the password. We will call it password Now let's get a random character. First you need to select on a those availableCollections randomly. So you want to find a function to retrieve a random item out of availableCollections. Let's call this item randomCollection. This randomCollection is one of your arrays you defined earlier containing a set of characters. (uppercase, lowercase, numbers, symbols) You want to select a random character out of the randomCollection. Use the same method from above. And let's call this character randomCharacter. You can now concatenate this randomCharacter with the password string. To generate the full password you just have to make this task in a loop to generate the desired number of characters.
The secret is in my PassGen constructor. Give it a go! //<![CDATA[ /* js/external.js */ let get, post, doc, html, bod, nav, M, I, mobile, S, Q, aC, rC, tC, shuffle, rand, PassGen; // for use on other loads addEventListener('load', ()=>{ get = (url, success, context)=>{ const x = new XMLHttpRequest; const c = context || x; x.open('GET', url); x.onload = ()=>{ if(success)success.call(c, JSON.parse(x.responseText)); } x.send(); } post = function(url, send, success, context){ const x = new XMLHttpRequest; const c = context || x; x.open('POST', url); x.onload = ()=>{ if(success)success.call(c, JSON.parse(x.responseText)); } if(typeof send === 'object' && send && !(send instanceof Array)){ if(send instanceof FormData){ x.send(send); } else{ const fd = new FormData; for(let k in send){ fd.append(k, JSON.stringify(send[k])); } x.send(fd); } } else{ throw new Error('send argument must be an Object'); } return x; } doc = document; html = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id); mobile = nav.userAgent.match(/Mobi/i) ? true : false; S = (selector, within)=>{ var w = within || doc; return w.querySelector(selector); } Q = (selector, within)=>{ var w = within || doc; return w.querySelectorAll(selector); } aC = function(){ const a = [].slice.call(arguments), n = a.shift(); n.classList.add(...a); return aC; } rC = function(){ const a = [].slice.call(arguments), n = a.shift(); n.classList.remove(...a); return rC; } tC = function(){ const a = [].slice.call(arguments), n = a.shift(); n.classList.toggle(...a); return tC; } shuffle = array=>{ let a = array.slice(), i = a.length, n, h; while(i){ n = Math.floor(Math.random()*i--); h = a[i]; a[i] = a[n]; a[n] = h; } return a; } rand = (min, max)=>{ let mn = min, mx = max; if(mx === undefined){ mx = mn; mn = 0; } return mn+Math.floor(Math.random()*(mx-mn+1)); } PassGen = function(special = '!##$%^&*-+/=_?'){ const abc = 'abcdefghijklmnopqrstuvwxyz'; const az = abc.split(''), aZ = abc.toUpperCase().split(''), aL = az.length-1; const sc = special.split(''), sL = sc.length-1; let gen = ''; this.numbers = count=>{ for(let i=0; i<count; i++){ gen += rand(9).toString(); } return this; } this.lowerCases = count=>{ for(let i=0; i<count; i++){ gen += az[rand(aL)]; } return this; } this.upperCases = count=>{ for(let i=0; i<count; i++){ gen += aZ[rand(aL)]; } return this; } this.specials = count=>{ for(let i=0; i<count; i++){ gen += sc[rand(sL)]; } return this; } this.generate = ()=>{ const g = shuffle(gen.split('')).join(''); gen = ''; return g; } } // you can put the following on another page using a load Event - besides the end load const user = I('user'), pass = I('pass'), pass_match = I('pass_match'), gen = I('gen'); const pg = new PassGen("!#$&%]'()*+-/:;<=>?#^_~`{|}."), choose = I('choose'); const generate = I('generate'), login = I('login'), uc = I('uc'), lc = I('lc'); const no = I('no'), sc = I('sc'); let see = false; user.value = pass.value = ''; uc.value = lc.value = no.value = sc.value = '2'; user.onfocus = pass.onfocus = pass_match.onfocus = ()=>{ pass.type = pass_match.type = 'password'; aC(choose, 'hid'); see = false; } user.oninput = pass.oninput = pass_match.oninput = function(){ let f = this.value !== '' ? aC : rC; let p = pass.value, m = pass_match.value, r; f(this, 'good'); if(user.value === '' || p === '' || m === '' || p !== m){ f = aC; r = p === m && p !== '' ? aC : rC; } else if(p === m){ r = aC; f = rC; } r(pass, 'good'); r(pass_match, 'good'); f(login, 'hid'); } gen.onclick = ()=>{ let f, p = pass.value, m = pass_match.value; if(see){ aC(choose, 'hid'); f = rC; pass.type = pass_match.type = 'password'; } else{ rC(choose, 'hid'); f = aC; pass.type = pass_match.type = 'text'; generate.focus(); } if(user.value === '' || p === '' || m === '' || p !== m)f = aC; f(login, 'hid'); see = !see; } uc.oninput = lc.oninput = no.oninput = sc.oninput = function(){ const v = this.value, n = +v, c = +uc.value+(+lc.value)+(+no.value)+(+sc.value); let f, r; if(v.match(/^(0|[1-9][0-9]*)$/) && c < 129 && c > 7){ f = aC; r = rC; } else{ f = rC; r = aC; } f(this, 'good'); r(generate, 'hid'); } generate.onclick = ()=>{ pass.value = pass_match.value = pg.upperCases(+uc.value).lowerCases(+lc.value).numbers(+no.value).specials(+sc.value).generate(); aC(pass, 'good'); aC(pass_match, 'good'); aC(choose, 'hid'); see = false; if(user.value !== '')rC(login, 'hid'); } login.onclick = ()=>{ console.log('AJAX here'); } }); // end load //]]> /* css/external.css */ *{ box-sizing:border-box; padding:0; margin:0; font-size:0; overflow:hidden; } html,body,.main{ width:100%; height:100%; background:#ccc; } .main{ padding:10px; overflow-y:scroll; } #inc,#dec{ width:20px; } label,input,textarea{ font:bold 22px Tahoma, Geneva, sans-serif; border-radius:3px; } input,textarea,select{ width:100%; padding:3px 5px; border:1px solid #b00; } label{ display:inline-block; cursor:pointer; margin-top:2px; } label:first-child{ margin-top:0; } #pass{ width:90%; } #pass_match,#login{ margin-bottom:10px; } input[type=button]{ background:linear-gradient(#1b7bbb,#147); color:#fff; border:1px solid #147; border-radius:5px; margin-top:7px; cursor:pointer; } input[type=button].gen{ width:10%; margin:0; } #choose{ padding:3px 7px 7px; border:5px solid #1b7bbb; border-radius:4px; margin-top:7px; } #login{ background:linear-gradient(#679467,#235023); border:1px solid #c00; border-color:#050; } .hid{ display:none; } .good{ border-color:#0b0; } <!DOCTYPE html> <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'> <head> <meta charset='UTF-8' /><meta name='viewport' content='width=device-width, height=device-height, initial-scale:1, user-scalable=no' /> <title>Title Here</title> <link type='text/css' rel='stylesheet' href='css/external.css' /> <script src='js/external.js'></script> </head> <body> <div class='main'> <label for='user'>Username</label> <input id='user' type='text' maxlength='128' value='' /> <label for='pass'>Password</label><br /> <input id='pass' type='password' maxlength='128' value='' /><input class='gen' id='gen' type='button' value='!' /> <label for='pass_match'>Reenter Password</label> <input id='pass_match' type='password' maxlength='128' value='' /> <div class='hid' id='choose'> <label for='uc'>Uppercase</label> <input class='good' id='uc' type='number' min='0' max='128' value='2' /> <label for='lc'>Lowercase</label> <input class='good' id='lc' type='number' min='0' max='128' value='2' /> <label class='good' for='no'>Numbers</label> <input class='good' id='no' type='number' min='0' max='128' value='2' /> <label class='good' for='sc'>Special</label> <input class='good' id='sc' type='number' min='0' max='128' value='2' /> <input id='generate' type='button' value='Generate' /> </div> <input class='hid' id='login' type='button' value='Login' /> </div> </body> </html>
Here's one way of doing it. const PASSWORD_LENGTH = 20; const uppercase = ["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"]; const lowercase = ["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"]; const numbers = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; const symbols = ["!", "#", "$", "&", "%", "'", "(", ")", "*", "+", "-", "/", ":", ";", "<", "=", ">", "?", "#", "^", "_", "~", "`", "{", "|", "}", "."]; function generatePassword(useUpper, useLower, useNumbers, useSymbols) { return [] .reduce((collection, item) => { if (useUpper) collection.push(item); return collection; }, uppercase) .reduce((collection, item) => { if (useLower) collection.push(item); return collection; }, lowercase) .reduce((collection, item) => { if (useNumbers) collection.push(item); return collection; }, numbers) .reduce((collection, item) => { if (useSymbols) collection.push(item); return collection; }, symbols) .sort(() => Math.random() - 0.5) .slice(0, PASSWORD_LENGTH) .join(''); } console.log(generatePassword(true, true, true, true)); console.log(generatePassword(true, false, false, true)); Now for the steps, we use boolean type indicators (useUpper, useLower, useNumbers, useSymbols) to tell us what arrays we need to add together. We loop over every possible array to allow chaining and the if (use%%%) collection.append just adds the item to our collection of characters. Could have had a bunch of conditionals but that would require us to mutate the array. .reduce((collection, item) => { if (useUpper) collection.push(item); return collection; }, uppercase) After appending all the needed items we see a call to the array sort method, .sort(() => Math.random() - 0.5) this just shuffles the array around so we don't get the same sequence of characters. Then we slice off part of the array starting at the 0 index and equal to the length of PASSWORD_LENGTH. Then we just join the array together with an empty string separator and we now have our password. Do note this is far from the most efficient solution.
Results display in console but not on the browser
I am creating a psychic game and when I inspect my code in Google Chrome and type my ID's I see the total of wins/losses and how many guesses left. However, I do not see the results in the browser. I think I'm missing something and cannot seem to isolate the actual issue. I have pseudocode lines not needed, removed lines of code that may be the problem. search the internet for this issue. document.elementByID().innerHTML all of my if/else statements. 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"]; var losses = 0; var wins = 0; var guessesLeft = 10; var guessesSoFar = []; // capture user input var psychicGuess; document.onkeypress = function(event) { var userChoice = event.key; guessesSoFar.push(userChoice); var psychicGuess = letters[Math.floor(Math.random() * letters.length)]; if (userChoice === psychicGuess) { wins++; guessesLeft = 10; guessesSoFar = []; } else if (guessesLeft == 0) { losses++; guessesLeft = 10; guessesSoFar = []; } if (userChoice !== psychicGuess) { guessesLeft--; } } <!DOCTYPE html> <html lang="en-us"> <head> <meta charset="UTF-8"> <title>Psychic Game</title> <link rel="stylesheet" type="text/css" href="assets/css/reset.css"> <link rel="stylesheet" type="text/css" href="assets/css/style.css"> </head> <body> <div class="game"> <h1>Psychic Game</h1> <br> <p> Guess what letters I'm thinking of:</p> <br> <p id="wins">Wins:</p> <br> <p id='losses'>Losses:</p> <br> <p id="left">Guesses Left: 10</p> <br> <p id="guesses">Guesses:</p> </div> <script src="assets/javascript/game.js"></script> </body> </html> Inspect -> Console does product results when I type in wins/losses and guesses left.
HTML and Javascript - Two input boxes, one button and an output box
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.
Getting Input Value Issue JavaScript
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>
<p> Shows only last value assigned
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