PageSourceSearch

https://meteo.hr/fdaw/js/fdaw.js

js meteo.hr collected 2026-10-01 10:41:29 UTC 32,550 bytes, 876 lines download raw bytes

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">&times;</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.