PageSourceSearch

https://hidur.co.il/Plugins/Nop.NopShop.Widgets.Accessibility/wwwroot/js/accessibility-widget.js

js hidur.co.il collected 2026-10-06 12:54:00 UTC 11,739 bytes, 334 lines download raw bytes

1(function () {
2    "use strict";
3
4    var storageKey = "ofekAccessibilityPreferences";
5    var bodyClasses = [
6        "ofek-a11y-large-text",
7        "ofek-a11y-xlarge-text",
8        "ofek-a11y-high-contrast",
9        "ofek-a11y-grayscale",
10        "ofek-a11y-highlight-links",
11        "ofek-a11y-readable-font",
12        "ofek-a11y-line-height",
13        "ofek-a11y-letter-spacing",
14        "ofek-a11y-pause-animations",
15        "ofek-a11y-big-cursor",
16        "ofek-a11y-hide-images"
17    ];
18
19    var actions = [
20        { action: "increaseText", label: "הגדלת טקסט", state: false },
21        { action: "decreaseText", label: "הקטנת טקסט", state: false },
22        { action: "resetText", label: "איפוס טקסט", state: false },
23        { action: "highContrast", label: "ניגודיות גבוהה", state: "highContrast" },
24        { action: "grayscale", label: "מצב גווני אפור", state: "grayscale" },
25        { action: "highlightLinks", label: "הדגשת קישורים", state: "highlightLinks" },
26        { action: "readableFont", label: "פונט קריא", state: "readableFont" },
27        { action: "lineHeight", label: "הגדלת ריווח שורות", state: "lineHeight" },
28        { action: "letterSpacing", label: "הגדלת ריווח אותיות", state: "letterSpacing" },
29        { action: "pauseAnimations", label: "עצירת אנימציות", state: "pauseAnimations" },
30        { action: "bigCursor", label: "סמן גדול", state: "bigCursor" },
31        { action: "hideImages", label: "הסתרת תמונות", state: "hideImages" },
32        { action: "resetAll", label: "איפוס כל ההגדרות", state: false, reset: true }
33    ];
34
35    function readState() {
36        var defaults = {
37            textLevel: 0,
38            highContrast: false,
39            grayscale: false,
40            highlightLinks: false,
41            readableFont: false,
42            lineHeight: false,
43            letterSpacing: false,
44            pauseAnimations: false,
45            bigCursor: false,
46            hideImages: false
47        };
48
49        try {
50            var saved = window.localStorage ? window.localStorage.getItem(storageKey) : null;
51            if (!saved) {
52                return defaults;
53            }
54
55            return Object.assign(defaults, JSON.parse(saved));
56        } catch (error) {
57            return defaults;
58        }
59    }
60
61    function saveState(state) {
62        try {
63            if (window.localStorage) {
64                window.localStorage.setItem(storageKey, JSON.stringify(state));
65            }
66        } catch (error) {
67            // localStorage can be blocked by browser privacy settings.
68        }
69    }
70
71    function clearState() {
72        try {
73            if (window.localStorage) {
74                window.localStorage.removeItem(storageKey);
75            }
76        } catch (error) {
77            // Ignore storage failures.
78        }
79    }
80
81    function removeBodyClasses() {
82        if (!document.body) {
83            return;
84        }
85
86        bodyClasses.forEach(function (className) {
87            document.body.classList.remove(className);
88        });
89    }
90
91    function applyState(state, root) {
92        if (!document.body) {
93            return;
94        }
95
96        removeBodyClasses();
97
98        if (state.textLevel === 1) {
99            document.body.classList.add("ofek-a11y-large-text");
100        }
101
102        if (state.textLevel >= 2) {
103            document.body.classList.add("ofek-a11y-xlarge-text");
104        }
105
106        setBodyClass("ofek-a11y-high-contrast", state.highContrast);
107        setBodyClass("ofek-a11y-grayscale", state.grayscale);
108        setBodyClass("ofek-a11y-highlight-links", state.highlightLinks);
109        setBodyClass("ofek-a11y-readable-font", state.readableFont);
110        setBodyClass("ofek-a11y-line-height", state.lineHeight);
111        setBodyClass("ofek-a11y-letter-spacing", state.letterSpacing);
112        setBodyClass("ofek-a11y-pause-animations", state.pauseAnimations);
113        setBodyClass("ofek-a11y-big-cursor", state.bigCursor);
114        setBodyClass("ofek-a11y-hide-images", state.hideImages);
115        updatePressedStates(root, state);
116    }
117
118    function setBodyClass(className, enabled) {
119        if (enabled) {
120            document.body.classList.add(className);
121        } else {
122            document.body.classList.remove(className);
123        }
124    }
125
126    function updatePressedStates(root, state) {
127        if (!root) {
128            return;
129        }
130
131        actions.forEach(function (item) {
132            if (!item.state) {
133                return;
134            }
135
136            var button = root.querySelector('[data-ofek-a11y-action="' + item.action + '"]');
137            if (button) {
138                button.setAttribute("aria-pressed", state[item.state] ? "true" : "false");
139            }
140        });
141    }
142
143    function buildWidget(container) {
144        var state = readState();
145        var position = container.getAttribute("data-position") || "bottom-right";
146        var primaryColor = container.getAttribute("data-primary-color") || "#1f6feb";
147        var buttonText = container.getAttribute("data-button-text") || "נגישות";
148        var showSkipLink = container.getAttribute("data-show-skip-link") !== "fal
148se";
149        var iconSize = parseInt(container.getAttribute("data-icon-size") || "48", 10);
150        var root = document.createElement("div");
151        var button = document.createElement("button");
152        var panel = document.createElement("div");
153        var panelId = "ofek-a11y-panel-" + Math.random().toString(36).slice(2);
154        var list = document.createElement("div");
155
156        root.className = "ofek-accessibility-widget ofek-accessibility-widget--" + position;
157        root.style.setProperty("--ofek-a11y-primary", primaryColor);
158        root.style.setProperty("--ofek-a11y-button-size", Math.max(36, Math.min(iconSize, 72)) + "px");
159        root.setAttribute("dir", "rtl");
160
161        if (showSkipLink) {
162            root.appendChild(createSkipLink());
163        }
164
165        button.type = "button";
166        button.className = "ofek-accessibility-widget__toggle";
167        button.setAttribute("aria-label", buttonText);
168        button.setAttribute("aria-expanded", "false");
169        button.setAttribute("aria-controls", panelId);
170        button.innerHTML = '<span aria-hidden="true">Aa</span><span class="ofek-accessibility-widget__toggle-text">' + escapeHtml(buttonText) + "</span>";
171
172        panel.id = panelId;
173        panel.className = "ofek-accessibility-widget__panel";
174        panel.setAttribute("role", "dialog");
175        panel.setAttribute("aria-modal", "false");
176        panel.setAttribute("aria-label", "סרגל נגישות");
177        panel.hidden = true;
178
179        list.className = "ofek-accessibility-widget__actions";
180        actions.forEach(function (item) {
181            var actionButton = document.createElement("button");
182            actionButton.type = "button";
183            actionButton.className = item.reset ? "ofek-accessibility-widget__action ofek-accessibility-widget__action--reset" : "ofek-accessibility-widget__action";
184            actionButton.setAttribute("data-ofek-a11y-action", item.action);
185            actionButton.textContent = item.label;
186
187            if (item.state) {
188                actionButton.setAttribute("aria-pressed", state[item.state] ? "true" : "false");
189            }
190
191            list.appendChild(actionButton);
192        });
193
194        panel.appendChild(list);
195        root.appendChild(button);
196        root.appendChild(panel);
197        container.replaceWith(root);
198
199        applyState(state, root);
200
201        button.addEventListener("click", function () {
202            setOpen(root, button, panel, panel.hidden);
203        });
204
205        root.addEventListener("click", function (event) {
206            var actionButton = event.target.closest("[data-ofek-a11y-action]");
207            if (!actionButton || !root.contains(actionButton)) {
208                return;
209            }
210
211            handleAction(actionButton.getAttribute("data-ofek-a11y-action"), state, root);
212        });
213
214        root.addEventListener("keydown", function (event) {
215            if (event.key === "Escape" && !panel.hidden) {
216                setOpen(root, button, panel, false);
217                button.focus();
218            }
219        });
220    }
221
222    function createSkipLink() {
223        var link = document.createElement("a");
224        var target = findMainContentTarget();
225
226        link.className = "ofek-accessibility-widget__skip-link";
227        link.href = "#" + target.id;
228        link.textContent = "דלג לתוכן המרכזי";
229        return link;
230    }
231
232    function findMainContentTarget() {
233        var target = document.querySelector("main, #main, #content, .main, .master-wrapper-content");
234
235        if (!target) {
236            target = document.body;
237        }
238
239        if (!target.id) {
240            target.id = "ofek-a11y-main-content";
241        }
242
243        if (!target.hasAttribute("tabindex")) {
244            target.setAttribute("tabindex", "-1");
245        }
246
247        return target;
248    }
249
250    function setOpen(root, button, panel, open) {
251        panel.hidden = !open;
252        button.setAttribute("aria-expanded", open ? "true" : "false");
253        root.classList.toggle("ofek-accessibility-widget--open", open);
254
255        if (open) {
256            var firstAction = panel.querySelector("button");
257            if (firstAction) {
258                firstAction.focus();
259            }
260        }
261    }
262
263    function handleAction(action, state, root) {
264        switch (action) {
265            case "increaseText":
266                state.textLevel = Math.min((state.textLevel || 0) + 1, 2);
267                break;
268            case "decreaseText":
269                state.textLevel = Math.max((state.textLevel || 0) - 1, -1);
270                break;
271            case "resetText":
272                state.textLevel = 0;
273                break;
274            case "highContrast":
275                state.highContrast = !state.highContrast;
276                break;
277            case "grayscale":
278                state.grayscale = !state.grayscale;
279                break;
280            case "highlightLinks":
281                state.highlightLinks = !state.highlightLinks;
282                break;
283            case "readableFont":
284                state.readableFont = !state.readableFont;
285                break;
286            case "lineHeight":
287                state.lineHeight = !state.lineHeight;
288                break;
289            case "letterSpacing":
290                state.letterSpacing = !state.letterSpacing;
291                break;
292            case "pauseAnimations":
293                state.pauseAnimations = !state.pauseAnimations;
294                break;
295            case "bigCursor":
296                state.bigCursor = !state.bigCursor;
297                break;
298            case "hideImages":
299                state.hideImages = !state.hideImages;
300                break;
301            case "resetAll":
302                clearState();
303                state = readState();
304                applyState(state, root);
305                return;
306            default:
307                return;
308        }
309
310        saveState(state);
311        applyState(state, root);
312    }
313
314    function escapeHtml(value) {
315        var node = document.createElement("span");
316        node.textContent = value;
317        return node.innerHTML;
318    }
319
320    function init() {
321        if (!document.body) {
322            return;
323        }
324
325        var containers = document.querySelectorAll("[data-ofek-accessibility-widget]");
326        Array.prototype.forEach.call(containers, buildWidget);
327    }
328
329    if (document.readyState === "loading") {
330        document.addEventListener("DOMContentLoaded", init);
331    } else {
332        init();
333    }
334})();

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.