PageSourceSearch

https://ndu.edu.ua/modules/mod_bm_slider_for_k2/assets/js/jquery.cycle2.js

js ndu.edu.ua collected 2026-10-02 05:22:35 UTC 47,564 bytes, 1,511 lines download raw bytes

1/*!
2* jQuery Cycle2; build: v20131005
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        opts.API.trigger('cycle-update-view', [ opts, slideOpts, currSlide, isAfter ]);
521        
522        if ( isAfter )
523            opts.API.trigger('cycle-update-view-after', [ opts, slideOpts, currSlide ]);
524    },
525
526    getComponent: function( name ) {
527        var opts = this.opts();
528        var selector = opts[name];
529        if (typeof selector === 'string') {
530            // if selector is a child, sibling combinator, adjancent selector then use find, otherwise query full dom
531            return (/^\s*[\>|\+|~]/).test( selector ) ? opts.container.find( selector ) : $( selector );
532        }
533        if (selector.jquery)
534            return selector;
535        
536        return $(selector);
537    },
538
539    stackSlides: function( curr, next, fwd ) {
540        var opts = this.opts();
541        if ( !curr ) {
542            curr = opts.slides[opts.currSlide];
543            next = opts.slides[opts.nextSlide];
544            fwd = !opts.reverse;
545        }
546
547        // reset the zIndex for the common case:
548        // curr slide on top,  next slide beneath, and the rest in order to be shown
549        $(curr).css('zIndex', opts.maxZ);
550
551        var i;
552        var z = opts.maxZ - 2;
553        var len = opts.slideCount;
554        if (fwd) {
555            for ( i = opts.currSlide + 1; i < len; i++ )
556                $( opts.slides[i] ).css( 'zIndex', z-- );
557            for ( i = 0; i < opts.currSlide; i++ )
558                $( opts.slides[i] ).css( 'zIndex', z-- );
559        }
560        else {
561            for ( i = opts.currSlide - 1; i >= 0; i-- )
562                $( opts.slides[i] ).css( 'zIndex', z-- );
563            for ( i = len - 1; i > opts.currSlide; i-- )
564                $( opts.slides[i] ).css( 'zIndex', z-- );
565        }
566
567        $(next).css('zIndex', opts.maxZ - 1);
568    },
569
570    getSlideIndex: function( el ) {
571        return this.opts().slides.index( el );
572    }
573
574}; // API
575
576// default logger
577$.fn.cycle.log = function log() {
578    /*global console:true */
579    if (window.console && console.log)
580        console.log('[cycle2] ' + Array.prototype.join.call(arguments, ' ') );
581};
582
583$.fn.cycle.version = function() { return 'Cycle2: ' + version; };
584
585// helper functions
586
587function lowerCase(s) {
588    return (s || '').toLowerCase();
589}
590
591// expose transition object
592$.fn.cycle.transitions = {
593    custom: {
594    },
595    none: {
596        before: function( opts, curr, next, fwd ) {
597            opts.API.stackSlides( next, curr, fwd );
598            opts.cssBefore = { opacity: 1, display: 'block' };
599        }
600    },
601    fade: {
602        before: function( opts, curr, next, fwd ) {
603            var css = opts.API.getSlideOpts( opts.nextSlide ).slideCss || {};
604            opts.API.stackSlides( curr, next, fwd );
605            opts.cssBefore = $.extend(css, { opacity: 0, display: 'block' });
606            opts.animIn = { opacity: 1 };
607            opts.animOut = { opacity: 0 };
608        }
609    },
610    fadeout: {
611        before: function( opts , curr, next, fwd ) {
612            var css = opts.API.getSlideOpts( opts.nextSlide ).slideCss || {};
613            opts.API.stackSlides( curr, next, fwd );
614            opts.cssBefore = $.extend(css, { opacity: 1, display: 'block' });
615            opts.animOut = { opacity: 0 };
616        }
617    },
618    scrollHorz: {
619        before: function( opts, curr, next, fwd ) {
620            opts.API.stackSlides( curr, next, fwd );
621            var w = opts.container.css('overflow','hidden').width();
622            opts.cssBefore = { left: fwd ? w : - w, top: 0, opacity: 1, display: 'block' };
623            opts.cssAfter = { zIndex: opts._maxZ - 2, left: 0 };
624            opts.animIn = { left: 0 };
625            opts.animOut = { left: fwd ? -w : w };
626        }
627    }
628};
629
630// @see: http://jquery.malsup.com/cycle2/api
631$.fn.cycle.defaults = {
632    allowWrap:        true,
633    autoSelector:     '.cycle-slideshow[data-cycle-auto-init!=false]',
634    delay:            0,
635    easing:           null,
636    fx:              'fade',
637    hideNonActive:    true,
638    loop:             0,
639    manualFx:         undefined,
640    manualSpeed:      undefined,
641    manualTrump:      true,
642    maxZ:             100,
643    pauseOnHover:     false,
644    reverse:          false,
645    slideActiveClass: 'cycle-slide-active',
646    slideClass:       'cycle-slide',
647    slideCss:         { position: 'absolute', top: 0, left: 0 },
648    slides:          '> img',
649    speed:            500,
650    startingSlide:    0,
651    sync:             true,
652    timeout:          4000,
653    updateView:       -1
654};
655
656// automatically find and run slideshows
657$(document).ready(function() {
658    $( $.fn.cycle.defaults.autoSelector ).cycle();
659});
660
661})(jQuery);
662
663/*! Cycle2 autoheight plugin; Copyright (c) M.Alsup, 2012; version: 20130304 */
664(function($) {
665"use strict";
666
667$.extend($.fn.cycle.defaults, {
668    autoHeight: 0 // setting this option to false disables autoHeight logic
669});    
670
671$(document).on( 'cycle-initialized', function( e, opts ) {
672    var autoHeight = opts.autoHeight;
673    var t = $.type( autoHeight );
674    var resizeThrottle = null;
675    var ratio;
676
677    if ( t !== 'string' && t !== 'number' )
678        return;
679
680    // bind events
681    opts.container.on( 'cycle-slide-added cycle-slide-removed', initAutoHeight );
682    opts.container.on( 'cycle-destroyed', onDestroy );
683
684    if ( autoHeight == 'container' ) {
685        opts.container.on( 'cycle-before', onBefore );
686    }
687    else if ( t === 'string' && /\d+\:\d+/.test( autoHeight ) ) { 
688        // use ratio
689        ratio = autoHeight.match(/(\d+)\:(\d+)/);
690        ratio = ratio[1] / ratio[2];
691        opts._autoHeightRatio = ratio;
692    }
693
694    // if autoHeight is a number then we don't need to recalculate the sentinel
695    // index on resize
696    if ( t !== 'number' ) {
697        // bind unique resize handler per slideshow (so it can be 'off-ed' in onDestroy)
698        opts._autoHeightOnResize = function () {
699            clearTimeout( resizeThrottle );
700            resizeThrottle = setTimeout( onResize, 50 );
701        };
702
703        $(window).on( 'resize orientationchange', opts._autoHeightOnResize );
704    }
705
706    setTimeout( onResize, 30 );
707
708    function onResize() {
709        initAutoHeight( e, opts );
710    }
711});
712
713function initAutoHeight( e, opts ) {
714    var clone, height, sentinelIndex;
715    var autoHeight = opts.autoHeight;
716
717    if ( autoHeight == 'container' ) {
718        height = $( opts.slides[ opts.currSlide ] ).outerHeight();
719        opts.container.height( height );
720    }
721    else if ( opts._autoHeightRatio ) { 
722        opts.container.height( opts.container.width() / opts._autoHeightRatio );
723    }
724    else if ( autoHeight === 'calc' || ( $.type( autoHeight ) == 'number' && autoHeight >= 0 ) ) {
725        if ( autoHeight === 'calc' )
726            sentinelIndex = calcSentinelIndex( e, opts );
727        else if ( autoHeight >= opts.slides.length )
728            sentinelIndex = 0;
729        else 
730            sentinelIndex = autoHeight;
731
732        // only recreate sentinel if index is different
733        if ( sentinelIndex == opts._sentinelIndex )
734            return;
735
736        opts._sentinelIndex = sentinelIndex;
737        if ( opts._sentinel )
738            opts._sentinel.remove();
739
740        // clone existing slide as sentinel
741        clone = $( opts.slides[ sentinelIndex ].cloneNode(true) );
742        
743        // #50; remove special attributes from cloned content
744        clone.removeAttr( 'id name rel' ).find( '[id],[name],[rel]' ).removeAttr( 'id name rel' );
745
746        clone.css({
747            position: 'static',
748            visibility: 'hidden',
749            display: 'block'
750        }).prependTo( opts.container ).addClass('cycle-sentinel cycle-slide').removeClass('cycle-slide-active');
751        clone.find( '*' ).css( 'visibility', 'hidden' );
752
753        opts._sentinel = clone;
754    }
755}    
756
757function calcSentinelIndex( e, opts ) {
758    var index = 0, max = -1;
759
760    // calculate tallest slide index
761    opts.slides.each(function(i) {
762        var h = $(this).height();
763        if ( h > max ) {
764            max = h;
765            index = i;
766        }
767    });
768    return index;
769}
770
771function onBefore( e, opts, outgoing, incoming, forward ) {
772    var h = $(incoming).outerHeight();
773    var duration = opts.sync ? opts.speed / 2 : opts.speed;
774    opts.container.animate( { height: h }, duration );
775}
776
777function onDestroy( e, opts ) {
778    if ( opts._autoHeightOnResize ) {
779        $(window).off( 'resize orientationchange', opts._autoHeightOnResize );
780        opts._autoHeightOnResize = null;
781    }
782    opts.container.off( 'cycle-slide-added cycle-slide-removed', initAutoHeight );
783    opts.container.off( 'cycle-destroyed', onDestroy );
784    opts.container.off( 'cycle-before', onBefore );
785
786    if ( opts._sentinel ) {
787        opts._sentinel.remove();
788        opts._sentinel = null;
789    }
790}
791
792})(jQuery);
793
794/*! caption plugin for Cycle2;  version: 20130306 */
795(function($) {
796"use strict";
797
798$.extend($.fn.cycle.defaults, {
799    caption:          '> .cycle-caption',
800    captionTemplate:  '{{slideNum}} / {{slideCount}}',
801    overlay:          '> .cycle-overlay',
802    overlayTemplate:  '<div>{{title}}</div><div>{{desc}}</div>',
803    captionModule:    'caption'
804});    
805
806$(document).on( 'cycle-update-view', function( e, opts, slideOpts, currSlide ) {
807    if ( opts.captionModule !== 'caption' )
808        return;
809    var el;
810    $.each(['caption','overlay'], function() {
811        var name = this; 
812        var template = slideOpts[name+'Template'];
813        var el = opts.API.getComponent( name );
814        if( el.length && template ) {
815            el.html( opts.API.tmpl( template, slideOpts, opts, currSlide ) );
816            el.show();
817        }
818        else {
819            el.hide();
820        }
821    });
822});
823
824$(document).on( 'cycle-destroyed', function( e, opts ) {
825    var el;
826    $.each(['caption','overlay'], function() {
827        var name = this, template = opts[name+'Template'];
828        if ( opts[name] && template ) {
829            el = opts.API.getComponent( 'caption' );
830            el.empty();
831        }
832    });
833});
834
835})(jQuery);
836
837/*! command plugin for Cycle2;  version: 20130707 */
838(function($) {
839"use strict";
840
841var c2 = $.fn.cycle;
842
843$.fn.cycle = function( options ) {
844    var cmd, cmdFn, opts;
845    var args = $.makeArray( arguments );
846
847    if ( $.type( options ) == 'number' ) {
848        return this.cycle( 'goto', options );
849    }
850
851    if ( $.type( options ) == 'string' ) {
852        return this.each(function() {
853            var cmdArgs;
854            cmd = options;
855            opts = $(this).data('cycle.opts');
856
857            if ( opts === undefined ) {
858                c2.log('slideshow must be initialized before sending commands; "' + cmd + '" ignored');
859                return;
860            }
861            else {
862                cmd = cmd == 'goto' ? 'jump' : cmd; // issue #3; change 'goto' to 'jump' internally
863                cmdFn = opts.API[ cmd ];
864                if ( $.isFunction( cmdFn )) {
865                    cmdArgs = $.makeArray( args );
866                    cmdArgs.shift();
867                    return cmdFn.apply( opts.API, cmdArgs );
868                }
869                else {
870                    c2.log( 'unknown command: ', cmd );
871                }
872            }
873        });
874    }
875    else {
876        return c2.apply( this, arguments );
877    }
878};
879
880// copy props
881$.extend( $.fn.cycle, c2 );
882
883$.extend( c2.API, {
884    next: function() {
885        var opts = this.opts();
886        if ( opts.busy && ! opts.manualTrump )
887            return;
888        
889        var count = opts.reverse ? -1 : 1;
890        if ( opts.allowWrap === false && ( opts.currSlide + count ) >= opts.slideCount )
891            return;
892
893        opts.API.advanceSlide( count );
894        opts.API.trigger('cycle-next', [ opts ]).log('cycle-next');
895    },
896
897    prev: function() {
898        var opts = this.opts();
899        if ( opts.busy && ! opts.manualTrump )
900            return;
901        var count = opts.reverse ? 1 : -1;
902        if ( opts.allowWrap === false && ( opts.currSlide + count ) < 0 )
903            return;
904
905        opts.API.advanceSlide( count );
906        opts.API.trigger('cycle-prev', [ opts ]).log('cycle-prev');
907    },
908
909    destroy: function() {
910        this.stop(); //#204
911
912        var opts = this.opts();
913        var clean = $.isFunction( $._data ) ? $._data : $.noop;  // hack for #184 and #201
914        clearTimeout(opts.timeoutId);
915        opts.timeoutId = 0;
916        opts.API.stop();
917        opts.API.trigger( 'cycle-destroyed', [ opts ] ).log('cycle-destroyed');
918        opts.container.removeData();
919        clean( opts.container[0], 'parsedAttrs', false );
920
921        // #75; remove inline styles
922        if ( ! opts.retainStylesOnDestroy ) {
923            opts.container.removeAttr( 'style' );
924            opts.slides.removeAttr( 'style' );
925            opts.slides.removeClass( opts.slideActiveClass );
926        }
927        opts.slides.each(function() {
928            $(this).removeData();
929            clean( this, 'parsedAttrs', false );
930        });
931    },
932
933    jump: function( index ) {
934        // go to the requested slide
935        var fwd;
936        var opts = this.opts();
937        if ( opts.busy && ! opts.manualTrump )
938            return;
939        var num = parseInt( index, 10 );
940        if (isNaN(num) || num < 0 || num >= opts.slides.length) {
941            opts.API.log('goto: invalid slide index: ' + num);
942            return;
943        }
944        if (num == opts.currSlide) {
945            opts.API.log('goto: skipping, already on slide', num);
946            return;
947        }
948        opts.nextSlide = num;
949        clearTimeout(opts.timeoutId);
950        opts.timeoutId = 0;
951        opts.API.log('goto: ', num, ' (zero-index)');
952        fwd = opts.currSlide < opts.nextSlide;
953        opts.API.prepareTx( true, fwd );
954    },
955
956    stop: function() {
957        var opts = this.opts();
958        var pauseObj = opts.container;
959        clearTimeout(opts.timeoutId);
960        opts.timeoutId = 0;
961        opts.API.stopTransition();
962        if ( opts.pauseOnHover ) {
963            if ( opts.pauseOnHover !== true )
964                pauseObj = $( opts.pauseOnHover );
965            pauseObj.off('mouseenter mouseleave');
966        }
967        opts.API.trigger('cycle-stopped', [ opts ]).log('cycle-stopped');
968    },
969
970    reinit: function() {
971        var opts = this.opts();
972        opts.API.destroy();
973        opts.container.cycle();
974    },
975
976    remove: function( index ) {
977        var opts = this.opts();
978        var slide, slideToRemove, slides = [], slideNum = 1;
979        for ( var i=0; i < opts.slides.length; i++ ) {
980            slide = opts.slides[i];
981            if ( i == index ) {
982                slideToRemove = slide;
983            }
984            else {
985                slides.push( slide );
986                $( slide ).data('cycle.opts').slideNum = slideNum;
987                slideNum++;
988            }
989        }
990        if ( slideToRemove ) {
991            opts.slides = $( slides );
992            opts.slideCount--;
993            $( slideToRemove ).remove();
994            if (index == opts.currSlide)
995                opts.API.advanceSlide( 1 );
996            else if ( index < opts.currSlide )
997                opts.currSlide--;
998            else
999                opts.currSlide++;
1000
1001            opts.API.trigger('cycle-slide-removed', [ opts, index, slideToRemove ]).log('cycle-slide-removed');
1002            opts.API.updateView();
1003        }
1004    }
1005
1006});
1007
1008// listen for clicks on elements with data-cycle-cmd attribute
1009$(document).on('click.cycle', '[data-cycle-cmd]', function(e) {
1010    // issue cycle command
1011    e.preventDefault();
1012    var el = $(this);
1013    var command = el.data('cycle-cmd');
1014    var context = el.data('cycle-context') || '.cycle-slideshow';
1015    $(context).cycle(command, el.data('cycle-arg'));
1016});
1017
1018
1019})(jQuery);
1020
1021/*! hash plugin for Cycle2;  version: 20130905 */
1022(function($) {
1023"use strict";
1024
1025$(document).on( 'cycle-pre-initialize', function( e, opts ) {
1026    onHashChange( opts, true );
1027
1028    opts._onHashChange = function() {
1029        onHashChange( opts, false );
1030    };
1031
1032    $( window ).on( 'hashchange', opts._onHashChange);
1033});
1034
1035$(document).on( 'cycle-update-view', function( e, opts, slideOpts ) {
1036    if ( slideOpts.hash && ( '#' + slideOpts.hash ) != window.location.hash ) {
1037        opts._hashFence = true;
1038        window.location.hash = slideOpts.hash;
1039    }
1040});
1041
1042$(document).on( 'cycle-destroyed', function( e, opts) {
1043    if ( opts._onHashChange ) {
1044        $( window ).off( 'hashchange', opts._onHashChange );
1045    }
1046});
1047
1048function onHashChange( opts, setStartingSlide ) {
1049    var hash;
1050    if ( opts._hashFence ) {
1051        opts._hashFence = false;
1052        return;
1053    }
1054    
1055    hash = window.location.hash.substring(1);
1056
1057    opts.slides.each(function(i) {
1058        if ( $(this).data( 'cycle-hash' ) == hash ) {
1059            if ( setStartingSlide === true ) {
1060                opts.startingSlide = i;
1061            }
1062            else {
1063                var fwd = opts.currSlide < i;
1064                opts.nextSlide = i;
1065                opts.API.prepareTx( true, fwd );
1066            }
1067            return false;
1068        }
1069    });
1070}
1071
1072})(jQuery);
1073
1074/*! loader plugin for Cycle2;  version: 20130307 */
1075(function($) {
1076"use strict";
1077
1078$.extend($.fn.cycle.defaults, {
1079    loader: false
1080});
1081
1082$(document).on( 'cycle-bootstrap', function( e, opts ) {
1083    var addFn;
1084
1085    if ( !opts.loader )
1086        return;
1087
1088    // override API.add for this slideshow
1089    addFn = opts.API.add;
1090    opts.API.add = add;
1091
1092    function add( slides, prepend ) {
1093        var slideArr = [];
1094        if ( $.type( slides ) == 'string' )
1095            slides = $.trim( slides );
1096        else if ( $.type( slides) === 'array' ) {
1097            for (var i=0; i < slides.length; i++ )
1098                slides[i] = $(slides[i])[0];
1099        }
1100
1101        slides = $( slides );
1102        var slideCount = slides.length;
1103
1104        if ( ! slideCount )
1105            return;
1106
1107        slides.hide().appendTo('body').each(function(i) { // appendTo fixes #56
1108            var count = 0;
1109            var slide = $(this);
1110            var images = slide.is('img') ? slide : slide.find('img');
1111            slide.data('index', i);
1112            // allow some images to be marked as unimportant (and filter out images w/o src value)
1113            images = images.filter(':not(.cycle-loader-ignore)').filter(':not([src=""])');
1114            if ( ! images.length ) {
1115                --slideCount;
1116                slideArr.push( slide );
1117                return;
1118            }
1119
1120            count = images.length;
1121            images.each(function() {
1122                // add images that are already loaded
1123                if ( this.complete ) {
1124                    imageLoaded();
1125                }
1126                else {
1127                    $(this).load(function() {
1128                        imageLoaded();
1129                    }).error(function() {
1130                        if ( --count === 0 ) {
1131                            // ignore this slide
1132                            opts.API.log('slide skipped; img not loaded:', this.src);
1133                            if ( --slideCount === 0 && opts.loader == 'wait') {
1134                                addFn.apply( opts.API, [ slideArr, prepend ] );
1135                            }
1136                        }
1137                    });
1138                }
1139            });
1140
1141            function imageLoaded() {
1142                if ( --count === 0 ) {
1143                    --slideCount;
1144                    addSlide( slide );
1145                }
1146            }
1147        });
1148
1149        if ( slideCount )
1150            opts.container.addClass('cycle-loading');
1151        
1152
1153        function addSlide( slide ) {
1154            var curr;
1155            if ( opts.loader == 'wait' ) {
1156                slideArr.push( slide );
1157                if ( slideCount === 0 ) {
1158                    // #59; sort slides into original markup order
1159                    slideArr.sort( sorter );
1160                    addFn.apply( opts.API, [ slideArr, prepend ] );
1161                    opts.container.removeClass('cycle-loading');
1162                }
1163            }
1164            else {
1165                curr = $(opts.slides[opts.currSlide]);
1166                addFn.apply( opts.API, [ slide, prepend ] );
1167                curr.show();
1168                opts.container.removeClass('cycle-loading');
1169            }
1170        }
1171
1172        function sorter(a, b) {
1173            return a.data('index') - b.data('index');
1174        }
1175    }
1176});
1177
1178})(jQuery);
1179
1180/*! pager plugin for Cycle2;  version: 20130525 */
1181(function($) {
1182"use strict";
1183
1184$.extend($.fn.cycle.defaults, {
1185    pager:            '> .cycle-pager',
1186    pagerActiveClass: 'cycle-pager-active',
1187    pagerEvent:       'click.cycle',
1188    pagerTemplate:    '<span>&bull;</span>'
1189});    
1190
1191$(document).on( 'cycle-bootstrap', function( e, opts, API ) {
1192    // add method to API
1193    API.buildPagerLink = buildPagerLink;
1194});
1195
1196$(document).on( 'cycle-slide-added', function( e, opts, slideOpts, slideAdded ) {
1197    if ( opts.pager ) {
1198        opts.API.buildPagerLink ( opts, slideOpts, slideAdded );
1199        opts.API.page = page;
1200    }
1201});
1202
1203$(document).on( 'cycle-slide-removed', function( e, opts, index, slideRemoved ) {
1204    if ( opts.pager ) {
1205        var pagers = opts.API.getComponent( 'pager' );
1206        pagers.each(function() {
1207            var pager = $(this);
1208            $( pager.children()[index] ).remove();
1209        });
1210    }
1211});
1212
1213$(document).on( 'cycle-update-view', function( e, opts, slideOpts ) {
1214    var pagers;
1215
1216    if ( opts.pager ) {
1217        pagers = opts.API.getComponent( 'pager' );
1218        pagers.each(function() {
1219           $(this).children().removeClass( opts.pagerActiveClass )
1220            .eq( opts.currSlide ).addClass( opts.pagerActiveClass );
1221        });
1222    }
1223});
1224
1225$(document).on( 'cycle-destroyed', function( e, opts ) {
1226    var pager = opts.API.getComponent( 'pager' );
1227
1228    if ( pager ) {
1229        pager.children().off( opts.pagerEvent ); // #202
1230        if ( opts.pagerTemplate )
1231            pager.empty();
1232    }
1233});
1234
1235function buildPagerLink( opts, slideOpts, slide ) {
1236    var pagerLink;
1237    var pagers = opts.API.getComponent( 'pager' );
1238    pagers.each(function() {
1239        var pager = $(this);
1240        if ( slideOpts.pagerTemplate ) {
1241            var markup = opts.API.tmpl( slideOpts.pagerTemplate, slideOpts, opts, slide[0] );
1242            pagerLink = $( markup ).appendTo( pager );
1243        }
1244        else {
1245            pagerLink = pager.children().eq( opts.slideCount - 1 );
1246        }
1247        pagerLink.on( opts.pagerEvent, function(e) {
1248            e.preventDefault();
1249            opts.API.page( pager, e.currentTarget);
1250        });
1251    });
1252}
1253
1254function page( pager, target ) {
1255    /*jshint validthis:true */
1256    var opts = this.opts();
1257    if ( opts.busy && ! opts.manualTrump )
1258        return;
1259
1260    var index = pager.children().index( target );
1261    var nextSlide = index;
1262    var fwd = opts.currSlide < nextSlide;
1263    if (opts.currSlide == nextSlide) {
1264        return; // no op, clicked pager for the currently displayed slide
1265    }
1266    opts.nextSlide = nextSlide;
1267    opts.API.prepareTx( true, fwd );
1268    opts.API.trigger('cycle-pager-activated', [opts, pager, target ]);
1269}
1270
1271})(jQuery);
1272
1273
1274/*! prevnext plugin for Cycle2;  version: 20130709 */
1275(function($) {
1276"use strict";
1277
1278$.extend($.fn.cycle.defaults, {
1279    next:           '> .cycle-next',
1280    nextEvent:      'click.cycle',
1281    disabledClass:  'disabled',
1282    prev:           '> .cycle-prev',
1283    prevEvent:      'click.cycle',
1284    swipe:          false
1285});
1286
1287$(document).on( 'cycle-initialized', function( e, opts ) {
1288    opts.API.getComponent( 'next' ).on( opts.nextEvent, function(e) {
1289        e.preventDefault();
1290        opts.API.next();
1291    });
1292
1293    opts.API.getComponent( 'prev' ).on( opts.prevEvent, function(e) {
1294        e.preventDefault();
1295        opts.API.prev();
1296    });
1297
1298    if ( opts.swipe ) {
1299        var nextEvent = opts.swipeVert ? 'swipeUp.cycle' : 'swipeLeft.cycle swipeleft.cycle';
1300        var prevEvent = opts.swipeVert ? 'swipeDown.cycle' : 'swipeRight.cycle swiperight.cycle';
1301        opts.container.on( nextEvent, function(e) {
1302            opts.API.next();
1303        });
1304        opts.container.on( prevEvent, function() {
1305            opts.API.prev();
1306        });
1307    }
1308});
1309
1310$(document).on( 'cycle-update-view', function( e, opts, slideOpts, currSlide ) {
1311    if ( opts.allowWrap )
1312        return;
1313
1314    var cls = opts.disabledClass;
1315    var next = opts.API.getComponent( 'next' );
1316    var prev = opts.API.getComponent( 'prev' );
1317    var prevBoundry = opts._prevBoundry || 0;
1318    var nextBoundry = (opts._nextBoundry !== undefined)?opts._nextBoundry:opts.slideCount - 1;
1319
1320    if ( opts.currSlide == nextBoundry )
1321        next.addClass( cls ).prop( 'disabled', true );
1322    else
1323        next.removeClass( cls ).prop( 'disabled', false );
1324
1325    if ( opts.currSlide === prevBoundry )
1326        prev.addClass( cls ).prop( 'disabled', true );
1327    else
1328        prev.removeClass( cls ).prop( 'disabled', false );
1329});
1330
1331
1332$(document).on( 'cycle-destroyed', function( e, opts ) {
1333    opts.API.getComponent( 'prev' ).off( opts.nextEvent );
1334    opts.API.getComponent( 'next' ).off( opts.prevEvent );
1335    opts.container.off( 'swipeleft.cycle swiperight.cycle swipeLeft.cycle swipeRight.cycle swipeUp.cycle swipeDown.cycle' );
1336});
1337
1338})(jQuery);
1339
1340/*! progressive loader plugin for Cycle2;  version: 20130315 */
1341(function($) {
1342"use strict";
1343
1344$.extend($.fn.cycle.defaults, {
1345    progressive: false
1346});
1347
1348$(document).on( 'cycle-pre-initialize', function( e, opts ) {
1349    if ( !opts.progressive )
1350        return;
1351
1352    var API = opts.API;
1353    var nextFn = API.next;
1354    var prevFn = API.prev;
1355    var prepareTxFn = API.prepareTx;
1356    var type = $.type( opts.progressive );
1357    var slides, scriptEl;
1358
1359    if ( type == 'array' ) {
1360        slides = opts.progressive;
1361    }
1362    else if ($.isFunction( opts.progressive ) ) {
1363        slides = opts.progressive( opts );
1364    }
1365    else if ( type == 'string' ) {
1366        scriptEl = $( opts.progressive );
1367        slides = $.trim( scriptEl.html() );
1368        if ( !slides )
1369            return;
1370        // is it json array?
1371        if ( /^(\[)/.test( slides ) ) {
1372            try {
1373                slides = $.parseJSON( slides );
1374            }
1375            catch(err) {
1376                API.log( 'error parsing progressive slides', err );
1377                return;
1378            }
1379        }
1380        else {
1381            // plain text, split on delimeter
1382            slides = slides.split( new RegExp( scriptEl.data('cycle-split') || '\n') );
1383            
1384            // #95; look for empty slide
1385            if ( ! slides[ slides.length - 1 ] )
1386                slides.pop();
1387        }
1388    }
1389
1390
1391
1392    if ( prepareTxFn ) {
1393        API.prepareTx = function( manual, fwd ) {
1394            var index, slide;
1395
1396            if ( manual || slides.length === 0 ) {
1397                prepareTxFn.apply( opts.API, [ manual, fwd ] );
1398                return;
1399            }
1400
1401            if ( fwd && opts.currSlide == ( opts.slideCount-1) ) {
1402                slide = slides[ 0 ];
1403                slides = slides.slice( 1 );
1404                opts.container.one('cycle-slide-added', function(e, opts ) {
1405                    setTimeout(function() {
1406                        opts.API.advanceSlide( 1 );
1407                    },50);
1408                });
1409                opts.API.add( slide );
1410            }
1411            else if ( !fwd && opts.currSlide === 0 ) {
1412                index = slides.length-1;
1413                slide = slides[ index ];
1414                slides = slides.slice( 0, index );
1415                opts.container.one('cycle-slide-added', function(e, opts ) {
1416                    setTimeout(function() {
1417                        opts.currSlide = 1;
1418                        opts.API.advanceSlide( -1 );
1419                    },50);
1420                });
1421                opts.API.add( slide, true );
1422            }
1423            else {
1424                prepareTxFn.apply( opts.API, [ manual, fwd ] );
1425            }
1426        };
1427    }
1428
1429    if ( nextFn ) {
1430        API.next = function() {
1431            var opts = this.opts();
1432            if ( slides.length && opts.currSlide == ( opts.slideCount - 1 ) ) {
1433                var slide = slides[ 0 ];
1434                slides = slides.slice( 1 );
1435                opts.container.one('cycle-slide-added', function(e, opts ) {
1436                    nextFn.apply( opts.API );
1437                    opts.container.removeClass('cycle-loading');
1438                });
1439                opts.container.addClass('cycle-loading');
1440                opts.API.add( slide );
1441            }
1442            else {
1443                nextFn.apply( opts.API );    
1444            }
1445        };
1446    }
1447    
1448    if ( prevFn ) {
1449        API.prev = function() {
1450            var opts = this.opts();
1451            if ( slides.length && opts.currSlide === 0 ) {
1452                var index = slides.length-1;
1453                var slide = slides[ index ];
1454                slides = slides.slice( 0, index );
1455                opts.container.one('cycle-slide-added', function(e, opts ) {
1456                    opts.currSlide = 1;
1457                    opts.API.advanceSlide( -1 );
1458                    opts.container.removeClass('cycle-loading');
1459                });
1460                opts.container.addClass('cycle-loading');
1461                opts.API.add( slide, true );
1462            }
1463            else {
1464                prevFn.apply( opts.API );
1465            }
1466        };
1467    }
1468});
1469
1470})(jQuery);
1471
1472/*! tmpl plugin for Cycle2;  version: 20121227 */
1473(function($) {
1474"use strict";
1475
1476$.extend($.fn.cycle.defaults, {
1477    tmplRegex: '{{((.)?.*?)}}'
1478});
1479
1480$.extend($.fn.cycle.API, {
1481    tmpl: function( str, opts /*, ... */) {
1482        var regex = new RegExp( opts.tmplRegex || $.fn.cycle.defaults.tmplRegex, 'g' );
1483        var args = $.makeArray( arguments );
1484        args.shift();
1485        return str.replace(regex, function(_, str) {
1486            var i, j, obj, prop, names = str.split('.');
1487            for (i=0; i < args.length; i++) {
1488                obj = args[i];
1489                if ( ! obj )
1490                    continue;
1491                if (names.length > 1) {
1492                    prop = obj;
1493                    for (j=0; j < names.length; j++) {
1494                        obj = prop;
1495                        prop = prop[ names[j] ] || str;
1496                    }
1497                } else {
1498                    prop = obj[str];
1499                }
1500
1501                if ($.isFunction(prop))
1502                    return prop.apply(obj, args);
1503                if (prop !== undefined && prop !== null && prop != str)
1504                    return prop;
1505            }
1506            return str;
1507        });
1508    }
1509});    
1510
1511})(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.