/*!********************************************************************* * * Liquid Slider v1.3.6 * Kevin Batdorf * * http://liquidslider.com * * GPL license * ************************************************************************/ // See https://github.com/KevinBatdorf/liquidslider for version updates /*jslint bitwise: true, browser: true */ /*global $, jQuery */ /*jshint unused:false */ // Utility for creating objects in older browsers if (typeof Object.create !== 'function') { Object.create = function (obj) { "use strict"; function F() {} F.prototype = obj; return new F(); }; } (function ($, window, document, undefined) { "use strict"; var Slider = { //initialize addPreloader: function () { var self = this; if (self.useCSS) { $(self.sliderId).append('
'); } else { $(self.sliderId + ' .panel-container').children().each(function () { $(this).children().append('
'); }); } }, removePreloader: function () { // I think this is broken TODO ~~continuous var self = this, //heightCandidate, height = 0; // Remove most preloaders (ones without images, etc) if (self.options.preloader) { $(self.sliderId + ' .panel').children().each(function () { // If it has images, get the highest panel and use that until the page is fully loaded // Otherwise, the panels with images may be too short. if ($(this).find(self.options.preloaderElements).not('.liquid-slider-preloader').length) { height = self.getHeighestPanel(); } else { var $this = $(this); $this.find('.liquid-slider-preloader').remove(); if ($this.parent()[0] === $((self.$panelContainer).children()[self.currentTab + ~~self.options.continuous])[0] && self.options.autoHeight) { $(self.sliderId).css('height', $((self.$panelContainer).children()[self.currentTab + ~~self.options.continuous]).css('height')); } } return height; }); } }, determineAnimationType: function () { var self = this, animationstring = 'animation', keyframeprefix = '', domPrefixes = 'Webkit Moz O ms Khtml'.split(' '), pfx = '', i = 0; // Decide whether or not to use CSS transitions or jQuery // https://developer.mozilla.org/en-US/docs/CSS/CSS_animations/Detecting_CSS_animation_support self.useCSS = false; if (self.elem.style.animationName) { self.useCSS = true; } if (self.useCSS === false) { for (i = 0; i < domPrefixes.length; i++) { if (self.elem.style[domPrefixes[i] + 'AnimationName'] !== undefined) { pfx = domPrefixes[i]; animationstring = pfx + 'Animation'; keyframeprefix = '-' + pfx.toLowerCase() + '-'; self.useCSS = true; break; } } } // Disable CSS transitions if the width is wider than the max // Some features are disabled or different when using CSS transitions if (document.documentElement.clientWidth > self.options.useCSSMaxWidth) {self.useCSS = false; } // Disable some buggy settings for css transitions(for now) // Preloader also works differently if (self.useCSS) { self.options.continuous = false; } }, configureCSSTransitions: function () { var self = this, slideEasing, heightEasing; self.easing = { // Penner equations easeOutCubic: 'cubic-bezier(.215,.61,.355,1)', easeInOutCubic: 'cubic-bezier(.645,.045,.355,1)', easeInCirc: 'cubic-bezier(.6,.04,.98,.335)', easeOutCirc: 'cubic-bezier(.075,.82,.165,1)', easeInOutCirc: 'cubic-bezier(.785,.135,.15,.86)', easeInExpo: 'cubic-bezier(.95,.05,.795,.035)', easeOutExpo: 'cubic-bezier(.19,1,.22,1)', easeInOutExpo: 'cubic-bezier(1,0,0,1)', easeInQuad: 'cubic-bezier(.55,.085,.68,.53)', easeOutQuad: 'cubic-bezier(.25,.46,.45,.94)', easeInOutQuad: 'cubic-bezier(.455,.03,.515,.955)', easeInQuart: 'cubic-bezier(.895,.03,.685,.22)', easeOutQuart: 'cubic-bezier(.165,.84,.44,1)', easeInOutQuart: 'cubic-bezier(.77,0,.175,1)', easeInQuint: 'cubic-bezier(.755,.05,.855,.06)', easeOutQuint: 'cubic-bezier(.23,1,.32,1)', easeInOutQuint: 'cubic-bezier(.86,0,.07,1)', easeInSine: 'cubic-bezier(.47,0,.745,.715)', easeOutSine: 'cubic-bezier(.39,.575,.565,1)', easeInOutSine: 'cubic-bezier(.445,.05,.55,.95)', easeInBack: 'cubic-bezier(.6,-.28,.735,.045)', easeOutBack: 'cubic-bezier(.175,.885,.32,1.275)', easeInOutBack: 'cubic-bezier(.68,-.55,.265,1.55)' }; // Build a CSS class depending on the type of transition if (self.useCSS) { slideEasing = 'all ' + self.options.slideEaseDuration + 'ms ' + self.easing[self.options.slideEaseFunction]; heightEasing = 'all ' + self.options.autoHeightEaseDuration + 'ms ' + self.easing[self.options.autoHeightEaseFunction]; // Build the width transition rules $(self.panelContainer).css({ '-webkit-transition': slideEasing, '-moz-transition': slideEasing, '-ms-transition': slideEasing, '-o-transition': slideEasing, 'transition': slideEasing }); // Build the height transition rules if (self.options.autoHeight) { (self.$sliderId).css({ '-webkit-transition': heightEasing, '-moz-transition': heightEasing, '-ms-transition': heightEasing, '-o-transition': heightEasing, 'transition': heightEasing }); } } }, makeResponsive: function () { var self = this; // Adjust widths and add classes to make responsive $(self.sliderId + '-wrapper').addClass('liquid-responsive').css({ 'max-width': $(self.sliderId + ' .panel').width(), 'width': '100%' }); $(self.sliderId + ' .panel-container').css('width', 100 * self.panelCount + self.pSign); $(self.sliderId + ' .panel').css('width', 100 / self.panelCount + self.pSign); // Set the initial height if (!self.options.autoHeight) { (self.$sliderId).css('height', self.getHeighestPanel() + 'px'); } //else { //self.adjustHeightNoAnimation(); //} // Cache the padding for add/removing arrows if (self.options.hideArrowsWhenMobile) { self.leftWrapperPadding = $(self.sliderId + '-wrapper').css('padding-left'); self.rightWrapperPadding = (self.$sliderWrap).css('padding-right'); } if (self.options.dynamicArrows || self.options.dynamicArrowsGraphical) { // Add padding to the top equal to the height of the arrows to make room for arrows, if enabled.. (self.$sliderId).css('padding-top', $(self.sliderId + '-wrapper .liquid-nav-right').css('height')); } // Set the width to slide self.slideWidth = (self.$sliderId).width(); self.pSign = 'px'; // Change navigation when the screen size is too small. if (self.options.responsive) {self.responsiveEvents(); } // Do something when an item is selected from the select box $(self.sliderId + '-nav-select').change(function () { self.setCurrent(parseInt($(this).val().split('tab')[1], 10) - 1); }); // Match the slider margin with the width of the slider (better height transitions) $(self.sliderId + '-wrapper').css('width', (self.$sliderId).width()); // Change navigation if the user resizes the screen. if (self.options.responsive) { $(window).bind('resize', function () { self.responsiveEvents(); clearTimeout(self.resizingTimeout); self.resizingTimeout = setTimeout(function () { // Send to adjust the height after resizing completes self.adjustHeight(); self.transition(); }, 500); }); } }, responsiveEvents: function () { var self = this, mobileNavChangeOver; if (self.options.responsive) { mobileNavChangeOver = (self.options.mobileUIThreshold || (self.totalNavWidth + 10 || self.options.hideArrowsThreshold)); if ((self.$sliderId).outerWidth() < mobileNavChangeOver) { if (self.options.mobileNavigation && self.totalNavWidth) { (self.$sliderNavUl).css('display', 'none'); $(self.sliderId + '-wrapper .liquid-slider-select-box').css('display', 'block'); $(self.sliderId + '-nav-select').css('display', 'block'); // Update the navigation if (self.loaded) {$(self.sliderId + '-nav-select').val(self.options.mobileNavDefaultText); } } if (self.options.hideArrowsWhenMobile && self.options.dynamicArrows) { (self.$leftArrow).remove(); (self.$rightArrow).remove(); } else if (!self.options.dynamicArrowsGraphical && self.options.dynamicArrows) { (self.$leftArrow).css('margin-' + self.options.dynamicTabsPosition, '0'); (self.$rightArrow).css('margin-' + self.options.dynamicTabsPosition, '0'); } } else { if (self.options.mobileNavigation && self.options.dynamicTabs) { (self.$sliderNavUl).css('display', 'block'); $(self.sliderId + '-wrapper .liquid-slider-select-box').css('display', 'none'); $(self.sliderId + '-nav-select').css('display', 'none'); } if (self.options.hideArrowsWhenMobile && self.options.dynamicArrows && !($(self.leftArrow).length || $(self.rightArrow).length)) { self.addArrows(); self.registerArrows(); } else if (!self.options.dynamicArrowsGraphical && self.options.dynamicArrows) { (self.$leftArrow).css('margin-' + self.options.dynamicTabsPosition, (self.$sliderNavUl).css('height')); (self.$rightArrow).css('margin-' + self.options.dynamicTabsPosition, (self.$sliderNavUl).css('height')); } } // While resizing, set the width to 100% $(self.sliderId + '-wrapper').css('width', '100%'); // Set the width to slide self.slideWidth = $(self.sliderId).outerWidth(true); } }, addNavigation: function () { var self = this, // The id is assigned here to allow for responsive dropDownList, dynamicTabsElm = '<' + self.options.navElementTag + ' class="liquid-nav">', selectBoxDefault = (self.options.mobileNavDefaultText) ? '' : null; if (self.options.responsive && self.options.mobileNavigation) { dropDownList = '
'; } // Add basic frame if (self.options.dynamicTabsPosition === 'bottom') { (self.$sliderId).after(dynamicTabsElm); } else { (self.$sliderId).before(dynamicTabsElm); } // Add responsive navigation if (self.options.responsive) { self.$sliderNavUl = $(self.sliderId + '-nav-ul'); (self.$sliderNavUl).before(dropDownList); } // Add labels $.each( (self.$elem).find(self.options.panelTitleSelector), function (n) { $((self.$sliderWrap)).find('.liquid-nav ul').append('
  • ' + $(this).text() + '
  • '); } ); // Adds dropdown navigation for smaller screens if responsive if (self.options.responsive && self.options.mobileNavigation) { $.each( (self.$elem).find(self.options.panelTitleSelector), function (n) { $((self.$sliderWrap)).find('.liquid-slider-select-box select').append(''); } ); } }, alignNavigation: function () { var self = this, arrow = (self.options.dynamicArrowsGraphical) ? '-arrow' : ''; // Set the alignment, adjusting for margins if (self.options.dynamicTabsAlign !== 'center') { if (!self.options.responsive) { $((self.$sliderWrap)).find('.liquid-nav ul').css( 'margin-' + self.options.dynamicTabsAlign, // Finds the width of the aarows and the margin $((self.$sliderWrap)).find( '.liquid-nav-' + self.options.dynamicTabsAlign + arrow ).outerWidth(true) + parseInt((self.$sliderId).css('margin-' + self.options.dynamicTabsAlign), 10) ); } $((self.$sliderWrap)).find('.liquid-nav ul').css('float', self.options.dynamicTabsAlign); } self.totalNavWidth = $((self.$sliderWrap)).find('.liquid-nav ul').outerWidth(true); if (self.options.dynamicTabsAlign === 'center') { // Get total width of the navigation tabs and center it self.totalNavWidth = 0; $((self.$sliderWrap)).find('.liquid-nav li a').each(function () { self.totalNavWidth += $(this).outerWidth(true); }); $((self.$sliderWrap)).find('.liquid-nav ul').css('width', self.totalNavWidth + 1); } }, addArrows: function () { var self = this; if (self.options.dynamicArrows) { (self.$sliderWrap).addClass("arrows"); if (self.options.dynamicArrowsGraphical) { (self.$sliderId).before('
    '); (self.$sliderId).after('
    '); } else { (self.$sliderId).before('
    ' + self.options.dynamicArrowLeftText + '
    '); (self.$sliderId).after('
    ' + self.options.dynamicArrowRightText + '
    '); } // Will hide the arrows on load if on the first or last panel if (self.options.hideSideArrows || self.options.hoverArrows || self.options.hideArrowsWhenMobile) { self.leftArrow = self.sliderId + '-wrapper [class^=liquid-nav-left]'; self.rightArrow = self.sliderId + '-wrapper [class^=liquid-nav-right]'; self.$leftArrow = $(self.leftArrow); self.$rightArrow = $(self.rightArrow); (self.$leftArrow).css({visibility: "hidden", opacity: 0}); (self.$rightArrow).css({visibility: "hidden", opacity: 0}); } // Add a margin to the top of responsive arrows if (self.options.responsive && self.options.dynamicArrows && !self.options.dynamicArrowsGraphical && (self.options.dynamicTabsAlign !== 'center')) { (self.$leftArrow).css('margin-' + self.options.dynamicTabsPosition, (self.$sliderNavUl).css('height')); (self.$rightArrow).css('margin-' + self.options.dynamicTabsPosition, (self.$sliderNavUl).css('height')); } // If using the hover arrows, then adjust the transition speed. self.options.hideSideArrowsDuration = (self.options.hoverArrows) ? self.options.hoverArrowDuration : self.options.hideSideArrowsDuration; } }, hideArrows: function () { var self = this; // If the tab is 0 or panelCount minus the two continuous clones if (self.currentTab === 0 || self.currentTab === (self.panelCount - 2) * ~~(self.options.continuous)) { // Fade out the left and make sure the right is faded in (used for on load) (self.$leftArrow).fadeOut(self.options.hideSideArrowsDuration, function () { $(this).show().css({visibility: "hidden"}); }); if ((self.$rightArrow).css('visibility') === 'hidden' && (!self.options.hoverArrows || self.hoverOn)) { (self.$rightArrow).css({opacity: 1, visibility: "visible"}); } } else if (self.currentTab === (self.panelCount - (~~(self.options.continuous) * 2) - 1) || self.currentTab === -1) { // Fade out the right and make sure the left is faded in (used for on load) (self.$rightArrow).fadeOut(self.options.hideSideArrowsDuration, function () { $(this).show().css({visibility: "hidden"}); }); if ((self.$leftArrow).css('visibility') === 'hidden' && (!self.options.hoverArrows || self.hoverOn)) { (self.$leftArrow).css({opacity: 1, visibility: "visible"}); } } else if (!self.options.hoverArrows || self.hoverOn) { // Fade in on all other tabs if ((self.$leftArrow).css('visibility') === 'hidden') { // Duration * 3 because we're using different fade methods (looks similar this way) (self.$leftArrow).css({opacity: 0, visibility: "visible"}).animate({opacity: 1}, self.options.hideSideArrowsDuration * 3); } if ((self.$rightArrow).css('visibility') === 'hidden') { (self.$rightArrow).css({opacity: 0, visibility: "visible"}).animate({opacity: 1}, self.options.hideSideArrowsDuration * 3); } } }, registerArrows: function () { var self = this; // CLick arrows if (self.options.dynamicArrows) { $((self.$sliderWrap).find('[class^=liquid-nav-]')).on('click', function () { // These prevent clicking when in continuous mode, which would break it otherwise. if (!self.clickable) { return false; } if (typeof self.options.callforwardFunction === 'function') { self.animationCallForward(true); } self.setCurrent($(this).attr('class').split('-')[2]); if (typeof self.options.callbackFunction === 'function') { self.animationCallback(true); } return false; }); if (self.options.autoSlide) { self.checkAutoSlideStop(); } } }, registerCrossLinks: function () { var self = this; // Click cross links if (self.options.crossLinks) { // Re calculate cross links (for applying current tabs) self.$crosslinks = $('[data-liquidslider-ref*=' + (self.sliderId).split('#')[1] + ']'); (self.$crosslinks).on('click', function () { if (!self.clickable) {return false; } // Stop and Play controls // When the user presses stop if (self.options.autoSlideControls) { if ($(this).attr('name') === 'stop') { self.options.autoSlide = false; clearTimeout(self.autoslideTimeout); $(this).html(self.options.autoSlideStartText); $(this).attr('name', 'start'); return false; } // When the user presses play if ($(this).attr('name') === 'start') { $(this).html(self.options.autoSlideStopText); self.autoSlideStopped = false; self.options.autoSlide = true; self.hover(); self.setCurrent(self.options.autoSliderDirection); self.autoSlide(); $(this).attr('name', 'stop'); return false; } } if (typeof self.options.callforwardFunction === 'function') { self.animationCallForward(true); } // Stores the clicked data-liquidslider-ref and checks if it is a # or left or right var direction = ($(this).attr('href').split('#')[1]); if (direction === 'left' || direction === 'right') { self.setCurrent(direction); } else if (self.options.hashCrossLinks) { self.getHashTags('#' + direction); self.setCurrent(parseInt(self.hashValue - 1, 10) - ~~(self.options.continuous)); } else { self.setCurrent(parseInt(direction - 1, 10)); } if (self.options.autoSlide) { self.checkAutoSlideStop(); } if (typeof self.options.callbackFunction === 'function') { self.animationCallback(true); } return false; }); } }, getHashTags: function (hash) { var self = this; if (hash && self.options.hashLinking) { //set the value as a variable, and remove the # self.hashValue = (hash).replace('#', ''); if (self.options.hashNames) { $.each( (self.$elem).find(self.options.hashTitleSelector), function (n) { var $this = $(this).text().replace(/(\s)/g, '-'); self.hashValue = self.hashValue.replace(self.options.hashTagSeparator, ''); self.hashValue = self.hashValue.replace(self.options.hashTLD, ''); if (($this).toLowerCase() === self.hashValue.toLowerCase()) { self.hashValue = parseInt(n + 1, 10); // Adjust if continuous if (self.options.continuous && self.hashValue === 0) { self.hashValue = self.panelCount - 2; } return false; } } ); } else { self.hashValue = parseInt(self.hashValue, 10); } } }, updateHashTags: function (tab) { var self = this; if (self.options.hashLinking) { if (self.options.continuous) { if (self.currentTab === self.panelCount - 2) { window.location.hash = (self.options.hashNames) ? self.options.hashTagSeparator + $($(self.$elem).find(self.options.hashTitleSelector)[1]).text().replace(/(\s)/g, '-', '-').toLowerCase() + self.options.hashTLD : 1; } else if (self.currentTab === -1) { window.location.hash = (self.options.hashNames) ? self.options.hashTagSeparator + $($(self.$elem).find(self.options.hashTitleSelector)[self.panelCount - 2]).text().replace(/(\s)/g, '-', '-').toLowerCase() + self.options.hashTLD : self.panelCount - 2; } else { window.location.hash = (self.options.hashNames) ? self.options.hashTagSeparator + $($(self.$elem).find(self.options.hashTitleSelector)[tab + 1]).text().replace(/(\s)/g, '-', '-').toLowerCase() + self.options.hashTLD : tab + 1; } } else { window.location.hash = (self.options.hashNames) ? self.options.hashTagSeparator + $($(self.$elem).find(self.options.hashTitleSelector)[tab]).text().replace(/(\s)/g, '-', '-').toLowerCase() + self.options.hashTLD : tab + 1; } } }, hover: function () { var self = this; // Hover events (self.$sliderWrap).hover( function () { // Hover Arrows if (self.options.hoverArrows && self.options.dynamicArrows) { self.hoverOn = true; (self.$leftArrow).stop(true); (self.$rightArrow).stop(true); if (self.options.hideSideArrows) { self.hideArrows(); } else { (self.$leftArrow).css({opacity: 0, visibility: "visible"}).animate({opacity: 1}, self.options.hideSideArrowsDurations); (self.$rightArrow).css({opacity: 0, visibility: "visible"}).animate({opacity: 1}, self.options.hideSideArrowsDurations); } } // Pause on Hover if (self.options.autoSlidePauseOnHover && self.options.autoSlide) { self.dontCallback = true; clearTimeout(self.autoslideTimeout); } }, function () { // Hover Arrows if (self.options.hoverArrows && self.options.dynamicArrows) { self.hoverOn = false; (self.$leftArrow).fadeOut(self.options.hideSideArrowsDuration, function () { $(this).show().css({visibility: "hidden"}); }); (self.$rightArrow).fadeOut(self.options.hideSideArrowsDuration, function () { $(this).show().css({visibility: "hidden"}); }); } // Pause on Hover if (self.options.autoSlidePauseOnHover && self.options.autoSlide && self.clickable) { self.dontCallback = false; var isAnimating = $('.panel-container:animated'); if (!self.autoSlideStopped && !~~isAnimating) { self.autoSlide(clearTimeout(self.autoslideTimeout)); } } } ); }, touch: function () { // Touch Events var self = this; $(self.sliderId + ' .panel').swipe({fallbackToMouseEvents:false, allowPageScroll: "vertical", swipe: function (e, dir) { // Reverse the swipe direction self.swipeDir = (dir === 'left') ? 'right' : 'left'; if (!self.options.continuous) { // Check if on the first or last panel, and don't slide beyond (always swipe on fade) if ( ((self.currentTab === 0 && dir === 'right') || ( (self.currentTab === (self.panelCount - 1)) && dir === 'left')) && self.options.slideEaseFunction !== "fade") { return false; } } self.setCurrent(self.swipeDir); self.clickable = false; $(this).trigger('click'); if (self.options.autoSlide) { self.checkAutoSlideStop(); } if (typeof self.options.callbackFunction === 'function') { self.animationCallback(true); } }}); }, keyboard: function () { // Keyboard Events var self = this; $(document).keydown(function (event) { if (typeof self.options.callforwardFunction === 'function') { self.animationCallForward(true); } var key = event.keyCode || event.which; if (event.target.type !== 'textarea' && event.target.type !== 'textbox') { if (key === self.options.leftKey) { self.setCurrent('right'); self.clickable = false; } if (key === self.options.rightKey) { self.setCurrent('left'); self.clickable = false; } $.each(self.options.panelKeys, function (index, value) { if (key === value) { self.setCurrent(index - 1); self.clickable = false; } }); } if (self.options.autoSlide) { self.checkAutoSlideStop(); } if (typeof self.options.callbackFunction === 'function') { self.animationCallback(true); } }); }, autoSlide: function () { var self = this; // Can't set the autoslide slower than the easing ;-) if (self.options.autoSlideInterval < self.options.slideEaseDuration) { self.options.autoSlideInterval = (self.options.slideEaseDuration > self.options.autoHeightEaseDuration) ? self.options.slideEaseDuration : self.options.autoHeightEaseDuration; } //self.clickable = false; self.autoslideTimeout = setTimeout(function () { if (typeof self.options.callforwardFunction === 'function' && self.loaded) { self.animationCallForward(); } // Slide left or right self.setCurrent(self.options.autoSliderDirection); self.autoSlide(); }, self.options.autoSlideInterval); if (typeof self.options.callbackFunction === 'function' && self.loaded) { self.animationCallback(); } }, checkAutoSlideStop: function () { var self = this; // If the slider has not stopped, check whether it should stop if (!self.autoSlideStopped && self.loaded) { if (self.options.autoSlideStopWhenClicked) { clearTimeout(self.autoslideTimeout); self.autoSlideStopped = true; if (self.options.autoSlideControls) { $('body').find('[data-liquidslider-ref*=' + (self.sliderId).split('#')[1] + '][name=stop]').html(self.options.autoSlideStartText); } } else if (!self.options.hoverArrows && !self.options.autoSlidePauseOnHover || !self.clickable) { self.autoSlide(clearTimeout(self.autoslideTimeout)); } } }, continuousSlide: function () { var self = this; // If on the last panel (the clone of panel 1), set the margin to the original. if (self.currentTab === self.panelCount - 2 || self.marginLeft === -((self.slideWidth * self.panelCount) - self.slideWidth)) { $(self.panelContainer).css('margin-left', -self.slideWidth + self.pSign); self.currentTab = 0; } else if (self.currentTab === -1 || self.marginLeft === 0) { // If on the first panel the clone of the last panel), set the margin to the original. $(self.panelContainer).css('margin-left', -(((self.slideWidth * self.panelCount) - (self.slideWidth * 2))) + self.pSign); self.currentTab = (self.panelCount - 3); } self.clickable = true; }, animationCallback: function (go) { var self = this; if (!self.dontCallback || go) { setTimeout(function () {self.options.callbackFunction.call(self); }, self.options.slideEaseDuration + 50); } }, animationCallForward: function (go) { var self = this; if (!self.dontCallback || go) { self.options.callforwardFunction.call(self); } }, init: function (options, elem) { var self = this; // Cache the element self.elem = elem; self.$elem = $(elem); $('body').removeClass('no-js'); // Cache the ID and class. This allows for multiple instances with any ID name supplied self.sliderId = '#' + (self.$elem).attr('id'); self.$sliderId = $(self.sliderId); // Set the options self.options = $.extend({}, $.fn.liquidSlider.options, options); // Variable for the % sign if needed (responsive), otherwise px self.pSign = (self.options.responsive) ? '%' : 'px'; // Slide animations bad in ie7, so don't animate height if (((navigator.appVersion.indexOf("MSIE 7.") !== -1) || navigator.appVersion.indexOf("MSIE 8.") !== -1)) { //self.options.slideEaseFunction = "fade"; self.dontAnimateHeight = true; } if (self.options.responsive) { self.determineAnimationType(); } // Build the tabs and navigation self.build(); // Add preloader if (self.options.preloader) { self.addPreloader(); } // Start auto slider if (self.options.autoSlide) { self.autoSlide(); } self.events(); if (self.options.preloader & !self.useCSS) { self.removePreloader(); } // Disable clicking until fully loaded. Otherwise buggy with css transitions if (self.useCSS) { self.clickable = false; } $(window).bind("load", function () { // Remove preloader from remaining elements if (self.options.preloader) { $('.liquid-slider-preloader').each(function () { $(this).fadeOut(self.options.preloaderFadeOutDuration); }); } // Page fully loaded self.loaded = true; self.clickable = true; // This will adjust the slider's height in case of images, etc. self.adjustHeightNoAnimation(); // Adjust the width after load (IE won't otherwise). if (self.options.responsive) {self.responsiveEvents(self.loaded); } if (self.options.responsive) { self.configureCSSTransitions(); } self.readyToSlide = true; // Adjust the height again (Chrome seems to like this) self.adjustHeightNoAnimation(); self.transition(); }); }, build: function () { var self = this, isAbsolute; // Grab the current hash tag if (self.options.hashLinking) { self.getHashTags(window.location.hash); // Default to panel 1 if mistyped if (typeof(self.hashValue) !== 'number' ) { self.hashValue = 1; } } // Store current tab self.currentTab = (self.hashValue) ? self.hashValue - 1 : self.options.firstPanelToLoad - 1; // Store a temp var for callback functions self.tabTemp = self.currentTab; // Wrap the entire slider (backwards compatible) if ((self.$sliderId).parent().attr('class') !== 'liquid-slider-wrapper') {(self.$sliderId).wrap('
    '); } // Cache the wrapper self.$sliderWrap = $(self.sliderId + '-wrapper'); // Add the .panel class to the individual panels $(self.sliderId).children().addClass((self.$elem).attr('id') + '-panel panel'); self.panelClass = self.sliderId + ' .' + (self.$elem).attr('id') + '-panel'; self.$panelClass = $(self.panelClass); // Wrap all panels in a div, and wrap inner content in a div (not backwards compatible) (self.$panelClass).wrapAll('
    '); (self.$panelClass).wrapInner('
    '); self.panelContainer = (self.$panelClass).parent(); self.$panelContainer = self.panelContainer; // If using fade transition, add the class here and disable other options. if (self.options.slideEaseFunction === "fade") { (self.$panelClass).addClass('fadeClass'); self.options.continuous = false; $((self.$panelContainer).children()[self.currentTab]).css('display', 'block'); } // Apply starting height to the container if (self.options.autoHeight && !self.options.responsive) { self.adjustHeightNoAnimation($($(self.panelContainer).children()[self.currentTab]).height() + ~~($(self.sliderId + '-wrapper .liquid-nav-right').height()) + self.pSign); } else if (!self.options.preloader) { self.adjustHeightNoAnimation($($(self.panelContainer).children()[self.currentTab]).height()); } // Build navigation tabs if (self.options.dynamicTabs) { self.addNavigation(); } // Build navigation arrows or disable features if (self.options.dynamicArrows) { self.addArrows(); } else { self.options.hoverArrows = false; self.options.hideSideArrows = false; } // Find cross links (for applying current tabs) if (self.options.crossLinks) { self.$crosslinks = $('[data-liquidslider-ref*=' + (self.sliderId).split('#')[1] + ']'); } // Create a container width to allow for a smooth float right. Won't calculate arrows if absolute isAbsolute = ((self.$leftArrow) && (self.$leftArrow).css('position') === 'absolute') ? 0 : 1; self.totalSliderWidth = (self.$sliderId).outerWidth(true) + ~~($(self.$leftArrow).outerWidth(true)) * isAbsolute + ~~($(self.$rightArrow).outerWidth(true)) * isAbsolute; $((self.$sliderWrap)).css('width', self.totalSliderWidth); // Align navigation tabs if (self.options.dynamicTabs) { self.alignNavigation(); } // Clone panels if continuous is enabled if (self.options.continuous) { (self.$panelContainer).prepend((self.$panelContainer).children().last().clone()); (self.$panelContainer).append((self.$panelContainer).children().eq(1).clone()); } // Allow the slider to be clicked self.clickable = true; // Count the number of panels and get the combined width self.panelCount = (self.options.slideEaseFunction === 'fade') ? 1 : $(self.panelClass).length; self.panelWidth = $(self.panelClass).outerWidth(); self.totalWidth = self.panelCount * self.panelWidth; // Create a variable for responsive setting if (self.options.responsive && !self.useCSS) { self.slideWidth = 100; } else { self.slideWidth = (self.$sliderId).width(); } // Puts the margin at the starting point with no animation. Made for both continuous and firstPanelToLoad features. // ~~(self.options.continuous) will equal 1 if true, otherwise 0 if (self.options.slideEaseFunction !== 'fade' && !self.useCSS) { $(self.panelContainer).css('margin-left', (-self.slideWidth * ~~(self.options.continuous)) + (-self.slideWidth * self.currentTab) + self.pSign); } // Configure the current tab self.setCurrent(self.currentTab); // Apply the width to the panel container $(self.sliderId + ' .panel-container').css('width', self.totalWidth); // Make responsive (beta) if (self.options.responsive) { self.makeResponsive(); } // Apply margin for css3 transitions if (self.useCSS) { self.panelWidth = $(self.panelClass).outerWidth(); (self.panelContainer).css({ 'margin-left': '0%' }); $(self.panelContainer).css({ 'transform': 'translate3d(' + ((-self.panelWidth * ~~(self.options.continuous)) + (-self.panelWidth * self.currentTab) + 'px') + ', 0, 0)', '-webkit-transform': 'translate3d(' + ((-self.panelWidth * ~~(self.options.continuous)) + (-self.panelWidth * self.currentTab) + 'px') + ', 0, 0)', '-moz-transform': 'translate3d(' + ((-self.panelWidth * ~~(self.options.continuous)) + (-self.panelWidth * self.currentTab) + 'px') + ', 0, 0)' }); } }, events: function () { var self = this; if (self.options.dynamicArrows) { self.registerArrows(); } if (self.options.crossLinks) { self.registerCrossLinks(); } // Click tabs if (self.options.dynamicTabs) { (self.$sliderWrap).find('[class^=liquid-nav] li').on('click', function () { if (!self.clickable) {return false; } if (typeof self.options.callforwardFunction === 'function') { self.animationCallForward(true); } self.setCurrent(parseInt($(this).attr('class').split('tab')[1], 10) - 1); if (typeof self.options.callbackFunction === 'function') { self.animationCallback(true); } return false; }); } // Click to stop autoslider (self.$sliderWrap).find('*').on('click', function () { if (!self.options.autoSlidePauseOnHover || self.options.autoSlideStopWhenClicked) { // AutoSlide controls. if (self.options.autoSlide) { self.checkAutoSlideStop(); } // Stops from speedy clicking for continuous sliding. if (self.options.continuous) {clearTimeout(self.continuousTimeout); } } }); // Enable Hover Events if (self.options.autoSlidePauseOnHover || (self.options.hoverArrows && self.options.dynamicArrows)) { self.hoverable = true; self.hover(); } // Enable Touch Events if (self.options.swipe) {self.touch(); } // Enable Keyboard Events if (self.options.keyboardNavigation) {self.keyboard(); } }, setCurrent: function (direction) { var self = this; if (self.clickable) { self.clickable = false; if (typeof direction === 'number') { self.currentTab = direction; } else { // "left" = -1; "right" = 1; self.currentTab += (~~(direction === 'right') || -1); // If not continuous, slide back at the last or first panel if (!self.options.continuous) { self.currentTab = (self.currentTab < 0) ? $(self.panelClass).length - 1 : (self.currentTab % $(self.panelClass).length); } } // This is so the height will match the current panel, ignoring the clones. // It also adjusts the count for the "currrent" class that's applied if (self.options.continuous) { self.panelHeightCount = self.currentTab + 1; if (self.currentTab === self.panelCount - 2) { self.setTab = 0; } else if (self.currentTab === -1) { self.setTab = self.panelCount - 3; } else { self.setTab = self.currentTab; } } else { self.panelHeightCount = self.currentTab; self.setTab = self.currentTab; } // Add and remove current class. if (self.options.dynamicTabs) { $((self.$sliderWrap)).find('.tab' + (self.setTab + 1) + ':first a') .addClass('current') .parent().siblings().children().removeClass('current'); } // Add current class to cross linked Tabs if (self.options.crossLinks) { (self.$crosslinks).each(function () { if (self.options.hashCrossLinks) { if ($(this).attr('href') === ('#' + $($(self.panelContainer).children()[(self.setTab + ~~(self.options.continuous))]).find(self.options.panelTitleSelector).text().replace(/(\s)/g, '-').toLowerCase())) { $('[data-liquidslider-ref=' + (self.sliderId).split('#')[1] + ']').removeClass('currentCrossLink'); $(this).addClass('currentCrossLink'); } } else if ($(this).attr('href') === '#' + (self.setTab + 1)) { $('[data-liquidslider-ref=' + (self.sliderId).split('#')[1] + ']').removeClass('currentCrossLink'); $(this).addClass('currentCrossLink'); } }); } // Update the dropdown menu when small. if (self.options.responsive && self.options.mobileNavigation && self.loaded) { $(self.sliderId + '-nav-select').val('tab' + (self.setTab + 1)); } // Update hash tags if (self.options.hashLinking) { self.updateHashTags(self.currentTab); } // Update arrows if side arrows enabled if (self.options.hideSideArrows) { self.hideArrows(); } // Show arrows if hoverArrows is disabled if (self.$leftArrow && !self.options.hoverArrows && self.options.dynamicArrows && !self.options.hideSideArrows) { (self.$leftArrow).css({opacity: 1, visibility: "visible"}); (self.$rightArrow).css({opacity: 1, visibility: "visible"}); } this.transition(); } }, getHeight: function (height) { var self = this, currentPanelHeight; // Cache the original height of the current panel currentPanelHeight = height || $($(self.panelContainer).children()[self.panelHeightCount]).css('height').split('px')[0]; // Create a new height based on the user settings (Beta) self.setHeight = (self.options.autoHeightRatio) ? (((self.$sliderWrap).outerWidth(true) / (self.options.autoHeightRatio).split(':')[1] * (self.options.autoHeightRatio).split(':')[0])) : currentPanelHeight; // If the user settings indicate a height too high, use the smaller value self.setHeight = (self.setHeight < currentPanelHeight) ? self.setHeight : currentPanelHeight; self.setHeight = (self.setHeight < self.options.autoHeightMin) ? self.options.autoHeightMin : self.setHeight; if (!self.removePre && self.options.preloader) { // Only run once self.removePre = true; return self.removePreloader(); } return self.setHeight; }, getHeighestPanel: function () { var self = this, height = 0, heightCandidate; $(self.sliderId + ' .panel').each(function () { heightCandidate = $(this).height(); height = (heightCandidate > height) ? heightCandidate : height; }); return height; }, adjustHeight: function (easing, duration, height) { var self = this; // Adjust the height if (self.options.autoHeight && (self.useCSS || self.dontAnimateHeight)) { // CSS transitions or IE self.adjustHeightNoAnimation(height); } else if (self.options.autoHeight) { // jQuery animations (self.$sliderId).animate({ 'height': self.getHeight(height) + 'px' }, { easing: easing || self.options.autoHeightEaseFunction, duration: duration || self.options.autoHeightEaseDuration, queue: false }); } }, adjustHeightNoAnimation: function (height) { var self = this; (self.$sliderId).css({ 'height': self.getHeight(height) + 'px' }); }, transition: function () { var self = this; // Adjust the height if (self.options.autoHeight) { self.adjustHeight(); } // Transition for fade option if (self.options.slideEaseFunction === 'fade') { if (self.loaded) { $($(self.panelContainer).children()[self.currentTab]) .fadeTo(self.options.fadeInDuration, 1.0).css('z-index', 1) .siblings().fadeTo(self.options.fadeOutDuration, 0).css('z-index', 0); setTimeout(function () { if (self.options.continuous) { self.continuousSlide(); } else { self.clickable = true; } }, self.options.slideEaseDuration + 50); } } else if (self.loaded || !self.useCSS) { // Adjust the margin for continuous sliding if (self.options.continuous) { self.marginLeft = -(self.currentTab * self.slideWidth) - self.slideWidth; } else { // Otherwise adjust as normal self.marginLeft = -(self.currentTab * self.slideWidth); } // Don't transition on load if the slider has the same margin. This messes up when the // user clicks before fully loaded if ((self.marginLeft + self.pSign) !== (self.panelContainer).css('margin-left') || (self.marginLeft !== -100)) { // Animate the slider if (self.useCSS && self.loaded) { (self.panelContainer).css({ '-webkit-transform': 'translate3d(' + self.marginLeft + self.pSign + ', 0, 0)', '-moz-transform': 'translate3d(' + self.marginLeft + self.pSign + ', 0, 0)', '-ms-transform': 'translate3d(' + self.marginLeft + self.pSign + ', 0, 0)', '-o-transform': 'translate3d(' + self.marginLeft + self.pSign + ', 0, 0)', 'transform': 'translate3d(' + self.marginLeft + self.pSign + ', 0, 0)' }); // Timeout to replicate callback function setTimeout(function () { if (self.options.continuous) { self.continuousSlide(); } else { self.clickable = true; } }, self.options.slideEaseDuration + 50); } else { (self.panelContainer).animate({ 'margin-left': self.marginLeft + self.pSign }, { easing: self.options.slideEaseFunction, duration: self.options.slideEaseDuration, queue: false, complete: function () { if (self.options.continuous) { self.continuousSlide(); } else { self.clickable = true; } } }); } } } if (self.options.responsive) { // Match the slider margin with the width of the slider (better height transitions) $(self.sliderId + '-wrapper').css('width', (self.$sliderId).outerWidth(true)); } } }; $.fn.liquidSlider = function (options) { return this.each(function () { var slider = Object.create(Slider); slider.init(options, this); $.data(this, 'liquidSlider', slider); }); }; $.fn.liquidSlider.options = { autoHeight: true, autoHeightMin: 0, autoHeightEaseDuration: 1500, autoHeightEaseFunction: "easeInOutExpo", autoHeightRatio: null, // still in development slideEaseDuration: 1500, fadeInDuration:1000, fadeOutDuration: 1000, slideEaseFunction: "easeInOutExpo", callforwardFunction: null, callbackFunction: null, autoSlide: false, autoSliderDirection: 'right', autoSlideInterval: 7000, autoSlideControls: false, autoSlideStartText: 'Start', autoSlideStopText: 'Stop', autoSlideStopWhenClicked: true, autoSlidePauseOnHover: true, continuous: true, dynamicArrows: true, dynamicArrowsGraphical: true, dynamicArrowLeftText: "« left", dynamicArrowRightText: "right »", hideSideArrows: false, hideSideArrowsDuration: 750, hoverArrows: true, hoverArrowDuration: 250, dynamicTabs: true, dynamicTabsAlign: "left", dynamicTabsPosition: "top", firstPanelToLoad: 1, panelTitleSelector: "h2.title", navElementTag: "div", crossLinks: false, hashLinking: false, hashNames: true, hashCrossLinks: false, hashTitleSelector: "h2.title", hashTagSeparator: '', // suggestion '/' hashTLD: '', keyboardNavigation: false, leftKey: 39, rightKey: 37, panelKeys: { 1: 49, 2: 50, 3: 51, 4: 52 }, responsive: true, mobileNavigation: true, mobileNavDefaultText: 'Menu', mobileUIThreshold: 0, hideArrowsWhenMobile: true, hideArrowsThreshold: 481, useCSSMaxWidth: 1030, preloader: false, preloaderFadeOutDuration: 250, preloaderElements: 'img,video,iframe,object', swipe: true }; })(jQuery, window, document);