PageSourceSearch

https://banksy.co.uk/assets/js/jquery.cycle2.js

js banksy.co.uk collected 2026-09-24 08:40:30 UTC 47,907 bytes, 1,520 lines download raw bytes

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