\";\n html += this.renderArrow(true);\n html += this.renderArrow(false);\n html += \"
\";\n return html;\n };\n\n _proto3.renderArrow = function renderArrow(prev) {\n var _this$options = this.options,\n classes = _this$options.classes,\n i18n = _this$options.i18n;\n var attrs = {\n class: classes.arrow + \" \" + (prev ? classes.prev : classes.next),\n type: \"button\",\n ariaLabel: prev ? i18n.prev : i18n.next\n };\n return \"\";\n html += \"\";\n\n if (slider) {\n html += beforeSlider || \"\";\n html += \"
\";\n }\n\n html += beforeTrack || \"\";\n\n if (arrows) {\n html += this.renderArrows();\n }\n\n html += \"
\";\n html += \"<\" + listTag + \" class=\\\"splide__list\\\">\";\n html += this.renderSlides();\n html += \"\" + listTag + \">\";\n html += \"
\";\n html += afterTrack || \"\";\n\n if (slider) {\n html += \"
\";\n html += afterSlider || \"\";\n }\n\n html += \"
\";\n return html;\n };\n\n return SplideRenderer;\n}();\n\nexport { CLASSES, CLASS_ACTIVE, CLASS_ARROW, CLASS_ARROWS, CLASS_ARROW_NEXT, CLASS_ARROW_PREV, CLASS_CLONE, CLASS_CONTAINER, CLASS_FOCUS_IN, CLASS_INITIALIZED, CLASS_LIST, CLASS_LOADING, CLASS_NEXT, CLASS_OVERFLOW, CLASS_PAGINATION, CLASS_PAGINATION_PAGE, CLASS_PREV, CLASS_PROGRESS, CLASS_PROGRESS_BAR, CLASS_ROOT, CLASS_SLIDE, CLASS_SPINNER, CLASS_SR, CLASS_TOGGLE, CLASS_TOGGLE_PAUSE, CLASS_TOGGLE_PLAY, CLASS_TRACK, CLASS_VISIBLE, DEFAULTS, EVENT_ACTIVE, EVENT_ARROWS_MOUNTED, EVENT_ARROWS_UPDATED, EVENT_AUTOPLAY_PAUSE, EVENT_AUTOPLAY_PLAY, EVENT_AUTOPLAY_PLAYING, EVENT_CLICK, EVENT_DESTROY, EVENT_DRAG, EVENT_DRAGGED, EVENT_DRAGGING, EVENT_END_INDEX_CHANGED, EVENT_HIDDEN, EVENT_INACTIVE, EVENT_LAZYLOAD_LOADED, EVENT_MOUNTED, EVENT_MOVE, EVENT_MOVED, EVENT_NAVIGATION_MOUNTED, EVENT_OVERFLOW, EVENT_PAGINATION_MOUNTED, EVENT_PAGINATION_UPDATED, EVENT_READY, EVENT_REFRESH, EVENT_RESIZE, EVENT_RESIZED, EVENT_SCROLL, EVENT_SCROLLED, EVENT_SHIFTED, EVENT_SLIDE_KEYDOWN, EVENT_UPDATED, EVENT_VISIBLE, EventBinder, EventInterface, FADE, LOOP, LTR, RTL, RequestInterval, SLIDE, STATUS_CLASSES, Splide, SplideRenderer, State, TTB, Throttle, Splide as default };\n","/*\r\n * Backstretch\r\n * http://srobbin.com/jquery-plugins/backstretch/\r\n *\r\n * Copyright (c) 2013 Scott Robbin\r\n * Licensed under the MIT license.\r\n */\r\n\r\n;(function ($, window, undefined) {\r\n 'use strict';\r\n\r\n /** @const */\r\n var YOUTUBE_REGEXP = /^.*(youtu\\.be\\/|youtube\\.com\\/v\\/|youtube\\.com\\/embed\\/|youtube\\.com\\/watch\\?v=|youtube\\.com\\/watch\\?.*\\&v=)([^#\\&\\?]*).*/i;\r\n\r\n /* PLUGIN DEFINITION\r\n * ========================= */\r\n\r\n $.fn.backstretch = function (images, options) {\r\n var args = arguments;\r\n\r\n /*\r\n * Scroll the page one pixel to get the right window height on iOS\r\n * Pretty harmless for everyone else\r\n */\r\n if ($(window).scrollTop() === 0) {\r\n window.scrollTo(0, 0);\r\n }\r\n\r\n var returnValues;\r\n\r\n this.each(function (eachIndex) {\r\n var $this = $(this)\r\n , obj = $this.data('backstretch');\r\n\r\n // Do we already have an instance attached to this element?\r\n if (obj) {\r\n\r\n // Is this a method they're trying to execute?\r\n if (typeof args[0] === 'string' &&\r\n typeof obj[args[0]] === 'function') {\r\n\r\n // Call the method\r\n var returnValue = obj[args[0]].apply(obj, Array.prototype.slice.call(args, 1));\r\n if (returnValue === obj) { // If a method is chaining\r\n returnValue = undefined;\r\n }\r\n if (returnValue !== undefined) {\r\n returnValues = returnValues || [];\r\n returnValues[eachIndex] = returnValue;\r\n }\r\n\r\n return; // Nothing further to do\r\n }\r\n\r\n // Merge the old options with the new\r\n options = $.extend(obj.options, options);\r\n\r\n // Remove the old instance\r\n if (typeof obj === 'object' && 'destroy' in obj) {\r\n obj.destroy(true);\r\n }\r\n }\r\n\r\n // We need at least one image\r\n if (!images || (images && images.length === 0)) {\r\n var cssBackgroundImage = $this.css('background-image');\r\n if (cssBackgroundImage && cssBackgroundImage !== 'none') {\r\n images = [{url: $this.css('backgroundImage').replace(/url\\(|\\)|\"|'/g, \"\")}];\r\n }\r\n else {\r\n $.error('No images were supplied for Backstretch, or element must have a CSS-defined background image.');\r\n }\r\n }\r\n\r\n obj = new Backstretch(this, images, options || {});\r\n $this.data('backstretch', obj);\r\n });\r\n\r\n return returnValues ? returnValues.length === 1 ? returnValues[0] : returnValues : this;\r\n };\r\n\r\n // If no element is supplied, we'll attach to body\r\n $.backstretch = function (images, options) {\r\n // Return the instance\r\n return $('body')\r\n .backstretch(images, options)\r\n .data('backstretch');\r\n };\r\n\r\n // Custom selector\r\n $.expr[':'].backstretch = function (elem) {\r\n return $(elem).data('backstretch') !== undefined;\r\n };\r\n\r\n /* DEFAULTS\r\n * ========================= */\r\n\r\n $.fn.backstretch.defaults = {\r\n duration: 5000 // Amount of time in between slides (if slideshow)\r\n , transition: 'fade' // Type of transition between slides\r\n , transitionDuration: 0 // Duration of transition between slides\r\n , animateFirst: true // Animate the transition of first image of slideshow in?\r\n , alignX: 0.5 // The x-alignment for the image, can be 'left'|'center'|'right' or any number between 0.0 and 1.0\r\n , alignY: 0.5 // The y-alignment for the image, can be 'top'|'center'|'bottom' or any number between 0.0 and 1.0\r\n , paused: false // Whether the images should slide after given duration\r\n , start: 0 // Index of the first image to show\r\n , preload: 2 // How many images preload at a time?\r\n , preloadSize: 1 // How many images can we preload in parallel?\r\n , resolutionRefreshRate: 2500 // How long to wait before switching resolution?\r\n , resolutionChangeRatioThreshold: 0.1 // How much a change should it be before switching resolution?\r\n };\r\n\r\n /* STYLES\r\n *\r\n * Baked-in styles that we'll apply to our elements.\r\n * In an effort to keep the plugin simple, these are not exposed as options.\r\n * That said, anyone can override these in their own stylesheet.\r\n * ========================= */\r\n var styles = {\r\n wrap: {\r\n left: 0\r\n , top: 0\r\n , overflow: 'hidden'\r\n , margin: 0\r\n , padding: 0\r\n , height: '100%'\r\n , width: '100%'\r\n , zIndex: -999999\r\n }\r\n , itemWrapper: {\r\n position: 'absolute'\r\n , display: 'none'\r\n , margin: 0\r\n , padding: 0\r\n , border: 'none'\r\n , width: '100%'\r\n , height: '100%'\r\n , zIndex: -999999\r\n }\r\n , item: {\r\n position: 'absolute'\r\n , margin: 0\r\n , padding: 0\r\n , border: 'none'\r\n , width: '100%'\r\n , height: '100%'\r\n , maxWidth: 'none'\r\n }\r\n };\r\n\r\n /* Given an array of different options for an image,\r\n * choose the optimal image for the container size.\r\n *\r\n * Given an image template (a string with {{ width }} and/or\r\n * {{height}} inside) and a container object, returns the\r\n * image url with the exact values for the size of that\r\n * container.\r\n *\r\n * Returns an array of urls optimized for the specified resolution.\r\n *\r\n */\r\n var optimalSizeImages = (function () {\r\n\r\n /* Sorts the array of image sizes based on width */\r\n var widthInsertSort = function (arr) {\r\n for (var i = 1; i < arr.length; i++) {\r\n var tmp = arr[i],\r\n j = i;\r\n while (arr[j - 1] && parseInt(arr[j - 1].width, 10) > parseInt(tmp.width, 10)) {\r\n arr[j] = arr[j - 1];\r\n --j;\r\n }\r\n arr[j] = tmp;\r\n }\r\n\r\n return arr;\r\n };\r\n\r\n /* Given an array of various sizes of the same image and a container width,\r\n * return the best image.\r\n */\r\n var selectBest = function (containerWidth, containerHeight, imageSizes) {\r\n\r\n var devicePixelRatio = window.devicePixelRatio || 1;\r\n var deviceOrientation = getDeviceOrientation();\r\n var windowOrientation = getWindowOrientation();\r\n var wrapperOrientation = (containerHeight > containerWidth) ?\r\n 'portrait' :\r\n (containerWidth > containerHeight ? 'landscape' : 'square');\r\n\r\n var lastAllowedImage = 0;\r\n var testWidth;\r\n\r\n for (var j = 0, image; j < imageSizes.length; j++) {\r\n\r\n image = imageSizes[j];\r\n\r\n // In case a new image was pushed in, process it:\r\n if (typeof image === 'string') {\r\n image = imageSizes[j] = {url: image};\r\n }\r\n\r\n if (image.pixelRatio && image.pixelRatio !== 'auto' && parseFloat(image.pixelRatio) !== devicePixelRatio) {\r\n // We disallowed choosing this image for current device pixel ratio,\r\n // So skip this one.\r\n continue;\r\n }\r\n\r\n if (image.deviceOrientation && image.deviceOrientation !== deviceOrientation) {\r\n // We disallowed choosing this image for current device orientation,\r\n // So skip this one.\r\n continue;\r\n }\r\n\r\n if (image.windowOrientation && image.windowOrientation !== deviceOrientation) {\r\n // We disallowed choosing this image for current window orientation,\r\n // So skip this one.\r\n continue;\r\n }\r\n\r\n if (image.orientation && image.orientation !== wrapperOrientation) {\r\n // We disallowed choosing this image for current element's orientation,\r\n // So skip this one.\r\n continue;\r\n }\r\n\r\n // Mark this one as the last one we investigated\r\n // which does not violate device pixel ratio rules.\r\n // We may choose this one later if there's no match.\r\n lastAllowedImage = j;\r\n\r\n // For most images, we match the specified width against element width,\r\n // And enforcing a limit depending on the \"pixelRatio\" property if specified.\r\n // But if a pixelRatio=\"auto\", then we consider the width as the physical width of the image,\r\n // And match it while considering the device's pixel ratio.\r\n testWidth = containerWidth;\r\n if (image.pixelRatio === 'auto') {\r\n containerWidth *= devicePixelRatio;\r\n }\r\n\r\n // Stop when the width of the image is larger or equal to the container width\r\n if (image.width >= testWidth) {\r\n break;\r\n }\r\n }\r\n\r\n // Use the image located at where we stopped\r\n return imageSizes[Math.min(j, lastAllowedImage)];\r\n };\r\n\r\n var replaceTagsInUrl = function (url, templateReplacer) {\r\n\r\n if (typeof url === 'string') {\r\n url = url.replace(/{{(width|height)}}/g, templateReplacer);\r\n }\r\n else if (url instanceof Array) {\r\n for (var i = 0; i < url.length; i++) {\r\n if (url[i].src) {\r\n url[i].src = replaceTagsInUrl(url[i].src, templateReplacer);\r\n }\r\n else {\r\n url[i] = replaceTagsInUrl(url[i], templateReplacer);\r\n }\r\n }\r\n }\r\n\r\n return url;\r\n };\r\n\r\n return function ($container, images) {\r\n var containerWidth = $container.width(),\r\n containerHeight = $container.height();\r\n\r\n var chosenImages = [];\r\n\r\n var templateReplacer = function (match, key) {\r\n if (key === 'width') {\r\n return containerWidth;\r\n }\r\n if (key === 'height') {\r\n return containerHeight;\r\n }\r\n return match;\r\n };\r\n\r\n for (var i = 0; i < images.length; i++) {\r\n if ($.isArray(images[i])) {\r\n images[i] = widthInsertSort(images[i]);\r\n var chosen = selectBest(containerWidth, containerHeight, images[i]);\r\n chosenImages.push(chosen);\r\n }\r\n else {\r\n // In case a new image was pushed in, process it:\r\n if (typeof images[i] === 'string') {\r\n images[i] = {url: images[i]};\r\n }\r\n\r\n var item = $.extend({}, images[i]);\r\n item.url = replaceTagsInUrl(item.url, templateReplacer);\r\n chosenImages.push(item);\r\n }\r\n }\r\n return chosenImages;\r\n };\r\n\r\n })();\r\n\r\n var isVideoSource = function (source) {\r\n return YOUTUBE_REGEXP.test(source.url) || source.isVideo;\r\n };\r\n\r\n /* Preload images */\r\n var preload = (function (sources, startAt, count, batchSize, callback) {\r\n // Plugin cache\r\n var cache = [];\r\n\r\n // Wrapper for cache\r\n var caching = function (image) {\r\n for (var i = 0; i < cache.length; i++) {\r\n if (cache[i].src === image.src) {\r\n return cache[i];\r\n }\r\n }\r\n cache.push(image);\r\n return image;\r\n };\r\n\r\n // Execute callback\r\n var exec = function (sources, callback, last) {\r\n if (typeof callback === 'function') {\r\n callback.call(sources, last);\r\n }\r\n };\r\n\r\n // Closure to hide cache\r\n return function preload(sources, startAt, count, batchSize, callback) {\r\n // Check input data\r\n if (typeof sources === 'undefined') {\r\n return;\r\n }\r\n if (!$.isArray(sources)) {\r\n sources = [sources];\r\n }\r\n\r\n if (arguments.length < 5 && typeof arguments[arguments.length - 1] === 'function') {\r\n callback = arguments[arguments.length - 1];\r\n }\r\n\r\n startAt = (typeof startAt === 'function' || !startAt) ? 0 : startAt;\r\n count = (typeof count === 'function' || !count || count < 0) ? sources.length : Math.min(count, sources.length);\r\n batchSize = (typeof batchSize === 'function' || !batchSize) ? 1 : batchSize;\r\n\r\n if (startAt >= sources.length) {\r\n startAt = 0;\r\n count = 0;\r\n }\r\n if (batchSize < 0) {\r\n batchSize = count;\r\n }\r\n batchSize = Math.min(batchSize, count);\r\n\r\n var next = sources.slice(startAt + batchSize, count - batchSize);\r\n sources = sources.slice(startAt, batchSize);\r\n count = sources.length;\r\n\r\n // If sources array is empty\r\n if (!count) {\r\n exec(sources, callback, true);\r\n return;\r\n }\r\n\r\n // Image loading callback\r\n var countLoaded = 0;\r\n\r\n var loaded = function () {\r\n countLoaded++;\r\n if (countLoaded !== count) {\r\n return;\r\n }\r\n\r\n exec(sources, callback, !next);\r\n preload(next, 0, 0, batchSize, callback);\r\n };\r\n\r\n // Loop sources to preload\r\n var image;\r\n\r\n for (var i = 0; i < sources.length; i++) {\r\n\r\n if (isVideoSource(sources[i])) {\r\n\r\n // Do not preload videos. There are issues with that.\r\n // First - we need to keep an instance of the preloaded and use that exactly, not a copy.\r\n // Second - there are memory issues.\r\n // If there will be a requirement from users - I'll try to implement this.\r\n\r\n continue;\r\n\r\n }\r\n else {\r\n\r\n image = new Image();\r\n image.src = sources[i].url;\r\n\r\n image = caching(image);\r\n\r\n if (image.complete) {\r\n loaded();\r\n }\r\n else {\r\n $(image).on('load error', loaded);\r\n }\r\n\r\n }\r\n\r\n }\r\n };\r\n })();\r\n\r\n /* Process images array */\r\n var processImagesArray = function (images) {\r\n var processed = [];\r\n for (var i = 0; i < images.length; i++) {\r\n if (typeof images[i] === 'string') {\r\n processed.push({url: images[i]});\r\n }\r\n else if ($.isArray(images[i])) {\r\n processed.push(processImagesArray(images[i]));\r\n }\r\n else {\r\n processed.push(processOptions(images[i]));\r\n }\r\n }\r\n return processed;\r\n };\r\n\r\n /* Process options */\r\n var processOptions = function (options, required) {\r\n\r\n // Convert old options\r\n\r\n // centeredX/centeredY are deprecated\r\n if (options.centeredX || options.centeredY) {\r\n if (window.console && window.console.log) {\r\n window.console.log('jquery.backstretch: `centeredX`/`centeredY` is deprecated, please use `alignX`/`alignY`');\r\n }\r\n if (options.centeredX) {\r\n options.alignX = 0.5;\r\n }\r\n if (options.centeredY) {\r\n options.alignY = 0.5;\r\n }\r\n }\r\n\r\n // Deprecated spec\r\n if (options.speed !== undefined) {\r\n\r\n if (window.console && window.console.log) {\r\n window.console.log('jquery.backstretch: `speed` is deprecated, please use `transitionDuration`');\r\n }\r\n\r\n options.transitionDuration = options.speed;\r\n options.transition = 'fade';\r\n }\r\n\r\n // Typo\r\n if (options.resolutionChangeRatioTreshold !== undefined) {\r\n window.console.log('jquery.backstretch: `treshold` is a typo!');\r\n options.resolutionChangeRatioThreshold = options.resolutionChangeRatioTreshold;\r\n }\r\n\r\n // Current spec that needs processing\r\n\r\n if (options.fadeFirst !== undefined) {\r\n options.animateFirst = options.fadeFirst;\r\n }\r\n\r\n if (options.fade !== undefined) {\r\n options.transitionDuration = options.fade;\r\n options.transition = 'fade';\r\n }\r\n\r\n if (options.scale) {\r\n options.scale = validScale(options.scale);\r\n }\r\n\r\n return processAlignOptions(options);\r\n };\r\n\r\n /* Process align options */\r\n var processAlignOptions = function (options, required) {\r\n if (options.alignX === 'left') {\r\n options.alignX = 0.0;\r\n }\r\n else if (options.alignX === 'center') {\r\n options.alignX = 0.5;\r\n }\r\n else if (options.alignX === 'right') {\r\n options.alignX = 1.0;\r\n }\r\n else {\r\n if (options.alignX !== undefined || required) {\r\n options.alignX = parseFloat(options.alignX);\r\n if (isNaN(options.alignX)) {\r\n options.alignX = 0.5;\r\n }\r\n }\r\n }\r\n\r\n if (options.alignY === 'top') {\r\n options.alignY = 0.0;\r\n }\r\n else if (options.alignY === 'center') {\r\n options.alignY = 0.5;\r\n }\r\n else if (options.alignY === 'bottom') {\r\n options.alignY = 1.0;\r\n }\r\n else {\r\n if (options.alignX !== undefined || required) {\r\n options.alignY = parseFloat(options.alignY);\r\n if (isNaN(options.alignY)) {\r\n options.alignY = 0.5;\r\n }\r\n }\r\n }\r\n\r\n return options;\r\n };\r\n\r\n var SUPPORTED_SCALE_OPTIONS = {\r\n 'cover': 'cover',\r\n 'fit': 'fit',\r\n 'fit-smaller': 'fit-smaller',\r\n 'fill': 'fill'\r\n };\r\n\r\n function validScale(scale) {\r\n if (!SUPPORTED_SCALE_OPTIONS.hasOwnProperty(scale)) {\r\n return 'cover';\r\n }\r\n return scale;\r\n }\r\n\r\n /* CLASS DEFINITION\r\n * ========================= */\r\n var Backstretch = function (container, images, options) {\r\n this.options = $.extend({}, $.fn.backstretch.defaults, options || {});\r\n\r\n this.firstShow = true;\r\n\r\n // Process options\r\n processOptions(this.options, true);\r\n\r\n /* In its simplest form, we allow Backstretch to be called on an image path.\r\n * e.g. $.backstretch('/path/to/image.jpg')\r\n * So, we need to turn this back into an array.\r\n */\r\n this.images = processImagesArray($.isArray(images) ? images : [images]);\r\n\r\n /**\r\n * Paused-Option\r\n */\r\n if (this.options.paused) {\r\n this.paused = true;\r\n }\r\n\r\n /**\r\n * Start-Option (Index)\r\n */\r\n if (this.options.start >= this.images.length) {\r\n this.options.start = this.images.length - 1;\r\n }\r\n if (this.options.start < 0) {\r\n this.options.start = 0;\r\n }\r\n\r\n // Convenience reference to know if the container is body.\r\n this.isBody = container === document.body;\r\n\r\n /* We're keeping track of a few different elements\r\n *\r\n * Container: the element that Backstretch was called on.\r\n * Wrap: a DIV that we place the image into, so we can hide the overflow.\r\n * Root: Convenience reference to help calculate the correct height.\r\n */\r\n var $window = $(window);\r\n this.$container = $(container);\r\n this.$root = this.isBody ? supportsFixedPosition ? $window : $(document) : this.$container;\r\n\r\n this.originalImages = this.images;\r\n this.images = optimalSizeImages(\r\n this.options.alwaysTestWindowResolution ? $window : this.$root,\r\n this.originalImages);\r\n\r\n /**\r\n * Pre-Loading.\r\n * This is the first image, so we will preload a minimum of 1 images.\r\n */\r\n preload(this.images, this.options.start || 0, this.options.preload || 1);\r\n\r\n // Don't create a new wrap if one already exists (from a previous instance of Backstretch)\r\n var $existing = this.$container.children(\".backstretch\").first();\r\n this.$wrap = $existing.length ? $existing :\r\n $('')\r\n .append(that.$item);\r\n\r\n if (this.options.bypassCss) {\r\n that.$itemWrapper.css({\r\n 'display': 'none'\r\n });\r\n }\r\n else {\r\n that.$itemWrapper.css(styles.itemWrapper);\r\n that.$item.css(styles.item);\r\n }\r\n\r\n that.$item.bind(isVideo ? 'canplay' : 'load', function (e) {\r\n var $this = $(this)\r\n , $wrapper = $this.parent()\r\n , options = $wrapper.data('options');\r\n\r\n if (overrideOptions) {\r\n options = $.extend({}, options, overrideOptions);\r\n }\r\n\r\n var imgWidth = this.naturalWidth || this.videoWidth || this.width\r\n , imgHeight = this.naturalHeight || this.videoHeight || this.height;\r\n\r\n // Save the natural dimensions\r\n $wrapper\r\n .data('width', imgWidth)\r\n .data('height', imgHeight);\r\n\r\n var getOption = function (opt) {\r\n return options[opt] !== undefined ?\r\n options[opt] :\r\n that.options[opt];\r\n };\r\n\r\n var transition = getOption('transition');\r\n var transitionEasing = getOption('transitionEasing');\r\n var transitionDuration = getOption('transitionDuration');\r\n\r\n // Show the image, then delete the old one\r\n var bringInNextImage = function () {\r\n\r\n if (oldVideoWrapper) {\r\n oldVideoWrapper.stop();\r\n oldVideoWrapper.destroy();\r\n }\r\n\r\n $oldItemWrapper.remove();\r\n\r\n // Resume the slideshow\r\n if (!that.paused && that.images.length > 1) {\r\n that.cycle();\r\n }\r\n\r\n // Now we can clear the background on the element, to spare memory\r\n if (!that.options.bypassCss && !that.isBody) {\r\n that.$container.css('background-image', 'none');\r\n }\r\n\r\n // Trigger the \"after\" and \"show\" events\r\n // \"show\" is being deprecated\r\n $(['after', 'show']).each(function () {\r\n that.$container.trigger($.Event('backstretch.' + this, evtOptions), [that, newIndex]);\r\n });\r\n\r\n if (isVideo) {\r\n that.videoWrapper.play();\r\n }\r\n };\r\n\r\n if ((that.firstShow && !that.options.animateFirst) || !transitionDuration || !transition) {\r\n // Avoid transition on first show or if there's no transitionDuration value\r\n $wrapper.show();\r\n bringInNextImage();\r\n }\r\n else {\r\n\r\n performTransition({\r\n 'new': $wrapper,\r\n old: $oldItemWrapper,\r\n transition: transition,\r\n duration: transitionDuration,\r\n easing: transitionEasing,\r\n complete: bringInNextImage\r\n });\r\n\r\n }\r\n\r\n that.firstShow = false;\r\n\r\n // Resize\r\n that.resize();\r\n });\r\n\r\n that.$itemWrapper.appendTo(that.$wrap);\r\n\r\n that.$item.attr('alt', selectedImage.alt || '');\r\n that.$itemWrapper.data('options', selectedImage);\r\n\r\n if (!isVideo) {\r\n that.$item.attr('src', selectedImage.url);\r\n }\r\n\r\n that._currentImage = selectedImage;\r\n\r\n return that;\r\n }\r\n\r\n , current: function () {\r\n return this.index;\r\n }\r\n\r\n , next: function () {\r\n var args = Array.prototype.slice.call(arguments, 0);\r\n args.unshift(this.index < this.images.length - 1 ? this.index + 1 : 0);\r\n return this.show.apply(this, args);\r\n }\r\n\r\n , prev: function () {\r\n var args = Array.prototype.slice.call(arguments, 0);\r\n args.unshift(this.index === 0 ? this.images.length - 1 : this.index - 1);\r\n return this.show.apply(this, args);\r\n }\r\n\r\n , pause: function () {\r\n // Pause the slideshow\r\n this.paused = true;\r\n\r\n if (this.videoWrapper) {\r\n this.videoWrapper.pause();\r\n }\r\n\r\n return this;\r\n }\r\n\r\n , resume: function () {\r\n // Resume the slideshow\r\n this.paused = false;\r\n\r\n if (this.videoWrapper) {\r\n this.videoWrapper.play();\r\n }\r\n\r\n this.cycle();\r\n return this;\r\n }\r\n\r\n , cycle: function () {\r\n // Start/resume the slideshow\r\n if (this.images.length > 1) {\r\n // Clear the timeout, just in case\r\n clearTimeout(this._cycleTimeout);\r\n\r\n var duration = (this._currentImage && this._currentImage.duration) || this.options.duration;\r\n var isVideo = isVideoSource(this._currentImage);\r\n\r\n var callNext = function () {\r\n this.$item.off('.cycle');\r\n\r\n // Check for paused slideshow\r\n if (!this.paused) {\r\n this.next();\r\n }\r\n };\r\n\r\n // Special video handling\r\n if (isVideo) {\r\n\r\n // Leave video at last frame\r\n if (!this._currentImage.loop) {\r\n var lastFrameTimeout = 0;\r\n\r\n this.$item\r\n .on('playing.cycle', function () {\r\n var player = $(this).data('player');\r\n\r\n clearTimeout(lastFrameTimeout);\r\n lastFrameTimeout = setTimeout(function () {\r\n player.pause();\r\n player.$video.trigger('ended');\r\n }, (player.getDuration() - player.getCurrentTime()) * 1000);\r\n })\r\n .on('ended.cycle', function () {\r\n clearTimeout(lastFrameTimeout);\r\n });\r\n }\r\n\r\n // On error go to next\r\n this.$item.on('error.cycle initerror.cycle', $.proxy(callNext, this));\r\n }\r\n\r\n if (isVideo && !this._currentImage.duration) {\r\n // It's a video - playing until end\r\n this.$item.on('ended.cycle', $.proxy(callNext, this));\r\n\r\n }\r\n else {\r\n // Cycling according to specified duration\r\n this._cycleTimeout = setTimeout($.proxy(callNext, this), duration);\r\n }\r\n\r\n }\r\n return this;\r\n }\r\n\r\n , destroy: function (preserveBackground) {\r\n // Stop the resize events\r\n $(window).off('resize.backstretch orientationchange.backstretch');\r\n\r\n // Stop any videos\r\n if (this.videoWrapper) {\r\n this.videoWrapper.destroy();\r\n }\r\n\r\n // Clear the timeout\r\n clearTimeout(this._cycleTimeout);\r\n\r\n // Remove Backstretch\r\n if (!preserveBackground) {\r\n this.$wrap.remove();\r\n }\r\n this.$container.removeData('backstretch');\r\n }\r\n };\r\n\r\n /**\r\n * Video Abstraction Layer\r\n *\r\n * Static methods:\r\n * > VideoWrapper.loadYoutubeAPI() -> Call in order to load the Youtube API.\r\n * An 'youtube_api_load' event will be triggered on $(window) when the API is loaded.\r\n *\r\n * Generic:\r\n * > player.type -> type of the video\r\n * > player.video / player.$video -> contains the element holding the video\r\n * > player.play() -> plays the video\r\n * > player.pause() -> pauses the video\r\n * > player.setCurrentTime(position) -> seeks to a position by seconds\r\n *\r\n * Youtube:\r\n * > player.ytId will contain the youtube ID if the source is a youtube url\r\n * > player.ytReady is a flag telling whether the youtube source is ready for playback\r\n * */\r\n\r\n var VideoWrapper = function () { this.init.apply(this, arguments); };\r\n\r\n /**\r\n * @param {Object} options\r\n * @param {String|Array
|Array<{{src: String, type: String?}}>} options.url\r\n * @param {Boolean} options.loop=false\r\n * @param {Boolean?} options.mute=true\r\n * @param {String?} options.poster\r\n * loop, mute, poster\r\n */\r\n VideoWrapper.prototype.init = function (options) {\r\n\r\n var that = this;\r\n\r\n var $video;\r\n\r\n var setVideoElement = function () {\r\n that.$video = $video;\r\n that.video = $video[0];\r\n };\r\n\r\n // Determine video type\r\n\r\n var videoType = 'video';\r\n\r\n if (!(options.url instanceof Array) &&\r\n YOUTUBE_REGEXP.test(options.url)) {\r\n videoType = 'youtube';\r\n }\r\n\r\n that.type = videoType;\r\n\r\n if (videoType === 'youtube') {\r\n\r\n // Try to load the API in the meantime\r\n VideoWrapper.loadYoutubeAPI();\r\n\r\n that.ytId = options.url.match(YOUTUBE_REGEXP)[2];\r\n var src = 'https://www.youtube.com/embed/' + that.ytId +\r\n '?rel=0&autoplay=0&showinfo=0&controls=0&modestbranding=1' +\r\n '&cc_load_policy=0&disablekb=1&iv_load_policy=3&loop=0' +\r\n '&enablejsapi=1&origin=' + encodeURIComponent(window.location.origin);\r\n\r\n that.__ytStartMuted = !!options.mute || options.mute === undefined;\r\n\r\n $video = $('')\r\n .attr({'src_to_load': src})\r\n .css({'border': 0, 'margin': 0, 'padding': 0})\r\n .data('player', that);\r\n\r\n if (options.loop) {\r\n $video.on('ended.loop', function () {\r\n if (!that.__manuallyStopped) {\r\n that.play();\r\n }\r\n });\r\n }\r\n\r\n that.ytReady = false;\r\n\r\n setVideoElement();\r\n\r\n if (window['YT'] && window['YT'].loaded) {\r\n that._initYoutube();\r\n $video.trigger('initsuccess');\r\n }\r\n else {\r\n $(window).one('youtube_api_load', function () {\r\n that._initYoutube();\r\n $video.trigger('initsuccess');\r\n });\r\n }\r\n\r\n }\r\n else {\r\n // Traditional