From 3cebeb9b8ae9c7de53c95f8df040a5021c746ef6 Mon Sep 17 00:00:00 2001 From: bnu Date: Mon, 6 Jul 2015 10:50:59 +0900 Subject: [PATCH] =?UTF-8?q?Revert=20"Grunt=20js=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20Swiper,=20Parallax=20js=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20(min=ED=8C=8C=EC=9D=BC=EB=A7=8C=20?= =?UTF-8?q?=EB=82=A8=EA=B9=80)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 2b40378138482873592a992c791d9e01d51d9e5f. --- Gruntfile.js | 1 + layouts/xedition/js/idangerous.swiper.js | 2893 +++++++++++++++++ layouts/xedition/js/jquery.parallax-scroll.js | 126 + 3 files changed, 3020 insertions(+) create mode 100644 layouts/xedition/js/idangerous.swiper.js create mode 100644 layouts/xedition/js/jquery.parallax-scroll.js diff --git a/Gruntfile.js b/Gruntfile.js index 1f0ccf655..14f024715 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -112,6 +112,7 @@ module.exports = function(grunt) { }, 'layout': { files: { + 'layouts/xedition/js/jquery.easing.min.js': ['layouts/xedition/js/jquery.easing.js'], 'layouts/xedition/js/layout.min.js': ['layouts/xedition/js/layout.js'], 'layouts/xedition/js/welcome.min.js': ['layouts/xedition/js/welcome.js'], 'layouts/xedition/js/gnb.pc.min.js': ['layouts/xedition/js/gnb.pc.js'], diff --git a/layouts/xedition/js/idangerous.swiper.js b/layouts/xedition/js/idangerous.swiper.js new file mode 100644 index 000000000..b630afc39 --- /dev/null +++ b/layouts/xedition/js/idangerous.swiper.js @@ -0,0 +1,2893 @@ +/* + * Swiper 2.7.6 + * Mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/sliders/swiper/ + * + * Copyright 2010-2015, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under GPL & MIT + * + * Released on: February 11, 2015 +*/ +var Swiper = function (selector, params) { + 'use strict'; + + /*========================= + A little bit dirty but required part for IE8 and old FF support + ===========================*/ + if (!document.body.outerHTML && document.body.__defineGetter__) { + if (HTMLElement) { + var element = HTMLElement.prototype; + if (element.__defineGetter__) { + element.__defineGetter__('outerHTML', function () { return new XMLSerializer().serializeToString(this); }); + } + } + } + + if (!window.getComputedStyle) { + window.getComputedStyle = function (el, pseudo) { + this.el = el; + this.getPropertyValue = function (prop) { + var re = /(\-([a-z]){1})/g; + if (prop === 'float') prop = 'styleFloat'; + if (re.test(prop)) { + prop = prop.replace(re, function () { + return arguments[2].toUpperCase(); + }); + } + return el.currentStyle[prop] ? el.currentStyle[prop] : null; + }; + return this; + }; + } + if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (obj, start) { + for (var i = (start || 0), j = this.length; i < j; i++) { + if (this[i] === obj) { return i; } + } + return -1; + }; + } + if (!document.querySelectorAll) { + if (!window.jQuery) return; + } + function $$(selector, context) { + if (document.querySelectorAll) + return (context || document).querySelectorAll(selector); + else + return jQuery(selector, context); + } + + /*========================= + Check for correct selector + ===========================*/ + if (typeof selector === 'undefined') return; + + if (!(selector.nodeType)) { + if ($$(selector).length === 0) return; + } + + /*========================= + _this + ===========================*/ + var _this = this; + + /*========================= + Default Flags and vars + ===========================*/ + _this.touches = { + start: 0, + startX: 0, + startY: 0, + current: 0, + currentX: 0, + currentY: 0, + diff: 0, + abs: 0 + }; + _this.positions = { + start: 0, + abs: 0, + diff: 0, + current: 0 + }; + _this.times = { + start: 0, + end: 0 + }; + + _this.id = (new Date()).getTime(); + _this.container = (selector.nodeType) ? selector : $$(selector)[0]; + _this.isTouched = false; + _this.isMoved = false; + _this.activeIndex = 0; + _this.centerIndex = 0; + _this.activeLoaderIndex = 0; + _this.activeLoopIndex = 0; + _this.previousIndex = null; + _this.velocity = 0; + _this.snapGrid = []; + _this.slidesGrid = []; + _this.imagesToLoad = []; + _this.imagesLoaded = 0; + _this.wrapperLeft = 0; + _this.wrapperRight = 0; + _this.wrapperTop = 0; + _this.wrapperBottom = 0; + _this.isAndroid = navigator.userAgent.toLowerCase().indexOf('android') >= 0; + var wrapper, slideSize, wrapperSize, direction, isScrolling, containerSize; + + /*========================= + Default Parameters + ===========================*/ + var defaults = { + eventTarget: 'wrapper', // or 'container' + mode : 'horizontal', // or 'vertical' + touchRatio : 1, + speed : 300, + freeMode : false, + freeModeFluid : false, + momentumRatio: 1, + momentumBounce: true, + momentumBounceRatio: 1, + slidesPerView : 1, + slidesPerGroup : 1, + slidesPerViewFit: true, //Fit to slide when spv "auto" and slides larger than container + simulateTouch : true, + followFinger : true, + shortSwipes : true, + longSwipesRatio: 0.5, + moveStartThreshold: false, + onlyExternal : false, + createPagination : true, + pagination : false, + paginationElement: 'span', + paginationClickable: false, + paginationAsRange: true, + resistance : true, // or false or 100% + scrollContainer : false, + preventLinks : true, + preventLinksPropagation: false, + noSwiping : false, // or class + noSwipingClass : 'swiper-no-swiping', //:) + initialSlide: 0, + keyboardControl: false, + mousewheelControl : false, + mousewheelControlForceToAxis : false, + useCSS3Transforms : true, + // Autoplay + autoplay: false, + autoplayDisableOnInteraction: true, + autoplayStopOnLast: false, + //Loop mode + loop: false, + loopAdditionalSlides: 0, + // Round length values + roundLengths: false, + //Auto Height + calculateHeight: false, + //Apply CSS for width and/or height + cssWidthAndHeight: false, // or true or 'width' or 'height' + //Images Preloader + updateOnImagesReady : true, + //Form elements + releaseFormElements : true, + //Watch for active slide, useful when use effects on different slide states + watchActiveIndex: false, + //Slides Visibility Fit + visibilityFullFit : false, + //Slides Offset + offsetPxBefore : 0, + offsetPxAfter : 0, + offsetSlidesBefore : 0, + offsetSlidesAfter : 0, + centeredSlides: false, + //Queue callbacks + queueStartCallbacks : false, + queueEndCallbacks : false, + //Auto Resize + autoResize : true, + resizeReInit : false, + //DOMAnimation + DOMAnimation : true, + //Slides Loader + loader: { + slides: [], //array with slides + slidesHTMLType: 'inner', // or 'outer' + surroundGroups: 1, //keep preloaded slides groups around view + logic: 'reload', //or 'change' + loadAllSlides: false + }, + // One way swipes + swipeToPrev: true, + swipeToNext: true, + //Namespace + slideElement: 'div', + slideClass: 'swiper-slide', + slideActiveClass: 'swiper-slide-active', + slideVisibleClass: 'swiper-slide-visible', + slideDuplicateClass: 'swiper-slide-duplicate', + wrapperClass: 'swiper-wrapper', + paginationElementClass: 'swiper-pagination-switch', + paginationActiveClass: 'swiper-active-switch', + paginationVisibleClass: 'swiper-visible-switch' + }; + params = params || {}; + for (var prop in defaults) { + if (prop in params && typeof params[prop] === 'object') { + for (var subProp in defaults[prop]) { + if (! (subProp in params[prop])) { + params[prop][subProp] = defaults[prop][subProp]; + } + } + } + else if (! (prop in params)) { + params[prop] = defaults[prop]; + } + } + _this.params = params; + if (params.scrollContainer) { + params.freeMode = true; + params.freeModeFluid = true; + } + if (params.loop) { + params.resistance = '100%'; + } + var isH = params.mode === 'horizontal'; + + /*========================= + Define Touch Events + ===========================*/ + var desktopEvents = ['mousedown', 'mousemove', 'mouseup']; + if (_this.browser.ie10) desktopEvents = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp']; + if (_this.browser.ie11) desktopEvents = ['pointerdown', 'pointermove', 'pointerup']; + + _this.touchEvents = { + touchStart : _this.support.touch || !params.simulateTouch ? 'touchstart' : desktopEvents[0], + touchMove : _this.support.touch || !params.simulateTouch ? 'touchmove' : desktopEvents[1], + touchEnd : _this.support.touch || !params.simulateTouch ? 'touchend' : desktopEvents[2] + }; + + /*========================= + Wrapper + ===========================*/ + for (var i = _this.container.childNodes.length - 1; i >= 0; i--) { + if (_this.container.childNodes[i].className) { + var _wrapperClasses = _this.container.childNodes[i].className.split(/\s+/); + for (var j = 0; j < _wrapperClasses.length; j++) { + if (_wrapperClasses[j] === params.wrapperClass) { + wrapper = _this.container.childNodes[i]; + } + } + } + } + + _this.wrapper = wrapper; + /*========================= + Slide API + ===========================*/ + _this._extendSwiperSlide = function (el) { + el.append = function () { + if (params.loop) { + el.insertAfter(_this.slides.length - _this.loopedSlides); + } + else { + _this.wrapper.appendChild(el); + _this.reInit(); + } + + return el; + }; + el.prepend = function () { + if (params.loop) { + _this.wrapper.insertBefore(el, _this.slides[_this.loopedSlides]); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else { + _this.wrapper.insertBefore(el, _this.wrapper.firstChild); + } + _this.reInit(); + return el; + }; + el.insertAfter = function (index) { + if (typeof index === 'undefined') return false; + var beforeSlide; + + if (params.loop) { + beforeSlide = _this.slides[index + 1 + _this.loopedSlides]; + if (beforeSlide) { + _this.wrapper.insertBefore(el, beforeSlide); + } + else { + _this.wrapper.appendChild(el); + } + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else { + beforeSlide = _this.slides[index + 1]; + _this.wrapper.insertBefore(el, beforeSlide); + } + _this.reInit(); + return el; + }; + el.clone = function () { + return _this._extendSwiperSlide(el.cloneNode(true)); + }; + el.remove = function () { + _this.wrapper.removeChild(el); + _this.reInit(); + }; + el.html = function (html) { + if (typeof html === 'undefined') { + return el.innerHTML; + } + else { + el.innerHTML = html; + return el; + } + }; + el.index = function () { + var index; + for (var i = _this.slides.length - 1; i >= 0; i--) { + if (el === _this.slides[i]) index = i; + } + return index; + }; + el.isActive = function () { + if (el.index() === _this.activeIndex) return true; + else return false; + }; + if (!el.swiperSlideDataStorage) el.swiperSlideDataStorage = {}; + el.getData = function (name) { + return el.swiperSlideDataStorage[name]; + }; + el.setData = function (name, value) { + el.swiperSlideDataStorage[name] = value; + return el; + }; + el.data = function (name, value) { + if (typeof value === 'undefined') { + return el.getAttribute('data-' + name); + } + else { + el.setAttribute('data-' + name, value); + return el; + } + }; + el.getWidth = function (outer, round) { + return _this.h.getWidth(el, outer, round); + }; + el.getHeight = function (outer, round) { + return _this.h.getHeight(el, outer, round); + }; + el.getOffset = function () { + return _this.h.getOffset(el); + }; + return el; + }; + + //Calculate information about number of slides + _this.calcSlides = function (forceCalcSlides) { + var oldNumber = _this.slides ? _this.slides.length : false; + _this.slides = []; + _this.displaySlides = []; + for (var i = 0; i < _this.wrapper.childNodes.length; i++) { + if (_this.wrapper.childNodes[i].className) { + var _className = _this.wrapper.childNodes[i].className; + var _slideClasses = _className.split(/\s+/); + for (var j = 0; j < _slideClasses.length; j++) { + if (_slideClasses[j] === params.slideClass) { + _this.slides.push(_this.wrapper.childNodes[i]); + } + } + } + } + for (i = _this.slides.length - 1; i >= 0; i--) { + _this._extendSwiperSlide(_this.slides[i]); + } + if (oldNumber === false) return; + if (oldNumber !== _this.slides.length || forceCalcSlides) { + + // Number of slides has been changed + removeSlideEvents(); + addSlideEvents(); + _this.updateActiveSlide(); + if (_this.params.pagination) _this.createPagination(); + _this.callPlugins('numberOfSlidesChanged'); + } + }; + + //Create Slide + _this.createSlide = function (html, slideClassList, el) { + slideClassList = slideClassList || _this.params.slideClass; + el = el || params.slideElement; + var newSlide = document.createElement(el); + newSlide.innerHTML = html || ''; + newSlide.className = slideClassList; + return _this._extendSwiperSlide(newSlide); + }; + + //Append Slide + _this.appendSlide = function (html, slideClassList, el) { + if (!html) return; + if (html.nodeType) { + return _this._extendSwiperSlide(html).append(); + } + else { + return _this.createSlide(html, slideClassList, el).append(); + } + }; + _this.prependSlide = function (html, slideClassList, el) { + if (!html) return; + if (html.nodeType) { + return _this._extendSwiperSlide(html).prepend(); + } + else { + return _this.createSlide(html, slideClassList, el).prepend(); + } + }; + _this.insertSlideAfter = function (index, html, slideClassList, el) { + if (typeof index === 'undefined') return false; + if (html.nodeType) { + return _this._extendSwiperSlide(html).insertAfter(index); + } + else { + return _this.createSlide(html, slideClassList, el).insertAfter(index); + } + }; + _this.removeSlide = function (index) { + if (_this.slides[index]) { + if (params.loop) { + if (!_this.slides[index + _this.loopedSlides]) return false; + _this.slides[index + _this.loopedSlides].remove(); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else _this.slides[index].remove(); + return true; + } + else return false; + }; + _this.removeLastSlide = function () { + if (_this.slides.length > 0) { + if (params.loop) { + _this.slides[_this.slides.length - 1 - _this.loopedSlides].remove(); + _this.removeLoopedSlides(); + _this.calcSlides(); + _this.createLoop(); + } + else _this.slides[_this.slides.length - 1].remove(); + return true; + } + else { + return false; + } + }; + _this.removeAllSlides = function () { + var num = _this.slides.length; + for (var i = _this.slides.length - 1; i >= 0; i--) { + _this.slides[i].remove(); + if (i === num - 1) { + _this.setWrapperTranslate(0); + } + } + }; + _this.getSlide = function (index) { + return _this.slides[index]; + }; + _this.getLastSlide = function () { + return _this.slides[_this.slides.length - 1]; + }; + _this.getFirstSlide = function () { + return _this.slides[0]; + }; + + //Currently Active Slide + _this.activeSlide = function () { + return _this.slides[_this.activeIndex]; + }; + + /*========================= + Wrapper for Callbacks : Allows additive callbacks via function arrays + ===========================*/ + _this.fireCallback = function () { + var callback = arguments[0]; + if (Object.prototype.toString.call(callback) === '[object Array]') { + for (var i = 0; i < callback.length; i++) { + if (typeof callback[i] === 'function') { + callback[i](arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + } + } else if (Object.prototype.toString.call(callback) === '[object String]') { + if (params['on' + callback]) _this.fireCallback(params['on' + callback], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } else { + callback(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); + } + }; + function isArray(obj) { + if (Object.prototype.toString.apply(obj) === '[object Array]') return true; + return false; + } + + /** + * Allows user to add callbacks, rather than replace them + * @param callback + * @param func + * @return {*} + */ + _this.addCallback = function (callback, func) { + var _this = this, tempFunc; + if (_this.params['on' + callback]) { + if (isArray(this.params['on' + callback])) { + return this.params['on' + callback].push(func); + } else if (typeof this.params['on' + callback] === 'function') { + tempFunc = this.params['on' + callback]; + this.params['on' + callback] = []; + this.params['on' + callback].push(tempFunc); + return this.params['on' + callback].push(func); + } + } else { + this.params['on' + callback] = []; + return this.params['on' + callback].push(func); + } + }; + _this.removeCallbacks = function (callback) { + if (_this.params['on' + callback]) { + _this.params['on' + callback] = null; + } + }; + + /*========================= + Plugins API + ===========================*/ + var _plugins = []; + for (var plugin in _this.plugins) { + if (params[plugin]) { + var p = _this.plugins[plugin](_this, params[plugin]); + if (p) _plugins.push(p); + } + } + _this.callPlugins = function (method, args) { + if (!args) args = {}; + for (var i = 0; i < _plugins.length; i++) { + if (method in _plugins[i]) { + _plugins[i][method](args); + } + } + }; + + /*========================= + Windows Phone 8 Fix + ===========================*/ + if ((_this.browser.ie10 || _this.browser.ie11) && !params.onlyExternal) { + _this.wrapper.classList.add('swiper-wp8-' + (isH ? 'horizontal' : 'vertical')); + } + + /*========================= + Free Mode Class + ===========================*/ + if (params.freeMode) { + _this.container.className += ' swiper-free-mode'; + } + + /*================================================== + Init/Re-init/Resize Fix + ====================================================*/ + _this.initialized = false; + _this.init = function (force, forceCalcSlides) { + var _width = _this.h.getWidth(_this.container, false, params.roundLengths); + var _height = _this.h.getHeight(_this.container, false, params.roundLengths); + if (_width === _this.width && _height === _this.height && !force) return; + + _this.width = _width; + _this.height = _height; + + var slideWidth, slideHeight, slideMaxHeight, wrapperWidth, wrapperHeight, slideLeft; + var i; // loop index variable to avoid JSHint W004 / W038 + containerSize = isH ? _width : _height; + var wrapper = _this.wrapper; + + if (force) { + _this.calcSlides(forceCalcSlides); + } + + if (params.slidesPerView === 'auto') { + //Auto mode + var slidesWidth = 0; + var slidesHeight = 0; + + //Unset Styles + if (params.slidesOffset > 0) { + wrapper.style.paddingLeft = ''; + wrapper.style.paddingRight = ''; + wrapper.style.paddingTop = ''; + wrapper.style.paddingBottom = ''; + } + wrapper.style.width = ''; + wrapper.style.height = ''; + if (params.offsetPxBefore > 0) { + if (isH) _this.wrapperLeft = params.offsetPxBefore; + else _this.wrapperTop = params.offsetPxBefore; + } + if (params.offsetPxAfter > 0) { + if (isH) _this.wrapperRight = params.offsetPxAfter; + else _this.wrapperBottom = params.offsetPxAfter; + } + + if (params.centeredSlides) { + if (isH) { + _this.wrapperLeft = (containerSize - this.slides[0].getWidth(true, params.roundLengths)) / 2; + _this.wrapperRight = (containerSize - _this.slides[_this.slides.length - 1].getWidth(true, params.roundLengths)) / 2; + } + else { + _this.wrapperTop = (containerSize - _this.slides[0].getHeight(true, params.roundLengths)) / 2; + _this.wrapperBottom = (containerSize - _this.slides[_this.slides.length - 1].getHeight(true, params.roundLengths)) / 2; + } + } + + if (isH) { + if (_this.wrapperLeft >= 0) wrapper.style.paddingLeft = _this.wrapperLeft + 'px'; + if (_this.wrapperRight >= 0) wrapper.style.paddingRight = _this.wrapperRight + 'px'; + } + else { + if (_this.wrapperTop >= 0) wrapper.style.paddingTop = _this.wrapperTop + 'px'; + if (_this.wrapperBottom >= 0) wrapper.style.paddingBottom = _this.wrapperBottom + 'px'; + } + slideLeft = 0; + var centeredSlideLeft = 0; + _this.snapGrid = []; + _this.slidesGrid = []; + + slideMaxHeight = 0; + for (i = 0; i < _this.slides.length; i++) { + slideWidth = _this.slides[i].getWidth(true, params.roundLengths); + slideHeight = _this.slides[i].getHeight(true, params.roundLengths); + if (params.calculateHeight) { + slideMaxHeight = Math.max(slideMaxHeight, slideHeight); + } + var _slideSize = isH ? slideWidth : slideHeight; + if (params.centeredSlides) { + var nextSlideWidth = i === _this.slides.length - 1 ? 0 : _this.slides[i + 1].getWidth(true, params.roundLengths); + var nextSlideHeight = i === _this.slides.length - 1 ? 0 : _this.slides[i + 1].getHeight(true, params.roundLengths); + var nextSlideSize = isH ? nextSlideWidth : nextSlideHeight; + if (_slideSize > containerSize) { + if (params.slidesPerViewFit) { + _this.snapGrid.push(slideLeft + _this.wrapperLeft); + _this.snapGrid.push(slideLeft + _slideSize - containerSize + _this.wrapperLeft); + } + else { + for (var j = 0; j <= Math.floor(_slideSize / (containerSize + _this.wrapperLeft)); j++) { + if (j === 0) _this.snapGrid.push(slideLeft + _this.wrapperLeft); + else _this.snapGrid.push(slideLeft + _this.wrapperLeft + containerSize * j); + } + } + _this.slidesGrid.push(slideLeft + _this.wrapperLeft); + } + else { + _this.snapGrid.push(centeredSlideLeft); + _this.slidesGrid.push(centeredSlideLeft); + } + centeredSlideLeft += _slideSize / 2 + nextSlideSize / 2; + } + else { + if (_slideSize > containerSize) { + if (params.slidesPerViewFit) { + _this.snapGrid.push(slideLeft); + _this.snapGrid.push(slideLeft + _slideSize - containerSize); + } + else { + if (containerSize !== 0) { + for (var k = 0; k <= Math.floor(_slideSize / containerSize); k++) { + _this.snapGrid.push(slideLeft + containerSize * k); + } + } + else { + _this.snapGrid.push(slideLeft); + } + } + + } + else { + _this.snapGrid.push(slideLeft); + } + _this.slidesGrid.push(slideLeft); + } + + slideLeft += _slideSize; + + slidesWidth += slideWidth; + slidesHeight += slideHeight; + } + if (params.calculateHeight) _this.height = slideMaxHeight; + if (isH) { + wrapperSize = slidesWidth + _this.wrapperRight + _this.wrapperLeft; + if (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height') { + wrapper.style.width = (slidesWidth) + 'px'; + } + if (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width') { + wrapper.style.height = (_this.height) + 'px'; + } + } + else { + if (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height') { + wrapper.style.width = (_this.width) + 'px'; + } + if (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width') { + wrapper.style.height = (slidesHeight) + 'px'; + } + wrapperSize = slidesHeight + _this.wrapperTop + _this.wrapperBottom; + } + + } + else if (params.scrollContainer) { + //Scroll Container + wrapper.style.width = ''; + wrapper.style.height = ''; + wrapperWidth = _this.slides[0].getWidth(true, params.roundLengths); + wrapperHeight = _this.slides[0].getHeight(true, params.roundLengths); + wrapperSize = isH ? wrapperWidth : wrapperHeight; + wrapper.style.width = wrapperWidth + 'px'; + wrapper.style.height = wrapperHeight + 'px'; + slideSize = isH ? wrapperWidth : wrapperHeight; + + } + else { + //For usual slides + if (params.calculateHeight) { + slideMaxHeight = 0; + wrapperHeight = 0; + //ResetWrapperSize + if (!isH) _this.container.style.height = ''; + wrapper.style.height = ''; + + for (i = 0; i < _this.slides.length; i++) { + //ResetSlideSize + _this.slides[i].style.height = ''; + slideMaxHeight = Math.max(_this.slides[i].getHeight(true), slideMaxHeight); + if (!isH) wrapperHeight += _this.slides[i].getHeight(true); + } + slideHeight = slideMaxHeight; + _this.height = slideHeight; + + if (isH) wrapperHeight = slideHeight; + else { + containerSize = slideHeight; + _this.container.style.height = containerSize + 'px'; + } + } + else { + slideHeight = isH ? _this.height : _this.height / params.slidesPerView; + if (params.roundLengths) slideHeight = Math.ceil(slideHeight); + wrapperHeight = isH ? _this.height : _this.slides.length * slideHeight; + } + slideWidth = isH ? _this.width / params.slidesPerView : _this.width; + if (params.roundLengths) slideWidth = Math.ceil(slideWidth); + wrapperWidth = isH ? _this.slides.length * slideWidth : _this.width; + slideSize = isH ? slideWidth : slideHeight; + + if (params.offsetSlidesBefore > 0) { + if (isH) _this.wrapperLeft = slideSize * params.offsetSlidesBefore; + else _this.wrapperTop = slideSize * params.offsetSlidesBefore; + } + if (params.offsetSlidesAfter > 0) { + if (isH) _this.wrapperRight = slideSize * params.offsetSlidesAfter; + else _this.wrapperBottom = slideSize * params.offsetSlidesAfter; + } + if (params.offsetPxBefore > 0) { + if (isH) _this.wrapperLeft = params.offsetPxBefore; + else _this.wrapperTop = params.offsetPxBefore; + } + if (params.offsetPxAfter > 0) { + if (isH) _this.wrapperRight = params.offsetPxAfter; + else _this.wrapperBottom = params.offsetPxAfter; + } + if (params.centeredSlides) { + if (isH) { + _this.wrapperLeft = (containerSize - slideSize) / 2; + _this.wrapperRight = (containerSize - slideSize) / 2; + } + else { + _this.wrapperTop = (containerSize - slideSize) / 2; + _this.wrapperBottom = (containerSize - slideSize) / 2; + } + } + if (isH) { + if (_this.wrapperLeft > 0) wrapper.style.paddingLeft = _this.wrapperLeft + 'px'; + if (_this.wrapperRight > 0) wrapper.style.paddingRight = _this.wrapperRight + 'px'; + } + else { + if (_this.wrapperTop > 0) wrapper.style.paddingTop = _this.wrapperTop + 'px'; + if (_this.wrapperBottom > 0) wrapper.style.paddingBottom = _this.wrapperBottom + 'px'; + } + + wrapperSize = isH ? wrapperWidth + _this.wrapperRight + _this.wrapperLeft : wrapperHeight + _this.wrapperTop + _this.wrapperBottom; + if (parseFloat(wrapperWidth) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height')) { + wrapper.style.width = wrapperWidth + 'px'; + } + if (parseFloat(wrapperHeight) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width')) { + wrapper.style.height = wrapperHeight + 'px'; + } + slideLeft = 0; + _this.snapGrid = []; + _this.slidesGrid = []; + for (i = 0; i < _this.slides.length; i++) { + _this.snapGrid.push(slideLeft); + _this.slidesGrid.push(slideLeft); + slideLeft += slideSize; + if (parseFloat(slideWidth) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'height')) { + _this.slides[i].style.width = slideWidth + 'px'; + } + if (parseFloat(slideHeight) > 0 && (!params.cssWidthAndHeight || params.cssWidthAndHeight === 'width')) { + _this.slides[i].style.height = slideHeight + 'px'; + } + } + + } + + if (!_this.initialized) { + _this.callPlugins('onFirstInit'); + if (params.onFirstInit) _this.fireCallback(params.onFirstInit, _this); + } + else { + _this.callPlugins('onInit'); + if (params.onInit) _this.fireCallback(params.onInit, _this); + } + _this.initialized = true; + }; + + _this.reInit = function (forceCalcSlides) { + _this.init(true, forceCalcSlides); + }; + + _this.resizeFix = function (reInit) { + _this.callPlugins('beforeResizeFix'); + + _this.init(params.resizeReInit || reInit); + + // swipe to active slide in fixed mode + if (!params.freeMode) { + _this.swipeTo((params.loop ? _this.activeLoopIndex : _this.activeIndex), 0, false); + // Fix autoplay + if (params.autoplay) { + if (_this.support.transitions && typeof autoplayTimeoutId !== 'undefined') { + if (typeof autoplayTimeoutId !== 'undefined') { + clearTimeout(autoplayTimeoutId); + autoplayTimeoutId = undefined; + _this.startAutoplay(); + } + } + else { + if (typeof autoplayIntervalId !== 'undefined') { + clearInterval(autoplayIntervalId); + autoplayIntervalId = undefined; + _this.startAutoplay(); + } + } + } + } + // move wrapper to the beginning in free mode + else if (_this.getWrapperTranslate() < -maxWrapperPosition()) { + _this.setWrapperTransition(0); + _this.setWrapperTranslate(-maxWrapperPosition()); + } + + _this.callPlugins('afterResizeFix'); + }; + + /*========================================== + Max and Min Positions + ============================================*/ + function maxWrapperPosition() { + var a = (wrapperSize - containerSize); + if (params.freeMode) { + a = wrapperSize - containerSize; + } + // if (params.loop) a -= containerSize; + if (params.slidesPerView > _this.slides.length && !params.centeredSlides) { + a = 0; + } + if (a < 0) a = 0; + return a; + } + + /*========================================== + Event Listeners + ============================================*/ + function initEvents() { + var bind = _this.h.addEventListener; + var eventTarget = params.eventTarget === 'wrapper' ? _this.wrapper : _this.container; + //Touch Events + if (! (_this.browser.ie10 || _this.browser.ie11)) { + if (_this.support.touch) { + bind(eventTarget, 'touchstart', onTouchStart); + bind(eventTarget, 'touchmove', onTouchMove); + bind(eventTarget, 'touchend', onTouchEnd); + } + if (params.simulateTouch) { + bind(eventTarget, 'mousedown', onTouchStart); + bind(document, 'mousemove', onTouchMove); + bind(document, 'mouseup', onTouchEnd); + } + } + else { + bind(eventTarget, _this.touchEvents.touchStart, onTouchStart); + bind(document, _this.touchEvents.touchMove, onTouchMove); + bind(document, _this.touchEvents.touchEnd, onTouchEnd); + } + + //Resize Event + if (params.autoResize) { + bind(window, 'resize', _this.resizeFix); + } + //Slide Events + addSlideEvents(); + //Mousewheel + _this._wheelEvent = false; + if (params.mousewheelControl) { + if (document.onmousewheel !== undefined) { + _this._wheelEvent = 'mousewheel'; + } + if (!_this._wheelEvent) { + try { + new WheelEvent('wheel'); + _this._wheelEvent = 'wheel'; + } catch (e) {} + } + if (!_this._wheelEvent) { + _this._wheelEvent = 'DOMMouseScroll'; + } + if (_this._wheelEvent) { + bind(_this.container, _this._wheelEvent, handleMousewheel); + } + } + + //Keyboard + function _loadImage(img) { + var image, src; + var onReady = function () { + if (typeof _this === 'undefined' || _this === null) return; + if (_this.imagesLoaded !== undefined) _this.imagesLoaded++; + if (_this.imagesLoaded === _this.imagesToLoad.length) { + _this.reInit(); + if (params.onImagesReady) _this.fireCallback(params.onImagesReady, _this); + } + }; + + if (!img.complete) { + src = (img.currentSrc || img.getAttribute('src')); + if (src) { + image = new Image(); + image.onload = onReady; + image.onerror = onReady; + image.src = src; + } else { + onReady(); + } + + } else {//image already loaded... + onReady(); + } + } + + if (params.keyboardControl) { + bind(document, 'keydown', handleKeyboardKeys); + } + if (params.updateOnImagesReady) { + _this.imagesToLoad = $$('img', _this.container); + + for (var i = 0; i < _this.imagesToLoad.length; i++) { + _loadImage(_this.imagesToLoad[i]); + } + } + } + + //Remove Event Listeners + _this.destroy = function (removeStyles) { + var unbind = _this.h.removeEventListener; + var eventTarget = params.eventTarget === 'wrapper' ? _this.wrapper : _this.container; + //Touch Events + if (! (_this.browser.ie10 || _this.browser.ie11)) { + if (_this.support.touch) { + unbind(eventTarget, 'touchstart', onTouchStart); + unbind(eventTarget, 'touchmove', onTouchMove); + unbind(eventTarget, 'touchend', onTouchEnd); + } + if (params.simulateTouch) { + unbind(eventTarget, 'mousedown', onTouchStart); + unbind(document, 'mousemove', onTouchMove); + unbind(document, 'mouseup', onTouchEnd); + } + } + else { + unbind(eventTarget, _this.touchEvents.touchStart, onTouchStart); + unbind(document, _this.touchEvents.touchMove, onTouchMove); + unbind(document, _this.touchEvents.touchEnd, onTouchEnd); + } + + //Resize Event + if (params.autoResize) { + unbind(window, 'resize', _this.resizeFix); + } + + //Init Slide Events + removeSlideEvents(); + + //Pagination + if (params.paginationClickable) { + removePaginationEvents(); + } + + //Mousewheel + if (params.mousewheelControl && _this._wheelEvent) { + unbind(_this.container, _this._wheelEvent, handleMousewheel); + } + + //Keyboard + if (params.keyboardControl) { + unbind(document, 'keydown', handleKeyboardKeys); + } + + //Stop autoplay + if (params.autoplay) { + _this.stopAutoplay(); + } + // Remove styles + if (removeStyles) { + _this.wrapper.removeAttribute('style'); + for (var i = 0; i < _this.slides.length; i++) { + _this.slides[i].removeAttribute('style'); + } + } + // Plugins + _this.callPlugins('onDestroy'); + + // Check jQuery/Zepto data + if (window.jQuery && window.jQuery(_this.container).data('swiper')) { + window.jQuery(_this.container).removeData('swiper'); + } + if (window.Zepto && window.Zepto(_this.container).data('swiper')) { + window.Zepto(_this.container).removeData('swiper'); + } + + //Destroy variable + _this = null; + }; + + function addSlideEvents() { + var bind = _this.h.addEventListener, + i; + + //Prevent Links Events + if (params.preventLinks) { + var links = $$('a', _this.container); + for (i = 0; i < links.length; i++) { + bind(links[i], 'click', preventClick); + } + } + //Release Form Elements + if (params.releaseFormElements) { + var formElements = $$('input, textarea, select', _this.container); + for (i = 0; i < formElements.length; i++) { + bind(formElements[i], _this.touchEvents.touchStart, releaseForms, true); + if (_this.support.touch && params.simulateTouch) { + bind(formElements[i], 'mousedown', releaseForms, true); + } + } + } + + //Slide Clicks & Touches + if (params.onSlideClick) { + for (i = 0; i < _this.slides.length; i++) { + bind(_this.slides[i], 'click', slideClick); + } + } + if (params.onSlideTouch) { + for (i = 0; i < _this.slides.length; i++) { + bind(_this.slides[i], _this.touchEvents.touchStart, slideTouch); + } + } + } + function removeSlideEvents() { + var unbind = _this.h.removeEventListener, + i; + + //Slide Clicks & Touches + if (params.onSlideClick) { + for (i = 0; i < _this.slides.length; i++) { + unbind(_this.slides[i], 'click', slideClick); + } + } + if (params.onSlideTouch) { + for (i = 0; i < _this.slides.length; i++) { + unbind(_this.slides[i], _this.touchEvents.touchStart, slideTouch); + } + } + //Release Form Elements + if (params.releaseFormElements) { + var formElements = $$('input, textarea, select', _this.container); + for (i = 0; i < formElements.length; i++) { + unbind(formElements[i], _this.touchEvents.touchStart, releaseForms, true); + if (_this.support.touch && params.simulateTouch) { + unbind(formElements[i], 'mousedown', releaseForms, true); + } + } + } + //Prevent Links Events + if (params.preventLinks) { + var links = $$('a', _this.container); + for (i = 0; i < links.length; i++) { + unbind(links[i], 'click', preventClick); + } + } + } + /*========================================== + Keyboard Control + ============================================*/ + function handleKeyboardKeys(e) { + var kc = e.keyCode || e.charCode; + if (e.shiftKey || e.altKey || e.ctrlKey || e.metaKey) return; + if (kc === 37 || kc === 39 || kc === 38 || kc === 40) { + var inView = false; + //Check that swiper should be inside of visible area of window + var swiperOffset = _this.h.getOffset(_this.container); + var scrollLeft = _this.h.windowScroll().left; + var scrollTop = _this.h.windowScroll().top; + var windowWidth = _this.h.windowWidth(); + var windowHeight = _this.h.windowHeight(); + var swiperCoord = [ + [swiperOffset.left, swiperOffset.top], + [swiperOffset.left + _this.width, swiperOffset.top], + [swiperOffset.left, swiperOffset.top + _this.height], + [swiperOffset.left + _this.width, swiperOffset.top + _this.height] + ]; + for (var i = 0; i < swiperCoord.length; i++) { + var point = swiperCoord[i]; + if ( + point[0] >= scrollLeft && point[0] <= scrollLeft + windowWidth && + point[1] >= scrollTop && point[1] <= scrollTop + windowHeight + ) { + inView = true; + } + + } + if (!inView) return; + } + if (isH) { + if (kc === 37 || kc === 39) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if (kc === 39) _this.swipeNext(); + if (kc === 37) _this.swipePrev(); + } + else { + if (kc === 38 || kc === 40) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + if (kc === 40) _this.swipeNext(); + if (kc === 38) _this.swipePrev(); + } + } + + _this.disableKeyboardControl = function () { + params.keyboardControl = false; + _this.h.removeEventListener(document, 'keydown', handleKeyboardKeys); + }; + + _this.enableKeyboardControl = function () { + params.keyboardControl = true; + _this.h.addEventListener(document, 'keydown', handleKeyboardKeys); + }; + + /*========================================== + Mousewheel Control + ============================================*/ + var lastScrollTime = (new Date()).getTime(); + function handleMousewheel(e) { + var we = _this._wheelEvent; + var delta = 0; + + //Opera & IE + if (e.detail) delta = -e.detail; + //WebKits + else if (we === 'mousewheel') { + if (params.mousewheelControlForceToAxis) { + if (isH) { + if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) delta = e.wheelDeltaX; + else return; + } + else { + if (Math.abs(e.wheelDeltaY) > Math.abs(e.wheelDeltaX)) delta = e.wheelDeltaY; + else return; + } + } + else { + delta = e.wheelDelta; + } + } + //Old FireFox + else if (we === 'DOMMouseScroll') delta = -e.detail; + //New FireFox + else if (we === 'wheel') { + if (params.mousewheelControlForceToAxis) { + if (isH) { + if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) delta = -e.deltaX; + else return; + } + else { + if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) delta = -e.deltaY; + else return; + } + } + else { + delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? - e.deltaX : - e.deltaY; + } + } + + if (!params.freeMode) { + if ((new Date()).getTime() - lastScrollTime > 60) { + if (delta < 0) _this.swipeNext(); + else _this.swipePrev(); + } + lastScrollTime = (new Date()).getTime(); + + } + else { + //Freemode or scrollContainer: + var position = _this.getWrapperTranslate() + delta; + + if (position > 0) position = 0; + if (position < -maxWrapperPosition()) position = -maxWrapperPosition(); + + _this.setWrapperTransition(0); + _this.setWrapperTranslate(position); + _this.updateActiveSlide(position); + + // Return page scroll on edge positions + if (position === 0 || position === -maxWrapperPosition()) return; + } + if (params.autoplay) _this.stopAutoplay(true); + + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + return false; + } + _this.disableMousewheelControl = function () { + if (!_this._wheelEvent) return false; + params.mousewheelControl = false; + _this.h.removeEventListener(_this.container, _this._wheelEvent, handleMousewheel); + return true; + }; + + _this.enableMousewheelControl = function () { + if (!_this._wheelEvent) return false; + params.mousewheelControl = true; + _this.h.addEventListener(_this.container, _this._wheelEvent, handleMousewheel); + return true; + }; + + /*========================= + Grab Cursor + ===========================*/ + if (params.grabCursor) { + var containerStyle = _this.container.style; + containerStyle.cursor = 'move'; + containerStyle.cursor = 'grab'; + containerStyle.cursor = '-moz-grab'; + containerStyle.cursor = '-webkit-grab'; + } + + /*========================= + Slides Events Handlers + ===========================*/ + + _this.allowSlideClick = true; + function slideClick(event) { + if (_this.allowSlideClick) { + setClickedSlide(event); + _this.fireCallback(params.onSlideClick, _this, event); + } + } + + function slideTouch(event) { + setClickedSlide(event); + _this.fireCallback(params.onSlideTouch, _this, event); + } + + function setClickedSlide(event) { + + // IE 6-8 support + if (!event.currentTarget) { + var element = event.srcElement; + do { + if (element.className.indexOf(params.slideClass) > -1) { + break; + } + element = element.parentNode; + } while (element); + _this.clickedSlide = element; + } + else { + _this.clickedSlide = event.currentTarget; + } + + _this.clickedSlideIndex = _this.slides.indexOf(_this.clickedSlide); + _this.clickedSlideLoopIndex = _this.clickedSlideIndex - (_this.loopedSlides || 0); + } + + _this.allowLinks = true; + function preventClick(e) { + if (!_this.allowLinks) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + if (params.preventLinksPropagation && 'stopPropagation' in e) { + e.stopPropagation(); + } + return false; + } + } + function releaseForms(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.returnValue = false; + return false; + + } + + /*================================================== + Event Handlers + ====================================================*/ + var isTouchEvent = false; + var allowThresholdMove; + var allowMomentumBounce = true; + function onTouchStart(event) { + if (params.preventLinks) _this.allowLinks = true; + //Exit if slider is already was touched + if (_this.isTouched || params.onlyExternal) { + return false; + } + + // Blur active elements + var eventTarget = event.target || event.srcElement; + if (document.activeElement && document.activeElement !== document.body) { + if (document.activeElement !== eventTarget) document.activeElement.blur(); + } + + // Form tag names + var formTagNames = ('input select textarea').split(' '); + + // Check for no swiping + if (params.noSwiping && (eventTarget) && noSwipingSlide(eventTarget)) return false; + allowMomentumBounce = false; + //Check For Nested Swipers + _this.isTouched = true; + isTouchEvent = event.type === 'touchstart'; + + // prevent user enter with right and the swiper move (needs isTouchEvent) + if (!isTouchEvent && 'which' in event && event.which === 3) { + _this.isTouched = false; + return false; + } + + if (!isTouchEvent || event.targetTouches.length === 1) { + _this.callPlugins('onTouchStartBegin'); + if (!isTouchEvent && !_this.isAndroid && formTagNames.indexOf(eventTarget.tagName.toLowerCase()) < 0) { + + if (event.preventDefault) event.preventDefault(); + else event.returnValue = false; + } + + var pageX = isTouchEvent ? event.targetTouches[0].pageX : (event.pageX || event.clientX); + var pageY = isTouchEvent ? event.targetTouches[0].pageY : (event.pageY || event.clientY); + + //Start Touches to check the scrolling + _this.touches.startX = _this.touches.currentX = pageX; + _this.touches.startY = _this.touches.currentY = pageY; + + _this.touches.start = _this.touches.current = isH ? pageX : pageY; + + //Set Transition Time to 0 + _this.setWrapperTransition(0); + + //Get Start Translate Position + _this.positions.start = _this.positions.current = _this.getWrapperTranslate(); + + //Set Transform + _this.setWrapperTranslate(_this.positions.start); + + //TouchStartTime + _this.times.start = (new Date()).getTime(); + + //Unset Scrolling + isScrolling = undefined; + + //Set Treshold + if (params.moveStartThreshold > 0) { + allowThresholdMove = false; + } + + //CallBack + if (params.onTouchStart) _this.fireCallback(params.onTouchStart, _this, event); + _this.callPlugins('onTouchStartEnd'); + + } + } + var velocityPrevPosition, velocityPrevTime; + function onTouchMove(event) { + // If slider is not touched - exit + if (!_this.isTouched || params.onlyExternal) return; + if (isTouchEvent && event.type === 'mousemove') return; + + var pageX = isTouchEvent ? event.targetTouches[0].pageX : (event.pageX || event.clientX); + var pageY = isTouchEvent ? event.targetTouches[0].pageY : (event.pageY || event.clientY); + + //check for scrolling + if (typeof isScrolling === 'undefined' && isH) { + isScrolling = !!(isScrolling || Math.abs(pageY - _this.touches.startY) > Math.abs(pageX - _this.touches.startX)); + } + if (typeof isScrolling === 'undefined' && !isH) { + isScrolling = !!(isScrolling || Math.abs(pageY - _this.touches.startY) < Math.abs(pageX - _this.touches.startX)); + } + if (isScrolling) { + _this.isTouched = false; + return; + } + + // One way swipes + if (isH) { + if ((!params.swipeToNext && pageX < _this.touches.startX) || ((!params.swipeToPrev && pageX > _this.touches.startX))) { + return; + } + } + else { + if ((!params.swipeToNext && pageY < _this.touches.startY) || ((!params.swipeToPrev && pageY > _this.touches.startY))) { + return; + } + } + + //Check For Nested Swipers + if (event.assignedToSwiper) { + _this.isTouched = false; + return; + } + event.assignedToSwiper = true; + + //Block inner links + if (params.preventLinks) { + _this.allowLinks = false; + } + if (params.onSlideClick) { + _this.allowSlideClick = false; + } + + //Stop AutoPlay if exist + if (params.autoplay) { + _this.stopAutoplay(true); + } + if (!isTouchEvent || event.touches.length === 1) { + + //Moved Flag + if (!_this.isMoved) { + _this.callPlugins('onTouchMoveStart'); + + if (params.loop) { + _this.fixLoop(); + _this.positions.start = _this.getWrapperTranslate(); + } + if (params.onTouchMoveStart) _this.fireCallback(params.onTouchMoveStart, _this); + } + _this.isMoved = true; + + // cancel event + if (event.preventDefault) event.preventDefault(); + else event.returnValue = false; + + _this.touches.current = isH ? pageX : pageY; + + _this.positions.current = (_this.touches.current - _this.touches.start) * params.touchRatio + _this.positions.start; + + //Resistance Callbacks + if (_this.positions.current > 0 && params.onResistanceBefore) { + _this.fireCallback(params.onResistanceBefore, _this, _this.positions.current); + } + if (_this.positions.current < -maxWrapperPosition() && params.onResistanceAfter) { + _this.fireCallback(params.onResistanceAfter, _this, Math.abs(_this.positions.current + maxWrapperPosition())); + } + //Resistance + if (params.resistance && params.resistance !== '100%') { + var resistance; + //Resistance for Negative-Back sliding + if (_this.positions.current > 0) { + resistance = 1 - _this.positions.current / containerSize / 2; + if (resistance < 0.5) + _this.positions.current = (containerSize / 2); + else + _this.positions.current = _this.positions.current * resistance; + } + //Resistance for After-End Sliding + if (_this.positions.current < -maxWrapperPosition()) { + + var diff = (_this.touches.current - _this.touches.start) * params.touchRatio + (maxWrapperPosition() + _this.positions.start); + resistance = (containerSize + diff) / (containerSize); + var newPos = _this.positions.current - diff * (1 - resistance) / 2; + var stopPos = -maxWrapperPosition() - containerSize / 2; + + if (newPos < stopPos || resistance <= 0) + _this.positions.current = stopPos; + else + _this.positions.current = newPos; + } + } + if (params.resistance && params.resistance === '100%') { + //Resistance for Negative-Back sliding + if (_this.positions.current > 0 && !(params.freeMode && !params.freeModeFluid)) { + _this.positions.current = 0; + } + //Resistance for After-End Sliding + if (_this.positions.current < -maxWrapperPosition() && !(params.freeMode && !params.freeModeFluid)) { + _this.positions.current = -maxWrapperPosition(); + } + } + //Move Slides + if (!params.followFinger) return; + + if (!params.moveStartThreshold) { + _this.setWrapperTranslate(_this.positions.current); + } + else { + if (Math.abs(_this.touches.current - _this.touches.start) > params.moveStartThreshold || allowThresholdMove) { + if (!allowThresholdMove) { + allowThresholdMove = true; + _this.touches.start = _this.touches.current; + return; + } + _this.setWrapperTranslate(_this.positions.current); + } + else { + _this.positions.current = _this.positions.start; + } + } + + if (params.freeMode || params.watchActiveIndex) { + _this.updateActiveSlide(_this.positions.current); + } + + //Grab Cursor + if (params.grabCursor) { + _this.container.style.cursor = 'move'; + _this.container.style.cursor = 'grabbing'; + _this.container.style.cursor = '-moz-grabbin'; + _this.container.style.cursor = '-webkit-grabbing'; + } + //Velocity + if (!velocityPrevPosition) velocityPrevPosition = _this.touches.current; + if (!velocityPrevTime) velocityPrevTime = (new Date()).getTime(); + _this.velocity = (_this.touches.current - velocityPrevPosition) / ((new Date()).getTime() - velocityPrevTime) / 2; + if (Math.abs(_this.touches.current - velocityPrevPosition) < 2) _this.velocity = 0; + velocityPrevPosition = _this.touches.current; + velocityPrevTime = (new Date()).getTime(); + //Callbacks + _this.callPlugins('onTouchMoveEnd'); + if (params.onTouchMove) _this.fireCallback(params.onTouchMove, _this, event); + + return false; + } + } + function onTouchEnd(event) { + //Check For scrolling + if (isScrolling) { + _this.swipeReset(); + } + // If slider is not touched exit + if (params.onlyExternal || !_this.isTouched) return; + _this.isTouched = false; + + //Return Grab Cursor + if (params.grabCursor) { + _this.container.style.cursor = 'move'; + _this.container.style.cursor = 'grab'; + _this.container.style.cursor = '-moz-grab'; + _this.container.style.cursor = '-webkit-grab'; + } + + //Check for Current Position + if (!_this.positions.current && _this.positions.current !== 0) { + _this.positions.current = _this.positions.start; + } + + //For case if slider touched but not moved + if (params.followFinger) { + _this.setWrapperTranslate(_this.positions.current); + } + + // TouchEndTime + _this.times.end = (new Date()).getTime(); + + //Difference + _this.touches.diff = _this.touches.current - _this.touches.start; + _this.touches.abs = Math.abs(_this.touches.diff); + + _this.positions.diff = _this.positions.current - _this.positions.start; + _this.positions.abs = Math.abs(_this.positions.diff); + + var diff = _this.positions.diff; + var diffAbs = _this.positions.abs; + var timeDiff = _this.times.end - _this.times.start; + + if (diffAbs < 5 && (timeDiff) < 300 && _this.allowLinks === false) { + if (!params.freeMode && diffAbs !== 0) _this.swipeReset(); + //Release inner links + if (params.preventLinks) { + _this.allowLinks = true; + } + if (params.onSlideClick) { + _this.allowSlideClick = true; + } + } + + setTimeout(function () { + //Release inner links + if (typeof _this === 'undefined' || _this === null) return; + if (params.preventLinks) { + _this.allowLinks = true; + } + if (params.onSlideClick) { + _this.allowSlideClick = true; + } + }, 100); + + var maxPosition = maxWrapperPosition(); + + //Not moved or Prevent Negative Back Sliding/After-End Sliding + if (!_this.isMoved && params.freeMode) { + _this.isMoved = false; + if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event); + _this.callPlugins('onTouchEnd'); + return; + } + if (!_this.isMoved || _this.positions.current > 0 || _this.positions.current < -maxPosition) { + _this.swipeReset(); + if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event); + _this.callPlugins('onTouchEnd'); + return; + } + + _this.isMoved = false; + + //Free Mode + if (params.freeMode) { + if (params.freeModeFluid) { + var momentumDuration = 1000 * params.momentumRatio; + var momentumDistance = _this.velocity * momentumDuration; + var newPosition = _this.positions.current + momentumDistance; + var doBounce = false; + var afterBouncePosition; + var bounceAmount = Math.abs(_this.velocity) * 20 * params.momentumBounceRatio; + if (newPosition < -maxPosition) { + if (params.momentumBounce && _this.support.transitions) { + if (newPosition + maxPosition < -bounceAmount) newPosition = -maxPosition - bounceAmount; + afterBouncePosition = -maxPosition; + doBounce = true; + allowMomentumBounce = true; + } + else newPosition = -maxPosition; + } + if (newPosition > 0) { + if (params.momentumBounce && _this.support.transitions) { + if (newPosition > bounceAmount) newPosition = bounceAmount; + afterBouncePosition = 0; + doBounce = true; + allowMomentumBounce = true; + } + else newPosition = 0; + } + //Fix duration + if (_this.velocity !== 0) momentumDuration = Math.abs((newPosition - _this.positions.current) / _this.velocity); + + _this.setWrapperTranslate(newPosition); + + _this.setWrapperTransition(momentumDuration); + + if (params.momentumBounce && doBounce) { + _this.wrapperTransitionEnd(function () { + if (!allowMomentumBounce) return; + if (params.onMomentumBounce) _this.fireCallback(params.onMomentumBounce, _this); + _this.callPlugins('onMomentumBounce'); + + _this.setWrapperTranslate(afterBouncePosition); + _this.setWrapperTransition(300); + }); + } + + _this.updateActiveSlide(newPosition); + } + if (!params.freeModeFluid || timeDiff >= 300) _this.updateActiveSlide(_this.positions.current); + + if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event); + _this.callPlugins('onTouchEnd'); + return; + } + + //Direction + direction = diff < 0 ? 'toNext' : 'toPrev'; + + //Short Touches + if (direction === 'toNext' && (timeDiff <= 300)) { + if (diffAbs < 30 || !params.shortSwipes) _this.swipeReset(); + else _this.swipeNext(true, true); + } + + if (direction === 'toPrev' && (timeDiff <= 300)) { + if (diffAbs < 30 || !params.shortSwipes) _this.swipeReset(); + else _this.swipePrev(true, true); + } + + //Long Touches + var targetSlideSize = 0; + if (params.slidesPerView === 'auto') { + //Define current slide's width + var currentPosition = Math.abs(_this.getWrapperTranslate()); + var slidesOffset = 0; + var _slideSize; + for (var i = 0; i < _this.slides.length; i++) { + _slideSize = isH ? _this.slides[i].getWidth(true, params.roundLengths) : _this.slides[i].getHeight(true, params.roundLengths); + slidesOffset += _slideSize; + if (slidesOffset > currentPosition) { + targetSlideSize = _slideSize; + break; + } + } + if (targetSlideSize > containerSize) targetSlideSize = containerSize; + } + else { + targetSlideSize = slideSize * params.slidesPerView; + } + if (direction === 'toNext' && (timeDiff > 300)) { + if (diffAbs >= targetSlideSize * params.longSwipesRatio) { + _this.swipeNext(true, true); + } + else { + _this.swipeReset(); + } + } + if (direction === 'toPrev' && (timeDiff > 300)) { + if (diffAbs >= targetSlideSize * params.longSwipesRatio) { + _this.swipePrev(true, true); + } + else { + _this.swipeReset(); + } + } + if (params.onTouchEnd) _this.fireCallback(params.onTouchEnd, _this, event); + _this.callPlugins('onTouchEnd'); + } + + + /*================================================== + noSwiping Bubble Check by Isaac Strack + ====================================================*/ + function hasClass(el, classname) { + return el && el.getAttribute('class') && el.getAttribute('class').indexOf(classname) > -1; + } + function noSwipingSlide(el) { + /*This function is specifically designed to check the parent elements for the noSwiping class, up to the wrapper. + We need to check parents because while onTouchStart bubbles, _this.isTouched is checked in onTouchStart, which stops the bubbling. + So, if a text box, for example, is the initial target, and the parent slide container has the noSwiping class, the _this.isTouched + check will never find it, and what was supposed to be noSwiping is able to be swiped. + This function will iterate up and check for the noSwiping class in parents, up through the wrapperClass.*/ + + // First we create a truthy variable, which is that swiping is allowd (noSwiping = false) + var noSwiping = false; + + // Now we iterate up (parentElements) until we reach the node with the wrapperClass. + do { + + // Each time, we check to see if there's a 'swiper-no-swiping' class (noSwipingClass). + if (hasClass(el, params.noSwipingClass)) + { + noSwiping = true; // If there is, we set noSwiping = true; + } + + el = el.parentElement; // now we iterate up (parent node) + + } while (!noSwiping && el.parentElement && !hasClass(el, params.wrapperClass)); // also include el.parentElement truthy, just in case. + + // because we didn't check the wrapper itself, we do so now, if noSwiping is false: + if (!noSwiping && hasClass(el, params.wrapperClass) && hasClass(el, params.noSwipingClass)) + noSwiping = true; // if the wrapper has the noSwipingClass, we set noSwiping = true; + + return noSwiping; + } + + function addClassToHtmlString(klass, outerHtml) { + var par = document.createElement('div'); + var child; + + par.innerHTML = outerHtml; + child = par.firstChild; + child.className += ' ' + klass; + + return child.outerHTML; + } + + + /*================================================== + Swipe Functions + ====================================================*/ + _this.swipeNext = function (runCallbacks, internal) { + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (!internal && params.loop) _this.fixLoop(); + if (!internal && params.autoplay) _this.stopAutoplay(true); + _this.callPlugins('onSwipeNext'); + var currentPosition = _this.getWrapperTranslate().toFixed(2); + var newPosition = currentPosition; + if (params.slidesPerView === 'auto') { + for (var i = 0; i < _this.snapGrid.length; i++) { + if (-currentPosition >= _this.snapGrid[i].toFixed(2) && -currentPosition < _this.snapGrid[i + 1].toFixed(2)) { + newPosition = -_this.snapGrid[i + 1]; + break; + } + } + } + else { + var groupSize = slideSize * params.slidesPerGroup; + newPosition = -(Math.floor(Math.abs(currentPosition) / Math.floor(groupSize)) * groupSize + groupSize); + } + if (newPosition < -maxWrapperPosition()) { + newPosition = -maxWrapperPosition(); + } + if (newPosition === currentPosition) return false; + swipeToPosition(newPosition, 'next', {runCallbacks: runCallbacks}); + return true; + }; + _this.swipePrev = function (runCallbacks, internal) { + if (typeof runCallbacks === 'undefined') runCallbacks = true; + if (!internal && params.loop) _this.fixLoop(); + if (!internal && params.autoplay) _this.stopAutoplay(true); + _this.callPlugins('onSwipePrev'); + + var currentPosition = Math.ceil(_this.getWrapperTranslate()); + var newPosition; + if (params.slidesPerView === 'auto') { + newPosition = 0; + for (var i = 1; i < _this.snapGrid.length; i++) { + if (-currentPosition === _this.snapGrid[i]) { + newPosition = -_this.snapGrid[i - 1]; + break; + } + if (-currentPosition > _this.snapGrid[i] && -currentPosition < _this.snapGrid[i + 1]) { + newPosition = -_this.snapGrid[i]; + break; + } + } + } + else { + var groupSize = slideSize * params.slidesPerGroup; + newPosition = -(Math.ceil(-currentPosition / groupSize) - 1) * groupSize; + } + + if (newPosition > 0) newPosition = 0; + + if (newPosition === currentPosition) return false; + swipeToPosition(newPosition, 'prev', {runCallbacks: runCallbacks}); + return true; + + }; + _this.swipeReset = function (runCallbacks) { + if (typeof runCallbacks === 'undefined') runCallbacks = true; + _this.callPlugins('onSwipeReset'); + var currentPosition = _this.getWrapperTranslate(); + var groupSize = slideSize * params.slidesPerGroup; + var newPosition; + var maxPosition = -maxWrapperPosition(); + if (params.slidesPerView === 'auto') { + newPosition = 0; + for (var i = 0; i < _this.snapGrid.length; i++) { + if (-currentPosition === _this.snapGrid[i]) return; + if (-currentPosition >= _this.snapGrid[i] && -currentPosition < _this.snapGrid[i + 1]) { + if (_this.positions.diff > 0) newPosition = -_this.snapGrid[i + 1]; + else newPosition = -_this.snapGrid[i]; + break; + } + } + if (-currentPosition >= _this.snapGrid[_this.snapGrid.length - 1]) newPosition = -_this.snapGrid[_this.snapGrid.length - 1]; + if (currentPosition <= -maxWrapperPosition()) newPosition = -maxWrapperPosition(); + } + else { + newPosition = currentPosition < 0 ? Math.round(currentPosition / groupSize) * groupSize : 0; + if (currentPosition <= -maxWrapperPosition()) newPosition = -maxWrapperPosition(); + } + if (params.scrollContainer) { + newPosition = currentPosition < 0 ? currentPosition : 0; + } + if (newPosition < -maxWrapperPosition()) { + newPosition = -maxWrapperPosition(); + } + if (params.scrollContainer && (containerSize > slideSize)) { + newPosition = 0; + } + + if (newPosition === currentPosition) return false; + + swipeToPosition(newPosition, 'reset', {runCallbacks: runCallbacks}); + return true; + }; + + _this.swipeTo = function (index, speed, runCallbacks) { + index = parseInt(index, 10); + _this.callPlugins('onSwipeTo', {index: index, speed: speed}); + if (params.loop) index = index + _this.loopedSlides; + var currentPosition = _this.getWrapperTranslate(); + if (!isFinite(index) || index > (_this.slides.length - 1) || index < 0) return; + var newPosition; + if (params.slidesPerView === 'auto') { + newPosition = -_this.slidesGrid[index]; + } + else { + newPosition = -index * slideSize; + } + if (newPosition < - maxWrapperPosition()) { + newPosition = - maxWrapperPosition(); + } + + if (newPosition === currentPosition) return false; + + if (typeof runCallbacks === 'undefined') runCallbacks = true; + swipeToPosition(newPosition, 'to', {index: index, speed: speed, runCallbacks: runCallbacks}); + return true; + }; + + function swipeToPosition(newPosition, action, toOptions) { + var speed = (action === 'to' && toOptions.speed >= 0) ? toOptions.speed : params.speed; + var timeOld = + new Date(); + + function anim() { + var timeNew = + new Date(); + var time = timeNew - timeOld; + currentPosition += animationStep * time / (1000 / 60); + condition = direction === 'toNext' ? currentPosition > newPosition : currentPosition < newPosition; + if (condition) { + _this.setWrapperTranslate(Math.ceil(currentPosition)); + _this._DOMAnimating = true; + window.setTimeout(function () { + anim(); + }, 1000 / 60); + } + else { + if (params.onSlideChangeEnd) { + if (action === 'to') { + if (toOptions.runCallbacks === true) _this.fireCallback(params.onSlideChangeEnd, _this, direction); + } + else { + _this.fireCallback(params.onSlideChangeEnd, _this, direction); + } + + } + _this.setWrapperTranslate(newPosition); + _this._DOMAnimating = false; + } + } + + if (_this.support.transitions || !params.DOMAnimation) { + _this.setWrapperTranslate(newPosition); + _this.setWrapperTransition(speed); + } + else { + //Try the DOM animation + var currentPosition = _this.getWrapperTranslate(); + var animationStep = Math.ceil((newPosition - currentPosition) / speed * (1000 / 60)); + var direction = currentPosition > newPosition ? 'toNext' : 'toPrev'; + var condition = direction === 'toNext' ? currentPosition > newPosition : currentPosition < newPosition; + if (_this._DOMAnimating) return; + + anim(); + } + + //Update Active Slide Index + _this.updateActiveSlide(newPosition); + + //Callbacks + if (params.onSlideNext && action === 'next' && toOptions.runCallbacks === true) { + _this.fireCallback(params.onSlideNext, _this, newPosition); + } + if (params.onSlidePrev && action === 'prev' && toOptions.runCallbacks === true) { + _this.fireCallback(params.onSlidePrev, _this, newPosition); + } + //'Reset' Callback + if (params.onSlideReset && action === 'reset' && toOptions.runCallbacks === true) { + _this.fireCallback(params.onSlideReset, _this, newPosition); + } + + //'Next', 'Prev' and 'To' Callbacks + if ((action === 'next' || action === 'prev' || action === 'to') && toOptions.runCallbacks === true) + slideChangeCallbacks(action); + } + /*================================================== + Transition Callbacks + ====================================================*/ + //Prevent Multiple Callbacks + _this._queueStartCallbacks = false; + _this._queueEndCallbacks = false; + function slideChangeCallbacks(direction) { + //Transition Start Callback + _this.callPlugins('onSlideChangeStart'); + if (params.onSlideChangeStart) { + if (params.queueStartCallbacks && _this.support.transitions) { + if (_this._queueStartCallbacks) return; + _this._queueStartCallbacks = true; + _this.fireCallback(params.onSlideChangeStart, _this, direction); + _this.wrapperTransitionEnd(function () { + _this._queueStartCallbacks = false; + }); + } + else _this.fireCallback(params.onSlideChangeStart, _this, direction); + } + //Transition End Callback + if (params.onSlideChangeEnd) { + if (_this.support.transitions) { + if (params.queueEndCallbacks) { + if (_this._queueEndCallbacks) return; + _this._queueEndCallbacks = true; + _this.wrapperTransitionEnd(function (swiper) { + _this.fireCallback(params.onSlideChangeEnd, swiper, direction); + }); + } + else { + _this.wrapperTransitionEnd(function (swiper) { + _this.fireCallback(params.onSlideChangeEnd, swiper, direction); + }); + } + } + else { + if (!params.DOMAnimation) { + setTimeout(function () { + _this.fireCallback(params.onSlideChangeEnd, _this, direction); + }, 10); + } + } + } + } + + /*================================================== + Update Active Slide Index + ====================================================*/ + _this.updateActiveSlide = function (position) { + if (!_this.initialized) return; + if (_this.slides.length === 0) return; + _this.previousIndex = _this.activeIndex; + if (typeof position === 'undefined') position = _this.getWrapperTranslate(); + if (position > 0) position = 0; + var i; + if (params.slidesPerView === 'auto') { + var slidesOffset = 0; + _this.activeIndex = _this.slidesGrid.indexOf(-position); + if (_this.activeIndex < 0) { + for (i = 0; i < _this.slidesGrid.length - 1; i++) { + if (-position > _this.slidesGrid[i] && -position < _this.slidesGrid[i + 1]) { + break; + } + } + var leftDistance = Math.abs(_this.slidesGrid[i] + position); + var rightDistance = Math.abs(_this.slidesGrid[i + 1] + position); + if (leftDistance <= rightDistance) _this.activeIndex = i; + else _this.activeIndex = i + 1; + } + } + else { + _this.activeIndex = Math[params.visibilityFullFit ? 'ceil' : 'round'](-position / slideSize); + } + + if (_this.activeIndex === _this.slides.length) _this.activeIndex = _this.slides.length - 1; + if (_this.activeIndex < 0) _this.activeIndex = 0; + + // Check for slide + if (!_this.slides[_this.activeIndex]) return; + + // Calc Visible slides + _this.calcVisibleSlides(position); + + // Mark visible and active slides with additonal classes + if (_this.support.classList) { + var slide; + for (i = 0; i < _this.slides.length; i++) { + slide = _this.slides[i]; + slide.classList.remove(params.slideActiveClass); + if (_this.visibleSlides.indexOf(slide) >= 0) { + slide.classList.add(params.slideVisibleClass); + } else { + slide.classList.remove(params.slideVisibleClass); + } + } + _this.slides[_this.activeIndex].classList.add(params.slideActiveClass); + } else { + var activeClassRegexp = new RegExp('\\s*' + params.slideActiveClass); + var inViewClassRegexp = new RegExp('\\s*' + params.slideVisibleClass); + + for (i = 0; i < _this.slides.length; i++) { + _this.slides[i].className = _this.slides[i].className.replace(activeClassRegexp, '').replace(inViewClassRegexp, ''); + if (_this.visibleSlides.indexOf(_this.slides[i]) >= 0) { + _this.slides[i].className += ' ' + params.slideVisibleClass; + } + } + _this.slides[_this.activeIndex].className += ' ' + params.slideActiveClass; + } + + //Update loop index + if (params.loop) { + var ls = _this.loopedSlides; + _this.activeLoopIndex = _this.activeIndex - ls; + if (_this.activeLoopIndex >= _this.slides.length - ls * 2) { + _this.activeLoopIndex = _this.slides.length - ls * 2 - _this.activeLoopIndex; + } + if (_this.activeLoopIndex < 0) { + _this.activeLoopIndex = _this.slides.length - ls * 2 + _this.activeLoopIndex; + } + if (_this.activeLoopIndex < 0) _this.activeLoopIndex = 0; + } + else { + _this.activeLoopIndex = _this.activeIndex; + } + //Update Pagination + if (params.pagination) { + _this.updatePagination(position); + } + }; + /*================================================== + Pagination + ====================================================*/ + _this.createPagination = function (firstInit) { + if (params.paginationClickable && _this.paginationButtons) { + removePaginationEvents(); + } + _this.paginationContainer = params.pagination.nodeType ? params.pagination : $$(params.pagination)[0]; + if (params.createPagination) { + var paginationHTML = ''; + var numOfSlides = _this.slides.length; + var numOfButtons = numOfSlides; + if (params.loop) numOfButtons -= _this.loopedSlides * 2; + for (var i = 0; i < numOfButtons; i++) { + paginationHTML += '<' + params.paginationElement + ' class="' + params.paginationElementClass + '">'; + } + _this.paginationContainer.innerHTML = paginationHTML; + } + _this.paginationButtons = $$('.' + params.paginationElementClass, _this.paginationContainer); + if (!firstInit) _this.updatePagination(); + _this.callPlugins('onCreatePagination'); + if (params.paginationClickable) { + addPaginationEvents(); + } + }; + function removePaginationEvents() { + var pagers = _this.paginationButtons; + if (pagers) { + for (var i = 0; i < pagers.length; i++) { + _this.h.removeEventListener(pagers[i], 'click', paginationClick); + } + } + } + function addPaginationEvents() { + var pagers = _this.paginationButtons; + if (pagers) { + for (var i = 0; i < pagers.length; i++) { + _this.h.addEventListener(pagers[i], 'click', paginationClick); + } + } + } + function paginationClick(e) { + var index; + var target = e.target || e.srcElement; + var pagers = _this.paginationButtons; + for (var i = 0; i < pagers.length; i++) { + if (target === pagers[i]) index = i; + } + if (params.autoplay) _this.stopAutoplay(true); + _this.swipeTo(index); + } + _this.updatePagination = function (position) { + if (!params.pagination) return; + if (_this.slides.length < 1) return; + var activePagers = $$('.' + params.paginationActiveClass, _this.paginationContainer); + if (!activePagers) return; + + //Reset all Buttons' class to not active + var pagers = _this.paginationButtons; + if (pagers.length === 0) return; + for (var i = 0; i < pagers.length; i++) { + pagers[i].className = params.paginationElementClass; + } + + var indexOffset = params.loop ? _this.loopedSlides : 0; + if (params.paginationAsRange) { + if (!_this.visibleSlides) _this.calcVisibleSlides(position); + //Get Visible Indexes + var visibleIndexes = []; + var j; // lopp index - avoid JSHint W004 / W038 + for (j = 0; j < _this.visibleSlides.length; j++) { + var visIndex = _this.slides.indexOf(_this.visibleSlides[j]) - indexOffset; + + if (params.loop && visIndex < 0) { + visIndex = _this.slides.length - _this.loopedSlides * 2 + visIndex; + } + if (params.loop && visIndex >= _this.slides.length - _this.loopedSlides * 2) { + visIndex = _this.slides.length - _this.loopedSlides * 2 - visIndex; + visIndex = Math.abs(visIndex); + } + visibleIndexes.push(visIndex); + } + + for (j = 0; j < visibleIndexes.length; j++) { + if (pagers[visibleIndexes[j]]) pagers[visibleIndexes[j]].className += ' ' + params.paginationVisibleClass; + } + + if (params.loop) { + if (pagers[_this.activeLoopIndex] !== undefined) { + pagers[_this.activeLoopIndex].className += ' ' + params.paginationActiveClass; + } + } + else { + if (pagers[_this.activeIndex]) pagers[_this.activeIndex].className += ' ' + params.paginationActiveClass; + } + } + else { + if (params.loop) { + if (pagers[_this.activeLoopIndex]) pagers[_this.activeLoopIndex].className += ' ' + params.paginationActiveClass + ' ' + params.paginationVisibleClass; + } + else { + if (pagers[_this.activeIndex]) pagers[_this.activeIndex].className += ' ' + params.paginationActiveClass + ' ' + params.paginationVisibleClass; + } + } + }; + _this.calcVisibleSlides = function (position) { + var visibleSlides = []; + var _slideLeft = 0, _slideSize = 0, _slideRight = 0; + if (isH && _this.wrapperLeft > 0) position = position + _this.wrapperLeft; + if (!isH && _this.wrapperTop > 0) position = position + _this.wrapperTop; + + for (var i = 0; i < _this.slides.length; i++) { + _slideLeft += _slideSize; + if (params.slidesPerView === 'auto') + _slideSize = isH ? _this.h.getWidth(_this.slides[i], true, params.roundLengths) : _this.h.getHeight(_this.slides[i], true, params.roundLengths); + else _slideSize = slideSize; + + _slideRight = _slideLeft + _slideSize; + var isVisibile = false; + if (params.visibilityFullFit) { + if (_slideLeft >= -position && _slideRight <= -position + containerSize) isVisibile = true; + if (_slideLeft <= -position && _slideRight >= -position + containerSize) isVisibile = true; + } + else { + if (_slideRight > -position && _slideRight <= ((-position + containerSize))) isVisibile = true; + if (_slideLeft >= -position && _slideLeft < ((-position + containerSize))) isVisibile = true; + if (_slideLeft < -position && _slideRight > ((-position + containerSize))) isVisibile = true; + } + + if (isVisibile) visibleSlides.push(_this.slides[i]); + + } + if (visibleSlides.length === 0) visibleSlides = [_this.slides[_this.activeIndex]]; + + _this.visibleSlides = visibleSlides; + }; + + /*========================================== + Autoplay + ============================================*/ + var autoplayTimeoutId, autoplayIntervalId; + _this.startAutoplay = function () { + if (_this.support.transitions) { + if (typeof autoplayTimeoutId !== 'undefined') return false; + if (!params.autoplay) return; + _this.callPlugins('onAutoplayStart'); + if (params.onAutoplayStart) _this.fireCallback(params.onAutoplayStart, _this); + autoplay(); + } + else { + if (typeof autoplayIntervalId !== 'undefined') return false; + if (!params.autoplay) return; + _this.callPlugins('onAutoplayStart'); + if (params.onAutoplayStart) _this.fireCallback(params.onAutoplayStart, _this); + autoplayIntervalId = setInterval(function () { + if (params.loop) { + _this.fixLoop(); + _this.swipeNext(true, true); + } + else if (!_this.swipeNext(true, true)) { + if (!params.autoplayStopOnLast) _this.swipeTo(0); + else { + clearInterval(autoplayIntervalId); + autoplayIntervalId = undefined; + } + } + }, params.autoplay); + } + }; + _this.stopAutoplay = function (internal) { + if (_this.support.transitions) { + if (!autoplayTimeoutId) return; + if (autoplayTimeoutId) clearTimeout(autoplayTimeoutId); + autoplayTimeoutId = undefined; + if (internal && !params.autoplayDisableOnInteraction) { + _this.wrapperTransitionEnd(function () { + autoplay(); + }); + } + _this.callPlugins('onAutoplayStop'); + if (params.onAutoplayStop) _this.fireCallback(params.onAutoplayStop, _this); + } + else { + if (autoplayIntervalId) clearInterval(autoplayIntervalId); + autoplayIntervalId = undefined; + _this.callPlugins('onAutoplayStop'); + if (params.onAutoplayStop) _this.fireCallback(params.onAutoplayStop, _this); + } + }; + function autoplay() { + autoplayTimeoutId = setTimeout(function () { + if (params.loop) { + _this.fixLoop(); + _this.swipeNext(true, true); + } + else if (!_this.swipeNext(true, true)) { + if (!params.autoplayStopOnLast) _this.swipeTo(0); + else { + clearTimeout(autoplayTimeoutId); + autoplayTimeoutId = undefined; + } + } + _this.wrapperTransitionEnd(function () { + if (typeof autoplayTimeoutId !== 'undefined') autoplay(); + }); + }, params.autoplay); + } + /*================================================== + Loop + ====================================================*/ + _this.loopCreated = false; + _this.removeLoopedSlides = function () { + if (_this.loopCreated) { + for (var i = 0; i < _this.slides.length; i++) { + if (_this.slides[i].getData('looped') === true) _this.wrapper.removeChild(_this.slides[i]); + } + } + }; + + _this.createLoop = function () { + if (_this.slides.length === 0) return; + if (params.slidesPerView === 'auto') { + _this.loopedSlides = params.loopedSlides || 1; + } + else { + _this.loopedSlides = Math.floor(params.slidesPerView) + params.loopAdditionalSlides; + } + + if (_this.loopedSlides > _this.slides.length) { + _this.loopedSlides = _this.slides.length; + } + + var slideFirstHTML = '', + slideLastHTML = '', + i; + var slidesSetFullHTML = ''; + /** + loopedSlides is too large if loopAdditionalSlides are set. + Need to divide the slides by maximum number of slides existing. + + @author Tomaz Lovrec + */ + var numSlides = _this.slides.length; + var fullSlideSets = Math.floor(_this.loopedSlides / numSlides); + var remainderSlides = _this.loopedSlides % numSlides; + // assemble full sets of slides + for (i = 0; i < (fullSlideSets * numSlides); i++) { + var j = i; + if (i >= numSlides) { + var over = Math.floor(i / numSlides); + j = i - (numSlides * over); + } + slidesSetFullHTML += _this.slides[j].outerHTML; + } + // assemble remainder slides + // assemble remainder appended to existing slides + for (i = 0; i < remainderSlides;i++) { + slideLastHTML += addClassToHtmlString(params.slideDuplicateClass, _this.slides[i].outerHTML); + } + // assemble slides that get preppended to existing slides + for (i = numSlides - remainderSlides; i < numSlides;i++) { + slideFirstHTML += addClassToHtmlString(params.slideDuplicateClass, _this.slides[i].outerHTML); + } + // assemble all slides + var slides = slideFirstHTML + slidesSetFullHTML + wrapper.innerHTML + slidesSetFullHTML + slideLastHTML; + // set the slides + wrapper.innerHTML = slides; + + _this.loopCreated = true; + _this.calcSlides(); + + //Update Looped Slides with special class + for (i = 0; i < _this.slides.length; i++) { + if (i < _this.loopedSlides || i >= _this.slides.length - _this.loopedSlides) _this.slides[i].setData('looped', true); + } + _this.callPlugins('onCreateLoop'); + + }; + + _this.fixLoop = function () { + var newIndex; + //Fix For Negative Oversliding + if (_this.activeIndex < _this.loopedSlides) { + newIndex = _this.slides.length - _this.loopedSlides * 3 + _this.activeIndex; + _this.swipeTo(newIndex, 0, false); + } + //Fix For Positive Oversliding + else if ((params.slidesPerView === 'auto' && _this.activeIndex >= _this.loopedSlides * 2) || (_this.activeIndex > _this.slides.length - params.slidesPerView * 2)) { + newIndex = -_this.slides.length + _this.activeIndex + _this.loopedSlides; + _this.swipeTo(newIndex, 0, false); + } + }; + + /*================================================== + Slides Loader + ====================================================*/ + _this.loadSlides = function () { + var slidesHTML = ''; + _this.activeLoaderIndex = 0; + var slides = params.loader.slides; + var slidesToLoad = params.loader.loadAllSlides ? slides.length : params.slidesPerView * (1 + params.loader.surroundGroups); + for (var i = 0; i < slidesToLoad; i++) { + if (params.loader.slidesHTMLType === 'outer') slidesHTML += slides[i]; + else { + slidesHTML += '<' + params.slideElement + ' class="' + params.slideClass + '" data-swiperindex="' + i + '">' + slides[i] + ''; + } + } + _this.wrapper.innerHTML = slidesHTML; + _this.calcSlides(true); + //Add permanent transitionEnd callback + if (!params.loader.loadAllSlides) { + _this.wrapperTransitionEnd(_this.reloadSlides, true); + } + }; + + _this.reloadSlides = function () { + var slides = params.loader.slides; + var newActiveIndex = parseInt(_this.activeSlide().data('swiperindex'), 10); + if (newActiveIndex < 0 || newActiveIndex > slides.length - 1) return; //<-- Exit + _this.activeLoaderIndex = newActiveIndex; + var firstIndex = Math.max(0, newActiveIndex - params.slidesPerView * params.loader.surroundGroups); + var lastIndex = Math.min(newActiveIndex + params.slidesPerView * (1 + params.loader.surroundGroups) - 1, slides.length - 1); + //Update Transforms + if (newActiveIndex > 0) { + var newTransform = -slideSize * (newActiveIndex - firstIndex); + _this.setWrapperTranslate(newTransform); + _this.setWrapperTransition(0); + } + var i; // loop index + //New Slides + if (params.loader.logic === 'reload') { + _this.wrapper.innerHTML = ''; + var slidesHTML = ''; + for (i = firstIndex; i <= lastIndex; i++) { + slidesHTML += params.loader.slidesHTMLType === 'outer' ? slides[i] : '<' + params.slideElement + ' class="' + params.slideClass + '" data-swiperindex="' + i + '">' + slides[i] + ''; + } + _this.wrapper.innerHTML = slidesHTML; + } + else { + var minExistIndex = 1000; + var maxExistIndex = 0; + + for (i = 0; i < _this.slides.length; i++) { + var index = _this.slides[i].data('swiperindex'); + if (index < firstIndex || index > lastIndex) { + _this.wrapper.removeChild(_this.slides[i]); + } + else { + minExistIndex = Math.min(index, minExistIndex); + maxExistIndex = Math.max(index, maxExistIndex); + } + } + for (i = firstIndex; i <= lastIndex; i++) { + var newSlide; + if (i < minExistIndex) { + newSlide = document.createElement(params.slideElement); + newSlide.className = params.slideClass; + newSlide.setAttribute('data-swiperindex', i); + newSlide.innerHTML = slides[i]; + _this.wrapper.insertBefore(newSlide, _this.wrapper.firstChild); + } + if (i > maxExistIndex) { + newSlide = document.createElement(params.slideElement); + newSlide.className = params.slideClass; + newSlide.setAttribute('data-swiperindex', i); + newSlide.innerHTML = slides[i]; + _this.wrapper.appendChild(newSlide); + } + } + } + //reInit + _this.reInit(true); + }; + + /*================================================== + Make Swiper + ====================================================*/ + function makeSwiper() { + _this.calcSlides(); + if (params.loader.slides.length > 0 && _this.slides.length === 0) { + _this.loadSlides(); + } + if (params.loop) { + _this.createLoop(); + } + _this.init(); + initEvents(); + if (params.pagination) { + _this.createPagination(true); + } + + if (params.loop || params.initialSlide > 0) { + _this.swipeTo(params.initialSlide, 0, false); + } + else { + _this.updateActiveSlide(0); + } + if (params.autoplay) { + _this.startAutoplay(); + } + /** + * Set center slide index. + * + * @author Tomaz Lovrec + */ + _this.centerIndex = _this.activeIndex; + + // Callbacks + if (params.onSwiperCreated) _this.fireCallback(params.onSwiperCreated, _this); + _this.callPlugins('onSwiperCreated'); + } + + makeSwiper(); +}; + +Swiper.prototype = { + plugins : {}, + + /*================================================== + Wrapper Operations + ====================================================*/ + wrapperTransitionEnd : function (callback, permanent) { + 'use strict'; + var a = this, + el = a.wrapper, + events = ['webkitTransitionEnd', 'transitionend', 'oTransitionEnd', 'MSTransitionEnd', 'msTransitionEnd'], + i; + + function fireCallBack(e) { + if (e.target !== el) return; + callback(a); + if (a.params.queueEndCallbacks) a._queueEndCallbacks = false; + if (!permanent) { + for (i = 0; i < events.length; i++) { + a.h.removeEventListener(el, events[i], fireCallBack); + } + } + } + + if (callback) { + for (i = 0; i < events.length; i++) { + a.h.addEventListener(el, events[i], fireCallBack); + } + } + }, + + getWrapperTranslate : function (axis) { + 'use strict'; + var el = this.wrapper, + matrix, curTransform, curStyle, transformMatrix; + + // automatic axis detection + if (typeof axis === 'undefined') { + axis = this.params.mode === 'horizontal' ? 'x' : 'y'; + } + + if (this.support.transforms && this.params.useCSS3Transforms) { + curStyle = window.getComputedStyle(el, null); + if (window.WebKitCSSMatrix) { + // Some old versions of Webkit choke when 'none' is passed; pass + // empty string instead in this case + transformMatrix = new WebKitCSSMatrix(curStyle.webkitTransform === 'none' ? '' : curStyle.webkitTransform); + } + else { + transformMatrix = curStyle.MozTransform || curStyle.OTransform || curStyle.MsTransform || curStyle.msTransform || curStyle.transform || curStyle.getPropertyValue('transform').replace('translate(', 'matrix(1, 0, 0, 1,'); + matrix = transformMatrix.toString().split(','); + } + + if (axis === 'x') { + //Latest Chrome and webkits Fix + if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m41; + //Crazy IE10 Matrix + else if (matrix.length === 16) + curTransform = parseFloat(matrix[12]); + //Normal Browsers + else + curTransform = parseFloat(matrix[4]); + } + if (axis === 'y') { + //Latest Chrome and webkits Fix + if (window.WebKitCSSMatrix) + curTransform = transformMatrix.m42; + //Crazy IE10 Matrix + else if (matrix.length === 16) + curTransform = parseFloat(matrix[13]); + //Normal Browsers + else + curTransform = parseFloat(matrix[5]); + } + } + else { + if (axis === 'x') curTransform = parseFloat(el.style.left, 10) || 0; + if (axis === 'y') curTransform = parseFloat(el.style.top, 10) || 0; + } + return curTransform || 0; + }, + + setWrapperTranslate : function (x, y, z) { + 'use strict'; + var es = this.wrapper.style, + coords = {x: 0, y: 0, z: 0}, + translate; + + // passed all coordinates + if (arguments.length === 3) { + coords.x = x; + coords.y = y; + coords.z = z; + } + + // passed one coordinate and optional axis + else { + if (typeof y === 'undefined') { + y = this.params.mode === 'horizontal' ? 'x' : 'y'; + } + coords[y] = x; + } + + if (this.support.transforms && this.params.useCSS3Transforms) { + translate = this.support.transforms3d ? 'translate3d(' + coords.x + 'px, ' + coords.y + 'px, ' + coords.z + 'px)' : 'translate(' + coords.x + 'px, ' + coords.y + 'px)'; + es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = translate; + } + else { + es.left = coords.x + 'px'; + es.top = coords.y + 'px'; + } + this.callPlugins('onSetWrapperTransform', coords); + if (this.params.onSetWrapperTransform) this.fireCallback(this.params.onSetWrapperTransform, this, coords); + }, + + setWrapperTransition : function (duration) { + 'use strict'; + var es = this.wrapper.style; + es.webkitTransitionDuration = es.MsTransitionDuration = es.msTransitionDuration = es.MozTransitionDuration = es.OTransitionDuration = es.transitionDuration = (duration / 1000) + 's'; + this.callPlugins('onSetWrapperTransition', {duration: duration}); + if (this.params.onSetWrapperTransition) this.fireCallback(this.params.onSetWrapperTransition, this, duration); + + }, + + /*================================================== + Helpers + ====================================================*/ + h : { + getWidth: function (el, outer, round) { + 'use strict'; + var width = window.getComputedStyle(el, null).getPropertyValue('width'); + var returnWidth = parseFloat(width); + //IE Fixes + if (isNaN(returnWidth) || width.indexOf('%') > 0 || returnWidth < 0) { + returnWidth = el.offsetWidth - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left')) - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-right')); + } + if (outer) returnWidth += parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-right')); + if (round) return Math.ceil(returnWidth); + else return returnWidth; + }, + getHeight: function (el, outer, round) { + 'use strict'; + if (outer) return el.offsetHeight; + + var height = window.getComputedStyle(el, null).getPropertyValue('height'); + var returnHeight = parseFloat(height); + //IE Fixes + if (isNaN(returnHeight) || height.indexOf('%') > 0 || returnHeight < 0) { + returnHeight = el.offsetHeight - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-top')) - parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-bottom')); + } + if (outer) returnHeight += parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-top')) + parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-bottom')); + if (round) return Math.ceil(returnHeight); + else return returnHeight; + }, + getOffset: function (el) { + 'use strict'; + var box = el.getBoundingClientRect(); + var body = document.body; + var clientTop = el.clientTop || body.clientTop || 0; + var clientLeft = el.clientLeft || body.clientLeft || 0; + var scrollTop = window.pageYOffset || el.scrollTop; + var scrollLeft = window.pageXOffset || el.scrollLeft; + if (document.documentElement && !window.pageYOffset) { + //IE7-8 + scrollTop = document.documentElement.scrollTop; + scrollLeft = document.documentElement.scrollLeft; + } + return { + top: box.top + scrollTop - clientTop, + left: box.left + scrollLeft - clientLeft + }; + }, + windowWidth : function () { + 'use strict'; + if (window.innerWidth) return window.innerWidth; + else if (document.documentElement && document.documentElement.clientWidth) return document.documentElement.clientWidth; + }, + windowHeight : function () { + 'use strict'; + if (window.innerHeight) return window.innerHeight; + else if (document.documentElement && document.documentElement.clientHeight) return document.documentElement.clientHeight; + }, + windowScroll : function () { + 'use strict'; + if (typeof pageYOffset !== 'undefined') { + return { + left: window.pageXOffset, + top: window.pageYOffset + }; + } + else if (document.documentElement) { + return { + left: document.documentElement.scrollLeft, + top: document.documentElement.scrollTop + }; + } + }, + + addEventListener : function (el, event, listener, useCapture) { + 'use strict'; + if (typeof useCapture === 'undefined') { + useCapture = false; + } + + if (el.addEventListener) { + el.addEventListener(event, listener, useCapture); + } + else if (el.attachEvent) { + el.attachEvent('on' + event, listener); + } + }, + + removeEventListener : function (el, event, listener, useCapture) { + 'use strict'; + if (typeof useCapture === 'undefined') { + useCapture = false; + } + + if (el.removeEventListener) { + el.removeEventListener(event, listener, useCapture); + } + else if (el.detachEvent) { + el.detachEvent('on' + event, listener); + } + } + }, + setTransform : function (el, transform) { + 'use strict'; + var es = el.style; + es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = transform; + }, + setTranslate : function (el, translate) { + 'use strict'; + var es = el.style; + var pos = { + x : translate.x || 0, + y : translate.y || 0, + z : translate.z || 0 + }; + var transformString = this.support.transforms3d ? 'translate3d(' + (pos.x) + 'px,' + (pos.y) + 'px,' + (pos.z) + 'px)' : 'translate(' + (pos.x) + 'px,' + (pos.y) + 'px)'; + es.webkitTransform = es.MsTransform = es.msTransform = es.MozTransform = es.OTransform = es.transform = transformString; + if (!this.support.transforms) { + es.left = pos.x + 'px'; + es.top = pos.y + 'px'; + } + }, + setTransition : function (el, duration) { + 'use strict'; + var es = el.style; + es.webkitTransitionDuration = es.MsTransitionDuration = es.msTransitionDuration = es.MozTransitionDuration = es.OTransitionDuration = es.transitionDuration = duration + 'ms'; + }, + /*================================================== + Feature Detection + ====================================================*/ + support: { + + touch : (window.Modernizr && Modernizr.touch === true) || (function () { + 'use strict'; + return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); + })(), + + transforms3d : (window.Modernizr && Modernizr.csstransforms3d === true) || (function () { + 'use strict'; + var div = document.createElement('div').style; + return ('webkitPerspective' in div || 'MozPerspective' in div || 'OPerspective' in div || 'MsPerspective' in div || 'perspective' in div); + })(), + + transforms : (window.Modernizr && Modernizr.csstransforms === true) || (function () { + 'use strict'; + var div = document.createElement('div').style; + return ('transform' in div || 'WebkitTransform' in div || 'MozTransform' in div || 'msTransform' in div || 'MsTransform' in div || 'OTransform' in div); + })(), + + transitions : (window.Modernizr && Modernizr.csstransitions === true) || (function () { + 'use strict'; + var div = document.createElement('div').style; + return ('transition' in div || 'WebkitTransition' in div || 'MozTransition' in div || 'msTransition' in div || 'MsTransition' in div || 'OTransition' in div); + })(), + + classList : (function () { + 'use strict'; + var div = document.createElement('div'); + return 'classList' in div; + })() + }, + + browser : { + + ie8 : (function () { + 'use strict'; + var rv = -1; // Return value assumes failure. + if (navigator.appName === 'Microsoft Internet Explorer') { + var ua = navigator.userAgent; + var re = new RegExp(/MSIE ([0-9]{1,}[\.0-9]{0,})/); + if (re.exec(ua) !== null) + rv = parseFloat(RegExp.$1); + } + return rv !== -1 && rv < 9; + })(), + + ie10 : window.navigator.msPointerEnabled, + ie11 : window.navigator.pointerEnabled + } +}; + +/*========================= + jQuery & Zepto Plugins + ===========================*/ +if (window.jQuery || window.Zepto) { + (function ($) { + 'use strict'; + $.fn.swiper = function (params) { + var firstInstance; + this.each(function (i) { + var that = $(this); + var s = new Swiper(that[0], params); + if (!i) firstInstance = s; + that.data('swiper', s); + }); + return firstInstance; + }; + })(window.jQuery || window.Zepto); +} + +// CommonJS support +if (typeof(module) !== 'undefined') { + module.exports = Swiper; + +// requirejs support +} else if (typeof define === 'function' && define.amd) { + define([], function () { + 'use strict'; + return Swiper; + }); +} diff --git a/layouts/xedition/js/jquery.parallax-scroll.js b/layouts/xedition/js/jquery.parallax-scroll.js new file mode 100644 index 000000000..033b7fcbf --- /dev/null +++ b/layouts/xedition/js/jquery.parallax-scroll.js @@ -0,0 +1,126 @@ +/* + * Parallax-Scroll - v0.2.0 + * jQuery plugin for background-attachment: scroll with friction, similar to the parallax scrolling effect on Spotify. + * http://parallax-scroll.aenism.com + * + * Made by Aen Tan + * Under MIT License + */ +;(function (root, factory) { + if (typeof define === "function" && define.amd) { + // AMD. Register as an anonymous module. + define(["jquery"], factory); + } else { + // Browser globals + factory(root.jQuery); + } +}(this, function ($) { + "use strict"; + + var ParallaxScroll, + defaults = { + friction: 0.5, + direction: "vertical" + }, + $win = $(window), + lastTickTime = 0; + + window.requestAnimationFrame = function (callback) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 5 - (currTime - lastTickTime)); + var id = window.setTimeout(function () { + callback(currTime + timeToCall); + }, timeToCall); + lastTickTime = currTime + timeToCall; + return id; + }; + + ParallaxScroll = function (background, options) { + return { + init: function () { + this.$background = $(background); + this.settings = $.extend({}, defaults, options); + this._initStyles(); + this._bindEvents(); + }, + _initStyles: function () { + this.$background.css({ + "background-attachment": "scroll" + }); + }, + _visibleInViewport: function () { + var vpHeight = $win.height(); + var rec = this.$background.get(0).getBoundingClientRect(); + return (rec.top < vpHeight && rec.bottom > 0) || (rec.bottom <= vpHeight && rec.top > vpHeight); + }, + _bindEvents: function () { + var self = this; + $win.on("load scroll resize", function () { + self._requestTick(); + }); + }, + _requestTick: function () { + var self = this; + if (!this.ticking) { + this.ticking = true; + requestAnimationFrame(function () { + self._updateBgPos(); + }); + } + }, + _updateBgPos: function () { + if (this._visibleInViewport()) { + var winW = $win.width(); + var winH = $win.height(); + var imgW = this.$background.data("width"); + var imgH = this.$background.data("height"); + var imgA = imgW / imgH; + var bgW = this.$background.width(); + var bgH = this.$background.height(); + var bgA = bgW / bgH; + var revA = bgA < imgA; + var bgScale = bgW / imgW; + var bgScaledH = imgH * bgScale; + var bgScaledW = imgW * bgScale; + var bgOffsetTop = this.$background.offset().top; + var winScrollTop = $win.scrollTop(); + var bgScrollTop = winScrollTop - bgOffsetTop; + var xDistToMove = winH + bgScaledH; + var yDistToMove = winW + bgScaledW; + var xf1 = bgScrollTop * (winH / xDistToMove); + var xf2 = bgScrollTop / winH; + var yf1 = bgScrollTop * (winW / yDistToMove); + var yf2 = bgScrollTop / winW; + var centerOffsetY = (winH - bgH) / 2; + centerOffsetY = revA ? centerOffsetY * xf2 : centerOffsetY; + var centerOffsetX = (winW - bgW) / 2; + centerOffsetX = revA ? centerOffsetX : centerOffsetX * yf2; + var bgFriction = revA? this.settings.friction * (bgA * 2) : this.settings.friction * bgA; + var bgSize; + var bgPos; + if (this.settings.direction === "horizontal") { + bgSize = revA ? winW + "px auto" : "auto " + winH + "px"; + bgPos = (centerOffsetX - (yf1 * bgFriction)) + "px 50%"; + } else { + bgSize = revA ? "auto " + winH + "px" : winW + "px auto"; + bgPos = "50% " + ((xf1 * bgFriction) - centerOffsetY) + "px"; + } + this.$background.css({ + "background-size": bgSize, + "background-position": bgPos + }); + } + this.ticking = false; + } + }; + }; + + ParallaxScroll.defaults = defaults; + $.fn.parallaxScroll = function (options) { + return this.each(function () { + new ParallaxScroll(this, options).init(); + }); + }; + + return ParallaxScroll; +})); \ No newline at end of file