too many arguments while calculating values - javascript

I have multiple variables that use arguments to calculate an answer, but it only seems to work when I have a single variable with arguments.
My HTML is:
<textarea id="given" placeholder="Given"></textarea>
<input type="text" id="result" placeholder="Result" list="resultAutoComplete"/>
<datalist id="resultAutoComplete">
<option value="v">(v) Speed</option>
<option value="ρ">(ρ) density</option>
<option value="Eₚ">(Eₚ) Potential energy</option>
</datalist>
<button type="button" onClick="calculateAnswer();">result</button>
<p><a id="Rho" onClick="RhoAdd();" style="cursor: pointer;">ρ</a></p>
<button id="Example" onClick="Examplefill();" style="cursor: pointer;">ρ</button>
<p>Answer: <b id="answer"></b></p>
<div style="background-color: #ACACAC; width: 100%;"><ins style="color: #ED141A; font-size: 20px; margin-left: 5px;" id="errorAlerts"></ins></div>
When I get rid of other variables: ress and rest it works.
Here's what worked
function calculateAnswer() {
var givenInput = document.getElementById('given').value;
var road_s = givenInput.match(/s=(.*)(;)/); //looks for S= (road)
var time_t = givenInput.match(/t=(.*)(;)/); //looks for t= (time)
var speed_v = givenInput.match(/v=(.*)(;)/); //looks for v= (speed)
var toFind = document.getElementById('result').value;
var resv = road_s[1] / time_t[1];
if (toFind === "v") {
document.getElementById('answer').innerHTML = resv;
document.getElementById('errorAlerts').innerHTML = "";
} else {
document.getElementById('errorAlerts').innerHTML = "ERROR... invalid requested result";
}
}
I need this to print out a answer using road_s[1], time_t[1] and speed_v[1], but when I add more variables using these arguments
var resv = road_s[1] / time_t[1];
var ress = speed_v[1] * time_t[1];
var rest = road_s[1] / speed_v[1];
the system doesn't print out anything
function calculateAnswer() {
var givenInput = document.getElementById('given').value;
var road_s = givenInput.match(/s=(.*)(;)/); //looks for S= (road)
var time_t = givenInput.match(/t=(.*)(;)/); //looks for t= (time)
var speed_v = givenInput.match(/v=(.*)(;)/); //looks for v= (speed)
var toFind = document.getElementById('result').value;
var resv = road_s[1] / time_t[1];
var ress = speed_v[1] * time_t[1];
var rest = road_s[1] / speed_v[1];
if (toFind === "v") {
document.getElementById('answer').innerHTML = resv;
document.getElementById('errorAlerts').innerHTML = "";
} else {
document.getElementById('errorAlerts').innerHTML = "ERROR... invalid requested result";
}
if (toFind === "s") {
document.getElementById('answer').innerHTML = ress;
document.getElementById('errorAlerts').innerHTML = "";
} else {
document.getElementById('errorAlerts').innerHTML = "ERROR... invalid requested result";
}
if (toFind === "t") {
document.getElementById('answer').innerHTML = rest;
document.getElementById('errorAlerts').innerHTML = "";
} else {
document.getElementById('errorAlerts').innerHTML = "ERROR... invalid requested result";
}
}
It's is very hard to explain because I'm not very familiar with arguments.

So, there are a few things going on here. First, when you match your regex (given the input you've commented), you will always have one of the three that doesn't match. Given the comment input, speed_v will be null, and would cause a fatal error in two of the three equations. At the first fatal error, the program would halt.
To fix this, I changed your match statements a little:
var road_s = givenInput.match(/s=(.*)(;)/) || [null, 0]; //looks for S= (road)
var time_t = givenInput.match(/t=(.*)(;)/) || [null, 0]; //looks for t= (time)
var speed_v = givenInput.match(/v=(.*)(;)/) || [null, 0]; //looks for v= (speed)
In each case, if match returns null, the || operator (logical or) kicks in, and creates a 'dummy array', containing [null, 0] - thus providing a value for the missing option, each time.
The second problem you encounter is in your if statement. In each branch, you say 'if the chosen option is thus-and-such, display the calculation. if not, show an error!' And that is happening for each of the various options.
A better approach may be to use a switch statement, allowing you to watch for each possible outcome:
switch(toFind){
case 'v':
document.getElementById('answer').innerHTML = resv;
document.getElementById('errorAlerts').innerHTML = "";
break;
case 's':
document.getElementById('answer').innerHTML = ress;
document.getElementById('errorAlerts').innerHTML = "";
break;
case 't':
document.getElementById('answer').innerHTML = rest;
document.getElementById('errorAlerts').innerHTML = "";
break;
default:
document.getElementById('errorAlerts').innerHTML = "ERROR... invalid requested result";
}
To see this as a working solution, take a look at this repl: https://repl.it/#TobiasParent/tooManyArgsSO
edit: I know this is a hacky solution, but let's face it - the HTML is hacky, the input is hacky, the whole thing has a slap-dash feel. Given that, this is a teachable moment. Learn about the switch/case branching mechanism, and try to understand why you were getting a fatal error in your calculations.

Related

Why do I get null characters at the end of my files when encoding and decoding?

I'm making a web app that encodes an input file into a canvas element based on the char codes of each character in the input file.
For instance ABC, being 0x41, 0x42 and 0x43 would make the color code #414243, and so on for the entire file.
A canvas element is then updated with the color codes to create a downloadable image.
To decode, there is a function that goes through each part of the uploaded image file, gets the color code and converts it back into characters based on the color values.
The issue is, I'm getting NUL characters at the end of the decoded file, and I'm at my wits end about how to handle these.
Here's the full JS code
function getFile (inp, encode=true){
//no return
let file = inp.files[0];
let fr = new FileReader();
if (encode){
fr.readAsText(file);
fr.onload = function(){
let hexCodes = colorCode (fr.result, file['name']);
let imgMain = document.getElementById ("main-canvas");
imgMain.width = hexCodes.length;
imgMain.height = 100;
let ctx = imgMain.getContext("2d");
for (let i=0;i<hexCodes.length;++i){
ctx.fillStyle = hexCodes[i];
ctx.fillRect (i,0,i+1,100);
}
};
}else{
fr.readAsDataURL(file);
fr.onload = function(){
var imgTmp = new Image();
imgTmp.src = fr.result;
imgTmp.onload = function(){
let tmpDecode = colorDecode(imgTmp);
let link = document.getElementById("download-link");
link.download = tmpDecode[0];
let tmpBlob = new Blob ([tmpDecode[1]],{type: 'text/plain'});
link.href = window.URL.createObjectURL(tmpBlob);
}
}
}
fr.onerror = function(){
console.log (fr.error);
};
}
function rbg(r,g,b){
//returns an HTML color code
let rR = "0"+r.toString(16);
let rG = "0"+g.toString(16);
let rB = "0"+b.toString(16);
rR = rR.substr(rR.length - 2);
rG = rG.substr(rG.length - 2);
rB = rB.substr(rB.length - 2);
return "#" + rR + rG + rB;
}
function colorCode(strInp, strName){
//returns an array of color codes;
let colors = [[],[],[]];
let colorsHex = [];
while(strName.length<256)
strName += String.fromCharCode (0);
let wholeStr = strName + strInp;
for(let i=0;i<wholeStr.length;++i){
colors[i%3].push(wholeStr[i].charCodeAt(0));
}
if (colors[0].length>colors[1].length)
colors[1].push(0);
if (colors[1].length>colors[2].length)
colors[2].push(0);
for (let i=0;i<colors[0].length;++i){
colorsHex.push(rbg(colors[0][i],colors[1][i],colors[2][i]));
}
return colorsHex;
}
function colorDecode(imgInp){
//returns text value of file
let imgMain = document.createElement ("canvas");
let ctx = imgMain.getContext("2d");
imgMain.width = imgInp.width;
if (imgMain.width < 256)
return "Image is not of correct length!";
imgMain.height = imgInp.height;
ctx.drawImage (imgInp, 0, 0);
let retVal = "";
let name = "";
for (let i=0;i<86;++i){
let p = ctx.getImageData(i,10,1,1).data;
if (p[0] === 0)
break;
name += String.fromCharCode (p[0]);
if (i!==86){
if (p[1] === 0)
break;
name += String.fromCharCode (p[1]);
if (p[2] === 0)
break;
name += String.fromCharCode (p[2]);
}
}
name += String.fromCharCode(0); //ensures it's null terminated
for (let i=85;i<imgMain.width;++i){
let p = ctx.getImageData(i,10,1,1).data;
if (i!==85)
retVal += String.fromCharCode(p[0]);
retVal += String.fromCharCode(p[1]);
retVal += String.fromCharCode(p[2]);
}
while(retVal[-1]===String.fromCharCode(0) ||
retVal[-1]===String.fromCharCode(32))
retVal = retVal.substr(0,retVal.length-1);
return [name.substring(0,name.length-1), retVal];
}
And here's the HTML just in case it's relevant
<doctype html>
<html>
<head>
<title>Color Coder</title>
<script src="colorCoder.js"></script>
</head>
<body>
<label for="inp">Select a file to convert</label>
<input type="file" id="inp" onchange="getFile(this)">
<br>
<canvas id="main-canvas" height=100></canvas>
<br>
<label for="inpDecode">Select an image to decode</label>
<input type="file" id="inpDecode" onchange="getFile(this, false)">
<br>
<a id="download-link" download href="javascript:alert('Nothing to download!');">Download</a>
</body>
</html>
I know I'm adding char values 0 at the end of the strings, but shouldn't
while(retVal[-1]===String.fromCharCode(0) ||
retVal[-1]===String.fromCharCode(32))
retVal = retVal.substr(0,retVal.length-1);
take care of removing those NUL characters?
I've tried changing readAsText to readAsBinaryString, still get similar (the same?) issues.
I'm downloading the images as .PNG, and while I don't know, it doesn't look like it's losing resolution at any point.
Edit for Clarity
The specific test case I'm using to get this behavior is using the colorCode.js (copied above in its entirety) as the source file to generate the PNG image and I'm getting NUL characters (ascii 0) along with space characters (ascii 32) appended to the end of the input.
while(retVal[-1]===String.fromCharCode(0) ||
retVal[-1]===String.fromCharCode(32))
retVal = retVal.substr(0,retVal.length-1);
doesn't take care of it, because that doesn't test the last character. You can't use negative subscripts to index from the end (the substr() method implements this convention, but it's deprecated). To get the last character, use retVal[retVal.length-1].

How to compare 2 text input values?

I'm trying to create a simple game where you have to answer the correct answer from a calculation.
I already have the function to generate random calculations, but i don't know how to compare it with the result which the user writted.
I tried to make the if, so when the user press the submit button, then the app will try to determine if that's the correct answer.
var numArray = ["10/2", "5x5", "12-22", "5-6", "20-70"];
var question = document.getElementById("textQuestion");
var answer = document.getElementById("textAnswer");
function rollDice() {
document.form[0].textQuestion.value = numArray[Math.floor(Math.random() * numArray.length)];
}
function equal() {
var dif = document.forms[0].textQuestion.value
if (dif != document.forms[0].textAnswer.value) {
life--;
}
}
<form>
<input type="textview" id="textQuestion">
<br>
<textarea id="textAnswer" form="post" placeholder="Answer"></textarea>
</form>
<input type="button" name="start" onclick="">
document.forms[0].textQuestion.value looking for an element with name=textQuestion, which doesn't exist. Use getElementById instead or add name attribute (needed to work with the input value on server-side).
function equal() {
if (document.getElementById('textQuestion').value != document.getElementById('textAnswer').value) {
life--; // life is undefined
}
}
// don't forget to call `equal` and other functions.
This is probably what you're looking for. I simply alert(true || false ) based on match between the random and the user input. Check the Snippet for functionality and comment accordingly.
var numArray = ["10/2", "5x5", "12-22", "5-6", "20-70"];
var questionElement = document.getElementById("textQuestion");
var answerElement = document.getElementById("textAnswer");
function rollDice() {
var question = numArray[Math.floor(Math.random() * numArray.length)];
questionElement.setAttribute("value", question);
}
//rolldice() so that the user can see the question to answer
rollDice();
function equal()
{
var dif = eval(questionElement.value); //get the random equation and evaluate the answer before comparing
var answer = Number(answerElement.value); //get the answer from unser input
var result = false; //set match to false initially
if(dif === answer){
result = true; //if match confirmed return true
}
//alert the match result
alert(result);
}
document.getElementById("start").addEventListener
(
"click",
function()
{
equal();
}
);
<input type="textview" id="textQuestion" value="">
<br>
<textarea id="textAnswer" form="post" placeholder="Answer"></textarea>
<input type="button" id="start" value="Start">
There's more I would fix and add for what you're trying to achieve.
First of you need a QA mechanism to store both the question and the correct answer. An object literal seems perfect for that case: {q: "", a:""}.
You need to store the current dice number, so you can reuse it when needed (see qa_curr variable)
Than you could check the user trimmed answer equals the QA.a
Example:
let life = 10,
qa_curr = 0;
const EL = sel => document.querySelector(sel),
el_question = EL("#question"),
el_answer = EL("#answer"),
el_check = EL("#check"),
el_lives = EL("#lives"),
qa = [{
q: "Calculate 10 / 2", // Question
a: "5", // Answer
}, {
q: "What's the result of 5 x 5",
a: "25"
}, {
q: "5 - 6",
a: "-1"
}, {
q: "Subtract 20 from 70",
a: "-50"
}];
function rollDice() {
qa_curr = ~~(Math.random() * qa.length);
el_question.textContent = qa[qa_curr].q;
el_lives.textContent = life;
}
function checkAnswer() {
const resp = el_answer.value.trim(),
is_equal = qa[qa_curr].a === el_answer.value;
let msg = "";
if (resp === '') return alert('Enter your answer!');
if (is_equal) {
msg += `CORRECT! ${qa[qa_curr].q} equals ${resp}`;
rollDice();
} else {
msg += `NOT CORRECT! ${qa[qa_curr].q} does not equals ${resp}`;
life--;
}
if (life) {
msg += `\nLives: ${life}`
} else {
msg += `\nGAME OVER. No more lifes left!`
}
// Show result msg
el_answer.value = '';
alert(msg);
}
el_check.addEventListener('click', checkAnswer);
// Start game
rollDice();
<span id="question"></span><br>
<input id="answer" placeholder="Your answer">
<input id="check" type="button" value="Check"> (Lives:<span id="lives"></span>)
The above still misses a logic to not repeat questions, at least not insequence :) but hopefully this will give you a good start.

How to remove innerHTML value to be shown initially

I am trying to create a multiplication table in JavaScript. The user is prompted to provide the Table number (1 to 10) after which all the question marks ('?') are replaced with that number. The user then needs to enter the answers in all the provided text fields. Finally, the user will have the option to check the answer (i.e. whether it is right or wrong).
When I run my code. After entering the user data to prompt it shows Incorrect infront of each textfield and the user entered value just before the Check answers button. How can I remove them to be shown initially.
Output:
My code:
function result() {
var value = document.getElementById("a1").value;
var checkMessageSpan1 = document.getElementById("checkMessage1");
var checkMessageSpan2 = document.getElementById("checkMessage2");
var r = x * 1;
if (value == x) {
checkMessageSpan1.innerHTML = "<span style=\"color:green\">"+"Correct!";
}else{
checkMessageSpan1.innerHTML = "<span style=\"color:red\">"+"Incorrect!";
}
var value = document.getElementById("a2").value;
var r = x * 2;
if (value == r) {
checkMessageSpan2.innerHTML = "<span style=\"color:green\">"+"Correct!";
}else{
checkMessageSpan2.innerHTML = "<span style=\"color:red\">"+"Incorrect!";
}
</script>
<button onClick="alert_field()"> Generate Question</button><br><br>
<p id="s1">
? x 1 = <input type="text" id="a1"><span id="checkMessage1"></span><br>
? x 2 = <input type="text" id="a2"><span id="checkMessage2"></span><br>
</p><br><br>
<p id="a"></p>
Check answers
For replacing all special characters, you may leverage regular expressions in js
var res=str.replace(/[^a-zA-Z0-9]/g,x); instead of
var res = str.replace("?",x);
More on Regular expressions in JS https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
Try to add this code:
var value = document.getElementById("a1").value;
if (checkMessageSpan1.style.display === "none") {
checkMessageSpan1.style.display = "inline-block";
} else {
checkMessageSpan1.style.display = "none";
}
var value = document.getElementById("a2").value;
if (checkMessageSpan2.style.display === "none") {
checkMessageSpan2.style.display = "inline-block";
} else {
checkMessageSpan2.style.display = "none";
}

Removing a range starting occurrence with specified place

I need to define the text area to delete from 4th occurrence of (_) and preserve the extension.
before 12_345_678_900_xxxxxxxxxxxxxxx.jpg after 12_345_678_900.jpg,
before 34_567_890_123_xxxxxxxx_xxxxx_xxxxxxxxxxx.jpg
after 34_567_890_123.jpg
Is it possible?
One solution is to find the nth occurence and then use substring.
var one='12_345_678_900_xxxxxxxxxxxxxxx.jpg'; // 12_345_678_900.jpg
function nth_occurrence (string, char, nth) {
var first_index = string.indexOf(char);
var length_up_to_first_index = first_index + 1;
if (nth == 1) {
return first_index;
} else {
var string_after_first_occurrence = string.slice(length_up_to_first_index);
var next_occurrence = nth_occurrence(string_after_first_occurrence, char, nth - 1);
if (next_occurrence === -1) {
return -1;
} else {
return length_up_to_first_index + next_occurrence;
}
}
}
console.log(one.substring(0,nth_occurrence(one,'_',4))+one.substring(one.indexOf('.')));
Sure, split by "_" and then join back the data you want:
var str = "12_345_678_900_xxxxxxxxxxxxxxx.jpg";
str = str.split("_").slice(0,4).join("_") + "."+ str.split(".").slice(-1)
console.log(str)
Regular Expressions are great for this sort of scenario:
const data1 = '12_345_678_900_xxxxxxxxxxxxxxx.jpg'
const data2 = '34_567_890_123_xxxxxxxx_xxxxx_xxxxxxxxxxx.jpg'
const re = /^([^_]+_[^_]+_[^_]+_[^_]+).*(.jpg)$/;
var test1 = data1.replace(re, '$1$2');
var test2 = data2.replace(re, '$1$2');
Try it out: https://jsfiddle.net/648xt3qq/
There are probably a few different regular expression approaches that would get the job done
Maybe this works for you:
function clean() {
var el = document.getElementById('area');
el.value = el.value.replace(/^(.*?_.*?_.*?_.*?)(_.*?)(\..*?.*)$/gmi, '$1$3');
}
<form action="">
<textarea cols="50" rows="4" id="area">12_345_678_900_xxxxxxxxxxxxxxx.jpg
34_567_890_123_xxxxxxxx_xxxxx_xxxxxxxxxxx.jpg</textarea><br />
<input type="submit" onclick="clean(); return false;" />
</form>

Check if textbox contains a number

I'm currently working on a digital assistant website which is based around JavaScript and jQuery. The user can type in questions or tell the assistant things into the textbox and the assistant will respond with something relevant to the input. What I am planning to implement is to check if the textbox contains a number (intager) and if it does some sort of function will run. The concept sounds fairly simple and but I am having trouble. I have been searching around for a bit but I can't seem to find anything which will work with my code.
I will add my JavaScript and the nessacary parts of the HTML. But I am warning you, the code is messy.
JavaScript:
// JavaScript Document
function submitted() {
var srch = document.getElementById("srch");
command();
getPlaceHolder();
srch.value = "";
}
function searchKeyPress(e) {
e = e || window.event;
if (e.keyCode == 13) {
//document.getElementById('btn').click();
submitted();
}
}
function goBtn() {
submitted();
}
function refreshBtn() {
getWelcome();
}
function stClock() {
window.setTimeout("stClock()", 1000);
today = new Date();
self.status = today.toString();
}
function getWelcome() {
var ar = new Array(20)
ar[0] = "What's on your mind?";
ar[1] = "How can I help?";
ar[2] = "Anything you need help with?";
ar[3] = "Ask me anything";
ar[4] = "What can I help you with?";
ar[5] = "What would you like me to do?";
ar[6] = "What can I do for you?";
ar[7] = "Need help with anything?";
ar[8] = "Need someone to talk to?";
ar[9] = "I'm here to help";
ar[10] = "Anything you need to know?";
ar[11] = "How else can I help?";
ar[12] = "What can I do now?";
ar[13] = "Need anything?";
ar[14] = "Any problems you need solving?";
ar[15] = "Hello, how do you do?";
ar[16] = "Hi there";
ar[17] = "Hi, I'm aurum";
ar[18] = "Hello there";
ar[19] = "How do you do?";
var now = new Date();
var sec = now.getSeconds();
document.getElementById('output').innerHTML = ar[sec % 20];
}
function getPlaceHolder() {
var ar = new Array(20)
ar[0] = "What's on your mind?";
ar[1] = "How can I help?";
ar[2] = "Anything you need help with?";
ar[3] = "Ask me anything";
ar[4] = "What can I help you with?";
ar[5] = "What would you like me to do?";
ar[6] = "What can I do for you?";
ar[7] = "Need help with anything?";
ar[8] = "Need someone to talk to?";
ar[9] = "I'm here to help";
ar[10] = "Anything you need to know?";
ar[11] = "How else can I help?";
ar[12] = "What can I do now?";
ar[13] = "Need anything?";
ar[14] = "Any problems you need solving?";
ar[15] = "Hello, how do you do?";
ar[16] = "Hi there";
ar[17] = "Hi, I'm aurum";
ar[18] = "Hello there";
ar[19] = "How do you do?";
var now = new Date();
var sec = now.getSeconds();
document.getElementsByName('srch')[0].placeholder=ar[sec % 20];
}
function command() {
var srchVar = document.getElementById("srch");
var srch = srchVar.value;
var t = srch;
var outputElement = document.getElementById('output');
if (srch == '') {
outputElement.innerHTML = "How can I help you, if you don't say anything?";
}
else if (srch.indexOf('about') != -1) {
outputElement.innerHTML = "Hello, I'm Aurum. I was designed by Omar Latreche to help people answer their questions. However, I also like to talk to people aswell as answer their questions.";
}
else if (srch.indexOf('time') != -1) {
outputElement.innerHTML = 'The current time according to your computer is' + ShowTime(new Date());
}
else {
if (confirm("I am sorry but for some reason I don't understand. You could either repeat that or would you like to search Google for that instead?") == true) {
window.open('https://www.google.co.uk/#q=' + srch, '_blank');
}
else { /* Nothing */ }
}
}
//Show time in 12hour format
var ShowTime = (function() {
function addZero(num) {
return (num >= 0 && num < 10) ? "0" + num : num + "";
}
return function(dt) {
var formatted = '';
if (dt) {
var hours24 = dt.getHours();
var hours = ((hours24 + 11) % 12) + 1;
formatted = [formatted, [addZero(hours), addZero(dt.getMinutes())].join(":"), hours24 > 11 ? "PM" : "AM"].join(" ");
}
return formatted;
};
})();
And the HTML:
<!DOCTYPE html>
<html>
<body onload="getWelcome(); getPlaceHolder();">
<div class="output" id="output">
An error has occoured. Please make sure you have JavaScript enabled in your browser.
</div>
<div class="cont">
<div class="ui-widget">
<div class="search-cont">
<input class="search-field" id="srch" name="srch" onkeypress="searchKeyPress(event);" placeholder="ask me anything" spellcheck="false"> <input class="refresh" onclick="refreshBtn()" title="Refresh the conversation" type="button"> <input class="go" onclick="goBtn()" type="button">
</div>
</div><br>
</div>
</body>
</html>
I really appreciate any help provided. Thanks, Omar.
PS. I apologies for the long paragraph but that is the only way I could think to explain what I need.
PPS. If you need any more information on my project just incase, the URL is http://omarlatreche.tk/aurum/
This is the function I came up with to check for number:
function checkNum() {
text = document.getElementById('srch').value;
valArr = document.getElementById('srch').value.split(' ');
for (i = 0; i < valArr.length; i++) {
if (isNaN(valArr[i])==false) {
alert("Number found");
}
}
}
Here is the JSFiddle demo
I called the function in the goBtn() function.
can you explain this line?
document.getElementById('output').innerHTML = [0].innerHTML=ar[sec % 20];
shouldn't it be
document.getElementById('output').innerHTML = ar[sec % 20];

Categories