Changing current text for custom HTML dropdowns - javascript

I'm creating a set of dropdowns with a custom look so I've built these using divs and checkboxes rather than the usual element
I'm looking to change the 'select-wrapper--title' text (e.g. the first option) to whatever is selected in the dropdown
I'm having some trouble doing this with multiple dropdowns, it seems to change the title for all of them instead of just the dropdown I'm interacting with. I think I need a loop but I'm not sure how to go about this logic
I've created a JSFiddle of my code here: https://jsfiddle.net/m9h32nzq/6/
But here is the code here too:
$(function() {
$(".filter-grid .select-wrapper--title").on("click", function() {
var index = $(this).index(".select-wrapper--title");
console.log(index);
if ($(".select-wrapper.open").length >= 1) {
if ($(this).parents(".select-wrapper").hasClass("open")) {
$(".filter-grid .select-wrapper.open").removeClass("open");
} else {
//Close other filter boxes if open
$(".filter-grid .select-wrapper.open").removeClass("open");
$(".filter-grid .select-wrapper").eq(index).addClass("open");
}
} else {
$(".filter-grid .select-wrapper").eq(index).addClass("open");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-grid">
<div class="select-filter">
<div class="select-wrapper">
<label class="select-wrapper--title">No. of Nights</label>
<div class="select-wrapper--dropdown">
<label class="select-item">
<input type="checkbox" class="checkbox" value="">
1 Night
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="">
2 Nights
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="">
3 Nights
</label>
</div>
</div>
</div>
<div class="select-filter">
<div class="select-wrapper">
<label class="select-wrapper--title">No. of People</label>
<div class="select-wrapper--dropdown">
<label class="select-item">
<input type="checkbox" class="checkbox" value="">
1 Person
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="">
2 People
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="">
3 People
</label>
</div>
</div>
</div>
</div>

Assuming I've understood what you're asking, you want the text label for the dropdown to be filled with the text labels of the selected checkboxes within each instance.
To do this you simply need to use DOM traversal to find the checked boxes within the current dropdown. From there you can build an array of their values using map(). You can also provide a default value for the dropdown in a data attribute for the cases where no checkboxes are selected.
Also note that you can massively simplify the code you're using to show/hide the dropdown options. All you need is toggleClass().
Taking this a step further, you can hook an event handler to the document to hide the dropdown when the user clicks outside of it.
With all that said, here's a working example updated to ES6.
jQuery($ => {
// show dropdown on click inside
$(".filter-grid .select-wrapper--title").on("click", e => {
e.stopPropagation();
$(e.currentTarget).closest('.select-wrapper').toggleClass('open');
});
// hide dropdowns on click outside
$(document).on('click', e => {
if ($(e.target).closest('.select-filter').length == 0)
$('.select-wrapper').removeClass('open');
});
// set dropdown text on checkbox update
$('.filter-grid :checkbox').on('change', e => {
let $container = $(e.target).closest('.select-wrapper');
let values = $container.find(':checkbox:checked').map((i, el) => el.value).get().join(', ');
if (!values)
values = $container.find('.select-wrapper--title').data('default');
$container.find('.select-wrapper--title').text(values);
});
});
.filter-grid {
margin-bottom: 10px;
max-width: 300px
}
.filter-grid .select-filter {
padding: 5px 10px 5px 0;
z-index: 99
}
.filter-grid .select-filter .select-wrapper {
flex: 0 0 100%;
display: block;
position: relative;
width: 100%
}
.filter-grid .select-filter .select-wrapper:after {
border: 5px solid transparent;
border-right-color: orange;
border-bottom-color: orange;
position: absolute;
top: 16px;
right: 15px;
content: "";
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
z-index: 1
}
.filter-grid .select-filter .select-wrapper .select-wrapper--title {
position: relative;
display: block;
font-weight: 500;
cursor: pointer;
border: 2px solid orange;
padding: 12px 35px 12px 20px;
color: orange;
font-family: museo-slab, serif
}
.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown {
overflow-y: hidden;
max-height: 0;
position: relative;
z-index: 9;
background: white;
box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.4);
opacity: 1;
visibility: hidden;
min-width: 150px;
overflow: hidden
}
.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown div {
padding: 10px
}
.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown .select-item {
display: block;
width: 100%;
line-height: normal;
padding: 5px 0 5px 17px
}
.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown .select-item .checkbox {
top: 7px
}
.filter-grid .select-filter .select-wrapper.open .select-wrapper--dropdown {
max-height: 250px;
overflow-y: auto;
opacity: 1;
visibility: visible
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="filter-grid">
<div class="select-filter">
<div class="select-wrapper">
<label class="select-wrapper--title" data-default="No. of Nights">No. of Nights</label>
<div class="select-wrapper--dropdown">
<label class="select-item">
<input type="checkbox" class="checkbox" value="1 Night">
1 Night
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="2 Nights">
2 Nights
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="3 Nights">
3 Nights
</label>
</div>
</div>
</div>
<div class="select-filter">
<div class="select-wrapper">
<label class="select-wrapper--title" data-default="No. of People">No. of People</label>
<div class="select-wrapper--dropdown">
<label class="select-item">
<input type="checkbox" class="checkbox" value="1 Person">
1 Person
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="2 People">
2 People
</label>
<label class="select-item">
<input type="checkbox" class="checkbox" value="3 People">
3 People
</label>
</div>
</div>
</div>
</div>
One last thing to note is that the values in your controls don't make sense. A user shouldn't be allowed to select multiple selections from wither dropdown. For example, how can I possibly book '1 Night' and '3 Nights' at the same time? I assume this is because this is just a learning exercise, and not for a production system.

I made the following changes to your code:
type="radio" instead of type="checkbox" so you dont need additional logic to uncheck other boxes
Wrap the dropdown item text in a span so you can read it easily
Added JS code at the bottom which does what you eventually want.
<div class="select-filter">
<div class="select-wrapper">
<label class="select-wrapper--title">No. of Nights</label>
<div class="select-wrapper--dropdown">
<label class="select-item">
<input type="radio" class="checkbox" name="item" value="">
<span>1 Night</span>
</label>
<label class="select-item">
<input type="radio" class="checkbox" name="item" value="">
<span>2 Nights</span>
</label>
<label class="select-item">
<input type="radio" class="checkbox" name="item"value="">
<span>3 Nights</span>
</label>
</div>
</div>
</div>
<div class="select-filter">
<div class="select-wrapper">
<label class="select-wrapper--title">No. of People</label>
<div class="select-wrapper--dropdown">
<label class="select-item">
<input type="radio" class="checkbox" name="item" value="">
<span>1 Person</span>
</label>
<label class="select-item">
<input type="radio" class="checkbox" name="item" value="">
<span>2 People</span>
</label>
<label class="select-item">
<input type="radio" class="checkbox" name="item" value="">
<span>3 People</span>
</label>
</div>
</div>
</div>
$('[name="item"]').each(function() {
$(this).on('click', function(e) {
const target = $(e.target);
const name = target.next().html();
console.log(target.parent().parent().prev());
target.parent().parent().prev().html(name);
});
});

Related

remove element (span) with click on out of same element body or window in javascript

I want to click on confirm includes:(input && label), yesItems displayed.
And then click on any part of the page(body or window) except yesItems, yesItems to delete.
in fact, I want to delete (yes-items) when the user clicks anywhere on the page except the (yes-items).
But when clicking on children of yes-items include(NodeList(16):pan, label, input),yes-items should not be deleted.
Are my codes correct?
Please help me to do this work. If you have a suggestion for solving this problem, thank you for letting me know. Thank you in advance for your cooperation.
const confirm = document.getElementById('confirm');
confirm.addEventListener('click',function(){
const healthProblem = document.querySelector('#health-problem');
const yesItems = document.getElementById('yes-items');
if(healthProblem.checked == true){
yesItems.classList.add('open');
}else{
yesItems.classList.remove('open');
}
document.querySelector('body').addEventListener('click', function(e){
if(!(e.target == yesItems.querySelectorAll("*"))){
yesItems.classList.remove('open');
}
})
})
items {
border: 1px solid red;
padding: .5rem;
border-radius: 10px;
}
span.yes-items {
position: absolute;
border: 2px solid var(--c1);
color: var(--txt);
background-color: #e6eef7;
top: 20%;
left: 0;
width: 94%;
padding: 1rem;
border-radius: 10px;
display: none;
}
span.yes-items input {
width: auto;
}
span.yes-items.open{
display: block;
}
<p class="items">
<span class="label">example</span>
<span class="label-items">
<label class="label-item" for="health-problem" id="confirm">
<input type="radio" id="health-problem" name="problem">
Yes
</label>
<label class="label-item" for="no-problem">
<input type="radio" id="no-problem" name="problem">
No
</label>
</span>
<span class="yes-items" id="yes-items">
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
a
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
b
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
c
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
d
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
e
<textarea class="explain" placeholder="Define Other" cols="50" rows="3"></textarea>
</label>
</span>
</span>
</p>
See here in your own question for more
Snippet
var w = window;
var a = document.getElementById("example");
var c = document.getElementById("okay");
var e = document.getElementById("yes-items");
a.addEventListener("click", check);
w.addEventListener("click", clickedBody);
function clickedBody(event){
if(event.target.id == "body"){
hideExplainIfOpened();
}
}
function check(){
if(c.checked){ showExplain();}
else{ hideExplain(); }
}
function hideExplainIfOpened(){
if(!e.classList.contains("d-none")){
hideExplain();
}
}
function showExplain(){ e.classList.remove("d-none"); }
function hideExplain(){ e.classList.add("d-none"); }
#body {
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
overflow:auto;
}
items {
border: 1px solid red;
padding: .5rem;
border-radius: 10px;
}
span.yes-items {
position: absolute;
border: 2px solid var(--c1);
color: var(--txt);
background-color: #e6eef7;
top: 20%;
left: 0;
width: 94%;
padding: 1rem;
border-radius: 10px;
}
.d-none{ display:none; }
span.yes-items input {
width: auto;
}
<div id="body">
<p class="items">
<span class="label">example</span>
<span class="label-items" id="example">
<label class="label-item" for="okey" id="confirm">
<input type="radio" class="input" name="example" value="1" id="okay">
Yes
</label>
<label class="label-item">
<input type="radio" class="input" name="example" value="0" id="No">
No
</label>
</span>
<span class="yes-items d-none" id="yes-items"><span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
1
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
2
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
3
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
4
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
other
<textarea class="explain" placeholder="Define Other" cols="50" rows="3"></textarea>
</label>
</span>
</span>
</p>
</div>

body or window outside of element remove same element with click in javascript

want to delete when the user clicks anywhere on the page except the .
In addition, the checked to remain in after remove or when the user clicks No, remove checked in and
Please help me to do this work. If you have a suggestion for solving this problem, thank you for letting me know. Thank you in advance for your cooperation.
const confirm = document.getElementById('confirm');
confirm.addEventListener('click', function() {
const yes = document.querySelector('input[type="checkbox"]:checked');
const yesItems = document.getElementById('yes-items');
if (yes.checked == true) {
yesItems.style.display = "block";
}
document.querySelector('body').addEventListener('click', function(e) {
if (e.target.yes.checked == true) {
yesItems.style.display = "none";
}
});
});
items {
border: 1px solid red;
padding: .5rem;
border-radius: 10px;
}
span.yes-items {
position: absolute;
border: 2px solid var(--c1);
color: var(--txt);
background-color: #e6eef7;
top: 20%;
left: 0;
width: 94%;
padding: 1rem;
border-radius: 10px;
display: none;
}
span.yes-items input {
width: auto;
}
<p class="items">
<span class="label">example</span>
<span class="label-items">
<label class="label-item" for="okey" id="confirm">
<input type="checkbox" name="Yes" id="okey">
Yes
</label>
<label class="label-item">
<input type="checkbox" name="No" id="No">
No
</label>
</span>
<span class="yes-items" id="yes-items"><span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
1
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
2
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
3
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
4
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
other
<textarea class="explain" placeholder="Define Other" cols="50" rows="3"></textarea>
</label>
</span>
</span>
</p>
Its Very simple,
Just Create And Put All Items into div#body
And You Have to use the event window.onclick
Then create if statement and check event.target.id == "body" ( To Check The Clicked Element is the div#body ( Not Its Children ) )
if (event.target.id == "body"){ /* Hiding Code */ }
Example
var w = window;
var a = document.getElementById("example");
var c = document.getElementById("okay");
var e = document.getElementById("yes-items");
a.addEventListener("click", check);
w.addEventListener("click", clickedBody);
function clickedBody(event){
if(event.target.id == "body"){
hideExplainIfOpened();
}
}
function check(){
if(c.checked){ showExplain();}
else{ hideExplain(); }
}
function hideExplainIfOpened(){
if(!e.classList.contains("d-none")){
hideExplain();
}
}
function showExplain(){ e.classList.remove("d-none"); }
function hideExplain(){ e.classList.add("d-none"); }
#body {
position:absolute;
top:0;
bottom:0;
left:0;
right:0;
overflow:auto;
}
items {
border: 1px solid red;
padding: .5rem;
border-radius: 10px;
}
span.yes-items {
position: absolute;
border: 2px solid var(--c1);
color: var(--txt);
background-color: #e6eef7;
top: 20%;
left: 0;
width: 94%;
padding: 1rem;
border-radius: 10px;
}
.d-none{ display:none; }
span.yes-items input {
width: auto;
}
<div id="body">
<p class="items">
<span class="label">example</span>
<span class="label-items" id="example">
<label class="label-item" for="okey" id="confirm">
<input type="radio" class="input" name="example" value="1" id="okay">
Yes
</label>
<label class="label-item">
<input type="radio" class="input" name="example" value="0" id="No">
No
</label>
</span>
<span class="yes-items d-none" id="yes-items"><span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
1
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
2
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
3
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
4
</label>
</span>
<span>
<label for="Diabetic">
<input type="checkbox" name="Diabetic" id="Diabetic">
other
<textarea class="explain" placeholder="Define Other" cols="50" rows="3"></textarea>
</label>
</span>
</span>
</p>
</div>

jQuery not reacting to number input

I have this code, where if I fill in specific input fields then it will 'enable' or in this case remove a class but when it comes to filling in an input field of a number it won't react to the input value of the number what is filled. I want it to when something is filled in then enable the button.
I'm setting up a validation that when not all the fields are filled in, you can't go to the next page but before that you need to fill in all the fields.
HTML
<input id="LAMINAAT" type="radio" name="group1" onclick="myFunction()"
value="Laminaat" />
<label for="LAMINAAT">Laminaat</label>
<input id="PARKET" type="radio" name="group1" onclick="myFunction()" value="Parket" />
<label for="PARKET">Parket</label>
<input id="PVC" type="radio" name="group1" onclick="myFunction()" value="Pvc" />
<label for="PVC">PVC</label>
<hr>
<input id="JA2" type="radio" name="group3" value="Ja">
<label for="JA2" class="form-field__radio__label">Ja, meerprijs €1.50 per m<sup>2</sup></label><br>
<input id="NEE2" type="radio" name="group3" onclick="JaNeeFirst()" value="Nee">
<label for="NEE2">Nee</label>
<div id="form_JA2" class="desc desc3" style="float: inherit;">
<h5>Hoeveel m<sup>2</sup> ondervloer wil je laten leggen?</h5>
<input type="number" id="ondervloer" name="ondervloeren">
</div>
<hr>
<input id="JA3" type="radio" name="group4" value="Ja">
<label for="JA3" class="form-field__radio__label">Ja</label><br>
<input id="NEE3" type="radio" name="group4" onclick="JaNeeSecond()" value="Nee">
<label for="NEE3">Nee</label>
<hr>
<input id="JA4" type="radio" name="group5" value="Ja">
<label for="JA4" class="form-field__radio__label">Ja, meerprijs €5.00 per meter</label><br>
<input id="NEE4" type="radio" name="group5" onclick="JaNeeThirth()" value="Nee">
<label for="NEE4">Nee</label>
<hr>
<input id="JA5" type="radio" name="group6" value="Ja">
<label for="JA5" class="form-field__radio__label">Ja, meerprijs €2.50 per m<sup>2</sup></label><br>
<input id="NEE5" type="radio" name="group6" onclick="JaNeeFourth()" value="Nee">
<label for="NEE5">Nee</label>
<hr>
<input id="JA6" type="radio" name="group7" value="Ja">
<label for="JA6" class="form-field__radio__label">Ja, meerprijs €20.00 per deur</label><br>
<input id="NEE6" type="radio" name="group7" onclick="JaNeeFifth()" value="Nee">
<label for="NEE6">Nee</label>
<hr>
<input id="JA7" type="radio" name="group8" value="Ja">
<label for="JA7" class="form-field__radio__label">Ja, meerprijs €20.00 per plint</label><br>
<input id="NEE7" type="radio" name="group8" onclick="JaNeeSixth()" value="Nee">
<label for="NEE7">Nee</label>
<hr>
<input id="tweedebutton" type="button" value="volgende stap" onclick="show_next('user_details','qualification','bar2'); topFunction()" />
jQuery
$(document).ready(function () {
$("#tweedebutton").addClass("disabledbuttonNext");
$('input[type="radio"]').on('change', function () {
if ($('#LAMINAAT').is(":checked") && $('input[name="group3"]').is(":checked") && $('input[name="group4"]').is(":checked") && $('input[name="group5"]').is(":checked") && $('input[name="group7"]').is(":checked") && $('input[name="group8"]').is(":checked") ) {
$("#tweedebutton").removeClass("disabledbuttonNext");
} else if ($('#PARKET').is(":checked") && $('input[name="group3"]').is(":checked") && $('input[name="group4"]').is(":checked") && $('input[name="group5"]').is(":checked") && $('input[name="group7"]').is(":checked") && $('input[name="group8"]').is(":checked") && $('input[name="group6"]').is(":checked") ){
$("#tweedebutton").removeClass("disabledbuttonNext");
} else if ($('#PVC').is(":checked") && $('input[name="group3"]').is(":checked") && $('input[name="group4"]').is(":checked") && $('input[name="group5"]').is(":checked") && $('input[name="group7"]').is(":checked") && $('input[name="group8"]').is(":checked") ) {
$("#tweedebutton").removeClass("disabledbuttonNext");
}
else{
$("#tweedebutton").addClass("disabledbuttonNext");
}
});
});
$(document).ready(function () {
$('input[type="radio"], input[type="number"]').on('change', function () {
if ( $('#JA2').is(":checked") && $('#ondervloer').val() == '' ) {
$("#tweedebutton").addClass("disabledbuttonNext");
}
});
});
CSS
.disabledbuttonNext {
pointer-events: none;
opacity: 0.5;
}
I want the result to be when I filled in everything and I filled something in the number input(example: '1') that it reacts to it immediately and enables the button or in this case adds a class.
Here's the code similar for your application.
It interacts with both "radio buttons" as well as "input box" & accordingly triggers the "Submit button".
function checkout() {
alert("It worked");
}
$(document).ready(function() {
//console.log("Document loaded !");
$("input").change(function() {
var snacksValue = $('input[name="snacks"]:checked').val();
var extrasValue = $('input[name="extras"]:checked').val();
var quantity = $('#input1').val();
if (snacksValue != undefined && extrasValue != undefined && quantity != '') {
//console.log("go");
$('#checkout').removeClass("disabled");
$('#checkout').addClass("enabled");
} else {
//console.log("error");
$('#checkout').removeClass("enabled");
$('#checkout').addClass("disabled");
}
});
});
div {
margin: 10px 5px;
}
.enabled {
background-color: #4CAF50;
/* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
.disabled {
background-color: #e7e7e7;
border: none;
color: black;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
pointer-events: none;
/* display:none; */
/* If you wanna hide it */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<label>
<input type="radio" name="snacks" value="burger" />
Burger</label>
<label>
<input type="radio" name="snacks" value="pizza" />Pizza</label>
<label>
<input type="radio" name="snacks" value="hotdog" /> Hotdog</label>
</div>
<div>
<label>
<input id="extra1" type="radio" name="extras" value="cheese">
With Cheese</label>
<label>
<input id="extra2" type="radio" name="extras" value="nocheese">
Without Cheese</label>
</div>
<div>
<label>Quantity</label>
<input id="input1" type="number" value="" min=1>
</div>
<div>
<input id="checkout" class="disabled" type="button" value="Next" onclick="checkout();" />
</div>

Change the value of a variable when an image is selected

I want to select one image among four of them. And then the variable that i have should be increased. If i select other image then the variable should change and take the value of that image. Here is the code i have so far that does not work
HTML
<div class="checkbox">
<input type="checkbox" name="paroxi" value="10"><br>
</div>
CSS
.checkbox{
width: 23px;
height: 21px;
background: black;
visibility:hidden;
}
.checked{
background: red;
visibility:block;
}
JAVASCRIPT
$(".checkbox").click(function(){
$(this).toggleClass('checked')
});
If you wanna keep the checkboxes, guess to post price value later, than you can do it this way:
$('.image-selection input').on('change', function(e) {
$('.selected-value').text( $('.image-selection input:checked').val() );
}).trigger('change');
.image-selection input {
display: none;
}
.image-selection input:checked + img {
box-shadow: 0 0 5px rgba(0, 0, 0, .4);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="image-selection">
<label for="checkbox-1">
<input id="checkbox-1" name="image-input" type="radio" value="10" checked="checked" />
<img src="http://placehold.it/150x150" />
</label>
<label for="checkbox-2">
<input id="checkbox-2" name="image-input" type="radio" value="20" />
<img src="http://placehold.it/150x150" />
</label>
<label for="checkbox-3">
<input id="checkbox-3" name="image-input" type="radio" value="30" />
<img src="http://placehold.it/150x150" />
</label>
<label for="checkbox-4">
<input id="checkbox-4" name="image-input" type="radio" value="40" />
<img src="http://placehold.it/150x150" />
</label>
</div>
<p>Price: <span class="selected-value"></span></p>
Also on JSFiddle.

How to count number of checkboxes selected, change background after selected, and have hover continue to work

I want to create a list of checkboxes that users can select, however, limit the number of checkboxes to 5, as well as show the user how many they have currently clicked.
I also want to change the background color of the checkbox labels after they have been selected.
My main problem is that the number showing how many checkboxes have been selected is always one click behind. Also, the background color is changing after being selected, but the hover call stops working if selected.
Finally, I'd love to hear any suggestions on how to make my count function cleaner. I don't like having 7 if statements...
$(document).ready(function() {
$("input[name='group_option[]']").change(function() {
var maxAllowed = 5;
var cnt = $("input[name='group_option[]']:checked").length;
if (cnt > maxAllowed) {
$(this).prop("checked", "");
}
});
});
function count() {
var count = 0;
if ($('#checkbox1').is(':checked')) {
count = count + 1;
}
if ($('#checkbox2').is(':checked')) {
count = count + 1;
}
if ($('#checkbox3').is(':checked')) {
count = count + 1;
}
if ($('#checkbox4').is(':checked')) {
count = count + 1;
}
if ($('#checkbox5').is(':checked')) {
count = count + 1;
}
if ($('#checkbox6').is(':checked')) {
count = count + 1;
}
if ($('#checkbox7').is(':checked')) {
count = count + 1;
}
document.getElementById("count").innerHTML = count + "/5 Selected";
}
.options {
background-color: #e6e6e6;
display: block;
width: 300px;
margin-left: 20px;
padding: 2px;
margin-bottom: 1px;
}
.options:hover {
color: black;
cursor: pointer;
transition-duration: .15s;
background-color: #b3b3b3;
}
input {
float: left;
}
label:hover {
background-color: #bfbfbf;
}
input[type=checkbox]:checked + label {
background-color: #cccccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<b id="count" style="float: left;">0/5 Selected</b>
<br>
<br>
<input id="checkbox1" type="checkbox" name="group_option[]" value="option1" />
<label for="checkbox1" class="options" onclick="count(this)"> Option 1</label>
<input id="checkbox2" type="checkbox" name="group_option[]" value="option2" />
<label for="checkbox2" class="options" onclick="count(this)"> Option 2</label>
<input id="checkbox3" type="checkbox" name="group_option[]" value="option3" />
<label for="checkbox3" class="options" onclick="count(this)"> Option 3</label>
<input id="checkbox4" type="checkbox" name="group_option[]" value="option4" />
<label for="checkbox4" class="options" onclick="count(this)"> Option 4</label>
<input id="checkbox5" type="checkbox" name="group_option[]" value="option5" />
<label for="checkbox5" class="options" onclick="count(this)"> Option 5</label>
<input id="checkbox6" type="checkbox" name="group_option[]" value="option6" />
<label for="checkbox6" class="options" onclick="count(this)"> Option 6</label>
<input id="checkbox7" type="checkbox" name="group_option[]" value="option7" />
<label for="checkbox7" class="options" onclick="count(this)"> Option 7</label>
There's no need for your separate count() function as you can do all the required processing in your jQuery change event handler (and on* event attributes are considered outdated and should avoided anyway). You already have the cnt variable stored there which you can use. Try this:
$(document).ready(function() {
var maxAllowed = 5;
$("input[name='group_option[]']").change(function() {
var cnt = $("input[name='group_option[]']:checked").length;
if (cnt > maxAllowed)
$(this).prop("checked", false);
else
$('#count').text(cnt + '/5 Selected');
});
});
.options {
background-color: #e6e6e6;
display: block;
width: 300px;
margin-left: 20px;
padding: 2px;
margin-bottom: 1px;
}
.options:hover {
color: black;
cursor: pointer;
transition-duration: .15s;
background-color: #b3b3b3;
}
input {
float: left;
}
input:checked + label {
background-color: #cccccc;
}
input:checked + label:hover {
background-color: #bfbfbf;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<b id="count" style="float: left;">0/5 Selected</b><br><br>
<input id="checkbox1" type="checkbox" name="group_option[]" value="option1" />
<label for="checkbox1" class="options"> Option 1</label>
<input id="checkbox2" type="checkbox" name="group_option[]" value="option2" />
<label for="checkbox2" class="options"> Option 2</label>
<input id="checkbox3" type="checkbox" name="group_option[]" value="option3" />
<label for="checkbox3" class="options"> Option 3</label>
<input id="checkbox4" type="checkbox" name="group_option[]" value="option4" />
<label for="checkbox4" class="options"> Option 4</label>
<input id="checkbox5" type="checkbox" name="group_option[]" value="option5" />
<label for="checkbox5" class="options"> Option 5</label>
<input id="checkbox6" type="checkbox" name="group_option[]" value="option6" />
<label for="checkbox6" class="options"> Option 6</label>
<input id="checkbox7" type="checkbox" name="group_option[]" value="option7" />
<label for="checkbox7" class="options"> Option 7</label>
because of the CSS tag and for the anecdote, here is a CSS possibility :
// no need of javascript here, it is a CSS demo
form {
display: table;
}
label {
display: block;
margin-left: 20px;
position: relative;
padding: 0.25em 1em 0 0;
background: lightgray;
margin-bottom: 1px;
}
label[for^="checkbox"]:after {/* select the labels to use to draw a checkbox*/
content: '';
position: absolute;
right: 100%;
display: inline-block;
line-height: 9px;
height: 11px;
width: 11px;
margin: 2px 5px 0 0;
border: solid 1px #999;
box-shadow: inset 0 0 0 1px white, inset 0 0 1px 1px gray;
background: linear-gradient(to bottom right, gray, white 75%)
}
/* update checkbox colors on hover/checked */
#checkbox1:checked ~ label[for="checkbox1"]:after,
#checkbox2:checked ~ label[for="checkbox2"]:after,
#checkbox3:checked ~ label[for="checkbox3"]:after,
#checkbox4:checked ~ label[for="checkbox4"]:after,
#checkbox5:checked ~ label[for="checkbox5"]:after,
#checkbox6:checked ~ label[for="checkbox6"]:after,
#checkbox7:checked ~ label[for="checkbox7"]:after,
label:hover:after {
border: solid 1px #5586A3;
box-shadow: inset 0 0 0 1px white, inset 0 0 0 2px #9FD7F9;
background: linear-gradient(to bottom right, #7AB6DB, white 75%)
}
/* about time to hide imputs cloned in CSS */
[name^="group_option"] {
position: absolute;
right: 100%;
}
/* trigger the checkmark when checked */
#checkbox1:checked ~ label[for="checkbox1"]:after,
#checkbox2:checked ~ label[for="checkbox2"]:after,
#checkbox3:checked ~ label[for="checkbox3"]:after,
#checkbox4:checked ~ label[for="checkbox4"]:after,
#checkbox5:checked ~ label[for="checkbox5"]:after,
#checkbox6:checked ~ label[for="checkbox6"]:after,
#checkbox7:checked ~ label[for="checkbox7"]:after {
content: '\2714';
color: #223C82;
}
/* disallow option when 5 is reached */
[name^="group_option"]:checked ~[name^="group_option"]:checked ~[name^="group_option"]:checked ~[name^="group_option"]:checked ~[name^="group_option"]:checked ~ label {
pointer-events:none;
color:gray;
}
/* but allow to unchecked if you change yor mind */
label:hover,
#checkbox1:checked ~ label[for="checkbox1"],
#checkbox2:checked ~ label[for="checkbox2"],
#checkbox3:checked ~ label[for="checkbox3"],
#checkbox4:checked ~ label[for="checkbox4"],
#checkbox5:checked ~ label[for="checkbox5"],
#checkbox6:checked ~ label[for="checkbox6"],
#checkbox7:checked ~ label[for="checkbox7"] {
pointer-events:auto;
color:initial;
background: gray;
cursor:pointer;
}
/* add infos */
b {
display: block;
text-align: center
}
form {
counter-reset: checked;
}
input:checked {
counter-increment: checked;
}
b:before {
content: counter(checked);
}
b:after {
content: '5'
}
<form>
<!-- input linked to labels to be hidden -->
<input id="checkbox1" type="checkbox" name="group_option[]" value="option1" />
<input id="checkbox2" type="checkbox" name="group_option[]" value="option2" />
<input id="checkbox3" type="checkbox" name="group_option[]" value="option3" />
<input id="checkbox4" type="checkbox" name="group_option[]" value="option4" />
<input id="checkbox5" type="checkbox" name="group_option[]" value="option5" />
<input id="checkbox6" type="checkbox" name="group_option[]" value="option6" />
<input id="checkbox7" type="checkbox" name="group_option[]" value="option7" />
<!-- end hidden input linked to labels -->
<b>/</b>
<!-- label using pseudo to draw the checkbox -->
<label for="checkbox1" class="options"> Option 1</label>
<label for="checkbox2" class="options"> Option 2</label>
<label for="checkbox3" class="options" > Option 3</label>
<label for="checkbox4" class="options"> Option 4</label>
<label for="checkbox5" class="options"> Option 5</label>
<label for="checkbox6" class="options"> Option 6</label>
<label for="checkbox7" class="options"> Option 7</label>
<!-- end label using pseudo to draw the checkbox -->
<form>
demo to play with
The answer is at line 4 of your own code...
function count() {
var cnt = $("input[name='group_option[]']:checked").length;
document.getElementById("count").innerHTML = cnt + "/5 Selected";
}
To answer the second part of your question first: the reason your losing the :hover state on the labels is due to CSS specificity; you have the rule for a label following a :checked input after the rule for a hovered label, so the latter is being overridden. But the selector for the :checked rule has a higher specficity than the one for the :hover rule so simply changing the order of those two rules won't be enough, you'll also need to increase the specificity of the :hover rule.
The rest of your problems can be solved by addressing the last part of your question; simplifying your JavaScript. One way to do so would be to loop through all the inputs and listen for the change event on each, incrementing or decrementing the value of the count variable, depending on the checbox's status and the checking the value of count is not greater than 5.
I've added the ability to have some checkboxes initially checked and also taken the liberty of simplfying how you update the counter element and adding some CSS to make unchecked checkboxes & their labels appear disabled once 5 options have been selected in order to make it clearer that no more options can be selected.
var inputs=document.querySelectorAll("input.options"),
length=inputs.length,
counter=document.querySelector("#count>span"),
dataset=counter.parentNode.dataset,
count=0,input,max=5;
while(length--){
input=inputs[length];
count+=input.checked;
input.addEventListener("change",function(event){
count+=this.checked&&1||-1;
if(count>max){
this.checked=0;
count--;
}
dataset.count=counter.innerHTML=count;
},0);
}
dataset.count=counter.innerHTML=count;
*{box-sizing:border-box;font-family:sans-serif;}
#count{
font-weight:bold;
margin:0 0 20px;
}
input.options{
clear:left;
float:left;
}
label.options{
background:#e6e6e6;
cursor:pointer;
display:block;
margin:0 0 1px 20px;
padding:2px 2px 2px 20px;
transition:background .15s;
width:300px;
}
input.options:checked+label.options{
background:#ccc;
}
input.options+label.options:hover{
background:#bfbfbf;
}
#count[data-count="5"]~input.options:not(:checked),#count[data-count="5"]~input.options:not(:checked)+label.options{
opacity:.5;
pointer-events:none;
}
<p id="count"><span>0</span>/5 Selected</p>
<input class="options" id="checkbox1" name="group_option[]" type="checkbox" value="option1" />
<label class="options" for="checkbox1">Option 1</label>
<input class="options" id="checkbox2" name="group_option[]" type="checkbox" value="option2" />
<label class="options" for="checkbox2">Option 2</label>
<input class="options" id="checkbox3" name="group_option[]" type="checkbox" value="option3" />
<label class="options" for="checkbox3">Option 3</label>
<input checked class="options" id="checkbox4" name="group_option[]" type="checkbox" value="option4" />
<label class="options" for="checkbox4">Option 4</label>
<input class="options" id="checkbox5" name="group_option[]" type="checkbox" value="option5" />
<label class="options" for="checkbox5">Option 5</label>
<input class="options" id="checkbox6" name="group_option[]" type="checkbox" value="option6" />
<label class="options" for="checkbox6">Option 6</label>
<input class="options" id="checkbox7" name="group_option[]" type="checkbox" value="option7" />
<label class="options" for="checkbox7">Option 7</label>

Categories

Resources