How to fix my Javascript for checkbox questions/answers with feedback? - javascript

I need help figuring out how to get each checkbox give back a different modal. I figured if it was fine with showing two modals that I could add another one in but it did not work. I want it to give separate feedback for each answer chosen. So for example if Answer A is chosen, then I want Modal1 for feedback. Same for B but Modal 2. Choice C works as being correct already.
<form id="submit1">
<div id="question1" class="p-body flex-col-left" style="justify-content: flex-start;">
<label>
<input type="checkbox" name="input" value="wrongA" class="question1" data-seen=1>
<span class="lineup">A. Emily should cross through the incorrect information and write in
the correct information.</span>
</label>
<br>
<label>
<input type="checkbox" name="input" value="wrongB" class="question1" data-seen=2>
<span class="lineup">B. Emily does not need to do anything until it is time for her to renew
her license.</span>
</label>
<br>
<label>
<input type="checkbox" name="input" value="right" class="question1" data-seen=0>
<span class="lineup">C. Emily needs to fill out the appropriate paperwork and submit it to
the TDLR. </span>
</label>
<br>
<br>
</div>
<div class="flex-center">
<button type="submit" id="answer" class="modal-button modal-a">Submit</button>
</div>
</form>
<script>
document.getElementById("answer").onclick = validate;
function validate() {
var checkboxes = document.getElementsByName("input");
var checkboxChecked = [];
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked && (checkboxes[i].value === "right")) {
checkboxChecked.push(checkboxes[i]);
}
}
for (var i = 1; i < checkboxes.length; i++) {
if (checkboxes[i].checked && (checkboxes[i].value === "wrongA")) {
checkboxWrongA.push(checkboxes[i]);
}
}
for (var i = 2; i < checkboxes.length; i++) {
if (checkboxes[i].checked && (checkboxes[i].value === "wrongB")) {
checkboxWrongB.push(checkboxes[i]);
}
}
if (checkboxChecked.length === 1) {
const modal1 = document.querySelector('#modal1');
modal1.style.display = 'block'
window.nextBtn.style.display = "block";
window.dropdown.style.display = "block";
window.breadcrumb.style.display = "block";
}
if (checkboxWrongA.length === 1) {
const modal2 = document.querySelector('#modal2');
modal2.style.display = 'block'
}
if (checkboxWrongB.length === 1) {
const modal3 = document.querySelector('#modal3');
modal3.style.display = 'block'
}
}
</script>

Because you mentioned that your users should only choose 1 option, then a set radio buttons would be the way to go. Then we need to evaluate your JS to work with the radio buttons.
First of make sure that each radio has the same name attribute value. This enables us to use the name to get the value from the input that is checked. Allow the value to represent the chosen option. You could use right or wrongA here, but that doesn't say much about which option is chosen, only it's correctness.
<input type="radio" name="answer" value="A">
<input type="radio" name="answer" value="B">
<input type="radio" name="answer" value="C">
Now on the JavaScript side, we can make things simpler. Since you're using a <form> element, I'd suggest that you listen for a submit event on the form to know when you clicked your validate button.
A submit event happens whenever you have <form> with a <button type="submit"> inside of it and click the button. By default the page would reload. We'll need to stop that from happening by preventing the default behavior of the form. (see event.preventDefault()).
We can extract the data from the form using a FormData object. This object does a lot of work for us, for example, figuring out which of our inputs have been checked. With that object, we can ask for the value of the input by using the name of the input. In this case, I used the name: 'answer'.
Because we now use radio inputs, the value can only be either A, B or C. Based on the answer, look for the appropriate modal and show it.
const form = document.querySelector('#question-form');
form.addEventListener('submit', event => {
event.preventDefault();
const formData = new FormData(form);
const answer = formData.get('answer');
if (answer === 'A') {
const modal = document.querySelector('#modal1');
modal.classList.add('show');
} else if (answer === 'B') {
const modal = document.querySelector('#modal2');
modal.classList.add('show');
} else if (answer === 'C') {
const modal = document.querySelector('#modal3');
modal.classList.add('show');
}
});
.modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
translate: -50% -50%;
background: pink;
padding: 50px 100px;
}
.modal.show {
display: block;
}
<form id="question-form">
<div>
<label>
<input type="radio" name="answer" value="A" class="question1" data-seen=1>
<span class="lineup">A. Emily should cross through the incorrect information and write in the correct information.</span>
</label>
</div>
<div>
<label>
<input type="radio" name="answer" value="B" class="question1" data-seen=2>
<span class="lineup">B. Emily does not need to do anything until it is time for her to renew her license.</span>
</label>
</div>
<div>
<label>
<input type="radio" name="answer" value="C" class="question1" data-seen=0>
<span class="lineup">C. Emily needs to fill out the appropriate paperwork and submit it to the TDLR.</span>
</label>
</div>
<button type="submit" class="modal-button modal-a">Submit</button>
</form>
<div id="modal1" class="modal">
Modal 1
</div>
<div id="modal2" class="modal">
Modal 2
</div>
<div id="modal3" class="modal">
Modal 3
</div>

In this example checkboxes are replaced by radio buttons since it looks as if there's only one correct answer (and multiple modals are silly). The modals are <dialog> elements. Also, the "answer" button triggers a "submit" event that's registered to the <form>. The event handler check(e) is designed to leverage control by event delegation. In addition, the HTMLFormElement and HTMLFormControlsCollection interfaces were used to reference the <form> and it's form controls (all <input> in the <form>).
Details are commented in example
/**
* Register the <form> to the "submit" event
* The event handler check(e) is called when a "submit" event is triggered
*/
document.forms.quiz.onsubmit = check;
/**
* The event handler passes the Event object by default
* Prevent the default behavior of <form> during "submit" event
* Collect all HTMLFormControls into a HTMLCollection
* If a one form control with [name="chx"] is .checked...
* ...get the checked radio button's value...
* ...reference the <dialog> with the class of the same value as the
* checked radio button...
* ...then open that <dialog>
*/
function check(e) {
e.preventDefault();
const fc = this.elements;
if (Array.from(fc.rad).some(c => c.checked)) {
const answer = fc.rad.value;
const modal = document.querySelector('.' + answer);
modal.showModal();
}
}
/**
* Collect all .close (buttons) into a NodeList and bind each one to the
* "click" event.
* The event handler close(e) is called when the "click" event is triggered.
*/
document.querySelectorAll(".close").forEach(btn => btn.onclick = close);
/**
* This event handler will close the parent <dialog> of the clicked <button>
*/
function close(e) {
this.closest('dialog').close();
}
html {
font: 300 2ch/1.2 'Segoe UI'
}
body {
min-height: 100vh;
}
body,
form {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
margin: 0 20px;
}
form {
padding: 10px 30px;
}
fieldset {
width: min(50vw, 500px);
}
legend {
font-size: 1.25rem;
}
menu {
margin: 0 20px 10px 0;
}
.list {
list-style-type: lower-latin;
margin: 20px 30px 0 -10px;
}
label {
display: inline-flex;
align-items: flex-start;
transform: translate(12px, -17px);
line-height: 1;
}
button,
input {
font: inherit;
cursor: pointer;
}
.right * {
float: right;
margin-bottom: 20px;
}
<form id="quiz">
<fieldset>
<legend>Quiz</legend>
<menu class="list">
<li><label>
<input name="rad" type="radio" value="A"> Emily should cross through the incorrect information and write in the correct information.
</label></li>
<li><label>
<input name="rad" type="radio" value="B"> Emily does not need to do anything until it is time for her to renew her license.
</label></li>
<li><label>
<input name="rad" type="radio" value="C"> Emily needs to fill out the appropriate paperwork and submit it to the TDLR.
</label></li>
</menu>
<menu class="right">
<button>Done</button>
</menu>
</fieldset>
</form>
<dialog class="A">
<fieldset>
<legend>Message A</legend>
<p>Quote mode. It's called carpe diem Morty. Look it up. Morty! The principal and I have discussed it, a-a-and we're both insecure enough to agree to a three-way! Haha god-damn! </p>
<menu class="right">
<input class="close" type="button" value="OK">
</menu>
</fieldset>
</dialog>
<dialog class="B">
<fieldset>
<legend>Message B</legend>
<p>Yo! What up my glip glops! Lookin' good! Are you kidding? I'm hoping I can get to both of them, Rick! I mixed in some praying mantis DNA. You know a praying mantis is the exact opposite of a vole, Morty? They mate once and then bluergh cut each other's
heads off. </p>
<menu class="right">
<input class="close" type="button" value="OK">
</menu>
</fieldset>
</dialog>
<dialog class="C">
<fieldset>
<legend>Message C</legend>
<p>Get off the high road Summer. We all got pink eye because you wouldn't stop texting on the toilet. Flip the pickle over. Honey, stop raising your father's colesterol so you can take a hot funeral selfie. God? God's turning people into insect monsters
Beth. I'm the one beating them to death. Thank me. </p>
<menu class="right">
<input class="close" type="button" value="OK">
</menu>
</fieldset>
</dialog>

Related

How do I validate a radio button with JavaScript?

How do I validate a radio button? I want to make it so that if the user left the radio button unclicked the section background will turn a red colour/color.
Here is the HTML Page
<p id="caption_project">Project Selection
<br/>
<input type="radio" name="f__project" id="in_restaurant" value="restaurant"/>
<label for="in_restaurant">LEGO Project</label>
<br/>
<input type="radio" name="f__project" id="in_humber" value="Humber News"/>
<label for="in_humber">Humber Current Project</label>
<br/>
<input type="radio" name="f__project" id="in_self" value="self-determined"/>
<label for="in_self">Self-determined Project</label>
</p>
So how do I turn the background red when they leave it unchecked?
You need to think of some event the user will fire which you want to trigger the function that makes the background go red. That could be if the user clicks on the next form control. Then when that event fires you test whether they checked any radio buttons. If they did not (!checked) then you set the style attribute of your p element to background:red:
const nextThing = document.querySelector('#next-thing');
const p = document.querySelector('p');
nextThing.addEventListener('click', function(){
const checked = document.querySelector("input[name='f__project']:checked");
if(!checked){
p.setAttribute('style', 'background:red');
}
});
<p id="caption_project">Project Selection
<br/>
<input type="radio" name="f__project" id="in_restaurant" value="restaurant"/>
<label for="in_restaurant">LEGO Project</label>
<br/>
<input type="radio" name="f__project" id="in_humber" value="Humber News"/>
<label for="in_humber">Humber Current Project</label>
<br/>
<input type="radio" name="f__project" id="in_self" value="self-determined"/>
<label for="in_self">Self-determined Project</label>
</p>
<button id='next-thing'>Next form control</button>
Use document.querySelector("input[name='f__project']:checked"). If this returns null, none of the radio buttons were checked, and you can display the red background.
If this is in a <form> you can add the required attribute to the radio buttons. If they try to submit the form without selecting one of them, the browser will display a validation error.
Use document.getElementById('id').checkedthe statement returns True or False.
const checkedRadioButton = document.
querySelector("input[name='f__project']:checked");
if (!checkedRadioButton) {
// No values are selected
} else {
// Some value is selected and the element is stored in checkedRadioButton
}
You can use CSS to manipulate the colour depending on whether the radio input is checked or not.
input[type="radio"] {
display: none;
}
input[type="radio"] + label {
border: 5px solid lightblue;
background-color: lightblue;
cursor: pointer;
display: block;
height: 40px;
width: 200px;
text-align: center;
line-height: 40px;
}
input[type="radio"]:checked + label {
border: 5px solid blue;
background-color: dodgerblue;
}
Or else you can make a Javascript function to check
function checkRadioValidity() {
if(document.getElementById('in_restaurant').checked) {
//change CSS here for the element
}
}
The idea of radio button is that it can not be unchecked.
EDIT:
document.querySelector("input[name='f__project']:checked")
will return element if it is checked

Set focus on input using javascript or css on text input that is hidden until user selects an option

I am editing an existing form with inputs that are hidden until the user clicks on an option, and then text input will appear. I need to get that specific text input to have active focus once that happens. I would love to do this with CSS because I am not great with javascript, but here is a portion of that code:
if ($("#frmSubmittedValue").val() == '') {
return false;
}
if ($("#frmSubmittedValue").val() == 'Individual')
$("#personSubmittedByValue").val('');
if ($("#frmProjectSub").val() == 0) {
return false;
}
Any help is greatly appreciated!
Who's afraid of some javascript? I've thrown in a little extra method select()
function show_it() {
document.querySelector("#f16").style.display = "block";
}
function focus_it() {
document.querySelector("#f16").focus();
}
function select_it() {
document.querySelector("#f16").select();
}
<button onclick="show_it(); focus_it(); select_it();">click</button>
<input id="f16" type="text" value="untitled" style="display:none">
You can set focus with jQuery using the code below:
$( "#other" ).click(function() {
$( "#target" ).focus();
});
There's a simple form example on the jQuery site here.
As for making the element visible, start off having the element you don't want shown to be display: none and has aria-hidden="true" (so screen-readers avoid) and a tabIndex="-1" (so the user can't tab to it). Then, using an if condition, set the properties to display: block, aria-hidden="false" and tabIndex="0".
I've put together a rough form with a few different input types. It's not perfect, but should give the general idea.
function makeMeVisible(id) {
$(id).parent().removeClass('hidden').attr('aria-hidden', 'false').attr('tabIndex', '0');
}
function makeMeVanish(id) {
$(id).parent().addClass('hidden').attr('aria-hidden', 'true').attr('tabIndex', '-1')
}
/* Select the first input and listen out for when it gets clicked */
$('#itemOne').on('click', function() {
/* If we are checked, run the makeMeVisible function and set focus to the next element we want shown */
if( $(this).is(':checked') ) {
makeMeVisible('#itemTwo');
$('#itemTwo').focus();
} else {
/* If we're not, make the item vanish and set the focus back to the original element */
makeMeVanish('#itemTwo');
$('#itemOne').focus();
}
})
/* Select elements need to listen for a change. When changes, get the selected option */
$('#itemTwo').on('change', function() {
/* Change what we do next based on what is chosen (looking at the value property) */
switch($('#itemTwo option:selected').val()) {
case "Value 1" :
makeMeVanish('#itemFive');
makeMeVisible('#itemFour');
$('#itemFour').focus();
break;
case "Value 2" :
makeMeVanish('#itemFour');
makeMeVisible('#itemFive');
$('#itemFive').focus();
break;
default:
/* If nothing is chosen, hide both */
makeMeVanish('#itemFour');
makeMeVanish('#itemFive');
}
})
.form-item + .form-item {
margin-top: 1rem;
}
.form-item {
display: block;
}
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="form-item"><label><input type="checkbox" id="itemOne">Item one</label></div>
<div class="form-item hidden" aria-hidden="true" tabIndex="-1">
<label for="itemTwo">Item two</label>
<select name="option" id="itemTwo">
<option>Select</option>
<option value="Value 1">Option one</option>
<option value="Value 2">Option two</option>
</select>
</div>
<div class="form-item hidden" aria-hidden="true" tabIndex="-1">
<label for="itemThree">Item three</label>
<input type="text" id="itemThree">
</div>
<div class="form-item hidden" aria-hidden="true" tabIndex="-1">
<label for="itemFour">Item four (Option one)</label>
<input type="text" id="itemFour">
</div>
<div class="form-item hidden" aria-hidden="true" tabIndex="-1">
<label for="itemFive">Item five (Option two)</label>
<input type="text" id="itemFive">
</div>
</form>

Generating dynamic ID's in HTML elements with jQuery

I'm builtin an web resume-generator to learn how to develop for web. I've made a HTML form which the user can add more fields to add more information's about him. Example: he has more than one professional experience, but the form starts with a single prof-exp field to fill. So he clicks in a "add new exp" button and the JS creates a new field for it. I used the clone() method from jQuery to do this, but this gives me with the problems I've listed bellow. Also, here's the code I've made:
var index = 0;
$(document).ready(() => {
$("#add-exp").click(() => {
$("#professional").clone().attr("id", "professional" + index++).
appendTo("#professional-info").find("select, input, textarea").val("");
})
})
<!DOCTYPE html>
<html>
<body>
<form action="" method="GET" id="main">
<fieldset id="professional-info">
<legend><h2>professional experience</h2></legend>
<div id="professional">
<label for="level">Nível: <select name="level" id="level" >
<option value="empty">Selecione</option>
<option value="estagio">Estágio</option>
<option value="junior-trainee">Junior/Trainee</option>
<option value="aux-opera">Auxiliar/Operacional</option>
<option value="pleno">Pleno</option>
<option value="senior">Sênior</option>
<option value="sup-coord">Supervisão/Coordenação</option>
<option value="gerencia">Gerência</option>
</select></label>
<label for="position"> Cargo: <input type="text" name="carrer" id="carrer" ></label><br>
<label for="company"> Empresa: <input type="text" name="company" id="company" ></label><br>
<label for="begin"> Início: <input type="month" name="begin" id="begin" ></label>
<label for="break"> Término: <input type="month" name="break" id="break" ></label>
<label for="stl-work"><input type="checkbox" name="stl-work" id="stl-work" >Ainda trabalho aqui</label><br>
<label for="job-desc"> Descrição: <textarea name="job-desc" id="job-desc" placeholder="Conte um pouco sobre o que você fazia lá." cols="40" rows="1"></textarea></label>
<button type="button" id="remove-exp" >Remove this professional xp</button>
</div>
<button type="button" form="main" id="add-exp">Add other professional exp</button>
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</body>
</html>
The problems are:
Only the divs have dynamic ID's, which causes me the following two other problems;
I don't know how to implement the remove button logic, since I cannot make difference between the 1st button and the other ones from other divs;
Since the labels use their correspondent input ID to make reference, when the user clicks it, they point to the first field inputs;
I hope you guys could understand my problem and help me with it. Also, sorry for my english - i'm learning too. Thank you all!
As suggested, Vue.js is cool, but jQuery has some forgotten powers too.
And, since you create elements dynamically, don't use IDs.
And submit to the backend your experiences as arrays []: i.e: name="carrer[]", name="company[]" etc. Than on the backend loop those data arrays to retrieve all the user experiences.
const new_exp = () => $('<div>', {
'class': 'professional-exp',
html: `
<label>Nível:
<select name="level[]">
<option value="empty">Selecione</option>
<option value="estagio">Estágio</option>
<!-- etc... -->
</select>
</label>
<label>Cargo: <input type="text" name="carrer[]"></label><br>
<label>Empresa: <input type="text" name="company[]"></label><br>
<label>Início: <input type="month" name="begin[]"></label>
<label>Término: <input type="month" name="break[]" ></label>
<label><input type="checkbox" name="stl-work[]"> Ainda trabalho aqui</label><br>
<label>Descrição: <textarea name="job-desc[]" placeholder="Conte um pouco sobre o que você fazia lá." cols="40" rows="1"></textarea></label><br>
`,
append: $('<button>', {
type: 'button',
text: 'Remove',
click() {
$(this).closest('.professional-exp').remove();
}
}),
appendTo: '#professional',
});
jQuery($ => { // DOM ready and $ alias in scope
new_exp(); // On init (Create first exp)
$("#new_exp").on('click', new_exp); // On click
});
.professional-exp {
padding: 10px;
margin-bottom: 10px;
background: #eee;
}
<form action="" method="POST" id="main">
<fieldset>
<legend>
<h2>Professional experience</h2>
</legend>
<div id="professional"></div>
<button type="button" id="new_exp">+ Add more</button>
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Above we're defining the Remove's button action right within the template, but if you want you can also hardcode the button into the template and create a dynamic click handler (using jQuery's .on()) like:
const exp_new = () => $('<div>', {
'class': 'professional-exp',
html: `
<label>Nível:
<select name="level[]">
<option value="empty">Selecione</option>
<option value="estagio">Estágio</option>
<!-- etc... -->
</select>
</label>
<label>Cargo: <input type="text" name="carrer[]"></label><br>
<label>Empresa: <input type="text" name="company[]"></label><br>
<label>Início: <input type="month" name="begin[]"></label>
<label>Término: <input type="month" name="break[]" ></label>
<label><input type="checkbox" name="stl-work[]"> Ainda trabalho aqui</label><br>
<label>Descrição: <textarea name="job-desc[]" placeholder="Conte um pouco sobre o que você fazia lá." cols="40" rows="1"></textarea></label><br>
<button class="exp_delete">REMOVE</button>
`,
appendTo: '#professional',
});
jQuery($ => { // DOM ready and $ alias in scope
exp_new(); // On init (Create first exp)
$("#exp_new").on('click', exp_new); // and on click.
$('#main').on('click', '.exp_delete', ev => $(ev.target).closest('.professional-exp').remove());
});
.professional-exp {
padding: 10px;
margin-bottom: 10px;
background: #eee;
}
<form action="" method="POST" id="main">
<fieldset>
<legend>
<h2>Professional experience</h2>
</legend>
<div id="professional"></div>
<button type="button" id="exp_new">+ Add more</button>
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Details of demo code are commented in the code itself. There are minor changes to some classes for <fieldset>s and <button>s. The structure is altered a little so keep that in mind. jQuery is versatile and it allows you to generalize DOM operations and do away with dependency on ids -- it's very possible to just use classes.
Events registered to dynamic tags fail unless you delegate events. To delegate a click event to all buttons existing currently and in the future, register an ancestor tag that the buttons commonly share (ex. #main). Then assign the selectors of the buttons in the second parameter (event data):
$('#main').on('click', '.add, .remove', function(e) {...
As for removing a by clicking a nested button -- $(e.target) and $(this) can be used to reference the button that was currently clicked. When you need to find the appropriate ancestor of a clicked button (ex. .professional) use .closest() method like so:
$(e.target).closest('.professional').remove();
Demo
let index = 0;
// Hide the first .remove button
$('#remove').hide();
/*
Register the form to the click event
Event data directs .add and .remove buttons
*/
$("#main").on('click', '.add, .remove', function(e) {
// if the clicked button has .add
if ($(this).hasClass('add')) {
/*
clone the first .professional
increment counter
Reference all form controls of the clone
on each form control modify its id
*/
const dupe = $(".professional:first").clone(true, true);
index++;
const formControls = dupe.find('select, button, input, textarea');
formControls.each(function() {
let ID = $(this).attr('id');
$(this).attr('id', ID + index);
});
/*
Remove the legend from clone
Show the .add and .remove on clone
Hide the clicked button
Add clone to form
Stop event bubbling
*/
dupe.find('legend').remove();
dupe.find('.add, .remove').show();
$(e.target).hide();
$('#main').append(dupe);
e.stopPropagation();
// Otherwise if clicked button has .remove...
} else if ($(e.target).hasClass('remove')) {
/*
Find clicked button ancestor .professional and remove
it.
Hide all .add buttons
Show the last .add
Stop event bubbling
*/
$(e.target).closest('.professional').remove();
$('.add').hide();
$('.add:last').show();
e.stopPropagation();
} else {
// Otherwise just stop event bubbling
e.stopPropagation();
}
});
:root {
font: 400 14px/1 Consolas
}
fieldset {
width: fit-content
}
legend {
margin-bottom: -15px
}
label {
display: block
}
input,
select,
button {
display: inline-block;
font: inherit;
height: 3ex;
line-height: 3ex;
vertical-align: middle
}
.text input {
width: 24ch
}
select {
line-height: 4ex;
height: 4ex;
}
label b {
display: inline-block;
width: 7.5ch;
}
button {
position: absolute;
display: inline-block;
height: initial;
margin: 0;
}
.add {
position: absolute;
right: 0;
}
[for=level] b {
width: 6ch
}
.btn-grp {
position: relative;
width: 97%;
min-height: 26px;
padding: 0
}
<!DOCTYPE html>
<html>
<head></head>
<body>
<form action="" method="GET" id="main">
<fieldset class="professional">
<legend>
<h2>Professional Experience</h2>
</legend>
<label for="level">
<b>Nível: </b>
<select name="level" id="level">
<option value="empty">Selecione</option>
<option value="estagio">Estágio</option>
<option value="junior-trainee">
Junior/Trainee
</option>
<option value="aux-opera">
Auxiliar/Operacional
</option>
<option value="pleno">Pleno</option>
<option value="senior">Sênior</option>
<option value="sup-coord">
Supervisão/Coordenação
</option>
<option value="gerencia">
Gerência
</option>
</select>
</label>
<fieldset class='text'>
<label for="carrier"><b>Cargo: </b>
<input type="text" name="carrer" id="carrer">
</label>
<label for="company"><b>Empresa: </b>
<input type="text" name="company" id="company">
</label>
<label for="begin"><b>Início: </b>
<input type="month" name="begin" id="begin">
</label>
<label for="break"><b>Término: </b>
<input type="month" name="break" id="break">
</label>
</fieldset>
<label for="stl-work">
<input type="checkbox" name="stl-work" id="stl-work" >Ainda trabalho aqui
</label>
<label for="job-desc"><b>Descrição: </b></label>
<textarea name="job-desc" id="job-desc" placeholder="Conte um pouco sobre o que você fazia lá." cols="35" rows="1"></textarea>
<fieldset class='btn-grp'>
<button type="button" id='remove' class='remove'>Remove</button>
<button type="button" id='add' class="add">Add</button>
</fieldset>
</fieldset>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</body>
</html>
if you already wrap your input inside a label, you dont need id anymore,
and you can use this as a parameter of delete button, so you can use it to delete your block.
Please check the following example
$(function(){
// keep the first block hidden as an empty template
$('.form-row:first').hide();
// trigger add new item
AddItem();
})
function AddItem(){
var container = $('#container');
// clone the form, show it & append before add button
var cloned = $('.form-row:first').clone().show().insertBefore($('#addBtn'));
}
function RemoveItem(elm){
// get form element & remove it
$(elm).closest('.form-row').remove()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style type="text/css">
.form-row {border:1px solid #ccc; margin:5px 0;padding:10px;}
</style>
<div id="container">
<div class="form-row">
<!-- wrap your input inside label tag to avoid using id as reference -->
<label>Field 1 : <input type="text" name="field1"></label>
<label>Field 2 : <input type="text" name="field2"></label>
<input type="button" value="Remove this item" onclick="RemoveItem(this)">
</div>
<input id="addBtn" type="button" value="Add new item" onclick="AddItem()">
</div>
One way to connect your new "remove" button with its "professional" div would be to add an extra statement in your event handler to update its id parallel to the new div's id, something like:
let lastIndex = index - 1;
$("#professional" + lastIndex).find("button").attr("id", "add-exp" + lastIndex);
(This code may not have the correct syntax -- I don't use jQuery very much -- but you can see the idea.)
A better way might be, when the "remove" button is clicked, don't remove according to ID, but instead find the closest ancestor div and remove that div.
For labels, you should leave out the ids (because no two elements on the same page should ever have the same id). And because the inputs are nested in the labels, you should be able to leave out the for attribute as well and let the the association be implicit. (See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label.)

How to align checkboxes horizontally next to each other and show form upon click?

i have been searching stackoverflow but, I am unable to find a solution pertaining to my problem. What i want is when a user clicks a checkbox, a form shows up. I managed to get one checkbox and make the form show up, but having trouble putting checkboxes side by side next to each other. So what i want is:
[] residential [] commercial [] industrial.
When a user clicks the above boxes, a form opens up on the same page. My code:
edit: Thanks to #brk for the solution. After copying the solution below, for some reason When i click on 'residential', i don't see anything popping up. My code:
<script>
// Add event listener to each of the radio button
document.querySelectorAll('input[name="selectType"]').forEach(function(item) {
item.addEventListener('click', function(e) {
// get the data-type from this, this data-type will be used to
// hide show relevant form
let name = this.getAttribute('data-type');
// hide previously displayed form
if (document.querySelector('.formDisplay') !== null) {
document.querySelector('.formDisplay').classList.remove('formDisplay');
}
// find the form whose name+_info is same as the name of the form
// & add a formDisplay to it
document.querySelector('form[name="' + name + '_info"]').classList.add('formDisplay');
})
})
</script>
<style>
form {
display: none;
}
.formDisplay {
display: block;
}
</style>
<html>
<body>
<div class="form-group">
<input id="checkboxR" data-type='res' name='selectType' type='radio'>
<label for="checkboxR">Residential</label>
<input id="checkboxC" data-type='com' name='selectType' type='radio'>
<label for="checkboxC">Commercial</label>
<input id="checkboxI" data-type='ind' name='selectType' type='radio'>
<label for="checkboxI">Industrail</label>
</div>
<form name="res_info" action="/result/" method="get" class="form-horizontal" role="form">
Residential Form
</form>
<form name="com_info" action="/result/" method="get" class="form-horizontal" role="form">
Commercial Form
</form>
<form name="ind_info" action="/result/" method="get" class="form-horizontal" role="form">
Industrial Form
</form>
</body>
</html>
So, I see 3 radio buttons, but clicking on them doesn't open up anything. Sorry im kinda new to html/css so this concept is new.
Make changes in your html and add another attribute data-type .This value will be used to display corresponding form.
Create tep css and initially hide all the forms. Add another class to display the form using display:block
Onclick of the radio button get the data-type find the forma whose name matches with this data-type and display that form
// Add event listener to each of the radio button
document.querySelectorAll('input[name="selectType"]').forEach(function(item) {
item.addEventListener('click', function(e) {
// get the data-type from this, this data-type will be used to
// hide show relevant form
let name = this.getAttribute('data-type');
// hide previously displayed form
if (document.querySelector('.formDisplay') !== null) {
document.querySelector('.formDisplay').classList.remove('formDisplay');
}
// find the form whose name+_info is same as the name of the form
// & add a formDisplay to it
document.querySelector('form[name="' + name + '_info"]').classList.add('formDisplay');
})
})
form {
display: none;
}
.formDisplay {
display: block;
}
<body>
<div class="form-group">
<input id="checkboxR" data-type='res' name='selectType' type='radio'>
<label for="checkboxR">Residential</label>
<input id="checkboxC" data-type='com' name='selectType' type='radio'>
<label for="checkboxC">Commercial</label>
<input id="checkboxI" data-type='ind' name='selectType' type='radio'>
<label for="checkboxI">Industrail</label>
</div>
<form name="res_info" action="/result/" method="get" class="form-horizontal" role="form">
Residential Form
</form>
<form name="com_info" action="/result/" method="get" class="form-horizontal" role="form">
Commercial Form
</form>
<form name="ind_info" action="/result/" method="get" class="form-horizontal" role="form">
Industrial Form
</form>
</body>
This worked for me
<body>
<div class="form-group">
<div class="horizontal">
<input id="checkbox" type=checkbox> Residential</input>
</div>
<div class="horizontal" id="delivery_div" style="display:none">
<input id="delivery" type=checkbox > etc </input>
</div>
</div>
<script>
var checkbox = document.getElementById('checkbox');
var delivery_div = document.getElementById('delivery_div');
checkbox.onclick = function() {
console.log(this);
if(this.checked) {
delivery_div.style['display'] = 'block';
} else {
delivery_div.style['display'] = 'none';
}
};
</script>
<style>
<body>
<div class="form-group">
<div class="horizontal">
<input id="checkbox" type=checkbox> Residential</input>
</div>
<div class="horizontal" id="delivery_div" style="display:none">
<input id="delivery" type=checkbox > etc </input>
</div>
</div>
<script>
var checkbox = document.getElementById('checkbox');
var delivery_div = document.getElementById('delivery_div');
checkbox.onclick = function() {
console.log(this);
if(this.checked) {
delivery_div.style['display'] = 'block';
} else {
delivery_div.style['display'] = 'none';
}
};
</script>
<style>
.horizontal {
display: inline-block;
float:left;
}
</style>
</body>
.horizontal {
display: inline-block;
float:left;
}
</style>
</body>

check if all inputs are checked

I have 2 buttons and 2 inputs. The "buy"-button should only fire its default function when both inputs are checked. If not it should mark them with a red border. What am I doing wrong here?
jQuery(function($) {
$('.checkedterms:checked').length == $('.checkedterms').length
$("#upsellyes").click(function(e) {
$(".checkedterms").change(function(){
if (!$('.checkedterms:checked').length == $('.checkedterms').length) {
e.preventDefault();
$("#terms-required").addClass('invalid');
}
else {
$("#terms-required").removeClass('invalid');
}
});
});
});
.invalid {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="terms-required">
<input type="checkbox" class="checkedterms" name="terms" id="terms" style="position: absolute;"><label for="terms" class="checkbox" style="display: inline-block!important;font-weight:normal!important;margin-left: 25px;">I have read <a href="#" >Allgemeinen Geschäftsbedingungen</a>.<span class="required">*</span></label><br />
<input type="checkbox" class="checkedterms" name="terms" id="terms" style="position: absolute;"><label for="terms" class="checkbox" style="display: inline-block!important;font-weight:normal!important;margin-left: 25px;">I have read <a href="#" >Widerrufsbelehrung</a>.<span class="required">*</span></label><br />
</div><br>
buy<br><br>
no thanks
There's a couple of issues here:
You've got an equality check at the start of the code which does nothing.
You've nested the change handler on the checkboxes within the click handler of the button; remove it.
Unrelated to the issue, but you are using duplicate id attributes. They need to be unique within the DOM.
Your logic is backwards. You state that you want the red border to only appear when both checkboxes are not checked when the 'Buy' button is clicked.
You can also make the logic more succinct by caching the checkbox selector and using toggleClass(). Something like this:
jQuery(function($) {
$("#upsellyes").click(function(e) {
var $terms = $('.checkedterms');
$("#terms-required").toggleClass('invalid', $terms.length != $terms.filter(':checked').length);
});
});
.invalid {
border: 1px solid red;
}
.checkedterms {
position: absolute;
}
label {
display: inline-block!important;
font-weight: normal!important;
margin-left: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="terms-required">
<input type="checkbox" class="checkedterms" name="terms" />
<label for="terms" class="checkbox">
I have read Allgemeinen Geschäftsbedingungen.
<span class="required">*</span>
</label><br />
<input type="checkbox" class="checkedterms" name="terms" />
<label for="terms" class="checkbox">
I have read <a href="#" >Widerrufsbelehrung</a>.
<span class="required">*</span>
</label><br />
</div><br />
buy<br><br>
no thanks
Finally note the use of a separate stylesheet. Inline styling is a bad idea and should be avoided where possible.
remove this line
$(".checkedterms").change(function(){ //remove
//keep the code that's currently here
}); //remove
leaving you with
jQuery(function($) {
$('.checkedterms:checked').length == $('.checkedterms').length
$("#upsellyes").click(function(e) {
if ($('.checkedterms:checked').length != $('.checkedterms').length) {
e.preventDefault();
$("#terms-required").addClass('invalid');
}
else {
$("#terms-required").removeClass('invalid');
}
});
});
the code wasn't running because you were setting an event listener on the checkboxes inside the event listener on the button. what was happening is that when you clicked the button, javascript would set an event listener on the checkboxes that fires when their state changes
You need an if statement at line 2 and one more '='
if ($('.checkedterms:checked').length === $('.checkedterms').length) {
....
}
and you should put an eventListener each input change

Categories

Resources