PageSourceSearch

https://framgangspodden.se/Scripts/horizontsl-scroller.js

js framgangspodden.se collected 2026-10-04 00:25:50 UTC 7,882 bytes, 232 lines download raw bytes

1// The Horizontal<a href="https://www.jqueryscript.net/tags.php?/Scroll/">Scroll</a>er Class accepts a jQuery object as its only argument
2// The argument is the parent container of the scrolling element
3// The element requires an ID to differentiate HorizontalScroller instances
4
5function HorizontalScroller(elem) {
6    this.scrollbox = elem; // The scrollers viewable area
7    this.scrollImages = this.scrollbox.find("img");
8    this.leftScrollControl = this.scrollbox.siblings(".left-scroll");
9    this.rightScrollControl = this.scrollbox.siblings(".right-scroll");
10
11    // Listener to change visibility of left and right controls
12    // when at scroll extremes
13    this.scrollbox.on("scroll", this.evaluateControlVisibility.bind(this));
14};
15
16HorizontalScroller.prototype = {    
17    scrollboxWidth: function () {
18        return this.scrollbox.outerWidth(true);
19    },
20
21    currentScrollPosition: function () {
22        return this.scrollbox.scrollLeft();
23    },
24
25    currentRightPosition: function () {
26        return this.currentScrollPosition() + this.scrollboxWidth() - this.totalWidths();
27    },
28
29    // Maps the image width of each image in the scroller
30    imageWidths: function () {
31        return $.map(this.scrollImages, function (img) {
32            return $(img).outerWidth(true);
33        })
34    },
35
36    // Returns the total width of all the images, that is,
37    // the total of the visible and overflow content.
38    totalWidths: function () {
39        return this.imageWidths().reduce(function (a, b) { return a + b });
40    },
41
42    // Returns the average width of all the images
43    avgWidth: function () {
44        return this.totalWidths() / this.imageWidths().length;
45    },
46
47    // Determines the number of images in view area.
48    // Number of images changes with responsive CSS
49    imagesAcross: function () {
50        return Math.round(this.scrollboxWidth() / this.avgWidth());
51    },
52
53    // maps the offset x-distance of each image
54    // from the left edge of the view area
55    imageOffsets: function () {
56        return $.map(this.scrollImages, function (img) {
57            return Math.round($(img).position().left);
58        });
59    },
60
61    // Returns the index of the first number in the given array
62    // greater than the given value, or, returns the index of
63    // the first positive number in the array
64    indexOfFirst: function (array, value) {
65        value = value || 0;
66        var firstIndex;
67        var i = 0;
68        while (firstIndex === undefined && array.length > i) {
69            if (array[i] >= value)
70                firstIndex = i;
71            i += 1;
72        }
73        return firstIndex;        
74    },
75
76    // Returns the index of first image that is completely in view
77    // within the scrollbox
78    firstVisibleImageIndex: function () {
79        return this.indexOfFirst(this.imageOffsets());
80    },
81
82    // Returns the first image that is completely in view 
83    // within the scrollbox
84    firstVisibleImage: function () {        
85        return this.scrollImages[this.firstVisibleImageIndex()];
86    },
87
88    // Returns the index of the last image with its left edge in view 
89    // within the scrollbox
90    lastVisibleImageIndex: function () {
91        return this.firstVisibleImageIndex() + this.imagesAcross();
92    },
93
94    // Returns the last image with its left edge in view 
95    // within the scrollbox
96    lastVisibleImage: function () {
97        return this.scrollImages[this.lastVisibleImageIndex()];
98    },
99
100    // Returns the difference between the scrollboxes left edge
101    // and the left edge of the first fully visible image, that is,
102    // how far in the first fully visible image is
103    //offset: function () {        
104    //    var offset = $(this.firstVisibleImage()).position().left;
105    //    return Math.round(offset);
106    //},
107
108    // Returns the combined scroll amount that the images have to travel
109    // in order to land evenly within the scroll window. The resulting
110    nextScrollPosition: function (direction) {        
111        var firstVisibleImage = this.firstVisibleImage();
112        var offset = Math.round($(firstVisibleImage).position().left);
113        var nextScrollPosition = this.currentScrollPosition() + offset;        
114        switch (direction) {
115            case "left":                
116                nextScrollPosition -= this.scrollboxWidth();
117                if (($(firstVisibleImage).outerWidth(true) - offset) < 0) {
118                    nextScrollPosition -= $(firstVisibleImage).outerWidth(true);
119                }
120                break;
121            case "right":                
122                nextScrollPosition += this.scrollboxWidth();
123                if (offset > 0) {
124                    nextScrollPosition -= $(firstVisibleImage).outerWidth(true);
125                }
126                break;
127        }
128        return nextScrollPosition;
129    },
130
131    // Triggers the animation
132    animateScroll: function (direction) {
133        resetFocusedImg();
134        var scroller = this;
135        setTimeout(function () {
136            scroller.scrollbox.animate({
137                scrollLeft: scroller.nextScrollPosition(direction)
138            }, this.scrollboxWidth())
139        }.bind(this), 50);
140    },
141
142    hideScrollControl: function (control) {
143        control.addClass("invisible");
144    },
145
146    showScrollControl: function (control) {
147        control.removeClass("invisible");
148    },
149
150    scrollControlVisibility: function (control) {
151        return control.hasClass("invisible");
152    },
153
154    scrollAtZero: function () {
155        return this.currentScrollPosition() == 0;
156    },
157
158    scrollAtMax: function () {
159        return this.currentRightPosition() >= -1;
160    },
161
162    evaluateControlVisibility: function () {
163        var left = this.leftScrollControl;
164        var right = this.rightScrollControl;
165        var leftIsInvisible = this.scrollControlVisibility(left);
166        var rightIsInvisible = this.scrollControlVisibility(right);
167
168        if (this.scrollAtZero()) this.hideScrollControl(left);
169        if (this.scrollAtMax()) this.hideScrollControl(right);
170        if (!this.scrollAtZero() && leftIsInvisible) this.showScrollControl(left);
171        if (!this.scrollAtMax() && rightIsInvisible) this.showScrollControl(right);
172    }
173};
174
175// End HorizontalScroller.prototype
176
177var scrollers = {};
178
179// Detects scrollers in the DOM
180function detectScrollers() {
181    return $.map($(".horiz-scroll"), function (scroller) {
182        return $(scroller).attr("id");
183    });
184}
185
186// Generates a new HorizontalScroller for each scroller in DOM
187function mapScrollers(scrollerIds) {
188    scrollerIds.forEach(function (elem, i, arr) {
189        var scroller = "#" + elem + " .scroll-images";
190        scrollers[elem] = new HorizontalScroller($(scroller));
191    });
192}
193
194// Gets the scroll direction to pass to animation function
195function getScrollDirection(button) {
196    return (button.hasClass("left-scroll")) ? "left" : "right"
197}
198
199// Triggers the scroll animation for specific scroller
200// in a specific direction
201function triggerAnimation(button) {
202    var scrollId = button.closest(".horiz-scroll").attr("id");
203    var scrollDirection = getScrollDirection(button);
204    scrollers[scrollId].animateScroll(scrollDirection);
205}
206
207// Scroll buttons listener
208function listenForScroll() {
209    $(".left-scroll, .right-scroll").on("click", function () {
210        var button = $(this);
211        triggerAnimation(button);
212    });
213}
214
215function resetFocusedImg() {
216    $(".focused").removeClass("focused");
217}
218
219// listener for click, slides up
220var horizontalScrollImg = $(".horiz-scroll .scroll-images .img");
221horizontalScrollImg.on("click", function () {
222    if (!$(this).hasClass("focused"))
223        resetFocusedImg();
224    $(this).toggleClass("focused");
225});
226
227// Registers scrollers and initiates listeners 
228function scrollerInit() {
229    var scrollerIds = detectScrollers();
230    mapScrollers(scrollerIds);
231    listenForScroll();
232}

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.