Set Focus outline on containing label on checkbox - javascript

When tabbing through a list of checkboxes I want to see the outline of a checkbox around the whole label. The code I have just puts the outline on the input itself:
<label class="b-label" data-selected-value="Hello" data-selected-display-name="Hello">
<span class="b-checkbox">
<input class="b-input" name="Hello" type="checkbox" value="Hello">
</span>
<span class="b-text-wrap">
<span class="b-text">Hello</span><span class="b-count">12</span>
</span>
</label>
Codepen: https://codepen.io/anon/pen/gyeGZG
The idea is to make the checkboxes as accessible as possible for keyboard users etc.
Cheers

You don't need JS to do this, CSS can manage it.
:focus-within
The :focus-within CSS pseudo-class represents an element that has received focus or contains an element that has received focus. In other words, it represents an element that is itself matched by the :focus pseudo-class or has a descendant that is matched by :focus. (This includes descendants in shadow trees.)
MDN
Support is non-IE/Edge, although the latter may change when Edge switches to Chromium-based
body {
text-align: center;
}
.b-label {
margin:1em;
display: inline-block;
padding:.25em;
}
.b-label:focus-within {
outline :1px solid red;
}
<label class="b-label" data-selected-value="Hello" data-selected-display-name="Hello">
<span class="b-checkbox">
<input class="b-input" name="Hello" type="checkbox" value="Hello">
</span>
<span class="b-text-wrap">
<span class="b-text">Hello</span><span class="b-count">1</span>
</span>
</label>
<label class="b-label" data-selected-value="Hello" data-selected-display-name="Hello">
<span class="b-checkbox">
<input class="b-input" name="Hello" type="checkbox" value="Hello">
</span>
<span class="b-text-wrap">
<span class="b-text">Hello</span><span class="b-count">2</span>
</span>
</label>
<label class="b-label" data-selected-value="Hello" data-selected-display-name="Hello">
<span class="b-checkbox">
<input class="b-input" name="Hello" type="checkbox" value="Hello">
</span>
<span class="b-text-wrap">
<span class="b-text">Hello</span><span class="b-count">3</span>
</span>
</label>

Related

How to apply css style from successive classes

I need, when the .checked class is present, to insert text-decoration: line-through; style to .todo-name
(I never understood if it is possible to do it with css, but in case I can also use js as a last chance)
<label class="checkbox-container" for="0"><span class="todo-name">Todo</span>
<input onclick="updateStatus(this)" type="checkbox" id="0" checked="">
<span class="checkmark checked"></span>
</label>
<!--This content does not have .checked and should not change-->
<label class="checkbox-container" for="0"><span class="todo-name">Todo</span>
<input onclick="updateStatus(this)" type="checkbox" id="0">
<span class="checkmark"></span>
</label>
<style>
/*.todo-name{text-decoration: line-through;}*/
/*Not working*/
/*
.checkbox-container .checked ~ .todo-name {
text-decoration: line-through;
}
.checkbox-container:not(.checked) .todo-name {text-decoration: line-through;}
*/
</style>
Codepen project
The end result should look like this
You've got a couple issues going on here. As mentioned in a comment, you should be using a pseudo-class, if you don't want to use JavaScript. :checked in this example.
Next, you are using the CSS selector ~, which selects a sibling that comes after the element, not before. So trying to select .todo-name with the selector #0:checked ~ .todo-name will not work due to the name coming before the checkbox.
Below is an example of a working version.
input:checked ~ .todo-name {
text-decoration: line-through;
}
<label class="checkbox-container" for="checkbox">
<input type="checkbox" id="checkbox" checked="">
<span class="todo-name">Todo</span>
</label>
<label class="checkbox-container" for="checkbox2">
<input type="checkbox" id="checkbox2">
<span class="todo-name">Todo</span>
</label>

checkbox default checked="checked" is not working?

checkbox default checked is not working!
I tried to fix it, but I can not find where is the error here?
so on page load that is checked, after page loadet that is unchecked!?
I tried that
<div class="onoffswitch" style="margin: 0 auto;">
<input type="checkbox" class="avacheckbox onoffswitch-checkbox" id="AvButtonAutoGames" checked="checked"/>
<label class="onoffswitch-label" for="AvButtonAutoGames">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
and that
<div class="onoffswitch" style="margin: 0 auto;">
<input type="checkbox" class="avacheckbox onoffswitch-checkbox" id="AvButtonAutoGames" checked/>
<label class="onoffswitch-label" for="AvButtonAutoGames">
<span class="onoffswitch-inner"></span>
<span class="onoffswitch-switch"></span>
</label>
</div>
To specify the value, use the checked="true", otherwise do not specify the property.
Checked: <input type="checkbox" checked="true" /><br/>
Not checked: <input type="checkbox" />
It's hard to see, but you're using this syntax to define the checkbox value?
document.getElementById('AvButtonAutoGames').checked = true
If so, this isn't correct - but in the first JS example you have a correct the prop usage:
$('#AvButtonAutoGames').prop('checked', true)
as in HTML5, the syntax to apply is simply <input checked> or to expand for clarity <input checked="checked">. The absence of the checked attribute leads to an unchecked input field.
Simply convert your .checked=X to the functional calls and it should work

Combining two filters when clicking two different sections of buttons

I would like to combine two filters when clicking two different sections of buttons. Right now, when I click one button it removes the selection of the previous one. I have tried several functions but I have not been able to come with the right logic.
I have written a schema of my current status.
HTML
<!-- Buttons -->
<p> Language: <button class="btn" data-category="en"> EN </button> <button class="btn" data-category="it"> IT </button> </p>
<p> Stuff: <button class="btn" data-category="a"> A </button> <button class="btn" data-category="b"> B </button> <button class="btn" data-category="c"> C </button> </p>
<!-- Elements to select -->
<div class="element en a">
<p>en A</p>
</div>
<div class="element en b">
<p>en B</p>
</div>
<div class="element it c">
<p>it C</p>
</div>
<div class="element it b">
<p>it b</p>
</div>
js / jQuery
$(".btn").click(function(e){
e.preventDefault();
var category = $(this).data("category")
$('.element').hide();
$('.element.'+category).fadeIn();
})
It's also in this fiddle.
Also, nice to haves:
I would like to know how to color the button once it is selected.
Add a reset button (which I guess would be easy adding "reset" in data-category.
Thanks for the advice and the suggestions in advance!
One method is to use radio buttons. They allow one selection per group.
One downside is that you can't uncheck a radio button unless its by selecting another one in the same group, so I've added a "reset" button to each group.
Upon selection, I'm building a selector string of classes based on the checked buttons.
$(".mycb input").on('change', function(e) {
// select all the checked buttons.
var $checked = $('.mycb :checked');
// build an array of all the checked values.
var checked_classes = $checked.map(function() {
return this.value;
}).toArray();
// add the baseline "element" class to the array.
checked_classes.unshift('.element');
// build the class selector string.
var classes=checked_classes.join('.');
// debug the class selector string.
// console.log(classes);
// hide all elements.
$('.element').hide();
// show the elements that match the class selector string.
$(classes).fadeIn();
});
$('.reset').on('click', function() {
var $container = $(this).closest('p');
$('input', $container).prop('checked', false).last().trigger('change');
});
btn-selected {
color: red;
}
.mycb input {
display: none;
}
.mycb span {
background-color: white;
border: 1px solid #CCC;
border-radius: .3em;
padding: 0 .3em;
cursor:pointer;
user-select: none;
}
.mycb input:checked+span {
background-color: lightblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Button -->
<p>Language:
<label class="mycb">
<input type="radio" name="lang" value="en">
<span>EN</span>
</label>
<label class="mycb">
<input type="radio" name="lang" value="it">
<span>IT</span>
</label>
<span class="mycb reset"><span>Reset</span></span>
</p>
<p>Stuff:
<label class="mycb">
<input type="radio" name="stuff" value="a">
<span>A</span>
</label>
<label class="mycb">
<input type="radio" name="stuff" value="b">
<span>B</span>
</label>
<label class="mycb">
<input type="radio" name="stuff" value="c">
<span>C</span>
</label>
<span class="mycb reset"><span>Reset</span></span>
</p>
<!-- Elements to select -->
<div class="element en a">
<p>en A</p>
</div>
<div class="element en b">
<p>en B</p>
</div>
<div class="element it c">
<p>it C</p>
</div>
<div class="element it b">
<p>it b</p>
</div>
I have forked your js fiddle to provide a solution using your CSS class
https://jsfiddle.net/sguex20k/
JavaScript
$('.btn').removeClass('btn-selected'); // resetting all buttons to remove class
/* other code */
$(this).addClass('btn-selected'); // adding class to clicked button
And the problem in your CSS you were missing the . in your selector
.btn-selected { }

How do I make a button-like filter?

I want to make a button-like filter in my web. Right now, I just put the radio-button filter inside the box, but I want to remove the radio button and just make the filter work when I just click the box.
The code looks like this right now:
<div class="question-header" data-bind="visible: jobQuestions().length > 0">
<div class="col-sm-3" id="filter-1">
<div class="panel-body">
<input type="radio" value="new" data-bind="checked: jobQuestionsFilter" class="" />
New Questions
(<span data-bind="text: newJobQuestionsCount"></span>)
</div>
</div>
<div class="col-sm-3" id="filter-2">
<div class="panel-body"">
<input type="radio" value="ignored" data-bind="checked: jobQuestionsFilter" />
Ignored Questions
(<span data-bind="text: ignoredJobQuestionsCount"></span>)
</div>
</div>
<div class="col-sm-3" id="filter-3">
<div class="panel-body">
<input type="radio" value="answered" data-bind="checked: jobQuestionsFilter" />
Answered Questions
(<span data-bind="text: answeredJobQuestionsCount"></span>)
</div>
</div>
<div class="col-sm-3" id="filter-4">
<div class="panel-body">
<input type="radio" value="all" data-bind="checked: jobQuestionsFilter" />
All Questions
(<span data-bind="text: allJobQuestionsCount"></span>)
</div>
</div>
</div>
What do i have to fix?
EDIT:
When I try to hover it, the bg-color of the entire box changes, but when I just click it only the part of it changes. I am assuming this is because the label size is not full. How can I fix this issue?
You can fix this by adding an id to each of the radio buttons and then wrapping the .panel-body in a label like this:
<label for="radio1">
<div class="panel-body">
<input type="radio" value="new" id="radio1" data-bind="checked: jobQuestionsFilter" class="" />
New Questions
(<span data-bind="text: newJobQuestionsCount"></span>)
</div>
</label>
Then in your css apply display: none to all the radio buttons you want to hide.
EDIT
I have created a codepen that will give you the desired results. The only thing you will need to do is arrange the buttons horizontally like the image you provided. I hope this gets you on the right track.
Play around with that for a while to familiarize yourself with how it works.
Give the input an id, use a label with the for attribute to connect the label to the input, hide the input, and use the :checked pseudo class and adjacent sibling selector to style the label when an input is selected by clicking on the label.
And since you want to only be able to select one input at a time, you need to give the elements a name attribute so they're all tied to providing a value for that name
input[type="radio"] {
display: none;
}
input[type="radio"]:checked + label {
background: #09c;
}
label {
height: 100%; width: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
<div class="question-header" data-bind="visible: jobQuestions().length > 0">
<div class="col-sm-3" id="filter-1">
<div class="panel-body">
<input type="radio" value="new" data-bind="checked: jobQuestionsFilter" class="" id="new" name="someName" /> <label for="new">New Questions (
<span data-bind="text: newJobQuestionsCount"></span>)</label>
</div>
</div>
<div class="col-sm-3" id="filter-2">
<div class="panel-body">
<input type="radio" value="ignored" data-bind="checked: jobQuestionsFilter" id="ignored" name="someName"/><label for="ignored"> Ignored Questions (
<span data-bind="text: ignoredJobQuestionsCount"></span>)</label>
</div>
</div>
<div class="col-sm-3" id="filter-3">
<div class="panel-body">
<input type="radio" value="answered" data-bind="checked: jobQuestionsFilter" id="answered" name="someName"/><label for="answered"> Answered Questions (
<span data-bind="text: answeredJobQuestionsCount"></span>)</label>
</div>
</div>
<div class="col-sm-3" id="filter-4">
<div class="panel-body">
<input type="radio" value="all" name="someName" data-bind="checked: jobQuestionsFilter" id="all"/> <label for="all">All Questions (
<span data-bind="text: allJobQuestionsCount"></span>)</label>
</div>
</div>
</div>

Multi inputs which user can only enter in one of them

Consider a form which has many inputs, the inputs each has an radio button associated with them. User selects a radio and the associated input will be displayed.
http://jsfiddle.net/0uL6zzja/
If the number of inputs increase (for example 15) we will end up with lots of boilerplate code in js of all radio buttons ( they all do the same thing, disable other inputs, enable my input)
The js is as:
$('#precentRadio').change(function () {
$("#dolorsInput").attr("disabled", true);
$("#precentInput").attr("disabled", false);
})
$('#dolorsRadio').change(function () {
$("#precentInput").attr("disabled", true);
$("#dolorsInput").attr("disabled", false);
})
Are there any way which can can minimize the code ?!
Working demo
Use a class name for the buttons that trigger the inputs to disable/enable, and a class name for the inputs. Disable them all, and enable the one you want by traversing from the clicked button to the closest .input-group then back down to the input field.
jQuery (this is all)
$('.some-button').change(function () {
$('.some-input').prop("disabled", true);
$(this).closest('.input-group').find('.some-input').prop("disabled", false);
})
HTML
Please enter amount in "$" or "%":<p/>
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-addon">
<input name="switched" checked="checked" type="radio" class="some-button">
</span>
<div class="input-group input-group-applyed-input-manager">
<span class="input-group-addon">$</span>
<input class="form-control some-input" type="text" >
</div>
</div>
</div>
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-addon">
<input name="switched" type="radio" class="some-button">
</span>
<div class="input-group input-group-applyed-input-manager">
<span class="input-group-addon">%</span>
<input class="form-control some-input" type="text" disabled>
</div>
</div>
</div>
(repeat)
Also disabled="true" isn't correct, it's not a boolean value in HTML, it's either there or not there, and you should use .prop() not attr() for disabled.
You can add a common class to your radio buttons and attach a single event to all of them. From there you can use DOM traversal to only change the related text input. Something like this:
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-addon">
<input name="switched" class="input-toggle" checked="checked" type="radio" />
</span>
<div class="input-group input-group-applyed-input-manager">
<span class="input-group-addon">$</span>
<input class="form-control" type="text" />
</div>
</div>
</div>
$('.input-toggle').change(function() {
$('.input-group input[type="text"]').prop('disabled', true); // disable all
$(this).closest('.input-group').find('input[type="text"]').prop('disabled', false);
});
Example fiddle
Sure. The correct way to associate radio buttons with a similar function is to use a common name rather than a class. This makes the radio buttons mutually exclusive (so only one of the options in the group can be active at once).
Then, add the jQuery .change handler not to a single item but to all the radio buttons with that name $('input:radio[name=whatever]').change( ... );.
Inside the function, it is easy to write code which enables the text field directly following the radio button that was clicked, using jQuery's next() method, and disables all other text fields that follow other radio buttons in the group.
If you can't change the HTML, but the ids of the radio buttons and inputs will continue to match (xxxRadio and xxxInput), you can handle things by looking up the id of the selected radio button, and enabling the respective input:
$('input[name=switched]').change(
function() {
var selected = $('input[name=switched]:checked');
var selId = selected.attr('id');
var inpId = '#' + selId.replace(/Radio$/, 'Input');
var activeInput = $(inpId);
$('input.form-control').prop('disabled' ,true);
activeInput.prop('disabled', false);
}
);
#import url('http://getbootstrap.com/dist/css/bootstrap.css');
div.input-group > div.input-group > span.input-group-addon {
border-radius: 0px !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Please enter amount in "$" or "%":<p/>
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-addon">
<input name="switched" checked="checked" type="radio" id="dolorsRadio">
</span>
<div class="input-group input-group-applyed-input-manager">
<span class="input-group-addon">$</span>
<input class="form-control" type="text" id="dolorsInput">
</div>
</div>
</div>
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-addon">
<input name="switched" type="radio" id="precentRadio">
</span>
<div class="input-group input-group-applyed-input-manager">
<span class="input-group-addon">%</span>
<input class="form-control" type="text" id="precentInput" disabled="true">
</div>
</div>
</div>

Categories