WIP integrating youtube video:

- fix ontimeupdate event
- fix currentTime for youtube type
- fix not working play_video
- fix video not getting a fullwidth
This commit is contained in:
Hadi Nategh 2021-02-16 18:00:33 +01:00
parent 81b4737710
commit 1501df227a
2 changed files with 197 additions and 32 deletions

View File

@ -71,10 +71,14 @@ var et2_video = /** @class */ (function (_super) {
*/ */
_this._previousTime = 0; _this._previousTime = 0;
//Create Video tag //Create Video tag
_this.video = jQuery(document.createElement(_this._isYoutube() ? "div" : "video")); _this.video = jQuery(document.createElement(_this._isYoutube() ? "div" : "video")).addClass('et2_video');
if (_this._isYoutube()) { if (_this._isYoutube()) {
// this div will be replaced by youtube iframe api when youtube gets ready
_this.youtubeFrame = jQuery(document.createElement('div'))
.appendTo(_this.video)
.attr('id', et2_video.youtubePrefixId + _this.id);
_this.video.attr('id', _this.id); _this.video.attr('id', _this.id);
// 2. This code loads the IFrame Player API code asynchronously. //Load youtube iframe api
var tag = document.createElement('script'); var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api"; tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0]; var firstScriptTag = document.getElementsByTagName('script')[0];
@ -115,13 +119,26 @@ var et2_video = /** @class */ (function (_super) {
} }
else if (_value) { else if (_value) {
//initiate youtube Api object, it gets called automatically by iframe_api script from the api //initiate youtube Api object, it gets called automatically by iframe_api script from the api
// @ts-ignore
window.onYouTubeIframeAPIReady = function () { window.onYouTubeIframeAPIReady = function () {
self.youtube = new YT.Player(self.id, { // @ts-ignore
height: '100%', self.youtube = new YT.Player(et2_video.youtubePrefixId + self.id, {
width: 'auto', height: '400',
videoId: '', width: '100%',
playerVars: {
'autoplay': 0,
'controls': 0,
'modestbranding': 1,
'fs': 0,
'disablekb': 1,
'rel': 0,
'iv_load_policy': 0,
'cc_load_policy': 0
},
videoId: _value.split('v=')[1],
events: { events: {
'onReady': jQuery.proxy(self._onReady, self) 'onReady': jQuery.proxy(self._onReady, self),
'onStateChange': jQuery.proxy(self._onStateChangeYoutube, self)
} }
}); });
}; };
@ -169,7 +186,10 @@ var et2_video = /** @class */ (function (_super) {
*/ */
et2_video.prototype.seek_video = function (_vtime) { et2_video.prototype.seek_video = function (_vtime) {
if (this._isYoutube()) { if (this._isYoutube()) {
this.youtube.seekTo(_vtime); if (this.youtube.seekTo) {
this.youtube.seekTo(_vtime, true);
this._currentTime = _vtime;
}
} }
else { else {
this.video[0].currentTime = _vtime; this.video[0].currentTime = _vtime;
@ -179,14 +199,26 @@ var et2_video = /** @class */ (function (_super) {
* Play video * Play video
*/ */
et2_video.prototype.play_video = function () { et2_video.prototype.play_video = function () {
return this._isYoutube() ? this.youtube.playVideo() : this.video[0].play(); if (this._isYoutube()) {
var self_1 = this;
return new Promise(function (resolve) {
if (self_1.youtube.playVideo) {
self_1.youtube.playVideo();
resolve();
}
});
}
return this.video[0].play();
}; };
/** /**
* Pause video * Pause video
*/ */
et2_video.prototype.pause_video = function () { et2_video.prototype.pause_video = function () {
if (this._isYoutube()) { if (this._isYoutube()) {
if (this.youtube.pauseVideo) {
this.youtube.pauseVideo(); this.youtube.pauseVideo();
this.currentTime(this.youtube.getCurrentTime());
}
} }
else { else {
this.video[0].pause(); this.video[0].pause();
@ -213,8 +245,12 @@ var et2_video = /** @class */ (function (_super) {
else { else {
this.video[0].currentTime = _time; this.video[0].currentTime = _time;
} }
return this._currentTime = _time;
} }
if (this._isYoutube()) { if (this._isYoutube()) {
if (typeof this._currentTime != 'undefined') {
return this._currentTime;
}
return ((_a = this.youtube) === null || _a === void 0 ? void 0 : _a.getCurrentTime) ? this.youtube.getCurrentTime() : 0; return ((_a = this.youtube) === null || _a === void 0 ? void 0 : _a.getCurrentTime) ? this.youtube.getCurrentTime() : 0;
} }
else { else {
@ -271,6 +307,9 @@ var et2_video = /** @class */ (function (_super) {
this.video[0].addEventListener("loadedmetadata", function () { this.video[0].addEventListener("loadedmetadata", function () {
self._onReady(); self._onReady();
}); });
this.video[0].addEventListener("timeupdate", function () {
self._onTimeUpdate();
});
} }
return false; return false;
}; };
@ -280,10 +319,21 @@ var et2_video = /** @class */ (function (_super) {
} }
}; };
et2_video.prototype._onReady = function () { et2_video.prototype._onReady = function () {
// need to set the video dom to transformed iframe
if (this._isYoutube() && this.youtube.getIframe)
this.youtubeFrame = jQuery(this.youtube.getIframe());
var event = document.createEvent("Event"); var event = document.createEvent("Event");
event.initEvent('et2_video.onReady.' + this.id, true, true); event.initEvent('et2_video.onReady.' + this.id, true, true);
this.video[0].dispatchEvent(event); this.video[0].dispatchEvent(event);
}; };
et2_video.prototype._onTimeUpdate = function () {
// update currentTime manually since youtube currentTime might be updated due to the loading
if (this._isYoutube() && this.youtube.getCurrentTime)
this._currentTime = this.youtube.getCurrentTime();
var event = document.createEvent("Event");
event.initEvent('et2_video.onTimeUpdate.' + this.id, true, true);
this.video[0].dispatchEvent(event);
};
/** /**
* check if the video is a youtube type * check if the video is a youtube type
* @return return true if it's a youtube type video * @return return true if it's a youtube type video
@ -292,6 +342,20 @@ var et2_video = /** @class */ (function (_super) {
et2_video.prototype._isYoutube = function () { et2_video.prototype._isYoutube = function () {
return !!this.options.src_type.match('youtube'); return !!this.options.src_type.match('youtube');
}; };
et2_video.prototype._onStateChangeYoutube = function (_data) {
switch (_data.data) {
case et2_video.youtube_player_states.unstarted:
// do not start the video on initiation
this.pause_video();
break;
case et2_video.youtube_player_states.playing:
this._youtubeOntimeUpdateIntrv = window.setInterval(jQuery.proxy(this._onTimeUpdate, this), 100);
break;
default:
window.clearInterval(this._youtubeOntimeUpdateIntrv);
}
console.log(_data);
};
et2_video._attributes = { et2_video._attributes = {
"video_src": { "video_src": {
"name": "Video", "name": "Video",
@ -341,13 +405,18 @@ var et2_video = /** @class */ (function (_super) {
} }
}; };
et2_video.youtube_player_states = { et2_video.youtube_player_states = {
unstarted: 0, unstarted: -1,
ended: 1, ended: 0,
playing: 2, playing: 1,
paused: 3, paused: 2,
buffering: 4, buffering: 3,
video_cued: 5 video_cued: 5
}; };
/**
* prefix id used for addressing youtube player dom
* @private
*/
et2_video.youtubePrefixId = "frame-";
return et2_video; return et2_video;
}(et2_core_baseWidget_1.et2_baseWidget)); }(et2_core_baseWidget_1.et2_baseWidget));
exports.et2_video = et2_video; exports.et2_video = et2_video;

View File

@ -103,11 +103,11 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
youtube: any; youtube: any;
private static youtube_player_states = { private static youtube_player_states = {
unstarted: 0, unstarted: -1,
ended: 1, ended: 0,
playing: 2, playing: 1,
paused: 3, paused: 2,
buffering: 4, buffering: 3,
video_cued: 5 video_cued: 5
}; };
@ -116,22 +116,49 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
* @private * @private
*/ */
private _previousTime: number = 0; private _previousTime: number = 0;
/**
* keeps the currentTime
* @private
*/
private _currentTime : number;
/**
* interval defined for youtube type to simulate ontimeupdate html5 event
* @private
*/
private _youtubeOntimeUpdateIntrv : number;
/**
* youtube iframe api will replace it with iframe
* @protected
*/
protected youtubeFrame : JQuery;
/**
* prefix id used for addressing youtube player dom
* @private
*/
private static youtubePrefixId : string = "frame-";
constructor(_parent, _attrs? : WidgetConfig, _child? : object) constructor(_parent, _attrs? : WidgetConfig, _child? : object)
{ {
super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_video._attributes, _child || {})); super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_video._attributes, _child || {}));
//Create Video tag //Create Video tag
this.video = jQuery(document.createElement(this._isYoutube()?"div":"video")); this.video = jQuery(document.createElement(this._isYoutube()?"div":"video")).addClass('et2_video');
if (this._isYoutube()) if (this._isYoutube())
{ {
// this div will be replaced by youtube iframe api when youtube gets ready
this.youtubeFrame = jQuery(document.createElement('div'))
.appendTo(this.video)
.attr('id', et2_video.youtubePrefixId+this.id);
this.video.attr('id', this.id); this.video.attr('id', this.id);
// 2. This code loads the IFrame Player API code asynchronously.
//Load youtube iframe api
let tag = document.createElement('script'); let tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api"; tag.src = "https://www.youtube.com/iframe_api";
let firstScriptTag = document.getElementsByTagName('script')[0]; let firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
} }
if (!this._isYoutube() && this.options.controls) if (!this._isYoutube() && this.options.controls)
{ {
this.video.attr("controls", 1); this.video.attr("controls", 1);
@ -161,7 +188,7 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
* @param {string} _value url * @param {string} _value url
*/ */
set_src(_value: string) { set_src(_value: string) {
var self = this; let self = this;
if (_value && !this._isYoutube()) if (_value && !this._isYoutube())
{ {
let source = jQuery(document.createElement('source')) let source = jQuery(document.createElement('source'))
@ -176,13 +203,26 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
else if(_value) else if(_value)
{ {
//initiate youtube Api object, it gets called automatically by iframe_api script from the api //initiate youtube Api object, it gets called automatically by iframe_api script from the api
// @ts-ignore
window.onYouTubeIframeAPIReady = function() { window.onYouTubeIframeAPIReady = function() {
self.youtube = new YT.Player( self.id, { // @ts-ignore
height: '100%', self.youtube = new YT.Player( et2_video.youtubePrefixId+self.id, {
width: 'auto', height: '400',
videoId: '', //TODO get youtube video id width: '100%',
playerVars: {
'autoplay': 0,
'controls': 0,
'modestbranding': 1,
'fs':0,
'disablekb': 1,
'rel': 0,
'iv_load_policy': 0,
'cc_load_policy': 0
},
videoId: _value.split('v=')[1], //TODO get youtube video id
events: { events: {
'onReady': jQuery.proxy(self._onReady, self) 'onReady': jQuery.proxy(self._onReady, self),
'onStateChange': jQuery.proxy(self._onStateChangeYoutube, self)
} }
}); });
} }
@ -243,7 +283,11 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
{ {
if (this._isYoutube()) if (this._isYoutube())
{ {
this.youtube.seekTo(_vtime); if (this.youtube.seekTo)
{
this.youtube.seekTo(_vtime, true);
this._currentTime = _vtime;
}
} }
else else
{ {
@ -256,7 +300,18 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
*/ */
public play_video() : Promise<void> public play_video() : Promise<void>
{ {
return this._isYoutube()?this.youtube.playVideo():(<HTMLVideoElement>this.video[0]).play(); if (this._isYoutube())
{
let self = this;
return new Promise<void>(function(resolve){
if (self.youtube.playVideo)
{
self.youtube.playVideo();
resolve();
}
});
}
return (<HTMLVideoElement>this.video[0]).play();
} }
/** /**
@ -265,8 +320,12 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
public pause_video() public pause_video()
{ {
if (this._isYoutube()) if (this._isYoutube())
{
if (this.youtube.pauseVideo)
{ {
this.youtube.pauseVideo(); this.youtube.pauseVideo();
this.currentTime(this.youtube.getCurrentTime());
}
} }
else else
{ {
@ -299,9 +358,14 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
{ {
(<HTMLVideoElement>this.video[0]).currentTime = _time; (<HTMLVideoElement>this.video[0]).currentTime = _time;
} }
return this._currentTime = _time;
} }
if (this._isYoutube()) if (this._isYoutube())
{ {
if (typeof this._currentTime != 'undefined')
{
return this._currentTime;
}
return this.youtube?.getCurrentTime ? this.youtube.getCurrentTime() : 0; return this.youtube?.getCurrentTime ? this.youtube.getCurrentTime() : 0;
} }
else else
@ -372,6 +436,9 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
this.video[0].addEventListener("loadedmetadata", function(){ this.video[0].addEventListener("loadedmetadata", function(){
self._onReady(); self._onReady();
}); });
this.video[0].addEventListener("timeupdate", function(){
self._onTimeUpdate();
});
} }
return false; return false;
} }
@ -386,11 +453,23 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
private _onReady() private _onReady()
{ {
// need to set the video dom to transformed iframe
if (this._isYoutube() && this.youtube.getIframe) this.youtubeFrame = jQuery(this.youtube.getIframe());
let event = document.createEvent("Event"); let event = document.createEvent("Event");
event.initEvent('et2_video.onReady.'+this.id, true, true); event.initEvent('et2_video.onReady.'+this.id, true, true);
this.video[0].dispatchEvent(event); this.video[0].dispatchEvent(event);
} }
private _onTimeUpdate()
{
// update currentTime manually since youtube currentTime might be updated due to the loading
if (this._isYoutube() && this.youtube.getCurrentTime) this._currentTime = this.youtube.getCurrentTime();
let event = document.createEvent("Event");
event.initEvent('et2_video.onTimeUpdate.'+this.id, true, true);
this.video[0].dispatchEvent(event);
}
/** /**
* check if the video is a youtube type * check if the video is a youtube type
* @return return true if it's a youtube type video * @return return true if it's a youtube type video
@ -400,5 +479,22 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode
{ {
return !!this.options.src_type.match('youtube'); return !!this.options.src_type.match('youtube');
} }
private _onStateChangeYoutube(_data)
{
switch (_data.data)
{
case et2_video.youtube_player_states.unstarted:
// do not start the video on initiation
this.pause_video();
break;
case et2_video.youtube_player_states.playing:
this._youtubeOntimeUpdateIntrv = window.setInterval(jQuery.proxy(this._onTimeUpdate, this), 100);
break;
default:
window.clearInterval(this._youtubeOntimeUpdateIntrv);
}
console.log(_data)
}
} }
et2_register_widget(et2_video, ["video"]); et2_register_widget(et2_video, ["video"]);