I need to write a js function that outputs a DOM-tree by button click. The tree should be output as an unnumbered list (ul) with attachments and it's needed to use the name of the element, i.e. head, body, p, div, etc., and the element id as the text output in the list item (of course if it is specified). I thought it would work but there are some "undefined" elements but they shouldn't be here. So I don't understand what's wrong
function DOM_Tree(e) {
for (let i = 0; i < document.body.childNodes.length - 1; i++) {
if (document.body.childNodes[i].id != 'tree') {
let ul = document.getElementById('tree');
let li = document.createElement('li');
let el = document.body.childNodes[i];
let ul1 = document.createElement('ul');
if (el.hasChildNodes()) {
li.innerText = document.body.childNodes[i].id;
ul.append(li);
for (let j = 0; j < el.childNodes.length; j++) {
if (el.childNodes[j].id != undefined) {
let li1 = document.createElement('li');
li1.innerText = el.childNodes[j].id;
ul1.append(li1);
}
let li1 = document.createElement('li');
li1.innerText = el.childNodes[j].id;
ul1.append(li1);
}
ul.append(ul1);
} else {
if (document.body.childNodes[i].id != undefined) {
li.innerText = document.body.childNodes[i].id;
ul.append(li);
}
}
}
}
}
confirmButton.onclick = function() {
DOM_Tree(document.body);
alert('click');
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="container1" style="background-color: cyan;">
<h1 id="header1">Header</h1>
<p id="paragraph1">Paragraph</p>
<div id="container2" style="background-color: red;">
</div>
</div>
<ul id="tree"></ul>
<input type="text" id="formText">
<br>
<button id="confirmButton" style="margin-top: 5px;">Build a DOM tree</button>
</body>
</html>
Here's a pair of recursive functions that first builds a description of the tree as plain objects, then renders that description out into a DOM tree of UL/LI.
function describeNode(node) {
return {
id: node.id,
type: node.nodeType,
text: node.textContent,
children: [...node.childNodes].map(describeNode),
};
}
function renderDescription(d) {
const li = document.createElement("li");
if (d.type === 3) { // Text node with content
if (!d.text.trim().length) {
return null; // Empty node, don't represent
}
li.appendChild(document.createTextNode(`text: ` + d.text));
} else {
li.appendChild(document.createTextNode(`node of type ${d.type}, id ${d.id || '--'}`));
}
if (d.children && d.children.length) {
const childrenUl = document.createElement("ul");
li.appendChild(childrenUl);
d.children.map(renderDescription).forEach((c) => c && childrenUl.appendChild(c));
}
return li;
}
const descr = describeNode(document.getElementById("source"));
document.getElementById("result_json").value = JSON.stringify(descr, null, 2);
document.getElementById("result_tree").appendChild(renderDescription(descr));
<main id="source">
<div id="container1" style="background-color: cyan;">
<h1 id="header1">Header</h1>
<p id="paragraph1">Paragraph</p>
<div id="container2" style="background-color: red;">
<h2 id="header2">SubHeader</h1>
<p id="paragraph2">Sub-Paragraph</p>
<p id="paragraph3">Sub-Paragraph Two</p>
</div>
</div>
</main>
<textarea id="result_json"></textarea>
<ul id="result_tree"></ul>
You have this block of code twice:
let li1 = document.createElement('li');
li1.innerText = el.childNodes[j].id;
ul1.append(li1);
The first one is inside an if (el.childNodes[j].id != undefined), so it won't print undefined IDs. The second one is after the if, so it prints the undefined IDs.
Just removing the second block gets rid of undefined bullets.
If you want the input to specify the ID to start from, use document.getElementById() in the onclick function. Then change DOM_Tree to use e instead of document.body as its starting element.
function DOM_Tree(e) {
for (let i = 0; i < e.childNodes.length - 1; i++) {
if (e.childNodes[i].id != 'tree') {
let ul = document.getElementById('tree');
let li = document.createElement('li');
let el = e.childNodes[i];
let ul1 = document.createElement('ul');
if (el.hasChildNodes()) {
li.innerText = e.childNodes[i].id;
ul.append(li);
for (let j = 0; j < el.childNodes.length; j++) {
if (el.childNodes[j].id != undefined) {
let li1 = document.createElement('li');
li1.innerText = el.childNodes[j].id;
ul1.append(li1);
}
}
ul.append(ul1);
} else {
if (e.childNodes[i].id != undefined) {
li.innerText = e.childNodes[i].id;
ul.append(li);
}
}
}
}
}
confirmButton.onclick = function() {
let target = document.body; // default target
let id = document.getElementById("formText").value;
if (id) {
target = document.getElementById(id);
if (!target) {
alert(`ID ${id} not found`);
return;
}
}
DOM_Tree(target);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div id="container1" style="background-color: cyan;">
<h1 id="header1">Header</h1>
<p id="paragraph1">Paragraph</p>
<div id="container2" style="background-color: red;">
</div>
</div>
<ul id="tree"></ul>
<input type="text" id="formText" placeholder="ID to start at, default = document.body">
<br>
<button id="confirmButton" style="margin-top: 5px;">Build a DOM tree</button>
</body>
</html>
Related
I'm trying to make a very basic expense tracker by building off the foundation of a todo app with vanilla Javascript. I'm having trouble isolating the value of all three input bars and getting them to display on the page. At the moment I'm getting 3 [objectHTMLInputElement] and undefined. I'd just like to know if I'm on the right track or if there's an easier way to isolate multiple input values and get them to display on the page. If somebody could point me in the right direction that'd be awesome. Thanks!
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
let inputName = document.getElementById('input-name');
let inputDate = document.getElementById('input-date');
let inputAmount = document.getElementById('input-amount');
let inputAll = document.querySelectorAll('.input-all');
let expenses = [
]
function add() {
let inputs = inputAll.value;
if (inputs == '') {
return true;
}
expenses.push(inputs);
displayExpenses();
}
function remove() {
}
function displayExpenses() {
let expensesUl = document.getElementById('expenses-ul');
expensesUl.innerHTML = `${inputName}${inputDate}${inputAmount}`;
for (var i = 0; i < expenses.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = expenses[i];
expensesUl.appendChild(expensesLi);
}
}
* {
padding: 0;
box-sizing: border-box;
}
.headings {
text-align: center;
}
.headings h1 {
font-size: 3rem;
font-family: 'Courier New', Courier, monospace;
}
.headings h2 {
margin-top: -20px;
}
form {
text-align: center;
}
#input-name {
width: 50%;
}
#input-date {
width: 18%;
margin-right: 160px;
}
#input-amount {
width: 18%;
margin-left: 18px;
}
#add-btn {
margin-top: 50px;
margin-left: 800px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Expense Tracker</title>
</head>
<body>
<div class="headings">
<h1>Expense Tracker</h1>
<h2>Add A New Item</h2>
</div>
<form>
<label>Name:</label>
<input class="input-all" id="input-name">
<br>
<br>
<label>Date:</label>
<input class="input-all" id="input-date">
<label>Amount:</label>
<input class="input-all" id="input-amount">
</form>
<button id="add-btn">Add Expense</button>
<ul id="expenses-ul"></ul>
<script src="main.js"></script>
</body>
</html>
Try this
const btn = document.getElementById('btn');
btn.addEventListener('click', function (event) {
const form = document.getElementById('form');
const output = document.getElementById('output');
const data = Object.fromEntries(new FormData(form).entries());
output.innerHTML = JSON.stringify(data, undefined, 2);
});
.wrap{
display: flex;
}
#output{
margin-left:50px;
border-width:3px;
border-style:dashed;
border-color:#FFAC55;
padding:5px;
min-width: 150px;
min-height: 80px;
}
<div class="wrap">
<div>
<form id="form">
<label for="name">Name:</label><br>
<input type="text" id="name" name="name"><br>
<label for="date">Date:</label><br>
<input type="text" id="role" name="role"> <br>
<label for="lname">Amount:</label><br>
<input type="text" id="amount" name="amount"><br><br>
<input id="btn" type="button" value="Print all value">
</form>
</div>
<div>
<pre id="output">
</pre>
</div>
</div>
When using document.querySelectorAll it's return a [NodeList] that consists of all selected elements on the other side there's also document.getElementsByClassName that return [HTMLCollection] - whatever you used you need to loop through to get the value of every selected input
When you passed [HTMLInputElement] as innerHTML of expensesUl it's will return the element object name not the value of this element because you are not selected any property of this object so you can't set an object as innerHTML of html element
if you want the right way of this part it's will be like that
let inputName = document.getElementById('input-name');
let inputDate = document.getElementById('input-date');
let inputAmount = document.getElementById('input-amount');
let expensesUl = document.getElementById('expenses-ul');
//this will give you empty string because they aren't get a value yet
expensesUl.innerHTML = `name = ${inputName.value}, date = ${inputDate.value}, amoute = ${inputAmount.value}`;
but now because we are selected all elements we are not need to select every input one by one anymore we will make a loop so we will loop through inputAll var to get the value of [HTMLInputElement] object
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
function add() {
let inputAll = document.querySelectorAll('.input-all');
for(var i of inputAll) {
if (i.value == '') {
return "Sorry you need to fill all inputs"
}
}
displayExpenses(inputAll);
}
function displayExpenses(elements) {
let expensesUl = document.getElementById('expenses-ul');
for (var i = 0; i < elements.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = elements[i].value
expensesUl.appendChild(expensesLi);
}
}
at the example above i removed expenses array but if you want to use it to take the value of the inputs you can make it like that
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
function add() {
let inputAll = document.querySelectorAll('.input-all');
let expenses = []
for(var i of inputAll) {
if (i.value == '') {
return "Sorry you need to fill all inputs"
}
expenses.push(i.value)
}
displayExpenses(expenses);
}
function displayExpenses(values) {
let expensesUl = document.getElementById('expenses-ul');
for (var i = 0; i < values.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = values[i]
expensesUl.appendChild(expensesLi);
}
}
the whole code should to be like that
let addButton = document.getElementById('add-btn');
addButton.addEventListener('click', add);
let inputName = document.getElementById('input-name');
let inputDate = document.getElementById('input-date');
let inputAmount = document.getElementById('input-amount');
let inputAll = document.querySelectorAll('.input-all');
let expenses = []
function add() {
for(var i of inputAll) {
if (i.value == '') {
return true
}
expenses.push(i.value)
}
displayExpenses();
}
function displayExpenses() {
let expensesUl = document.getElementById('expenses-ul');
expensesUl.innerHTML = `${inputName.value}, ${inputDate.value}, ${inputAmount.value}`;
for (var i = 0; i < expenses.length; i++) {
let expensesLi = document.createElement('li');
expensesLi.innerHTML = expenses[i];
expensesUl.appendChild(expensesLi);
}
}
about document.getElementsByClassName, document.querySelectorAll one deferant is that you can use array methods like forEach() with document.querySelectorAll while you can't do that with document.getElementsByClassName
I have a <div> element that contains both html elements and text. I want to find/remove the last or the last nth or the nth text only portion of it.
So for example
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I had a method to delete the last text character, the first call would delete z and the second call would delete g. Or if I had a method to find the 4th character, it would return d.
It sounds like you only care about the text nodes, so probably something like this so you can just delete the nth character:
var div = document.getElementById("foo");
const getTextNodes = (el, nodes) => {
nodes = nodes || [];
for (var i = 0; i < el.childNodes.length; i++) {
var curNode = el.childNodes[i];
if (curNode.nodeName === "#text") {
if (curNode.textContent.trim().length) {
nodes.push(curNode);
}
} else {
getTextNodes(curNode, nodes);
}
}
return nodes;
}
console.log(getTextNodes(div).map((el) => el.textContent));
const deleteNthCharacter = (el, n) => {
n--; // since we want to be "1 indexed"
const nodes = getTextNodes(el);
let len = 0;
for (let i = 0; i < nodes.length; i++) {
const curNode = nodes[i];
if (len + curNode.textContent.length > n) {
curNode.textContent = curNode.textContent.substring(0, n - len) + curNode.textContent.substring(n + 1 - len);
break;
} else {
len += curNode.textContent.length;
}
}
}
deleteNthCharacter(div, 2);
deleteNthCharacter(div, 7);
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I understood your question correctly this should do the trick:
function deleteLastChar(targetId){
const target = document.getElementById(targetId);
let lastWithText = -1;
//find last child that has text set
target.childNodes.forEach((child, iter) => {
if(child.innerText != undefined && child.innerText.length > 0){
lastWithText = iter;
}
});
// exit if no valid text node was found
if(lastWithText === -1)
return;
const lastNode = target.childNodes[lastWithText];
lastNode.innerText = lastNode.innerText.slice(0, -1);
}
deleteLastChar("foo")
deleteLastChar("foo")
deleteLastChar("foo")
deleteLastChar("foo")
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
If I understand the question this is probably what you're looking for
let x = document.getElementById('foo').children;
function erase() {
for (let i = x.length - 1; i >=0; i--) {
if(x[i].textContent.length > 0) {
const textC = x[i].textContent;
x[i].textContent = textC.substring(0, textC.length - 1);
return;
}
}
}
<div id="foo">
<span id="bar">abcdefg</span>
<span id="baz">z</span>
</div>
<button onclick="erase()">Erase</button>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="foo">
<span id="bar">abcdefg</span><br>
<span id="baz">z</span><br><br>
<div id="result"></div>
<div id="result2"></div>
</div>
<script type="text/javascript">
var s = function(x){
return document.querySelector(x)
}
log = console.log;
var span1 = s("#bar")
var span2 = s("#baz")
var result = s("#result")
var result2 = s("#result2")
var res = span1.innerText.charAt(4)
// with the charAt method
result.innerText = " Result is : " +res+"\n\n"
// with regular Expression
var reg = /e/
result2.innerText = " Result2 is : " +span1.innerText.match(reg)
</script>
</body>
</html>
I have this simple function that will create a paragraph.
function appendElements() {
const input = document.getElementById("myInput");
const createDiv = document.createElement("div");
createDiv.classList.add("myDiv");
const createP = document.createElement("P");
createP.classList.add("myParagraph");
createP.innerHTML = input.value;
createDiv.appendChild(createP);
const div = document.getElementById("examplediv");
div.appendChild(createDiv);
}
And another function that will sum the innerHTML of the divs, and create a div element for the result.
function calculateSum() {
let div = document.getElementsByClassName("myParagraph");
let array = new Array;
for (var i = 0; i <div.length; i++) {
array.push(div[i].innerHTML);
}
let numberedArray = array.map((i) => Number(i));
const sumArray = numberedArray.reduce(function(a, b){
return a + b;
}, 0);
const createElement = document.createElement("div");
createElement.innerHTML = sumArray;
document.getElementById("divForAvg").appendChild(createElement);
}
And the last function that will change the innerHTML of the paragraph element when clicked.
function editELement() {
const input2 = document.getElementById("myInput2")
let items = document.getElementsByClassName("myParagraph");
for(var i = 0; i < items.length; i++){
items[i].onclick = function(){
items[i].innerHTML = input2.value;
}
}
}
So basically when I create some paragraphs and execute the second function, the second function will calculate the sum of the paragraphs and create a div with the sum inside.
What I want is when I remove one of the paragraph elements or edit them, I want the previously created divs to update(recalculate the sum), I have literally no idea on how to do this.
Let's try this using event delegation. I have interpreted what I think you are looking for (note: it's exemplary, but it may give you an idea for your code) and reduced your code a bit for the example. Note the 2 different ways to create new elements (insertAdjacentHTML and Object.assign).
You can play with the code #Stackblitz.com.
document.addEventListener("click", handle);
function handle(evt) {
if (evt.target.id === "create") {
return appendInputValueElement();
}
if (evt.target.classList.contains("remove")) {
return removeThis(evt.target);
}
if (evt.target.id === "clear") {
document.querySelector("#accumulated ul").innerHTML = "";
return true;
}
}
function appendInputValueElement() {
const input = document.querySelector(".myInput");
const div = document.querySelector("#exampleDiv");
exampleDiv.insertAdjacentHTML("beforeEnd", `
<div class="myDiv">
<button class="remove">remove</button>
<span class="myParagraph">${input.value || 0}</span>
</div>
`);
calculateSum();
}
function removeThis(elem) {
elem.closest(".myDiv").remove();
calculateSum();
}
function calculateSum() {
const allParas = [...document.querySelectorAll(".myParagraph")];
const sum = allParas.reduce( (acc, val) => acc + +val.textContent, 0);
document.querySelector("#accumulated ul")
.append(Object.assign(document.createElement("li"), {textContent: sum}));
document.querySelector(".currentSum").dataset.currentSum = sum;
if (sum < 1) {
document.querySelector("#accumulated ul").innerHTML = "";
}
}
.currentSum::after {
content: ' 'attr(data-current-sum);
color: green;
font-weight: bold;
}
.myParagraph {
color: red;
}
.accSums, .currentSum, .myDiv {
margin-top: 0.3rem;
}
<div>
A number please: <input class="myInput" type="number" value="12">
<button id="create">create value</button>
</div>
<div class="currentSum" data-current-sum="0">*Current sum</div>
<p id="exampleDiv"></p>
<div id="accumulated">
<div class="accSums">*Accumulated sums</div>
<ul></ul>
<button id="clear">Clear accumulated</button>
</div>
i've changed calculateSum you can call it when you edited paragraph. If summParagraph doesn't exists then we create it.
function calculateSum() {
let div = document.getElementsByClassName("myParagraph");
let array = new Array;
for (var i = 0; i <div.length; i++) {
array.push(div[i].innerHTML);
}
let numberedArray = array.map((i) => Number(i));
const sumArray = numberedArray.reduce(function(a, b){
return a + b;
}, 0);
if (!document.getElementById("summParagraph")) {
const createElement = document.createElement("div");
createElement.setAttribute("id", "summParagraph");
document.getElementById("divForAvg").appendChild(createElement);
}
document.getElementById("summParagraph").innerHTML = summArray;
}
In my electron app I want to toggle between different screens, thus I need to use block and none displays.
I have a side navbar which contain the anchor tags, whenever I click one of those I want my screen to block all the other screens and display the one which was clicked.
Required Code Below
Side NavBar -not attaching the css for it
<div class="sidebar">
Home
Tasks
TimeTable
Quick notes
Expenses
</div>
Different Displays
<div id="home" class="screen" style="display: none">
<h1 class="centertitle">Home</h1>
</div>
<div id="tasks" class="screen" style="display: none">
<h1 class="centertitle">Tasks</h1>
</div>
Script
<script>
function showtasks() {
let task = document.getElementById("tasks");
let taskbtn = document.getElementById("taskbtn");
let allnav = document.getElementsByClassName("nava");
let allscreens = document.getElementsByClassName("screen");
allscreens.style.display = "none";
task.style.display = "block";
allnav.className = "";
taskbtn.className = "active";
}
function showhome() {
let home = document.getElementById("home");
let homebtn = document.getElementById("homebtn");
let allnav = document.getElementsByClassName("nava");
let allscreens = document.getElementsByClassName("screen");
allscreens.style.display = "none";
home.style.display = "block";
allnav.className = "";
homebtn.className = "active";
}
</script>
The problem here is the allscreens variable.
getElementsByClassName returns an array of elements with the given class name. So in order to set them all to display: none, you will need to loop through the elements.
let allscreens = document.getElementsByClassName("screen");
for (var i = 0; i < allscreens.length; i++) {
allscreens[i].style.display = "none";
}
function showtasks() {
let task = document.getElementById("tasks");
let taskbtn = document.getElementById("taskbtn");
let allnav = document.getElementsByClassName("nava");
let allscreens = document.getElementsByClassName("screen");
for (var i = 0; i < allscreens.length; i++ ) {
allscreens[i].style.display = "none";
}
task.style.display = "block";
allnav.className = "";
taskbtn.className = "active";
}
function showhome() {
let home = document.getElementById("home");
let homebtn = document.getElementById("homebtn");
let allnav = document.getElementsByClassName("nava");
let allscreens = document.getElementsByClassName("screen");
for (var i = 0; i < allscreens.length; i++ ) {
allscreens[i].style.display = "none";
}
home.style.display = "block";
allnav.className = "";
homebtn.className = "active";
}
<div class="sidebar">
Home
Tasks
TimeTable
Quick notes
Expenses
</div>
<div id="home" class="screen" style="display: none">
<h1 class="centertitle">Home</h1>
</div>
<div id="tasks" class="screen" style="display: none">
<h1 class="centertitle">Tasks</h1>
</div>
My code can be found here: https://www.w3schools.com/code/tryit.asp?filename=FHC2UOT0RQX6
The program accepts an array var array=[1,0,1,0,1,1,0,0,0] and solves the pseudoternary encoding scheme. All i want to do is simple. Insead of changing the elements of the array(when i want to insert a different input), i want to use the input text and take the values from it and when i press enter or the submit button, it will solve the problem depending on the user inputs. Is that possible to take the values of the text input and make them act as an array ?
Here is the script below but it is better to see the whole code, use the link above.
<script type="text/javascript">
var array=[1,0,1,0,1,1,0,0,0]; //input here
var text="";
for(var b=0;b<array.length;b++)
{
text+=array[b];
}
document.getElementById('enc').innerHTML=text;
pseudo(array);
function pseudo(a) //function pseudo
{
var pulse = false;
var count = 0;
for(var b=0;b<array.length;b++)
if(a[b]===1)
{
count++;
document.write('<img src="http://i.imgur.com/30DU9iC.png">');
}
else if(a[b]===0)
{
count++;
pulse=!pulse; //toggles boolean value each time it finds zero
if(pulse===true) //pulse shows up
{
document.write('<img src="http://i.imgur.com/Ghtajy7.png">');
}
else{
document.write('<img class="down" src="http://i.imgur.com/uObQjTA.png">');
}
}
}
</script>
Actually you want to write your code inside a function and call the function onload and onclick respectively. Try this, http://www.w3schools.com/code/tryit.asp?filename=FALV2XZQ7V36
var array = [1, 0, 1, 0, 1, 1, 0, 0, 0]; //input here
var text = "";
function loading() {
for (var b = 0; b < array.length; b++) {
text += array[b];
}
document.getElementById('enc').innerHTML = text;
pseudo(array);
}
function pseudo(a) //function pseudo
{
var pulse = false;
var count = 0;
var output = '';
var b = 0;
for (b = 0; b < a.length; b++)
if (a[b] === 1) {
count++;
//document.write('<p class="w3-center w3-text-red">'+'Step '+count+': No line'+'<br>'+'</p>');
//document.write('<img src="http://i.imgur.com/30DU9iC.png">');
output += '<img src="http://i.imgur.com/30DU9iC.png">';
} else if (a[b] === 0) {
count++;
pulse = !pulse; //toggles boolean value each time it finds zero
if (pulse === true) //pulse shows up
{
//document.write('<p class="w3-center w3-text-red">'+'Step: '+count+' goes up'+'<br>'+'</p>');
//document.write('<img src="http://i.imgur.com/Ghtajy7.png">');
output += '<img src="http://i.imgur.com/Ghtajy7.png">';
} else {
// document.write('<p class="w3-center w3-text-red">'+'Step: '+count+' goes down'+'<br>'+'</p>');
//document.write('<img class="down" src="http://i.imgur.com/uObQjTA.png">');
output += '<img class="down" src="http://i.imgur.com/uObQjTA.png">';
}
}
document.getElementById("js").innerHTML = output;
}
function gettext() {
var inputText = document.getElementById("tf").value;
var inparray = [inputText.length];
for (i in inputText) {
inparray[i] = parseInt(inputText[i]);
}
document.getElementById('enc').innerHTML = inputText;
pseudo(inparray);
}
body {} .pad {
padding-top: 20%;
}
.inline {
display: inline;
}
.down {
margin: 0 -2 -65 -3;
}
<html>
<head>
<title>Pseudoternary Encoding</title>
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<!-- <link rel="stylesheet" href="style.css" type="text/css"/>-->
<h4>Use this input </h4>
<input type="text" id="tf"></input>
<input type="button" style="width:50px;" value="solve" onclick="gettext()" id="tf"></input>
</head>
<body onload="loading()" ;>
<h1>Illustration of pseudoternary encoding scheme </h1>
<h1 class="pad w3-center">Encode <span id="enc" class="w3-text-red"> </span></h1>
<div id="js" class="w3-center">
</div>
</body>
</html>
Note, <input> element is self-closing. <input> element should be child nodes of <body> element instead of <head> element. id of element in document should be unique. Replace duplicate "tf" id at input elements with unique values. Remove <script> element from being child node of div element. Place <script> element before closing </body> tag. Substitute concatenating .innerHTML for document.write()
Attach click event to input type="button", use String.prototype.split() with parameter "" to create an array from input type="text" .value, Array.prototype.map() with parameter Number to convert String to Number values. Assign resulting array to array variable. Set #js .innerHTML to empty string before calling function again with array as parameter.
<!DOCTYPE html>
<html>
<head>
<style>
body {}
.pad {
padding-top: 20%;
}
.inline {
display: inline;
}
.down {
margin: 0 -2 -65 -3;
}
</style>
<title>Pseudoternary Encoding</title>
<link rel="stylesheet" href="http://www.w3schools.com/lib/w3.css">
<link rel="stylesheet" href="style.css" type="text/css" />
</head>
<body>
<h4 style="margin-top:240px;position:absolute">Use this input </h4>
<h1>Illustration of pseudoternary encoding scheme </h1>
<input type="text" style="position:relative" id="tf">
<input type="button" style="position:relative;width:50px;" value="solve" id="button">
<h1 class="pad w3-center">Encode <span id="enc" class="w3-text-red"> </span></h1>
<div id="js" class="w3-center"> </div>
<script>
var array = [1, 0, 1, 0, 1, 1, 0, 0, 0]; //input here
var text = "";
var enc = document.getElementById("enc");
var button = document.getElementById("button");
var tf = document.getElementById("tf");
var center = document.getElementById("js");
for (var b = 0; b < array.length; b++) {
text += array[b];
}
enc.innerHTML = text;
pseudo(array);
function pseudo(a) {
var pulse = false;
var count = 0;
for (var b = 0; b < array.length; b++)
if (a[b] === 1) {
count++;
center.innerHTML += '<img src="http://i.imgur.com/30DU9iC.png">';
} else if (a[b] === 0) {
count++;
pulse = !pulse; //toggles boolean value each time it finds zero
if (pulse === true) //pulse shows up
{
center.innerHTML += '<img src="http://i.imgur.com/Ghtajy7.png">';
} else {
center.innerHTML += '<img class="down" src="http://i.imgur.com/uObQjTA.png">';
}
}
}
button.onclick = function() {
array = tf.value.split("").map(Number);
enc.innerHTML = array.join("");
console.log(array, enc);
center.innerHTML = "";
pseudo(array)
}
</script>
</body>
</html>