PageSourceSearch

https://www.fusion5.com/scripts/ui.js

js fusion5.com collected 2026-10-03 19:58:31 UTC 7,438 bytes, 185 lines download raw bytes

1function UI(options) {
2    options = options || {};
3    this.wpm = options.wpm || 250;
4    this.timeToReadElements = $(".time-to-read");
5    this.contentElements = $(".text");
6    this.hoverItems = $("html.no-touch .item.has-hover.items-1");
7}
8
9UI.prototype = {
10    init: function () {
11        if (this.timeToReadElements.length > 0 && this.contentElements.length > 0) {
12            this.setupTimeToRead();
13        } else {
14            this.timeToReadElements.remove();
15        }
16        if (this.hoverItems.length > 0) {
17            this.setupHoverItems();
18
19        }
20    },
21    setupHoverItems: function () {
22        this.hoverItems.each(function () {
23            $(this).mouseenter(function () {
24                var $this = $(this);
25                var revealWrapperHeight = $(this).find(".reveal-wrapper").outerHeight();
26                requestAnimationFrame(function () {
27                    $this.css('height', (revealWrapperHeight + 200) + 'px');
28                });
29            }).mouseleave(function () {
30
31                var $this = $(this);
32                requestAnimationFrame(function () {
33                    $this.css('height', '200px');
34                });
35            });
36
37        })
38    },
39    setupTimeToRead: function () {
40        var that = this;
41        var totalWords = 0;
42
43        this.contentElements.each(function () {
44            var text = $(this).text();
45            var wordCount = text.replace(/\s\s+/g, ' ').trim().split(' ').length;
46            totalWords += wordCount;
47        });
48
49        var minutes = totalWords / that.wpm;
50        minutes = Math.ceil(minutes); // Always round up to the next full minute
51        var svgIcon = '<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">' +
52            '<g clip-path="url(#clip0_3392_20279)">' +
53            '<path d="M12.9654 8.47035L11.025 9.5907V5.25C11.025 5.11076 10.9697 4.97723 10.8712 4.87877C10.7728 4.78031 10.6392 4.725 10.5 4.725C10.3608 4.725 10.2272 4.78031 10.1288 4.87877C10.0303 4.97723 9.975 5.11076 9.975 5.25V10.5C9.975 10.5922 9.99926 10.6827 10.0453 10.7625C10.0914 10.8423 10.1577 10.9086 10.2375 10.9547C10.3173 11.0007 10.4078 11.025 10.5 11.025C10.5922 11.025 10.6827 11.0007 10.7625 10.9546L13.4904 9.37965C13.5506 9.34543 13.6034 9.29964 13.6458 9.24492C13.6883 9.1902 13.7194 9.12763 13.7376 9.06081C13.7557 8.99399 13.7605 8.92425 13.7515 8.85559C13.7426 8.78693 13.7202 8.72071 13.6856 8.66075C13.651 8.60079 13.6048 8.54827 13.5498 8.50622C13.4948 8.46416 13.432 8.4334 13.3651 8.4157C13.2982 8.398 13.2284 8.39372 13.1598 8.4031C13.0912 8.41248 13.0251 8.43533 12.9654 8.47035ZM10.5 0C4.70085 0 0 4.70085 0 10.5C0 16.2992 4.70085 21 10.5 21C16.296 20.9937 20.9937 16.296 21 10.5C21 4.70085 16.2992 0 10.5 0ZM10.5 19.95C9.25901 19.95 8.03017 19.7056 6.88364 19.2307C5.73711 18.7558 4.69535 18.0597 3.81784 17.1822C2.94033 16.3046 2.24425 15.2629 1.76934 14.1164C1.29443 12.9698 1.05 11.741 1.05 10.5C1.05 9.25901 1.29443 8.03017 1.76934 6.88364C2.24425 5.73711 2.94033 4.69535 3.81784 3.81784C4.69535 2.94033 5.73711 2.24425 6.88364 1.76934C8.03017 1.29443 9.25901 1.05 10.5 1.05C13.0054 1.05278 15.4075 2.04929 17.1791 3.82091C18.9507 5.59253 19.9472 7.99456 19.95 10.5C19.95 13.0063 18.9544 15.4099 17.1822 17.1822C15.4099 18.9544 13.0063 19.95 10.5 19.95Z" fill=""/>' +
54            '</g>' +
55            '<defs>' +
56            '<clipPath id="clip0_3392_20279">' +
57            '<rect width="21" height="21" fill="white"/>' +
58            '</clipPath>' +
59            '</defs>' +
60            '</svg>';
61
62
63        var timeStr = svgIcon + ' <div>' + minutes + " min read</div>";
64
65        this.timeToReadElements.addClass("ready");
66        this.timeToReadElements.html($(timeStr));
67    }
68};
69
70
71function updateListingPromoPods() {
72    $("section").each(function () {
73        const $section = $(this);
74        const $podsContainers = $section.find(".right-col .listing-pods");
75        if (!$podsContainers.length) return;
76
77        // Count grid items in this section, excluding anything inside .right-col
78        const listingsCount = $section
79            .find(".listing.listing_basic-grid .item")
80            .filter(function () {
81                return $(this).closest(".right-col").length === 0;
82            }).length;
83
84        const maxPods =
85            listingsCount < 8 ? 2 :
86                listingsCount < 11 ? 3 : 4;
87
88        $podsContainers.each(function () {
89            $(this).children(".item").show().slice(maxPods).hide();
90        });
91    });
92}
93
94function setupStickySwpOverlapBackground() {
95    var overlapClass = "swp-overlap-img-left";
96    var overlapCheckQueued = false;
97
98    function hasRectOverlap(rectA, rectB) {
99        return rectA.left < rectB.right &&
100            rectA.right > rectB.left &&
101            rectA.top < rectB.bottom &&
102            rectA.bottom > rectB.top;
103    }
104
105    function checkStickyOverlap() {
106        overlapCheckQueued = false;
107
108        var swpElements = document.querySelectorAll(".left-col .swp");
109        if (!swpElements.length) {
110            return;
111        }
112
113        var imgLeftElements = document.querySelectorAll(".img-left");
114
115        if (!imgLeftElements.length) {
116            for (var i = 0; i < swpElements.length; i++) {
117                swpElements[i].classList.remove(overlapClass);
118            }
119            return;
120        }
121
122        for (var swpIndex = 0; swpIndex < swpElements.length; swpIndex++) {
123            var swpElement = swpElements[swpIndex];
124            var swpRect = swpElement.getBoundingClientRect();
125
126            if (swpRect.width <= 0 || swpRect.height <= 0) {
127                swpElement.classList.remove(overlapClass);
128                continue;
129            }
130
131            var overlapsImgLeft = false;
132
133            for (var imgIndex = 0; imgIndex < imgLeftElements.length; imgIndex++) {
134                var imgRect = imgLeftElements[imgIndex].getBoundingClientRect();
135
136                if (imgRect.width <= 0 || imgRect.height <= 0) {
137                    continue;
138                }
139
140                if (hasRectOverlap(swpRect, imgRect)) {
141                    overlapsImgLeft = true;
142                    break;
143                }
144            }
145
146            swpElement.classList.toggle(overlapClass, overlapsImgLeft);
147        }
148    }
149
150    function queueOverlapCheck() {
151        if (overlapCheckQueued) {
152            return;
153        }
154
155        overlapCheckQueued = true;
156        window.requestAnimationFrame(checkStickyOverlap);
157    }
158
159    window.addEventListener("scroll", queueOverlapCheck, { passive: true });
160    window.addEventListener("resize", queueOverlapCheck);
161    window.addEventListener("orientationchange", queueOverlapCheck);
162    window.addEventListener("load", queueOverlapCheck);
163
164    document.addEventListener("load", function (event) {
165        if (event.target && event.target.matches && event.target.matches(".img-left img")) {
166            queueOverlapCheck();
167        }
168    }, true);
169
170    $(document).on("ajaxComplete", queueOverlapCheck);
171
172    queueOverlapCheck();
173}
174
175
176$(document).on("ajaxComplete", function () {
177    updateListingPromoPods();
178});
179
180$(function () {
181    var ui = new UI({ wpm: 250 });
182    ui.init();
183    updateListingPromoPods(); // initial page load
184    setupStickySwpOverlapBackground();
185});

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.