blueimp-gallery
Version:
blueimp Gallery is a touch-enabled, responsive and customizable image and video gallery, carousel and lightbox, optimized for both mobile and desktop web browsers. It features swipe, mouse and keyboard navigation, transition effects, slideshow functionali
225 lines (206 loc) • 6.21 kB
JavaScript
/*
* blueimp Gallery YouTube Video Factory JS
* https://github.com/blueimp/Gallery
*
* Copyright 2013, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*/
/* global define, YT */
;(function (factory) {
'use strict'
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['./blueimp-helper', './blueimp-gallery-video'], factory)
} else {
// Browser globals:
factory(window.blueimp.helper || window.jQuery, window.blueimp.Gallery)
}
})(function ($, Gallery) {
'use strict'
if (!window.postMessage) {
return Gallery
}
var galleryPrototype = Gallery.prototype
$.extend(galleryPrototype.options, {
// The list object property (or data attribute) with the YouTube video id:
youTubeVideoIdProperty: 'youtube',
// Optional object with parameters passed to the YouTube video player:
// https://developers.google.com/youtube/player_parameters
youTubePlayerVars: {
wmode: 'transparent'
},
// Require a click on the native YouTube player for the initial playback:
youTubeClickToPlay: false
})
var textFactory =
galleryPrototype.textFactory || galleryPrototype.imageFactory
var YouTubePlayer = function (videoId, playerVars, clickToPlay) {
this.videoId = videoId
this.playerVars = playerVars
this.clickToPlay = clickToPlay
this.element = document.createElement('div')
this.listeners = {}
}
$.extend(YouTubePlayer.prototype, {
on: function (type, func) {
this.listeners[type] = func
return this
},
loadAPI: function () {
var that = this
var onYouTubeIframeAPIReady = window.onYouTubeIframeAPIReady
var apiUrl = 'https://www.youtube.com/iframe_api'
var scriptTags = document.getElementsByTagName('script')
var i = scriptTags.length
var scriptTag
window.onYouTubeIframeAPIReady = function () {
if (onYouTubeIframeAPIReady) {
onYouTubeIframeAPIReady.apply(this)
}
if (that.playOnReady) {
that.play()
}
}
while (i) {
i -= 1
if (scriptTags[i].src === apiUrl) {
return
}
}
scriptTag = document.createElement('script')
scriptTag.src = apiUrl
scriptTags[0].parentNode.insertBefore(scriptTag, scriptTags[0])
},
onReady: function () {
this.ready = true
if (this.playOnReady) {
this.play()
}
},
onPlaying: function () {
if (this.playStatus < 2) {
this.listeners.playing()
this.playStatus = 2
}
},
onPause: function () {
this.listeners.pause()
delete this.playStatus
},
onStateChange: function (event) {
window.clearTimeout(this.pauseTimeout)
switch (event.data) {
case YT.PlayerState.PLAYING:
this.hasPlayed = true
this.onPlaying()
break
case YT.PlayerState.UNSTARTED:
case YT.PlayerState.PAUSED:
// YouTube sends an unstarted event if pause is triggered before the
// video has started.
// YouTube sends a pause event when seeking.
// In both cases, we initiate a pause in a timeout that gets cleared
// if followed by another event within the timeout window.
this.pauseTimeout = galleryPrototype.setTimeout.call(
this,
this.onPause,
null,
500
)
break
case YT.PlayerState.ENDED:
this.onPause()
break
}
},
onError: function (event) {
this.listeners.error(event)
},
play: function () {
var that = this
if (!this.playStatus) {
this.listeners.play()
this.playStatus = 1
}
if (this.ready) {
if (
!this.hasPlayed &&
(this.clickToPlay ||
(window.navigator &&
/iP(hone|od|ad)/.test(window.navigator.platform)))
) {
// Manually trigger the playing callback if clickToPlay
// is enabled and to workaround a limitation in iOS,
// which requires synchronous user interaction to start
// the video playback:
this.onPlaying()
} else {
this.player.playVideo()
}
} else {
this.playOnReady = true
if (!(window.YT && YT.Player)) {
this.loadAPI()
} else if (!this.player) {
this.player = new YT.Player(this.element, {
videoId: this.videoId,
playerVars: this.playerVars,
events: {
onReady: function () {
that.onReady()
},
onStateChange: function (event) {
that.onStateChange(event)
},
onError: function (event) {
that.onError(event)
}
}
})
}
}
},
pause: function () {
if (this.ready) {
this.player.pauseVideo()
} else if (this.playStatus) {
delete this.playOnReady
this.listeners.pause()
delete this.playStatus
}
}
})
$.extend(galleryPrototype, {
YouTubePlayer: YouTubePlayer,
textFactory: function (obj, callback) {
var options = this.options
var videoId = this.getItemProperty(obj, options.youTubeVideoIdProperty)
if (videoId) {
if (this.getItemProperty(obj, options.urlProperty) === undefined) {
obj[options.urlProperty] =
'https://www.youtube.com/watch?v=' + videoId
}
if (
this.getItemProperty(obj, options.videoPosterProperty) === undefined
) {
obj[options.videoPosterProperty] =
'https://img.youtube.com/vi/' + videoId + '/maxresdefault.jpg'
}
return this.videoFactory(
obj,
callback,
new YouTubePlayer(
videoId,
options.youTubePlayerVars,
options.youTubeClickToPlay
)
)
}
return textFactory.call(this, obj, callback)
}
})
return Gallery
})