"Writing" inside a HTML page using JS and JS scope - javascript

I'm developing a program which basically just receives input from the user twice (risk carrier and sum, but that's just a placeholder to make my program less abstract), groups those two values together and then repeats the contents in a loop. See the code below.
<head>
<script type="text/javascript">
function fillArray(){
document.getElementById("danke").innerHTML = "Thanks for specifying the amount of entries.";
var numberOfEntries = parseInt(document.getElementById('input0').value);
var i = 0;
var myArrA = [];
var myArrB = [];
var x = " ";
while(i<numberOfEntries){
var neuRT = prompt("Enter a risk carrier");
myArrA.push(neuRT);
var neuRH = prompt("Enter a risk sum");
myArrB.push(neuRH);
i++;
}
for(i = 0; i<anzahlEintraege; i++){
x = myArrA[i] + " carries a risk of " + myArrB[i];
document.getElementById("test").innerHTML = x;
}
}
</script>
</head>
<body>
<h1>risk assessment</h1>
<input type="text" id="input0" />
<button type="button" onclick="fillArray()">Number of entries</button> <p id="danke"></p>
<button type="button" onclick="untilNow()">Show all entries so far</button>
<br />
<br />
<div id="test"></div>
</body>
</html>
My issues are:
1.) I want to display the array by writing into an HTML element, which I attempted in the for-loop. Pop-ups are to be avoided. How can I loop through HTML elements, such as demo1, demo2, demo3 etc.? I can't just write <p id="demo" + i></p>. What other options are there?
2.) Say I want to make use of the untilNow() function. The scope of my arrays is limited to fillArray(). Do I need to "return" the arrays to the untilNow() function as parameters?
Thanks everyone!!!

The problem with your current code is that you're replacing the html by the last value in every loop. You're using = rather than +=. So, a quick fix would be to replace:
document.getElementById("test").innerHTML = x;
by:
document.getElementById("test").innerHTML += x;
An example of how you could wrap an array of strings in HTMLElements and add them to your document (note that there are many other ways/libraries to achieve the same result):
var myStrings = ["Hello", "stack", "overflow"];
// Two performance rules:
// 1. Use a fragment to prevent multiple updates to the DOM
// 2. No DOM queries in the loop
var newContent = myStrings.reduce(function(result, str) {
var li = document.createElement("li");
var txt = document.createTextNode(str);
li.appendChild(txt);
result.appendChild(li);
return result;
}, document.createDocumentFragment());
// Actually add the new content
document.querySelector("ul").appendChild(newContent);
<ul class="js-list"></ul>

Related

How to write the code in "function printOut(){} " in javascript?

I need help with how to code this program in javascript. The javascript code should load a character from a box and a number (N) from another box. When you press a button, N rows prints each one of those with N characters (same characters that are loaded are printed). Before printing, check that it is only available a character in the box where characters are to be entered.
code in html:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p id="theText"></p>
<p id="theNumber"></p>
a charachter: <input type="charachter" id="theChar">
a number: <input type="number" id="theNbr">
<button onclick="printOut()">print out!</button>
<script type="text/javascript" src="script.js" ></script>
</body>
</html>
Code in Javascript:
function printOut(){
var theText = document.getElementById("theText").innerHTML;
document.getElementById("theText").innerHTML=
document.getElementById("theChar").value;
var theNumber = document.getElementById("theNbr").innerHTML;
document.getElementById("theNumber").innerHTML=
document.getElementById("theNbr").value;
var newText= theText;
var outPut;
for(i = 0; i<theNumber; i++){
newText =newText + theText;
}
newText = newText + "<br>";
for( i = 0; i< theNumber; i++){
outPut = outPut + newText;
}
document.getElementById("theText").innerHTML= outPut;
}
There are several issues in your code, even after the corrections you made after comments were made. Some of the more important:
Don't use innerHTML on an input element. It makes no sense. To get its value, use value.
Don't assign to document.getElementById("theNumber").innerHTML: it will replace any HTML you already had, and thus will remove the theNbr input. Any reference to it will fail with an error from now on.
Initialise your variables before reading from them. outPut is never initialised and so outPut + newText will give undesired results.
Although your can do this with for loops, there is a nice string method in JavaScript with which you can repeat a character or even a longer string: repeat.
Here is how it could work:
function printOut(){
var theNumber = document.getElementById("theNbr").value; // Don't use innerHTML
var theChar = document.getElementById("theChar").value;
var oneLine = theChar.repeat(theNumber) + "<br>";
var output = oneLine.repeat(theNumber);
document.getElementById("theText").innerHTML = output;
}
a charachter: <input type="charachter" id="theChar">
a number: <input type="number" id="theNbr">
<button onclick="printOut()">print out!</button>
<p id="theText"></p>

Issue with getting a keyup function to get sum of input field values using plain Javascript

I'm working on a personal project and I've run into an issue that I haven't been able to solve.
Here is a function that generates new table rows into a table (with id of "tableData") when a button is clicked:
function addNewRow(){
var tableEl = document.getElementById("tableData");
var newLine = '<tr class="newEntry">';
var classArray = ["classA", "classB", "classC", "classD"];
for (var i = 0; i < classArray.length; i++){
newLine += '<td><input class="' + classArray[i] + '"></td>';
}
newLine += '</tr>';
tableEl.insertAdjacentHTML("beforeend", newLine);
}
document.getElementById("addRow").addEventListener("click", addNewRow, false);
//the element with id="addRow" is a button
I've simplified the code for the above function for the sake of readability as it's not the focus of the problem. When the button is clicked, a new row is added successfully.
The problematic part involves another function that takes the sum of the respective classes of each row and displays them in a div.
The goal is to get the sum of the values of all input fields with matching class names. For example, let's say I use the addNewRow function to get six rows. Then I want to have the div showing the sum of the values of all input fields with the class name of "classA"; the number in that div should be the sum of those six values, which gets updated as I type in the values or change the existing values in any of the input fields with class name of "ClassA".
function sumValues(divId, inputClass){
var sumVal = document.getElementsByClassName(inputClass);
var addedUp = 0;
for (var j = 0; j < sumVal.length; j++){
addedUp += Number(sumVal[j].value);
}
document.getElementById(divId).innerHTML = addedUp;
}
Here are a couple (out of several) failed attempts:
document.input.addEventListener("keyup", sumValues("genericDivId", "classA"), false);
document.getElementsByClassName("classA").onkeyup = function(){sumValues("genericDivId", "classA");}
Unfortunately, after scouring the web for a solution and failing to find one, I just added an event listener to a button that, when clicked, would update the div to show the sum of values. Also had to modify the sumValues function to take values from an array rather than accepting arguments.
My question is: How can I modify the code so that the sum value updates as I type in new values or change existing values using pure Javascript (vanilla JS)?
You are very close, document.getElementsByClassName() returns an array of DOM objects, you need to set the onkeyup function for each and every element by looping through that array.
var classA = document.getElementsByClassName('classA'); // this is an array
classA.forEach(function(elem){ // loop through the array
elem.onkeyup = function(){ // elem is a single element
sumValues("genericDivId", "classA");
}
}
Hopefully this fixes your issue
Maybe the example below is not same with your situation, but you'll get the logic, easily. Anyway, do not hesitate to ask for more guide.
document.getElementById("row_adder").addEventListener("click", function() {
var t = document.getElementById("my_table");
var r = t.insertRow(-1); // adds rows to bottom - change it to 0 for top
var c = r.insertCell(0);
c.innerHTML = "<input class='not_important_with_that_way' type='number' value='0' onchange='calculate_sum()'></input>";
});
function calculate_sum() {
var sum = ([].slice.call(document.querySelectorAll("[type=number]"))).map(e=>parseFloat(e.value)).reduce((a, b) => a+b);
document.getElementById("sum").innerHTML = sum;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
<p>
<strong>Sum</strong>:<span id="sum">0</span>
</p>
</div>
<button id="row_adder">
Click me
</button>
<table id="my_table">
</table>
</body>
</html>

Javascript for loop running out of sequence

I have a confusing problem where a line of code in my function is running before a loop which is stated above it. In my HTML I have:
<textarea id="textBox"></textarea>
<button id="submitButton" onclick="parseData()">submit</button>
<div id="put"></div>
And my JS function is:
function parseData() {
var data = $("#textBox").val();
var tab = /\t/;
data = data.split(tab);
$("#put").html($("#put").html() + "<table>");
for (var i = 0; i < data.length; i++) {
$("#put").html($("#put").html() + "<tr>"+data[i]+"</tr>");
};
$("#put").html($("#put").html() + "</table>");
return;
};
The resulting html in $("#put") is this:
<table></table>
"SiO2 (%)Al2O3 (%)TiO2 (%)CaO2 (%)MgO2 (%) 8.21.25.31.51.8 45.32.52.60.210.5 65.23.48.70.0662.3 20.11.85.42.540.2 18.91.12.34.810.7"
I'm not sure why the final </table> is being placed before the for loop runs, and I'm not sure why the <tr> tags aren't being added within the for loop. Any pointers?
jQuery automatically closes up tags upon insertion. Try this.
function parseData() {
var data = $("#textBox").val();
var tab = /\t/;
var put_html = $("#put").html() + "<table>";
data = data.split(tab);
for (var i = 0; i < data.length; i++) {
put_html += "<tr>"+data[i]+"</tr>";
};
put_html += '</table>';
$("#put").html(put_html);
return;
};
However, I notice that you aren't using <td> elements. You might want to look into fixing that too.
Every time you are adding content into the html() property rather than building the entire content and adding it.
Since you are using jQuery you can bind the event using jQuery rather than adding that directly in the HTML
<textarea id="textBox"></textarea>
<button id="submitButton">submit</button>
<div id="put"></div>
$(function(){
$("#submitButton").click(function(){
parseData();
});
function parseData() {
var data = $("#textBox").val();
var tab = /\t/;
data = data.split(tab);
// Build your html
$("#put").html('htmlstructure');
return;
}
});
Also you can look for something similar like concatenating the string in an array so that you don't create string isntances each time when you append, since strings are immutable.
Good example

Modify innerHTML of a child div

I am new to JavaScript. What I am trying to do is make a div and inside of it there will be another div. Within my script code I am trying to create new instances of that div using factory function if that is the right name for it, and then change the innerHTML of the child div if that is possible. Thanks in advance.
<div class = "loopBlock" style="width:350px;">
<fieldset>
<legend style="color:black;font-weight:bold;">While Loop</legend>
<table>
<tr>
<td>Condition:</td>
<td><input type="text" /></td>
</tr>
</table>
<div class = "codeDivClass" id = "codeDiv">
HelloWorld!
</div>
</fieldset>
</div>
<script>
var loopDiv = document.getElementsByClassName("loopBlock");
var loopi =1;
function loopObject(){
var loopDivObject = document.createElement("div");
loopDivObject.innerHTML = loopDiv[0].innerHTML;
loopDivObject.className = "loopBlock";
loopDivObject.id = "loopBlock"+loopi;
loopi++;
return loopDivObject;
};
var functionCodeDiv = document.getElementById("codeDiv");
for (i=0; i<5; i++){
var tempLoop = loopObject();
functionCodeDiv.appendChild(tempLoop);
var id = "loopBlock"+i+1;
document.getElementById(id).getElementsByTagName('div')[0].innerHTML = "bye";
}
</script>
Didn't really get how it should work, but I'm sure I've found a mistake.
var id = "loopBlock"+i+1;
you have to replace with:
var id = "loopBlock"+(i+1);
Example i is 2.
In first case you get: "loopBlock21"
In second (my) case, you'll get "loopBlock3"
The problem is in operator precedence. Since in this line
var id = "loopBlock" + i + 1;
you have two + (unary plus) operators with the same precedence they will act as a string concatenation operators, because one of the operands is a string ("loopBlock").
In your case you want to group i + 1 with parentheses to make the expression evaluate first as arithmetic addition operator. After that string concatenation with "loopBlock" will produce expected result:
var id = "loopBlock" + (i + 1);
Demo: http://jsfiddle.net/0091n9tt/
I think you're problem in is this line:
document.getElementById(id).getElementsByTagName('div')[0].innerHTML = "bye";
What you are actually doing is trying to gett divs inside the newly created div (loopBlock), which is empty.
You already have a reference to the block you want to modify the innerHTML; you can simply use it like this:
tempLoop.innerHTML = "bye";
So you're for loop would look like this:
for (i=0; i<5; i++){
var tempLoop = loopObject();
functionCodeDiv.appendChild(tempLoop);
tempLoop.innerHTML = "bye";
}
Note that you don't need the id anymore.

Javascript no jquery - How do I add this function to existing javascript that is triggered by onload / onpaste?

This is an add-on to my previously answered question.
question 8423472
I have tried to implement a validate function to this wonderful code to no avail.
Looks like I need more hand holding here.
This script is a slightly modified version of the quite excellent answer I received from #Martin Jespersen.
The script takes a single column list of emails and breaks it up into textareas containing single row comma delimited lists of no more than 150 addresses. Nice.
Below works great but, I need to add a basic validation function.
<html>
<head>
<script language=javascript type='text/javascript'>
function onpaste(e) {
var t = this;
var cnt='0';
setTimeout(function(){
var list = document.getElementById('t');
var emails= t.value.split(/\s+/), ta;
while(emails.length) {
cnt++;
ta = document.createElement('textarea');
ta.value = emails.splice(0,150).join(',').replace(/,\s*$/,'');
document.body.appendChild(ta);
}
document.getElementById('button1').value=cnt;
},1);
}
window.onload = function() {
document.getElementById('t').onpaste = onpaste;
}
</script>
</head>
<BODY>
<p><textarea id="t" rows="10" cols="50" class="textarea"></textarea><br /></p><br />
There are <input type="button" id="button1" value="0"> textareas
<pre id="p" class="pre"></pre>
</body>
</html>
HOWEVER, the guy I made it for (actually #Martin made it) is not real meticulous about what he pastes into the textarea.
So, I am trying to implement a function that will reduce invalid emails / bad input.
I tried several ways including changing the onload event to a button in the page with onclick event.
I thought I was learning here but, I just can't wrap my brain around what I am doing wrong.
So, how can I insert this function, or just its' "validation" routine into one of the above functions?
function findEmailAddresses(StrObj) {
var separateEmailsBy = '\n';
var email = "<none>"; // if no match, use this
var emailsArray = StrObj.match(/([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi); // yeah could be better
if (emailsArray) {
email = "";
for (var i = 0; i < emailsArray.length; i++) {
if (i != 0) email += separateEmailsBy;
email += emailsArray[i];
}
}
return email;
}
Useage of findEmailAddresses function:
<textarea name=t rows=10 cols=50 onBlur="this.form.email.value=findEmailAddresses(this.value);"></textarea>
I tried calling the function individually in the functions above and even tried removing the function just inserting the code using "emails" instead of "this.value" in both cases. I even tried a two page approach. For some reason, I just can't implement this code into the working splitter. My results are either no effect or I break the thing.
Basically I tried many variations of inserting. Like below:
<html>
<head>
<script language=javascript type='text/javascript'>
function onpaste(e) {
var t = this;
var cnt='0';
setTimeout(function(){
var list = document.getElementById('t');
var emails= t.value.split(/\s+/), ta;
//
findEmailAddresses(emails);
// also tried inserting code from function. ///
while(emails.length) {
cnt++;
ta = document.createElement('textarea');
ta.value = emails.splice(0,150).join(',').replace(/,\s*$/,'');
document.body.appendChild(ta);
}
document.getElementById('button1').value=cnt;
},1);
}
window.onload = function() {
// tried to trigger it here as well and even added a new split //
document.getElementById('t').onpaste = onpaste;
}
/////
function findEmailAddresses(StrObj) {
var separateEmailsBy = '\n';
var email = "<none>"; // if no match, use this
var emailsArray = StrObj.match(/([a-zA-Z0-9._-]+#[a-zA-Z0-9._-]+\.[a-zA-Z0-9._-]+)/gi); // yeah could be better
if (emailsArray) {
email = "";
for (var i = 0; i < emailsArray.length; i++) {
if (i != 0) email += separateEmailsBy;
email += emailsArray[i];
}
}
return email;
}
////////
</script>
</head>
<BODY>
<p><textarea id="t" rows="10" cols="50" class="textarea"></textarea><br /></p><br />
There are <input type="button" id="button1" value="0"> textareas
<pre id="p" class="pre"></pre>
</body>
</html>
Much thanks to anyone who can assist.
Try putting return true; after your inline javascript.

Categories