PageSourceSearch

https://mesroma.com/modules/mod_jux_horizontal_accordion_slider/assets/js/jquery.jAccordion.js

js mesroma.com collected 2026-10-09 01:40:54 UTC 49,945 bytes, 1,178 lines download raw bytes

1/**
2 * @version		$id: $
3 * @author		JoomlaUX!
4 * @package		Joomla!
5 * @subpackage	mod_jux_horizontal_accordion_slider
6 * @copyright	Copyright (C) 2013 by JoomlaUX. All rights reserved.
7 * @license		http://www.gnu.org/licenses/gpl-3.0.html GNU/GPL version 3, See LICENSE.txt
8 */
9 
10 // The 2 lines below are for jsLint
11/*jslint browser: true*/
12/*global jQuery*/
13
14/*
15 * jAccordion
16 * Version 1.2.2
17 * @requires jQuery v1.4.3 or newer
18 * @requires jQuery easing plugin in most cases
19 * 
20 * Author maniacpc
21 * Created exclusively for http://codecanyon.net
22 * Licensed under codecanyon's regular license:
23 * http://codecanyon.net/licenses/regular_extended
24 *
25 * jAccordion can be bought at http://codecanyon.net/item/jaccordion/512859
26 */
27
28(function ($) {
29	"use strict";
30    var Accordion = function (element, userSettings) {
31        var options = $.extend({}, $.fn.jAccordion.defaults, userSettings),
32            version = '1.2.2',
33            $_accordion = $(element),
34            $slidesWrapper = $(' > .jAccordion-slidesWrapper', $_accordion),
35            $slides = $(' > .jAccordion-slide', $slidesWrapper),
36            slidesNumber = $slides.length,
37            $headers = $(options.headers, $slides),
38			// User-defined size of the accordion via CSS
39            accDefaultSize = {
40                width: parseInt($_accordion.css('max-width'), 10),
41                height: $_accordion.height()
42            },
43			// The actual size of the accordion if responsiveness is used
44            accCurrSize = {
45                width: 0,
46                height: 0
47            },
48            activeSlideSize,	// Vertical/horizontal size of active slide (depends on option "vertical")
49            inactiveSlideSize,	// Vertical/horizontal size of a slide (if no slide is open)
50            shrinkedSlideSize,	// Vertical/horizontal size of a non-active slide (if a slide is open)
51			/* Stores primary and secondary size property. For vertical accordion the primary property is height 
52			 * and for horizontal accordion width.
53			 */
54            sizeProp = {
55                primary: options.vertical ? 'height' : 'width',
56                secondary: options.vertical ? 'width' : 'height'
57            },
58			/* Stores primary and secondary offset properties. For vertical accordion the primary properties are top 
59			 * and bottom and for horizontal accordion left and right.
60			 */
61            offsetProp = {
62				primary1 : options.vertical ? 'top' : 'left',
63				primary2 : options.vertical ? 'bottom' : 'right',
64				secondary1 : options.vertical ? 'left' : 'top',
65				secondary2 : options.vertical ? 'right' : 'bottom'
66			},
67			/* Sum of left and right and top and bottom border widths. These values are used for calculation of
68			 * offset of a slide.
69			 */
70            bordersWidth = {
71                primary: parseInt($slides.eq(0).css('border' + (options.vertical ? 'Top' : 'Left') + 'Width'), 10) +
72                    parseInt($slides.eq(0).css('border' + (options.vertical ? 'Bottom' : 'Right') + 'Width'), 10),
73                secondary: parseInt($slides.eq(0).css('border' + (options.vertical ? 'Left' : 'Top') + 'Width'), 10) +
74                    parseInt($slides.eq(0).css('border' + (options.vertical ? 'Right' : 'Bottom') + 'Width'), 10)
75            },
76            useCloseSlidesAnim = true,	// Determines whether all slides should be closed when cursor leaves the accordion (Depends on option "sticky")
77            resized = false,			// Determines whether width of accordion changed when onResize event occurred
78            $activeSlide = null,
79            activeSlideIndex = -1,
80			/* Variable stores information inidicating whether active slide is completely open, this information is used to determine
81			 * whether to hide elements with attribute data-initEvent="onSlideOpened" of closing slide.
82			 * It's unwanted to hide these elements when displaying of them didn't start.
83			 */
84			activeSlideCompletelyOpen = false,
85			/* Variable stores width of browser window. It's used to determine whether browser width changes.
86			 * IE triggers resize event even when an element size or position is unwanted behaviour, that's why
87			 * handler of resize event is executed only when browser width changes.
88			 */
89			windowWidth = $(window).width(),
90            isAnimated = false, // Stores information about accordion state (isAnimated == true while a slide is opening or closing)
91            autoplay = null, // Variable which stores "Timer" which is used as a representation of autoplay
92            base = this; // Scope
93
94
95        /*
96         * --------------- Public API ---------------
97         */
98
99        // Public variable which stores jQuery object of the accordion.
100        base.$accordion = $_accordion;
101
102        /* Method returns version of the plugin.
103		 *
104		 * @return version of the plugin
105		 */
106        base.getVersion = function () {
107            return version;
108        };
109
110        /* Method opens a slide with specified index.
111		 *
112		 * @param index - index of a slide to be open
113		 *
114		 * @return instance of the plugin
115		 */
116        base.goToSlide = function (index) {
117            $slides.eq(index).triggerHandler('openSlide');
118            return base;
119        };
120
121        /* Method opens the first slide.
122		 *
123		 * @return instance of the plugin
124		 */
125        base.goToFirstSlide = function () {
126            base.goToSlide(0);
127            return base;
128        };
129
130        /* Method opens the last slide.
131		 *
132		 * @return instance of the plugin
133		 */
134        base.goToLastSlide = function () {
135            base.goToSlide(slidesNumber - 1);
136            return base;
137        };
138
139        /* Method opens the next slide or the first slide if none or the last one is open.
140		 *
141		 * @return instance of the plugin
142		 */
143        base.next = function () {
144            if ($activeSlide === null || (activeSlideIndex + 1) === slidesNumber) {
145                base.goToSlide(0);
146            } else {
147                base.goToSlide(activeSlideIndex + 1);
148            }
149            return base;
150        };
151
152        /* Method opens the previous slide or the last slide if none or the first one is open.
153		 *
154		 * @return instance of the plugin
155		 */
156        base.prev = function () {
157            if ($activeSlide === null || activeSlideIndex === 0) {
158                base.goToSlide(slidesNumber - 1);
159            } else {
160                base.goToSlide(activeSlideIndex - 1);
161            }
162            return base;
163        };
164
165        /* Method closes all slides.
166         * Method takes effect only if one of the slide is open and autoplay is disabled.
167         *
168		 * @return instance of the plugin
169		 */
170        base.closeSlides = function () {
171            if ($activeSlide !== null && !options.autoplay) {
172                useCloseSlidesAnim = true;
173                $activeSlide.triggerHandler('closeSlide');
174            }
175            return base;
176        };
177
178        /* Method returns boolean value which determines whether any slide is opening or closing.
179		 *
180		 * @return state of the plugin
181		 */
182        base.isAnimated = function () {
183            return isAnimated;
184        };
185
186        /* Method returns number of slides.
187		 *
188		 * @return number of slides
189		 */
190        base.getSlidesCount = function () {
191            return slidesNumber;
192        };
193
194        /* Method returns active slide (if there is one) as jQuery object or null.
195		 *
196		 * @return active slide as jQuery object
197		 */
198        base.getActiveSlide = function () {
199            return $activeSlide;
200        };
201
202        /* Method returns index of active slide or -1 if none is selected. Slides are numbered from 0.
203		 *
204		 * @return index of active slide (numbered from 0)
205		 */
206        base.getActiveSlideIndex = function () {
207            return activeSlideIndex;
208        };
209
210        /* Method returns boolean value which specifies whether autoplay is paused.
211		 *
212		 * @return state of autoplay functionality
213		 */
214        base.isPaused = function () {
215            if (options.autoplay) {
216                return autoplay.isPaused();
217            }
218            return false;
219        };
220
221
222        /*
223         * --------------- Private functions ---------------
224         */
225
226		/* Timer represents autoplay functionality of plugin.
227		 *
228		 * @param callback - function to be executed when timer finishes countdown
229		 * @param duration - time period after which @callback is called
230         */
231        function Timer(callback, duration) {
232            var timer,
233				startTime,
234				timeLeft = duration,
235                paused = false;
236
237			// Method restarts timer
238            this.restart = function () {
239                startTime = new Date();
240                timeLeft = duration;
241                timer = window.setTimeout(callback, duration);
242            };
243
244			// Method resumes timer
245            this.resume = function () {
246                if (!isAnimated) {
247                    startTime = new Date();
248                    timer = window.setTimeout(callback, timeLeft);
249                }
250                paused = false;
251                // Callback function to be executed when autoplay is resumed
252                if ($.isFunction(options.onResume)) {
253                    options.onResume.call(base, {
254                        remainingTime: timeLeft
255                    });
256                }
257            };
258
259			// Method stops timer. It can't be resumed again
260            this.stop = function () {
261                clearTimeout(timer);
262                timeLeft = duration;
263            };
264
265			// Method only pauses timer, which means that it can be resumed again
266            this.pause = function () {
267                if (!isAnimated) {
268                    clearTimeout(timer);
269                    timeLeft -= new Date() - startTime;
270                }
271                paused = true;
272                // Callback function to be executed when autoplay gets paused
273                if ($.isFunction(options.onPause)) {
274                    options.onPause.call(base);
275                }
276            };
277
278			// Method returns state of timer
279            this.isPaused = function () {
280                return paused;
281            };
282        }
283
284		/* Function calculates final size (width/height) of a slide specified by index.
285		 *
286		 * @param index - index of a slide (numbered from 0)
287		 *
288		 * @return final size of a slide specified by index
289		 */
290        function getSlideFinalSize(index) {
291			// No slide is active
292            if (activeSlideIndex === -1) {
293                return inactiveSlideSize;
294            }
295			// There is active slide but its index is not equal to the one passed to function
296            if (index !== activeSlideIndex) {
297                return shrinkedSlideSize;
298            }
299			// Passed index is equal to index of active slide but active slide size is same for every slide
300            if (!options.activeSlideAutoHeight) {
301                return activeSlideSize;
302            }
303			/* option activeSlideAutoHeight is enabled, which means that height of every slide (when they are active) can vary
304			 * so it's necessary to recalculate size of active slide.
305			 */
306			activeSlideSize = $slides.eq(index).children('.jAccordion-slideWrapper').height() + bordersWidth.primary;
307            return activeSlideSize;
308        }
309
310        /* Function calculates final left/top offset of a slide specified by index
311		 *
312		 * @param index - index of a slide (numbered from 0)
313		 *
314		 * @return primary offset of a slide specified by index
315		 */
316        function getSlideFinalOffset(index) {
317			// No slide is active
318            if (activeSlideIndex === -1) {
319                return index * (inactiveSlideSize + options.spacing);
320            }
321			// Passed index is lower or equal to index of active slide
322            if (index <= activeSlideIndex) {
323                return index * (shrinkedSlideSize + options.spacing);
324            }
325			// Passed index is higher than index of active slide
326            return activeSlideSize + options.spacing + (index - 1) * (shrinkedSlideSize + options.spacing);
327        }
328
329		/* Function returns final left/top and right/bottom offset of a slide specified by index.
330		 *
331		 * @param index - index of a slide (numbered from 0)
332		 *
333		 * @return map of final css properties (offset) of a slide specified by index
334
335		 */
336        function getSlideFinalStyle(index) {
337			var finalPropsMap = {},
338				sizeTemp = getSlideFinalSize(index);
339			finalPropsMap[offsetProp.primary1] = getSlideFinalOffset(index);
340            finalPropsMap[offsetProp.primary2] = Math.max(0, accCurrSize[sizeProp.primary] - finalPropsMap[offsetProp.primary1] - sizeTemp);
341			return finalPropsMap;
342        }
343
344		/* Function finds out which slides are going to be animated (final left/top or final right/bottom offset differs from current values)
345		 * and whether size of the whole accordion is going to change.
346		 *
347		 * @return object containing all kinds of attributes necessary for animation of opening/closing slide
348		 */
349		function precalcAnimProps() {
350			var $currSlide,
351				currSlideIndex,
352				firstAnimatedSlideFinalStyle = {},	//Map of final css properties of the first animated slide
353				accStartCSSMap = null,		// Map of css properties assigned to accordion before start of animation
354				slidePropsMap = {},			// Map of final css properties of a slide
355				animSlidesStartStyle = [],	// Array of properties maps assigned to slides which are going to be animated
356				/* Array which stores slides which are going to be animated so only these slides are going to be effected 
357				 * inside the step function of animation (improves performance).
358				 */
359				$animatedSlides = [],
360				slideStartCSSMap = {};	// Map of css properties assigned to a slide before start of the animation
361			if (options.accordionAutoSize) {
362				accStartCSSMap = {};
363				accStartCSSMap[sizeProp.primary] = $_accordion[sizeProp.primary]();
364				// Calculate final size of accordion when a slide is going to open
365				if (activeSlideIndex > -1) {
366					if (options.activeSlideAutoHeight) {
367						getSlideFinalSize(activeSlideIndex);
368					}
369					accCurrSize[sizeProp.primary] = activeSlideSize + (slidesNumber - 1) * (shrinkedSlideSize + options.spacing);
370				} else {	// Calculate final size of accordion when all slides are going to close
371					accCurrSize[sizeProp.primary] = slidesNumber * (inactiveSlideSize + options.spacing) - options.spacing;
372				}
373				// Save values important for animation only if current size of accordion differs from final size
374				if (accStartCSSMap[sizeProp.primary] !== accCurrSize[sizeProp.primary]) {
375					// Precalculated value which would have to be calculated in every step of animation
376					accStartCSSMap[sizeProp.primary + 'PreCalc'] = accStartCSSMap[sizeProp.primary] - accCurrSize[sizeProp.primary];
377				} else {
378					accStartCSSMap = null;
379				}
380			}
381			$slides.each(function () {
382				$currSlide = $(this);
383				currSlideIndex = $currSlide.prevAll('.jAccordion-slide').length;
384				slidePropsMap = getSlideFinalStyle(currSlideIndex);
385				// top/left offset of the slide before start of animation (depends on option "vertical").
386				slideStartCSSMap[offsetProp.primary1] = $currSlide.position()[offsetProp.primary1];
387				// bottom/right offset of the slide before start of animation (depends on option "vertical").
388				slideStartCSSMap[offsetProp.primary2] = parseFloat($currSlide.css(offsetProp.primary2), 10);
389				// Store only slides which are going to be animated. i.e. their offset is going to change
390				if ((slideStartCSSMap[offsetProp.primary1] !== slidePropsMap[offsetProp.primary1]) || (slideStartCSSMap[offsetProp.primary2] !== slidePropsMap[offsetProp.primary2])) {
391					// Precalculated value which would have to be calculated in every step of animation
392					slideStartCSSMap[offsetProp.primary1 + 'PreCalc'] = slideStartCSSMap[offsetProp.primary1] - slidePropsMap[offsetProp.primary1];
393					if ($animatedSlides.length !== 0) {
394						// Precalculated value which would have to be calculated in every step of animation
395						slideStartCSSMap[offsetProp.primary2 + 'PreCalc'] = slideStartCSSMap[offsetProp.primary2] - slidePropsMap[offsetProp.primary2];
396					} else {
397						delete slidePropsMap[offsetProp.primary1];
398						firstAnimatedSlideFinalStyle = slidePropsMap;
399					}
400					animSlidesStartStyle.push(slideStartCSSMap);
401					$animatedSlides.push($currSlide);
402				}
403				slideStartCSSMap = {};
404			});
405			return {
406				accPrecalcProps : accStartCSSMap,
407				firstAnimSlideFinalStyle : firstAnimatedSlideFinalStyle,
408				$animSlides : $animatedSlides,
409				animSlidesPrecalcProps : animSlidesStartStyle
410			};
411		}
412
413		/* Function sets animated elements of a specific slide to their starting positions.
414		 *
415		 * @param $elem - an animated element which is supposed to be hidden or displayed
416		 * @param show - boolean variable specifying whether animated element will be displayed or hidden
417		 */
418		function showHideAnimElem($elem, show) {
419			var moveDirection = $elem.attr('data-moveDirection'),
420                offset = $elem.attr('data-offset'),
421				elemFinalProps = {},
422                fade = $elem.attr('data-fade') === 'true',
423				transitionSpeed,
424				transitionEasing,
425				elemVisibility = {};
426			if (!!offset && !!moveDirection) {
427				elemFinalProps[moveDirection] = show ? ('-=' + offset) : ('+=' + offset);
428			}
429			if (show) {
430				transitionSpeed = parseInt($elem.attr('data-speed'), 10);
431				transitionEasing = $elem.attr('data-easing');
432                transitionSpeed = (!!transitionSpeed) ? transitionSpeed : 750;
433				transitionEasing = (!!transitionEasing) ? transitionEasing : 'swing';
434				if (fade) {
435					elemFinalProps.opacity = 1;
436					// Restore z-index of faded elements
437					$elem.css('z-index', $elem.data('defaultIndex'));
438				}
439				$elem
440					.animate(elemFinalProps, transitionSpeed, transitionEasing, function () {
441						/* Remove filter from animated element (applies to IE7 or IE8) so its 
442						 * overall look is smooth at least after animation finished.
443						 */
444						if ($.browser.msie) {
445							$(this)[0].style.removeAttribute('filter');
446						}
447					});
448			} else {
449				if (fade) {
450					elemFinalProps.opacity = 0;
451					elemVisibility['z-index'] = -999;	// Element is "send to back" so it's impossible to click it
452				}
453				/* Element is moved to its final state using stop(true, true) and then moved back to starting state.
454				 * method animate() is used instead of method css() because css() supports += and -= since jQuery 
455				 * version 1.6 but animate supports this functionality in earlier versions (including 1.4.3
456				 * which is the oldest version jAccordion works with).
457				 * Default z-index is saved so it can be restored when the element is displayed.
458				 */
459				$elem
460					.stop(true, true)
461					.data('defaultIndex', $elem.css('z-index'))
462					.animate(elemFinalProps, 0).css(elemVisibility);
463			}
464		}
465
466		/* Function sets animated elements of a specific slide to their starting positions.
467		 *
468		 * @param $slide - a slide whose elements are initialized
469		 */
470        function initAnimElems($slide) {
471            $('*[data-initEvent]', $slide).each(function () {
472				/* Display all hidden (animated) elements. The elements are never really hidden,
473				 * they have visibility: hidden and negative z-index because elements with display: none
474				 * don't occupy any space which would cause problems to option activeSlideAutoHeight.
475				 * Their position is set to relative (if not absolute already) so z-index takes effect.
476				 */
477				$(this).css({
478					'position' : $(this).css('position') === 'absolute' ? 'absolute' : 'relative',
479					'display' : 'block'
480				});
481				if ($(this).attr('data-initEvent') !== 'onSlideStartClosing') {
482					showHideAnimElem($(this), false);
483				}
484            });
485        }
486
487        /* Function displays, delays or hides appropriate elements of a slide
488		 *
489		 * @param $slide - jQuery object containing an HTML element whose elements will be shown or hidden
490		 * @param initEvent - value of attribute data-initEvent of an HTML element which specifies the affected elements
491		 * @param show - boolean variable specifying whether elements of the slide will be shown or hidden
492		 */
493        function showHideAnimElems($slide, initEvent, show) {
494            $('*[data-initEvent=' + initEvent + ']', $slide).each(function () {
495                var $currElem = $(this),
496                    transitionDelay = parseInt($currElem.attr('data-delay'), 10);
497                transitionDelay = (!!transitionDelay) ? transitionDelay : 0;
498				if (show) {
499					if (transitionDelay === 0) {
500						showHideAnimElem($(this), true);
501					} else {
502						/* Delay of displaying animated element.
503						 * State of delay and timer (setTimeout()) are stored in data of the animated element so the delay 
504						 * can be interrupted if slide is closed before the animation even started.
505						 * jQuery method delay() cannot be used because it's improperly stopped by method stop(true, true).
506						 * setTimeout() method of javascript and $.proxy() method of jQuery are used instead.
507						 */
508						$currElem.data(
509							{
510								'delayState' : 'running',
511								'timerDelay' : setTimeout($.proxy(function () {
512									showHideAnimElem($(this).data('delayState', 'finished'), true);
513								}, $currElem.get(0)), transitionDelay)
514							}
515						);
516					}
517				} else {
518					/* Delayed animated element which hasn't been displayed yet doesn't have to be hidden
519					 * because its displaying hasn't started.
520					 */
521					if (transitionDelay > 0 && $currElem.data('delayState') === 'running') {
522						clearTimeout($currElem.data('delayState', 'finished').data('timerDelay'));
523					} else {
524						showHideAnimElem($(this), false);
525					}
526				}
527            });
528        }
529
530		/* Function removes and sets approprieate attributes/css style to achieve scaling of images.
531		 * 
532		 * Note: Only images with class 'jAccordion-img' are scaled
533		 */
534		function scaleImages() {
535			var imagesCSSMap = {};
536			if (options.scaleImgs === 'fit') {
537				imagesCSSMap.width = '100%';
538				imagesCSSMap.height = '100%';
539			} else if (options.scaleImgs === 'fitWidth') {
540				imagesCSSMap.width = '100%';
541			} else {
542				imagesCSSMap.height = '100%';
543			}
544			$('img.jAccordion-img', $slides)
545					.removeAttr('width')
546					.removeAttr('height')
547					.css(imagesCSSMap);
548		}
549
550		// Function initializes previous and next buttons events
551        function initBtnsEvents() {
552            if (options.prevBtn !== null) {
553                (options.prevBtn).click(function (e) {
554					/* Propagation of click event has to be stopped because clicking button placed inside a slide
555					 * would also trigger event 'openSlide'.
556					 */
557                    e.stopPropagation();
558                    if ((!options.disableBtnsDuringTransition) || (options.disableBtnsDuringTransition && !isAnimated)) {
559                        base.prev();
560                    }
561                });
562            }
563            if (options.nextBtn !== null) {
564                (options.nextBtn).click(function (e) {
565					/* Propagation of click event has to be stopped because clicking button placed inside a slide
566					 * would also trigger event 'openSlide'.
567					 */
568                    e.stopPropagation();
569                    if ((!options.disableBtnsDuringTransition) || (options.disableBtnsDuringTransition && !isAnimated)) {
570                        base.next();
571                    }
572                });
573            }
574        }
575
576		/* Function "disables" links of a specific slide using method of jQuery preventDefault().
577		 *
578		 * @param $slide - jQuery object containing an HTML element whose links will be disabled
579		 */
580        function disableLinks($slide) {
581			if (!$_accordion.hasClass('jAccordion-keepLinksEnabled')) {
582				$('a:not(.jAccordion-keepEnabled)', $slide).bind('click.smartLink', function (e) {
583					e.preventDefault();
584				});
585			}
586        }
587
588        /* Function enables links of a slide by unbinding click event in namespace smartLink
589		 * so click event handler created by user is not affected.
590		 *
591		 * @param $slide - jQuery object containing an HTML element whose links will be enabled
592		 */
593        function enableLinks($slide) {
594			if (!$_accordion.hasClass('jAccordion-keepLinksEnabled')) {
595				$('a:not(.jAccordion-keepEnabled)', $slide).unbind('click.smartLink');
596			}
597        }
598
599		/* Function intitializes events of a slide.
600		 *
601		 * @param $slide - jQuery object containing an HTML element whose events will be initialized
602		 */
603        function initSlideEvents($slide) {
604            var currSlideIndex = $slide.prevAll('.jAccordion-slide').length;
605			//Close slide by clicking header inside the slide
606            if ($headers !== null) {
607                $headers.eq(currSlideIndex).click(function (e) {
608					/* It's necessary to check activeSlideIndex first because $activeSlide could be null and 
609					 * $activeSlide[0] would cause an error.
610					 */
611                    if (activeSlideIndex !== -1 && $(this).closest('.jAccordion-slide')[0] === $activeSlide[0]) {
612                        e.stopPropagation();
613                        base.closeSlides();
614                    }
615                });
616            }
617
618            $slide.bind(options.event, function () {
619                $_accordion.focus();	//Activate this instance of jAccordion so only this one can be controlled by keyboard
620                $(this).triggerHandler('openSlide');
621            }).bind({
622                'openSlide': function () {
623                    /* In case there is no active slide or user tries to open non-open slide then a slide is open.
624                     * DOM comparison method is used to determine whether user tries to open slide which is already open.
625                     */
626                    if (activeSlideIndex === -1 || $(this)[0] !== $activeSlide[0]) {
627                        isAnimated = true;
628                        $slides.stop(true);
629                        if (options.autoplay) {
630                            autoplay.stop();
631                        }
632                        // Close previously open slide
633                        if ($activeSlide !== null) {
634                            useCloseSlidesAnim = false;
635                            $activeSlide.triggerHandler('closeSlide');
636                        }
637                        $activeSlide = $(this).addClass(options.activeSlideClass);
638                        
639                       jQuery('.jAccordion-slide.active_slide .title').css({
640                            display: 'none'
641                        });
642
643                        activeSlideIndex = $activeSlide.prevAll('.jAccordion-slide').length;
644
645						var animProps = precalcAnimProps(),
646							animSlidesCount = animProps.$animSlides.length;
647                        // Callback function to be executed when a slide starts opening
648                        if ($.isFunction(options.onSlideStartOpening)) {
649                            options.onSlideStartOpening.call(base, {
650                                $slide: $activeSlide,
651                                index: activeSlideIndex
652                            });
653                        }
654                        // Display appropriate elements of opening slide
655                        showHideAnimElems($activeSlide, 'onSlideStartOpening', true);
656                        // Hide elements (of opening slide) which are visible when the slide is closed
657                        showHideAnimElems($activeSlide, 'onSlideStartClosing', false);
658                        // Animate only right/bottom offset of the first animated slide and set offset of the others inside the step function
659                        animProps.$animSlides[0].animate(animProps.firstAnimSlideFinalStyle, {
660                            duration: options.transitionSpeed,
661                            easing: options.easing,
662                            step: function (now, fx) {
663								var i;
664								// Set left/top offset of first animated slide
665								animProps.$animSlides[0]
666										.css(offsetProp.primary1,
667											 animProps.animSlidesPrecalcProps[0][offsetProp.primary1] - animProps.animSlidesPrecalcProps[0][offsetProp.primary1 + 'PreCalc'] * fx.pos);
668								// Set left/top and right/bottom offset of animated slides (except the first one)
669								for (i = 1; i < animSlidesCount; i = i + 1) {
670                                    animProps.$animSlides[i]
671										.css(offsetProp.primary1,
672											 animProps.animSlidesPrecalcProps[i][offsetProp.primary1] - animProps.animSlidesPrecalcProps[i][offsetProp.primary1 + 'PreCalc'] * fx.pos)
673										.css(offsetProp.primary2,
674											 animProps.animSlidesPrecalcProps[i][offsetProp.primary2] - animProps.animSlidesPrecalcProps[i][offsetProp.primary2 + 'PreCalc'] * fx.pos);
675                                }
676								// Set height of accordion (if necessary)
677								if (!!animProps.accPrecalcProps) {
678                                    $_accordion.css(sizeProp.primary, animProps.accPrecalcProps[sizeProp.primary] - animProps.accPrecalcProps[sizeProp.primary + 'PreCalc'] * fx.pos);
679                                }
680                            },
681                            complete: function () {
682								isAnimated = false;
683								activeSlideCompletelyOpen = true;
684                                // Callback function to be executed after a slide is completely open
685                                if ($.isFunction(options.onSlideOpened)) {
686                                    options.onSlideOpened.call(base, {
687                                        $slide: $activeSlide,
688                                        index: activeSlideIndex
689                                    });
690                                }
691                                // Display appropriate elements when the slide is completely open
692                                showHideAnimElems($activeSlide, 'onSlideOpened', true);
693								if (options.autoplay && !autoplay.isPaused()) {
694                                    autoplay.restart();
695                                }
696                                enableLinks($activeSlide);
697								/* Add scrollbars if the slide has class jAccordion-scrollbar or accordion has class jAccordion-scrollbars.
698								 * Note: Value "auto" makes scrollbar visible only when necessary.
699								 */
700								if ($activeSlide.hasClass('jAccordion-scrollbar') || $_accordion.hasClass('jAccordion-scrollbars')) {
701									$activeSlide.children('.jAccordion-slideWrapper')
702										.css('overflow-' + (options.vertical ? 'y' : 'x'), 'auto')
703										.css('overflow-' + (options.vertical ? 'x' : 'y'), 'hidden');
704								}
705                            }
706                        });
707                    }
708                },
709                'closeSlide': function () {
710                    isAnimated = true;
711                    disableLinks($activeSlide);
712					var $closingSlide = $activeSlide,
713						closingSlideIndex = activeSlideIndex,
714						animProps,
715						animSlidesCount;
716					// Remove class (added to active slide), scroll slide back to left and top and remove scrollbar of closing slide
717					$activeSlide
718						.removeClass(options.activeSlideClass)
719						.children('.jAccordion-slideWrapper')
720						.scrollLeft(0)
721						.scrollTop(0)
722						.css({
723							'overflow-x' : '',
724							'overflow-y' : ''
725						});
726
727                    jQuery('.jAccordion-slide .title').css({
728                            display: 'block',
729                            transition: '2s'
730                        });
731                    $activeSlide = null;
732                    activeSlideIndex = -1;
733                    // Callback function to be executed when a slide starts closing
734                    if ($.isFunction(options.onSlideStartClosing)) {
735                        options.onSlideStartClosing.call(base, {
736                            $slide: $closingSlide,
737                            index: closingSlideIndex
738                        });
739                    }
740                    // Hide appropriate elements of closing slide
741                    showHideAnimElems($closingSlide, 'onSlideStartOpening', false);
742                    if (activeSlideCompletelyOpen) {
743						showHideAnimElems($closingSlide, 'onSlideOpened', false);
744						activeSlideCompletelyOpen = false;
745					}
746					// Show elements which are visible when the slide is closed
747                    showHideAnimElems($closingSlide, 'onSlideStartClosing', true);
748                    if (useCloseSlidesAnim) {
749						$slides.stop(true);
750						animProps = precalcAnimProps();
751						animSlidesCount = animProps.$animSlides.length;
752						// Animate only right/bottom offset of the first animated slide and set offset of the others inside the step function
753                        animProps.$animSlides[0].animate(animProps.firstAnimSlideFinalStyle, {
754                            duration: options.transitionSpeed,
755                            easing: options.easing,
756                            step: function (now, fx) {
757								var i;
758								// Set left/top offset of first animated slide
759								animProps.$animSlides[0]
760										.css(offsetProp.primary1,
761											 animProps.animSlidesPrecalcProps[0][offsetProp.primary1] - animProps.animSlidesPrecalcProps[0][offsetProp.primary1 + 'PreCalc'] * fx.pos);
762								// Set left/top and right/bottom offset of animated slides (except the first one)
763								for (i = 1; i < animSlidesCount; i = i + 1) {
764                                    animProps.$animSlides[i]
765										.css(offsetProp.primary1,
766											 animProps.animSlidesPrecalcProps[i][offsetProp.primary1] - animProps.animSlidesPrecalcProps[i][offsetProp.primary1 + 'PreCalc'] * fx.pos)
767										.css(offsetProp.primary2,
768											 animProps.animSlidesPrecalcProps[i][offsetProp.primary2] - animProps.animSlidesPrecalcProps[i][offsetProp.primary2 + 'PreCalc'] * fx.pos);
769                                }
770								// Set height of accordion (if necessary)
771								if (!!animProps.accPrecalcProps) {
772                                    $_accordion.css(sizeProp.primary, animProps.accPrecalcProps[sizeProp.primary] - animProps.accPrecalcProps[sizeProp.primary + 'PreCalc'] * fx.pos);
773                                }
774                            },
775                            complete: function () {
776                                isAnimated = false;
777                            }
778                        });
779                    }
780                }
781            });
782        }
783
784		/* Function sets some css properties of a slide.
785		 *
786		 * @param $slide - jQuery object containing an HTML element whose style will be initialized
787		 */
788        function initSlideStyle($slide) {
789            var slideIndex = $slide.prevAll('.jAccordion-slide').length,
790				slidePropsMap = getSlideFinalStyle(slideIndex);
791            slidePropsMap.position = 'absolute';
792            slidePropsMap[offsetProp.secondary1] = slidePropsMap[offsetProp.secondary2] = 0;
793
794			$slide
795				.css(slidePropsMap)
796				.children()
797				.wrapAll('<div class="jAccordion-slideWrapper" />')
798				.parent('.jAccordion-slideWrapper')
799				.css(sizeProp.primary, options.activeSlideAutoHeight ? 'auto' : activeSlideSize - bordersWidth.primary)
800				.css(sizeProp.secondary, accCurrSize[sizeProp.secondary] - bordersWidth.secondary)
801				.css({'position' : 'relative', 'filter' : 'inherit'});
802        }
803
804		// Function changes size of accordion.
805        function changeAccordionSize() {
806			$_accordion
807				.css(sizeProp.primary, accCurrSize[sizeProp.primary])
808				.css(sizeProp.secondary, accCurrSize[sizeProp.secondary]);
809        }
810
811		/* Function recalculates size of accordion and variables which depend on it.
812		 * This function is called for the first time during initialization of the plugin and
813		 * it's necessary to calculate all kinds of values even though size of accordion hasn't changed.
814		 *
815		 * @param firstCall - boolean variable specifying whether this function is called for the first time
816		 */
817        function recalcAccordionVars(firstCall) {
818            var prevWidth = $_accordion.width(),
819				ratio;
820            $_accordion.css('width', '');
821            ratio = $_accordion.width() / accDefaultSize.width;
822            if (prevWidth !== $_accordion.width() || firstCall) {
823                accCurrSize.width = Math.round(accDefaultSize.width * ratio);
824                /* Ratio for vertical accordion (with option "keepAspectRatio" disabled) is set to 1 => 
825				 * height of active slide, inactive slide and shrinked slide won't change.
826				 * Note: Ratio can't be set to 1 for horizontal accordion because it would cause static 
827				 * width of slides.
828				 */
829				if (!options.keepAspectRatio && options.vertical) {
830                    ratio = 1;
831                }
832                accCurrSize.height = Math.round(accDefaultSize.height * (options.keepAspectRatio ? ratio : 1));
833                if (options.inactiveSlideSize > 0) {
834                    inactiveSlideSize = shrinkedSlideSize = Math.round((options.inactiveSlideSize) * ratio);
835					if (!options.activeSlideAutoHeight) {
836	                    activeSlideSize = accCurrSize[sizeProp.primary] - (inactiveSlideSize + options.spacing) * (slidesNumber - 1);
837					} else if (activeSlideIndex > -1) {
838						activeSlideSize = $activeSlide
839							.children('.jAccordion-slideWrapper')
840							.css({width : accCurrSize.width - bordersWidth.secondary})
841							.height() + bordersWidth.primary;
842					}
843                } else {
844                    activeSlideSize = Math.round((options.activeSlideSize) * ratio);
845                    inactiveSlideSize = Math.round((accCurrSize[sizeProp.primary] - (options.spacing * (slidesNumber - 1))) / slidesNumber);
846                    shrinkedSlideSize = Math.max(0, Math.round((accCurrSize[sizeProp.primary] - activeSlideSize) / (slidesNumber - 1)) - options.spacing);
847                }
848				if (options.accordionAutoSize) {
849					if (activeSlideIndex > -1) {
850						accCurrSize[sizeProp.primary] = activeSlideSize + (slidesNumber - 1) * (shrinkedSlideSize + options.spacing);
851					} else {
852						accCurrSize[sizeProp.primary] = (inactiveSlideSize + options.spacing) * slidesNumber - options.spacing;
853					}
854				}
855				resized = true;
856            } else {
857                /* If width of accordion didn't change it has to be set back because it was removed in the beginining of this function
858                 * and without setting it back its width would change to max-width, which would basically disable responsiveness.
859                 */
860                changeAccordionSize();
861                resized = false;
862            }
863        }
864
865		/* Function initializes events of the accordion such as mouseenter, mouseleave,
866		 * onResize event and keys events.
867		 */
868        function initAccordionEvents() {
869            $slidesWrapper.bind({
870                /* Callback function which is executed when mouse enters accordion.
871                 * Specifically it's executed when mouse enters .accordion > .jAccordion-slidesWrapper
872                 */
873                mouseenter: function () {
874                    if ($.isFunction(options.onAccordionMouseEnter)) {
875                        options.onAccordionMouseEnter.call(base);
876                    }
877                    if (options.autoplay && options.pauseOnHover) {
878                        autoplay.pause();
879                    }
880                },
881                /* Callback function which is executed when mouse leaves accordion.
882                 * Specifically it's executed when mouse leaves .accordion > .jAccordion-slidesWrapper.
883                 */
884                mouseleave: function () {
885                    /* Active slide is closed only when mouse leaves .accordion > .jAccordion-slidesWrapper,
886					 * which means that cursor can be moved over the space between slides 
887					 * (if option "spacing" is specified) and slides won't close.
888                     */
889                    if (!options.sticky) {
890                        useCloseSlidesAnim = true;
891                        $activeSlide.triggerHandler('closeSlide');
892                    }
893                    if ($.isFunction(options.onAccordionMouseLeave)) {
894                        options.onAccordionMouseLeave.call(base);
895                    }
896                    /* It's unwanted to resume autoplay while a slide is opening.
897                     * In fact the callback onResume is fired anyway but autoplay will start
898                     * after a slide is fully open.
899                     */
900                    if (options.autoplay && options.pauseOnHover) {
901                        autoplay.resume();
902                    }
903                }
904            });
905
906            /* ----- Responsiveness -----
907             * All animations are immediately finished when size of the accordion is changed.
908             */
909            if (options.responsive) {
910                $(window).resize(function () {
911					/* Not only javascript engine of IE is slow but that browser is so messed up
912					 * that resize event is triggered even when size of any element is changed
913					 * even though I specifically wrote $(window) that's why the condition below.
914					 */
915					if (windowWidth !== $(window).width()) {
916						windowWidth = $(window).width();
917						recalcAccordionVars(false);
918						if (resized) {
919							var slidePropsMap = {};
920							$slides.stop(true, true).each(function (e) {
921								// Finish animation of all elements inside a slide
922								$('*[data-initEvent]:animated', $slides.eq(e)).stop(true, true);
923								// Recalculate offset of current slide
924								slidePropsMap = getSlideFinalStyle(e);
925								// Set offset of current slide and size of slideWrapper
926								$slides.eq(e)
927									.css(slidePropsMap)
928									.children('.jAccordion-slideWrapper')
929									.css(sizeProp.secondary, accCurrSize[sizeProp.secondary] - bordersWidth.secondary)
930									.css(sizeProp.primary, options.activeSlideAutoHeight ? 'auto' : activeSlideSize - bordersWidth.primary);
931							});
932							changeAccordionSize();
933						}
934					}
935                });
936            }
937
938            // Arrow keys navigation
939            if (options.arrowKeysNav) {
940                /* Elements with tabindex -1 can be focused. User can control only focused accordion via arrow keys. 
941                 * This behaviour lets user control just the focused accordion, which is very handy if there
942                 * are more accordions on one page.
943                 */
944                $_accordion.attr('tabindex', -1);
945				// Disable scrolling of page via arrow keys if accordion is active.
946				var arrowKeys = [37, 38, 39, 40];
947				$(document).keydown(function (e) {
948					var code = e.keyCode || e.which;
949					if ($.inArray(code, arrowKeys) > -1) {
950						if (document.activeElement === $_accordion[0]) {
951							e.preventDefault();
952						}
953					}
954				});
955
956                $_accordion.keyup(function (e) {
957                    var code = e.keyCode || e.which;
958                    switch (code) {
959                    case 37:	// left arrow
960                    case 38:	// Up arrow
961                        base.prev();
962                        break;
963                    case 39:	// Right arrow
964                    case 40:	// Bottom arrow
965                        base.next();
966                        break;
967                    }
968                });
969            }
970        }
971
972		// Function enables/disables dependent options.
973        function validateOptions() {
974			var scaleImgsMethods = ['fit', 'fitWidth', 'fitHeight'];
975            /* Handheld devices don't have cursor so they can't trigger 'mouseenter' event 
976             * that's why the event is changed to 'click'.
977             */
978            if (/Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent)) {
979                options.event = 'click';
980            }
981            if (options.arrowKeysNav || options.autoplay) {
982                options.sticky = true;
983            }
984			if (options.autoplay && options.defaultActiveSlideIdx === null) {
985				options.defaultActiveSlideIdx = 0;
986            }
987            if ($headers.length !== slidesNumber || options.autoplay) {
988                options.headers = $headers = null;
989            } else {
990				options.sticky = true;
991				options.event = 'click';
992			}
993            if (options.inactiveSlideSize <= 0) {
994                options.accordionAutoSize = false;
995            }
996            if (options.activeSlideAutoHeight) {
997                if (options.inactiveSlideSize <= 0 || !options.vertical) {
998                    options.activeSlideAutoHeight = false;
999                } else {
1000                    options.accordionAutoSize = true;
1001                }
1002            }
1003			if ($.inArray(options.scaleImgs, scaleImgsMethods) === -1) {
1004				options.scaleImgs = 'fit';
1005			}
1006            if ($(options.prevBtn).length === 0) {
1007                options.prevBtn = null;
1008            }
1009            if ($(options.nextBtn).length === 0) {
1010                options.nextBtn = null;
1011            }
1012        }
1013
1014        // Function initializes the whole accordion
1015        function init() {
1016            validateOptions();
1017            recalcAccordionVars(true);
1018            changeAccordionSize();
1019            initAccordionEvents();
1020			$_accordion.removeClass('noJS');
1021            $slides.each(function () {
1022                var $currSlide = $(this);
1023                initSlideStyle($currSlide);
1024                disableLinks($currSlide);
1025                initSlideEvents($currSlide);
1026                initAnimElems($currSlide);
1027            });
1028			scaleImages();
1029            initBtnsEvents();
1030            if (options.autoplay) {
1031                autoplay = new Timer(function () {
1032                    base.next();
1033                }, options.autoplayInterval);
1034            }
1035            // Callback function to be executed after the accordion is fully loaded
1036            if ($.isFunction(options.ready)) {
1037                $_accordion.data('jAccordion', base);
1038                options.ready.call(base);
1039            }
1040            // Open default slide if defined
1041            if (options.defaultActiveSlideIdx !== null) {
1042                var userDefinedSlideDuration = options.transitionSpeed;
1043                options.transitionSpeed = 0;
1044                base.goToSlide(options.defaultActiveSlideIdx);
1045                options.transitionSpeed = userDefinedSlideDuration;
1046				// Finish animations of all elements, it's necessary to delay this action so the animation can start at first
1047				window.setTimeout(function () {
1048					$('*[data-initEvent]:animated', $slides.eq(options.defaultActiveSlideIdx)).each(function () {
1049						$(this).stop(true, true);
1050					});
1051				}, 100);
1052            }
1053        }
1054
1055        // Function configures preloader of images.
1056        function preload() {
1057            $slidesWrapper.imgPreloader({
1058                preloadTransitionSpeed: options.preloadTransitionSpeed,
1059                onImagesLoaded: function () {
1060                    init();
1061                }
1062            });
1063        }
1064
1065        if (options.preloadImages) {
1066            preload();
1067        } else {
1068            init();
1069        }
1070    };
1071
1072    $.fn.jAccordion = function (options) {
1073        return this.each(function () {
1074            if (!$(this).data('jAccordion')) {
1075                new Accordion(this, options);
1076            }
1077        });
1078    };
1079
1080    $.fn.jAccordion.defaults = {
1081        vertical: false,
1082        activeSlideSize: 650,
1083        inactiveSlideSize: 0,
1084        transitionSpeed: 750,
1085        spacing: 0,
1086        event: 'mouseenter',
1087        sticky: false,
1088        autoplay: false,
1089        autoplayInterval: 3000,
1090        pauseOnHover: true,
1091        defaultActiveSlideIdx: null,
1092        preloadImages: false,
1093        preloadTransitionSpeed: 750,
1094        activeSlideClass: 'active_slide',
1095        easing: 'swing',
1096        responsive: true,
1097        keepAspectRatio: true,
1098		scaleImgs : 'fit',
1099        arrowKeysNav: false,
1100        headers: null,
1101        accordionAutoSize: false,
1102        activeSlideAutoHeight: false,
1103        prevBtn: null,
1104        nextBtn: null,
1105        disableBtnsDuringTransition: true,
1106        ready: function () {},
1107		onSlideOpened: function () {},
1108        onSlideStartOpening: function () {},
1109        onSlideStartClosing: function () {},
1110        onAccordionMouseEnter: function () {},
1111        onAccordionMouseLeave: function () {},
1112        onPause: function () {},
1113        onResume: function () {}
1114    };
1115}(jQuery));
1116
1117/*
1118 * imgPreloader is sold as part of jAccordion plugin.
1119 *
1120 * imgPreloader
1121 * Version 1.1
1122 * @requires jQuery v1.4.3 or newer
1123 * 
1124 * Author maniacpc
1125 * Created exclusively for http://codecanyon.net in August 2012
1126 * Licensed under regular license:
1127 * http://codecanyon.net/licenses/regular_extended
1128 */
1129
1130(function ($) {
1131	"use strict";
1132    var ImgPreloader = function (element, userSettings) {
1133        var options = $.extend({}, $.fn.imgPreloader.defaults, userSettings),
1134            $imgsContainer = $(element).hide(),
1135            $images = $('img', $imgsContainer),
1136            imagesToLoad = $images.length;
1137
1138		function preloadingDone() {
1139			$imgsContainer.fadeIn(options.preloadTransitionSpeed, function () {
1140				if ($.browser.msie) {
1141					$imgsContainer.get(0).style.removeAttribute('filter');
1142				}
1143			});
1144			if ($.isFunction(options.onImagesLoaded)) {
1145				options.onImagesLoaded.call();
1146			}
1147		}
1148
1149        if (imagesToLoad === 0) {
1150			preloadingDone();
1151		}
1152
1153		$images.each(function (i) {
1154			// Remove attrbiute alt of all images because it's displayed when cursor is over the image (in IE)
1155			var img_source = $images.eq(i).removeAttr('alt').attr('src');
1156			$images.eq(i).load(function () {
1157				imagesToLoad -= 1;
1158				if (imagesToLoad === 0) {
1159					preloadingDone();
1160				}
1161			}).attr('src', img_source);
1162		});
1163    };
1164
1165    $.fn.imgPreloader = function (options) {
1166        return this.each(function () {
1167            if (!$(this).data('imgPreloader')) {
1168                var preloader = new ImgPreloader(this, options);
1169                $(this).data('imgPreloader', preloader);
1170            }
1171        });
1172    };
1173
1174    $.fn.imgPreloader.defaults = {
1175        preloadTransitionSpeed: 750,
1176        onImagesLoaded: function () {}
1177    };
1178}(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.