youtubemanager2
Version:
YouTube player which mimics SoundManager2 Sound object
248 lines (195 loc) • 6.66 kB
text/coffeescript
###
youtubeManager
2013 (c) Andrey Popp <8mayday@gmail.com>
###
class YoutubeSound
extractIdRe = /v=([^&]+)/
constructor: (options) ->
this.options = options
this.buffered = undefined
this.bytesLoaded = undefined
this.bytesTotal = 1
this.isBuffering = undefined
this.connected = undefined
this.duration = undefined
this.durationEstimate = undefined
this.isHTML5 = false
this.loaded = false
this.muted = false
this.paused = false
this.playState = 0
this.position = 0
this.readyState = 0
this.element = document.createElement 'div'
this.element.setAttribute 'id', options.id
this.container = options.container || document.body
this.container.appendChild(this.element)
# we don't want to change original options
this._autoPlay = this.options.autoPlay
this._whileplaying = undefined
this._whileloading = undefined
this._previousState = undefined
this._onLoadFired = false
this._onPositionItems = [];
videoId = options.youtubeVideoId or extractIdRe.exec(options.url)[1]
if not videoId?
throw new Error("cannot extract videoId from URL: #{options.url}")
this.videoId = videoId
this.player = new YT.Player options.id,
height: options.height
width: options.width
videoId: videoId
events:
onError: => this.onError()
onReady: => this.onReady()
onStateChange: => this.onStateChange()
playerVars:
controls: '0'
enablejsapi: '1'
modestbranding: '1'
showinfo: '0'
playerapiid: options.id
onReady: ->
this.duration = this.durationEstimate = this.player.getDuration() * 1000
this.play() if this._autoPlay
this.setPosition this._autoPosition if this._autoPosition
this.setVolume this.options.volume if this.options.volume?
this._startLoadingPoller()
this.readyState = 1
onStateChange: ->
state = this.player.getPlayerState()
if state == -1
this.duration = this.durationEstimate = this.player.getDuration() * 1000
this.playState = 0
if state == YT.PlayerState.PLAYING
this.duration = this.durationEstimate = this.player.getDuration() * 1000
this.playState = 1
this._startPlayingPoller()
this.paused = false
if this._previousState == YT.PlayerState.PAUSED
this.options.onresume.apply(this) if this.options.onresume
else
this.options.onplay.apply(this) if this.options.onplay
else if state == YT.PlayerState.PAUSED
this._stopPlayingPoller()
this.paused = true
this.options.onpause.apply(this) if this.options.onpause
else if state == YT.PlayerState.ENDED
this.paused = false
this.playState = 0
this._stopPlayingPoller()
this.options.onfinish.apply(this) if this.options.onfinish
this._previousState = state
onError: ->
this.readyState = 2
this.loaded = false
this.stop()
this.options.onload.apply(this, [this.loaded]) if this.options.onload
_startPlayingPoller: ->
this._whileplaying = setInterval(
(=> this._updatePosition()),
this.options.pollingInterval or 500)
_stopPlayingPoller: ->
return unless this._whileplaying
clearInterval(this._whileplaying)
this._whileplaying = undefined
_updatePosition: ->
this.position = this.player.getCurrentTime() * 1000
this.options.whileplaying.apply(this) if this.options.whileplaying
for item in this._onPositionItems when !item.fired && this.position >= item.position
item.fired = true
item.method.apply(this, [item.position]) if item.method
_startLoadingPoller: ->
this._whileloading = setInterval(
(=> this._updateLoading()),
this.options.pollingInterval or 500)
_stopLoadingPoller: ->
return unless this._whileloading
clearInterval(this._whileloading)
this._whileloading = undefined
_updateLoading: ->
this.bytesLoaded = this.player.getVideoLoadedFraction()
if this.bytesLoaded > 0
this.readyState = 3
this.loaded = true
this.options.onload.apply(this, [this.loaded]) if this.options.onload && !this._onLoadFired
this._onLoadFired = true;
if this.bytesLoaded == 1
this._stopLoadingPoller()
this.options.whileloading.apply(this) if this.options.whileloading
destruct: ->
this.player.destroy()
this._stopPlayingPoller()
this._stopLoadingPoller()
load: (url) ->
this.videoId = extractIdRe.exec(url)[1]
this.player.cueVideoById(this.videoId)
clearOnPosition: (ms, method) ->
ms = parseInt(ms, 10)
return false if isNaN(ms)
this._onPositionItems.splice(index, 1) for index, value of this._onPositionItems when value.position is ms and value.method is method
onPosition: (ms, method) ->
this._onPositionItems.push
position: parseInt(ms, 10)
method: method
fired: false
mute: ->
this.muted = true
this.player.mute()
pause: ->
if this.player.pauseVideo?
this.player.pauseVideo()
else
this._autoPlay = false
play: ->
if this.player.playVideo?
this.player.playVideo()
else
this._autoPlay = true
resume: ->
this.play()
setPan: ->
setPosition: (ms) ->
if this.player.seekTo then this.player.seekTo(ms / 1000) else this._autoPosition = ms
setVolume: (v) ->
this.player.setVolume(v)
stop: ->
if this.player.stopVideo?
this.player.seekTo(0)
this.player.stopVideo()
this._stopPlayingPoller()
this._stopLoadingPoller()
this.position = 0
else
this._autoPlay = false
toggleMute: ->
if this.player.isMuted()
this.unmute()
else
this.mute()
togglePause: ->
if this.player.getPlayerState() == YT.PlayerState.PLAYING
this.pause()
else
this.play()
unload: ->
unmute: ->
this.muted = false
this.player.unMute()
youtubeManager =
createSound: (options) ->
new YoutubeSound(options)
setup: (options = {}) ->
oldCallback = window.onYouTubeIframeAPIReady if window.onYouTubeIframeAPIReady?
window.onYouTubeIframeAPIReady = ->
options.onready() if options.onready
oldCallback() if oldCallback
this._injectScript()
_injectScript: ->
tag = document.createElement('script')
tag.src = "https://www.youtube.com/player_api"
firstScriptTag = document.getElementsByTagName('script')[0]
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag)
define(youtubeManager) if define?.amd?
module.exports = youtubeManager if module?.exports?
window.youtubeManager = youtubeManager