PageSourceSearch

https://rockymtn.com/wp-content/themes/rme/scripts/jquery.cycle2.js

js rockymtn.com collected 2026-09-26 09:42:51 UTC 48,854 bytes, 1,547 lines download raw bytes

1/*!
2* jQuery Cycle2; version: 2.1.6 build: 20141007
3* http://jquery.malsup.com/cycle2/
4* Copyright (c) 2014 M. Alsup; Dual licensed: MIT/GPL
5*/
6
7/* Cycle2 core engine */
8;(function($) {
9"use strict";
10
11var version = '2.1.6';
12
13$.fn.cycle = function( options ) {
14    // fix mistakes with the ready state
15    var o;
16    if ( this.length === 0 && !$.isReady ) {
17        o = { s: this.selector, c: this.context };
18        $.fn.cycle.log('requeuing slideshow (dom not ready)');
19        $(function() {
20            $( o.s, o.c ).cycle(options);
21        });
22        return this;
23    }
24
25    return this.each(function() {
26        var data, opts, shortName, val;
27        var container = $(this);
28        var log = $.fn.cycle.log;
29
30        if ( container.data('cycle.opts') )
31            return; // already initialized
32
33        if ( container.data('cycle-log') === false ||
34            ( options && options.log === false ) ||
35            ( opts && opts.log === false) ) {
36            log = $.noop;
37        }
38
39        log('--c2 init--');
40        data = container.data();
41        for (var p in data) {
42            // allow props to be accessed sans 'cycle' prefix and log the overrides
43            if (data.hasOwnProperty(p) && /^cycle[A-Z]+/.test(p) ) {
44                val = data[p];
45                shortName = p.match(/^cycle(.*)/)[1].replace(/^[A-Z]/, lowerCase);
46                log(shortName+':', val, '('+typeof val +')');
47                data[shortName] = val;
48            }
49        }
50
51        opts = $.extend( {}, $.fn.cycle.defaults, data, options || {});
52
53        opts.timeoutId = 0;
54        opts.paused = opts.paused || false; // #57
55        opts.container = container;
56        opts._maxZ = opts.maxZ;
57
58        opts.API = $.extend ( { _container: container }, $.fn.cycle.API );
59        opts.API.log = log;
60        opts.API.trigger = function( eventName, args ) {
61            opts.container.trigger( eventName, args );
62            return opts.API;
63        };
64
65        container.data( 'cycle.opts', opts );
66        container.data( 'cycle.API', opts.API );
67
68        // opportunity for plugins to modify opts and API
69        opts.API.trigger('cycle-bootstrap', [ opts, opts.API ]);
70
71        opts.API.addInitialSlides();
72        opts.API.preInitSlideshow();
73
74        if ( opts.slides.length )
75            opts.API.initSlideshow();
76    });
77};
78
79$.fn.cycle.API = {
80    opts: function() {
81        return this._container.data( 'cycle.opts' );
82    },
83    addInitialSlides: function() {
84        var opts = this.opts();
85        var slides = opts.slides;
86        opts.slideCount = 0;
87        opts.slides = $(); // empty set
88
89        // add slides that already exist
90        slides = slides.jquery ? slides : opts.container.find( slides );
91
92        if ( opts.random ) {
93            slides.sort(function() {return Math.random() - 0.5;});
94        }
95
96        opts.API.add( slides );
97    },
98
99    preInitSlideshow: function() {
100        var opts = this.opts();
101        opts.API.trigger('cycle-pre-initialize', [ opts ]);
102        var tx = $.fn.cycle.transitions[opts.fx];
103        if (tx && $.isFunction(tx.preInit))
104            tx.preInit( opts );
105        opts._preInitialized = true;
106    },
107
108    postInitSlideshow: function() {
109        var opts = this.opts();
110        opts.API.trigger('cycle-post-initialize', [ opts ]);
111        var tx = $.fn.cycle.transitions[opts.fx];
112        if (tx && $.isFunction(tx.postInit))
113            tx.postInit( opts );
114    },
115
116    initSlideshow: function() {
117        var opts = this.opts();
118        var pauseObj = opts.container;
119        var slideOpts;
120        opts.API.calcFirstSlide();
121
122        if ( opts.container.css('position') == 'static' )
123            opts.container.css('position', 'relative');
124
125        $(opts.slides[opts.currSlide]).css({
126            opacity: 1,
127            display: 'block',
128            visibility: 'visible'
129        });
130        opts.API.stackSlides( opts.slides[opts.currSlide], opts.slides[opts.nextSlide], !opts.reverse );
131
132        if ( opts.pauseOnHover ) {
133            // allow pauseOnHover to specify an element
134            if ( opts.pauseOnHover !== true )
135                pauseObj = $( opts.pauseOnHover );
136
137            pauseObj.hover(
138                function(){ opts.API.pause( true ); },
139                function(){ opts.API.resume( true ); }
140            );
141        }
142
143        // stage initial transition
144        if ( opts.timeout ) {
145            slideOpts = opts.API.getSlideOpts( opts.currSlide );
146            opts.API.queueTransition( slideOpts, slideOpts.timeout + opts.delay );
147        }
148
149        opts._initialized = true;
150        opts.API.updateView( true );
151        opts.API.trigger('cycle-initialized', [ opts ]);
152        opts.API.postInitSlideshow();
153    },
154
155    pause: function( hover ) {
156        var opts = this.opts(),
157            slideOpts = opts.API.getSlideOpts(),
158            alreadyPaused = opts.hoverPaused || opts.paused;
159
160        if ( hover )
161            opts.hoverPaused = true;
162        else
163            opts.paused = true;
164
165        if ( ! alreadyPaused ) {
166            opts.container.addClass('cycle-paused');
167            opts.API.trigger('cycle-paused', [ opts ]).log('cycle-paused');
168
169            if ( slideOpts.timeout ) {
170                clearTimeout( opts.timeoutId );
171                opts.timeoutId = 0;
172
173                // determine how much time is left for the current slide
174                opts._remainingTimeout -= ( $.now() - opts._lastQueue );
175                if ( opts._remainingTimeout < 0 || isNaN(opts._remainingTimeout) )
176                    opts._remainingTimeout = undefined;
177            }
178        }
179    },
180
181    resume: function( hover ) {
182        var opts = this.opts(),
183            alreadyResumed = !opts.hoverPaused && !opts.paused,
184            remaining;
185
186        if ( hover )
187            opts.hoverPaused = false;
188        else
189            opts.paused = false;
190
191
192        if ( ! alreadyResumed ) {
193            opts.container.removeClass('cycle-paused');
194            // #gh-230; if an animation is in progress then don't queue a new transition; it will
195            // happen naturally
196            if ( opts.slides.filter(':animated').length === 0 )
197                opts.API.queueTransition( opts.API.getSlideOpts(), opts._remainingTimeout );
198            opts.API.trigger('cycle-resumed', [ opts, opts._remainingTimeout ] ).log('cycle-resumed');
199        }
200    },
201
202    add: function( slides, prepend ) {
203        var opts = this.opts();
204        var oldSlideCount = opts.slideCount;
205        var startSlideshow = false;
206        var len;
207
208        if ( $.type(slides) == 'string')
209            slides = $.trim( slides );
210
211        $( slides ).each(function(i) {
212            var slideOpts;
213            var slide = $(this);
214
215            if ( prepend )
216                opts.container.prepend( slide );
217            else
218                opts.container.append( slide );
219
220            opts.slideCount++;
221            slideOpts = opts.API.buildSlideOpts( slide );
222
223            if ( prepend )
224                opts.slides = $( slide ).add( opts.slides );
225            else
226                opts.slides = opts.slides.add( slide );
227
228            opts.API.initSlide( slideOpts, slide, --opts._maxZ );
229
230            slide.data('cycle.opts', slideOpts);
231            opts.API.trigger('cycle-slide-added', [ opts, slideOpts, slide ]);
232        });
233
234        opts.API.updateView( true );
235
236        startSlideshow = opts._preInitialized && (oldSlideCount < 2 && opts.slideCount >= 1);
237        if ( startSlideshow ) {
238            if ( !opts._initialized )
239                opts.API.initSlideshow();
240            else if ( opts.timeout ) {
241                len = opts.slides.length;
242                opts.nextSlide = opts.reverse ? len - 1 : 1;
243                if ( !opts.timeoutId ) {
244                    opts.API.queueTransition( opts );
245                }
246            }
247        }
248    },
249
250    calcFirstSlide: function() {
251        var opts = this.opts();
252        var firstSlideIndex;
253        firstSlideIndex = parseInt( opts.startingSlide || 0, 10 );
254        if (firstSlideIndex >= opts.slides.length || firstSlideIndex < 0)
255            firstSlideIndex = 0;
256
257        opts.currSlide = firstSlideIndex;
258        if ( opts.reverse ) {
259            opts.nextSlide = firstSlideIndex - 1;
260            if (opts.nextSlide < 0)
261                opts.nextSlide = opts.slides.length - 1;
262        }
263        else {
264            opts.nextSlide = firstSlideIndex + 1;
265            if (opts.nextSlide == opts.slides.length)
266                opts.nextSlide = 0;
267        }
268    },
269
270    calcNextSlide: function() {
271        var opts = this.opts();
272        var roll;
273        if ( opts.reverse ) {
274            roll = (opts.nextSlide - 1) < 0;
275            opts.nextSlide = roll ? opts.slideCount - 1 : opts.nextSlide-1;
276            opts.currSlide = roll ? 0 : opts.nextSlide+1;
277        }
278        else {
279            roll = (opts.nextSlide + 1) == opts.slides.length;
280            opts.nextSlide = roll ? 0 : opts.nextSlide+1;
281            opts.currSlide = roll ? opts.slides.length-1 : opts.nextSlide-1;
282        }
283    },
284
285    calcTx: function( slideOpts, manual ) {
286        var opts = slideOpts;
287        var tx;
288
289        if ( opts._tempFx )
290            tx = $.fn.cycle.transitions[opts._tempFx];
291        else if ( manual && opts.manualFx )
292            tx = $.fn.cycle.transitions[opts.manualFx];
293
294        if ( !tx )
295            tx = $.fn.cycle.transitions[opts.fx];
296
297        opts._tempFx = null;
298        this.opts()._tempFx = null;
299
300        if (!tx) {
301            tx = $.fn.cycle.transitions.fade;
302            opts.API.log('Transition "' + opts.fx + '" not found.  Using fade.');
303        }
304        return tx;
305    },
306
307    prepareTx: function( manual, fwd ) {
308        var opts = this.opts();
309        var after, curr, next, slideOpts, tx;
310
311        if ( opts.slideCount < 2 ) {
312            opts.timeoutId = 0;
313            return;
314        }
315        if ( manual && ( !opts.busy || opts.manualTrump ) ) {
316            opts.API.stopTransition();
317            opts.busy = false;
318            clearTimeout(opts.timeoutId);
319            opts.timeoutId = 0;
320        }
321        if ( opts.busy )
322            return;
323        if ( opts.timeoutId === 0 && !manual )
324            return;
325
326        curr = opts.slides[opts.currSlide];
327        next = opts.slides[opts.nextSlide];
328        slideOpts = opts.API.getSlideOpts( opts.nextSlide );
329        tx = opts.API.calcTx( slideOpts, manual );
330
331        opts._tx = tx;
332
333        if ( manual && slideOpts.manualSpeed !== undefined )
334            slideOpts.speed = slideOpts.manualSpeed;
335
336        // if ( opts.nextSlide === opts.currSlide )
337        //     opts.API.calcNextSlide();
338
339        // ensure that:
340        //      1. advancing to a different slide
341        //      2. this is either a manual event (prev/next, pager, cmd) or
342        //              a timer event and slideshow is not paused
343        if ( opts.nextSlide != opts.currSlide &&
344            (manual || (!opts.paused && !opts.hoverPaused && opts.timeout) )) { // #62
345
346            opts.API.trigger('cycle-before', [ slideOpts, curr, next, fwd ]);
347            if ( tx.before )
348                tx.before( slideOpts, curr, next, fwd );
349
350            after = function() {
351                opts.busy = false;
352                // #76; bail if slideshow has been destroyed
353                if (! opts.container.data( 'cycle.opts' ) )
354                    return;
355
356                if (tx.after)
357                    tx.after( slideOpts, curr, next, fwd );
358                opts.API.trigger('cycle-after', [ slideOpts, curr, next, fwd ]);
359                opts.API.queueTransition( slideOpts);
360                opts.API.updateView( true );
361            };
362
363            opts.busy = true;
364            if (tx.transition)
365                tx.transition(slideOpts, curr, next, fwd, after);
366            else
367                opts.API.doTransition( slideOpts, curr, next, fwd, after);
368
369            opts.API.calcNextSlide();
370            opts.API.updateView();
371        } else {
372            opts.API.queueTransition( slideOpts );
373        }
374    },
375
376    // perform the actual animation
377    doTransition: function( slideOpts, currEl, nextEl, fwd, callback) {
378        var opts = slideOpts;
379        var curr = $(currEl), next = $(nextEl);
380        var fn = function() {
381            // make sure animIn has something so that callback doesn't trigger immediately
382            next.animate(opts.animIn || { opacity: 1}, opts.speed, opts.easeIn || opts.easing, callback);
383        };
384
385        next.css(opts.cssBefore || {});
386        curr.animate(opts.animOut || {}, opts.speed, opts.easeOut || opts.easing, function() {
387            curr.css(opts.cssAfter || {});
388            if (!opts.sync) {
389                fn();
390            }
391        });
392        if (opts.sync) {
393            fn();
394        }
395    },
396
397    queueTransition: function( slideOpts, specificTimeout ) {
398        var opts = this.opts();
399        var timeout = specificTimeout !== undefined ? specificTimeout : slideOpts.timeout;
400        if (opts.nextSlide === 0 && --opts.loop === 0) {
401            opts.API.log('terminating; loop=0');
402            opts.timeout = 0;
403            if ( timeout ) {
404                setTimeout(function() {
405                    opts.API.trigger('cycle-finished', [ opts ]);
406                }, timeout);
407            }
408            else {
409                opts.API.trigger('cycle-finished', [ opts ]);
410            }
411            // reset nextSlide
412            opts.nextSlide = opts.currSlide;
413            return;
414        }
415        if ( opts.continueAuto !== undefined ) {
416            if ( opts.continueAuto === false ||
417                ($.isFunction(opts.continueAuto) && opts.continueAuto() === false )) {
418                opts.API.log('terminating automatic transitions');
419                opts.timeout = 0;
420                if ( opts.timeoutId )
421                    clearTimeout(opts.timeoutId);
422                return;
423            }
424        }
425        if ( timeout ) {
426            opts._lastQueue = $.now();
427            if ( specificTimeout === undefined )
428                opts._remainingTimeout = slideOpts.timeout;
429
430            if ( !opts.paused && ! opts.hoverPaused ) {
431                opts.timeoutId = setTimeout(function() {
432                    opts.API.prepareTx( false, !opts.reverse );
433                }, timeout );
434            }
435        }
436    },
437
438    stopTransition: function() {
439        var opts = this.opts();
440        if ( opts.slides.filter(':animated').length ) {
441            opts.slides.stop(false, true);
442            opts.API.trigger('cycle-transition-stopped', [ opts ]);
443        }
444
445        if ( opts._tx && opts._tx.stopTransition )
446            opts._tx.stopTransition( opts );
447    },
448
449    // advance slide forward or back
450    advanceSlide: function( val ) {
451        var opts = this.opts();
452        clearTimeout(opts.timeoutId);
453        opts.timeoutId = 0;
454        opts.nextSlide = opts.currSlide + val;
455
456        if (opts.nextSlide < 0)
457            opts.nextSlide = opts.slides.length - 1;
458        else if (opts.nextSlide >= opts.slides.length)
459            opts.nextSlide = 0;
460
461        opts.API.prepareTx( true,  val >= 0 );
462        return false;
463    },
464
465    buildSlideOpts: function( slide ) {
466        var opts = this.opts();
467        var val, shortName;
468        var slideOpts = slide.data() || {};
469        for (var p in slideOpts) {
470            // allow props to be accessed sans 'cycle' prefix and log the overrides
471            if (slideOpts.hasOwnProperty(p) && /^cycle[A-Z]+/.test(p) ) {
472                val = slideOpts[p];
473                shortName = p.match(/^cycle(.*)/)[1].replace(/^[A-Z]/, lowerCase);
474                opts.API.log('['+(opts.slideCount-1)+']', shortName+':', val, '('+typeof val +')');
475                slideOpts[shortName] = val;
476            }
477        }
478
479        slideOpts = $.extend( {}, $.fn.cycle.defaults, opts, slideOpts );
480        slideOpts.slideNum = opts.slideCount;
481
482        try {
483            // these props should always be read from the master state object
484            delete slideOpts.API;
485            delete slideOpts.slideCount;
486            delete slideOpts.currSlide;
487            delete slideOpts.nextSlide;
488            delete slideOpts.slides;
489        } catch(e) {
490            // no op
491        }
492        return slideOpts;
493    },
494
495    getSlideOpts: function( index ) {
496        var opts = this.opts();
497        if ( index === undefined )
498            index = opts.currSlide;
499
500        var slide = opts.slides[index];
501        var slideOpts = $(slide).data('cycle.opts');
502        return $.extend( {}, opts, slideOpts );
503    },
504
505    initSlide: function( slideOpts, slide, suggestedZindex ) {
506        var opts = this.opts();
507        slide.css( slideOpts.slideCss || {} );
508        if ( suggestedZindex > 0 )
509            slide.css( 'zIndex', suggestedZindex );
510
511        // ensure that speed settings are sane
512        if ( isNaN( slideOpts.speed ) )
513            slideOpts.speed = $.fx.speeds[slideOpts.speed] || $.fx.speeds._default;
514        if ( !slideOpts.sync )
515            slideOpts.speed = slideOpts.speed / 2;
516
517        slide.addClass( opts.slideClass );
518    },
519
520    updateView: function( isAfter, isDuring, forceEvent ) {
521        var opts = this.opts();
522        if ( !opts._initialized )
523            return;
524        var slideOpts = opts.API.getSlideOpts();
525        var currSlide = opts.slides[ opts.currSlide ];
526
527        if ( ! isAfter && isDuring !== true ) {
528            opts.API.trigger('cycle-update-view-before', [ opts, slideOpts, currSlide ]);
529            if ( opts.updateView < 0 )
530                return;
531        }
532
533        if ( opts.slideActiveClass ) {
534            opts.slides.removeClass( opts.slideActiveClass )
535                .eq( opts.currSlide ).addClass( opts.slideActiveClass );
536        }
537
538        if ( isAfter && opts.hideNonActive )
539            opts.slides.filter( ':not(.' + opts.slideActiveClass + ')' ).css('visibility', 'hidden');
540
541        if ( opts.updateView === 0 ) {
542            setTimeout(function() {
543                opts.API.trigger('cycle-update-view', [ opts, slideOpts, currSlide, isAfter ]);
544            }, slideOpts.speed / (opts.sync ? 2 : 1) );
545        }
546
547        if ( opts.updateView !== 0 )
548            opts.API.trigger('cycle-update-view', [ opts, slideOpts, currSlide, isAfter ]);
549
550        if ( isAfter )
551            opts.API.trigger('cycle-update-view-after', [ opts, slideOpts, currSlide ]);
552    },
553
554    getComponent: function( name ) {
555        var opts = this.opts();
556        var selector = opts[name];
557        if (typeof selector === 'string') {
558            // if selector is a child, sibling combinator, adjancent selector then use find, otherwise query full dom
559            return (/^\s*[\>|\+|~]/).test( selector ) ? opts.container.find( selector ) : $( selector );
560        }
561        if (selector.jquery)
562            return selector;
563
564        return $(selector);
565    },
566
567    stackSlides: function( curr, next, fwd ) {
568        var opts = this.opts();
569        if ( !curr ) {
570            curr = opts.slides[opts.currSlide];
571            next = opts.slides[opts.nextSlide];
572            fwd = !opts.reverse;
573        }
574
575        // reset the zIndex for the common case:
576        // curr slide on top,  next slide beneath, and the rest in order to be shown
577        $(curr).css('zIndex', opts.maxZ);
578
579        var i;
580        var z = opts.maxZ - 2;
581        var len = opts.slideCount;
582        if (fwd) {
583            for ( i = opts.currSlide + 1; i < len; i++ )
584                $( opts.slides[i] ).css( 'zIndex', z-- );
585            for ( i = 0; i < opts.currSlide; i++ )
586                $( opts.slides[i] ).css( 'zIndex', z-- );
587        }
588        else {
589            for ( i = opts.currSlide - 1; i >= 0; i-- )
590                $( opts.slides[i] ).css( 'zIndex', z-- );
591            for ( i = len - 1; i > opts.currSlide; i-- )
592                $( opts.slides[i] ).css( 'zIndex', z-- );
593        }
594
595        $(next).css('zIndex', opts.maxZ - 1);
596    },
597
598    getSlideIndex: function( el ) {
599        return this.opts().slides.index( el );
600    }
601
602}; // API
603
604// default logger
605$.fn.cycle.log = function log() {
606    /*global console:true */
607    // if (window.console && console.log)
608    //     console.log('[cycle2] ' + Array.prototype.join.call(arguments, ' ') );
609};
610
611$.fn.cycle.version = function() { return 'Cycle2: ' + version; };
612
613// helper functions
614
615function lowerCase(s) {
616    return (s || '').toLowerCase();
617}
618
619// expose transition object
620$.fn.cycle.transitions = {
621    custom: {
622    },
623    none: {
624        before: function( opts, curr, next, fwd ) {
625            opts.API.stackSlides( next, curr, fwd );
626            opts.cssBefore = { opacity: 1, visibility: 'visible', display: 'block' };
627        }
628    },
629    fade: {
630        before: function( opts, curr, next, fwd ) {
631            var css = opts.API.getSlideOpts( opts.nextSlide ).slideCss || {};
632            opts.API.stackSlides( curr, next, fwd );
633            opts.cssBefore = $.extend(css, { opacity: 0, visibility: 'visible', display: 'block' });
634            opts.animIn = { opacity: 1 };
635            opts.animOut = { opacity: 0 };
636        }
637    },
638    fadeout: {
639        before: function( opts , curr, next, fwd ) {
640            var css = opts.API.getSlideOpts( opts.nextSlide ).slideCss || {};
641            opts.API.stackSlides( curr, next, fwd );
642            opts.cssBefore = $.extend(css, { opacity: 1, visibility: 'visible', display: 'block' });
643            opts.animOut = { opacity: 0 };
644        }
645    },
646    scrollHorz: {
647        before: function( opts, curr, next, fwd ) {
648            opts.API.stackSlides( curr, next, fwd );
649            var w = opts.container.css('overflow','hidden').width();
650            opts.cssBefore = { left: fwd ? w : - w, top: 0, opacity: 1, visibility: 'visible', display: 'block' };
651            opts.cssAfter = { zIndex: opts._maxZ - 2, left: 0 };
652            opts.animIn = { left: 0 };
653            opts.animOut = { left: fwd ? -w : w };
654        }
655    }
656};
657
658// @see: http://jquery.malsup.com/cycle2/api
659$.fn.cycle.defaults = {
660    allowWrap:        true,
661    autoSelector:     '.cycle-slideshow[data-cycle-auto-init!=false]',
662    delay:            0,
663    easing:           null,
664    fx:              'fade',
665    hideNonActive:    true,
666    loop:             0,
667    manualFx:         undefined,
668    manualSpeed:      undefined,
669    manualTrump:      true,
670    maxZ:             100,
671    pauseOnHover:     false,
672    reverse:          false,
673    slideActiveClass: 'cycle-slide-active',
674    slideClass:       'cycle-slide',
675    slideCss:         { position: 'absolute', top: 0, left: 0 },
676    slides:          '> img',
677    speed:            500,
678    startingSlide:    0,
679    sync:             true,
680    timeout:          4000,
681    updateView:       0
682};
683
684// automatically find and run slideshows
685$(document).ready(function() {
686    $( $.fn.cycle.defaults.autoSelector ).cycle();
687});
688
689})(jQuery);
690
691/*! Cycle2 autoheight plugin; Copyright (c) M.Alsup, 2012; version: 20130913 */
692(function($) {
693"use strict";
694
695$.extend($.fn.cycle.defaults, {
696    autoHeight: 0, // setting this option to false disables autoHeight logic
697    autoHeightSpeed: 250,
698    autoHeightEasing: null
699});
700
701$(document).on( 'cycle-initialized', function( e, opts ) {
702    var autoHeight = opts.autoHeight;
703    var t = $.type( autoHeight );
704    var resizeThrottle = null;
705    var ratio;
706
707    if ( t !== 'string' && t !== 'number' )
708        return;
709
710    // bind events
711    opts.container.on( 'cycle-slide-added cycle-slide-removed', initAutoHeight );
712    opts.container.on( 'cycle-destroyed', onDestroy );
713
714    if ( autoHeight == 'container' ) {
715        opts.container.on( 'cycle-before', onBefore );
716    }
717    else if ( t === 'string' && /\d+\:\d+/.test( autoHeight ) ) {
718        // use ratio
719        ratio = autoHeight.match(/(\d+)\:(\d+)/);
720        ratio = ratio[1] / ratio[2];
721        opts._autoHeightRatio = ratio;
722    }
723
724    // if autoHeight is a number then we don't need to recalculate the sentinel
725    // index on resize
726    if ( t !== 'number' ) {
727        // bind unique resize handler per slideshow (so it can be 'off-ed' in onDestroy)
728        opts._autoHeightOnResize = function () {
729            clearTimeout( resizeThrottle );
730            resizeThrottle = setTimeout( onResize, 50 );
731        };
732
733        $(window).on( 'resize orientationchange', opts._autoHeightOnResize );
734    }
735
736    setTimeout( onResize, 30 );
737
738    function onResize() {
739        initAutoHeight( e, opts );
740    }
741});
742
743function initAutoHeight( e, opts ) {
744    var clone, height, sentinelIndex;
745    var autoHeight = opts.autoHeight;
746
747    if ( autoHeight == 'container' ) {
748        height = $( opts.slides[ opts.currSlide ] ).outerHeight();
749        opts.container.height( height );
750    }
751    else if ( opts._autoHeightRatio ) {
752        opts.container.height( opts.container.width() / opts._autoHeightRatio );
753    }
754    else if ( autoHeight === 'calc' || ( $.type( autoHeight ) == 'number' && autoHeight >= 0 ) ) {
755        if ( autoHeight === 'calc' )
756            sentinelIndex = calcSentinelIndex( e, opts );
757        else if ( autoHeight >= opts.slides.length )
758            sentinelIndex = 0;
759        else
760            sentinelIndex = autoHeight;
761
762        // only recreate sentinel if index is different
763        if ( sentinelIndex == opts._sentinelIndex )
764            return;
765
766        opts._sentinelIndex = sentinelIndex;
767        if ( opts._sentinel )
768            opts._sentinel.remove();
769
770        // clone existing slide as sentinel
771        clone = $( opts.slides[ sentinelIndex ].cloneNode(true) );
772
773        // #50; remove special attributes from cloned content
774        clone.removeAttr( 'id name rel' ).find( '[id],[name],[rel]' ).removeAttr( 'id name rel' );
775
776        clone.css({
777            position: 'static',
778            visibility: 'hidden',
779            display: 'block'
780        }).prependTo( opts.container ).addClass('cycle-sentinel cycle-slide').removeClass('cycle-slide-active');
781        clone.find( '*' ).css( 'visibility', 'hidden' );
782
783        opts._sentinel = clone;
784    }
785}
786
787function calcSentinelIndex( e, opts ) {
788    var index = 0, max = -1;
789
790    // calculate tallest slide index
791    opts.slides.each(function(i) {
792        var h = $(this).height();
793        if ( h > max ) {
794            max = h;
795            index = i;
796        }
797    });
798    return index;
799}
800
801function onBefore( e, opts, outgoing, incoming, forward ) {
802    var h = $(incoming).outerHeight();
803    opts.container.animate( { height: h }, opts.autoHeightSpeed, opts.autoHeightEasing );
804}
805
806function onDestroy( e, opts ) {
807    if ( opts._autoHeightOnResize ) {
808        $(window).off( 'resize orientationchange', opts._autoHeightOnResize );
809        opts._autoHeightOnResize = null;
810    }
811    opts.container.off( 'cycle-slide-added cycle-slide-removed', initAutoHeight );
812    opts.container.off( 'cycle-destroyed', onDestroy );
813    opts.container.off( 'cycle-before', onBefore );
814
815    if ( opts._sentinel ) {
816        opts._sentinel.remove();
817        opts._sentinel = null;
818    }
819}
820
821})(jQuery);
822
823/*! caption plugin for Cycle2;  version: 20130306 */
824(function($) {
825"use strict";
826
827$.extend($.fn.cycle.defaults, {
828    caption:          '> .cycle-caption',
829    captionTemplate:  '{{slideNum}} / {{slideCount}}',
830    overlay:          '> .cycle-overlay',
831    overlayTemplate:  '<div>{{title}}</div><div>{{desc}}</div>',
832    captionModule:    'caption'
833});
834
835$(document).on( 'cycle-update-view', function( e, opts, slideOpts, currSlide ) {
836    if ( opts.captionModule !== 'caption' )
837        return;
838    var el;
839    $.each(['caption','overlay'], function() {
840        var name = this;
841        var template = slideOpts[name+'Template'];
842        var el = opts.API.getComponent( name );
843        if( el.length && template ) {
844            el.html( opts.API.tmpl( template, slideOpts, opts, currSlide ) );
845            el.show();
846        }
847        else {
848            el.hide();
849        }
850    });
851});
852
853$(document).on( 'cycle-destroyed', function( e, opts ) {
854    var el;
855    $.each(['caption','overlay'], function() {
856        var name = this, template = opts[name+'Template'];
857        if ( opts[name] && template ) {
858            el = opts.API.getComponent( 'caption' );
859            el.empty();
860        }
861    });
862});
863
864})(jQuery);
865
866/*! command plugin for Cycle2;  version: 20140415 */
867(function($) {
868"use strict";
869
870var c2 = $.fn.cycle;
871
872$.fn.cycle = function( options ) {
873    var cmd, cmdFn, opts;
874    var args = $.makeArray( arguments );
875
876    if ( $.type( options ) == 'number' ) {
877        return this.cycle( 'goto', options );
878    }
879
880    if ( $.type( options ) == 'string' ) {
881        return this.each(function() {
882            var cmdArgs;
883            cmd = options;
884            opts = $(this).data('cycle.opts');
885
886            if ( opts === undefined ) {
887                c2.log('slideshow must be initialized before sending commands; "' + cmd + '" ignored');
888                return;
889            }
890            else {
891                cmd = cmd == 'goto' ? 'jump' : cmd; // issue #3; change 'goto' to 'jump' internally
892                cmdFn = opts.API[ cmd ];
893                if ( $.isFunction( cmdFn )) {
894                    cmdArgs = $.makeArray( args );
895                    cmdArgs.shift();
896                    return cmdFn.apply( opts.API, cmdArgs );
897                }
898                else {
899                    c2.log( 'unknown command: ', cmd );
900                }
901            }
902        });
903    }
904    else {
905        return c2.apply( this, arguments );
906    }
907};
908
909// copy props
910$.extend( $.fn.cycle, c2 );
911
912$.extend( c2.API, {
913    next: function() {
914        var opts = this.opts();
915        if ( opts.busy && ! opts.manualTrump )
916            return;
917
918        var count = opts.reverse ? -1 : 1;
919        if ( opts.allowWrap === false && ( opts.currSlide + count ) >= opts.slideCount )
920            return;
921
922        opts.API.advanceSlide( count );
923        opts.API.trigger('cycle-next', [ opts ]).log('cycle-next');
924    },
925
926    prev: function() {
927        var opts = this.opts();
928        if ( opts.busy && ! opts.manualTrump )
929            return;
930        var count = opts.reverse ? 1 : -1;
931        if ( opts.allowWrap === false && ( opts.currSlide + count ) < 0 )
932            return;
933
934        opts.API.advanceSlide( count );
935        opts.API.trigger('cycle-prev', [ opts ]).log('cycle-prev');
936    },
937
938    destroy: function() {
939        this.stop(); //#204
940
941        var opts = this.opts();
942        var clean = $.isFunction( $._data ) ? $._data : $.noop;  // hack for #184 and #201
943        clearTimeout(opts.timeoutId);
944        opts.timeoutId = 0;
945        opts.API.stop();
946        opts.API.trigger( 'cycle-destroyed', [ opts ] ).log('cycle-destroyed');
947        opts.container.removeData();
948        clean( opts.container[0], 'parsedAttrs', false );
949
950        // #75; remove inline styles
951        if ( ! opts.retainStylesOnDestroy ) {
952            opts.container.removeAttr( 'style' );
953            opts.slides.removeAttr( 'style' );
954            opts.slides.removeClass( opts.slideActiveClass );
955        }
956        opts.slides.each(function() {
957            var slide = $(this);
958            slide.removeData();
959            slide.removeClass( opts.slideClass );
960            clean( this, 'parsedAttrs', false );
961        });
962    },
963
964    jump: function( index, fx ) {
965        // go to the requested slide
966        var fwd;
967        var opts = this.opts();
968        if ( opts.busy && ! opts.manualTrump )
969            return;
970        var num = parseInt( index, 10 );
971        if (isNaN(num) || num < 0 || num >= opts.slides.length) {
972            opts.API.log('goto: invalid slide index: ' + num);
973            return;
974        }
975        if (num == opts.currSlide) {
976            opts.API.log('goto: skipping, already on slide', num);
977            return;
978        }
979        opts.nextSlide = num;
980        clearTimeout(opts.timeoutId);
981        opts.timeoutId = 0;
982        opts.API.log('goto: ', num, ' (zero-index)');
983        fwd = opts.currSlide < opts.nextSlide;
984        opts._tempFx = fx;
985        opts.API.prepareTx( true, fwd );
986    },
987
988    stop: function() {
989        var opts = this.opts();
990        var pauseObj = opts.container;
991        clearTimeout(opts.timeoutId);
992        opts.timeoutId = 0;
993        opts.API.stopTransition();
994        if ( opts.pauseOnHover ) {
995            if ( opts.pauseOnHover !== true )
996                pauseObj = $( opts.pauseOnHover );
997            pauseObj.off('mouseenter mouseleave');
998        }
999        opts.API.trigger('cycle-stopped', [ opts ]).log('cycle-stopped');
1000    },
1001
1002    reinit: function() {
1003        var opts = this.opts();
1004        opts.API.destroy();
1005        opts.container.cycle();
1006    },
1007
1008    remove: function( index ) {
1009        var opts = this.opts();
1010        var slide, slideToRemove, slides = [], slideNum = 1;
1011        for ( var i=0; i < opts.slides.length; i++ ) {
1012            slide = opts.slides[i];
1013            if ( i == index ) {
1014                slideToRemove = slide;
1015            }
1016            else {
1017                slides.push( slide );
1018                $( slide ).data('cycle.opts').slideNum = slideNum;
1019                slideNum++;
1020            }
1021        }
1022        if ( slideToRemove ) {
1023            opts.slides = $( slides );
1024            opts.slideCount--;
1025            $( slideToRemove ).remove();
1026            if (index == opts.currSlide)
1027                opts.API.advanceSlide( 1 );
1028            else if ( index < opts.currSlide )
1029                opts.currSlide--;
1030            else
1031                opts.currSlide++;
1032
1033            opts.API.trigger('cycle-slide-removed', [ opts, index, slideToRemove ]).log('cycle-slide-removed');
1034            opts.API.updateView();
1035        }
1036    }
1037
1038});
1039
1040// listen for clicks on elements with data-cycle-cmd attribute
1041$(document).on('click.cycle', '[data-cycle-cmd]', function(e) {
1042    // issue cycle command
1043    e.preventDefault();
1044    var el = $(this);
1045    var command = el.data('cycle-cmd');
1046    var context = el.data('cycle-context') || '.cycle-slideshow';
1047    $(context).cycle(command, el.data('cycle-arg'));
1048});
1049
1050
1051})(jQuery);
1052
1053/*! hash plugin for Cycle2;  version: 20130905 */
1054(function($) {
1055"use strict";
1056
1057$(document).on( 'cycle-pre-initialize', function( e, opts ) {
1058    onHashChange( opts, true );
1059
1060    opts._onHashChange = function() {
1061        onHashChange( opts, false );
1062    };
1063
1064    $( window ).on( 'hashchange', opts._onHashChange);
1065});
1066
1067$(document).on( 'cycle-update-view', function( e, opts, slideOpts ) {
1068    if ( slideOpts.hash && ( '#' + slideOpts.hash ) != window.location.hash ) {
1069        opts._hashFence = true;
1070        window.location.hash = slideOpts.hash;
1071    }
1072});
1073
1074$(document).on( 'cycle-destroyed', function( e, opts) {
1075    if ( opts._onHashChange ) {
1076        $( window ).off( 'hashchange', opts._onHashChange );
1077    }
1078});
1079
1080function onHashChange( opts, setStartingSlide ) {
1081    var hash;
1082    if ( opts._hashFence ) {
1083        opts._hashFence = false;
1084        return;
1085    }
1086
1087    hash = window.location.hash.substring(1);
1088
1089    opts.slides.each(function(i) {
1090        if ( $(this).data( 'cycle-hash' ) == hash ) {
1091            if ( setStartingSlide === true ) {
1092                opts.startingSlide = i;
1093            }
1094            else {
1095                var fwd = opts.currSlide < i;
1096                opts.nextSlide = i;
1097                opts.API.prepareTx( true, fwd );
1098            }
1099            return false;
1100        }
1101    });
1102}
1103
1104})(jQuery);
1105
1106/*! loader plugin for Cycle2;  version: 20131121 */
1107(function($) {
1108"use strict";
1109
1110$.extend($.fn.cycle.defaults, {
1111    loader: false
1112});
1113
1114$(document).on( 'cycle-bootstrap', function( e, opts ) {
1115    var addFn;
1116
1117    if ( !opts.loader )
1118        return;
1119
1120    // override API.add for this slideshow
1121    addFn = opts.API.add;
1122    opts.API.add = add;
1123
1124    function add( slides, prepend ) {
1125        var slideArr = [];
1126        if ( $.type( slides ) == 'string' )
1127            slides = $.trim( slides );
1128        else if ( $.type( slides) === 'array' ) {
1129            for (var i=0; i < slides.length; i++ )
1130                slides[i] = $(slides[i])[0];
1131        }
1132
1133        slides = $( slides );
1134        var slideCount = slides.length;
1135
1136        if ( ! slideCount )
1137            return;
1138
1139        slides.css('visibility','hidden').appendTo('body').each(function(i) { // appendTo fixes #56
1140            var count = 0;
1141            var slide = $(this);
1142            var images = slide.is('img') ? slide : slide.find('img');
1143            slide.data('index', i);
1144            // allow some images to be marked as unimportant (and filter out images w/o src value)
1145            images = images.filter(':not(.cycle-loader-ignore)').filter(':not([src=""])');
1146            if ( ! images.length ) {
1147                --slideCount;
1148                slideArr.push( slide );
1149                return;
1150            }
1151
1152            count = images.length;
1153            images.each(function() {
1154                // add images that are already loaded
1155                if ( this.complete ) {
1156                    imageLoaded();
1157                }
1158                else {
1159                    $(this).load(function() {
1160                        imageLoaded();
1161                    }).on("error", function() {
1162                        if ( --count === 0 ) {
1163                            // ignore this slide
1164                            opts.API.log('slide skipped; img not loaded:', this.src);
1165                            if ( --slideCount === 0 && opts.loader == 'wait') {
1166                                addFn.apply( opts.API, [ slideArr, prepend ] );
1167                            }
1168                        }
1169                    });
1170                }
1171            });
1172
1173            function imageLoaded() {
1174                if ( --count === 0 ) {
1175                    --slideCount;
1176                    addSlide( slide );
1177                }
1178            }
1179        });
1180
1181        if ( slideCount )
1182            opts.container.addClass('cycle-loading');
1183
1184
1185        function addSlide( slide ) {
1186            var curr;
1187            if ( opts.loader == 'wait' ) {
1188                slideArr.push( slide );
1189                if ( slideCount === 0 ) {
1190                    // #59; sort slides into original markup order
1191                    slideArr.sort( sorter );
1192                    addFn.apply( opts.API, [ slideArr, prepend ] );
1193                    opts.container.removeClass('cycle-loading');
1194                }
1195            }
1196            else {
1197                curr = $(opts.slides[opts.currSlide]);
1198                addFn.apply( opts.API, [ slide, prepend ] );
1199                curr.show();
1200                opts.container.removeClass('cycle-loading');
1201            }
1202        }
1203
1204        function sorter(a, b) {
1205            return a.data('index') - b.data('index');
1206        }
1207    }
1208});
1209
1210})(jQuery);
1211
1212/*! pager plugin for Cycle2;  version: 20140415 */
1213(function($) {
1214"use strict";
1215
1216$.extend($.fn.cycle.defaults, {
1217    pager:            '> .cycle-pager',
1218    pagerActiveClass: 'cycle-pager-active',
1219    pagerEvent:       'click.cycle',
1220    pagerEventBubble: undefined,
1221    pagerTemplate:    '<span>&bull;</span>'
1222});
1223
1224$(document).on( 'cycle-bootstrap', function( e, opts, API ) {
1225    // add method to API
1226    API.buildPagerLink = buildPagerLink;
1227});
1228
1229$(document).on( 'cycle-slide-added', function( e, opts, slideOpts, slideAdded ) {
1230    if ( opts.pager ) {
1231        opts.API.buildPagerLink ( opts, slideOpts, slideAdded );
1232        opts.API.page = page;
1233    }
1234});
1235
1236$(document).on( 'cycle-slide-removed', function( e, opts, index, slideRemoved ) {
1237    if ( opts.pager ) {
1238        var pagers = opts.API.getComponent( 'pager' );
1239        pagers.each(function() {
1240            var pager = $(this);
1241            $( pager.children()[index] ).remove();
1242        });
1243    }
1244});
1245
1246$(document).on( 'cycle-update-view', function( e, opts, slideOpts ) {
1247    var pagers;
1248
1249    if ( opts.pager ) {
1250        pagers = opts.API.getComponent( 'pager' );
1251        pagers.each(function() {
1252           $(this).children().removeClass( opts.pagerActiveClass )
1253            .eq( opts.currSlide ).addClass( opts.pagerActiveClass );
1254        });
1255    }
1256});
1257
1258$(document).on( 'cycle-destroyed', function( e, opts ) {
1259    var pager = opts.API.getComponent( 'pager' );
1260
1261    if ( pager ) {
1262        pager.children().off( opts.pagerEvent ); // #202
1263        if ( opts.pagerTemplate )
1264            pager.empty();
1265    }
1266});
1267
1268function buildPagerLink( opts, slideOpts, slide ) {
1269    var pagerLink;
1270    var pagers = opts.API.getComponent( 'pager' );
1271    pagers.each(function() {
1272        var pager = $(this);
1273        if ( slideOpts.pagerTemplate ) {
1274            var markup = opts.API.tmpl( slideOpts.pagerTemplate, slideOpts, opts, slide[0] );
1275            pagerLink = $( markup ).appendTo( pager );
1276        }
1277        else {
1278            pagerLink = pager.children().eq( opts.slideCount - 1 );
1279        }
1280        pagerLink.on( opts.pagerEvent, function(e) {
1281            if ( ! opts.pagerEventBubble )
1282                e.preventDefault();
1283            opts.API.page( pager, e.currentTarget);
1284        });
1285    });
1286}
1287
1288function page( pager, target ) {
1289    /*jshint validthis:true */
1290    var opts = this.opts();
1291    if ( opts.busy && ! opts.manualTrump )
1292        return;
1293
1294    var index = pager.children().index( target );
1295    var nextSlide = index;
1296    var fwd = opts.currSlide < nextSlide;
1297    if (opts.currSlide == nextSlide) {
1298        return; // no op, clicked pager for the currently displayed slide
1299    }
1300    opts.nextSlide = nextSlide;
1301    opts._tempFx = opts.pagerFx;
1302    opts.API.prepareTx( true, fwd );
1303    opts.API.trigger('cycle-pager-activated', [opts, pager, target ]);
1304}
1305
1306})(jQuery);
1307
1308/*! prevnext plugin for Cycle2;  version: 20140408 */
1309(function($) {
1310"use strict";
1311
1312$.extend($.fn.cycle.defaults, {
1313    next:           '> .cycle-next',
1314    nextEvent:      'click.cycle',
1315    disabledClass:  'disabled',
1316    prev:           '> .cycle-prev',
1317    prevEvent:      'click.cycle',
1318    swipe:          false
1319});
1320
1321$(document).on( 'cycle-initialized', function( e, opts ) {
1322    opts.API.getComponent( 'next' ).on( opts.nextEvent, function(e) {
1323        e.preventDefault();
1324        opts.API.next();
1325    });
1326
1327    opts.API.getComponent( 'prev' ).on( opts.prevEvent, function(e) {
1328        e.preventDefault();
1329        opts.API.prev();
1330    });
1331
1332    if ( opts.swipe ) {
1333        var nextEvent = opts.swipeVert ? 'swipeUp.cycle' : 'swipeLeft.cycle swipeleft.cycle';
1334        var prevEvent = opts.swipeVert ? 'swipeDown.cycle' : 'swipeRight.cycle swiperight.cycle';
1335        opts.container.on( nextEvent, function(e) {
1336            opts._tempFx = opts.swipeFx;
1337            opts.API.next();
1338        });
1339        opts.container.on( prevEvent, function() {
1340            opts._tempFx = opts.swipeFx;
1341            opts.API.prev();
1342        });
1343    }
1344});
1345
1346$(document).on( 'cycle-update-view', function( e, opts, slideOpts, currSlide ) {
1347    if ( opts.allowWrap )
1348        return;
1349
1350    var cls = opts.disabledClass;
1351    var next = opts.API.getComponent( 'next' );
1352    var prev = opts.API.getComponent( 'prev' );
1353    var prevBoundry = opts._prevBoundry || 0;
1354    var nextBoundry = (opts._nextBoundry !== undefined)?opts._nextBoundry:opts.slideCount - 1;
1355
1356    if ( opts.currSlide == nextBoundry )
1357        next.addClass( cls ).prop( 'disabled', true );
1358    else
1359        next.removeClass( cls ).prop( 'disabled', false );
1360
1361    if ( opts.currSlide === prevBoundry )
1362        prev.addClass( cls ).prop( 'disabled', true );
1363    else
1364        prev.removeClass( cls ).prop( 'disabled', false );
1365});
1366
1367
1368$(document).on( 'cycle-destroyed', function( e, opts ) {
1369    opts.API.getComponent( 'prev' ).off( opts.nextEvent );
1370    opts.API.getComponent( 'next' ).off( opts.prevEvent );
1371    opts.container.off( 'swipeleft.cycle swiperight.cycle swipeLeft.cycle swipeRight.cycle swipeUp.cycle swipeDown.cycle' );
1372});
1373
1374})(jQuery);
1375
1376/*! progressive loader plugin for Cycle2;  version: 20130315 */
1377(function($) {
1378"use strict";
1379
1380$.extend($.fn.cycle.defaults, {
1381    progressive: false
1382});
1383
1384$(document).on( 'cycle-pre-initialize', function( e, opts ) {
1385    if ( !opts.progressive )
1386        return;
1387
1388    var API = opts.API;
1389    var nextFn = API.next;
1390    var prevFn = API.prev;
1391    var prepareTxFn = API.prepareTx;
1392    var type = $.type( opts.progressive );
1393    var slides, scriptEl;
1394
1395    if ( type == 'array' ) {
1396        slides = opts.progressive;
1397    }
1398    else if ($.isFunction( opts.progressive ) ) {
1399        slides = opts.progressive( opts );
1400    }
1401    else if ( type == 'string' ) {
1402        scriptEl = $( opts.progressive );
1403        slides = $.trim( scriptEl.html() );
1404        if ( !slides )
1405            return;
1406        // is it json array?
1407        if ( /^(\[)/.test( slides ) ) {
1408            try {
1409                slides = $.parseJSON( slides );
1410            }
1411            catch(err) {
1412                API.log( 'error parsing progressive slides', err );
1413                return;
1414            }
1415        }
1416        else {
1417            // plain text, split on delimeter
1418            slides = slides.split( new RegExp( scriptEl.data('cycle-split') || '\n') );
1419
1420            // #95; look for empty slide
1421            if ( ! slides[ slides.length - 1 ] )
1422                slides.pop();
1423        }
1424    }
1425
1426
1427
1428    if ( prepareTxFn ) {
1429        API.prepareTx = function( manual, fwd ) {
1430            var index, slide;
1431
1432            if ( manual || slides.length === 0 ) {
1433                prepareTxFn.apply( opts.API, [ manual, fwd ] );
1434                return;
1435            }
1436
1437            if ( fwd && opts.currSlide == ( opts.slideCount-1) ) {
1438                slide = slides[ 0 ];
1439                slides = slides.slice( 1 );
1440                opts.container.one('cycle-slide-added', function(e, opts ) {
1441                    setTimeout(function() {
1442                        opts.API.advanceSlide( 1 );
1443                    },50);
1444                });
1445                opts.API.add( slide );
1446            }
1447            else if ( !fwd && opts.currSlide === 0 ) {
1448                index = slides.length-1;
1449                slide = slides[ index ];
1450                slides = slides.slice( 0, index );
1451                opts.container.one('cycle-slide-added', function(e, opts ) {
1452                    setTimeout(function() {
1453                        opts.currSlide = 1;
1454                        opts.API.advanceSlide( -1 );
1455                    },50);
1456                });
1457                opts.API.add( slide, true );
1458            }
1459            else {
1460                prepareTxFn.apply( opts.API, [ manual, fwd ] );
1461            }
1462        };
1463    }
1464
1465    if ( nextFn ) {
1466        API.next = function() {
1467            var opts = this.opts();
1468            if ( slides.length && opts.currSlide == ( opts.slideCount - 1 ) ) {
1469                var slide = slides[ 0 ];
1470                slides = slides.slice( 1 );
1471                opts.container.one('cycle-slide-added', function(e, opts ) {
1472                    nextFn.apply( opts.API );
1473                    opts.container.removeClass('cycle-loading');
1474                });
1475                opts.container.addClass('cycle-loading');
1476                opts.API.add( slide );
1477            }
1478            else {
1479                nextFn.apply( opts.API );
1480            }
1481        };
1482    }
1483
1484    if ( prevFn ) {
1485        API.prev = function() {
1486            var opts = this.opts();
1487            if ( slides.length && opts.currSlide === 0 ) {
1488                var index = slides.length-1;
1489                var slide = slides[ index ];
1490                slides = slides.slice( 0, index );
1491                opts.container.one('cycle-slide-added', function(e, opts ) {
1492                    opts.currSlide = 1;
1493                    opts.API.advanceSlide( -1 );
1494                    opts.container.removeClass('cycle-loading');
1495                });
1496                opts.container.addClass('cycle-loading');
1497                opts.API.add( slide, true );
1498            }
1499            else {
1500                prevFn.apply( opts.API );
1501            }
1502        };
1503    }
1504});
1505
1506})(jQuery);
1507
1508/*! tmpl plugin for Cycle2;  version: 20121227 */
1509(function($) {
1510"use strict";
1511
1512$.extend($.fn.cycle.defaults, {
1513    tmplRegex: '{{((.)?.*?)}}'
1514});
1515
1516$.extend($.fn.cycle.API, {
1517    tmpl: function( str, opts /*, ... */) {
1518        var regex = new RegExp( opts.tmplRegex || $.fn.cycle.defaults.tmplRegex, 'g' );
1519        var args = $.makeArray( arguments );
1520        args.shift();
1521        return str.replace(regex, function(_, str) {
1522            var i, j, obj, prop, names = str.split('.');
1523            for (i=0; i < args.length; i++) {
1524                obj = args[i];
1525                if ( ! obj )
1526                    continue;
1527                if (names.length > 1) {
1528                    prop = obj;
1529                    for (j=0; j < names.length; j++) {
1530                        obj = prop;
1531                        prop = prop[ names[j] ] || str;
1532                    }
1533                } else {
1534                    prop = obj[str];
1535                }
1536
1537                if ($.isFunction(prop))
1538                    return prop.apply(obj, args);
1539                if (prop !== undefined && prop !== null && prop != str)
1540                    return prop;
1541            }
1542            return str;
1543        });
1544    }
1545});
1546
1547})(jQuery);

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.