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.