Straightforward Accessibility

Estelle Weyl

http://instartlogic.github.io/p/oscon/project.html

Create a Merry Go Round

Create the form

<form action="">
</form>

Add the fieldset

<form action="">
<fieldset class="mgr" id="mgrID">

</fieldset>
</form>

mgrID will be used to instantiate MerryGoRound

Add the legend

<form action="">
<fieldset class="mgr" id="address">
<legend>Instructions to Screen Reader user here:</legend>

</fieldset>
</form>

The legend is read aloud to the screen reader user

<div> to hold the visual component

<form action="">
<fieldset class="mgr" id="address">
<legend>Select an address to edit:</legend>
<div>
</div>
</fieldset>
</form>

Needed if you're going to use the optional arrows.

Add the labels

<form action="">
<fieldset class="mgr" id="address">
<legend>Select an address to edit:</legend>
<div>
  <ul class="mgr-labels left0">
    <li>
      <label for="radioID1">
         1st label
      </label>
    </li>
    <li>
      <label for="radioID2">
         2nd label
      </label>
    </li>...
  </ul>
</div>
</fieldset>
</form>

Example Labels

<form action="">
<fieldset class="mgr" id="address">
<legend>Select an address to edit:</legend>
<div>
  <ul class="mgr-labels left0">
    <li>
      <label for="address1">
      <p>Instart Logic</p>
      <p>US Headquarters</p>
      <p>450 Lambert Avenue</p>
      <p>Palo Alto, CA 94306</p>
      </label>
    </li>
    <li>
      <label for="address2">
      <p>Instart Logic</p>
      <p>India Office</p>
      <p>6th Floor, HM Vibha Towers</p>
      <p>Hosur Rd, Adugodi</p>
      <p>Bengaluru 560029</p>
      </label>
    </li>...
  </ul>
 </div>
</fieldset>
</form>

Add the Radio Buttons

<form action="">
<fieldset class="mgr" id="address">
<legend>Select an address to edit:</legend>
<div>
  <ul class="mgr-labels left0">
    <li>
      <label for="radioID1"> ...
    </li>...
  </ul>
 </div>
<ul id="optionalID" class="mgr-radios">
    <li>
      <input type="radio" name="sameName" data-value="0" id="radioID1" checked>
      <span></span>
    </li>
    <li>
      <input type="radio" name="sameName" data-value="1" id="radiosID2">
      <span></span>
    </li>...
  </ul>
</fieldset>
</form>

Make the form explicitly submittable

...
  <ul id="addressradios" class="mgr-radios">
    <li>
      <input type="radio" name="shipping-addresses" data-value="0" id="address1" checked><span></span>
    </li>
    <li>
      <input type="radio" name="shipping-addresses" data-value="1" id="address2"><span></span>
    </li>...
  </ul>
</fieldset>
<input type="submit" value="Put Submit Button Text Here">
</form>

Hitting enter or the button will submit the form

Add the JavaScript

<script src="path/js/merry-go-round.js"></script>

Simple JavaScript

var mgr = {

  mgrID: '',

  init: function (id) {
    mgr.mgrID = id;
    mgr.activateMerryGoRound();  
  },

  activateMerryGoRound : function () {
    var radios = document.querySelectorAll('#' + 
                 mgr.mgrID + ' input[type="radio"]');
      for(var i = 0; i < radios.length; i++) {
        radios[i].addEventListener('change', function (e) {
          mgr.mgrChange(e.target.dataset.value);
        })
    }
  },

  mgrChange: function (value) {
    document.querySelector('.mgr-labels')
      .setAttribute('class', 'mgr-labels left' + value);
  }
}

Initialize the MerryGoRound by ID

<script>
window.onload = function () {
  mgr.init('mgrID');
};
</script>

Add the CSS

<link rel="stylesheet" href="path/css/mgr.css"/>

Modify the SCSS

$themeColor: [color value for theme>;
        
//$arrowWidth: [the border-width of arrow's two lines];
//$arrowSize: [the length of those two lines];

$mgrWidth: [width of mgr in em units];
$mgrBorder: [none or border shorthand declaration];
$mgrRadius: [corners of the mgr];

$radioSpacing: [width of space between radio buttons];

Optional Arrows

<form action="">
<fieldset class="mgr" id="address">
<legend>Select an address to edit:</legend>
<div>
  <a class="backward" data-move="backward" data-mgr="RADIONAME" hidden></a>
  <ul class="mgr-labels left0">
    <li>
      <label for="address1">...
      </label>
    </li>
    <li>
      <label for="address2">...
      </label>
    </li>...
  </ul>
  <a class="forward" data-move="forward" data-mgr="RADIONAME" hidden></a>
  </div>
  <ul id="addressradios" class="mgr-radios">
    <li>
      <input type="radio" name="RADIONAME" data-value="0" id="address1" checked><span></span>
    </li>
    <li>
      <input type="radio" name="RADIONAME" data-value="1" id="address2"><span></span>
    </li>...
  </ul>
  </fieldset>
  </form>

Arrowed JavaScript

var mgr = {

  arrowButtons: true, // set to false if no arrows on your mgr
  mgrID: '',

  init: function (id) {
    mgr.mgrID = id;
    mgr.activateMerryGoRound();  
  },

  activateMerryGoRound : function () {
    var radios = document.querySelectorAll('#' + mgr.mgrID +' input[type="radio"]'),
        i = 0,
        l = radios.length;
    if(l) {
      if(l > 1  && mgr.arrowButtons) { // if you have more than one card, add back and forward buttons for sited users
        mgr.activateForwardAndBack();
      } 
      for(i = 0; i < l; i++) {
        radios[i].addEventListener('change', function (e) {
          mgr.mgrChange(e.target.dataset.value);
        })
      }
    }
  },

  // Activate arrows if there is more than one item and arrows are included
  activateForwardAndBack: function () {
    var arrowButtons = document.querySelectorAll('#' + mgr.mgrID +' [data-move]'),
        l = arrowButtons.length;
    for (var i = 0; i < l; i++) {
      arrowButtons[i].removeAttribute('hidden');arrowButtons[i].addEventListener('click', function(e) {
        mgr.moveForwardOrBack(e);
      });
      /*
      If you want to make the arrow buttons keyboardable then they have to be visible to screen readers:
       // enable keyboard focus
       //arrowButtons[i].setAttribute('tabindex', 0);

       // add an aria-label so something is read when arrows get keyboard focus
       //arrowButtons[i].setAttribute('aria-label', 'Go ' + arrowButtons[i].dataset.move + ' one radio button');
      
      // add the even handler
      arrowButtons[i].addEventListener('keyup', function(e) {
        if(e.keyCode == 13) {
          mgr.moveForwardOrBack(e);
          // add aria live to so when selection has changed, the user knows it.
        }
      });
      */
    }
  },

  moveForwardOrBack: function (e) {
        var name = e.target.dataset.mgr,
            buttons = document.querySelectorAll('input[name=' + name + ']'),
            move = (e.target.dataset.move == 'forward') ? 1 : -1,
            selectedButton = +document.querySelector('input[name=' + name + ']:checked').dataset.value,
            newValue = (buttons.length + selectedButton + move) % buttons.length;
        buttons[newValue].checked = true;
        mgr.mgrChange(newValue);
  },

  mgrChange: function (value) {
    document.querySelector('.mgr-labels').setAttribute('class', 'mgr-labels left' + value);
  }
}