Creating a textarea when user clicks button - javascript

I was wondering what the best way to approach this next feature is.
Right now, when user selects "no" an alert appears. However, I would like for a text area box to appear, instead. Any help or leads on how to tackle this? My first thought is that my if statement will have to change, correct? Any leads are appreciated. I provided a snippet for you to view of what I have so far.
let button = document.querySelector("input.button");
button.addEventListener("click", question1);
function question1() {
var selection = document.querySelector("input[name='groupOfDefaultRadios']:checked");
if (selection.value == 'yes') {
alert("Thank you for your kindness");
} else {
alert("We are sorry! Please write to us telling us what was wrong");
}
}
<div class="clienthelp-card">
<form id="myForm">
<h4> Was this helpful?</h4>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample1" name="groupOfDefaultRadios" value="yes">
<label class="custom-control-label" for="defaultGroupExample1">Yes</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample2" name="groupOfDefaultRadios" value="no">
<label class="custom-control-label" for="defaultGroupExample2">No</label>
</div>
<input class="button" type="button" name="groupOfDefaultRadios" value="Submit">
</form>
</div>

Here are a few ways you can give a user something to enter text into and then handle it as you see fit.
The first way is to insert a textarea element and add a callback so that when the user selects OK, you can do what you want with the text.
The second way is to use prompt as called called out in other comments
function okButtonCallback(evt) {
const textArea = document.getElementById('textarea1');
alert(`Text Area Text: ${textArea.value}`);
}
const btnTextArea = document.getElementById('textarea');
const btnPrompt = document.getElementById('prompt');
// Use a Text Area to get text and
// add a callback to handle the text
// when the user selects ok
btnTextArea.addEventListener('click', e => {
const container = document.getElementById('myContainer');
const textArea = document.createElement('textarea');
textArea.id = 'textarea1';
const okButton = document.createElement('button');
okButton.innerText = 'OK';
okButton.onclick = okButtonCallback;
container.appendChild(textArea);
container.appendChild(okButton);
});
// Use a prompt to get the text
btnPrompt.addEventListener('click', e => {
const enteredText = prompt('Some sort of message');
alert(`Prompt Text: ${enteredText}`);
});
<button id="textarea">Show Text Area</button>
<button id="prompt">Show Prompt</button>
<div id="myContainer"></div>

The built in alert function cannot be used to get user input.
You can add a hidden div which replaces the alert and where you can also add HTML elements.
Please find slightly modified version of your code to get the idea below:
<div class="clienthelp-card">
<form id="myForm">
<h4> Was this helpful?</h4>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample1" name="groupOfDefaultRadios" value="yes">
<label class="custom-control-label" for="defaultGroupExample1">Yes</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample2" name="groupOfDefaultRadios" value="no">
<label class="custom-control-label" for="defaultGroupExample2">No</label>
</div>
<input class="button" type="button" name="groupOfDefaultRadios" value="Submit">
</form>
</div>
<div id="result" style="display:none"></div>
<script>
let button = document.querySelector("input.button");
button.addEventListener("click", question1);
function question1() {
var selection = document.querySelector("input[name='groupOfDefaultRadios']:checked");
var result = document.getElementById("result");
if (selection.value == 'yes') {
result.innerHTML = "Thank you for your kindness";
result.style.display = "block";
} else {
var output = "";
output += "We are sorry! Please write to us telling us what was wrong:<br />";
output += "<textarea style='width: 100px; height 100px;'></textarea><br />";
output += "<button>Submit</button>";
result.innerHTML = output;
result.style.display = "block";
}
}
</script>

I think you can create a <textarea id="whatever_you_want" hidden> and you add in the else document.getElementById("whatever_you_want").removeAttribute("hidden")

You can toggle a hidden text field, based on the selection of the radio button.
In the example below, a class is added to the text field to hide it. When the choice is changed to "yes", the class is added; if it is changed to "no", the class is added back.
let submitButton = document.querySelector('input.button');
let radioButtons = document.querySelectorAll('input[type="radio"]');
let hiddenTextArea = document.querySelector('.custom-textarea textarea');
// Add listeners
Array.from(radioButtons).forEach(radio => {
radio.addEventListener('change', (e) => {
let hiddenWrapper = hiddenTextArea.parentElement;
hiddenWrapper.classList.toggle('hidden-field', e.target.value !== 'no');
});
});
submitButton.addEventListener('click', question1);
function question1() {
var selection = document.querySelector("input[name='groupOfDefaultRadios']:checked");
if (selection.value == 'yes') {
alert("Thank you for your kindness");
} else {
alert("We are sorry! Please write to us telling us what was wrong");
}
}
.hidden-field {
display: none;
}
<div class="clienthelp-card">
<form id="myForm">
<h4> Was this helpful?</h4>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample1" name="groupOfDefaultRadios" value="yes">
<label class="custom-control-label" for="defaultGroupExample1">Yes</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample2" name="groupOfDefaultRadios" value="no">
<label class="custom-control-label" for="defaultGroupExample2">No</label>
</div>
<!-- Here -->
<div class="custom-control custom-textarea hidden-field">
<textarea name="feedback"></textarea>
</div>
<input class="button" type="button" name="groupOfDefaultRadios" value="Submit">
</form>
</div>

Another approach is to createElement when the user mark the "NO". I put notes inside this general demo:
let radioI = document.querySelectorAll("input[name='groupOfDefaultRadios']"); // get radio in order to attach eventListener:
radioI.forEach((item) => { item.addEventListener("change", question1)}); // add change event that will trigger this function:
function question1() {
var selection = document.querySelector('input[name="groupOfDefaultRadios"]:checked'); // this is your lines
if (selection.value == 'yes') {
alert('Thank you for your kindness');
// and/or submit the form progrematically using submit() etc... and/or redirect the user etc..
} else {
// create textarea element and display the submit button:
var textA = document.createElement('textarea');
textA.setAttribute('name', 'notHelpNote');
textA.setAttribute('required', 'true');
textA.placeholder = 'We are sorry! Please write to us telling us what was wrong';
document.querySelector('#myForm').appendChild(textA);
document.querySelector('#myForm input[type="submit"]').style.display = 'block';
}
}
<div class="clienthelp-card">
<form id="myForm">
<h4> Was this helpful?</h4>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample1" name="groupOfDefaultRadios" value="yes">
<label class="custom-control-label" for="defaultGroupExample1">Yes</label>
</div>
<div class="custom-control custom-radio">
<input type="radio" class="custom-control-input" id="defaultGroupExample2" name="groupOfDefaultRadios" value="no">
<label class="custom-control-label" for="defaultGroupExample2">No</label>
</div>
<input class="button" type="submit" name="groupOfDefaultRadios" value="Submit" style="display: none;">
</form>
</div>

I guess you can create a:
<input type="hidden" name="message" id="myAwesomeHiddenMessageField">
in your form and replacing your second alert by a prompt displaying the question like this :
let promptMessage = prompt("We are sorry! Please write to us telling us what was wrong");
And on submit or whatever :
document.querySelector('#myAwesomeHiddenMessageField').val(promptMessage);
Or you could use document.createElement to append a textearea to your form when "no" is selected. But I'm to lazy to help you more with this. And if you wan't to do this you gonna have to hide the generated textarea if the user choose "yes" in the end. Not sure if it's the best UX choose to make.
Cheers.

Related

Get the current class from HTML in Javascript

I'm trying to get a "check all" checkbox working and I can't seem to find a way.
Edit: the issue is that in my case; the class names are all "checkButtonLot (current lot number)" as they're generated through a "for" loop in the twig. What I don't get is how to pass that current lot number as a variable to the Js; so that when I click on the 1st lot number checkbox; the 1st lot number sub-products are all checked; but the rest of the lot numbers are not.
Here's the Twig for the checkbox that should check the rest:
<div class="custom-control custom-checkbox">
<input id="checkButtonLot{{ currentProduct.lotNumber }}" type="checkbox"
class="custom-control-input js-checkBoxLot{{ currentProduct.lotNumber }} js-checkable"
name="checkButtonLot{{ currentProduct.lotNumber }}" value="{{ currentProduct.lotNumber }}">
<label class="custom-control-label" for="checkButtonLot{{ currentProduct.lotNumber }}"></label>
</div>
Here's the twig for the other checkboxes:
<div class="custom-control custom-checkbox">
<input id="checkButtonLotsub_product{{ sub_product.rankId }}_{{currentProduct.lotNumber}}" type="checkbox"
class="custom-control-input js-checkBoxLotsub_product{{ sub_product.rankId }}_{{currentProduct.lotNumber}} js-checkable"
name="checkButtonLotsub_product{{ sub_product.rankId }}_{{currentProduct.lotNumber}}"
value="{{ sub_product.id }}_{{ sub_product.rankId }}_{{currentProduct.lotNumber}}">
<label class="custom-control-label"
for="checkButtonLotsub_product{{ sub_product.rankId}}_{{currentProduct.lotNumber}}"></label>
</div>
Here's the Js script that's supposed to make it work:
var checkBoxSelectAllOneLot = Array.prototype.slice.call(
document.getElementsByClassName(classCheckboxesLots)
);
addEventAllOneLot(checkBoxSelectAllOneLot);
function addEventAllOneLot(checkboxAll) {
var checkboxAll = checkBoxSelectAllOneLot;
checkboxAll.map(function (btnElement) {
console.log(btnElement);
btnElement.addEventListener("click", selectAllOneLot);
});
}
function selectAllOneLot() {
var separator = "_";
var lotNumber = this.value.split([separator[1]]);
var checkboxAllOneLot = Array.prototype.slice.call(
document.getElementsByClassName(classCheckboxesLotWafer)
);
console.log(checkboxAllOneLot);
if (this.checked == true) {
checkboxAllOneLot.map(function (checkbox) {
checkbox.checked = true;
checkbox.classList.toggle("checked");
});
} else {
checkboxAllOneLot.map(function (checkbox) {
checkbox.checked = false;
});
}
deselectButtonAll();
}
EDITED: the display language isn't HTML its indeed Twig.
Any one would have any insight on this, I'd appreciate greatly.
Have a good one
Your code is pretty convoluted, so I'm not going to weed through it (no offense), but here's a very simple method I'm sure you can adapt for your situation:
document.getElementById("check-all").addEventListener('change', changeHandler)
function changeHandler(event) {
for (const checkbox of document.querySelectorAll('.group')) {
checkbox.checked = event.target.checked
}
}
<input type="checkbox" id="check-all"> <label for="check-all">check all</label>
<br>
<input type="checkbox" class="group">
<input type="checkbox" class="group">
<input type="checkbox" class="group">
<input type="checkbox" class="group">

How to get the checked radio button in JS?

I have seen that this works for most of users, but for some reason it doesn't for me. I use Google Chrome.
radioBut = document.querySelector(".rad-design")
getColor = function(){
for (i=0; i<radioBut.length; i++){
if (radioBut[i].checked){
console.log(radioBut[i)
}
}
Html
<form id = "rad">
<div class = "radioAll">
<label class="rad-label">
<input type="radio" class="rad-input" name="colList">
<div class="rad-design"></div>
</label>
<label class="rad-label">
<input type="radio" class="rad-input" name="colList">
<div class="rad-design"></div>
</label>
</div>
</form>
The selector should be document.querySelectorAll to get inputs as array and you should target to .rad-input class which is the input and not .rad-design which is the label. Also you should use checked for the inputs to make the input checked, its not check. Also you cannot set checked to two inputs with same name. If thats done only the last input with that name will be checked.
Working Fiddle
const radioBut = document.querySelectorAll(".rad-input")
getColor = function () {
for (i = 0; i < radioBut.length; i++) {
if (radioBut[i].checked) {
console.log(radioBut[i])
}
}
}
<form id="rad">
<div class="radioAll">
<label class="rad-label">
<input type="radio" class="rad-input" checked name="colList">
<div class="rad-design">One</div>
</label>
<label class="rad-label">
<input type="radio" class="rad-input" name="colList">
<div class="rad-design">Two</div>
</label>
</div>
<button type="button" onclick="getColor()">getColor</button>
</form>
document.querySelector returns just one element not an array/list, so in the for loop at i<radioBut.length radioBut.length is undefined, you need to use document.querySelectorAll() instead.
Also I noticed you have selected the div and not the input and you have a couple of syntax errors.
Maybe this can help you:
const radioBut = document.querySelectorAll(".rad-input")
const getColor = function(){
for (let i=0; i<radioBut.length; i++){
if (radioBut[i].checked){
console.log(radioBut[i].value)
}
}
}
console.log(getColor())
<form id = "rad">
<div class = "radioAll">
<label class="rad-label">
<input type="radio" class="rad-input" value='A' name="colList">
<div class="rad-design"></div>
</label>
<label class="rad-label">
<input type="radio" class="rad-input" value='B' name="colList" checked>
<div class="rad-design"></div>
</label>
</div>
</form>
Another options is to use the form element functionality
const form = document.getElementById('rad');
const getColor = function(){
return form.colList.value;
}
console.log(getColor())
<form id = "rad">
<div class = "radioAll">
<label class="rad-label">
<input type="radio" class="rad-input" value='A' name="colList">
<div class="rad-design"></div>
</label>
<label class="rad-label">
<input type="radio" class="rad-input" value='B' name="colList" checked>
<div class="rad-design"></div>
</label>
</div>
</form>

Client-side form validation for multiple forms on single page

I have multiple dynamic forms being presented on a page. Please see my snippet below for an example. The problem is I want to make sure a value is selected in each form using JavaScript.
<div class="form-check form-check-inline float-right" data-application-no="1">
<input type="radio" class="form-check-input" id="shortlist" name="decisionOptions1" value="shortlist">
<label for="shortlist" class="form-check-label mr-3">Shortlist</label>
<input type="radio" class="form-check-input" id="reject" name="decisionOptions1" value="reject">
<label for="reject" class="form-check-label">Reject</label>
</div>
<div class="form-check form-check-inline float-right" data-application-no="2">
<input type="radio" class="form-check-input" id="shortlist" name="decisionOptions2" value="shortlist">
<label for="shortlist" class="form-check-label mr-3">Shortlist</label>
<input type="radio" class="form-check-input" id="reject" name="decisionOptions2" value="reject">
<label for="reject" class="form-check-label">Reject</label>
</div>
<div class="form-check form-check-inline float-right" data-application-no="3">
<input type="radio" class="form-check-input" id="shortlist" name="decisionOptions3" value="shortlist">
<label for="shortlist" class="form-check-label mr-3">Shortlist</label>
<input type="radio" class="form-check-input" id="reject" name="decisionOptions3" value="reject">
<label for="reject" class="form-check-label">Reject</label>
</div>
I am really struggling on how to go about this.
Right now, I'm working with this:
function submitDecision(){
const decisionForm = document.querySelectorAll('[name^=decisionOptions]');
const shortlistSelector = document.querySelectorAll('#shortlist');
const rejectSelector = document.querySelectorAll('#reject');
for (const selector of decisionForm){
console.log(`${selector.name}: ${selector.value} , ${selector.checked}`);
if ((selector.value == "shortlist" && selector.checked == false) && (selector.value == "reject" && selector.checked == false)){
console.log("we have a problem!")
}
}
}
The code above isn't working though obviously because in that if statement I am referring to the same selector. Any suggestions on how I can go about this. I want to make sure that for each application (each form) an option of shortlist or reject is chosen. If no selection is made but the user tries to submit the form, I want to present an error.
In case anyone is interested, this is how I managed to solve it:
function submitDecision(){
const decisionForm = document.querySelectorAll('[name^=decisionOptions]');
for (const selector of decisionForm){
const rejectSelector = selector.parentNode.lastElementChild.previousElementSibling;
const formDiv = selector.parentNode
const brTag = formDiv.nextElementSibling;
const errorMsg = document.createElement('p');
errorMsg.className = 'error-msg float-right';
errorMsg.innerHTML = 'Please make a selection before submitting';
errorMsg.style.color = 'red';
if ((selector.value == "shortlist" && selector.checked == false) && (rejectSelector.checked == false)){
console.log(`no options selected for application-no${formDiv.dataset.applicationNo}`);
formDiv.parentNode.insertBefore(errorMsg, brTag.nextElementSibling);
selector.addEventListener('change', () => {
if (selector.checked){
console.log("remove error message");
try {
errorMsg.remove()
} catch(err){
console.log(err)
}
}
})
rejectSelector.addEventListener('change', () => {
if (rejectSelector.checked){
console.log("remove error message");
try {
errorMsg.remove()
} catch(err){
console.log(err)
}
}
})
}
}
}
I don't know if it is efficiently written per se but it definitely does the job.

HTML input checkbox always returns false

I know this has been already asked. I checked all the previous question about this topic but I can't find a solution.
This is the problem: I have two input, one is a checkbox and the other one is a radio with three possible choices. Inside a function I have to see firstly if the first checkbox is checked, if yes I will check some other things with an if else statement, otherwise the function will proceed. The radio input will appear later inside the same function. This one will check which of the three choices had been checked previously and will set a variable equal to the value of the checked one. To see if the checkbox is checked I use jQuery with .is(':checked'), but it every returns false, even if I checked them. Any idea?
Sorry if I haven't properly used Stack Overflow, but this is my first question.
This is the HTML, the input is #geoloc_waypoint_active and the radio is #locomotion_radio
<div id="create_route_modal_content" class="modal-body">
<div id="geo_switch">
<div id="geoSwitchDiv">
<label for="geoloc_waypoint_active">
Usa la tua posizione
</label>
<label class="switch">
<input id="geoloc_waypoint_active" class="form-check form-check-inline" type="checkbox">
<span class="slider round"></span>
</label>
</div>
<br>
<div id="locomotion_radio">
<label><input class="locomInput" type="radio" name="locomotion" value="walking" checked><img class='locomotionImg' src='immagini/walking.png'></label>
<label><input class="locomInput" type="radio" name="locomotion" value="cycling"><img class='locomotionImg' src='immagini/cycling.png'></label>
<label><input class="locomInput" type="radio" name="locomotion" value="driving"><img class='locomotionImg' src='immagini/driving.png'></label>
</div>
DrawOnMap() {
let formattedCoord = "";
let geoposition = $('#geoloc_waypoint_active').is(':checked');
console.log(geoposition)
if (geoposition) {
var geoL = $('#geo_Locator .mapboxgl-ctrl .mapboxgl-ctrl-icon');
if (!map.getLayer('points') && geoL.attr('aria-pressed') === 'false') {
alert("L'utente non ha una posizione attualmente attiva.");
return;
} else {
this.waypoints.unshift(window.userPosition);
}
}
if (this.waypoints.length < 2) {
alert("Devi inserire almeno due punti di interesse.");
return;
}
this.waypoints.forEach((waypoint, index, source) => {
formattedCoord += waypoint[0] + "," + waypoint[1];
if (index < source.length - 1) {
formattedCoord += ";";
}
});
let locomotion = $('input[name=locomotion]:checked').val();
let geoposition = $('#geoloc_waypoint_active').is(':checked'); is always false and so It never enter the if
Same thing with let locomotion = $('input[name=locomotion]:checked').val(); It can't find the checked one and set locomotion
have you tried this $("#geoloc_waypoint_active")[0].checked it will give you control right value.
$(document).ready(function(){
console.log($("#geoloc_waypoint_active")[0].checked)
$('#check').on('click',function(){
console.log($("#geoloc_waypoint_active")[0].checked)
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input value='checkVakue' type='button' id='check'/>
<div id="create_route_modal_content" class="modal-body">
<div id="geo_switch">
<div id="geoSwitchDiv">
<label for="geoloc_waypoint_active">
Usa la tua posizione
</label>
<label class="switch">
<input id="geoloc_waypoint_active" class="form-check form-check-inline" type="checkbox">
<span class="slider round"></span>
</label>
</div>
<br>
<div id="locomotion_radio">
<label><input class="locomInput" type="radio" name="locomotion" value="walking" checked><img class='locomotionImg' src='immagini/walking.png'></label>
<label><input class="locomInput" type="radio" name="locomotion" value="cycling"><img class='locomotionImg' src='immagini/cycling.png'></label>
<label><input class="locomInput" type="radio" name="locomotion" value="driving"><img class='locomotionImg' src='immagini/driving.png'></label>
</div>

Issue while checking radio buttons

I am trying to show a red circle with the "!" when the radio buttons are unchecked and to show a green circle when both are checked. After that I use a function to make the button submit or not according to the red/green circle.
I've tried many ways to tangle with the code but it doesn't want to show the green circle when it's checked any idea why ?
PS:
span3 (red circle )
span2 (green circle)
Basically I want to make my form validation by js not by php ...
HTML:
<label id="labelage">Age:</label>
<br>
<input type="radio" id="under_13" value="under_13" name="age">
<label for="under_13" class="light">Under 13</label>
<input type="radio" id="over_13" value="over_13" name="age">
<label for="over_13" class="light">13 or Older</label>
<div class="break"></div>
<div id="borderlabel">
<label id="labelage1">Gender:</label>
<input type="radio" id="male" value="male" name="gender">
<label for="male" class="light1">Male</label>
<input type="radio" id="female" value="female" name="gender">
<label for="female" class="light1">Female</label>
</div>
....
<button type="submit" id="signupb" name="register">Sign up
<div class="span3">!</div>
<div class="span2">✔</div>
</button>
JavaScript
$(".span1").hide();
$(".span2").hide();
$(".span3").hide();
function submit() {
if (!$('#male').is(':checked') || !$('#female').is(':checked')) {
$(".span3").show();
} else {
if (!$('#under_13').is(':checked') || !$('#over_13').is(':checked')) {
$(".span3").show();
} else {
$(".span2").show();
}
}
}
$("#signupb").on("mouseover", submit);
Your logic is off
Have the radio clicks also update the !
Do not call something submit
Cancel the submission if clicking anyway
Try this:
function checkRad() {
var ok = ($('#male').is(':checked') || $('#female').is(':checked')) &&
($('#under_13').is(':checked') || $('#over_13').is(':checked'))
$(".span3").toggle(!ok);
$(".span2").toggle(ok);
return ok;
}
$(function() {
$(".span1").hide();
$(".span2").hide();
$(".span3").hide();
$("#signupb").on("mouseover", checkRad)
.on("click", function(e) {
if (!checkRad()) e.preventDefault();
})
$("input[type=radio]").on("click", function() {
checkRad();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<label id="labelage">Age:</label>
<br>
<input type="radio" id="under_13" value="under_13" name="age">
<label for="under_13" class="light">Under 13</label>
<input type="radio" id="over_13" value="over_13" name="age">
<label for="over_13" class="light">13 or Older</label>
<div class="break"></div>
<div id="borderlabel">
<label id="labelage1">Gender:</label>
<input type="radio" id="male" value="male" name="gender">
<label for="male" class="light1">Male</label>
<input type="radio" id="female" value="female" name="gender">
<label for="female" class="light1">Female</label>
</div>
....
<button type="submit" id="signupb" name="register">Sign up
<div class="span3">!</div>
<div class="span2">✔</div>
</button>
I would recommend using jQuery Validation plugin instead
It's bad practice to assign IDs to every input element, makes code harder to maintain. Consider accessing elements by name attribute.
Consider adding server-side validation as well against browser errors/malicious users.
Change your submit() function to:
function validateForm() {
$(".span2").hide();
$(".span3").hide();
var isError = false;
if (!$('#male').is(':checked') && !$('#female').is(':checked')) {
isError = true
} else if (!$('#under_13').is(':checked') && !$('#over_13').is(':checked')) {
isError = true;
}
if(isError){
$(".span3").show();
} else {
$(".span2").show();
}
}
$("#signupb").on("mouseover", validateForm);
DEMO

Categories