PageSourceSearch

https://www.somalicentre.org.uk/scripts/anchor-scroll.js?v=d041026

js somalicentre.org.uk collected 2026-10-04 04:10:09 UTC 8,656 bytes, 279 lines download raw bytes

1(function (window, document, $) {
2    if (!$) {
3        return;
4    }
5
6    var ignoredHashes = {
7        "#hamburger-mobile-nav": true,
8        "#hamburger-desktop-nav": true
9    };
10
11    function getHashId(hash) {
12        if (!hash || hash == "#") {
13            return "";
14        }
15
16        try {
17            return decodeURIComponent(hash.substring(1));
18        } catch (e) {
19            return hash.substring(1);
20        }
21    }
22
23    function getAnchorTarget(hash) {
24        var id = getHashId(hash);
25
26        if (!id) {
27            return null;
28        }
29
30        var target = document.getElementById(id);
31        if (target) {
32            return target;
33        }
34
35        return $("[name]").filter(function () {
36            return this.getAttribute("name") == id;
37        }).get(0);
38    }
39
40    function isIgnoredHash(hash) {
41        return ignoredHashes[hash] === true;
42    }
43
44    function elementIsHidden($element) {
45        return !$element.length || !$element.is(":visible");
46    }
47
48    function includeElementForOffset(element, selectedDirectly) {
49        var $element = $(element);
50
51        if (elementIsHidden($element) || $element.closest(".modal, .modal-backdrop, .mm-menu, .mm-wrapper__blocker").length) {
52            return false;
53        }
54
55        var style = window.getComputedStyle(element);
56        var rect = element.getBoundingClientRect();
57        var topLimit = selectedDirectly ? 200 : 20;
58
59        if (rect.height < 1 || rect.width < 1 || rect.height > window.innerHeight * 0.6) {
60            return false;
61        }
62
63        if (rect.width < window.innerWidth * 0.4 && !selectedDirectly) {
64            return false;
65        }
66
67        if (style.position == "fixed") {
68            return rect.top <= topLimit && rect.bottom > 0;
69        }
70
71        if (style.position == "sticky" || style.position == "-webkit-sticky") {
72            var top = parseFloat(style.top);
73            top = isNaN(top) ? 0 : top;
74
75            return top <= topLimit;
76        }
77
78        return false;
79    }
80
81    function getElementOffsetBottom(element) {
82        var style = window.getComputedStyle(element);
83        var rect = element.getBoundingClientRect();
84
85        if (style.position == "sticky" || style.position == "-webkit-sticky") {
86            var top = parseFloat(style.top);
87            top = isNaN(top) ? 0 : top;
88
89            return top + rect.height;
90        }
91
92        return rect.bottom;
93    }
94
95    function getAnchorScrollOffset() {
96        var offset = 0;
97        var checked = [];
98        var selected = [];
99        var selectors = [
100            "#header-section",
101            "#navigation-section",
102            "#navigation-section-container",
103            "#mobile-header-section-hamburger",
104            "#desktop-header-section-hamburger",
105            ".fixed-top",
106            ".navbar-fixed-top",
107            ".sticky-top",
108            ".mhead",
109            ".mh-head"
110        ];
111
112        selected = selected.concat($(selectors.join(",")).toArray());
113        selected = selected.concat($("body").children().toArray());
114
115        $.each(selected, function (index, element) {
116            if ($.inArray(element, checked) !== -1) {
117                return;
118            }
119
120            checked.push(element);
121
122            if (!includeElementForOffset(element, $(element).is(selectors.join(",")))) {
123                return;
124            }
125
126            offset = Math.max(offset, getElementOffsetBottom(element));
127        });
128
129        return offset > 0 ? Math.ceil(offset + 12) : 0;
130    }
131
132    function scrollToAnchor(hash, animate, scrollOffset) {
133        if (isIgnoredHash(hash)) {
134            return true;
135        }
136
137        var target = getAnchorTarget(hash);
138
139        if (!target || $(target).closest(".mm-menu, .modal, .carousel").length) {
140            return true;
141        }
142
143        scrollOffset = parseFloat(scrollOffset);
144        scrollOffset = isFinite(scrollOffset) ? scrollOffset : 0;
145        var scrollTop = Math.max(0, $(target).offset().top - getAnchorScrollOffset() + scrollOffset);
146
147        if (animate === false || (window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches)) {
148            $("html, body").stop();
149            $("html, body").scrollTop(scrollTop);
150        } else {
151            $("html, body").stop().animate({
152                scrollTop: scrollTop
153            }, 440, "swing");
154        }
155
156        return false;
157    }
158
159    function normalisePath(pathname) {
160        return pathname.replace(/\/$/, "");
161    }
162
163    function urlWithoutHash(url) {
164        var link = document.createElement("a");
165        link.href = url;
166
167        return link.protocol + "//" + link.host + normalisePath(link.pathname) + link.search;
168    }
169
170    function isSamePageLink(link) {
171        return urlWithoutHash(link.href) == urlWithoutHash(window.location.href);
172    }
173
174    function linkShouldBeIgnored(link) {
175        var $link = $(link);
176
177        if (!link.hash || link.hash == "#" || isIgnoredHash(link.hash)) {
178            return true;
179        }
180
181        if (link.target && link.target != "_self") {
182            return true;
183        }
184
185        if ($link.is("[data-toggle], [data-bs-toggle], [data-slide], [data-bs-slide]")) {
186            return true;
187        }
188
189        if ($link.is("[data-text-tab], [role='tab']") || $link.closest("[role='tablist']").length) {
190            return true;
191        }
192
193        if ($link.is(".mburger, .mm-btn, .carousel-control, .carousel-control-prev, .carousel-control-next")) {
194            return true;
195        }
196
197        if ($link.closest(".mm-menu, .modal, .carousel").length) {
198            return true;
199        }
200
201        return false;
202    }
203
204    window.wfScrollToAnchor = scrollToAnchor;
205    window.wfAnchorScrollOffset = getAnchorScrollOffset;
206
207    // Mmenu consumes fragment links and restores the page's scroll position on close.
208    // Wait for its existing close transition, then position the page without a second animation.
209    document.addEventListener("click", function (event) {
210        var link = $(event.target).closest(".mm-menu a[href]").get(0);
211        if (!link || event.defaultPrevented || event.button !== 0 || event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || !isSamePageLink(link)) {
212            return;
213        }
214
215        var target = getAnchorTarget(link.hash);
216        var menu = $(link).closest(".mm-menu").get(0);
217        var api = menu && menu.mmApi;
218        if (!target || isIgnoredHash(link.hash) || (link.target && link.target !== "_self") || $(link).is(".mm-btn, [data-toggle], [data-bs-toggle], [role='tab']") || $(target).closest(".mm-menu, .modal, .carousel").length || !api || !api.bind || !api.close) {
219            return;
220        }
221
222        event.preventDefault();
223        event.stopImmediatePropagation();
224        menu.wfPendingAnchor = link.hash;
225        if (!menu.wfAnchorCloseBound) {
226            menu.wfAnchorCloseBound = true;
227            api.bind("close:finish", function () {
228                var hash = menu.wfPendingAnchor;
229                menu.wfPendingAnchor = null;
230                if (!hash) {
231                    return;
232                }
233                scrollToAnchor(hash, false);
234                if (window.history && window.history.pushState) {
235                    window.history.pushState(null, document.title, hash);
236                } else {
237                    window.location.hash = hash;
238                }
239                var destination = getAnchorTarget(hash);
240                if (destination && destination.focus) {
241                    if (!destination.hasAttribute("tabindex")) {
242                        destination.setAttribute("tabindex", "-1");
243                    }
244                    destination.focus({ preventScroll: true });
245                }
246            });
247        }
248        api.close();
249    }, true);
250
251    if (window.location.hash && !isIgnoredHash(window.location.hash)) {
252        scroll(0, 0);
253        setTimeout(function () {
254            scroll(0, 0);
255        }, 1);
256    }
257
258    $(window).on("load", function () {
259        if (window.location.hash) {
260            scrollToAnchor(window.location.hash);
261        }
262    });
263
264    $(document).on("click", "a[href*='#']", function (event) {
265        if (event.isDefaultPrevented() || linkShouldBeIgnored(this) || !isSamePageLink(this)) {
266            return;
267        }
268
269        if (scrollToAnchor(this.hash) === false) {
270            event.preventDefault();
271
272            if (window.history && window.history.pushState) {
273                window.history.pushState(null, document.title, this.hash);
274            } else {
275                window.location.hash = this.hash;
276            }
277        }
278    });
279})(window, document, window.jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.