(function() { 'use strict'; var radioButtonId = 1; function getNextRadioButtonId() { return 'laz-radio-button-' + (radioButtonId++); } angular.module('shared') .component('lazRadioButton', { bindings: { name: '@', ngChange: '<', ngClass: '<', ngClick: '<', ngModel: '<', ngValue: '<', ngDisabled: '<', overrideClass: '@', overrideRadioButtonClass: '@', screenReaderLabel: '@' }, controller: 'LazRadioButton', require: { ngModelCtrl: 'ngModel' }, templateUrl: '/shared/js/angular/ui/laz-radio-button.html', transclude: true }) .controller('LazRadioButton', ['$attrs', '$element', function LazRadioButtonCtrl($attrs, $element) { var ctrl = this; ctrl.radioButtonId = getNextRadioButtonId(); ctrl.$postLink = function() { setupRadioGroup(); setupRadioButton(); }; ctrl.getClass = function() { if (ctrl.overrideClass) { return ctrl.overrideClass; } return 'radioCustom'; }; ctrl.getRadioButtonClass = function() { if (ctrl.overrideRadioButtonClass) { return ctrl.overrideRadioButtonClass; } return 'radioCustom_button'; }; ctrl.getScreenReaderLabel = function() { if (ctrl.screenReaderLabel) { return ctrl.screenReaderLabel; } return ''; }; ctrl.handleChange = function(event) { if (ctrl.ngModelCtrl && typeof ctrl.ngModel !== 'function') { ctrl.ngModelCtrl.$setViewValue(ctrl.ngModel); } if (ctrl.ngChange && typeof ctrl.ngChange === 'function') { ctrl.ngChange(event); } }; ctrl.handleClick = function(event) { if (ctrl.ngClick) { ctrl.ngClick(event); } uncheckAllButtonsInGroup(); checkRadioButton(event.target); }; function setupRadioGroup() { var maybeRadioGroup = $element.closest('[role="radiogroup"]'); if (maybeRadioGroup) { ctrl.radioGroup = maybeRadioGroup[0]; } } function setupRadioButton() { var radioButton = getRadioButton(); if (isSelectedRadioButton()) { uncheckAllButtonsInGroup(); checkRadioButton(radioButton); } else if (!isFirstRadioButtonInGroup(radioButton)) { radioButton.setAttribute('tabindex', -1); } if (!ctrl.name) { // If no name is given for the radio button, // keyboard accessibility won't be supported by the browser. // We will try to provide this functionality ourselves. $element.on('keydown', handleKeyDown); } } function isFirstRadioButtonInGroup(radioButton) { if (!ctrl.radioGroup) { return true; } var radioButtons = ctrl.radioGroup.querySelectorAll('input[type=radio]'); return radioButtons && radioButtons[0] === radioButton; } function getRadioButton() { return $element.find('input[type=radio]')[0]; } function isSelectedRadioButton() { return (typeof ctrl.ngModel === 'function' && ctrl.ngValue === ctrl.ngModel()) || (ctrl.ngModel && ctrl.ngValue === ctrl.ngModel) } function handleKeyDown(event) { switch (event.keyCode) { case 39: // right arrow behaves the same as case 38: // up arrow handleArrowUp(event); break; case 37: // left arrow behaves the same as case 40: // down arrow handleArrowDown(event); break; } } function handleArrowUp(event) { if (!ctrl.radioGroup) { return; } event.preventDefault(); var radioButton = getRadioButton(); uncheckRadioButton(radioButton); goToNextRadioButton(radioButton); } function handleArrowDown(event) { if (!ctrl.radioGroup) { return; } event.preventDefault(); var radioButton = getRadioButton(); uncheckRadioButton(radioButton); goToPreviousRadioButton(radioButton); } function checkRadioButton(radioButton) { radioButton.setAttribute('tabindex', '0'); radioButton.checked = true; } function uncheckRadioButton(radioButton) { radioButton.setAttribute('tabindex', '-1'); radioButton.checked = false; } function uncheckAllButtonsInGroup() { if (!ctrl.radioGroup) { return; } var radioButtons = ctrl.radioGroup.querySelectorAll('input[type=radio]'); for (var i = 0; i < radioButtons.length; i++) { uncheckRadioButton(radioButtons[i]); } } function goToNextRadioButton(currentRadioButton) { if (!ctrl.radioGroup) { return; } var radioButtons = ctrl.radioGroup.querySelectorAll('input[type=radio]'); for (var i = 0; i < radioButtons.length; i++) { if (radioButtons[i].id === currentRadioButton.id) { if ((i + 1) !== radioButtons.length) { goToRadioButton(radioButtons[i + 1]); } else { goToRadioButton(radioButtons[0]); } break; } } } function goToPreviousRadioButton(currentRadioButton) { if (!ctrl.radioGroup) { return; } var radioButtons = ctrl.radioGroup.querySelectorAll('input[type=radio]'); for (var i = 0; i < radioButtons.length; i++) { if (radioButtons[i].id === currentRadioButton.id) { if (i !== 0) { goToRadioButton(radioButtons[i - 1]); } else { goToRadioButton(radioButtons[radioButtons.length - 1]); } break; } } } function goToRadioButton(radioButton) { checkRadioButton(radioButton); radioButton.click(); radioButton.focus(); } }]); })();