')\n .append(that.$item);\n\n if (this.options.bypassCss) {\n that.$itemWrapper.css({\n 'display': 'none'\n });\n } else {\n that.$itemWrapper.css(styles.itemWrapper);\n that.$item.css(styles.item);\n }\n\n that.$item.bind(isVideo ? 'canplay' : 'load', function (e) {\n var $this = $(this),\n $wrapper = $this.parent(),\n options = $wrapper.data('options');\n\n if (overrideOptions) {\n options = $.extend({}, options, overrideOptions);\n }\n\n var imgWidth = this.naturalWidth || this.videoWidth || this.width,\n imgHeight = this.naturalHeight || this.videoHeight || this.height;\n\n // Save the natural dimensions\n $wrapper\n .data('width', imgWidth)\n .data('height', imgHeight);\n\n var getOption = function (opt) {\n return options[opt] !== undefined ?\n options[opt] :\n that.options[opt];\n };\n\n var transition = getOption('transition');\n var transitionEasing = getOption('transitionEasing');\n var transitionDuration = getOption('transitionDuration');\n\n // Show the image, then delete the old one\n var bringInNextImage = function () {\n\n if (oldVideoWrapper) {\n oldVideoWrapper.stop();\n oldVideoWrapper.destroy();\n }\n\n $oldItemWrapper.remove();\n\n // Resume the slideshow\n if (!that.paused && that.images.length > 1) {\n that.cycle();\n }\n\n // Now we can clear the background on the element, to spare memory\n if (!that.options.bypassCss && !that.isBody) {\n // jadams, 2017-09-30: leave background unchanged\n //that.$container.css('background-image', 'none');\n }\n\n // Trigger the \"after\" and \"show\" events\n // \"show\" (as an event) is being deprecated (used only internallly)\n $(['after', 'show']).each(function () {\n that.$container.trigger($.Event('backstretch.' + this, evtOptions), [that, newIndex]);\n });\n\n if (isVideo) {\n that.videoWrapper.play();\n }\n };\n\n if ((that.firstShow && !that.options.animateFirst) || !transitionDuration || !transition) {\n // Avoid transition on first show or if there's no transitionDuration value\n $wrapper.show();\n bringInNextImage();\n } else {\n\n performTransition({\n 'new': $wrapper,\n old: $oldItemWrapper,\n transition: transition,\n duration: transitionDuration,\n easing: transitionEasing,\n complete: bringInNextImage\n });\n\n }\n\n that.firstShow = false;\n\n // jadams, 2017-12-07: Added log for testing\n if( j1_environment == 'test' ) {\n var imageWidth = this.naturalWidth || this.videoWidth || this.width;\n var imageHeight = this.naturalHeight || this.videoHeight || this.height;\n\n var logText = 'show: imageHeight x imageWidth: ' + imageHeight + ' x ' + imageWidth;\n logger.info(logText);\n }\n\n // Run resize on the image loaded\n that.resize();\n });\n\n that.$itemWrapper.appendTo(that.$wrap);\n\n that.$item.attr('alt', selectedImage.alt || '');\n that.$itemWrapper.data('options', selectedImage);\n\n if (!isVideo) {\n that.$item.attr('src', selectedImage.url);\n }\n\n that._currentImage = selectedImage;\n\n return that;\n }\n\n ,\n current: function () {\n return this.index;\n }\n\n ,\n next: function () {\n var args = Array.prototype.slice.call(arguments, 0);\n args.unshift(this.index < this.images.length - 1 ? this.index + 1 : 0);\n return this.show.apply(this, args);\n }\n\n ,\n prev: function () {\n var args = Array.prototype.slice.call(arguments, 0);\n args.unshift(this.index === 0 ? this.images.length - 1 : this.index - 1);\n return this.show.apply(this, args);\n }\n\n ,\n pause: function () {\n // Pause the slideshow\n this.paused = true;\n\n if (this.videoWrapper) {\n this.videoWrapper.pause();\n }\n\n return this;\n }\n\n ,\n resume: function () {\n // Resume the slideshow\n this.paused = false;\n\n if (this.videoWrapper) {\n this.videoWrapper.play();\n }\n\n this.cycle();\n return this;\n }\n\n ,\n cycle: function () {\n // Start/resume the slideshow\n if (this.images.length > 1) {\n // Clear the timeout, just in case\n clearTimeout(this._cycleTimeout);\n\n var duration = (this._currentImage && this._currentImage.duration) || this.options.duration;\n var isVideo = isVideoSource(this._currentImage);\n\n var callNext = function () {\n this.$item.off('.cycle');\n\n // Check for paused slideshow\n if (!this.paused) {\n this.next();\n }\n };\n\n // Special video handling\n if (isVideo) {\n\n // Leave video at last frame\n if (!this._currentImage.loop) {\n var lastFrameTimeout = 0;\n\n this.$item\n .on('playing.cycle', function () {\n var player = $(this).data('player');\n\n // jadams, 2017-10-10: Workaround the wrong handling of the\n // HTML5 Audio/Video property .data\n // See https://www.w3schools.com/tags/ref_av_dom.asp for more\n // details for HTML Audio and Video DOM Reference\n\n // ToDo: In general it should work. To be fixed.\n\n clearTimeout(lastFrameTimeout);\n if (typeof player != 'undefined') {\n lastFrameTimeout = setTimeout(function () {\n player.pause();\n player.$video.trigger('ended');\n }, (player.getDuration() - player.getCurrentTime()) * 1000);\n }\n })\n .on('ended.cycle', function () {\n clearTimeout(lastFrameTimeout);\n });\n }\n\n // On error go to next\n this.$item.on('error.cycle initerror.cycle', $.proxy(callNext, this));\n }\n\n if (isVideo && !this._currentImage.duration) {\n // It's a video - playing until end\n this.$item.on('ended.cycle', $.proxy(callNext, this));\n\n } else {\n // Cycling according to specified duration\n this._cycleTimeout = setTimeout($.proxy(callNext, this), duration);\n }\n\n }\n return this;\n }\n\n ,\n destroy: function (preserveBackground) {\n // Stop the resize events\n $(window).off('resize.backstretch orientationchange.backstretch');\n\n // Stop any videos\n if (this.videoWrapper) {\n this.videoWrapper.destroy();\n }\n\n // Clear the timeout\n clearTimeout(this._cycleTimeout);\n\n // Remove Backstretch\n if (!preserveBackground) {\n this.$wrap.remove();\n }\n this.$container.removeData('backstretch');\n }\n };\n\n /**\n * Video Abstraction Layer\n *\n * Static methods:\n * > VideoWrapper.loadYoutubeAPI() -> Call in order to load the Youtube API.\n * An 'youtube_api_load' event will be triggered on $(window) when the API is loaded.\n *\n * Generic:\n * > player.type -> type of the video\n * > player.video / player.$video -> contains the element holding the video\n * > player.play() -> plays the video\n * > player.pause() -> pauses the video\n * > player.setCurrentTime(position) -> seeks to a position by seconds\n *\n * Youtube:\n * > player.ytId will contain the youtube ID if the source is a youtube url\n * > player.ytReady is a flag telling whether the youtube source is ready for playback\n * */\n\n var VideoWrapper = function () {\n this.init.apply(this, arguments);\n };\n\n /**\n * @param {Object} options\n * @param {String|Array
|Array<{{src: String, type: String?}}>} options.url\n * @param {Boolean} options.loop=false\n * @param {Boolean?} options.mute=true\n * @param {String?} options.poster\n * loop, mute, poster\n */\n VideoWrapper.prototype.init = function (options) {\n\n var that = this;\n\n var $video;\n\n var setVideoElement = function () {\n that.$video = $video;\n that.video = $video[0];\n };\n\n // Determine video type\n\n var videoType = 'video';\n\n if (!(options.url instanceof Array) &&\n YOUTUBE_REGEXP.test(options.url)) {\n videoType = 'youtube';\n }\n\n that.type = videoType;\n\n if (videoType === 'youtube') {\n\n // Try to load the API in the meantime\n VideoWrapper.loadYoutubeAPI();\n\n that.ytId = options.url.match(YOUTUBE_REGEXP)[2];\n var src = 'https://www.youtube.com/embed/' + that.ytId +\n '?rel=0&autoplay=0&showinfo=0&controls=0&modestbranding=1' +\n '&cc_load_policy=0&disablekb=1&iv_load_policy=3&loop=0' +\n '&enablejsapi=1&origin=' + encodeURIComponent(window.location.origin);\n\n that.__ytStartMuted = !!options.mute || options.mute === undefined;\n\n $video = $('')\n .attr({\n 'src_to_load': src\n })\n .css({\n 'border': 0,\n 'margin': 0,\n 'padding': 0\n })\n .data('player', that);\n\n if (options.loop) {\n $video.on('ended.loop', function () {\n if (!that.__manuallyStopped) {\n that.play();\n }\n });\n }\n\n that.ytReady = false;\n\n setVideoElement();\n\n if (window['YT']) {\n that._initYoutube();\n $video.trigger('initsuccess');\n } else {\n $(window).one('youtube_api_load', function () {\n that._initYoutube();\n $video.trigger('initsuccess');\n });\n }\n\n } else {\n // Traditional