Changing a class outside an input element - javascript

I have an input element with a checkbox:
<input type="checkbox" id="ID1" name="ID1" checked>
Somwhere else (outside the input field), I would like to have a text, which is changing its appearence according the check status of the input element with the ID1.
Something like:
<span for id='ID1' class='Class1'>TEST</span>
How do I get a dependency between the text and the status of the input field and how is it possible to change Class1 to Class2 by checking and unchecking the checkbox? The class changes the background color of the Text. I know how to do this inside the same element. But having two different elements? Or is it possible to access the class via the ID of the input element, due to the "for" statement? I am working with javascript.
Thanks for any help!

Add an attribute to the checkbox with the ID of the related span.
document.querySelector("#ID1").addEventListener("click", function() {
let rel = document.getElementById(this.getAttribute("rel"));
if (rel) {
if (this.checked) {
rel.classList.add("Class1");
rel.classList.remove("Class2");
} else {
rel.classList.add("Class2");
rel.classList.remove("Class1");
}
}
});
.Class1 {
background-color: red;
}
.Class2 {
background-color: blue;
}
<input type="checkbox" id="ID1" name="ID1" checked rel="span1">
<span id="span1" class='Class1'>TEST</span>

First : you can't/shouldn't have two element with same Id
const checkbox = document.getElementById("ID1");
const span = document.getElementById("SpanID1");
checkbox.addEventListener('change', function() {
if (this.checked) {
span.innerHtml= 'TEST Checked'
} else {
span.innerHtml= 'TEST Unchecked'
}
});

If you want a CSS solution, you can target the input box and use the :checked selector followed by + then the adjacent element.
CSS: element+element [div + p] Selects the first <p> element that is placed immediately after <div> elements
.Class1 {
background-color: yellow
}
#ID1:checked + .Class1 {
background-color: skyblue
}
<input type="checkbox" id="ID1" name="ID1" checked>
<span for id='ID1' class='Class1'>TEST</span>
Check here to know more about the different CSS selectors.

Related

Hiding radio button name/label along with button

I'm trying to hide a radio button when another button is selected. I managed to hide the actual button but I can't find a way to hide the label/ name. This code below only hides the button.
document.getElementById('lights').style.display = 'none';
Code below is the actual button. I even trid putting the name in label tags.
Lights
<input type="radio" onclick="javascript:yesnoCheck();" name="yesno" id="lights" />
You can add the "lights" word inside a label or a span then use "previousElementSibling" to hide it.
const radioBtn = document.getElementById('lights');
radioBtn.style.display = 'none';
radioBtn.previousElementSibling.style.display = 'none';
<span>Lights</span>
<input type="radio" onclick="javascript:yesnoCheck();" name="yesno" id="lights" />
A better usability pattern would deemphasize it visually. Listen for clicks to the parent element and set a CSS class. Target the radio group's :checked attribute. Apply a style to the + next element, a label with a for= attribute.
let selector = "fieldset";
let parent = document.querySelector(selector);
parent.onclick = function(event) {
let element = event.target;
// if click child, deemphasize
if (element.nodeName.toLowerCase() != selector) {
element.closest(selector).classList.add("taint");
}
}
.taint {
border: 0.125em dotted red;
}
.taint input[type=radio]:not(:checked)+label {
opacity: 0.25;
}
<fieldset>
<input type="radio" name="hue" id="light" /><label for="light">Light</label>
<input type="radio" name="hue" id="dark" /><label for="dark">Dark</label>
</fieldset>

css toggle switch status

So here is what I have for a toggle switch I'm using off of https://metroui.org.ua/inputs.html
What Im trying to do is change the label thats before the switch/checkbox to say checked or not checked. If I click on the label it changes the switch but the text does not change.
JavaScript:
$(document).ready(function() {
$('#front_set').click(function() {
if ($(this).is(':checked')) {
$(this).siblings('label').html('checked');
} else {
$(this).siblings('label').html(' not checked');
}
});
});
<label for="front_set">checked</label>
<label class="switch-original right">
<input type="checkbox" id="front_set">
<span class="check"></span>
</label>
The issue: The label is not a sibling of the clicked checkbox, so you won't find it using siblings. The label is actually a sibling of the label that is the parent of the checkbox.
The solution: Use a different selector to find the label, so their relative positions don't matter much anymore. Using label[for="xyz"] you can find exactly that label that is bound to checkbox xyz, regardless of its position in the document. This makes your code more flexible too, because it won't break immediately if you reorganize your DOM.
var $myLabel = $('label[for="' + this.id + '"]');
$myLabel.html( $(this).is(':checked') ? 'checked' : ' not checked');
$(document).ready(function() {
$('#front_set').click(function() {
var $myLabel = $('label[for="' + this.id + '"]');
$myLabel.html( $(this).is(':checked') ? 'checked' : ' not checked');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="front_set">checked</label>
<label class="switch-original right">
<input type="checkbox" id="front_set">
<span class="check"></span>
</label>
You need to change the parent().siblings('label'), not .siblings('label') because $(this) is the element you bind the click event to, which is $('#front_set') ( = your input) and that's a child of <label>, not a sibling of it. So you need to go up a level, using .parent():
$(document).ready(function() {
$('#front_set').click(function() {
if ($(this).is(':checked')) {
$(this).parent().siblings('label').html('checked');
} else {
$(this).parent().siblings('label').html(' not checked');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="front_set">checked</label>
<label class="switch-original right">
<input type="checkbox" id="front_set">
<span class="check"></span>
</label>
What I don't understand is what is that <span class="check"></span> doing in your code? It does nothing and your code would do well without it.
Improved version:
You shouldn't bind events on click to checkboxes, but on change, as checkboxes can change their value without being clicked. So here is a better version of it, most likely to work on any device, in any browser:
$(document).on('ready', function() {
$.fn.extend({
setLabel: function() {
var label = $('[for="'+$(this).attr('id')+'"]').eq(0);
$(label).text(($(this).is(':checked') ? '' : 'not ') + 'checked');
}
});
$('#front_set').on('change', function(){
$(this).setLabel();
})
$('#front_set').setLabel();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label for="front_set">checked</label>
<label class="switch-original right">
<input type="checkbox" id="front_set">
</label>
This also registers the checking of the label as a jQuery function, enabling you to call it on any element using .setLabel(). In this version I used GolezTrol's solution for selecting the label, since it adds flexibility (the parent/child relation between input and label is no longer relevant).

Wrapping Checkbox on Checked with .is() not working

I have the following code snippet. Why might the .is() not be working on wrapping only the checked checkboxes?
$("input:checkbox").on("change", function() {
$("input:checkbox").is(":checked").wrap("<span class='check-wrap-sapn'></div>");
});
.red {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">
.is() returns a boolean so it is not chainable. You want .has()
Now the issue you have is if the user unchecks it, it still will be wrapped and if they check it again, you will have multiple wrapped elements. You probably should just wrap the element to start and toggle the class on the parent element.
$("input:checkbox").on("change", function() {
$(this).closest("label").toggleClass("checked", this.checked);
}).trigger("change");
label.checked {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>
<input type="checkbox">
</label>
<label>
<input type="checkbox">
</label>
<label>
<input type="checkbox">
</label>
Read the documentation of .is:
Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
So the return value of .is is a boolean. But you're trying to call a jQuery method on it.
Additionally, you're repeating your DOM query within the event handler, and so will act on all matching elements, not just the one that relates to the event.
And your wrapper starts out as a div but ends as a span. Might want to be consistent about that.
And I suspect check-wrap-sapn was meant to be check-wrap-span.
If I'm guessing correctly at your goal, then:
$("input:checkbox").on("change", function() {
var $this = $(this);
if ($this.is(":checked")) {
$this.wrap("<span class='check-wrap-span'></span>");
} else {
$this.unwrap();
}
});
Or:
$("input:checkbox").on("change", function() {
if (this.checked) {
$(this).wrap("<span class='check-wrap-span'></span>");
} else {
$(this).unwrap();
}
});
Live Example:
$("input:checkbox").on("change", function() {
if (this.checked) {
$(this).wrap("<span class='check-wrap-span'></span>");
} else {
$(this).unwrap();
}
});
.check-wrap-span {
border: 1px solid green;
}
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
But this is something that would be much better handled with styling the CSS, via the :checked pseudo-class, provided the styling in question can be applied to checkboxes. If it can't, I'd advocate always having the wrapper span, but toggling a class on it:
Live Example:
$("input:checkbox").on("change", function() {
$(this.parentNode).toggleClass("check-wrap-span", this.checked);
});
.check-wrap-span {
border: 1px solid green;
}
<span><input type="checkbox"></span>
<span><input type="checkbox"></span>
<span><input type="checkbox"></span>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Use $(this) inside the event handler to check if the checkbox is checked
is returns boolean result, use is() in if and if the checkbox is checked, then wrap it.
$("input:checkbox").on("change", function() {
var $this = $(this);
if ($this.is(":checked"))
$this.wrap("<span class='red'></div>");
});
.red {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox">
<input type="checkbox">
<input type="checkbox">

If Radio Button is Selected Show Div - 8 Radio Buttons / 8 Divs - Can this be simplified?

Basically, I want 8 radio buttons. And if one radio button is selected then a div is shown below. If another button is selected another div is shown. Only one div shown at a time and if no button selected (initially) then no divs shown.
This is my HTML which is fairly standard, I'm not trying to improve this for what I need.
<form id='group'>
<label><input type="radio" name="group1" class="sim-micro-btn"/></label>
<label><input type="radio" name="group1" class="sim-mini-btn"/></label>
<label><input type="radio" name="group1" class="sim-maxi-btn"/></label>
<label><input type="radio" name="group1" class="sim-mega-btn"/></label>
<label><input type="radio" name="group1" class="phone-smart-micro-btn"/></label>
<label><input type="radio" name="group1" class="phone-smart-mini-btn"/></label>
<label><input type="radio" name="group1" class="phone-smart-btn"/></label>
<label><input type="radio" name="group1" class="phone-smart-maxi-btn"/></label>
</form>
<div class="billpay-internet-add-ons">
<div class="sim-micro-desktop">sim-micro</div>
<div class="sim-mini-desktop">sim-mini</div>
<div class="sim-maxi-desktop">sim-maxi</div>
<div class="sim-mega-desktop">sim-mega</div>
<div class="phone-smart-micro-desktop">phone-smart-micro</div>
<div class="phone-smart-mini-desktop">phone-smart-mini</div>
<div class="phone-smart-desktop">phone-smart</div>
<div class="phone-smart-maxi-desktop">phone-smart-maxi</div>
</div>
However this is my script and it seems fairly hectic and I'm wondering before I move on is there a way to do this a bit more simple?
$(document).ready(function(){
$('.sim-micro-desktop').hide();
$('.sim-mini-desktop').hide();
$('.sim-maxi-desktop').hide();
$('.sim-mega-desktop').hide();
$('.phone-smart-micro-desktop').hide();
$('.phone-smart-mini-desktop').hide();
$('.phone-smart-desktop').hide();
$('.phone-smart-maxi-desktop').hide();
$('form#group').click(function(){
if($('.sim-micro-btn').is(":checked")){
$('.sim-micro-desktop').show();
} else {
$('.sim-micro-desktop').hide();
}
if($('.sim-mini-btn').is(":checked")){
$('.sim-mini-desktop').show();
} else {
$('.sim-mini-desktop').hide();
}
if($('.sim-maxi-btn').is(":checked")){
$('.sim-maxi-desktop').show();
} else {
$('.sim-maxi-desktop').hide();
}
if($('.sim-mega-btn').is(":checked")){
$('.sim-mega-desktop').show();
} else {
$('.sim-mega-desktop').hide();
}
if($('.phone-smart-micro-btn').is(":checked")){
$('.phone-smart-micro-desktop').show();
} else {
$('.phone-smart-micro-desktop').hide();
}
if($('.phone-smart-mini-btn').is(":checked")){
$('.phone-smart-mini-desktop').show();
} else {
$('.phone-smart-mini-desktop').hide();
}
if($('.phone-smart-btn').is(":checked")){
$('.phone-smart-desktop').show();
} else {
$('.phone-smart-desktop').hide();
}
if($('.phone-smart-maxi-btn').is(":checked")){
$('.phone-smart-maxi-desktop').show();
} else {
$('.phone-smart-maxi-desktop').hide();
}
});
});
Firstly put shared classes on both the radio buttons and the div elements which show the content. In my example I've used trigger and content respectively. Then add a data attribute to the radio to identify which div should be shown on click.
Shortened example:
<form id='group'>
<label>
<input type="radio" name="group1" class="sim-micro-btn trigger" data-rel="sim-micro-desktop" />
</label>
</form>
<div class="billpay-internet-add-ons">
<div class="sim-micro-desktop content">sim-micro</div>
</div>
Then you only need 1 click handler like this:
$(document).ready(function(){
$('.trigger').click(function() {
$('.content').hide();
$('.' + $(this).data('rel')).show();
});
});
You can also then use CSS to hide the div elements without jQuery - styling should always be done in CSS anyway as it's a much better separation of concerns.
.content {
display: none;
}
Example fiddle
You can hide the div elements using CSS:
.billpay-internet-add-ons div {
display: none;
}
Then you can use the className of the target to determine which div to show, hiding all sibling elements:
$('form#group').click(function(e) {
var className = e.target.className.replace('btn', 'desktop');
$('.' + className).show().siblings().hide();
});
Here's a fiddle
use html5 data attribute)(i.e data-mappingclass ) pointing to corresponding div you need to show. add same class to all radio button(ie radioClass).
HTML
<label><input type="radio" name="group1" class="radioClass sim-micro-btn" data-mappingclass="sim-micro-desktop"/></label>
<label><input type="radio" name="group1" class="radioClass sim-mini-btn" data-mappingclass="sim-mini-desktop"/></label>
... //same for others
JS
$('.radioClass').click(function() {
$('.billpay-internet-add-ons div').hide();
if(this.checked){
$('.' + $(this).data('mappingclass').show();
}
});
You could use selectors to reduce the number of lines of code here.
$('.sim-micro-desktop').hide();
$('.sim-mini-desktop').hide();
$('.sim-maxi-desktop').hide();
$('.sim-mega-desktop').hide();
$('.phone-smart-micro-desktop').hide();
$('.phone-smart-mini-desktop').hide();
$('.phone-smart-desktop').hide();
$('.phone-smart-maxi-desktop').hide();
Could be shortened to:
$('.billpay-internet-add-ons div').hide();
This uses the parent element to group those elements you want to hide, rather than repeating the request for each one.
Similarly, you can use your naming convention to map the items to the elements to show and hide - here is the full working example:
$(document).ready(function(){
$('.billpay-internet-add-ons div').hide();
$('form#group').click(function(){
$('#group input').each(function() {
var item = $(this);
var isChecked = item.is(':checked');
var name = item.attr('class').replace("-btn", "-desktop");
if (isChecked) {
$('.' + name).show();
} else {
$('.' + name).hide();
}
});
});
});
This example is purely based on your HTML without any changes. See it working here.
You could simplify this further if you didn't need to transform the names. You could use a data-attribute instead of changing the class names to do this.
var $billpay= $('.billpay-internet-add-ons');
$billpay.find("div").hide();
$("#group input:radio").click(function(){
$billpay.find("div").hide();
$billpay.find("div:eq("+$(this).parent().index()+")").show();
});
http://jsfiddle.net/KaF77/2/
I simplified it some four you. Basically you look which index the radio clicked has and then show a div with the same index. So the position of the divs has to match the radios.
Your HTML is the same as before.
Your CSS:
.billpay-internet-add-ons > div {
display:none;
}
All your Javascript:
$(document).ready(function(){
$('form#group').click(function(e)
{
$('.billpay-internet-add-ons > div').hide();
$('form#group input[type="radio"]').each(function(index)
{
if($(this).is(':checked'))
{
$('.billpay-internet-add-ons > div:eq(' + index + ')').show();
}
});
});
});
jsFiddle Demo: http://jsfiddle.net/cfSXY/
You can firstly have everything hidden by default (except one form maybe) using CSS, which gets rid of this:
$('.sim-micro-desktop').hide();
$('.sim-mini-desktop').hide();
$('.sim-maxi-desktop').hide();
$('.sim-mega-desktop').hide();
$('.phone-smart-micro-desktop').hide();
$('.phone-smart-mini-desktop').hide();
$('.phone-smart-desktop').hide();
$('.phone-smart-maxi-desktop').hide();
This has a negative implication for users without javascript, if you're worried - they'll never be able to see the other forms.
Next, only one radio can be checked, so just find out which one it is using:
$('input[name=group1]:checked);
But why would you do that, so you have the radios have a click handler more like:
$('#group input[type="radio"').click(function(){
//code to show/hide form
});
Now you have a choice as to how you link your radio buttons to the different forms one way could be to use the data attribute, so you define your radios like so:
<label><input type="radio" name="group1" class="phone-smart-maxi-btn" data-form="phone-smart-maxi-desktop"/></label>
Which you can access like so:
$('input[name=group1]:checked).data("form");
Now all you need to do is hide the div that was already showing, but that can be achieved with a similar use of the data attribute or by using the :visible selector.

jquery/javascript perform function on checkbox click or adjacent text click

I have an unordered list of text items with checkboxes beside each of them. I want to perform the same function both when a checkbox is checked/unchecked and when the text is clicked.
Here's what I have right now:
The HTML
<li><input type="checkbox" class="cbox" name="adwords_list[]" value="shave club" ><p class="term"> shave club</p></li>
The JS
$(function() {
$('ol.phrases li .term').click(function() {
$cboxStatus = $(this).parent().find('.cbox').prop('checked');
if ($cboxStatus) {
$(this).parent().find('.cbox').prop('checked', false);
} else {
$(this).parent().find('.cbox').prop('checked', true);
}
});
});
$(':checkbox, .term').on('change', function() {
console.log($(this).prop('checked'));
});
The on.change function isn't calling when the term is clicked. What can I do to get an accurate representation of the checked state no matter what element is clicked/changed?
If you change the p.term elements to label, with appropriate for attributes matching the associated checkboxes, clicking the text is just the same as checking the box. You then only need to watch the checkbox events.
<input type="checkbox" class="cbox" name="adwords_list[]" value="shave club" id="cb1" />
<label class="term" for="cb1"> shave club</label>
You can add
.term {
display: block;
}
etc. to your CSS if you need to match the styling of the p tag.

Categories