How to change label styling on checkbox :checked - javascript

I'm currently building a form that has checkboxes wrapped inside of labels. We are doing this because we need to swap our the original checkbox for an image. However, when the checkbox is checked, we need to make the label have a border to give some user feedback.
Here is the setup of the labels/checkboxes
<div class="one_column">
<label for="fieldname2_1_cb0">
<input name="fieldname2_1[]" id="fieldname2_1_cb0" class="field depItem group required" value="Alloy Wheel(s)" vt="Alloy Wheel(s)" type="checkbox"> <span>Alloy Wheel(s)</span>
</label>
</div>
We have tried going about is using the following but obviously doesn't work
label input[type="checkbox"]:checked + label {
border: 5px solid blue;
}
Any help would be appreciated!
I have managed to the the first checkbox using the code supplied below
window.onload=function() {
document.querySelector('input[type="checkbox"]').addEventListener('change',
function() {
if (this.checked) {
this.parentNode.classList.add('border-blue');
} else {
this.parentNode.classList.remove('border-blue');
}
})}
However, it only changes the first checkbox... there are 10 in total all following the same structure as above

Using CSS, there is no way to select parent elements from child elements.
If you are allowed to use JavaScript, you can solve it this way:
document.querySelectorAll('input[type="checkbox"]').forEach(function(el) {
el.addEventListener('change', function() {
if (this.checked) {
this.parentNode.classList.add('border-blue');
} else {
this.parentNode.classList.remove('border-blue');
}
})
})
.border-blue {
border: 5px solid blue;
}
It will check for changes on input. If it is checked, a class will be added. Otherwise, the class will be removed.

Related

I need to remove a class after adding it clicking on same checkbox, not the document

I'm clicking on a checkbox to add some animation to a div, but when I want this animation to disappear I can only make it happen through $(document) click. Checkbox must add and then remove the class.
JS
$('#inOrder').click(function(e) {
$('.border').addClass('colorsborder');
e.stopPropagation();
$(document).click(function(e) {
$('.border').removeClass('colorsborder');
});
});
$('#inOrder').click(function(e) {
e.stopPropagation();
});
HTML
<input id="inOrder" type="checkbox" />
You may call toggleClass() method on the jQuery object (element) that you want to add or remove the class from. The method toggleClass will either:
add the desired class when the element doesn't have it.
or remove that class when the element has it already.
Here's a basic, live demo to illustrate the functionality:
const checkbox = $('#inOrder'),
relatedDiv = $('#related');
checkbox.on('change', () => relatedDiv.toggleClass('custom'))
/** just for demo purpose */
#related {
margin: 15px 0;
padding: 10px;
border: 1px solid #ccc;
}
#related.custom {
border-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="inOrder" type="checkbox" />
<div id="related">My appearnace will change on checkbox click</div>
The above demo is pnly meant as a showcase of a possible solution that could be applied to your current problem and it WON'T do the exact thing you want to have unless you apply the required changes you need to suit your actual code/structuring.
Then you want to toggle the class not add it when you click on checkbox
$('#inOrder').click(function(e) {
$('.border').toggleClass('colorsborder');
....

Set div with an ID grit template after clicking checkbox

I have a question. I have a simple chekcbox that in html looks like
<label class="container__control--checkbox">
<input type="checkbox" checked="checked" id="presentation_full_screen" class="container__control" onchange="_handleMainLayout()" />
<span>CLICK</span>
</label>
So when I click checkbox I fire up this type script:
_handleMainLayout() {
const layoutContainer = <HTMLInputElement>document.getElementById("main_layout");
const hideCommunicationCheckbox <HTMLInputElement>document.getElementById("presentation_full_screen");
if (hideCommunicationCheckbox.checked) {
layoutContainer.removeAttribute("style");
} else {
layoutContainer.style.gridTemplateColumns = "1fr";
}
}
So what id does it sets template on main layout (id: main_layout) from 1 column to 2 columns depends on this if checkbox is selected, and well it works.
But I was wondering, there are those selectors in css :checked and not(). So thing is, element with id main layout is way up DOM tree, and question can I somehow get that element using those selectors or any any other css/scss trick and toggle this grid-template-colum?
something like
.container__control :checked {
//get div with ID and set its grid-template-colum
}
.container__control :not(:checked) {
//get div with ID and set its grid-template-colum
}
Or am I left with only JS solution?
You can absolutely use CSS only to do that. The "trick" is where to insert the <input> element. Thanks to label attribute for you don't need to have <input> and <label> near one from the other. However <input> must be placed before #main_layout and on same DOM "branch" in order to use General (~) or adjacent (+) sibling combinator.
#main_layout {
height: 20px;
background-color: red;
}
:checked + #main_layout {
background-color: blue;
}
<label for="checkox">Click me</label>
<input type="checkbox" name="" id="checkox" hidden>
<div id="main_layout"></div>
no need for :not() in this case

javascript checkbox checkd but not updating UI

I wrote a script to check checkbox when I am clicking on it's respective image.
Image have id like checkbox-img-1 and checkbox input have id like checkbox-1 for 1st pair of checkbox and image. For 2nd pair id's are checkbox-img-2 and checkbox-2 and so on.
So, whenever I click on image I want to check the respective checkbox. For few images the UI is getting updated but for few images it's not getting updated.
What is the possible problem? I searched a bit but all questions were doing mistake of having attr in place of prop.
My script is in pure javascript. I tried with jQuery but I am getting same bug.
I figured out that content which is not present or not yet displayed in front are not getting selected.
The javascript code is:
/* Check option on image click */
$(".option-check-img").click(function () {
var checkbox_img_id = $(this).attr("id");
var checkbox_id = checkbox_img_id.replace("checkbox-img", "checkbox");
if(document.getElementById(checkbox_id).checked)
{
document.getElementById(checkbox_id).checked = false;
var d = document.getElementById(checkbox_img_id);
d.className = "img-circle pointer";
/*$("#checkbox_id").prop("checked", false);
$("#checkbox_img_id").removeClass("img-border");
console.log(document.getElementById(checkbox_id));*/
}
else
{
document.getElementById(checkbox_id).checked = true;
var d = document.getElementById(checkbox_img_id);
d.className += " img-border";
/*$("#checkbox_id").prop("checked", true);
$("#checkbox_img_id").addClass("img-border");
console.log(document.getElementById(checkbox_id));*/
}
});
Any solution? Thank you.
Try to use prop() instead of attr()
JQuery Script not checking check-boxes correctly
Read docs for more info jQuery prop().
Are you sure you want to use js for this? You can do this just with css.
*, *:before, *:after {
font-family: sans-serif;
box-sizing: border-box;
}
label {
display: block;
margin-bottom: 20px;
cursor: pointer;
}
span:before {
content: '';
display: inline-block;
width: 15px;
height: 15px;
margin-right: 10px;
background: white; /* you can place your image url here */
border: 4px solid white;
border-radius: 3px;
box-shadow: 0 0 0 1px black;
}
input {
display: none;
}
input:checked + span:before {
background: black;
}
<label>
<input type="checkbox">
<span>Checkbox 1</span>
</label>
<label>
<input type="checkbox">
<span>Checkbox 2</span>
</label>
There is a pure-html solution (Fiddle):
<ul><li>
<input type="checkbox" id="checkbox-1" />
<label for="checkbox-1"><img /></label>
</li>
<li>
<input type="checkbox" id="checkbox-2" />
<label for="checkbox-2"><img /></label>
</li></ul>
if you need to add styling to your images when checkbox is checked you can use css3 (Fiddle):
input:checked + label img{
border: 1px solid black;
}
input:not(:checked) + label img{
border: 1px solid green;
}
// If you want to hide the checkbox
input[type=checkbox] {
display: none;
}
You should build your html such the checkbox and the image are next to each other.
This approach is much more elegant and doesn't use unnecessary javascript.
$(".option-check-img").click(function() {
var $this = $(this);
var checkbox_img_id = $(this).attr("id");
var checkbox_id = checkbox_img_id.replace("checkbox-img", "checkbox");
if ($("#" + checkbox_id + ":checked").length) {
$("#" + checkbox_id).prop('checked', false);
$("#" + checkbox_img_id).removeClass("img-border");
$("#" + checkbox_img_id).addClass("img-circle pointer");
} else {
$("#" + checkbox_id).prop('checked', true);
$("#" + checkbox_img_id).removeClass("img-circle pointer");
$("#" + checkbox_img_id).addClass("img-border");
}
});
Converted your code to proper jQuery Code.
Assumption: ID is of your check-box element.
Make sure no elements have same ID in your DOM.
Updated code to remove alternate-classes too.
Thanks
your checkbox id's are not unique.
A different checkbox with the same id is getting checked / unchecked instead of the one you want to manupulate. getElementById / $('#id') will return only one element which ever it finds first.
for instance, in the link that you shared the option Party has a id of checkbox-24 but with the same id there are total of three checkboxes.
similarly for Music with a id of checkbox-27 there are again 3 instances of checkbox with that id.
Your script is correct, but the ids are not unique. Make the id's unique or use someother identifier or combination of identifiers to uniquely identify the checkbox which you want to manipulate.
the problem was with infinite loop. Without infinite loop its working. But still I want that infinite slider so I will try something different.

JQuery: how to find element that lies after current element

Suppose, we have 2 checkboxes and 2 divs that follow the checkboxes:
<div class="wrapper">
<input type="checkbox" name="checkbox1" checked="" />
</div>
<div class="border"></div>
<div class="wrapper">
<input type="checkbox" name="checkbox2" checked="" />
</div>
<div class="border"></div>
My goal is to toggle the color of the appropriate "border" div, lying below the checkbox. The problem is, I don't know how to get the appropriate div. I tried this, but it doesn't work:
$('input[type="checkbox"]').change(
function ()
{
var div = $(this).find('div');//<-- ?
if ($(this).checked)
{
div.css("border", "solid 2px blue");
}
else
{
div.css("border", "solid 2px black");
}
});
jsfiddle
The problem is that the .find() method will select any descendant elements.
Since the input element is self-closed and doesn't contain any descendant elements, nothing is selected with $(this).find('div').
You could select the parent div element, and then the immediately following element:
$(this).parent().next();
The above will select the immediate parent element. It may be safer using the .closest() method in order to select the ancestor .wrapper element (just in case nesting varies):
$(this).closest('.wrapper').next();
In addition, jQuery objects don't have a checked property, you should retrieve the checked property of the DOM element, therefore $(this).checked should be this.checked or you could simply use the .prop() method to retrieve the checked property from the DOM element in the jQuery object by using: $(this).prop('checked').
Updated Example
$('input[type="checkbox"]').on('change', function() {
var div = $(this).closest('.wrapper').next();
if (this.checked) {
div.css("border", "solid 2px blue");
} else {
div.css("border", "solid 2px black");
}
});
As a side note, I'd suggest simply toggling a class on the corresponding element instead:
Updated Example
.border.blue-border {
border-color: blue;
}
$('input[type="checkbox"]').on('change', function() {
$(this).closest('.wrapper').next().toggleClass('blue-border')
});
Change it to var div = $(this).parent().next('.border');
You need to take parent().next() as was mentioned in some answers...
Also, checkbox status was not valuated correctly.
Try this solution:
$('input[type="checkbox"]').change(
function () {
var div = $(this).parent().next();
if ($(this).is(":checked")) {
div.css("border", "solid 2px blue");
} else {
div.css("border", "solid 2px black");
}
}
);
https://jsfiddle.net/gv3pqo2z/3/

Prevent JavaScript bubbling up in RAW JavaScript (not JQuery)

I'm trying to create a button-with-a-checkbox by creating a span containing some text and a checkbox input.
The interaction I want is that whenever the 'button' or the checkbox is clicked, the state of the checkbox toggles.
However, I am suffering from the bubble-up problem, and I can't figure out how to fix it as all solutions on here seem to be JQuery solutions - I'm looking to do this is raw JS.
What I have so far is:
HTML:
<span id="myCBbutton" class="CBbutton" onClick="toggleIt(event);">Toggle Me <input type="checkbox" id="myCheckBox" onClick="toggleIt(event);event.stopPropagation();"></span>
CSS:
.CBbutton {
border: solid 1px black;
border-radius: 3px;
background-color: silver;
padding: 2px;
cursor: pointer;
}
and JS:
function toggleIt(event) {
var checkBox = document.getElementById('myCheckBox');
if (checkBox.checked) {
alert("before: it's checked!");
} else {
alert("before: NOT checked");
}
checkBox.checked = (checkBox.checked)?false:true;
if (checkBox.checked) {
alert("after: it's checked!");
} else {
alert("after: NOT checked");
}
event.stopPropagation();
return false;
}
I've also created a fiddle here.
I guess fromother questions and answers that the solution is something to do with either event.preventDefault() or event.stopPropagation() with or without a return false but I just can't get this to work.
To achieve what you want you can use an label instead of going to Javascript:
.CBbutton {
border: solid 1px black;
border-radius: 3px;
background-color: silver;
padding: 2px;
cursor: pointer;
}
Label with checkbox inside:<br>
<label id="myCBbutton" class="CBbutton">Toggle Me <input type="checkbox" id="myCheckBox"></label>
<br><br>
Label with checkbox outside<br>
<label class="CBbutton" for="myCheckBox2">Toggle Me</label>
<input type="checkbox" id="myCheckBox2">
But replying to your question, stopPropagation is what would make an event do not propagate to parent's handlers.
event.stopPropagation() is the good code, but your problem is elsewhere.
When you do this : checkBox.checked = (checkBox.checked)?false:true;, the browser fire a new click event and this one is bubbling to the parent.
But anyway, Luizgrs solution is the better i think.
You can use event.stopImmediatePropagation()
Sample Here
Documentation Here
My suggestion is that you use a label as suggested by Luizgrs
However, the problem with your code is that even though you are preventing propagation (the handler on the span is not called when you click the checkbox), the click on checkbox is going to change its checked status and your code is then switching it back. There are ways to fix it but it's not worth it, a <label> does the hard work for you

Categories