1PeerJ.Tools.accessibility = (function () { 2 /** 3 * Minified by jsDelivr using Terser v5.19.2. 4 * Original file: /npm/[email protected]/src/color-contrast-checker.js 5 * 6 * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files 7 */ 8 function ColorContrastChecker() { 9 } 10 11 ColorContrastChecker.prototype = { 12 fontSize: 14, rgbClass: { 13 toString: function () { 14 return "<r: " + this.r + " g: " + this.g + " b: " + this.b + " >" 15 } 16 }, isValidSixDigitColorCode: function (t) { 17 return /^(#)?([0-9a-fA-F]{6})?$/.test(t) 18 }, isValidThreeDigitColorCode: function (t) { 19 return /^(#)?([0-9a-fA-F]{3})?$/.test(t) 20 }, isValidColorCode: function (t) { 21 return this.isValidSixDigitColorCode(t) || this.isValidThreeDigitColorCode(t) 22 }, isValidRatio: function (t) { 23 return "number" == typeof t 24 }, convertColorToSixDigit: function (t) { 25 return "#" + t[1] + t[1] + t[2] + t[2] + t[3] + t[3] 26 }, hexToLuminance: function (t) { 27 if (!this.isValidColorCode(t)) throw new Error("Invalid Color :" + t); 28 this.isValidThreeDigitColorCode(t) && (t = this.convertColorToSixDigit(t)), t = this.getRGBFromHex(t); 29 var i = this.calculateLRGB(t); 30 return this.calculateLuminance(i) 31 }, check: function (t, i, r, o) { 32 if (void 0 !== r && (this.fontSize = r), !t || !i) return !1; 33 var e = this.hexToLuminance(t), n = this.hexToLuminance(i), s = this.getContrastRatio(e, n); 34 return void 0 !== o ? !!this.isValidRatio(o) && this.verifyCustomContrastRatio(s, o) : this.verifyContrastRatio(s) 35 }, checkPairs: function (t, i) { 36 var r = []; 37 for (var o in t) { 38 var e = t[o]; 39 void 0 !== e.fontSize ? r.push(this.check(e.colorA, e.colorB, e.fontSize, i)) : r.push(this.check(e.colorA, e.colorB, void 0, i)) 40 } 41 return r 42 }, calculateLuminance: function (t) { 43 return .2126 * t.r + .7152 * t.g + .0722 * t.b 44 }, isLevelAA: function (t, i, r) { 45 return this.check(t, i, r).WCAG_AA 46 }, isLevelAAA: function (t, i, r) { 47 return this.check(t, i, r).WCAG_AAA 48 }, isLevelCustom: function (t, i, r) { 49 return this.check(t, i, void 0, r).customRatio 50 }, getRGBFromHex: function (t) { 51 var i, r, o, e = Object.create(this.rgbClass); 52 if ("string" != typeof t) throw new Error("must use string"); 53 return i = parseInt(t.slice(1, 3), 16), r = parseInt(t.slice(3, 5), 16), o = parseInt(t.slice(5, 7), 16), e.r = i, e.g = r, e.b = o, e 54 }, calculateSRGB: function (t) { 55 var i, r = Object.create(this.rgbClass); 56 for (i in t) t.hasOwnProperty(i) && (r[i] = parseFloat(t[i] / 255, 10)); 57 return r 58 }, calculateLRGB: function (t) { 59 var i, r = this.calculateSRGB(t), o = Object.create(this.rgbClass), e = 0; 60 for (i in r) r.hasOwnProperty(i) && (e = parseFloat(r[i], 10), o[i] = e <= .03928 ? e / 12.92 : Math.pow((e + .055) / 1.055, 2.4)); 61 return o 62 }, getContrastRatio: function (t, i) { 63 var r, o; 64 return t >= i ? (r = t, o = i) : (r = i, o = t), (r + .05) / (o + .05) 65 }, verifyContrastRatio: function (t) { 66 var i = Object.create({ 67 toString: function () { 68 return "< WCAG-AA: " + (this.WCAG_AA ? "pass" : "fail") + " WCAG-AAA: " + (this.WCAG_AAA ? "pass" : "fail") + " >" 69 } 70 }); 71 return (this.fontSize || 14) >= 18 ? (i.WCAG_AA = t >= 3, i.WCAG_AAA = t >= 4.5) : (i.WCAG_AA = t >= 4.5, i.WCAG_AAA = t >= 7), i 72 }, verifyCustomContrastRatio: function (t, i) { 73 var r = Object.create({ 74 toString: function () { 75 return "< Custom Ratio: " + (this.customRatio ? "pass" : "fail") + " >" 76 } 77 }); 78 return r.customRatio = t >= i, r 79 } 80 }; 81 82 function useAccessibilityComposable(classExemptions = []) { 83 var ccc = new ColorContrastChecker(); 84 85 function addAriaLabelsToMdiButtons( 86 buttons = document.querySelectorAll('button, .v-btn')) { 87 buttons.forEach(function (button) { 88 if (button.hasAttribute('aria-label')) return; 89 90 var mdiClass = Array 91 .from(button.classList) 92 .find(function (className) { 93 return className.includes('mdi-'); 94 }); 95 96 if (!mdiClass) { 97 var iconElement = button.querySelector('[class*="mdi-"]'); 98 99 if (iconElement) { 100 mdiClass = Array.from(iconElement.classList).find(function (className) { 101 return className.includes('mdi-'); 102 }); 103 } 104 } 105 106 if (mdiClass) { 107 var iconName = mdiClass.split('mdi-')[1]; 108 var readableLabel = iconName.replace(/-/g, ' '); 109 button.setAttribute('aria-label', checkForConventionalIcons(readableLabel)); 110 } 111 }); 112 } 113 114 function addAriaLabelsToLegacyButtons( 115 buttons = document.querySelectorAll('button.btn')) { 116 buttons.forEach(function (button) { 117 if (button.hasAttribute('aria-label')) return; 118 119 if (button.hasAttribute('id')) { 120 button.setAttribute( 121 'aria-label', 122 button.getAttribute('id') 123 .replace(/-/g, ' ') 124 .replace('landing ', '')); 125 } 126 }) 127 } 128 129 function parentHasClass(img, clazz) { 130 return img.tagName.toLowerCase() === 'img' && 131 img.parentElement && 132 img.parentElement.classList && 133 img.parentElement.classList.contains(clazz) 134 } 135 136 function subjectUsers(img) { 137 if (parentHasClass(img, 'subject-user-image')) { 138 if (img.parentElement && 139 img.parentElement.nextElementSibling && 140 img.parentElement.nextElementSibling.classList && 141 img.parentElement.nextElementSibling.classList.contains('subject-user-info')) 142 var userName = img.parentElement.nextElementSibling.querySelector('.subject-user-name') 143 return userName ? [0, userName.innerText] : null 144 } 145 return null 146 } 147 148 function addAltTextToImages() { 149 var images = document.querySelectorAll('img'); 150 // var regex = /\/([a-z]+-[a-z]+)-\d+\.[^\.]+$/; 151 var regex = /\/([A-Za-z]+(?:[-_][A-Za-z]+)*)\.[^.]+$/ 152
153 images.forEach(function (img) { 154 var r = null 155 156 switch (true) { 157 case !!img.classList && img.classList.contains('benefits-inline-image'): 158 img.setAttribute('aria-hidden', true) 159 break 160 161 case !img.hasAttribute('alt') && !!subjectUsers(img): 162 r = subjectUsers(img) || regex.exec(img.src) 163 break 164 165 case !img.hasAttribute('alt'): 166 r = regex.exec(img.src) 167 break 168 } 169 170 if (r) { 171 const quoteMessage = parentHasClass(img, 'boxout-quote') ? ' Quote from: ' : ': ' 172 173 img.setAttribute( 174 'alt', 175 'Image containing' + 176 quoteMessage + 177 r[1].replace(/^e_/, '') 178 .replace(/[-_]/g, ' ') 179 ) 180 } 181 }) 182 } 183 184 function addAriaLabelsToInputs() { 185 const inputs = document.querySelectorAll('input') 186 187 inputs.forEach(function (input) { 188 if (input.hasAttribute('placeholder')) { 189 input.setAttribute( 190 'aria-label', 191 input.getAttribute('placeholder') 192 ) 193 } else if (input.hasAttribute('id')) { 194 input.setAttribute( 195 'aria-label', 196 input.getAttribute('id').replace(/-/g, '') 197 ) 198 } 199 }) 200 } 201 202 function checkForConventionalIcons(label) { 203 switch (label) { 204 case 'weather night': 205 return 'dark/light mode toggle'; 206 case 'cog': 207 return 'settings'; 208 case 'pencil': 209 return 'edit'; 210 case 'plus': 211 return 'add'; 212 case 'trash can': 213 case 'trash can outline': 214 return 'remove'; 215 case 'mdi eye': 216 case 'mdi eye outline': 217 return 'show'; 218 case 'mdi eye off': 219 case 'mdi eye off-outline': 220 case 'mdi eye closed': 221 return 'hide'; 222 } 223 return label; 224 } 225 226 function removeStyleAttributeAlpha(element, attrName) { 227 var style = window.getComputedStyle(element); 228 if (style[attrName].includes('rgba')) { 229 var colors = style[attrName].match(/[+-]?(\d*\.)?\d+/g); 230 colors.pop(); 231 element.style[attrName] = 'rgb(' + colors.toString() + ')'; 232 } 233 } 234 235 function isolateRGBChannels(style) { 236 var matches = style ? style.match(/[+-]?(\d*\.)?\d+/g) : null; 237 return matches ? matches.map(function (it) { 238 return parseInt(it); 239 }) : [255, 255, 255]; 240 } 241 242 function rgbToHex(rgb) { 243 return '#' + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1); 244 } 245 246 function adjustFontChannels(params) { 247 var rCol = params.rCol; 248 var bgCol = params.bgCol; 249 250 for (var j = 0; j < 3; j++) { 251 if (rCol[j] <= bgCol[j]) rCol[j] -= !rCol[j] ? 0 : 1; 252 else rCol[j] += rCol[j] === 255 ? 0 : 1; 253 } 254 255 return {rCol: rCol, bgCol: bgCol}; 256 } 257 258 function maxFontChannel(params, root) { 259 var rCol = params.rCol; 260 var bgCol = params.bgCol; 261 262 for (var j = 0; j < 3; j++) { 263 if (rCol[j] <= 128) rCol[j] = 0; 264 else rCol[j] = 255; 265 } 266 267 root.style.setProperty('color', rgbToHex(rCol), 'important'); 268 return {rCol: rCol, bgCol: bgCol}; 269 } 270 271 function adjustBgChannels(params, bgEl) { 272 var rCol = params.rCol; 273 var bgCol = params.bgCol; 274 var success = false;
275 276 for (var i = 0; i < 256; i++) { 277 for (var j = 0; j < 3; j++) { 278 if (rCol[j] <= 128) { 279 bgCol[j] += bgCol[j] === 255 ? 0 : 1; 280 } else { 281 bgCol[j] -= !bgCol[j] ? 0 : 1; 282 } 283 } 284 285 if (ccc.isLevelCustom(rgbToHex(rCol), rgbToHex(bgCol), 7.1)) { 286 bgEl.style.setProperty('background-color', rgbToHex(bgCol), 'important'); 287 success = true; 288 break; 289 } 290 } 291 292 if (!success) { 293 for (var j = 0; j < 3; j++) { 294 if (rCol[j] < 128) bgCol[j] = 255; 295 else bgCol[j] = 0; 296 } 297 bgEl.style.setProperty('background-color', rgbToHex(bgCol), 'important'); 298 } 299 } 300 301 function isInsideButton(node) { 302 var current = node; 303 while (current) { 304 if (current.tagName === 'BUTTON' || 305 (current.getAttribute && current.getAttribute('role') === 'button')) { 306 return true; 307 } 308 current = current.parentElement; 309 } 310 return false; 311 } 312 313 function testAndRepairContrast(root, bgEl) { 314 var rStyle = window.getComputedStyle(root); 315 var bgStyle = window.getComputedStyle(bgEl); 316 317 var rCol = isolateRGBChannels(rStyle.color); 318 var bgCol = isolateRGBChannels(bgStyle.backgroundColor); 319 var success = false; 320 321 if (!ccc.isLevelAAA(rgbToHex(rCol), rgbToHex(bgCol), rStyle.fontSize)) { 322 if (rCol.length >= 3 && bgCol.length >= 3) { 323 for (var i = 0; i < 256; i++) { 324 var out = adjustFontChannels({rCol: rCol, bgCol: bgCol}); 325 326 if (ccc.isLevelCustom(rgbToHex(out.rCol), rgbToHex(bgCol), 7.1)) { 327 root.style.setProperty('color', rgbToHex(out.rCol), 'important'); 328 if (!isInsideButton(root)) { 329 bgEl.style.setProperty('background-color', rgbToHex(out.bgCol), 'important'); 330 } 331 success = true; 332 break; 333 } 334 } 335 if (!success) { 336 adjustBgChannels( 337 maxFontChannel({rCol: rCol, bgCol: bgCol}, bgEl), 338 bgEl); 339 } 340 } else { 341 console.error('Root and/or BG Element have invalid channels, (root, element:)', root, bgEl); 342 } 343 } 344 } 345 346 function manageContrast(rootElement) { 347 var walker = document.createTreeWalker( 348 rootElement, 349 NodeFilter.SHOW_TEXT, 350 null, 351 false 352 ); 353 354 var firstPass = true; 355 var textnode; 356 357 while (textnode = walker.nextNode()) { 358 if (textnode.parentElement) { 359 var currentElement = textnode.parentElement; 360 var bgElement = null; 361 362 while (currentElement && currentElement !== rootElement.parentElement) { 363 var style = window.getComputedStyle(currentElement); 364 if (style.backgroundColor !== 'rgba(0, 0, 0, 0)') { 365 bgElement = currentElement; 366 break; 367 } 368 currentElement = currentElement.parentElement; 369 } 370 371 if (!bgElement) { 372 bgElement = rootElement; 373 if (firstPass) { 374 bgElement.style.backgroundColor = 'rgb(255,255,255)'; 375 } 376 } 377 if (!classExemptions.some(className => bgElement.classList.contains(className))) { 378 removeStyleAttributeAlpha(bgElement, 'background-color'); 379 removeStyleAttributeAlpha(textnode.parentElement, 'color'); 380 testAndRepairContrast(textnode.parentElement, bgElement); 381 } 382 383 firstPass = false;
384 } 385 } 386 } 387 388 function assignDOTToAriaLabel() { 389 var aTags = $('a[data-original-title]:not([aria-label])') 390 391 aTags.each(function () { 392 var originalTitle = $(this).attr('data-original-title'); 393 $(this).attr('aria-label', originalTitle); 394 if (originalTitle === 'Cite this object using this DOI') { 395 $(this).attr('aria-label', originalTitle + ': ' + $(this).text()) 396 } else $(this).attr('aria-label', originalTitle); 397 }); 398 } 399 400 function assignAriaLabelToAuthors() { 401 var aTags = $('div.article-authors > .contrib a') 402 aTags.each(function () { 403 if ($(this).attr('rel') === 'author') { 404 $(this).attr('aria-label', 'Link to profile of: ' + $(this).text()) 405 } else if ($(this).attr('data-original-title')) { 406 $(this).attr('aria-label', 'send email to: ' + $(this).attr('href').replace(/^mailto:/, '')) 407 } else if ($(this).attr('itemprop') === 'affiliation') { 408 $(this).attr('aria-label', 'link to author\'s affiliation details, no. ' + $(this).text()) 409 } 410 }); 411 412 var spanTag = $('div.article-authors > .contrib span') 413 spanTag.each(function () { 414 $(this) 415 .attr('role', 'tooltip') 416 .attr('aria-description', $(this).attr('data-original-title')) 417 }) 418 } 419 420 function createSkipToMainContentLink() { 421 var newElement = document.createElement('a'); 422 newElement.textContent = 'Skip to main content'; 423 newElement.setAttribute('aria-label', 'Skip to main content') 424 newElement.className = 'SkipToMainContent'; // Use className for ES5 compatibility 425 newElement.href = '#MainContent' 426 return newElement 427 } 428 429 function skipToJournalLandingPage(el, toolbar) { 430 var targetElement = el 431 window.history.replaceState(null, null, '#MainContentJournal'); 432 targetElement.setAttribute('tabindex', '0'); // Make the element focusable 433 targetElement.focus(); // Programmatically move focus 434 435 setTimeout(function () { 436 window.scrollTo({top: targetElement.offsetTop - toolbar.offsetHeight,}); 437 }, 150) 438 return targetElement 439 } 440 441 function skipToOAMetaPage(el) { 442 var targetElement = el 443 targetElement.setAttribute('tabindex', '0'); // Make the element focusable 444 targetElement.focus(); // Programmatically move focus 445 window.history.replaceState(null, null, '#MainContentVue'); 446 447 setTimeout(function () { 448 window.scrollTo({top: 0}); 449 }, 250) 450 return targetElement 451 } 452 453 function skipToHubHomePage(el, toolbar) { 454 var targetElement = el 455 targetElement.setAttribute('tabindex', '0'); // Make the element focusable 456 targetElement.focus(); // Programmatically move focus 457 window.history.replaceState(null, null, '#MainContentHubsHome'); 458 459 setTimeout(function () { 460 window.scrollTo({top: toolbar.offsetHeight - 50,}); 461 }, 150) 462 return targetElement 463 } 464 465 function skipToHomePage(el) { 466 var targetElement = el 467 targetElement.setAttribute('tabindex', '0'); // Make the element focusable 468 targetElement.focus(); // Programmatically move focus 469 window.history.replaceState(null, null, '#MainContentVue'); 470 471 setTimeout(function () { 472 window.scrollTo({ 473 top: document.querySelector('.HomeHeader').offsetHeight 474 }); 475 }, 150) 476 return targetElement 477 } 478 479 function skipToVuePageContent(el, toolbar) { 480 targetElement = el 481 targetElement.setAttribute('tabindex', '0'); // Make the element focusable 482 targetElement.focus(); // Programmatically move focus 483 window.history.replaceState(null, null, '#MainContentVue'); 484 485 setTimeout(function () { 486 window.scrollTo({top: toolbar.offsetHeight,}); 487 }, 150) 488 return targetElement 489 } 490 491 function skipToLegacyPageContent(el, toolbar) { 492 var targetElement = el 493 window.history.replaceState(null, null, '#MainContent'); 494 targetElement.setAttribute('tabindex', '0'); // Make the element focusable 495 targetElement.setAttribute('role', 'main') 496 targetElement.focus(); // Programmatically move focus 497 setTimeout(function () { 498 window.scrollTo({top: targetElement.offsetTop - toolbar.offsetHeight,}); 499 }, 150) 500 return targetElement 501 } 502 503 function handleSkipToMainContentScroll(event = null, hash = '#MainContent') { 504 if (event) event.preventDefault(); // Prevent default behavior 505 var targetElement = document.querySelector(hash); 506 var toolbar = document.querySelector('.v-toolbar__content'); 507 508 if (targetElement) { 509 switch (true) { 510 // journal landing pages 511 case !!document.querySelector('.journal-landing-title-header'): 512 console.log(1) 513 targetElement = skipToJournalLandingPage( 514 document.querySelector('.journal-landing-title-header'), 515 toolbar) 516 break 517 518 // Hubs Home 519 case !!document.querySelector('#MainContentHubsHome'): 520 targetElement = skipToHubHomePage( 521 document.querySelector('#MainContentHubsHome'), 522 toolbar) 523 break 524 525 // Open advances dynamic meta pages 526 case !!document.querySelector('.mlp-dynamic-page'): 527 targetElement = skipToOAMetaPage(document.querySelector('#MainContentVue')) 528 break 529 530 // home page 531 case !!document.querySelector('#MainContentHome'): 532 targetElement = skipToHomePage(document.querySelector('#MainContentHome')) 533 break 534 535 // Vue page catch all 536 case !!document.querySelector('#MainContentVue > div > div'): 537 targetElement = skipToVuePageContent( 538 document.querySelector('#MainContentVue'), 539 toolbar) 540 break 541 542 // legacy page catch all 543 default: 544 targetElement = skipToLegacyPageContent(targetElement, toolbar) 545 break 546 } 547 548 // Remove tabindex after focus is moved to restore natural tab order 549 targetElement.addEventListener('blur', function () { 550 targetElement.removeAttribute('tabindex'); 551 }, {once: true}); 552 } 553 } 554 555 function skipToMainContentLink() { 556 var newElement = createSkipToMainContentLink() 557 558 // Add event listeners for all possible interactions 559 newElement.addEventListener('click', handleSkipToMainContentScroll); // Handle mouse click 560 newElement.addEventListener('mousedown', handleSkipToMainContentScroll); // Handle mouse down 561 newElement.addEventListener('keydown', function (event) { 562 if (event.key === 'Enter' || event.key === ' ') { // Handle Enter and Space keys 563 handleSkipToMainContentScroll(event); 564 } 565 }); 566 567 // Insert the element at the start of the <body> 568 document.body.insertBefore(newElement, document.body.firstChild); 569 } 570 571 function setMainRole() { 572 var targetElement 573 574 switch (true) { 575 // journal landing pages 576 case !!document.querySelector('#MainContentJournal'): 577 targetElement = document.querySelector('#MainContentJournal') 578 break 579 580 // Hubs Home 581 case !!document.querySelector('#MainContentHubsHome'): 582 targetElement = document.querySelector('#MainContentHubsHome') 583 break 584 585 // Open advances dynamic meta pages 586 case !!document.querySelector('.mlp-dynamic-page'): 587 targetElement = document.querySelector('#MainContentVue') 588 break 589 590 // home page 591 case !!document.querySelector('#MainContentHome'): 592 targetElement = document.querySelector('#MainContentHome') 593 break 594 595 // Vue page catch all 596 case !!document.querySelector('#MainContentVue > div > div'): 597 targetElement = document.querySelector('#MainContentVue') 598 break 599 600 // legacy page catch all 601 default: 602 targetElement = document.querySelector('#MainContent'); 603 break 604 } 605 606 if (targetElement) targetElement.setAttribute('role', 'main') 607 } 608 609 return { 610 assignAriaLabelToAuthors: assignAriaLabelToAuthors, 611 manageContrast: manageContrast, 612 addAriaLabelsToMdiButtons: addAriaLabelsToMdiButtons, 613 addAriaLabelsToLegacyButtons: addAriaLabelsToLegacyButtons, 614 addAltTextToImages: addAltTextToImages, 615 addAriaLabelsToInputs: addAriaLabelsToInputs, 616 assignDOTToAriaLabel: assignDOTToAriaLabel, 617 skipToMainContentLink: skipToMainContentLink, 618 handleSkipToMainContentScroll: handleSkipToMainContentScroll, 619 setMainRole: setMainRole, 620 }; 621 } 622 623 return useAccessibilityComposable([ 624 'self-citation', 625 'self-citation-elocation', 626 'alert-info', 627 'xref', 628 'xref-bibr', 629 'subject-btn-unfollow', 630 'activity-summary', 631 'offline-share', 632 'bluesky-share', 633 'fb-share', 634 'payment-notice-content', 635 'article-recommendation', 636 'peerj-paper-form', 637 'previous-reviews', 638 'previous-review-head', 639 'previous-review', 640 'article-revision-current', 641 'article-status-header', 642 'tag-coi-pass-ae', 643 'institutions-container', 644 'InstitutionSignupButton', 645 'card-type-reviewing', 646 'article-person-institution', 647 'tag-coi-pass-ae', 648 ]); 649})(); 650 651$(document).ready(function () { 652 var articlePage = document.querySelector('.article-status-header') 653 var mainPadding = document.querySelector('.main-padding') 654 var publicationJsonData = document.querySelector('.publication-jsondata') 655 switch (true) { 656 case !!articlePage: 657 PeerJ.Tools.accessibility.manageContrast(articlePage) 658 PeerJ.Tools.accessibility.manageContrast(document.querySelector('#wrap > .container')) 659 break 660 661 case !!publicationJsonData: 662 var left = document.querySelector('.article-sidebar-left') 663 if (left) PeerJ.Tools.accessibility.manageContrast(left) 664 break 665 666 case !!mainPadding: 667 PeerJ.Tools.accessibility.manageContrast(mainPadding) 668 break; 669 670 default: 671 PeerJ.Tools.accessibility.manageContrast(document.querySelector('.container')) 672 } 673 674 PeerJ.Tools.accessibility.skipToMainContentLink() 675 PeerJ.Tools.accessibility.assignAriaLabelToAuthors(articlePage) 676 PeerJ.Tools.accessibility.addAltTextToImages() 677 PeerJ.Tools.accessibility.addAriaLabelsToInputs() 678 PeerJ.Tools.accessibility.addAriaLabelsToLegacyButtons() 679 PeerJ.Tools.accessibility.assignDOTToAriaLabel() 680 PeerJ.Tools.accessibility.setMainRole() 681 682 if (window.location.hash && window.location.pathname !== '/benefits/') { 683 setTimeout(function () { 684 PeerJ.Tools.accessibility.handleSkipToMainContentScroll(null, window.location.hash) 685 }, 2500) 686 } 687})
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.