1class FdAccessibilityWidget { 2 3 constructor(options) { 4 5 Object.assign(this, {options}); 6 7 // an array of CSS classes saved in cookie or load from cookie 8 this.activeActionClasses = this.loadCookieOptions(); 9 10 if ( this.isWidgetDisabled() ) { 11 return; 12 } 13 14 this.createWidget(); 15 this.loadActions(); 16 this.toggleWidgetActive(); 17 this.initActions(); 18 19 document.addEventListener('fdawActionCall', (e) => { 20 this.updateCookieOptions(); 21 this.toggleWidgetActive(); 22 }, false); 23 } 24 25 26 /** 27 * Create main widget markup and trigger button 28 */ 29 createWidget() { 30 31 // Create main wrapper 32 this.fdawEl = document.createElement('div'); 33 this.fdawEl.id = 'fdaw'; 34 this.fdawEl.className = 'fdaw-el fdaw'; 35 36 this.fdawEl.setAttribute('data-position', this.options.widgetPosition || 'right bottom'); 37 38 const fdawElWrap = document.createElement('div'); 39 fdawElWrap.id = 'fdaw-wrap'; 40 fdawElWrap.className = 'fdaw-el fdaw-wrap'; 41 42 this.fdawEl.appendChild(fdawElWrap); 43 document.body.appendChild(this.fdawEl); 44 45 this.widgetUIElement = fdawElWrap; 46 47 // Create widget open button 48 const fdawTriggerEl = document.createElement('button'); 49 50 fdawTriggerEl.id = 'fdawToggleTrigger'; 51 fdawTriggerEl.className = 'fdaw-toggle fdaw-el'; 52 fdawTriggerEl.setAttribute('data-action', 'toggleWidget'); 53 fdawTriggerEl.setAttribute('data-fdaw', '1'); 54 fdawTriggerEl.setAttribute('aria-pressed', 'false'); 55 fdawTriggerEl.setAttribute('title', this.options.i18n.hr.widgetTitle); 56 fdawTriggerEl.innerHTML = `<div class="fdaw-el fdaw-action__check" aria-hidden="true"></div><svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path class="fdaw-el fdaw-icon-fill" fill="#0000b5" d="M256 48c114.953 0 208 93.029 208 208 0 114.953-93.029 208-208 208-114.953 0-208-93.029-208-208 0-114.953 93.029-208 208-208m0-40C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 56C149.961 64 64 149.961 64 256s85.961 192 192 192 192-85.961 192-192S362.039 64 256 64zm0 44c19.882 0 36 16.118 36 36s-16.118 36-36 36-36-16.118-36-36 16.118-36 36-36zm117.741 98.023c-28.712 6.779-55.511 12.748-82.14 15.807.851 101.023 12.306 123.052 25.037 155.621 3.617 9.26-.957 19.698-10.217 23.315-9.261 3.617-19.699-.957-23.316-10.217-8.705-22.308-17.086-40.636-22.261-78.549h-9.686c-5.167 37.851-13.534 56.208-22.262 78.549-3.615 9.255-14.05 13.836-23.315 10.217-9.26-3.617-13.834-14.056-10.217-23.315 12.713-32.541 24.185-54.541 25.037-155.621-26.629-3.058-53.428-9.027-82.141-15.807-8.6-2.031-13.926-10.648-11.895-19.249s10.647-13.926 19.249-11.895c96.686 22.829 124.283 22.783 220.775 0 8.599-2.03 17.218 3.294 19.249 11.895 2.029 8.601-3.297 17.219-11.897 19.249z"></path></svg>`; 57 this.widgetUIElement.appendChild(fdawTriggerEl); 58 59 // Create widget UI markup 60 const widgetActions = this.createWidgetActionsMarkup(this.options.actions); 61 const widgetTemplate = ` 62 <div class="fdaw-el fdaw-widget"> 63 <div class="fdaw-el fdaw-header"> 64 <div class="fdaw-el fdaw-header__title">${this.options.i18n.hr.widgetTitle}</div> 65 <div class="fdaw-el fdaw-header__close"> 66 <button type="button" id="fdawCloseTrigger" data-fdaw="1" data-action="closeWidget" class="fdaw-el fdaw-close" aria-label="${this.options.i18n.hr.closeButton}"><span class="fdaw-el" aria-hidden="true">×</span></button> 67 </div><!-- /.fdaw-header__close --> 68 </div><!-- /.fdaw-header --> 69 <div class="fdaw-el fdaw-body"> 70 ${widgetActions} 71 <div class="fdaw-el fdaw-body-item fdaw-body-item--reset"> 72 <button id="fdawResetTrigger" data-fdaw="1" data-action="resetWidget" class="fdaw-el fdaw-action" role="button" aria-pressed="false" tabindex="0" aria-label="${this.options.i18n.hr.resetButton}"> 73 <div class="fdaw-el fdaw-action__inner"> 74 <div class="fdaw-el fdaw-action__icon"> 75 <svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M500 8h-27.711c-6.739 0-12.157 5.548-11.997 12.286l2.347 98.575C418.212 52.043 342.256 8 256 8 134.813 8 33.933 94.924 12.296 209.824 10.908 217.193 16.604 224 24.103 224h28.576c5.674 0 10.542-3.982 11.737-9.529C83.441 126.128 161.917 60 256 60c79.545 0 147.942 47.282 178.676 115.302l-126.39-3.009c-6.737-.16-12.286 5.257-12.286 11.997V212c0 6.627 5.373 12 12 12h192c6.627 0 12-5.373 12-12V20c0-6.627-5.373-12-12-12zm-12.103 280h-28.576c-5.674 0-10.542 3.982-11.737 9.529C428.559 385.872 350.083 452 256 452c-79.546 0-147.942-47.282-178.676-115.302l126.39 3.009c6.737.16 12.286-5.257 12.286-11.997V300c0-6.
75627-5.373-12-12-12H12c-6.627 0-12 5.373-12 12v192c0 6.627 5.373 12 12 12h27.711c6.739 0 12.157-5.548 11.997-12.286l-2.347-98.575C93.788 459.957 169.744 504 256 504c121.187 0 222.067-86.924 243.704-201.824 1.388-7.369-4.308-14.176-11.807-14.176z"></path></svg> 76 </div> 77 <div class="fdaw-el fdaw-action__text">${this.options.i18n.hr.resetButton}</div> 78 </div> 79 </button> 80 </div> 81 82 <div class="fdaw-el fdaw-body-item fdaw-body-item--disable"> 83 <button id="fdawDisableTrigger" data-fdaw="1" data-action="disableWidget" class="fdaw-el fdaw-action" role="button" aria-pressed="false" tabindex="0" aria-label="${this.options.i18n.hr.disableButton}"> 84 <div class="fdaw-el fdaw-action__inner"> 85 <div class="fdaw-el fdaw-action__text">${this.options.i18n.hr.disableButton}</div> 86 </div> 87 </button> 88 </div> 89 90 </div><!-- /.fdaw-body --> 91 </div><!-- /.fdaw-widget --> 92 `; 93 94 const fdawElIn = document.createElement('div'); 95 96 fdawElIn.id = 'fdaw-in'; 97 fdawElIn.className = 'fdaw-el fdaw-in'; 98 fdawElIn.innerHTML = widgetTemplate; 99 100 this.widgetUIElement.appendChild(fdawElIn); 101 } 102 103 104 /** 105 * Load action classes from cookie 106 */ 107 loadActions() { 108 if (this.activeActionClasses.length) { 109 110 let i; 111 for (i = 0; i < this.activeActionClasses.length; i++) { 112 113 this.addClass(document.documentElement, this.activeActionClasses[i]); 114 115 if (this.activeActionClasses[i].indexOf('--l') === -1) { 116 const targetButton = document.querySelector('.fdaw-body-item--' + this.activeActionClasses[i] + ' .fdaw-action'); 117 118 if (targetButton) { 119 targetButton.setAttribute('aria-pressed', 'true'); 120 121 const actionKey = targetButton.dataset.action; 122 123 if (this.options.actions.hasOwnProperty(actionKey)) { 124 if (this.options.actions[actionKey].enabled) { 125 126 const targetAction = this.options.actions[actionKey]; 127 const actionTriggerId = targetButton.id ? targetButton.id : null; 128 129 if (actionTriggerId && typeof this[actionTriggerId] === 'function') { 130 this[actionTriggerId](targetAction, true); 131 132 this.triggerEvent(document, 'fdawActionCall'); 133 } 134 } 135 } 136 } 137 } 138 } 139 } 140 } 141 142 143 /** 144 * If any of accessibility options is in 145 * use widget is considered active 146 */ 147 toggleWidgetActive() { 148 if (!this.activeActionClasses.length) { 149 this.removeClass(document.documentElement, 'fdaw-active'); 150 } else { 151 this.addClass(document.documentElement, 'fdaw-active'); 152 } 153 } 154 155 156 /** 157 * Attach actions to action buttons 158 */ 159 initActions() { 160 document.addEventListener('click', (event) => { 161 162 if (event.target.dataset.fdaw === undefined) { 163 return; 164 } 165 166 const ariaPressed = event.target.getAttribute('aria-pressed') === 'true' ? 'false' : 'true'; 167 event.target.setAttribute('aria-pressed', ariaPressed); 168 169 const actionKey = event.target.dataset.action; 170 171 if (!actionKey) { 172 return; 173 } 174 175 if ('toggleWidget' === actionKey) { 176 this.toggleWidgetVisibility(); 177 } 178 179 if ('closeWidget' === actionKey) { 180 this.toggleWidgetVisibility(); 181 return; 182 } 183 184 if ('resetWidget' === actionKey) { 185 this.resetWidget(); 186 return; 187 } 188 189 if ( 'disableWidget' === actionKey ) { 190 this.disableWidget(); 191 return; 192 } 193 194 if (this.options.actions.hasOwnProperty(actionKey)) { 195 if (this.options.actions[actionKey].enabled) { 196 197 const targetAction = this.options.actions[actionKey]; 198 const actionTriggerId = event.target.id ? event.target.id : null; 199 200 if (actionTriggerId && typeof this[actionTriggerId] === 'function') { 201 this[actionTriggerId](targetAction); 202 this.triggerEvent(document, 'fdawActionCall'); 203 } 204 } 205 } 206 207 }, false); 208 } 209 210 211 /** 212 * Actions 213 * @param targetAction 214 * @param loadedAction If action is loaded from cookie we don't need 215 * css classes on html since they are loaded from there 216 */ 217 fdawFontsizeTrigger(targetAction, loadedAction = false) { 218 if (!loadedAction) { 219 this.triggerAction(targetAction); 220 } 221 222 this.triggerEvent(document, 'fdawTriggeredActionFontsize'); 223 } 224 225 fdawContrastTrigger(targetAction, loadedAction = false) { 226 if (!loadedAction) { 227 this.triggerAction(targetAction); 228 } 229 230 this.triggerEvent(document, 'fdawTriggeredActionContrast'); 231 } 232 233 fdawDyslexiaTrigger(targetAction, loadedAction = false) { 234 if (!loadedAction) { 235 this.triggerAction(targetAction); 236 } 237 238 this.triggerEvent(document, 'fdawTriggeredActionDyslexia'); 239 } 240 241 fdawLinksTrigger(targetAction, loadedAction = false) { 242 if (!loadedAction) { 243 this.triggerAction(targetAction); 244 } 245 246 this.triggerEvent(document, 'fdawTriggeredActionLinks'); 247 } 248 249 fdawKerningTrigger(targetAction, loadedAction = false) { 250 if (!loadedAction) { 251 this.triggerAction(targetAction); 252 } 253 254 this.triggerEvent(document, 'fdawTriggeredActionKerning'); 255 } 256 257 fdawReadguideTrigger(targetAction, loadedAction = false) { 258 if (!loadedAction) { 259 this.triggerAction(targetAction); 260 } 261 262 this.toggleReadingGuide(); 263 264 this.triggerEvent(document, 'fdawTriggeredActionReadguide'); 265 } 266 267 268 /** 269 * Update HTML class and save in global options 270 * @param action 271 */ 272 triggerAction(action) { 273 const actionLevelLookupClass = action.css + '--l-'; 274 const currentActionLevelClass = [...document.documentElement.classList].find(cssClass => cssClass.includes(actionLevelLookupClass)); 275
276 // Add first action level 277 if (!currentActionLevelClass) { 278 const firstActionLevelClass = actionLevelLookupClass + 1; 279 this.addClasses(document.documentElement, [action.css, firstActionLevelClass]); 280 this.addToOptions([action.css, firstActionLevelClass]); 281 282 return; 283 } 284 285 // Find the current action level 286 const actionLevel = parseInt(currentActionLevelClass.replace(actionLevelLookupClass, ''), 10); 287 288 // We are at the end so remove everything 289 if (actionLevel >= action.levels.length) { 290 this.removeClasses(document.documentElement, [action.css, currentActionLevelClass]); 291 this.removeFromOptions([action.css, currentActionLevelClass]); 292 293 return; 294 } 295 296 // Add next action level class 297 const nextActionLevelClass = actionLevelLookupClass + (actionLevel + 1); 298 this.removeClass(document.documentElement, currentActionLevelClass); 299 this.removeFromOptions([currentActionLevelClass]); 300 this.addClass(document.documentElement, nextActionLevelClass, action.canBeSaved); 301 this.addToOptions([nextActionLevelClass]); 302 } 303 304 305 /** 306 * Show/hide widget 307 */ 308 toggleWidgetVisibility() { 309 this.toggleClass(document.documentElement, 'fdaw-open'); 310 } 311 312 313 /** 314 * Create HTML markup for actions 315 * @param {Array} actions Settings 316 * @return {String} HTML 317 */ 318 createWidgetActionsMarkup(actions = []) { 319 const actionsMarkup = []; 320 321 for (const actionKey in actions) { 322 if (actions[actionKey].enabled) { 323 const actionTemplate = ` 324 <div class="fdaw-el fdaw-body-item fdaw-body-item--${actions[actionKey].css}"> 325 <button id="${actions[actionKey].trigger}" data-fdaw="1" data-action="${actionKey}" class="fdaw-el fdaw-action" role="button" aria-pressed="false" tabindex="0" aria-label="${actions[actionKey].title}"> 326 <div class="fdaw-el fdaw-action__inner"> 327 <div class="fdaw-el fdaw-action__icon">${actions[actionKey].icon}</div> 328 <div class="fdaw-el fdaw-action__text">${actions[actionKey].title}</div> 329 <div class="fdaw-el fdaw-action__check" aria-hidden="true"></div> 330 ${this.createActionLevelsMarkup(actions[actionKey].levels)} 331 </div> 332 </button> 333 </div> 334 `; 335 actionsMarkup.push(actionTemplate); 336 } 337 } 338 339 return actionsMarkup.join(''); 340 } 341 342 /** 343 * Create HTML markup for action levels 344 * @param {Array} levels 345 * @return {String} 346 */ 347 createActionLevelsMarkup(levels = []) { 348 349 const levelsLength = levels.length; 350 let levelsTemplate = ''; 351 352 if (levelsLength > 0) { 353 354 let levelMarkups = ''; 355 levels.forEach(() => { 356 levelMarkups += `<div class="fdaw-el"></div>`; 357 }); 358 359 levelsTemplate = ` 360 <div class="fdaw-el fdaw-action__steps fdaw-action__steps--${levelsLength}"> 361 ${levelMarkups} 362 </div> 363 `; 364 } 365 366 return levelsTemplate; 367 } 368 369 /** 370 * 371 * Update or delete cookie 372 */ 373 updateCookieOptions() { 374 if (!this.activeActionClasses.length) { 375 this.removeCookie(this.options.cookieName); 376 } else { 377 this.setCookie(this.options.cookieName, this.activeActionClasses, {expires: this.options.cookieExpireDays}); 378 } 379 } 380 381 /** 382 * Load action css classes from cookie and perform 383 * a basic check, remove duplicates if any 384 * 385 * @returns {Array} Empty array or array of CSS classes 386 */ 387 loadCookieOptions() { 388 389 const cookieOptions = this.getCookie(this.options.cookieName, true) || []; 390 391 if (Array.isArray(cookieOptions) && cookieOptions.length) { 392 return [...new Set(cookieOptions.filter(cssClass => cssClass.match(/^[\w-]+$/i)))]; 393 } 394 395 return []; 396 } 397 398 /** 399 * Merge two arrays with unique values 400 * @param arrays 401 * @returns {*[]} 402 */ 403 mergeArrays(...arrays) { 404 let jointArray = []; 405 406 arrays.forEach(array => { 407 jointArray = [...jointArray, ...array] 408 }); 409 410 return jointArray.filter((item, index) => jointArray.indexOf(item) === index); 411 } 412 413 /** 414 * Add CSS class to options for save in cookie 415 * @param {Array} classNames 416 */ 417 addToOptions(classNames) { 418 this.activeActionClasses = this.mergeArrays(this.activeActionClasses, classNames); 419 } 420 421 /** 422 * Add CSS class to options for save in cookie 423 * @param classNames 424 */ 425 removeFromOptions(classNames) { 426 this.activeActionClasses = this.activeActionClasses.filter((cssClass) => !classNames.includes(cssClass)); 427 } 428 429 /** 430 * Add class to element if not exist 431 * 432 * @param el 433 * @param className 434 */ 435 addClass(el, className) { 436 if (!this.hasClass(el, className)) { 437 el.classList.add(className); 438 } 439 } 440 441 /** 442 * Helper to add multiple CSS classes at once 443 * 444 * @param el 445 * @param classNames 446 */ 447 addClasses(el, classNames) { 448 if (classNames.length) {
449 classNames.forEach(className => this.addClass(el, className)); 450 } 451 } 452 453 /** 454 * Remove class from element 455 * 456 * @param el 457 * @param className 458 */ 459 removeClass(el, className) { 460 el.classList.remove(className); 461 } 462 463 /** 464 * Helper to remove multiple CSS classes at once 465 * 466 * @param el 467 * @param classNames 468 */ 469 removeClasses(el, classNames) { 470 if (classNames.length) { 471 classNames.forEach(className => this.removeClass(el, className)); 472 } 473 } 474 475 /** 476 * Check if element has class 477 * 478 * @param el 479 * @param className 480 * @returns {boolean} 481 */ 482 hasClass(el, className) { 483 return el.classList.contains(className); 484 } 485 486 /** 487 * Toggle class 488 * @param el 489 * @param className 490 */ 491 toggleClass(el, className) { 492 el.classList.toggle(className); 493 } 494 495 /** 496 * Toggle attribute 497 * 498 * @param el 499 * @param name 500 * @param valueOn 501 * @param valueOff 502 */ 503 toggleAttribute(el, name, valueOn, valueOff) { 504 el.setAttribute(name, el.getAttribute(name) === valueOn ? valueOff : valueOn); 505 } 506 507 /** 508 * Helper for trigger event 509 * @param el 510 * @param event_type 511 */ 512 triggerEvent(el, event_type) { 513 let evObj = document.createEvent('Events'); 514 evObj.initEvent(event_type, true, false); 515 el.dispatchEvent(evObj); 516 } 517 518 /** 519 * Hide reading guide if exist 520 */ 521 hideReadingGuide() { 522 if (this.fdawReadLineElement) { 523 this.fdawReadLineElement.style.display = 'none'; 524 document.removeEventListener('mousemove', this.readingGuidePositionEventHandler); 525 } 526 } 527 528 /** 529 * Show reading guide and create it if needed 530 */ 531 showReadingGuide() { 532 533 this.createReadingGuide(); 534 535 if (this.fdawReadLineElement) { 536 this.fdawReadLineElement.style.display = 'block'; 537 this.readingGuidePositionEventHandler = this.updateReadingGuidePosition.bind(this); 538 document.addEventListener('mousemove', this.readingGuidePositionEventHandler); 539 } 540 } 541 542 /** 543 * Create reading line element 544 */ 545 createReadingGuide() { 546 if (!this.fdawReadLineElement) { 547 const fdawReadLine = document.createElement('div'); 548 fdawReadLine.id = 'fdawReadLine'; 549 fdawReadLine.className = 'fdaw-el fdaw-read-line'; 550 fdawReadLine.style.display = 'none'; 551 document.body.appendChild(fdawReadLine); 552 this.fdawReadLineElement = fdawReadLine; 553 } 554 } 555 556 /** 557 * Show/create or hide 558 */ 559 toggleReadingGuide() { 560 if (!this.fdawReadLineElement || this.fdawReadLineElement.style.display === 'none') { 561 this.showReadingGuide(); 562 } else { 563 this.hideReadingGuide(); 564 } 565 } 566 567 /** 568 * Update position for reading guide on mousemove 569 * @param e 570 */ 571 updateReadingGuidePosition(e) { 572 const newPosition = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 573 this.fdawReadLineElement.style.top = newPosition + 'px'; 574 } 575 576 /** 577 * Remove all the actions and clear cookie 578 */ 579 resetWidget() { 580 581 const allWidgetClasses = [...document.documentElement.classList].filter(cssClass => cssClass.includes('fdaw') && cssClass !== 'fdaw-open'); 582 583 this.removeClasses(document.documentElement, allWidgetClasses); 584 585 const actionButtons = document.querySelectorAll('.fdaw-action'); 586 actionButtons.forEach((actionButton) => { 587 actionButton.setAttribute('aria-pressed', 'false'); 588 }); 589 590 this.activeActionClasses = []; 591 592 this.hideReadingGuide(); 593 this.removeCookie(this.options.cookieName); 594 } 595 596 597 /** 598 * Disable widget altogether and set disabled cookie so widget 599 * won't be loaded at all 600 */ 601 disableWidget() { 602 this.resetWidget(); 603 604 if ( this.fdawEl ) { 605 this.fdawEl.remove(); 606 } 607 608 this.setCookie(this.options.cookieName + 'Disable', '1', { expires: 999, path: '/' }); 609 } 610 611 isWidgetDisabled() { 612 return this.getCookie(this.options.cookieName + 'Disable'); 613 } 614 615 extend() { 616 let i = 0; 617 const result = {}; 618 for (; i < arguments.length; i++) { 619 const attributes = arguments[i]; 620 for (const key in attributes) { 621 result[key] = attributes[key]; 622 } 623 } 624 return result; 625 } 626 627 decode(s) { 628 return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent); 629 } 630 631 isDocumentUndefined() { 632 return (typeof document === 'undefined'); 633 } 634
635 setCookie(key, value, attributes) { 636 if (this.isDocumentUndefined()) { 637 return; 638 } 639 640 attributes = this.extend({ 641 path: '/' 642 }, {}, attributes); 643 644 if (typeof attributes.expires === 'number') { 645 attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5); 646 } 647 648 // We're using "expires" because "max-age" is not supported by IE 649 attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; 650 651 try { 652 const result = JSON.stringify(value); 653 if (/^[{\[]/.test(result)) { 654 value = result; 655 } 656 } catch (e) { 657 } 658 659 value = encodeURIComponent(String(value)) 660 .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); 661 662 key = encodeURIComponent(String(key)) 663 .replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent) 664 .replace(/[()]/g, escape); 665 666 let stringifiedAttributes = ''; 667 for (let attributeName in attributes) { 668 if (!attributes[attributeName]) { 669 continue; 670 } 671 stringifiedAttributes += '; ' + attributeName; 672 if (attributes[attributeName] === true) { 673 continue; 674 } 675 676 // Considers RFC 6265 section 5.2: 677 // ... 678 // 3. If the remaining unparsed-attributes contains a %x3B (";") 679 // character: 680 // Consume the characters of the unparsed-attributes up to, 681 // not including, the first %x3B (";") character. 682 // ... 683 stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]; 684 } 685 686 return (document.cookie = key + '=' + value + stringifiedAttributes); 687 } 688 689 getCookie(key, json) { 690 691 if (this.isDocumentUndefined()) { 692 return; 693 } 694 695 const jar = {}; 696 697 // To prevent the for loop in the first place assign an empty array 698 // in case there are no cookies at all. 699 const cookies = document.cookie ? document.cookie.split('; ') : []; 700 let i = 0; 701 702 for (; i < cookies.length; i++) { 703 const parts = cookies[i].split('='); 704 let cookie = parts.slice(1).join('='); 705 706 if (!json && cookie.charAt(0) === '"') { 707 cookie = cookie.slice(1, -1); 708 } 709 710 try { 711 const name = this.decode(parts[0]); 712 cookie = this.decode(cookie); 713 714 if (json) { 715 try { 716 cookie = JSON.parse(cookie); 717 } catch (e) { 718 } 719 } 720 721 jar[name] = cookie; 722 723 if (key === name) { 724 break; 725 } 726 } catch (e) { 727 } 728 } 729 730 return key ? jar[key] : jar; 731 } 732 733 removeCookie(key, attributes) { 734 this.setCookie(key, '', this.extend(attributes, { 735 expires: -1 736 })); 737 } 738} 739 740const fdAccessibilityWidgetOptions = { 741 cookieName: 'fdaw', 742 cookieExpireDays: 30, 743 widgetPosition: 'right bottom', 744 i18n: { 745 hr: { 746 widgetTitle: 'Prilagodba pristupaÄnosti', 747 resetButton: 'Vrati na poÄetak', 748 closeButton: 'Zatvori', 749 disableButton: 'OnemoguÄite prilagodbu pristupaÄnosti i sakrijte alat zauvijek', 750 } 751 }, 752 actions: { 753 fontsize: { 754 enabled: true, 755 canBeSaved: true, 756 trigger: 'fdawFontsizeTrigger', 757 css: 'fdaw-fontsize', 758 icon: `<svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M624 32H272a16 16 0 0 0-16 16v80a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16V96h112v336h-48a16 16 0 0 0-16 16v16a16 16 0 0 0 16 16h160a16 16 0 0 0 16-16v-16a16 16 0 0 0-16-16h-48V96h112v32a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zM304 224H16a16 16 0 0 0-16 16v64a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-32h80v160H96a16 16 0 0 0-16 16v16a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-16a16 16 0 0 0-16-16h-32V272h80v32a16 16 0 0 0 16 16h16a16 16 0 0 0 16-16v-64a16 16 0 0 0-16-16z"></path></svg>`, 759 title: 'VeliÄina teksta', 760 levels: [ 761 { 762 level: 1, 763 title: '', 764 icon: '', 765 active: false 766 }, 767 { 768 level: 2, 769 title: '', 770 icon: '', 771 active: true 772 }, 773 { 774 level: 3, 775 title: '', 776 icon: '', 777 active: false 778 } 779 ] 780 }, 781 contrast: { 782 enabled: true, 783 canBeSaved: true, 784 trigger: 'fdawContrastTrigger', 785 css: 'fdaw-contrast', 786 icon: `<svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M8 256c0 136.966 111.033 248 248 248s248-111.034 248-248S392.966 8 256 8 8 119.033 8 256zm248 184V72c101.705 0 184 82.311 184 184 0 101.705-82.311 184-184 184z"></path></svg>`, 787 title: 'Kontrast', 788 levels: [ 789 { 790 level: 1, 791 title: '', 792 icon: '', 793 active: false 794 } 795 ] 796 }, 797 dyslexia: { 798 enabled: true, 799 canBeSaved: true, 800 trigger: 'fdawDyslexiaTrigger', 801 css: 'fdaw-dyslexia', 802 icon: `<svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M1.38,341V1.32H96c131.87,0,191,53.12,191,169.6C287,287.88,226.89,341,96,341ZM49.83,39.06v216.2h55.45c93.66,0,127.67-19.57,134.66-89,0-84.8-41-127.2-134.66-127.2Z"/><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M470.29,163.79h40.33l-4.48,340.6H465.81V467.64c-16.58,29.13-42.57,43-78.43,43C328.23,510.66,287,459.12,287,382s41.23-128.62,100.38-128.62c35.86,0,61.85,13.9,78.43,43ZM316.13,377.56c6.72,42.57,24.65,60.05,67.22,60.05s63.19-9,64.54-63.19c-1.35-59.15-20.62-91.87-63.19-91.87C341.67,282.55,316.13,318.41,316.13,377.56Z"/></svg>`, 803 title: 'Za disleksiju', 804 levels: [ 805 { 806 level: 1, 807 title: '', 808 icon: '', 809 active: true 810 }, 811 ] 812 }, 813 links: { 814 enabled: true, 815 canBeSaved: true, 816 trigger: 'fdawLinksTrigger', 817 css: 'fdaw-links', 818 icon: `<svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M314.222 197.78c51.091 51.091 54.377 132.287 9.75 187.16-6.242 7.73-2.784 3.865-84.94 86.02-54.696 54.696-143.266 54.745-197.99 0-54.711-54.69-54.734-143.255 0-197.99 32.773-32.773 51.835-51.899 63.409-63.457 7.463-7.452 20.331-2.354 20.486 8.192a173.3
8181 173.31 0 0 0 4.746 37.828c.966 4.029-.272 8.269-3.202 11.198L80.632 312.57c-32.755 32.775-32.887 85.892 0 118.8 32.775 32.755 85.892 32.887 118.8 0l75.19-75.2c32.718-32.725 32.777-86.013 0-118.79a83.722 83.722 0 0 0-22.814-16.229c-4.623-2.233-7.182-7.25-6.561-12.346 1.356-11.122 6.296-21.885 14.815-30.405l4.375-4.375c3.625-3.626 9.177-4.594 13.76-2.294 12.999 6.524 25.187 15.211 36.025 26.049zM470.958 41.04c-54.724-54.745-143.294-54.696-197.99 0-82.156 82.156-78.698 78.29-84.94 86.02-44.627 54.873-41.341 136.069 9.75 187.16 10.838 10.838 23.026 19.525 36.025 26.049 4.582 2.3 10.134 1.331 13.76-2.294l4.375-4.375c8.52-8.519 13.459-19.283 14.815-30.405.621-5.096-1.938-10.113-6.561-12.346a83.706 83.706 0 0 1-22.814-16.229c-32.777-32.777-32.718-86.065 0-118.79l75.19-75.2c32.908-32.887 86.025-32.755 118.8 0 32.887 32.908 32.755 86.025 0 118.8l-45.848 45.84c-2.93 2.929-4.168 7.169-3.202 11.198a173.31 173.31 0 0 1 4.746 37.828c.155 10.546 13.023 15.644 20.486 8.192 11.574-11.558 30.636-30.684 63.409-63.457 54.733-54.735 54.71-143.3-.001-197.991z"></path></svg>`, 819 title: 'Naglasi poveznice', 820 levels: [ 821 { 822 level: 1, 823 title: '', 824 icon: '', 825 active: false 826 }, 827 ] 828 }, 829 kerning: { 830 enabled: true, 831 canBeSaved: true, 832 trigger: 'fdawKerningTrigger', 833 css: 'fdaw-kerning', 834 icon: `<svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M416.54 0h-17A8 8 0 0 0 392 5.32l-176.28 496a8 8 0 0 0 7.55 10.68h17a8 8 0 0 0 7.54-5.32l176.29-496A8 8 0 0 0 416.54 0zm206.25 393.94l-103.91-288A16 16 0 0 0 504.07 96h-48.14a16 16 0 0 0-14.81 9.94l-103.91 288A16 16 0 0 0 352 416h25.92a16 16 0 0 0 14.81-9.94l19.1-54.06h136.34l19.08 54.06a16 16 0 0 0 14.81 9.94H608a16 16 0 0 0 14.79-22.06zM434.42 288L480 158.84 525.59 288zM288 96h-25.94a16 16 0 0 0-14.81 9.94L160 353.16 72.75 105.94A16 16 0 0 0 57.94 96H32a16 16 0 0 0-14.81 22.06l103.91 288a16 16 0 0 0 14.83 9.94h48.14a16 16 0 0 0 14.81-9.94l103.91-288A16 16 0 0 0 288 96z"></path></svg>`, 835 title: 'Razmak teksta', 836 levels: [ 837 { 838 level: 1, 839 title: '', 840 icon: '', 841 active: false 842 }, 843 { 844 level: 2, 845 title: '', 846 icon: '', 847 active: true 848 }, 849 { 850 level: 3, 851 title: '', 852 icon: '', 853 active: false 854 }, 855 ] 856 }, 857 readguide: { 858 enabled: true, 859 canBeSaved: true, 860 trigger: 'fdawReadguideTrigger', 861 css: 'fdaw-readguide', 862 icon: `<svg class="fdaw-el" aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path class="fdaw-el fdaw-icon-fill" fill="#161E2E" d="M640 247.5v17a16 16 0 0 1-16 16H16a16 16 0 0 1-16-16v-17a16 16 0 0 1 16-16h608a16 16 0 0 1 16 16z"></path></svg>`, 863 title: 'VodiÄ za Äitanje', 864 levels: [ 865 { 866 level: 1, 867 title: '', 868 icon: '', 869 active: false 870 } 871 ] 872 } 873 } 874}; 875 876const FDAW = new FdAccessibilityWidget(fdAccessibilityWidgetOptions);
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.