PageSourceSearch

https://voyageaustin.com/wp-content/plugins/theia-post-slider/js/tps.js?ver=1.9.1

js voyageaustin.com collected 2026-10-01 10:46:24 UTC 33,447 bytes, 958 lines download raw bytes

1/*
2 * Copyright 2012-2015, Theia Post Slider, WeCodePixels, http://wecodepixels.com
3 */
4var tps = tps || {};
5tps.slideshowsOnPage = 0;
6tps.createSlideshowDefaults = {
7    slideContainer: '',
8    nav: [],
9    navText: '%{currentSlide} of %{totalSlides}',
10    helperText: '',
11    defaultSlide: 0,
12    transitionEffect: 'none',
13    transitionSpeed: 400,
14    keyboardShortcuts: false,
15    scrollAfterRefresh: true,
16    numberOfSlides: 0, // Total number of slides, including the ones not loaded.
17    slides: [],
18    useSlideSources: false,
19    themeType: 'classic',
20    prevPost: null,
21    nextPost: null,
22    prevText: null,
23    nextText: null,
24    buttonWidth: 0,
25    prevText_post: null,
26    nextText_post: null,
27    buttonWidth_post: 0,
28    onShowPost: null,
29    postUrl: null,
30    postId: null,
31    refreshAds: false,
32    refreshAdsEveryNSlides: 1,
33    adRefreshingMechanism: 'javascript',
34    siteUrl: '/',
35    loopSlides: false,
36    scrollTopOffset: 0
37};
38tps.createSlideshow = function (options) {
39    var i, j;
40    var me = this;
41    var $ = jQuery;
42
43    // Merge options with defaults and sanitize values.
44    me.options = $.extend(tps.createSlideshowDefaults, options);
45    for (i in me.options) {
46        // If the default is a number and the option is a string, then convert it to a number if possible.
47        if (!isNaN(tps.createSlideshowDefaults[i]) && (typeof me.options[i] == 'string')) {
48            var value = parseFloat(me.options[i]);
49            if (!isNaN(value)) {
50                me.options[i] = value;
51            }
52        }
53    }
54
55    me.slides = [];
56    me.slideContainer = $(me.options.slideContainer);
57    if (me.slideContainer.length == 0) {
58        return null;
59    }
60
61    tps.slideshowsOnPage++;
62    me.navEl = [];
63    for (i = 0; i < me.options.nav.length; i++) {
64        var e = $(me.options.nav[i]).get();
65        for (j = 0; j < e.length; j++) {
66            me.navEl.push({
67                container: $(e[j])
68            });
69        }
70    }
71
72    // Initialize variables.
73    me.currentPostId = me.options.postId;
74    me.isLoading = false;
75    me.slidesSinceLastAdRefresh = 0;
76
77    // Remote loading queue.
78    me.remoteLoadingQueue = async.queue(function (task, callback) {
79        callback();
80    }, 1);
81
82    // The current slide.
83    me.currentSlide = null;
84
85    // The slide that is currently displayed. This may lag behind "me.currentSlide" because of the animations.
86    me.currentlyDisplayedSlide = null;
87
88    // The number of animations that are currently running.
89    me.animations = 0;
90
91    // A queue that is executed when no animation is running.
92    me.semaphore = 0;
93    me.asyncQueue = async.queue(function (task, callback) {
94        callback();
95    }, 1);
96
97    me.incrementSemaphore = function () {
98        me.asyncQueue.pause();
99        me.semaphore++;
100    };
101
102    me.decrementSemaphore = function () {
103        me.semaphore--;
104        if (me.semaphore == 0) {
105            me.asyncQueue.resume();
106        }
107    };
108
109    // Initialization function
110    me.init = function () {
111        var i;
112
113        // Load scroll position, if available.
114        me.loadScrollTop();
115
116        // Get slides from me.options.slides
117        for (i in me.options.slides) {
118            if ('content' in me.options.slides[i]) {
119                if (me.options.useSlideSources) {
120                    me.options.slides[i].source = me.options.slides[i].content;
121                }
122
123                me.options.slides[i].content = $('<div>').html(me.options.slides[i].content);
124            }
125
126            me.slides[i] = me.options.slides[i];
127        }
128        me.options.slides = null;
129
130        // Get slides from HTML. The first slide is considered the default one, while the rest are detached.
131        me.slideContainer.children().each(function (index, slide) {
132            index = me.options.defaultSlide + index;
133            slide = $(slide);
134            me.slides[index] = me.slides[index] || {};
135            me.slides[index].title = document.title;
136            me.slides[index].permalink = document.location.href;
137            me.slides[index].content = slide;
138
139            if (index != me.options.defaultSlide) {
140                slide.detach();
141            }
142        });
143
144        // Count the slides.
145        me.numberOfSlides = me.options.numberOfSlides;
146
147        // Setup the navigation bars.
148        for (i = 0; i < me.navEl.length; i++) {
149            var navEl = me.navEl[i];
150            navEl.text = navEl.container.find('._text');
151            navEl.prev = navEl.container.find('._prev')
152                .click(function (me) {
153                    return function (event) {
154                        me.onNavClick(this, 'prev', event);
155                    }
156                }(me));
157            navEl.next = navEl.container.find('._next')
158                .click(function (me) {
159                    return function (event) {
160                        me.onNavClick(this, 'next', event);
161                    }
162                }(me));
163
164            navEl.title = navEl.container.find('._title');
165
166            // Get the default slide's title. The title will be the same for all navigation bars, so get it only from the first.
167            if (i === 0) {
168                me.slides[me.options.defaultSlide].shortCodeTitle = navEl.title.html();
169            }
170
171            /*
172             Add _active class on mousedown. This is a fix for IE and Opera which don't match :active on container elements.
173             Also, return false to prevent double click context menu in Opera.
174             */
175            navEl.container.find('._prev, ._next')
176                .mousedown(function () {
177                    $(this).addClass('_active');
178                })
179                .mouseup(function () {
180                    $(this).removeClass('_active');
181                });
182        }
183
184        // Skip loading the slide if we're not going to display another one anyway.
185        if (me.numberOfSlides == 1 || (me.options.refreshAds && me.options.adRefreshingMechanism == 'page' && me.options.refreshAdsEveryNSlides <= 1)
185) {
186            me.currentSlide = 0;
187        }
188        else {
189            // Show the first slide
190            me.setSlide(me.options.defaultSlide);
191
192            // Add history handler.
193            var history = window.History;
194            if (history.enabled) {
195                history.Adapter.bind(window, 'statechange', function (me) {
196                    return function () {
197                        var state = History.getState();
198                        if (state.data.currentPostId != undefined) {
199                            if (state.data.currentSlide != undefined) {
200                                me.setSlide(state.data.currentSlide);
201                            }
202                            else {
203                                me.setSlide(me.options.defaultSlide);
204                            }
205                        }
206                    };
207                }(me));
208            }
209        }
210
211        // Enable keyboard shortcuts
212        if (me.options.keyboardShortcuts) {
213            $(document).keydown(function (me) {
214                return function (e) {
215                    // Disable shortcut if there is more than one slideshow on the page.
216                    if (tps.slideshowsOnPage > 1) {
217                        return true;
218                    }
219
220                    // Disable shortcut if the target element is editable (input boxes, textareas, etc.).
221                    if (
222                        this !== e.target &&
223                        (
224                        /textarea|select/i.test(e.target.nodeName) ||
225                        e.target.type === "text" ||
226                        (
227                        $(e.target).prop &&
228                        $(e.target).prop('contenteditable') == 'true'
229                        )
230                        )
231                    ) {
232                        return true;
233                    }
234
235                    switch (e.which) {
236                        case 37:
237                            me.navEl[0].prev[0].click();
238                            return false;
239
240                        case 39:
241                            me.navEl[0].next[0].click();
242                            return false;
243                    }
244
245                    return true;
246                };
247            }(me));
248        }
249    };
250
251    // Load slides remotely
252    me.loadSlides = function (slides, callback) {
253        me.remoteLoadingQueue.push({name: ''}, function (me, slides, callback) {
254            return function (err) {
255                // Check if the slides are already loaded.
256                var allSlidesAreLoaded = true;
257                for (var i in slides) {
258                    if (!(slides[i] in me.slides) || !('content' in me.slides[slides[i]])) {
259                        allSlidesAreLoaded = false;
260                        break;
261                    }
262                }
263                if (allSlidesAreLoaded) {
264                    if (callback) {
265                        callback();
266                    }
267                    return;
268                }
269
270                // Load the slides and don't load anything else in the meantime.
271                me.remoteLoadingQueue.concurrency = 0;
272                $.ajax({
273                    dataType: 'json',
274                    data: {
275                        theiaPostSlider: 'get-slides',
276                        postId: me.currentPostId,
277                        slides: slides
278                    },
279                    url: me.options.siteUrl,
280                    success: function (me) {
281                        return function (data) {
282                            if (!data) {
283                                return;
284                            }
285                            if (data.postId == me.currentPostId) {
286                                // Add each slide.
287                                for (var i in data.slides) {
288                                    if (!(i in me.slides)) {
289                                        me.slides[i] = {};
290                                    }
291
292                                    // Add content.
293                                    if ('content' in data.slides[i]) {
294                                        if (me.options.useSlideSources) {
295                                            data.slides[i].source = data.slides[i].content;
296                                        }
297
298                                        data.slides[i].content = $('<div>').html(data.slides[i].content);
299                                    }
300
301                                    // Overwrite old data with new data.
302                                    for (var j in data.slides[i]) {
303                                        me.slides[i][j] = data.slides[i][j];
304                                    }
305                                }
306                            }
307                            else {
308                                console.error('Received AJAX results for a different post ID.');
309                            }
310                        };
311                    }(me),
312                    complete: function (me, callback) {
313                        return function () {
314                            if (callback) {
315                                callback();
316                            }
317                            me.remoteLoadingQueue.concurrency = 1;
318                            me.remoteLoadingQueue.push({});
319                        };
320                    }(me, callback)
321                });
322            };
323        }(me, slides, callback));
324    };
325
326    // Set the current slide.
327    me.setSlide = function (index, isCallback) {
328        if (me.isLoading == true && isCallback != true) {
329            return;
330        }
331
332        // Is the slide already displayed?
333        if (me.currentSlide == index) {
334            return;
335        }
336
337        // Do we need to refresh the ads by refreshing the entire page?
338        if (me.needToRefreshPage() && index in me.slides) {
339            me.saveScrollTop();
340            window.location = me.slides[index].permalink;
341
342            return;
343        }
344
345        // Fire events.
346        $(document).trigger('theiaPostSlider.willChangeSlide', [index]);
347
348        // Is the slide not yet loaded?
349        if (!me.isSlideLoaded(index)) {
350            if (!isCallback) {
351                me.showLoading();
352                me.loadSlides([index], function (me, index) {
353                    return function () {
354                        me.hideLoading();
355                        me.setSlide(index, true);
356                    }
357                }(me, index));
358
359                return;
360            }
361            else {
362                // The slide could not be loaded via AJAX. Abort.
363                console.error("The slide could not be loaded via AJAX.");
364                return;
365            }
366        }
367
368        var previousSlide = me.currentSlide;
369        me.currentSlide = index;
370
371        if (previousSlide != null) {
372            // Scroll the window up, if the beginning of the slide is out-of-view.            
373            // Get the lowest offset.top
374            var scrollTop = me.slideContainer.offset().top;
375            for (var i = 0; i < me.navEl.length; i++) {
376                scrollTop = Math.min(scrollTop, me.navEl[i].container.offset().top);
377            }
378            scrollTop += me.options.scrollTopOffset;
379            if ($(window).scrollTop() > scrollTop) {
380                $('body,html').animate({scrollTop: scrollTop});
381            }
382        }
383
384        // Set the title text.
385        me.updateTitleText();
386
387        // Change URL, but only if this isn't the first slide set (i.e. the default slide).
388        var history = window.History;
389        if (history.enabled) {
390            var url = me.slides[me.currentSlide].permalink;
391            if (url && previousSlide !== null) {
392                var f;
393                if (url == window.location) {
394                    f = history.replaceState;
395                }
396                else {
397                    f = history.pushState;
398                }
399                f({
400                    currentSlide: index,
401                    currentPostId: me.currentPostId
402                }, me.slides[me.currentSlide].title, url);
403            }
404        }
405
406        // Show the slide.
407        me.asyncQueue.push({name: ''}, me.showSlide);
408
409        // Refresh ads using JavaScript.
410        if (previousSlide != null) {
411            if (me.options.refreshAds) {
412                me.slidesSinceLastAdRefresh++;
413
414                if (me.slidesSinceLastAdRefresh >= me.options.refreshAdsEveryNSlides) {
415                    me.slidesSinceLastAdRefresh = 0;
416
417                    if (me.options.adRefreshingMechanism == 'javascript') {
418                        var p = null;
419
420                        if (typeof pubService === 'undefined') {
421                            if (typeof googletag !== 'undefined') {
422                                p = googletag.pubads();
423                            }
424                        }
425                        else {
426                            p = pubService;
427                        }
428
429                        if (p) {
430                            p.refresh();
431                        }
432
433                        $(document).trigger('theiaPostSlider.refreshAds');
434                    }
435                }
436            }
437        }
438
439        // Set the navigation bars.
440        me.updateNavigationBars();
441
442        // Preload, but only if we don't have to refresh the page immediately after.
443        if (
444            !(
445            me.options.refreshAds &&
446            me.slidesSinceLastAdRefresh + 1 >= me.options.refreshAdsEveryNSlides &&
447            me.options.adRefreshingMechanism == 'page'
448            )
449        ) {
450            // Direction is either +1 if the user is browsing forward (i.e. using the "next" button), or -1 otherwise.
451            var direction;
452            if (previousSlide == null) {
453                direction = 1;
454            }
455            else if (me.currentSlide == 0 && previousSlide == me.numberOfSlides - 1) {
456                direction = 1;
457            }
458            else if (me.currentSlide == me.numberOfSlides - 1 && previousSlide == 0) {
459                direction = -1;
460            }
461            else {
462                direction = me.currentSlide - previousSlide;
463                direction = Math.max(Math.min(direction, 1), -1);
464            }
465
466            var slideToPreload = me.currentSlide + direction;
467
468            // If the loop-slides settings is activated, also preload the first/last slide when applicable.
469            if ( slideToPreload == -1 && me.options.loopSlides ) {
470                slideToPreload = me.numberOfSlides - 1;
471            }
472            else if ( slideToPreload == me.numberOfSlides && me.options.loopSlides ) {
473                slideToPreload = 0;
474            }
475
476            if (
477                slideToPreload >= 0 &&
478                slideToPreload < me.numberOfSlides && !me.isSlideLoaded((slideToPreload))
479            ) {
480                me.loadSlides([slideToPreload]);
481            }
482
483        }
484
485        // Set up touch events.
486        if (typeof Hammer !== 'undefined') {
487            me.previousTouch = 0;
488            me.minimumTimeBetweenGestures = 500;
489            var hammertime = new Hammer(me.slideContainer[0]);
490            hammertime
491                .on('swipeleft', function () {
492                    var t = (new Date).getTime();
493                    if (t - me.minimumTimeBetweenGestures >= me.previousTouch) {
494                        me.setNext();
495                        me.previousTouch = t;
496                    }
497                })
498                .on('swiperight', function () {
499                    var t = (new Date).getTime();
500                    if (t - me.minimumTimeBetweenGestures >= me.previousTouch) {
501                        me.setPrev();
502                        me.previousTouch = t;
503                    }
504                });
505        }
506    };
507
508    // Show (display) the current slide using the chosen animation.
509    me.showSlide = function () {
510        // Don't do anything if the current slide is already shown.
511        if (me.currentlyDisplayedSlide == me.currentSlide) {
512            return;
513        }
514
515        // Track the pageview if this isn't the first slide displayed.
516        if (me.currentlyDisplayedSlide != null && me.slides[me.currentSlide]['permalink']) {
517            // URL Path
518            var path = me.slides[me.currentSlide]['permalink'].split('/');
519            if (path.length >= 4) {
520                path = '/' + path.slice(3).join('/');
521
522                // Google Analytics by Yoast, which renames the "ga" variable.
523                if (typeof __gaTracker !== 'undefined') {
524                    __gaTracker('send', 'pageview', path);
525                }
526                // Google Analytics (Analytics.js).
527                else if (typeof ga !== 'undefined') {
528                    ga('send', 'pageview', path);
529                }
530                // Google Analytics (ga.js, deprecated).
531                else if (typeof _gaq !== 'undefined' && typeof _gaq.push !== 'undefined') {
532                    _gaq.push(['_trackPageview', path]);
533                }
534                // Google Analytics Traditional.
535                else if (typeof pageTracker !== 'undefined' && typeof pageTracker._trackPageview !== 'undefined') {
536                    pageTracker._trackPageview(path);
537                }
538
539                // Piwik
540                if (typeof piwikTracker !== 'undefined' && typeof piwikTracker.trackPageView !== 'undefined') {
541                    piwikTracker.trackPageView(path);
542                }
543
544                // StatCounter
545                if (typeof sc_project !== 'undefined' && typeof sc_security !== 'undefined') {
546                    var img = new Image();
547                    img.src = '//c.statcounter.com/' + sc_project + '/0/' + sc_security + '/1/';
548                }
549
550                // Quantcast
551                if (typeof _qacct !== 'undefined') {
552                    var img = new Image();
553                    img.src = '//pixel.quantserve.com/pixel/' + _qacct + '.gif';
554                }
555            }
556        }
557
558        var previousIndex = me.currentlyDisplayedSlide;
559        me.currentlyDisplayedSlide = me.currentSlide;
560
561        me.createSlideContentFromSource(me.slides[me.currentSlide]);
562
563        // Change the slide while applying a certain effect/animation.
564        var animationsQueue = tps.transitions[me.options.transitionEffect](me, previousIndex, me.currentlyDisplayedSlide);
565
566        // Execute all "attachAnimation" methods before starting any animation.
567        // Otherwise, we might get a race condition when one animation finishes before others are started,
568        // thus triggering unwanted events before all animations have ended.
569        for (var i = 0; i < animationsQueue.length; i++) {
570            me.incrementSemaphore();
571        }
572
573        // This will be called after all animations finish, before any other items in the queue.
574        if (previousIndex !== null) {
575            me.asyncQueue.unshift({name: ''}, function (me, previousIndex) {
576                return function () {
577                    me.onRemovedSlide(previousIndex);
578                }
579            }(me, previousIndex));
580        }
581
582        // Start all animations.
583        for (var i = 0; i < animationsQueue.length; i++) {
584            animationsQueue[i]();
585        }
586    };
587
588    me.createSlideContentFromSource = function (slide) {
589        if (!('content' in slide) && ('source' in slide)) {
590            slide.content = $('<div>').html(slide.source);
591
592            if (false == me.options.useSlideSources) {
593                delete slide.source;
594            }
595        }
596    };
597
598    me.isSlideLoaded = function (index) {
599        if (!(index in me.slides)) {
600            return false;
601        }
602
603        // Only if this isn't the first slide.
604        if (me.currentlyDisplayedSlide !== null && me.options.useSlideSources && !('source' in me.slides[index])) {
605            return false;
606        }
607
608        if (!(('content' in me.slides[index]) || ('source' in me.slides[index]))) {
609            return false;
610        }
611
612        return true;
613    };
614
615    // Function that is called right after a new slide has been added to the DOM, and right before the animation (if available) has started.
616    me.onNewSlide = function () {
617        // "BJ Lazy Load" plugin.
618        $(".lazy-hidden").not(".data-lazy-ready").one("scrollin.bj_lazy_load", {
619            distance: 200
620        }, function () {
621            var b = $(this),
622                d = b.attr("data-lazy-type");
623            if (d == "image") {
624                b.hide().attr("src", b.attr("data-lazy-src")).removeClass("lazy-hidden").fadeIn()
625            } else if (d == "iframe") {
626                b.replaceWith(c(b.attr("data-lazy-src")))
627            }
628        }).addClass("data-lazy-ready");
629
630        // "Lazy Load" plugin.
631        var events = $('body').data('events');
632        if (events && events['post-load']) {
633            for (var i = 0; i < events['post-load'].length; i++) {
634                if (events['post-load'][i].handler.name == 'lazy_load_init') {
635                    events['post-load'][i].handler();
636                }
637            }
638        }
639
640        // WordPress [audio] and [video] shortcodes.
641        if (typeof _wpmejsSettings !== 'undefined') {
642            $('.wp-audio-shortcode, .wp-video-shortcode').mediaelementplayer(_wpmejsSettings);
643        }
644
645        // Instagram embeds.
646        if (typeof instgrm !== 'undefined' && typeof instgrm.Embeds !== 'undefined' && typeof instgrm.Embeds.process !== 'undefined') {
647            instgrm.Embeds.process();
648        }
649
650        // Fire events.
651        $(document).trigger('theiaPostSlider.changeSlide', [me.currentSlide]);
652    };
653
654    // Function that is called right after a slide has been removed from the DOM.
655    me.onRemovedSlide = function (slideId) {
656        if (me.options.useSlideSources) {
657            me.slides[slideId].content.remove();
658            delete me.slides[slideId].content;
659        }
660    };
661
662    // Update the title text.
663    me.updateTitleText = function () {
664        var shortCodeTitle = me.slides[me.currentSlide].shortCodeTitle;
665        if (!shortCodeTitle) {
666            shortCodeTitle = '<span class="_helper">' + me.options['helperText'] + '</span>';
667        }
668        for (i = 0; i < me.navEl.length; i++) {
669            me.navEl[i].title.html(shortCodeTitle);
670        }
671    };
672
673    // Update the navigation bar's text and buttons.
674    me.updateNavigationBars = function () {
675        for (var i = 0; i < me.navEl.length; i++) {
676            var navEl = me.navEl[i];
677            var navText;
678            if (me.numberOfSlides == 1) {
679                navText = '';
680            }
681            else {
682                navText = me.options.navText;
683                navText = navText.replace('%{currentSlide}', me.currentSlide + 1);
684                navText = navText.replace('%{totalSlides}', me.numberOfSlides);
685            }
686            navEl.text.html(navText);
687
688            // Update buttons.
689            me.updateNavigationBarButton(navEl, false);
690            me.updateNavigationBarButton(navEl, true);
691        }
692    };
693
694    // Update a button from a navigation bar.
695    me.updateNavigationBarButton = function (navEl, direction) {
696        var width,
697            html1 = '',
698            html2 = '',
699            html3 = '',
700            href,
701            directionName = direction ? 'next' : 'prev',
702            buttonEl = navEl[directionName];
703
704        if (me.options.themeType == 'font') {
705            width = 0;
706            html2 = me.options[directionName + 'FontIcon'];
707
708            if (direction == false) {
709                if (me.options.prevText_post) {
710                    if (me.currentSlide == 0) {
711                        html3 = me.options.prevText_post;
712                    } else {
713                        html3 = me.options.prevText;
714                    }
715                } else {
716                    html3 = me.options.prevText;
717                }
718            } else {
719                if (me.options.nextText_post) {
720                    if (me.currentSlide == me.numberOfSlides - 1) {
721                        html1 = me.options.nextText_post;
722                    } else {
723                        html1 = me.options.nextText;
724                    }
725                } else {
726                    html1 = me.options.nextText;
727                }
728            }
729        } else {
730            width = me.options.buttonWidth;
731
732            if (
733                (direction == false && me.options.prevPost && me.currentSlide == 0) ||
734                (direction == true && me.options.nextPost && me.currentSlide == me.numberOfSlides - 1)
735            ) {
736                html2 = me.options[directionName + 'Text_post'];
737                href = direction ? me.options.nextPost : me.options.prevPost;
738            }
739            else {
740                html2 = me.options[directionName + 'Text'];
741            }
742        }
743
744        // Set link.
745        {
746            var jumpToSlide = null;
747            if (direction == false && me.options.loopSlides && me.currentSlide == 0) {
748                jumpToSlide = me.numberOfSlides - 1;
749            }
750            else if (direction == true && me.options.loopSlides && me.currentSlide == me.numberOfSlides - 1) {
751                jumpToSlide = 0;
752            }
753            else if (
754                (direction == false && me.options.prevPost && me.currentSlide == 0) ||
755                (direction == true && me.options.nextPost && me.currentSlide == me.numberOfSlides - 1)
756            ) {
757                buttonEl.addClass('_another_post');
758                href = direction ? me.options.nextPost : me.options.prevPost;
759            } else {
760                buttonEl.removeClass('_another_post');
761                jumpToSlide = me.currentSlide + (direction ? 1 : -1);
762            }
763
764            if (jumpToSlide !== null) {
765                if (me.needToRefreshPage()) {
766                    var slide = me.slides[jumpToSlide];
767                    if (slide) {
768                        href = slide.permalink;
769                    }
770                }
771                else {
772                    href = '#';
773                }
774            }
775        }
776
777        buttonEl.find('._1').html(html1);
778        buttonEl.find('._2')
779            .css('width', width > 0 ? width : '')
780            .html(html2);
781        buttonEl.find('._3').html(html3);
782
783        // Disable or enable
784        if (
785            (direction == false && me.options.prevPost == null && !me.options.loopSlides && me.currentSlide == 0) ||
786            (direction == true && me.options.nextPost == null && !me.options.loopSlides && me.currentSlide == me.numberOfSlides - 1)
787        ) {
788            buttonEl.addClass('_disabled');
789            href = '#';
790        }
791        else {
792            buttonEl.removeClass('_disabled');
793        }
794
795        buttonEl.attr('href', href);
796    };
797
798    // Handler for previous and next buttons.
799    me.onNavClick = function (that, direction, event) {
800        var $that = $(that);
801
802        if (typeof $that.attr('href') === 'undefined') {
803            return;
804        }
805
806        // Jump to another page.
807        // Some 3rd party plugins misbehave and turn the '#' into '', namely https://github.com/medialize/URI.js with "Blackout Image Gallery".
808        if ($that.attr('href') != '#' && $that.attr('href') != '') {
809            me.showLoading();
810            me.saveScrollTop();
811            return;
812        }
813
814        if (direction == 'prev') {
815            me.setPrev();
816        } else {
817            me.setNext();
818        }
819
820        $that.focus();
821        if (event) {
822            event.preventDefault();
823        }
824    };
825
826    me.isHtml5StorageAvailable = function () {
827        try {
828            return 'localStorage' in window && window['localStorage'] !== null;
829        } catch (e) {
830            return false;
831        }
832    };
833
834    me.saveScrollTop = function () {
835        if (!me.options.scrollAfterRefresh) {
836            return;
837        }
838
839        if (!me.isHtml5StorageAvailable) {
840            return;
841        }
842        
843        localStorage.setItem('scrollTop', JSON.stringify({
844            postId: me.postId,
845            scrollTop: $(window).scrollTop()
846        }));
847    };
848
849    me.loadScrollTop = function () {
850        if (!me.options.scrollAfterRefresh) {
851            return;
852        }
853
854        if (!me.isHtml5StorageAvailable) {
855            return;
856        }
857
858        var data = JSON.parse(localStorage.getItem('scrollTop'));
859        if (data && data.postId == me.postId) {
860            var scrollTop = Math.min(data.scrollTop, me.slideContainer.offset().top);
861            $(window).scrollTop(scrollTop);
862        }
863
864        localStorage.removeItem('scrollTop');
865    };
866
867    // Go to the previous slide.
868    me.setPrev = function () {
869        if (me.currentSlide == 0) {
870            if (me.options.loopSlides) {
871                me.setSlide(me.numberOfSlides - 1);
872            }
873            else if (me.options.prevPost) {
874                me.showPost(me.options.prevPost);
875            }
876        }
877        else {
878            me.setSlide(me.currentSlide - 1);
879        }
880    };
881
882    // Go to the next slide.
883    me.setNext = function () {
884        if (me.currentSlide == me.numberOfSlides - 1) {
885            if (me.options.loopSlides) {
886                me.setSlide(0);
887            }
888            else if (me.options.nextPost) {
889                me.showPost(me.options.nextPost);
890            }
891        }
892        else {
893            me.setSlide(me.currentSlide + 1);
894        }
895    };
896
897    // Go to another post. This method will be called when navigating using the keyboard shortcuts.
898    me.showPost = function (postUrl) {
899        document.location = postUrl;
900    };
901
902    // Set the transition properties (used in Live Preview).
903    me.setTransition = function (options) {
904        var defaults = {
905            'effect': me.options.transitionEffect,
906            'speed': me.options.transitionSpeed
907        };
908        options = $.extend(defaults, options);
909        me.options.transitionEffect = options.effect;
910        me.options.transitionSpeed = options.speed;
911    };
912
913    // Set the navigation bar's text template (used in Live Preview).
914    me.setNavText = function (text) {
915        me.options.navText = text;
916        me.updateNavigationBars();
917    };
918
919    // Set the title for all slides (used in Live Preview).
920    me.setTitleText = function (text) {
921        for (i = 0; i < me.slides.length; i++) {
922            me.slides[i].shortCodeTitle = '';
923        }
924        me.options.helperText = text;
925        me.updateTitleText();
926    };
927
928    me.showLoading = function () {
929        me.isLoading = true;
930        for (i = 0; i < me.navEl.length; i++) {
931            me.navEl[i].container
932                .append($('<div class="_loading"></div>'))
933                .find('._buttons > a').addClass('_disabled');
934        }
935    };
936
937    me.hideLoading = function () {
938        me.isLoading = false;
939        for (i = 0; i < me.navEl.length; i++) {
940            me.navEl[i].container.find('._loading').remove();
941        }
942        me.updateNavigationBars();
943    };
944
945    me.needToRefreshPage = function () {
946        return (
947        me.currentSlide !== null &&
948        me.options.refreshAds &&
949        me.slidesSinceLastAdRefresh + 1 >= me.options.refreshAdsEveryNSlides &&
950        me.options.adRefreshingMechanism == 'page'
951        );
952    };
953
954    // Initialize the slider.
955    me.init();
956
957    return me;
958};

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.