Checkboxes and Radio Buttons

Checkboxes

Red
Yellow
Blue
Orange

Radios

Delivery Method

Email
Fedex
UPS
Snail Mail

HTML Source Code

    <h2>Checkboxes</h2>
    <div class="checkboxes">
      <div class="field">
        <div tabindex="0" role="checkbox" aria-setsize="4" aria-posinset="1" aria-checked="false" aria-labelledby="check-label-1" class="checkbox"><i class="fa fa-square-o"></i></div>
        <div id="check-label-1" class="label">Red</div>
      </div>
      <div class="field">
        <div tabindex="0" role="checkbox" aria-setsize="4" aria-posinset="2" aria-checked="false" aria-labelledby="check-label-2" class="checkbox"><i class="fa fa-square-o"></i></div>
        <div id="check-label-2" class="label">Yellow</div>
      </div>
      <div class="field">
        <div tabindex="0" role="checkbox" aria-setsize="4" aria-posinset="3" aria-checked="false" aria-labelledby="check-label-3" class="checkbox"><i class="fa fa-square-o"></i></div>
        <div id="check-label-3" class="label">Blue</div>
      </div>
      <div class="field">
        <div tabindex="0" role="checkbox" aria-setsize="4" aria-posinset="4" aria-checked="false" aria-labelledby="check-label-4" class="checkbox"><i class="fa fa-square-o"></i></div>
        <div id="check-label-4" class="label">Orange</div>
      </div>
    </div>
    <h2>Radios</h2>
    <div role="radiogroup" aria-required="true" class="radios" aria-labelledby="pseudo-legend">
      <h3 id="pseudo-legend">Delivery Method</h3>
      <div class="field">
        <div tabindex="0" role="radio" aria-setsize="4" aria-posinset="1" aria-checked="true" aria-labelledby="radio-label-1" class="radio"><i class="fa fa-dot-circle-o"></i></div>
        <div id="radio-label-1" class="label">Email</div>
      </div>
      <div class="field">
        <div tabindex="-1" role="radio" aria-setsize="4" aria-posinset="2" aria-checked="false" aria-labelledby="radio-label-2" class="radio"><i class="fa fa-circle-o"></i></div>
        <div id="radio-label-2" class="label">Fedex</div>
      </div>
      <div class="field">
        <div tabindex="-1" role="radio" aria-setsize="4" aria-posinset="3" aria-checked="false" aria-labelledby="radio-label-3" class="radio"><i class="fa fa-circle-o"></i></div>
        <div id="radio-label-3" class="label">UPS</div>
      </div>
      <div class="field">
        <div tabindex="-1" role="radio" aria-setsize="4" aria-posinset="4" aria-checked="false" aria-labelledby="radio-label-4" class="radio"><i class="fa fa-circle-o"></i></div>
        <div id="radio-label-4" class="label">Snail Mail</div>
      </div>
    </div>

JavaScript Source Code

Dependencies:
  • JQuery
// mimic functionality of clicking a
// label with a proper for attribute
$(document.body).on('click', '.label', function (e) {
  var assocInput = $('[aria-labelledby="' + this.id + '"]')[0];

  if (assocInput) {
    assocInput.click();
  }
});

$(document.body).on('click', '.checkbox', function (e) {
  var $target = $(this);
  var $icon = $target.find('i.fa').first();
  var wasChecked = $icon.hasClass('fa-check-square-o');
  var newClass = (wasChecked) ? 'fa-square-o' : 'fa-check-square-o';
  var oldClass = (wasChecked) ? 'fa-check-square-o' : 'fa-square-o';
  var ariaCheckedVal = (wasChecked) ? 'false' : 'true';

  $icon
    .removeClass(oldClass)
    .addClass(newClass);
  $target.attr('aria-checked', ariaCheckedVal);
});



$(document.body).on('keydown', '.checkbox', function (e) {
  var which = e.which;

  if (which === 13 || which === 32) {
    e.preventDefault(); // don't scroll
    e.target.click();
  }
});


var $radios = $('.radio');

$(document.body).on('click', '.radio', function (e) {
  var $target = $(this);
  var $icon = $target.find('i.fa');

  $icon
    .removeClass('fa-circle-o')
    .addClass('fa-dot-circle-o');
  $target
    .attr('aria-checked', 'true')
    .prop('tabindex', '0');

  $radios.each(function () {
    if (this !== $target[0]) {
      $(this)
        .attr('aria-checked', 'false')
        .prop('tabindex', '-1')
        .find('i')
          .removeClass('fa-dot-circle-o')
          .addClass('fa-circle-o');
    }
  });
});


$(document.body).on('keydown', '.radio', function (keyVent) {
  var which = keyVent.which;
  var target = keyVent.target;

  if (which === 37 || which === 38) { // LEFT |or| UP
    selectAdjacentRadio(target, 'prev');
	keyVent.preventDefault(); 
  } else if (which === 39 || which === 40) { // RIGHT |or| DOWN
    selectAdjacentRadio(target, 'next');
	keyVent.preventDefault(); 
  }

});

// iOS support for clicking on these 'non-natively clickable' elements
$(document.body).on('touchstart', '.radio, .checkbox', function () {
  this.click();
});


function selectAdjacentRadio(radio, dir) {
  var currentIndex = $.inArray(radio, $radios);
  var adjacentIndex = (dir === 'next') ? currentIndex + 1 : currentIndex - 1;
  var adjacentRadio = $radios[adjacentIndex];

  if (!adjacentRadio) {
    // go from last to first and vice versa
    adjacentRadio = (dir === 'next') ? $radios[0] : $radios[$radios.length - 1];
  }

  adjacentRadio.click();
  adjacentRadio.focus();
}

CSS Source Code

.label {
    display: inline-block;
    padding-left: 4px;
    cursor: default;
}

.checkbox, .radio {
    display: inline-block;
    width: 18px;
}

Copy and Paste Full Page Example