How can I pass a variable from a JS input to HTML? - javascript

I'm taking an input from a user in javascript and using it to display that number of pages. Basically, I ask the user how many items they have. If they say, for example, 4, I need to ask them the name of each item on the next page. Then, on the next 4 pages, they are to input the value of each item one per page and finally, I will display a table of the items, values, and final sum. My question is:
After obtaining the number of items in my javascript file, how do I pass it back to my HTML file? Should I even be passing it back to my HTML file?
When I have the number of items, how do I open that many new files/pages for javascript and HTML based on it? Or can I do it all on one js file? I know it's quite redundant to open a new HTML and JS file for each item but I don't know how to clear the page each time after a button click and display a new input box on the same file.
Sorry if this is a really stupid question, just a confused begginer here. Thank you!
Here's what I have so far:
index.html:
<body>
<h1>Welcome!</h1>
<h2>Ready to track your items?</h2>
<p><button>Start</button></p>
</body>
items.html:
<body>
<h3>How many items do you have?</h3>
<p><input id="numItems"></p>
<script src="main.js"></script>
</body>
main.js:
var numIt = document.getElementById("numItems");
numIt.addEventListener("input", display);
function display(){
var item = parseFloat(numIt.value);
alert("you have " + item+" items");
}

I am not 100% sure, but guess You need to dynamically generate N number of inputs to have users fill in names of each item. As mentioned opening new or creating new html files would not be the best solution, also it can't be done with browser javascript.
So instead why not generate input elements and append them to the DOM, for more info please see DOM w3schools
Small example.
function display(){
var item = parseFloat(numIt.value);
for(var i =0; i<item;i++){
var inpElem = document.createElement("input");
inpElem.setAttribute("name", "item"+i);
inpElem.setAttribute("placeholder", "Input name of the item #"+i);
document.body.appendChild(inpElem);
}
}
Let's say user inputs 2. It will generate
<input placeholder="Input name of the item #1" name="item1" >
<input placeholder="Input name of the item #2" name="item2" >
Also to empty the body - document.body.innerHTML = ""

Probably you can use "pages" (hide all elements except one)
There is an example, you can check it out
const pages = ["page1", "page2", "page3"]
showPage(0)
function hidePages() {
for(const page of pages)
changeElementVisibility(page, false)
}
function showPage(num) {
hidePages()
const pageId = pages[num]
changeElementVisibility(pageId, true)
}
function changeElementVisibility(id, visible) {
document.getElementById(id).style.display = visible ? "" : "none"
}
function secondPageSumbit() {
const itemsCount = document.getElementById("itemsCount").value
document.getElementById("result").innerText = "Items Count: " + itemsCount
}
<head>
<script src="main.js"></script>
</head>
<body>
<div id="page1">
<h1>Welcome!</h1>
<h2>Ready to track your items?</h2>
<p><button onclick="showPage(1)">Start</button></p>
</div>
<div id="page2">
<h3>How many items do you have?</h3>
<p><input id="itemsCount"></p>
<p><button onclick="secondPageSumbit();showPage(2)">Next</button></p>
</div>
<div id="page3">
<h3>Result</h3>
<p id="result"></p>
</div>
</body>

Related

Program is treating the same string differently when entered into a different text box

I have a program that is supposed to group links together. Like minecraft saved toolbars, you can save a collection of links, then enter in the name of a group and it will open all of them.
But my program is having trouble with getting the list from localStorage when the name is entered into the text box meant to get the link. But when I just use the value of the text box meant to name the group, it works fine.
My code is here:
var groupName = document.getElementById('name');
var link = document.getElementById('newLink');
var linkCounter = 0
var getByName = document.getElementById('getByName').value
function startGroup() {
localStorage.setItem(groupName.value, groupName.value);
console.log(localStorage.getItem(groupName.value))
}
function addLink() {
linkCounter++;
localStorage.setItem(groupName.value + '_link' + linkCounter, link.value);
console.log(localStorage.getItem(groupName.value + '_link' + linkCounter))
}
function saveGroup() {
localStorage.setItem(groupName.value + '_length', linkCounter);
console.log(localStorage.getItem(groupName.value + '_length'))
alert(groupName.value);
}
function getGroup() {
// if I replace getByName with groupName.value, it works fine.
var len = localStorage.getItem(getByName + '_length')
console.log(len)
for (var x = 1; x <= len; x++) {
window.open(localStorage.getItem(getByName + '_link' + x));
}
}
<!DOCTYPE html>
<html>
<a href='readit.html'>READ THIS BEFORE USING</a>
<p>WHEN ADDING A LINK YOU NEED TO PASTE IT OR ADD HTTPS:// TO THE BEGINNING OF THE LINK.</p>
<div id='toolbars'>
<p>Open a group!</p>
</div>
<div id='create'>
<p>Create some bookmark groups!</p>
<input type='text' placeholder='name your group' id='name'>
<button onclick='startGroup()'>Let's add some links!</button>
<br>
<input type='text' placeholder='add a link' id='newLink'>
<button onclick='addLink()'>Submit</button>
<br>
<button onclick='saveGroup()'>SAVE</button>
</div>
<div id='preview'>
<br><br>
<button onclick='getGroup()'>Open this group</button>
<input type="text" id="getByName">
</div>
</html>
<script src="script.js"></script>
You are reading the value of the getByName input element at page load. Instead you should read the value at the time of need. So define getByName as the DOM element (not as its value):
var getByName = document.getElementById('getByName');
And where you currently reference getByName, suffix the .value property accessor. For instance:
var len = localStorage.getItem(getByName.value + '_length');
Side note: I find it easier to use a memory data structure for all your data, and when something is added to it, to write that complete data structure to one single local storage key, JSON formatted. You may want to look into that.

Replace input value by variable and

I'm trying to make a sort of questionnaire/quiz in javascript for my website. The questionnaire is spread on 5 pages, each page has a question. I want to use the GET method so the URL of each page looks something like that:
(I must keep the GET method because I want to use for something else).
First question: http://website.com/quiz/first?q=1
Second question: http://website.com/quiz/second?q=133
Third question: http://website.com/quiz/third?q=133
Fourth question: http://website.com/quiz/fourth?q=1332
Fifth question: http://website.com/quiz/fifth?q=13324
The user lands on the first page --> get a radio input form --> checks one --> gets redirected to the second page --> etc...
The ?q= is a variable containing the answers, for example ?q=133 means the user picked the following answers:
In the first question, he checked the radio input of the value 1
In the second question, he checked the radio input of the value 3
In the third question, he checked the radio input of the value 3
(so 133 means the user check the 1 for the first question, 3 for the second, 3 for the third.)
I managed to make the variables work:
answPre: gets the previous answer from the form GET (?q=1).
answCurrent: gets the radio input checked from the current page.
urlVal: an combination of the two (answPre+answCurrent)
so I'd like urlVal to be the value that gets transferred from a page to the other.
But I don't want to have both urlVal and the "q" value (name of checked radio) in the url.
What's the right thing to do?
can I hide the "q" value from the URL?
or can I "overwrite" the q value and put instead urlVal?
I'm lost and would appreciate any help, thanks for your help and your time!
function displayRadioValue() {
// var pageURL = window.location.href;
var fakeURL="website.com/quiz/first?q=1"
var answPre = fakeURL.substr(fakeURL.lastIndexOf('=') + 1); //get the previous page's answer.
//get the current page's answer
var ele = document.getElementsByName('q');
for(j = 0; j < ele.length; j++) {
if(ele[j].checked)
var answCurrent= document.getElementById("demo2").innerHTML = ele[j].value;
}
var array = [answPre,answCurrent]; //combine answPre + answNew
var urlVal = "";
var i;
for (i = 0; i < array.length; i++) {
urlVal += array[i];
}
document.getElementById("demo1").innerHTML = answPre;
document.getElementById("demo3").innerHTML = urlVal;
//document.getElementById("fquiz").submit();// Form submission
}
<html>
<body>
<h2>second.html</h2>
<b>answPre: </b><span id="demo1"></span><br>
<b>answCurrent: </b><span id="demo2"></span><br>
<b>urlVal: </b><span id="demo3"></span><br>
<!-- <b>final answNew: </b><span id="demo4"></span><br> -->
<hr>
<form id="fquiz" method="GET" action="third.html">
<p>Who are you going with?</p>
<input type="radio" name="q" value="1" id="yes"
onClick="javascript: displayRadioValue()">Solo<br>
<input type="radio" name="q" value="2" id="no"
onClick="javascript: displayRadioValue()">Couple<br>
<input type="radio" name="q" value="3" id="no"
onClick="javascript: displayRadioValue()">Family with kids<br>
<input type="radio" name="q" value="4" id="no"
onClick="javascript: displayRadioValue()">Group of friends<br>
<p>(then it takes you to third.html with hopefully this url: ../third.html?q=XX where XX is urlVal)
</form>
</body>
</html>
I've made a few changes to your code to modernize it a bit.
I moved the binding of the event handlers to the JavaScript from the HTML. Generally speaking I like to keep my HTML about the structure and the JavaScript about the behavior.
I added code to grab the step from the URL in addition to the previous answers.
I used querySelector to retrieve the selected radio button, using the :checked pseudo-selector.
I used join('') on the array of answers to make it easier to read.
In the HTML, I used <p> elements for everything that needed to be in one line, rather than tacking a <br> at the end of each line. That's just a personal preference.
I wrapped the radio buttons and their text in <label> elements. This helps in accessibility and to give a larger target for people to click on (clicking on the entire label checks the radio, rather than just the radio itself).
I also changed the name of the URL parameter to urlVal rather than q, but I'm not sure I understood that part of your question. I'm not using the form submission process at all with this code, relying instead on changing the location directly...
Do note that running the code here on Stack Overflow won't redirect correctly, since of course there's nothing at example.com/quiz/second listening, and Stack Snippets are sandboxed anyway. You'll need to adjust the code for your specific use in any case.
// Use JavaScript to attach event handlers to HTML elements.
document.querySelectorAll('input[name="q"]').forEach(el => el.addEventListener('click', displayRadioValue));
function displayRadioValue() {
// var pageURL = window.location.href;
var fakeURL = "example.com/quiz/first?q=1"
var step = fakeURL.substring(fakeURL.lastIndexOf('/') + 1, fakeURL.indexOf('?'));
var answPre = fakeURL.substr(fakeURL.lastIndexOf('=') + 1); //get the previous page's answer.
//get the current page's answer
// The :checked pseudo-class makes it easier to find the checked radio button
var el = document.querySelector('input[name="q"]:checked');
var answCurrent = document.getElementById("demo2").innerHTML = el.value;
var array = [answPre, answCurrent]; //combine answPre + answNew
// The join method is easier to use than looping.
var urlVal = array.join('');
document.getElementById("demo1").innerHTML = answPre;
document.getElementById("demo3").innerHTML = urlVal;
switch (step) {
case 'first': step = 'second'; break;
case 'second': step = 'third'; break;
case 'third': step = 'final'; break;
default: return;
}
location.href = `example.com/quix/${step}?urlVal=${urlVal}`;
}
.form-group { margin: 0; }
<h2>second.html</h2>
<!-- <br> is a presentational element; better just to split up lines with paragraphs -->
<p class="form-group"><b>answPre: </b><span id="demo1"></span></p>
<p class="form-group"><b>answCurrent: </b><span id="demo2"></span></p>
<p class="form-group"><b>urlVal: </b><span id="demo3"></span></p>
<!-- <p class="form-group"><b>final answNew: </b><span id="demo4"></span></p> -->
<hr>
<form id="fquiz" method="GET" action="third.html">
<p>Who are you going with?</p>
<!-- <br> is a presentational element; better just to split up lines with paragraphs -->
<!-- Always use <label> elements to label form fields -->
<!-- IDs must be unique to a document. They did not appear relevant here. -->
<p class="form-group"><label><input type="radio" name="q" value="1">Solo</label></p>
<p class="form-group"><label><input type="radio" name="q" value="2">Couple</label></p>
<p class="form-group"><label><input type="radio" name="q" value="3">Family with kids</label></p>
<p class="form-group"><label><input type="radio" name="q" value="4">Group of friends</label></p>
<p>(then it takes you to third.html with hopefully this url: ../third.html?q=XX where XX is urlVal)</p>
</form>

javascript & html - creating new checkbox option everytime user enters item in textbox

So basically I'm creating a program that allows the user to create and manage a ‘to-do list’. This will allow the user to add new items, remove selected items, highlight/un-highlight selected items, and sort the items, etc. I'm currently working on the add button, but I'm extremely confused with different functions in HTML and code that will allow me to manipulate the DOM.
When the user clicks the add button and the item name is valid, a new item should be added to the page’s to-do list (which esentially creates a new checkbox for every item the user adds). The checkbox is basically so the item can be selected/deselected, as well as the text that was in the item name textbox when the add button was clicked.
I guess I have two problems right now. I'm trying to verify that the item name is at least 1 character long. I wrote code in my "addHandler.js" file but when I write nothing in the textbox and click on the add button on my HTML browser, no error message pops up. I don't know why it's ignoring my function. Another thing I'm struggling with is the part that creates a new checkbox for every valid item that is added. I know how to create a checkbox on my HTML page, but I don't understand how to get my program to create a new one per item that the user inputs.
Any help or push in the right direction would be appreciated. I'm also new to HTML and javascript, so explaining stuff in simple terms would also make me really grateful.
todo.html code:
<html>
<head>
<title>Checklist</title>
</head>
<body>
<div><h1>My to-do list</h1></div><br />
<div id ="myCheckList">Enter an item:</div>
<div>Type something: <input type="text" id="textbox"></input></div>
<button type="button" id="addBut">Add item</button>
<button type="button" id="removeBut">Remove items</button>
<button type="button" id="toggleBut">Toggle highlight</button>
<button type="button" id="sortBut">Sort items</button>
<script src="addHandler.js"></script>
</body>
</html>
addHandler.js code:
function init(){
let button = document.getElementById("addBut");
button.onclick = buttonClicked;
let tb = document.getElementById("textbox");
tb.onblur = validate;
}
function add(){
let someEle = document.getElementById("myCheckList");
someEle.innerHTML = 'You added an item';
}
function validate(){
if(document.getElementById("textbox").value.length == 0){
alert("You need to enter something");
}
}
You should have a wrapper that contains your checkbox items that you can append new elements to.
<div id="checklist_items"></div>
Then you can use the following function to create a new div that contains a checkbox and the entered text, and then append it to your checklist:
function addItem() {
var input = document.getElementById("textbox");
var wrapper = document.getElementById("checklist_items");
if(input.value.trim() != "") {
var new_element = document.createElement("DIV");
new_element.innerHTML = '<input type="checkbox"> '+input.value;
wrapper.appendChild(new_element);
}
else {
alert("You must enter at least 1 character.");
}
}
I would also use the following to add the function to your button:
document.getElementById("addBut").addEventListener("click", addItem);

multiple div with same template

I have a 'users page'. I would like to give a textbox for entering the no. of users. On click of submit 'n' no of user forms need to be presented to user.
User1
first name -
last name -
User2
first name -
last name -
.
.
.
UserN
first name -
last name -
I don't know the value of 'N' upfront. So it won't be a good idea to write multiple 'divs' in my html.
Requirement:Rather I want to have a user template div. And copy the template 'n' times depending on the value of 'n' in the textbox. But I would also want all the 'divs' to have different ids like 'user1', 'user2' etc.
I cannot figure out a way to do this apart from populating my html with too many 'divs'. Would need help achiving the Requirement specified.
Looking for a template like:-
<div id="user-template" class="hidden">
<label class="lbl"><b>Handle:</b></label><input type="text" id="first_name" value=""/>
</div>
And wanted to have id="user-template" change for all new divs.
You can try something like this:
You can make a template and append it to the DOM for the number entered in the input field.
$(document).ready(function() {
$("#createForms").click(function() {
var numOfForms = $("#numOfForms").val();
var template = $('#hidden-template').html();
for (var i = 0; i < numOfForms; i++) {
$('#targetDiv').append("<p>User" + (i + 1) + ":</p>");
$('#targetDiv').append(template);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="numOfForms"></input>
<input type="button" id="createForms" value="Get Fields"></input>
<div id="targetDiv"></div>
<script id="hidden-template" type="text/x-custom-template">
<div id="user-template" class="hidden">
<p>First Name:
<input type="text" name="firstName"></input>
</p>
<p>Last Name:
<input type="text" name="lastName"></input>
</p>
<br>
</div>
</script>
A simple way is to write a function that takes the n value and returns the actual dom that you can append to some parent element on your page. A simple example below:
function createNDivs(n) {
if(!n) return;
var fragment =document.createDocumentFragment();
for(var i=0;i<n;i++) {
var div = document.createElement('div');
fragment.appendChild(div);
}
return fragment;
}

Working with DOM and Encapsulating methods, passing arguments with Javascript OOP. How many is too many?

This is an update to my previous question and am posting the entirety of the code as is plus what I'd like to add to it. Thanks to everyone for their support so far.
Essentially I'm trying to build a queue or array that will hold Clip objects, each with three different properties: url, inpoint, and outpoint. This array will be the core of my system which will store different Youtube videos using the Youtube API so that the user can essentially edit and cue up the videos they enter into the array. This array I've called Timeline and should have the ability to push in new objects rearrange other elements etc.
Right now I'm trying to get it to just push in a new object; however, when I try to run the queue it will only display the alert that I should add something to the queue. I've been looking around and can't seem to find a very good example of how to do this so I'm beginning to wonder if my logic for tackling this problem is any good at all.
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta charset="UTF-8">
<title>Building an Array OOP - WIP</title>
<script type="text/javascript">
function Clip() {
this.url = userInput.url.value;
this.in = userInput.in.value;
this.out = userInput.out.value;
}
function Timeline() {
this.clips = [];
this.queue = function() {
this.clips.push(new Clip());
alert("Your url is: " + this.clips.length);
}
this.dequeue = function() {
if(this.clips.length != 0) this.clips.pop();
}
this.runQueue = function() {
if(this.clips.length == 0) {
alert("You need to add something to the queue.");
}
else {
var i = this.clips.length;
var slot = 0;
alert("in else.");
while(i!=0) {
document.getElementById('queue').innerHTML+= this.clips[slot].url + "<br>";
i--;
slot++;
}
}
}
}
var myTime = new Timeline();
</script>
</head>
<body>
<div id="wrapper">
<header id="mainHeader">
<h1>Building an Array with Object Oriented Programming</h1>
</header>
<section id = "addVideo">
<h1> Add a Video </h1>
<form name = "userInput">
<p>
Url: <input type="text" name="url" size="30" />
Start Time: <input type="text" name="in" size="2" />
End Time: <input type="text" name="out" size="2" />
<input type="button" onclick="myTime.queue()" value="Add" />
</p>
</form>
<!-- <table border = "1" id = "tblVideo">
<tr>
<th>Youtube URL</th>
</tr>
</table> //-->
</section>
<aside>
<h1>Show Contents of Timeline</h1>
<p>
<input type="button" onclick="myTime.runQueue()" value="Show Timeline" />
</p>
Your Queue:<br>
<div id="queue"></div>
</aside>
</div>
</body>
I'm curious as to how many of these queue methods I can encapsulate into the Timeline object. I would eventually like to add DOM to update a table with what's been added into the queue and am curious as to whether I should put it in this same object as well or break it off into another function, if so, how do I then pass arguments?
This is an example of a function I've already used in my code that used to take the url and update the table from the queue by simply putting the addTableRow(url); in the function but I'm unsure as to how to implemint this with objects. Would you just write it addTableRow(this.clips.url)? Or should I encapsulate it into the Timeline object?
function addTableRow(url) {
function delayed() {
var table=document.getElementById("tblVideo");
var lastRow = table.rows.length;
// if there's no header row in the table, then iteration = lastRow + 1
var iteration = lastRow;
var row = table.insertRow(lastRow);
var cell1=row.insertCell(0);
cell1.innerHTML=url;
}
setTimeout(delayed,500);
}
I've already made a very simple version of this already without any OOP seen here. I thought that OOP would increase the flexibility of my code and allow me to store multiple objects holding more information.
I apologize if any of this sounds overly simple but I'm kind of curious if OOP is really the way to go for this kind of problem.
Originally my input type was submit, which wouldn't update the array
<input type="submit" onclick="myTime.queue()" value="Add" />
So I changed it to button.
<input type="button" onclick="myTime.queue()" value="Add" />
After researching more the DOM question has grown into its own problem, which requires another question.

Categories

Resources