PageSourceSearch

https://www.tulsastatefair.com/Events/JS/widgets/cssScroller.js?sv=8.6.3.9.0

js tulsastatefair.com collected 2026-09-24 20:17:21 UTC 13,420 bytes, 347 lines download raw bytes

1extend(saffire, {
2  widgets: {
3    sponsors: function(el, opts) {
4      var $el = el;
5      var widget = {};
6      var defaults = {
7        bw: false,
8        contentType: 'application/json; charset=utf-8',
9        dataType: 'json',
10        legacy: true,
11        rotate: true,
12        timePerSponsor: 2.5,
13        trackClick: true,
14        imageWidthRestriction: 600,
15        defaultDirection: 'left',
16        playPauseButtons: true,
17        sponsorWidgetLoaded: function(data, hasData) {}
18      };
19
20      opts = extend(defaults, opts);
21
22      /**
23       * Retreives data for the widget.
24       * @protected
25       */
26      widget.data = saffire.utils.getWidgetData(opts);
27      widget.data.then(function(res) {
28        widget.items = res.Sponsors || res.Slides;
29        (widget.items.length < 1) ? widget.noData(res) : widget.setup(res);
30      });
31
32      /**
33       * Sets up the HTML for the Widget.
34       * @protected
35       */
36      widget.setup = function(data) {
37        $el.addClass('loading');
38        var sponsorTitle = data.SponsorText || data.WidgetModuleItemDisplayName || null;
39        var majorSponsorTitle = data.MajorSponsorText || null;
40        var optionClass = !opts.rotate ? ' never-animate' : '';
41
42        // convert image links to SSL if the page is encrypted
43        PAGESSL ? convertSources() : null;
44
45        // initialize Major sponsor counter
46        widget.majorSponsors = 0;
47
48        // build contatiners
49        widget.$container = $('<div class="sponsorWidgetContainer'+ optionClass +'"/>');
50        widget.$logoContainer = $('<div class="sponsorCarouselImageContainer"/>');
51        widget.$majorSponsorContainer = $('<div class="majorSponsor"/>');
52
53        // if this is a legacy client then put a container in the DOM to simply get it's css height (yuck)
54        opts.legacy ? $el.append('<div id="sponsorCarouselContainer" class="sponsorCarouselContainer" style="display:none"/>') : null;
55
56        // build the arrows
57        widget.$leftArrow = $('<span class="sponsorArrow" id="sponsorArrowLeft" role="button" tabindex="0" aria-disabled="true" aria-label="Change sponsor scroll direction - left"><span></span></span>');
58        widget.$rightArrow = $('<span class="sponsorArrow" id="sponsorArrowRight" role="button" tabindex="0" aria-disabled="false" aria-label="Change sponsor scroll direction - right"><span></span></span>');
59
60        // Iterate through the data and build image HTML for each sponsor
61        for (var i = 0; i < widget.items.length; i++) {
62          var $sponsor = widget.buildSponsor(widget.items[i]);
63          if (widget.items[i].IsMajorSponsor) {
64            widget.$majorSponsorContainer.append($sponsor);
65            widget.majorSponsors++;
66          } else {
67            widget.$logoContainer.append($sponsor);
68          }
69        }
70
71        // Add titles to the widget if they are present
72        if (sponsorTitle) {
73          widget.sponsorTitle = $('<div id="sponsorsTitleContainer"><h1 class="homepageh1">'+ sponsorTitle +'</h1></div>');
74          $el.append(widget.sponsorTitle);
75        }
76        if (widget.majorSponsors > 0 && majorSponsorTitle) {
77          widget.majorSponsorTitle = $('<div id="majorSponsorTitleContainer"><h1 class="homepageh1">'+ majorSponsorTitle +'</h1></div>');
78          // widget.$majorSponsorContainer.prepend(widget.majorSponsorTitle);
79          $el.append(widget.majorSponsorTitle);
80        }
81
82        // Add the sponsors to the DOM
83        (widget.majorSponsors > 0) ? $el.append(widget.$majorSponsorContainer) : $el.addClass('no-major-sponsor');
84        widget.$container.append(widget.$logoContainer);
85        opts.rotate ? widget.$container.append(widget.$logoContainer.clone()) : null;
86        $el.append(widget.$container);
87        $el.append(widget.$leftArrow).append(widget.$rightArrow);
88
89        // Add play / pause buttons for animation, (for ADA requirements)
90        if (opts.playPauseButtons) {
91          widget.$container.prepend('<div class="sponsor-controls-container"><button type="button" class="sponsor-playpause-btn" tabindex="0" aria-live="assertive"></button></div>');
92        }
93
94        // initialize widget
95        widget.initialize();
96      }
97
98      /**
99       * initalzes width calculations, click events, and starts animations
100       * @public
101       */
102      widget.initialize = function() {
103        var imgs = $el.find('.logo-image');
104        var count = widget.items.length;
105        widget.direction = widget.direction || opts.defaultDirection;
106
107        //set the direction for the widget
108        widget.$container.addClass('animate-' + widget.direction);
109
110        // attach click events to the arrows
111        widget.$leftArrow.on('click keydown', function(event) {
112          if (event.key === 'Enter' || event.type === 'click') {
113            animate('left');
114          }
115        });
116        widget.$rightArrow.on('click keydown', function(event) {
117          if (event.key === 'Enter' || event.type === 'click') {
118            animate('right');
119          }
120        });
121
122        // attach click events to the sponsor play pause button
123        $('.sponsor-playpause-btn').click(function() {
124          const $playpausebtn = $(this); 
125          const $container = widget.$container; 
126
127          // Toggle the paused state on the widget container
128          $container.toggleClass('sponsors-paused');
129
130          // Check if the ticker is paused or playing and update the button's ARIA attributes accordingly
131          if ($container.hasClass('sponsors-paused')) {
132            // If paused
133            $playpausebtn.attr('aria-label', 'Resume the sponsor ticker');
134            $playpausebtn.attr('aria-pressed', 'false');
135          } else {
136            // If playing (not paused)
137            $playpausebtn.attr('aria-label', 'Pause the sponsor ticker');
138            $playpausebtn.attr('aria-pressed', 'true');
139          }
140        });
141
142        // wait until all of the images have loaded befor initializing
143        imgs.load(function() {
144          count--;
145          if (!count) {
146            // images are loaded for this widget
147            // Find the duration of the animation
148            var duration = {
149              '-webkit-animation-duration': opts.timePerSponsor * widget.items.length + 's',
150              'animation-duration': opts.timePerSponsor * widget.items.length + 's'
151            }
152
153            widget.$container.css(duration);
154
155            // done loading...
156            $el.removeClass('loading');
157
158            // find DOM widths and start animationLogic
159            widget.findWidths();
160            // wait 500ms and check once more
161            setTimeout(function () {
162              widget.findWidths();
163            }, 500);
164
165            opts.sponsorsInitialized ? opts.sponsorsInitialized() : null;
166            opts.sponsorWidgetLoaded(widget, true); // callback if needed for the constructor
167
168
169          // Set up the intersection observer
170          const observer = new IntersectionObserver(function (entries, observer) {
171              entries.forEach(function (entry) {
172                  const $link = $(entry.target).closest('a'); // Find the closest <a> element
173                  
174                  if (entry.isIntersecting) {
175                      // When image is in view, make it tabbable
176                      $link.attr('tabindex', '0');
177                  } else {
178                      // When image is out of view, remove it from the tab order
179                      $link.attr('tabindex', '-1');
180                  }
181              });
182          }, { threshold: 0.5 }); // 50% of the image should be in view to be tabbable
183
184          // Select all image links in the carousel and observe each one
185          $('.sponsorCarouselImageContainer a').each(function () {
186              observer.observe(this); // Observe each <a> element
187          });
188
189          }
190        }).filter(function() {return this.complete;}).load();
191
192      }
193
194      /**
195       * finds the width of the widget and sponsorCarouselImageContainer
196       * @protected
197       */
198      widget.findWidths = function() {
199        widget.width = $el.width();
200        widget.sponsorsWidth = widget.$logoContainer.width();
201        opts.rotate ? animationLogic() : null;
202      }
203
204      /**
205       * Determines if the wdiget should animate or not
206       * @protected
207       */
208      function animationLogic() {
209        const $playpausebtn = widget.$container.find('.sponsor-playpause-btn');
210        if ( widget.sponsorsWidth >= widget.width ) {
211          widget.$container.addClass('animate');
212          $playpausebtn.attr('aria-label', 'Pause the sponsor ticker');
213          $playpausebtn.attr('aria-pressed', 'true');
214        } else {
215          widget.$container.removeClass('animate');
216          $playpausebtn.attr('aria-label', 'Resume the sponsor ticker');
217          $playpausebtn.attr('aria-pressed', 'false');          
218        }
219      }
220
221      /**
222       * Arrow movement function
223       * @public
224       */
225      function animate(direction) {
226        if (widget.direction !== direction) {
227          widget.$container.addClass('changing-direction');
228          setTimeout(function(){
229            widget.$container.removeClass('animate-' + widget.direction)
230            widget.$container.removeClass('changing-direction');
231            widget.direction = direction;
232            widget.$container.addClass('animate-' + widget.direction);
233
234            if (widget.direction == 'left') {
235              $('#sponsorArrowLeft').attr('aria-disabled', 'true');
236              $('#sponsorArrowRight').attr('aria-disabled', 'false');              
237            } else {
238              $('#sponsorArrowLeft').attr('aria-disabled', 'false');
239              $('#sponsorArrowRight').attr('aria-disabled', 'true');  
240            }            
241          }, 500);
242        }
243      }
244
245
246      /**
247       * Constructs each image and container.
248       * @protected
249       */
250      widget.buildSponsor = function (sponsorData) {
251        var link = sponsorData.URL || null;
252        var spanClass = sponsorData.IsMajorSponsor ? 'majorSponsorImage' : 'sponsorCarouselImage';
253        var spanID = sponsorData.IsMajorSponsor && opts.legacy ? 'id="majorSponsorImageContainer"' : '';
254        // var target = sponsorData.URLOpenInANewWindow ? '_blank' : '_self'; // URLOpenInANewWindow not in widget data or option in spark? *shrug*
255        var target = '_blank';
256        var title = sponsorData.Name || sponsorData.Title;
257        var imageAlternateText = "";
258
259        if (sponsorData.ImageAlternateText != null) {
260            imageAlternateText = (sponsorData.ImageAlternateText);
261        }
262
263        var trackingStr = opts.trackClick ? 'onclick="ga(\'send\', \'event\', {eventCategory: \'Sponsors Link\', eventAction: \'Click\', eventLabel: \'' + title + '\'});"' : '';
264
265        if (opts.imageWidthRestriction) {
266          sponsorData.ImageWithPath = sponsorData.ImageWithPath.concat('&w='+ opts.imageWidthRestriction);
267        }
268
269        if (opts.legacy) {
270          var height = $el.children('#sponsorCarouselContainer').height() || $el.children('.sponsorCarouselContainer').height();
271          sponsorData.ImageWithPath = sponsorData.ImageWithPath.concat('&h='+ height);
272        }
273
274        var $image = $('<span ' + spanID + ' class="' + spanClass + '"><img class="logo-image" src="' + sponsorData.ImageWithPath + '&bw=' + opts.bw + '" alt="' + imageAlternateText + '"/></span>');
275
276        if (link != null) {
277          var sponsName = sponsorData.Name ? sponsorData.Name : '';
278          var $anchor = $('<a href="' + link + '" aria-label="visit sponsor: '+sponsName+'" target="' + target + '" ' + trackingStr + ' />');
279        } else {
280          var $anchor = $('<a href="javascript:void(0)" class="no-link" />');
281        }
282
283        $anchor.append($image);
284        return $anchor;
285      }
286
287
288      /**
289       * Converts the image links in widget.items to be SSL call.
290       * @protected
291       */
292       function convertSources() {
293        for (var i = 0; i < widget.items.length; i++) {
294          widget.items[i].ImageWithPath = widget.items[i].ImageWithPath.replace(/^http:\/\//i,'https://');
295        }
296       }
297
298
299      /**
300       * There were'nt any sponsors
301       * @protected
302       */
303       widget.noData = function(data) {
304        var id =  $el.attr('id');
305        console.log("Service returned no data for " + id, data);
306        $('body').addClass(id + '-no-data');
307        opts.sponsorWidgetLoaded(widget, false);
308       };
309
310      /**
311       * Handle resize event
312       * @protected
313       */
314      if (opts.rotate) {
315        window.addEventListener("resize", sponsorResize);
316      };
317
318      function sponsorResize() {
319        widget.findWidths();
320      };
321
322
323      /**
324       * public API.
325       * @public
326       */
327      return {
328        a: function() {
329          alert($el);
330        },
331        data: widget.data,
332        moveLeft: function() {
333          animate('left');
334        },
335        moveRight: function() {
336          animate('right');
337        },
338        options: opts,
339        reinitialize: function() {
340          widget.initialize();
341        }
342      }
343
344    }
345
346  }
347});

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.