1/* 2* This content is licensed according to the W3C Software License at 3* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 4* 5* File: radioGroup.js 6* 7* Desc: Radio group widget using aria-activedescendant that implements ARIA Authoring Practices 8*/ 9 10/* 11* @constructor radioGroupActiveDescendent 12* 13* @desc 14* Wrapper for ARIA radiogroup control using ARIA active-descendant. Any descendant 15* element with role=radio will be included in this radiogroup as a radiobutton2. 16* 17* @param domNode 18* The DOM element node that serves as the radiogroup container. 19*/ 20 21// Merk: Denne er endret fra default for å støtte korrekte roller (tablist / tab) 22var RadioGroup = function (domNode) { 23 24 this.domNode = domNode; 25 26 this.radioButtons = []; 27 28 this.firstRadioButton = null; 29 this.lastRadioButton = null; 30 31 this.keyCode = Object.freeze({ 32 'TAB': 9, 33 'SPACE': 32, 34 'LEFT': 37, 35 'UP': 38, 36 'RIGHT': 39, 37 'DOWN': 40 38 }); 39}; 40 41RadioGroup.prototype.init = function () { 42 43 this.domNode.addEventListener('keydown', this.handleKeydown.bind(this)); 44 this.domNode.addEventListener('focus', this.handleFocus.bind(this)); 45 this.domNode.addEventListener('blur', this.handleBlur.bind(this)); 46 // initialize 47 if (!this.domNode.getAttribute('role')) { 48 this.domNode.setAttribute('role', 'radiogroup'); 49 } 50 51 var rbs = this.domNode.querySelectorAll('[role=radio], [role=tab]'); 52 53 for (var i = 0; i < rbs.length; i++) { 54 var rb = new RadioButtonActiveDescendant(rbs[i], this); 55 rb.init(); 56 this.radioButtons.push(rb); 57 if (!this.firstRadioButton) { 58 this.firstRadioButton = rb; 59 } 60 this.lastRadioButton = rb; 61 } 62 this.domNode.tabIndex = 0; 63}; 64 65RadioGroup.prototype.setChecked = function (currentItem) { 66 for (var i = 0; i < this.radioButtons.length; i++) { 67 var rb = this.radioButtons[i]; 68 rb.domNode.setAttribute('aria-checked', 'false'); 69 rb.domNode.classList.remove('focus'); 70 } 71 currentItem.domNode.setAttribute('aria-checked', 'true'); 72 currentItem.domNode.classList.add('focus'); 73 currentItem.domNode.click(); 74 this.domNode.setAttribute('aria-activedescendant', currentItem.domNode.id); 75 this.domNode.focus(); 76}; 77 78RadioGroup.prototype.setCheckedToPreviousItem = function (currentItem) { 79 var index; 80 81 if (currentItem === this.firstRadioButton) { 82 this.setChecked(this.lastRadioButton); 83 } 84 else { 85 index = this.radioButtons.indexOf(currentItem); 86 this.setChecked(this.radioButtons[index - 1]); 87 } 88}; 89 90RadioGroup.prototype.setCheckedToNextItem = function (currentItem) { 91 var index; 92 93 if (currentItem === this.lastRadioButton) { 94 this.setChecked(this.firstRadioButton); 95 } 96 else { 97 index = this.radioButtons.indexOf(currentItem); 98 this.setChecked(this.radioButtons[index + 1]); 99 } 100}; 101 102RadioGroup.prototype.getCurrentRadioButton = function () { 103 var id = this.domNode.getAttribute('aria-activedescendant'); 104 if (!id) { 105 this.domNode.setAttribute('aria-activedescendant', this.firstRadioButton.domNode.id); 106 return this.firstRadioButton; 107 } 108 for (var i = 0; i < this.radioButtons.length; i++) { 109 var rb = this.radioButtons[i]; 110 if (rb.domNode.id === id) { 111 return rb; 112 } 113 } 114 this.domNode.setAttribute('aria-activedescendant', this.firstRadioButton.domNode.id); 115 return this.firstRadioButton; 116}; 117 118// Event Handlers 119 120RadioGroup.prototype.handleKeydown = function (event) { 121 var flag = false; 122 123 var currentItem = this.getCurrentRadioButton(); 124 switch (event.keyCode) { 125 case this.keyCode.SPACE: 126 this.setChecked(currentItem); 127 flag = true; 128 break; 129 130 case this.keyCode.UP: 131 this.setCheckedToPreviousItem(currentItem); 132 flag = true; 133 break; 134 135 case this.keyCode.DOWN: 136 this.setCheckedToNextItem(currentItem); 137 flag = true; 138 break; 139 140 case this.keyCode.LEFT: 141 this.setCheckedToPreviousItem(currentItem); 142 flag = true; 143 break; 144 145 case this.keyCode.RIGHT: 146 this.setCheckedToNextItem(currentItem); 147 flag = true; 148 break; 149 150 default: 151 break; 152 } 153 154 if (flag) { 155 event.stopPropagation(); 156 event.preventDefault(); 157 } 158}; 159 160RadioGroup.prototype.handleFocus = function () { 161 var currentItem = this.getCurrentRadioButton(); 162 currentItem.domNode.classList.add('focus'); 163}; 164 165RadioGroup.prototype.handleBlur = function () { 166 var currentItem = this.getCurrentRadioButton(); 167 currentItem.domNode.classList.remove('focus'); 168};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.