1(function ($) { 2 'use strict'; 3 4 // TABS CLASS DEFINITION 5 // ====================== 6 // Usage: 7 // add attr data-tabs-keyboard-support="true" on html element with role=tablist 8 // OR 9 // $('[role=tablist]').tabsKeyboardSupport(); 10 11 const Tabs = function (element, options) { 12 this.$element = $(element); 13 this.options = $.extend({}, options); 14 this.tabs = []; 15 this.firstTab = null; 16 this.lastTab = null; 17 this.activeTab = null; 18 this.init(element); 19 } 20 21 Tabs.prototype.init = function (element) { 22 this.tabs = [...element.querySelectorAll('[role=tab]')]; 23 24 for (let i = 0; i < this.tabs.length; i++) { 25 const tab = this.tabs[i]; 26 tab.addEventListener('keydown', this.onKeydown.bind(this)); 27 tab.addEventListener('click', this.onClick.bind(this)); 28 29 if (tab.classList.contains('active')) { 30 this.activeTab = tab; 31 } 32 33 if (!this.firstTab) { 34 this.firstTab = tab; 35 } 36 this.lastTab = tab; 37 } 38 if (this.activeTab) { 39 this.setSelectedTab(this.activeTab); 40 } 41 } 42 43 Tabs.prototype.setSelectedTab = function (currentTab) { 44 for (let i = 0; i < this.tabs.length; i++) { 45 const tab = this.tabs[i]; 46 if (currentTab === tab) { 47 tab.classList.add('active'); 48 tab.setAttribute('aria-selected', 'true'); 49 tab.setAttribute('tabindex', '0'); 50 this.activeTab = tab; 51 } else { 52 tab.classList.remove('active'); 53 tab.setAttribute('aria-selected', 'false'); 54 tab.setAttribute('tabindex', '-1'); 55 } 56 } 57 } 58 59 60 Tabs.prototype.moveFocusToTab = function (currentTab) { 61 currentTab.focus(); 62 } 63 64 Tabs.prototype.moveFocusToPreviousTab = function (currentTab) { 65 let index; 66 67 if (currentTab === this.firstTab) { 68 this.moveFocusToTab(this.lastTab); 69 } else { 70 index = this.tabs.indexOf(currentTab); 71 this.moveFocusToTab(this.tabs[index - 1]); 72 } 73 } 74 75 Tabs.prototype.moveFocusToNextTab = function (currentTab) { 76 let index; 77 78 if (currentTab === this.lastTab) { 79 this.moveFocusToTab(this.firstTab); 80 } else { 81 index = this.tabs.indexOf(currentTab); 82 this.moveFocusToTab(this.tabs[index + 1]); 83 } 84 } 85 86 /* EVENT HANDLERS */ 87 88 Tabs.prototype.onKeydown = function (event) { 89 const target = event.currentTarget; 90 let flag = false; 91 92 switch (event.key) { 93 case 'ArrowLeft': 94 this.moveFocusToPreviousTab(target); 95 flag = true; 96 break; 97 98 case 'ArrowRight': 99 this.moveFocusToNextTab(target); 100 flag = true; 101 break; 102 103 case 'Home': 104 this.moveFocusToTab(this.firstTab); 105 flag = true; 106 break; 107 108 case 'End': 109 this.moveFocusToTab(this.lastTab); 110 flag = true; 111 break; 112 113 case ' ': 114 if (target.tagName.toLowerCase() === 'a') { 115 event.preventDefault(); 116 event.currentTarget.click(); 117 } 118 break; 119 120 default: 121 break; 122 } 123 124 if (flag) { 125 event.stopPropagation(); 126 event.preventDefault(); 127 } 128 } 129 130 Tabs.prototype.onClick = function (event) { 131 this.setSelectedTab(event.currentTarget); 132 } 133 134 // TABS PLUGIN DEFINITION 135 // ======================= 136 137 function Plugin(option) { 138 var actionParams = Array.prototype.slice.call(arguments, 1); 139 return this.each(function () { 140 var $this = $(this); 141 var data = $this.data('bs.tabsKeyboardSupport'); 142 var options = typeof option == 'object' && option; 143 if (!data) $this.data('bs.tabsKeyboardSupport', (data = new Tabs(this, options))); 144 145 var action = typeof option == 'string' && data[option]; 146 if (action) action.apply(data, actionParams); 147 }) 148 } 149 150 $.fn.tabsKeyboardSupport = Plugin; 151 $.fn.tabsKeyboardSupport.Constructor = Tabs; 152 153 $(function () { 154 const tabLists = [...document.querySelectorAll('[role=tablist][data-tabs-keyboard-support=true]')] 155 .filter((elm) => elm.querySelector('[role=tab]')); 156 157 $(tabLists).each(function () { 158 const $tabList = $(this); 159 Plugin.call($tabList); 160 }); 161 });
162 163}(jQuery)); 164 165$(function () { 166 167 $('.modal').on('show.bs.modal', function (e) { 168 $(this).attr('aria-hidden', 'false'); 169 }) 170 $('.modal').on('hide.bs.modal', function (e) { 171 $(this).attr('aria-hidden', 'true'); 172 }) 173 174 $(document).on('show.bs.modal', '.modal', function (e) { 175 var $target = $(this); 176 var $relatedElement = $(document.activeElement); 177 var modalData = $target.data('bs.modal'); 178 179 if (!modalData.isShown) { 180 $target.one('hidden.bs.modal', function () { 181 if ($relatedElement[0] != document.activeElement && $relatedElement.is(':visible')) { 182 $relatedElement.trigger('focus'); 183 } 184 }); 185 } 186 }); 187 188 // Bootstrap 3.x erroneously adds the aria-expanded attribute to collapsible content. 189 // In the code below we fix it by removing the attribute manually after each collapsing/expanging. 190 // The issue is fixed in Bootstrap 4, so our fix can be removed after migration to Bootstrap 4. 191 $(document).on("shown.bs.collapse hidden.bs.collapse", function (event) { 192 $(event.target).removeAttr("aria-expanded"); 193 }); 194}); 195 196(function ($) { 197 'use strict'; 198 199 // tooltip a11y patch 200 // ====================== 201 // fixes: 202 // the pointer can be moved over tooltip; 203 // tooltip can be dismissed by ESC 204 // 205 // new functionality: 206 // possibility to trigger tooltip from other element via param "relatedTargetId". 207 // for example trigger icon of tooltip is part of link but tooltip should be shown near icon 208 // Usage: 209 // data-related-target-id="other_element_id" 210 // <a href="#" id="link-id">Link text <span data-toggle="tooltip" data-related-target-id="link-id" title="Tooltip text">(i)</span></a> 211 212 $.fn.tooltip.Constructor.prototype.init = function (type, element, options) { 213 this.enabled = true 214 this.type = type 215 this.$element = $(element) 216 this.options = this.getOptions(options) 217 this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) 218 this.inState = {click: false, hover: false, focus: false} 219 220 if (this.$element[0] instanceof document.constructor && !this.options.selector) { 221 throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') 222 } 223 224 var triggers = this.options.trigger.split(' ') 225 226 for (var i = triggers.length; i--;) { 227 var trigger = triggers[i] 228 // relatedTargetId and selector cannot be used at the same time 229 var isSelector = !!this.options.selector; 230 var relatedTarget = this.options.relatedTargetId && document.getElementById(this.options.relatedTargetId); 231 232 if (!isSelector) { 233 this.relatedTarget = relatedTarget; 234 } 235 236 if (trigger == 'click') { 237 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 238 } else if (trigger == 'hover') { 239 this.$element.on('mouseenter.' + this.type, this.options.selector, $.proxy(this.mouseenterHandler, this)) 240 this.$element.on('mouseleave.' + this.type, this.options.selector, $.proxy(this.mouseleaveHandler, this)) 241 242 if (this.relatedTarget) { 243 $(this.relatedTarget).on('mouseover.' + this.type, this.options.selector, $.proxy(this.mouseenterHandler, this)) 244 $(this.relatedTarget).on('mouseout.' + this.type, this.options.selector, $.proxy(this.mouseleaveHandler, this)) 245 } 246 } else if (trigger == 'focus') { 247 this.$element.on('focusin.' + this.type, this.options.selector, $.proxy(this.focusinHandler, this)) 248 this.$element.on('focusout.' + this.type, this.options.selector, $.proxy(this.focusoutHandler, this)) 249 250 if (this.relatedTarget) { 251 $(this.relatedTarget).on('focusin.' + this.type, this.options.selector, $.proxy(this.focusinHandler, this)) 252 $(this.relatedTarget).on('focusout.' + this.type, this.options.selector, $.proxy(this.focusoutHandler, this)) 253 } 254 } 255 } 256 257 if (this.relatedTarget) { 258 $(this.relatedTarget).data('bs.' + this.type, this); 259 260 this.$element.on('inserted.bs.' + this.type, $.proxy(function () { 261 var tipId = this.tip().attr('id'); 262 $(this.relatedTarget).attr('aria-describedby', tipI
262d); 263 }, this)); 264 265 this.$element.on('hidden.bs.' + this.type, $.proxy(function () { 266 $(this.relatedTarget).removeAttr('aria-describedby'); 267 }, this)); 268 } 269 270 this.options.selector ? 271 (this._options = $.extend({}, this.options, {trigger: 'manual', selector: ''})) : 272 this.fixTitle() 273 } 274 275 $.fn.tooltip.Constructor.prototype.mouseenterHandler = function (e) { 276 var self = this.getInstance(e); 277 278 if (self.isInStateTrue()) { 279 clearTimeout(self.timeoutMouse); 280 return; 281 } 282 283 self.inState['hover'] = true; 284 self.enter(self); 285 self.tip().off('.' + this.type); 286 self.tip().on('mouseenter.' + this.type, $.proxy(this.mouseenterHandler, this)) 287 self.tip().on('mouseleave.' + this.type, $.proxy(this.mouseleaveHandler, this)) 288 } 289 290 $.fn.tooltip.Constructor.prototype.mouseleaveHandler = function (e) { 291 var self = this.getInstance(e); 292 293 clearTimeout(self.timeoutMouse); 294 self.timeoutMouse = setTimeout(function () { 295 self.inState['hover'] = false; 296 self.leave(self); 297 }, 100); 298 } 299 300 $.fn.tooltip.Constructor.prototype.focusinHandler = function (e) { 301 var self = this.getInstance(e); 302 self.inState['focus'] = true; 303 self.enter(self); 304 self.escape(); 305 } 306 307 $.fn.tooltip.Constructor.prototype.focusoutHandler = function (e) { 308 var self = this.getInstance(e); 309 self.inState['focus'] = false; 310 self.leave(self); 311 } 312 313 $.fn.tooltip.Constructor.prototype.escape = function () { 314 var $activeElement = $(document.activeElement); 315 $activeElement.off('keydown.dismiss.bs.' + this.type); 316 $activeElement.on('keydown.dismiss.bs.' + this.type, $.proxy(function (e) { 317 if (e.which == 27 && this.tip().hasClass('in')) { 318 this.inState['focus'] = false; 319 this.leave(this); 320 } 321 }, this)) 322 } 323 324 $.fn.tooltip.Constructor.prototype.getInstance = function (obj) { 325 var self = obj instanceof this.constructor ? 326 obj : $(obj.currentTarget).data('bs.' + this.type) 327 328 if (!self) { 329 self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) 330 $(obj.currentTarget).data('bs.' + this.type, self) 331 } 332 return self; 333 } 334 335 $.fn.tooltip.Constructor.prototype.destroy = function () { 336 var that = this; 337 clearTimeout(this.timeout); 338 clearTimeout(self.timeoutMouse); 339 this.hide(function () { 340 that.$element.off('.' + that.type).removeData('bs.' + that.type); 341 if (that.relatedTarget) { 342 $(that.relatedTarget).off('.' + that.type).removeData('bs.' + that.type); 343 that.relatedTarget = null; 344 } 345 if (that.$tip) { 346 that.$tip.detach() 347 } 348 that.$tip = null 349 that.$arrow = null 350 that.$viewport = null 351 that.$element = null 352 }) 353 } 354 355}(jQuery));
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.