Strange alphabetical sorting of checkbox lists [duplicate] - javascript

This question already has answers here:
Sorting an array of objects by property values
(35 answers)
Closed 6 years ago.
I have 4 checkboxes, each representing a region. Clicking any one of them shows 3 countries relevant to that region. Clicking combinations of the regional checkboxes shows all the relevant countries in-line, but I want
the list of country checkboxes to always be displayed in alphabetical order.
Strangely my jquery seemed to work for 3 regional checkboxes, but doesn't seem to work for 4. I just can't see what dumb mistake I'm making and am starting to suspect something more sinister. Here's my fiddle: https://jsfiddle.net/m5v7v6kv/
Thanks for any help.
function sortByText(a, b) {
return $.trim($(a).text()) > $.trim($(b).text());
}
var li = $(".CountryWrapper").children("label").detach().sort(sortByText)
$(".CountryWrapper").append(li)
$('input[type="checkbox"]').click(function() {
$('.my' + $(this).attr("id")).slideToggle(200)
})
.CountryWrapper {
border: 1px solid blue;
height: 150px;
width: 480px;
border: 1px solid blue;
}
.myEuropeCountries {
display: none;
}
.myNAMCountries {
display: none;
}
.mySAMCountries {
display: none;
}
.myAfricaMECountries {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label><input type="checkbox" id="EuropeCountries" />Europe</label>
<label><input type="checkbox" id="NAMCountries" />North America</label>
<label><input type="checkbox" id="SAMCountries" />South America</label>
<label><input type="checkbox" id="AfricaMECountries" />Africa and Middle East</label>
<div class="CountryWrapper">
<br>
<label class="myEuropeCountries"><input type="checkbox" value="Spain" />Spain</label>
<label class="myEuropeCountries"><input type="checkbox" value="Germany" />Germany</label>
<label class="myEuropeCountries"><input type="checkbox" value="Austria" />Austria</label>
<label class="myNAMCountries"><input type="checkbox" value="USA" />USA</label>
<label class="myNAMCountries"><input type="checkbox" value="Mexico" />Mexico</label>
<label class="myNAMCountries"><input type="checkbox" value="Canada" />Canada</label>
<label class="mySAMCountries"><input type="checkbox" value="Brazil" />Brazil</label>
<label class="mySAMCountries"><input type="checkbox" value="Argentina" />Argentina</label>
<label class="mySAMCountries"><input type="checkbox" value="Chile" />Chile</label>
<label class="myAfricaMECountries"><input type="checkbox" value="SouthAfrica" />South Africa</label>
<label class="myAfricaMECountries"><input type="checkbox" value="Egypt" />Egypt</label>
<label class="myAfricaMECountries"><input type="checkbox" value="SaudiArabia" />Saudi Arabia</label>
</div>

Looks like your compare function should return 1 or -1. There is really no reason to return 0 in your case unless somehow two countries will have the same name.
return $.trim($(a).text()) > $.trim($(b).text()) ? 1 : -1;
function sortByText(a, b) {
return $.trim($(a).text()) > $.trim($(b).text()) ? 1 : -1;
}
var li = $(".CountryWrapper").children("label").detach().sort(sortByText)
$(".CountryWrapper").append(li)
$('input[type="checkbox"]').click(function() {
$('.my' + $(this).attr("id")).slideToggle(200)
})
.CountryWrapper {
border: 1px solid blue;
height: 150px;
width: 480px;
border: 1px solid blue;
}
.myEuropeCountries {
display: none;
}
.myNAMCountries {
display: none;
}
.mySAMCountries {
display: none;
}
.myAfricaMECountries {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>
<input type="checkbox" id="EuropeCountries" />Europe</label>
<label>
<input type="checkbox" id="NAMCountries" />North America</label>
<label>
<input type="checkbox" id="SAMCountries" />South America</label>
<label>
<input type="checkbox" id="AfricaMECountries" />Africa and Middle East</label>
<!-------------------------------------------------------------------->
<div class="CountryWrapper">
<br>
<label class="myEuropeCountries">
<input type="checkbox" value="Spain" />Spain</label>
<label class="myEuropeCountries">
<input type="checkbox" value="Germany" />Germany</label>
<label class="myEuropeCountries">
<input type="checkbox" value="Austria" />Austria</label>
<label class="myNAMCountries">
<input type="checkbox" value="USA" />USA</label>
<label class="myNAMCountries">
<input type="checkbox" value="Mexico" />Mexico</label>
<label class="myNAMCountries">
<input type="checkbox" value="Canada" />Canada</label>
<label class="mySAMCountries">
<input type="checkbox" value="Brazil" />Brazil</label>
<label class="mySAMCountries">
<input type="checkbox" value="Argentina" />Argentina</label>
<label class="mySAMCountries">
<input type="checkbox" value="Chile" />Chile</label>
<label class="myAfricaMECountries">
<input type="checkbox" value="SouthAfrica" />South Africa</label>
<label class="myAfricaMECountries">
<input type="checkbox" value="Egypt" />Egypt</label>
<label class="myAfricaMECountries">
<input type="checkbox" value="SaudiArabia" />Saudi Arabia</label>
</div>

Related

Javascript for PDF form validation

The code is working fine. I want to add an option of selecting at least one check box out of 7. I am not sure how to do.
var emptyFields = [];
for (var i = 0; i < this.numFields; i++) {
var f = this.getField(this.getNthFieldName(i));
if (f.type != "button" && f.required) {
if ((f.type == "text" && f.value == "") || (f.type == "checkbox" && f.value == "Off") || (f.type == "signature" && f.value == "")) emptyFields.push(f.name);
}
}
if (emptyFields.length > 0) {
app.alert("Error! Please fill all red highlighted fields")
} else {
print();
}
You just need to change a bit the logic you have there:
Create a new array checkedCheckboxes.
Store there the elements where f.type === "checkbox" && f.checked === true.
Lastly, check if checkedCheckboxes.length === 0 and show the appropiate error message, just how you did with emptyFields.
Edit: Working example:
// Get a reference to the error box:
const errorBox = document.getElementById('errorBox');
// To the validate button:
const validateButton = document.getElementById('validateButton');
// And to all input elements:
const inputs = document.querySelectorAll('input');
function validateForm() {
// Reset the error box:
errorBox.innerHTML = '';
// Here we'll keep track of empty text inputs:
const emptyFields = [];
// And here we'll keep track of how many selected checkboxes each
// group has:
const checkedCheckboxesByGroup = {
checkboxes: 0,
checkboxes2: 0,
};
Array.from(inputs).map((input) => {
if (input.type === "text" && input.value === "") {
// Keep track of empty inputs:
emptyFields.push(input);
}
if (input.type === "checkbox" && input.checked) {
// Get the checkbox group (name attribute without the
// square brackets):
const groupName = input.name.slice(0, -2);
// Increment this counter:
++checkedCheckboxesByGroup[groupName];
}
});
if (emptyFields.length > 0) {
errorBox.innerHTML += "<p>All fields are required.</p>";
}
Object.entries(checkedCheckboxesByGroup).map(([groupName, checkedCheckboxes]) => {
if (checkedCheckboxes === 0)
errorBox.innerHTML += `<p>You need to select at least one element in ${ groupName }.</p>`;
});
}
// Validate the form every time we click the button:
validateButton.addEventListener('click', validateForm);
body,
input,
button {
font-family: monospace;
}
p {
margin: 0;
}
.label {
display: block;
border: 0;
margin: 0 0 16px;
padding: 0;
}
.labelTitle {
display: block;
margin-bottom: 4px;
}
input[type="text"],
button {
border: 2px solid black;
padding: 8px;
border-radius: 2px;
background: white;
}
.checkboxLabel {
display: block;
position: relative;
padding: 8px 8px 8px 32px;
}
input[type="checkbox"] {
position: absolute;
top: 50%;
left: 16px;
transform: translate(-50%, -50%);
margin: 0;
}
#errorBox {
border: 2px solid red;
padding: 8px;
border-radius: 2px;
margin-bottom: 16px;
}
#errorBox > p + p {
margin-top: 16px;
}
#errorBox:empty {
display: none;
}
<label class="label">
<span class="labelTitle">Field 1</span>
<input type="text" placeholder="Field 1" />
</label>
<label class="label">
<span class="labelTitle">Field 1</span>
<input type="text" placeholder="Field 1" />
</label>
<label class="label">
<span class="labelTitle">Field 1</span>
<input type="text" placeholder="Field 1" />
</label>
<fieldset class="label">
<span class="labelTitle">Checkboxes Group 1</span>
<label class="checkboxLabel"><input type="checkbox" value="1" name="checkboxes[]" />Checkbox 1</label>
<label class="checkboxLabel"><input type="checkbox" value="2" name="checkboxes[]" />Checkbox 2</label>
<label class="checkboxLabel"><input type="checkbox" value="3" name="checkboxes[]" />Checkbox 3</label>
<label class="checkboxLabel"><input type="checkbox" value="4" name="checkboxes[]" />Checkbox 4</label>
<label class="checkboxLabel"><input type="checkbox" value="5" name="checkboxes[]" />Checkbox 5</label>
<label class="checkboxLabel"><input type="checkbox" value="6" name="checkboxes[]" />Checkbox 6</label>
<label class="checkboxLabel"><input type="checkbox" value="7" name="checkboxes[]" />Checkbox 7</label>
</fieldset>
<fieldset class="label">
<span class="labelTitle">Checkboxes Group 2</span>
<label class="checkboxLabel"><input type="checkbox" value="10" name="checkboxes2[]" />Checkbox 10</label>
<label class="checkboxLabel"><input type="checkbox" value="20" name="checkboxes2[]" />Checkbox 20</label>
<label class="checkboxLabel"><input type="checkbox" value="30" name="checkboxes2[]" />Checkbox 30</label>
<label class="checkboxLabel"><input type="checkbox" value="40" name="checkboxes2[]" />Checkbox 40</label>
<label class="checkboxLabel"><input type="checkbox" value="50" name="checkboxes2[]" />Checkbox 50</label>
<label class="checkboxLabel"><input type="checkbox" value="60" name="checkboxes2[]" />Checkbox 60</label>
<label class="checkboxLabel"><input type="checkbox" value="70" name="checkboxes2[]" />Checkbox 70</label>
</fieldset>
<div id="errorBox"></div>
<button id="validateButton">Validate Form</button>

How to prevent user from selecting next collapsible item until previous responses are filled?

I am trying to write a basic form in Flask which is just a single page right now. The user first types in their name, then they can answer their gender, and finally respond what transportation method they use. But I need them to do be able to do this sequentially, so they cannot answer their transportation method until the previous two responses have been typed or selected. This is a learning exercise, so I also want to aim this to be on a single page.
The following html/css/javascript code shows the rudimentary basics of what I have currently. All three topic questions are in a collapsible field. So I want the user unable to click on the following collapsible fields until the previous field has a response. I was thinking that this must be done in javascript, but I am unsure as to how I can do this.
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
.collapsible {
background-color: rgb(200, 211, 214);
color: black;
font-weight:bold;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active, .collapsible:hover {
background-color: brown;
}
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: beige;
<!DOCTYPE html>
<html lang="en">
<head>
<title>Form</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="background-color:rgb(172, 212, 245);overflow-x:hidden">
<button type="button" class="collapsible">Name</button>
<div class="content">
<p> Must fill out before heading to next section </p>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname" value="John"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname" value="Doe">
</div>
<br>
<button type="button" class="collapsible">Gender</button>
<div class="content">
<p> Must fill out before heading to next section </p>
<input type="radio" id="male" name="gender" value="male">
<label for="male">Male</label><br>
<input type="radio" id="female" name="gender" value="female">
<label for="female">Female</label><br>
<input type="radio" id="other" name="gender" value="other">
<label for="other">Other</label>
</div>
<br>
<button type="button" class="collapsible">Transportation</button>
<div class="content">
<input type="checkbox" id="vehicle1" name="vehicle1" value="Bike">
<label for="vehicle1"> I have a bike</label><br>
<input type="checkbox" id="vehicle2" name="vehicle2" value="Car">
<label for="vehicle2"> I have a car</label><br>
<input type="checkbox" id="vehicle3" name="vehicle3" value="Boat">
<label for="vehicle3"> I have a boat</label>
</div>
</body>
</html>
can you try this
coll[i].collapsible( "disable" );
you can disable the rest after first is answered enable the second and go on like this

Javascript conditionals not working on correct button combination

I have 5 if else conditions under function getRadioButtonValue. The function does not go through all the conditions even after clicking the right button combinations.
I have tried to debug the script using Chrome Developer tools but the problem still exists. Where is the code breaking?
Some information regarding the page, I am using Javascript to hide the div's and headers so that at any one time there is only one question seen.
Only the first if conditions work, but nothing else
The results are seen after Get Result button is clicked on the last page which should redirect to the appropriate page.
[DELETED CODE]
[UPDATED CODE]
I am unable to auto hide my div's based on the response given below by Keith.
FYI: His code works as expected.
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style>
.hidden {
display: none;
}
.visible {
display: block;
margin: 0 auto;
width: 650px;
height: 445px;
background: #EFDFBC;
}
</style>
</head>
<body>
<div id="first-question" class="visible">
<h3>How?</h3>
<ul>
<li>abc</li>
<li>def</li>
</ul>
<hr>
<input type="radio" name="quiz-question-one" id="quiz-question-one-yes" value="yes" />
<label for="quiz-question-one-yes" id="oneYes">Yes</label>
<input type="radio" name="quiz-question-one" id="quiz-question-one-no" value="no" />
<label for="quiz-question-one-no" id="oneNo">No</label>
</div>
<div id="second-question" class="hidden">
<h3>To</h3>
<hr>
<input type="radio" name="quiz-question-two" id="quiz-question-two-yes" value="yes" />
<label for="quiz-question-two-yes" id="twoYes">Yes</label>
<input type="radio" name="quiz-question-two" id="quiz-question-two-no" value="no" />
<label for="quiz-question-two-yes" id="twoNo">No</label>
</div>
<div id="third-question" class="hidden">
<h3>Make </h3>
<hr>
<input type="radio" name="quiz-question-three" id="quiz-question-three-yes" value="yes" />
<label for="quiz-question-three-yes" id="threeYes">Yes</label>
<input type="radio" name="quiz-question-three" id="quiz-question-three-no" value="no" />
<label for="quiz-question-three-yes" id="threeNo">No</label>
</div>
<div id="fourth-question" class="hidden">
<h3>This</h3>
<hr>
<input type="radio" name="quiz-question-four" id="quiz-question-four-yes" value="yes" />
<label for="quiz-question-four-yes" id="fourYes">Yes</label>
<input type="radio" name="quiz-question-four" id="quiz-question-four-no" value="no" />
<label for="quiz-question-four-yes" id="fourNo">No</label>
</div>
<div id="fifth-question" class="hidden">
<h3>Work?</h3>
<hr>
<input type="radio" name="quiz-question-five-yes" id="quiz-question-five-yes" value="yes" />
<label for="quiz-question-five-yes" id="fiveYes">Yes</label>
<input type="radio" name="quiz-question-five-no" id="quiz-question-five-no" value="no" />
<label for="quiz-question-five-yes" id="fiveNo">No</label>
</div>
<div class="page result">
<label>Results</label>
<div id="result"></div>
</div>
</body>
</html>
<script type="text/javascript">
var results = {};
function updateResult() {
var r = results,
rt = $('#result');
if (r.quiz-question-one && r.quiz-question-two && r.quiz-question-three && r.quiz-question-four && r.quiz-question-five) {
rt.text('All Yes');
} else if (!r.quiz-question-one && !r.quiz-question-two && !r.quiz-question-three && !r.quiz-question-four && !r.quiz-question-five) {
rt.text('All No');
} else {
rt.text('We have a mixed response');
}
}
$(function () {
$('body').on('click', '[name]', function () {
var $this = $(this),
page = $this.closest('.hidden'),
next_page = $(page.next());
results[$this.attr('name')] = $(this).val() === 'yes';
page.removeClass('visible');
next_page.addClass('visible');
if (next_page.hasClass('result')) updateResult();
});
});
</script>
I've created an example below that I think you can work from. The values from the radio I don't think get updated until you submit, instead I've captured the results in the onclick. You can now add back you CSS styling etc. Hope that helps.
var results = {};
function updateResult() {
var r = results,
rt = $('#result');
if (r.q1 && r.q2 && r.q3) {
rt.text('All Yes');
} else if (!r.q1 && !r.q2 && !r.q3) {
rt.text('All No');
} else {
rt.text('We have a mixed response');
}
}
$(function () {
$('body').on('click', '[name]', function () {
var $this = $(this),
page = $this.closest('.page'),
next_page = $(page.next());
results[$this.attr('name')] = $(this).val() === 'yes';
page.removeClass('active');
next_page.addClass('active');
if (next_page.hasClass('result')) updateResult();
});
});
.page {
display: none;
}
.page.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="page active">
<div>Question 1</div>
<label for="q1yes">Yes</label>
<input id="q1yes" type="radio" name="q1" value="yes">
<label for="q1no">No</label>
<input id="q1no" type="radio" name="q1" value="no">
</div>
<div class="page">
<div>Question 2</div>
<label for="q2yes">Yes</label>
<input id="q2yes" type="radio" name="q2" value="yes">
<label for="q2no">No</label>
<input id="q2no" type="radio" name="q2" value="no">
</div>
<div class="page">
<div>Question 3</div>
<label for="q3yes">Yes</label>
<input id="q3yes" type="radio" name="q3" value="yes">
<label for="q3no">No</label>
<input id="q3no" type="radio" name="q3" value="no">
</div>
<div class="page result">
<label>Results</label>
<div id="result"></div>
</div>
<input type="radio" id="quiz-question-one-yes" value="yes" />
<label for="quiz-question-one-yes" id="oneYes">Yes</label>
<input type="radio" id="quiz-question-one-no" value="no" />
<label for="quiz-question-one-no" id="oneNo">No</label>
In the above you are using type="radio", that means all type="radio" with the same name will group together, and not just these two. To group together just give them a name on the input. eg.
<input type="radio" name="quiz-question-one" id="quiz-question-one-yes" value="yes" />
<label for="quiz-question-one-yes" id="oneYes">Yes</label>
<input type="radio" name="quiz-question-one" id="quiz-question-one-no" value="no" />
<label for="quiz-question-one-no" id="oneNo">No</label>
Above you can see I've given the 2 inputs the name="quiz-question-one", and then for the next question maybe give them a name="quiz-question-two" etc..
On another note, there are lots of places where your code could be simplified, but hopefully this will solve your current problem.

Toggle checkbox - click on parent DIV element

I have few div elements and inside every div one checkbox.
On click this div I want to check/uncheck checkbox and add class like active or checked. Have some code if you have any idea.
<div class="filter">
<div id="select_10">
<input type="checkbox" name="what" />
visible1
</div>
<div id="select_91">
<input type="checkbox" name="ever" />
visible2
</div>
<div id="select_101">
<input type="checkbox" name="whatever" />
visible3
</div>
</div>
using this code:
$(document).on("click", "div.filter div", function (event) {
var target = $(event.target);
var id = $(this)attr('id');
if (target.is('div#'+id+' input:checkbox')) {
return;
}
var checkbox = $(this).find("input[type='checkbox']");
checkbox.prop("checked", !checkbox.is(':checked'));
});
$(this)attr('id'); should have a . like in
$(this).attr('id');
That's it.
Why using DIV and JS when we have <label> for that purpose!
.filter label {
cursor: pointer;
display: block;
background: #eee;
margin:5px; padding: 10px;
}
<div class="filter">
<label id="select_10">
<input type="checkbox" name="what" />
visible1
</label>
<label id="select_91">
<input type="checkbox" name="ever" />
visible2
</label >
<label id="select_101">
<input type="checkbox" name="whatever" />
visible3
</label >
</div>
all you need. Style label as you would for your DIV by just adding eventually display: block;
Or you can even move the inputs before the label and style the complete LABEL elements in pure CSS:
.filter input{
position: absolute;
visibility: hidden;
}
.filter label {
cursor: pointer;
display: block;
margin:5px; padding: 10px;
background: #eee;
}
.filter input:checked + label{
background: #cf5;
}
.filter label:before{content: "\2610";}
.filter input:checked + label:before{content: "\2611";}
<div class="filter">
<input id="ckb_10" type="checkbox" name="what" />
<label for="ckb_10">
what
</label>
<input id="ckb_91" type="checkbox" name="foo" />
<label for="ckb_91">
foo
</label>
</div>

Set Class from radio:checked to div corresponding with session id

I'm learning jquery and I'm hard to build this script.
I need to set the radio class: checked in some divs with class corresponding section of the options .. Good to understand better just give a look at this code.
Who can help since I am already grateful!
Html:
<form action="">
<div class="object" id="obj01">
<h3>Colors-01</h3>
<label class="cor01 cor">01<input type="radio" name="color01" class="rd"></label>
<label class="cor02 cor">02<input type="radio" name="color01" class="rd"></label>
<label class="cor03 cor">03<input type="radio" name="color01" class="rd"></label>
<label class="cor04 cor">04<input type="radio" name="color01" class="rd"></label>
<label class="cor05 cor">05<input type="radio" name="color01" class="rd"></label>
</div>
<div class="object" id="obj02">
<h3>Colors-02</h3>
<label class="cor01 cor">01<input type="radio" name="color02" class="rd"></label>
<label class="cor02 cor">02<input type="radio" name="color02" class="rd"></label>
<label class="cor03 cor">03<input type="radio" name="color02" class="rd"></label>
<label class="cor04 cor">04<input type="radio" name="color02" class="rd"></label>
<label class="cor05 cor">05<input type="radio" name="color02" class="rd"></label>
</div>
<div class="object" id="obj03">
<h3>Colors-03</h3>
<label class="cor01 cor">01<input type="radio" name="color03" class="rd"></label>
<label class="cor02 cor">02<input type="radio" name="color03" class="rd"></label>
<label class="cor03 cor">03<input type="radio" name="color03" class="rd"></label>
<label class="cor04 cor">04<input type="radio" name="color03" class="rd"></label>
<label class="cor05 cor">05<input type="radio" name="color03" class="rd"></label>
</div>
</form>
<div class="obj obj01">Color me</div>
<div class="obj obj02">Hey! More color</div>
<div class="obj obj03">Colorize!</div>
Js/jquery:
$('.cor').click(function() {
var cor = $(this).find('.rd:checked').parents().css('background-color');
var id = $(this).closest('.object').attr('id');
/** Need a script for set the first class from <label> with radio checked **/
$('.' + id).css('background-color', cor);
});
CSS:
.cor01{
background-color: yellow;
}
.cor02{
background-color: lightblue;
}
.cor03{
background-color: lightgreen;
}
.cor04{
background-color: coral;
}
.cor05{
background-color: pink;
}
.obj{
padding: 2em;
border: 1px dashed #333;
text-align: center;
}
I update my fiddle, setting selected class to same element that get the background, check if this satisfy your needs:
https://jsfiddle.net/oo1s4jm0/3/
Relevant code:
var classs = $(this).attr('class');
var first = classs.split(' ')[0];
var newClass = $('.' + id).attr('class');
var splited = newClass.split(' ');
if(splited.length > 2){
splited[2] = first;
$('.' + id).attr('class', splited.join(' '));
}else{
$('.' + id).addClass(first);
}

Categories