Why output element is not displayed? - javascript

i am writing a simple app that displays how many characters
the user can add inside a text area without exceeding an upper limit.
The problem is that the output tag does not display result.
<!doctype html>
<html lang="el">
<head>
<title>Count Characters</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<style>
label{
font-size: 44.5px;
position: relative;
left: 5%;
font-family: "Times New Roman", Times, serif;
}
</style>
</head>
<body>
<form name="myForm">
<label for id="mytext"> CountLetters </label> <br>
<textarea id="mytext" name="aboutMe" rows="4" cols="50" maxlength="500" placeholder="write here yout text"></textarea>
<br>
<output id="charsleft"></output>
<br>
<br>
</form>
<script>
const textinput = document.querySelector("#mytext");
textinput.addEventListener("input",(e)=>{
charsleft.value=`You can Add ${textinput.maxLength-chars.value.length} characters`
});
</script>
</body>
</html>

Please note that this is invalid HTML markup:
<label for id="mytext">
You need to remove the id attribute, because the for attribute references the id of the labelable element that the <label> is associated to.
Elements that can be associated with a <label> element include <button>, <input> (except for type="hidden"), <meter>, <output>, <progress>, <select> and <textarea>.
What you had was essentially an empty for attribute and a duplicate element id. Every id attribute on a webpage should be unique; there can be no duplicates. Your querySelector call was grabbing your <label> instead of your <textarea>.
Corrective measures
Now, you can simplify this.
Use the event parameter's target property to access the event element
Do not display the message, if the input is cleared
document.querySelector('#mytext')
.addEventListener('input', ({ target: { maxLength, value: { length } } }) => {
charsleft.value = length > 0
? `You can add ${maxLength - length} characters`
: '';
});
label {
font-size: 44.5px;
position: relative;
left: 5%;
font-family: "Times New Roman", Times, serif;
}
<form name="myForm">
<label for="mytext">Count Letters</label>
<br>
<textarea id="mytext" name="aboutMe"
rows="4" cols="50" maxlength="500"
placeholder="write here yout text"></textarea>
<br>
<output id="charsleft"></output>
<br>
<button type="reset">Reset</button>
</form>

Does changing the for attribute as I assume it was a typo to use for id, and chars to mytext fix your problem? Though it is better to explicitly define the variables used.
const textinput = document.querySelector("#mytext");
textinput.addEventListener("input", (e) => {
charsleft.value = `You can Add ${mytext.maxLength-mytext.value.length} characters`
});
label {
font-size: 44.5px;
position: relative;
left: 5%;
font-family: "Times New Roman", Times, serif;
}
<form name="myForm">
<label for="mytext"> CountLetters </label> <br>
<textarea id="mytext" name="aboutMe" rows="4" cols="50" maxlength="500" placeholder="write here yout text"></textarea>
<br>
<output id="charsleft"></output>
<br>
<br>
</form>

This code work perfectly
<!doctype html>
<html lang="el">
<head>
<title>Count Characters</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<style>
label {
font-size: 44.5px;
position: relative;
left: 5%;
font-family: "Times New Roman", Times, serif;
}
</style>
</head>
<body>
<form name="myForm">
<label for="mytext"> CountLetters </label> <br> <!-- for id="mytext" => for="mytext" -->
<textarea id="mytext" name="aboutMe" rows="4" cols="50" maxlength="500" placeholder="write here yout text"></textarea>
<br>
<output id="charsleft"></output>
<br>
<br>
</form>
<script>
const textinput = document.querySelector("#mytext");
const charsleft = document.querySelector("#charsleft");
textinput.addEventListener("input", (e) => {
const maxLength = Number(e.target.getAttribute('maxlength'));
const value = e.target.value;
charsleft.innerHTML = `You can Add ${maxLength-value.length} characters`
});
</script>
</body>
</html>

Related

How to pre-fill a file type field for a form submission using the "post" method

I am developing a cultural web portal where users, after registering, will be able to add an article via a dedicated form.
As happens in most cultural web portals and also on social media, articles will be accompanied by a cover image that will anticipate the topic, a title and a description, as well as other fields that are not relevant here.
The CMS I have developed for the management (insertion, updating, removal) of articles has been designed for the total management in PHP of the data sent by forms. No forms are or will be loaded via JS/Ajax.
The form for saving articles will contain both mandatory and optional fields. If a mandatory field (e.g. title or text) is not filled in, the PHP script will redirect to the form, displaying the information previously entered in the fields that were filled in, to ease the user by relieving them of the task of having to re-enter all the fields again.
This choice does not create any problems for text, select and textarea type fields. It does, however, create a problem for the file type field dedicated to loading the cover image, since for security reasons it is impossible to save the local path to the image in order to retrieve it in the form and display it in the file type field.
In the form, as can be seen in the snippet below, after choosing the image it will be displayed as a preview, so that the user can check that he has chosen the correct image for his article.
Is there a way or an alternative to be able to pre-fill the file field in order to relieve the user of the task of having to choose the image again? Because the save script will retrieve all the fields via $_POST and the image via $_FILES.
I want to absolutely avoid encoding the image in base64 because some of the images that will be loaded will exceed 1280px in width and the save operation, having to transmit all the base64 encoding, would slow down a lot. Test already carried out.
HTML (fields not pre-filled)
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form</title>
<script src="js/jquery.js"></script>
<script>
$(function () {
$('input:file').on('change', function () {
var reader = new FileReader();
reader.onload = function () {
$('.row').find('.preview').attr('src', reader.result);
}
reader.readAsDataURL(this.files[0]);
});
});
</script>
<style>
form {
width: 500px;
margin: auto;
}
.row {
padding: 10px 0;
}
.row label {
display: block;
}
.row .preview {
display: block;
margin: 20px 0;
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<form method="post" action="save.php" enctype="multipart/form-data">
<fieldset>
<div class="row">
<label for="image">Image</label>
<input type="file" name="image" id="image">
<img src="" alt="" class="preview">
</div>
<div class="row">
<label for="title">Title</label>
<input type="text" name="title" id="title">
</div>
<div class="row">
<label for="text">Text</label>
<textarea name="text" id="text" cols="30" rows="10"></textarea>
</div>
</fieldset>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
HTML (pre-filled fields)
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form</title>
<script src="js/jquery.js"></script>
<script>
$(function () {
$('input:file').on('change', function () {
var reader = new FileReader();
reader.onload = function () {
$('.row').find('.preview').attr('src', reader.result);
}
reader.readAsDataURL(this.files[0]);
});
});
</script>
<style>
form {
width: 500px;
margin: auto;
}
.row {
padding: 10px 0;
}
.row label {
display: block;
}
.row .preview {
display: block;
margin: 20px 0;
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<form method="post" action="save.php" enctype="multipart/form-data">
<fieldset>
<div class="row">
<label for="image">Image</label>
<input type="file" name="image" id="image">
<img src="" alt="" class="preview">
</div>
<div class="row">
<label for="title">Title</label>
<input type="text" name="title" id="title" value="<?php echo $_SESSION['title'] ?>">
</div>
<div class="row">
<label for="text">Text</label>
<textarea name="text" id="text" cols="30" rows="10"><?php echo $_SESSION['text'] ?></textarea>
</div>
</fieldset>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
Screenshot (fields not pre-filled, image chosen)
Screenshot (fields pre-filled, image to be chosen again)

How to auto populate form fields with json using one select?

I have a form with a select field (for this case is the first name), I want to select one of the options and with that data selected, the other fiels should be auto completed.
The data is comming from an API.
I'm able to have the dropdown working but whenever I select one option the fields aren't being populated.
Can someone help me, please?
This is my javascript:
document.addEventListener('DOMContentLoaded',() => {
const nomeSelectDrop = document.getElementById('nome');
const sobrenome = document.getElementById('sobrenome');
const email = document.getElementById('email');
const password = document.getElementById('password');
fetch('http://localhost:5000/user')
.then(res => {
return res.json();
})
.then(data => {
let output = "";
data.forEach(users => {
output += `<option value = "${users.firstName}">${users.firstName}</option>`;
})
nomeSelectDrop.innerHTML = output;
})
.catch(err => {
console.log(err);
})
nome.addEventListener('change', (event) => {
sobrenome.innerHTML = event.target.lastName.value;
email.innerHTML = event.target.email.value;
password.innerHTML = event.target.password.value;
})
})
This is my html:
<!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" type="text/css" href="style.css">
<title>Form Exercise</title>
</head>
<body>
<form class="formulario">
<div class="field">
<label for="nome">Nome:</label>
<select id="nome" name="nome"></select>
</div>
<div class="field">
<label for="sobrenome">Sobrenome:</label>
<input type="text" id="sobrenome" name="sobrenome" placeholder="sobrenome" required>
</div>
<div class="field">
<label for="email">E-Mail:</label>
<input type="email" id="email" name="email" placeholder="e-mail" required>
</div>
<div class="field">
<label for="password">Password:</label>
<input type="password" id="password" name="password" placeholder="password" required>
</div>
<div class="buttons">
<input type="submit" name="atualizar" value="Atualizar">
<input type="submit" name="eliminar" value="Eliminar">
</div>
</form>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
Be aware that some of the #ids and names in HTML has been changed (I think slower reading foreign words -- I'm dumb that way 😕). HTMLFormElement and HTMLFormControlsCollection interfaces were used to reference <form>, <input>, and <select>. The most important part is declaring a variable outside of fetch(), then defining that variable as the data within fetch() which brings the data within scope for functions, expressions, etc outside of fetch().
Details are commented in example below
// Reference the <form>
const exc = document.forms.exc;
document.addEventListener('DOMContentLoaded', (e) => {
/*
Collect all <select>,<fieldset>,<input> into a HTMLCollection
*/
let io = exc.elements;
// Declare a variable outside of fetch()
let users;
fetch('https://my.api.mockaroo.com/userlist.json?key=3634fcf0')
.then(res => {
return res.json();
})
.then(data => {
/* IMPORTANT
Define users as JSON data -- now the JSON is in scope within
this event handler
*/
users = data;
let output = "";
data.forEach(user => {
output += `<option value = "${user.first}">${user.first}</option>`;
});
/*
Use insertAdjacentHTML() instead of innerHTML -- it doesn't destroy
content it adds to content.
*/
io.first.insertAdjacentHTML('beforeend', output);
})
.catch(err => {});
/*
Bind <form> to the change event
*/
exc.addEventListener('change', (e) => {
// Reference the tag user is interacting with
const sel = e.target;
/*
If the tag the user is interacting with is a <select>...
*/
if (sel.matches('select')) {
// Find the index of selected <option>
let idx = sel.selectedIndex;
/*
users = JSON
Reference index of users with index of selected <option>
*/
io.last.value = users[idx].last;
io.email.value = users[idx].email;
io.password.value = users[idx].password;
}
});
});
html {font: 2ch/1.25 'Segoe UI'}
fieldset {max-width: max-content;}
legend {font-size:1.25rem}
input, select, label {display: inline-block; margin: 2px; font: inherit;}
input:not([type='submit']) {width: 32ch}
[type='submit'] {float: right; cursor: pointer;}
select {width: 33ch}
<!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 href="style.css" rel="stylesheet">
<title>Form Exercise</title>
</head>
<body>
<form id="exc">
<fieldset class="field">
<legend>User Registration</legend>
<label for="first">First Name: </label><br>
<select id="first" name="first">
<option selected disabled>Select a user</option>
</select><br>
<label for="last">Last Name:</label><br>
<input id="last" name="last" required><br>
<label for="email">E-Mail:</label><br>
<input id="email" name="email" type="email" placeholder="user#mail.com" required><br>
<label for="password">Password:</label><br>
<input id="password" name="password" type="password" placeholder="Min 8 characters" required>
<menu class="buttons">
<input name="update" type="submit" value='Update'>
<input name="remove" type="submit" value="Remove">
</menu>
</fieldset>
</form>
<script src="app.js"></script>
</body>
</html>

How can I prevent my function from running on every click?

I'm trying to make a dynamic drop down list using HTML and JavaScript, but every time I click on the drop down I get a new set of duplicate values. How can I prevent this from happening? I would prefer to stick to vanilla JS and html
function yearsArray(num) {
let years=document.getElementById("years")
let year=[...Array(num+1).keys()]
year.shift()
year.shift()
year.forEach(element => {
switch (element) {
case 1:
years.add(new Option(element,element,true))
break;
default:
years.add(new Option(element,element,false))
break;
}
})
}
body{
font-family: Arial, Helvetica, sans-serif;
}
h1{
color: gray;
}
<!DOCTYPE html>
<head>
<script src="script.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<title>Simple Interest Calculator</title>
<body>
<div class="maindiv">
<h1>Simple Interest Calculator</h1>
<form>
<label for="principal">Amount</label>
<input type="number" name="principal" id="principal"> <br/>
<label for="rate">Interest Rate</label>
<input type="range" id="rate" name="rate" min="0" max="20" step=".25">
<span id="rate_val">10.25%</span> <br/>
<label for="years">No. of Years </label>
<select id="years" name="years" onclick="yearsArray(20)">
<option selected value="1">1</option>
</select><br/>
<!-- Interest : <span id="result"></span><br/> -->
<button type="submit">Compute Interest</button>
</form>
</div>
</body>
</html>
Just run that function once on page load:
(You could of course just create the options using markup)
function yearsArray(num) {
let years = document.getElementById("years")
let year = [...Array(num + 1).keys()]
year.shift()
year.shift()
year.forEach(element => {
switch (element) {
case 1:
years.add(new Option(element, element, true))
break;
default:
years.add(new Option(element, element, false))
break;
}
})
}
yearsArray(20); //<---------- This runs the function on page load
body {
font-family: Arial, Helvetica, sans-serif;
}
h1 {
color: gray;
}
<!DOCTYPE html>
<head>
<script src="script.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<title>Simple Interest Calculator</title>
<body>
<div class="maindiv">
<h1>Simple Interest Calculator</h1>
<form>
<label for="principal">Amount</label>
<input type="number" name="principal" id="principal"> <br/>
<label for="rate">Interest Rate</label>
<input type="range" id="rate" name="rate" min="0" max="20" step=".25">
<span id="rate_val">10.25%</span> <br/>
<label for="years">No. of Years </label>
<select id="years" name="years">
<option selected value="1">1</option>
</select><br/>
<!-- Interest : <span id="result"></span><br/> -->
<button type="submit">Compute Interest</button>
</form>
</div>
</body>
</html>
Figured it out. added the javascript function to the body tag
<body onload=yearsArray(20)></body>

How do I create output box for the calculator function?

I'm a completely beginner in Javascript and trying to create a simple program to calculate the area of a circle. I'm currently stuck on how to create an output box containing the variable area. Apologies if this is a dumb question, but I do appreciate any kind of help!
<!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">
<title>Circle Area Calculator</title>
</head>
<body>
<fieldset><h3><i>Enter radius of a circle:</i></h3>
<form name="circleForm" onsubmit="calc()">
<label for="name">Enter a number:</label><br>
<input type="number" name="radius" id="radius" placeholder="radius" required><br>
<button type="submit">Calculate Area</button>
<button type="reset">Reset value</button>
</form>
<div id="result">
<output name="result" onsubmit="result()">
</output>
</div>
</fieldset>
</body>
<script>
function calc() {
var radius = document.forms.circleForm.elements.namedItem("radius").value;
var area = (radius**2)*3.14
var calculate;
return area
document.getElementById("result").innerHTML = area;
}
</script>
</html>
Add an event listener to your button and run your calc function from there.
Using event.preventDefault() will prevent the browser from submitting the form and refreshing the page.
Setting the innerHTML of the result div is the right thing to do but you'd put it after your function returned a value, which was preventing it from being executed.
let calculate = document.getElementById('calculate');
calculate.addEventListener('click', () => {
event.preventDefault();
calc();
});
function calc() {
var radius = document.forms.circleForm.elements.namedItem("radius").value;
var area = (radius ** 2) * 3.14
var calculate;
document.getElementById("result").innerHTML = area;
}
<!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">
<title>Circle Area Calculator</title>
</head>
<body>
<fieldset>
<h3><i>Enter radius of a circle:</i></h3>
<form name="circleForm">
<label for="name">Enter a number:</label><br>
<input type="number" name="radius" id="radius" placeholder="radius" required><br>
<button id="calculate">Calculate Area</button>
<button type="reset">Reset value</button>
</form>
<div id="result">
</div>
</fieldset>
</body>
</html>
this way
<!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">
<title>Circle Area Calculator</title>
<style>
form {
width : 20em;
}
legend {
font-size : 1.2em;
font-weight : bold;
font-style : italic;
padding : 0 .4em;
}
label {
font-size : .8em;
}
input,output {
display : block;
}
button {
margin : .8em .4em;
}
</style>
</head>
<body>
<form name="circle-form">
<fieldset>
<legend>Enter radius of a circle:</legend>
<label>Enter a number:</label>
<input type="number" name="radius" id="radius" placeholder="radius" required><br>
<button type="submit">Calculate Area</button>
<button type="reset">Reset value</button>
<output name="result"> </output>
</fieldset>
</form>
<script>
const circleForm = document.forms['circle-form'];
circleForm.onsubmit = e =>
{
e.preventDefault() // disable page submit ==> relaod page
circleForm.result.textContent = (circleForm.radius.valueAsNumber ** 2) * Math.PI
}
circleForm.onreset = e =>
{
circleForm.result.innerHTML = ' '
circleForm.radius.value = ''
}
</script>
</body>
</html>
Demo
const circleForm = document.forms['circle-form'];
circleForm.onsubmit = e =>
{
e.preventDefault() // disable page submit ==> relaod page
circleForm.result.textContent = (circleForm.radius.valueAsNumber ** 2) * Math.PI
}
circleForm.onreset = e =>
{
circleForm.result.innerHTML = ' '
}
form {
width : 20em;
}
legend {
font-size : 1.2em;
font-weight : bold;
font-style : italic;
padding : 0 .4em;
}
label {
font-size : .8em;
}
input,output {
display : block;
}
button {
margin : .8em .4em;
}
<form name="circle-form">
<fieldset>
<legend>Enter radius of a circle:</legend>
<label>Enter a number:</label>
<input type="number" name="radius" id="radius" placeholder="radius" required><br>
<button type="submit">Calculate Area</button>
<button type="reset">Reset value</button>
<output name="result"> </output>
</fieldset>
</form>

Form Clear/Submit Javascript

So I have a HTML form, I need to clear the form inputs when a key is pressed and default content gets deleted as well. If reset is clicked, the form resets to its default "Enter ect" and you have to input something again. Also, if submit is clicked without one of the fields entered, it should display an error saying one of my fields are empty, how would I do that using JS?
I tried using JS to clear the default form but all of them get deleted at once rather than the one that gets clicked on.
HTML:
<!doctype html>
<html lang="en">
<head>
<title> Forms </title>
<style>
span {
padding-left: 10px;
display: block;
float: left;
width: 20%;
}
button { margin-left: 10px; }
body {
width: 80%; margin: auto; font-family: sans-serif;
border: 1px solid black;
}
</style>
<meta charset="utf-8">
<script src="prototype.js"></script>
<script src="formsubmit.js"></script>
</head>
<body>
<h1> Task 2: Keyboard Events and Form Submit </h1>
<p> <span>Name:</span> <input id="input1" value="Enter Name" name="Name"></p>
<p> <span>Id:</span> <input id="input2" value="Enter ID" name="ID"></p>
<p> <span>Email:</span> <input id="input3" value="Enter Email" name="Email"></p>
<p>
<button id="submitButton" type="button"> Submit </button>
<input type="reset" value="Reset">
</p>
<p style="color:red" id="ErrorMessage"> </p>
</form>
</body>
</html>
JS:
window.onload=function(){
document.getElementById('input1').value = "";
document.getElementById('input2').value = "";
document.getElementById('input3').value = "";
}
<!doctype html>
<html lang="en">
<head>
<title> Forms </title>
<script>
//window.onload = Reset();
function reset(){
document.getElementById('input1').value = "";
document.getElementById('input2').value = "";
document.getElementById('input3').value = "";
document.getElementById('ErrorMessage').innerHTML = "";
}
function submit(){
var inp1 = document.getElementById('input1').value;
var inp2 = document.getElementById('input2').value;
var inp3 = document.getElementById('input3').value;
if(inp1 == "" || inp2 == "" || inp3 == "")
{
document.getElementById('ErrorMessage').innerHTML = "Please enter all fields";
}
else{
//do your code here
document.getElementById('ErrorMessage').innerHTML = "";
}
}
</script>
<style>
span {
padding-left: 10px;
display: block;
float: left;
width: 20%;
}
button { margin-left: 10px; }
body {
width: 80%; margin: auto; font-family: sans-serif;
border: 1px solid black;
}
</style>
<meta charset="utf-8">
<script src="prototype.js"></script>
<script src="formsubmit.js"></script>
</head>
<body>
<h1> Task 2: Keyboard Events and Form Submit </h1>
<p> <span>Name:</span> <input id="input1" value="" placeholder="Enter Name" name="Name"></p>
<p> <span>Id:</span> <input id="input2" value=""
placeholder="Enter ID" name="ID"></p>
<p> <span>Email:</span> <input id="input3" value="" placeholder="Enter Email" name="Email"></p>
<p>
<button id="submitButton" type="button" onclick="submit()"> Submit </button>
<button id="resetButton" type="button" onclick="reset()"> Reset </button>
</p>
<p style="color:red" id="ErrorMessage"> </p>
</body>
</html>

Categories

Resources