You can use radio groups to achieve that functionality:
<input type="radio" name="choice" value="yes" />Yes
<input type="radio" name="choice" value="No" />No
<input type="radio" name="choice" value="null" />null
The jQuery plugin "jstree" with the checkbox plugin can do this.
http://www.jstree.com/documentation/checkbox
-Matt
My proposal would be using
See examples at:
/**_x000D_
* loops thru the given 3 values for the given control_x000D_
*/_x000D_
function tristate(control, value1, value2, value3) {_x000D_
switch (control.value.charAt(0)) {_x000D_
case value1:_x000D_
control.value = value2;_x000D_
break;_x000D_
case value2:_x000D_
control.value = value3;_x000D_
break;_x000D_
case value3:_x000D_
control.value = value1;_x000D_
break;_x000D_
default:_x000D_
// display the current value if it's unexpected_x000D_
alert(control.value);_x000D_
}_x000D_
}_x000D_
function tristate_Marks(control) {_x000D_
tristate(control,'\u2753', '\u2705', '\u274C');_x000D_
}_x000D_
function tristate_Circles(control) {_x000D_
tristate(control,'\u25EF', '\u25CE', '\u25C9');_x000D_
}_x000D_
function tristate_Ballot(control) {_x000D_
tristate(control,'\u2610', '\u2611', '\u2612');_x000D_
}_x000D_
function tristate_Check(control) {_x000D_
tristate(control,'\u25A1', '\u2754', '\u2714');_x000D_
}
_x000D_
<input type='text' _x000D_
style='border: none;' _x000D_
onfocus='this.blur()' _x000D_
readonly='true' _x000D_
size='1' _x000D_
value='❓' onclick='tristate_Marks(this)' />_x000D_
_x000D_
<input style="border: none;"_x000D_
id="tristate" _x000D_
type="text" _x000D_
readonly="true" _x000D_
size="1" _x000D_
value="❓" _x000D_
onclick="switch(this.form.tristate.value.charAt(0)) { _x000D_
case '❓': this.form.tristate.value='✅'; break; _x000D_
case '✅': this.form.tristate.value='❌'; break; _x000D_
case '❌': this.form.tristate.value='❓'; break; _x000D_
};" />
_x000D_
As I needed something like this -without any plug-in- for script-generated checkboxes in a table... I ended up with this solution:
<!DOCTYPE html>
<html>
<body>
Toto <input type="checkbox" id="myCheck1" onclick="updateChkBx(this)" /><br />
Tutu <input type="checkbox" id="myCheck2" onclick="updateChkBx(this)" /><br />
Tata <input type="checkbox" id="myCheck3" onclick="updateChkBx(this)" /><br />
Tete <input type="checkbox" id="myCheck4" onclick="updateChkBx(this)" /><br />
<script>
var chkBoxState = [];
function updateChkBx(src) {
var idx = Number(src.id.substring(7)); // 7 to bypass the "myCheck" part in each checkbox id
if(typeof chkBoxState[idx] == "undefined") chkBoxState[idx] = false; // make sure we can use stored state at first call
// the problem comes from a click on a checkbox both toggles checked attribute and turns inderminate attribute to false
if(chkBoxState[idx]) {
src.indeterminate = false;
src.checked = false;
chkBoxState[idx] = false;
}
else if (!src.checked) { // passing from checked to unchecked
src.indeterminate = true;
src.checked = true; // force considering we are in a checked state
chkBoxState[idx] = true;
}
}
// to know box state, just test indeterminate, and if not indeterminate, test checked
</script>
</body>
</html>
Edit — Thanks to Janus Troelsen's comment, I found a better solution:
indeterminate
See w3c reference guide. To make checkbox appear visually indeterminate set it to true:
element.indeterminate = true;
Here is Janus Troelsen's fiddle. Note, however, that:
The indeterminate
state cannot be set in the HTML markup, it can only be done via Javascript (see this JSfiddle test and this detailed article in CSS tricks)
This state doesn't change the value of the checkbox, it is only a visual cue that masks the input's real state.
Browser test: Worked for me in Chrome 22, Firefox 15, Opera 12 and back to IE7. Regarding mobile browsers, Android 2.0 browser and Safari mobile on iOS 3.1 don't have support for it.
Previous answer
Another alternative would be to play with the checkbox transparency for the "some selected" state (as Gmail
doesused to do in previous versions). It will require some javascript and a CSS class. Here I put a particular example that handles a list with checkable items and a checkbox that allows to select all/none of them. This checkbox shows a "some selected" state when some of the list items are selected.Given a checkbox with an ID
#select_all
and several checkboxes with a class.select_one
,The CSS class that fades the "select all" checkbox would be the following:
.some_selected { opacity: 0.5; filter: alpha(opacity=50); }
And the JS code that handles the tri-state of the select all checkbox is the following:
$('#select_all').change (function () { //Check/uncheck all the list's checkboxes $('.select_one').attr('checked', $(this).is(':checked')); //Remove the faded state $(this).removeClass('some_selected'); }); $('.select_one').change (function () { if ($('.select_one:checked').length == 0) $('#select_all').removeClass('some_selected').attr('checked', false); else if ($('.select_one:not(:checked)').length == 0) $('#select_all').removeClass('some_selected').attr('checked', true); else $('#select_all').addClass('some_selected').attr('checked', true); });
You can try it here: http://jsfiddle.net/98BMK/
Hope that helps!
Besides all cited above, there are jQuery plugins that may help too:
for individual checkboxes:
for tree-like behavior checkboxes:
EDIT Both libraries uses the 'indeterminate' checkbox attribute, since this attribute in Html5 is just for styling (https://www.w3.org/TR/2011/WD-html5-20110113/number-state.html#checkbox-state), the null value is never sent to the server (checkboxes can only have two values).
To be able to submit this value to the server, I've create hidden counterpart fields which are populated on form submission using some javascript. On the server side, you'd need to check those counterpart fields instead of original checkboxes, of course.
I've used the first library (standalone checkboxes) where it's important to:
Hope that helps.
Like @Franz answer you can also do it with a select. For example:
<select>
<option></option>
<option value="Yes">Yes</option>
<option value="No">No</option>
</select>
With this you can also give a concrete value that will be send with the form, I think that with javascript indeterminate version of checkbox, it will send the underline value of the checkbox.
At least, you can use it as a callback when javascript is disabled. For example, give it an id and in the load event change it to the javascript version of the checkbox with indeterminate status.
Here is a runnable example using the mentioned indeterminate
attribute:
const indeterminates = document.getElementsByClassName('indeterminate');_x000D_
indeterminates['0'].indeterminate = true;
_x000D_
<form>_x000D_
<div>_x000D_
<input type="checkbox" checked="checked" />True_x000D_
</div>_x000D_
<div>_x000D_
<input type="checkbox" />False_x000D_
</div>_x000D_
<div>_x000D_
<input type="checkbox" class="indeterminate" />Indeterminate_x000D_
</div>_x000D_
</form>
_x000D_
Just run the code snippet to see how it looks like.
You could use HTML's indeterminate
IDL attribute on input
elements.
It's possible to have HTML form elements disabled -- wouldn't that do? Your users would see it in one of three states, i.e. checked, unchecked, and disabled, which would be greyed out and not clickable. To me, that seems similar to "null" or "not applicable" or whatever you're looking for in that third state.
Refering to @BoltClock answer, here is my solution for a more complex recursive method:
http://jsfiddle.net/gx7so2tq/2/
It might not be the most pretty solution but it works fine for me and is quite flexible.
I use two data objects defining the container:
data-select-all="chapter1"
and the elements itself:
data-select-some="chapter1"
Both having the same value. The combination of both data-objects within one checkbox allows sublevels, which are scanned recursively. Therefore two "helper" functions are needed to prevent the change-trigger.
I think that the most semantic way is using readonly
attribute that checkbox inputs can have. No css, no images, etc; a built-in HTML property!
See Fiddle:
http://jsfiddle.net/chriscoyier/mGg85/2/
As described here in last trick: http://css-tricks.com/indeterminate-checkboxes/
Building on the answers above using the indeterminate state, I've come up with a little bit that handles individual checkboxes and makes them tri-state.
MVC razor uses 2 inputs per checkbox anyway (the checkbox and a hidden with the same name to always force a value in the submit). MVC uses things like "true" as the checkbox value and "false" as the hidden of the same name; makes it amenable to boolean use in api calls. This snippet uses an third hidden to persist the last request values across submits.
Checkboxes initialized with the below will start indeterminate. Checking once turns on the checkbox. Checking twice turns off the checkbox (returning the hidden value of the same name). Checking a third time returns it to indeterminate (and clears out the hidden so a submit will produce a blank).
The page also populates another hidden (e.g. triBox2Orig) with whatever value was on the query string to start, so the 3 states can be initialized and persisted between submits.
$(document).ready(function () {
var initCheckbox = function (chkBox)
{
var hidden = $('[name="' + $(chkBox).prop("name") + '"][type="hidden"]');
var hiddenOrig = $('[name="' + $(chkBox).prop("name") + 'Orig"][type="hidden"]').prop("value");
hidden.prop("origValue", hidden.prop("value"));
if (!chkBox.prop("checked") && !hiddenOrig) chkBox.prop("indeterminate", true);
if (chkBox.prop("indeterminate")) hidden.prop("value", null);
chkBox.change(checkBoxToggleFun);
}
var checkBoxToggleFun = function ()
{
var isChecked = $(this).prop('checked');
var hidden = $('[name="' + $(this).prop("name") + '"][type="hidden"]');
var thirdState = isChecked && hidden.prop("value") === hidden.prop("origValue");
if (thirdState) { // on 3rd click of a checkbox, set it back to indeterminate
$(this).prop("indeterminate", true);
$(this).prop('checked', false);
}
hidden.prop("value", thirdState ? null : hidden.prop("origValue"));
};
var chkBox = $('#triBox1');
initCheckbox(chkBox);
chkBox = $('#triBox2');
initCheckbox(chkBox);
});
There's a simple JavaScript tri-state input field implementation at https://github.com/supernifty/tristate-checkbox
You'll need to use javascript/css to fake it.
Try here for an example: http://www.dynamicdrive.com/forums/archive/index.php/t-26322.html
Here other Example with simple jQuery and property data-checked
:
$("#checkbox")_x000D_
.click(function(e) {_x000D_
var el = $(this);_x000D_
_x000D_
switch (el.data('checked')) {_x000D_
_x000D_
// unchecked, going indeterminate_x000D_
case 0:_x000D_
el.data('checked', 1);_x000D_
el.prop('indeterminate', true);_x000D_
break;_x000D_
_x000D_
// indeterminate, going checked_x000D_
case 1:_x000D_
el.data('checked', 2);_x000D_
el.prop('indeterminate', false);_x000D_
el.prop('checked', true);_x000D_
break;_x000D_
_x000D_
// checked, going unchecked_x000D_
default:_x000D_
el.data('checked', 0);_x000D_
el.prop('indeterminate', false);_x000D_
el.prop('checked', false);_x000D_
_x000D_
}_x000D_
});
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>_x000D_
<label><input type="checkbox" name="checkbox" value="" checked id="checkbox"> Tri-State Checkbox </label>
_x000D_
You can use an indeterminate state: http://css-tricks.com/indeterminate-checkboxes/. It's supported by the browsers out of the box and don't require any external js libraries.
Source: Stackoverflow.com