Skip to content

Instantly share code, notes, and snippets.

@Anubarak
Last active October 11, 2018 20:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Anubarak/30e8de6d6ad8ab0d1a37bc69cc6e8635 to your computer and use it in GitHub Desktop.
Save Anubarak/30e8de6d6ad8ab0d1a37bc69cc6e8635 to your computer and use it in GitHub Desktop.
$('.youtube-player').youtube();
/**
* Youtube Plugin
*/
(function ($, window, document, undefined) {
var pluginName = 'youtube';
var scriptLoaded = false;
var isTouch = 'ontouchstart' in window,
eStart = isTouch ? 'touchstart' : 'mousedown',
eMove = isTouch ? 'touchmove' : 'mousemove',
eEnd = isTouch ? 'touchend' : 'mouseup',
eCancel = isTouch ? 'touchcancel' : 'mouseup';
function Plugin(element, options) {
this.element = element;
this._name = pluginName;
this._defaults = $.fn.youtube.defaults;
this.playing = false;
for (var subName in this._defaults.cssClassSub) {
this._defaults.cssClass[subName] = this._defaults.classPrefix + '-' + this._defaults.cssClassSub[subName];
}
if (typeof this._defaults.youtubePlayerOptions.events === 'undefined') {
this._defaults.youtubePlayerOptions.events = {};
}
this.options = $.extend({}, this._defaults, options);
this.init();
}
$.extend(Plugin.prototype, {
$player: null,
$image: null,
$iFrame: null,
lastAction: null,
playing: null,
$container: null,
currentPlayerState: null,
$progressbar: null,
autoplay: false,
initialized: false,
isAdjusting: false,
playerOptions: {},
init: function () {
this.buildCache();
this.id = this.$element.attr('id');
if (typeof this.id === 'undefined' || this.id === null) {
throw new Error('Youtube Videos must have an ID in order to be selectable by Youtube');
}
// check if there is an image that triggers everything or if it should be
// loaded directly
if (this.$image.length === 0) {
this.initVideo();
} else {
this.$image.on('click' + '.' + this._name, function (event) {
event.preventDefault();
this.autoplay = true;
if (this.initialized === false) {
this.initVideo();
} else {
this.$player.playVideo();
this.toggleView();
}
}.bind(this));
}
},
toggleView: function (force) {
if (this.$image.length !== 0) {
if (typeof force === 'undefined') {
if (this.$player.getPlayerState() === 1) {
this.$iFrameWrap.hide();
this.$controls.hide();
this.$image.show();
} else {
this.$iFrameWrap.show();
this.$controls.show();
this.$image.hide();
}
} else {
if (force === false) {
this.$iFrameWrap.hide();
this.$controls.hide();
this.$image.show();
} else {
this.$iFrameWrap.show();
this.$controls.show();
this.$image.hide();
}
}
}
},
createPlayer: function () {
this.$player = new YT.Player(this.$element.attr('id'), this.playerOptions);
//this.$element.data('player', this.$player);
this.bindEvents();
},
initVideo: function () {
this.initialized = true;
this.playerOptions = this.options.youtubePlayerOptions;
this.videoId = this.$element.data('youtube-id');
if (typeof this.videoId === 'undefined' || this.videoId === null) {
throw new Error('The element must have a Youtube ID');
}
this.playerOptions.videoId = this.videoId;
this.playerOptions.events['onStateChange'] = this.onStateChange.bind(this);
this.playerOptions.events['onReady'] = this.onReady.bind(this);
if (scriptLoaded === false) {
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
Garnish.$bod.on('youtubeReady', function () {
scriptLoaded = true;
this.createPlayer();
}.bind(this));
} else {
this.createPlayer();
}
},
buildCache: function () {
this.$element = $(this.element);
this.$container = this.$element.closest('.videoplayer-container');
this.$iFrameWrap = this.$element.closest('.iframe-wrap');
this.$image = this.$container.find('.videoplayer-play-link');
this.$controls = this.$container.find('.videoplayer');
if (this.$image.length !== 0) {
this.$controls.hide();
} else {
this.$controls.show();
}
this.$playPause = this.$container.find('.videoplayer-playpause');
this.$progressbar = this.$container.find('.videoplayer-bar-loaded');
this.$bar = this.$container.find('.' + this.options.cssClass.bar);
this.$barPlayed = this.$container.find('.' + this.options.cssClass.barPlayed);
this.$barLoaded = this.$container.find('.' + this.options.cssClass.barLoaded);
this.$timeCurrent = this.$container.find('.' + this.options.cssClass.timeCurrent);
this.$timeDuration = this.$container.find('.' + this.options.cssClass.timeDuration);
this.$volumeButton = this.$container.find('.' + this.options.cssClass.volumeButton);
this.$volumeAdjuster = this.$container.find('.' + this.options.cssClass.volumeAdjust + ' > div');
this.$volumeBar = this.$container.find('.' + this.options.cssClass.volumeBar);
},
onReady: function () {
this.$iFrame = $(this.$player.getIframe());
this.$iFrame.data(pluginName, this);
if (this.autoplay === true) {
this.$player.playVideo();
}
this.$volumeBar.width(this.$player.getVolume() + '%');
this.toggleView(true);
this.updateTimerDisplay();
},
onStateChange: function (event) {
switch (event.data) {
case 0: // 0 (beendet)
clearInterval(this.timerInterval);
this.$playPause.removeClass(this.options.cssClass.iconPlay);
this.$playPause.addClass(this.options.cssClass.iconPause);
break;
case 1: // 1 (wird wiedergegeben)
this.startInterval();
this.$playPause.removeClass(this.options.cssClass.iconPlay);
this.$playPause.addClass(this.options.cssClass.iconPause);
break;
case 2: // 2 (pausiert)
clearInterval(this.timerInterval);
this.$playPause.removeClass(this.options.cssClass.iconPause);
this.$playPause.addClass(this.options.cssClass.iconPlay);
if (this.isAdjusting === false) {
this.toggleView(false);
}
break;
case 3: // 3 (wird gepuffert)
clearInterval(this.timerInterval);
this.$playPause.removeClass(this.options.cssClass.iconPlay);
this.$playPause.addClass(this.options.cssClass.iconPause);
break;
case 5: // 5 (Video positioniert)
clearInterval(this.timerInterval);
this.$playPause.removeClass(this.options.cssClass.iconPlay);
this.$playPause.addClass(this.options.cssClass.iconPause);
break;
}
},
bindEvents: function () {
this.$playPause.on('click' + '.' + this._name, function (event) {
event.preventDefault();
var state = this.$player.getPlayerState();
switch (state) {
case 1:
this.$player.pauseVideo();
this.toggleView();
break;
case 2:
this.$player.playVideo();
break;
case 5:
this.$player.playVideo();
break;
}
}.bind(this));
this.$bar.on(eStart + '.' + this._name, function (e) {
this.isAdjusting = true;
this.$player.pauseVideo();
this.adjustCurrentTime(e);
this.$bar.on(eMove + '.' + this._name, function (e) {
this.adjustCurrentTime(e);
}.bind(this));
}.bind(this))
.on(eEnd + '.' + this._name, function () {
this.$bar.unbind(eMove + '.' + this._name);
this.$player.seekTo(this.adjustedTime);
this.updateTimerDisplay(this.adjustedTime);
this.$player.playVideo();
this.isAdjusting = false;
}.bind(this));
this.$volumeAdjuster.on(eStart + '.' + this._name, function (e) {
this.adjustVolume(e);
this.$volumeAdjuster.on(eMove + '.' + this._name, function (e) {
this.adjustVolume(e);
}.bind(this));
}.bind(this))
.on(eEnd + '.' + this._name, function () {
this.$volumeAdjuster.unbind(eMove + '.' + this._name);
this.$player.setVolume(this.adjustedVolume);
}.bind(this));
this.$volumeButton.on('click.' + this._name, function () {
if (typeof this.$player !== 'undefined') {
if (this.$player.isMuted()) {
this.$player.unMute();
this.$container.removeClass(this.options.cssClass.mute);
} else {
this.$container.addClass(this.options.cssClass.mute);
this.$player.mute();
}
}
}.bind(this));
},
startInterval: function () {
clearInterval(this.timerInterval);
this.timerInterval = setInterval(function () {
this.updateTimerDisplay();
}.bind(this), 1000);
},
formatTime: function (time) {
time = Math.round(time);
var minutes = Math.floor(time / 60),
seconds = time - minutes * 60;
seconds = seconds < 10 ? '0' + seconds : seconds;
return minutes + ":" + seconds;
},
adjustVolume: function (e) {
var theRealEvent = isTouch ? e.originalEvent.touches[0] : e;
var volume = Math.abs((theRealEvent.pageX - this.$volumeAdjuster.offset().left) / this.$volumeAdjuster.width());
this.adjustedVolume = volume * 100;
this.$volumeBar.width(this.adjustedVolume + '%');
},
adjustCurrentTime: function (e) {
var theRealEvent = isTouch ? e.originalEvent.touches[0] : e;
var duration = this.$player.getDuration();
this.adjustedTime = Math.round((duration * (theRealEvent.pageX - this.$bar.offset().left)) / this.$bar.width());
this.updateTimerDisplay(this.adjustedTime);
},
updateTimerDisplay: function (time) {
// stop if no current time is given and players are null
if (typeof time === 'undefined' && (this.$player === null ||
typeof this.$player.getPlayerState !== 'function' ||
this.$player.getPlayerState() !== 1)) {
return;
}
var currentTime = typeof time === 'undefined' ? this.$player.getCurrentTime() : time;
var duration = this.$player.getDuration();
var currentTimeFormat = this.formatTime(currentTime);
this.$timeCurrent.text(currentTimeFormat);
this.$timeDuration.text(this.formatTime(this.$player.getDuration()));
this.$barPlayed.width((currentTime / duration) * 100 + '%');
},
playVideo: function () {
var plugin = this;
plugin.$container.addClass(plugin.options.containerPlayingClass);
plugin.$player.playVideo();
},
destroy: function () {
console.log('destroy');
this.unbindEvents();
this.$image.removeData();
this.$player.destroy();
this.$player = null;
this.$container.removeClass('playing');
},
unbindEvents: function () {
this.$image.off('.' + this._name);
}
});
$.fn.youtube = function (options) {
this.each(function () {
var e = $(this);
if (!e.data(pluginName)) {
e.data(pluginName, new Plugin(this, options));
}
});
return this;
};
$.fn.youtube.defaults = {
youtubePlayerOptions: {
height: '315',
width: '560',
playerVars: {
rel: 0,
controls: 0
}
},
classPrefix: 'videoplayer',
cssClass: {
iconPlay: 'icon-play',
iconPause: 'icon-pause'
},
containerPlayingClass: 'playing',
cssClassSub: {
playPause: 'playpause',
playing: 'playing',
time: 'time',
timeCurrent: 'time-current',
timeDuration: 'time-duration',
bar: 'bar',
barLoaded: 'bar-loaded',
barPlayed: 'bar-played',
volume: 'volume',
volumeButton: 'volume-button',
volumeAdjust: 'volume-adjust',
volumeBar: 'volume-bar',
noVolume: 'novolume',
mute: 'mute',
mini: 'mini'
}
}
})(jQuery, window, document);
function onYouTubeIframeAPIReady() {
Garnish.$bod.trigger('youtubeReady');
}
<div class="content-part video media even">
<div class="content size videoplayer-container">
<h2>Test Video</h2>
<figure class="media-wrap">
<a href="" title="Video abspeielen" class="video-wrap shadow videoplayer-play-link">
<span class="icon-play circle"><i class="bg"></i><em>Video abspeielen</em></span>
<img src="some url"/>
</a>
<div class="iframe-wrap" style="display: none">
<div class="youtube-player" data-youtube-id="WrAV5EVI4tU" id="29421423"></div>
</div>
</figure>
<div class="videoplayer">
<div class="" title="">
<a href="#" class="videoplayer-playpause icon-play"></a>
</div>
<div class="videoplayer-time videoplayer-time-current">00:00</div>
<div class="videoplayer-bar">
<div class="videoplayer-bar-loaded" style="width: 100%;"></div>
<div class="videoplayer-bar-played"></div>
</div>
<div class="videoplayer-time videoplayer-time-duration">00:02</div>
<div class="videoplayer-volume">
<div class="videoplayer-volume-button" title="">
<a href="#" class="icon-audio"></a>
</div>
<div class="videoplayer-volume-adjust">
<div>
<div class="videoplayer-volume-bar" style="width: 100%;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment