From f5e165a07a2823bfeea5aa3f6bca8acedef8b2b1 Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Mon, 15 Feb 2021 16:58:04 +0100 Subject: [PATCH] WIP integrating youtube video frame api into video widget --- api/js/etemplate/et2_widget_video.js | 114 ++++++++++++++++++---- api/js/etemplate/et2_widget_video.ts | 141 ++++++++++++++++++++++----- 2 files changed, 216 insertions(+), 39 deletions(-) diff --git a/api/js/etemplate/et2_widget_video.js b/api/js/etemplate/et2_widget_video.js index eb0643beb3..c36203845e 100644 --- a/api/js/etemplate/et2_widget_video.js +++ b/api/js/etemplate/et2_widget_video.js @@ -71,11 +71,19 @@ var et2_video = /** @class */ (function (_super) { */ _this._previousTime = 0; //Create Video tag - _this.video = jQuery(document.createElement("video")); - if (_this.options.controls) { + _this.video = jQuery(document.createElement(_this._isYoutube() ? "div" : "video")); + if (_this._isYoutube()) { + _this.video.attr('id', _this.id); + // 2. This code loads the IFrame Player API code asynchronously. + var tag = document.createElement('script'); + tag.src = "https://www.youtube.com/iframe_api"; + var firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + } + if (!_this._isYoutube() && _this.options.controls) { _this.video.attr("controls", 1); } - if (_this.options.autoplay) { + if (!_this._isYoutube() && _this.options.autoplay) { _this.video.attr("autoplay", 1); } if (_this.options.muted) { @@ -96,7 +104,8 @@ var et2_video = /** @class */ (function (_super) { * @param {string} _value url */ et2_video.prototype.set_src = function (_value) { - if (_value) { + var self = this; + if (_value && !this._isYoutube()) { var source = jQuery(document.createElement('source')) .attr('src', _value) .appendTo(this.video); @@ -104,6 +113,19 @@ var et2_video = /** @class */ (function (_super) { source.attr('type', this.options.src_type); } } + else if (_value) { + //initiate youtube Api object, it gets called automatically by iframe_api script from the api + window.onYouTubeIframeAPIReady = function () { + self.youtube = new YT.Player(self.id, { + height: '100%', + width: 'auto', + videoId: '', + events: { + 'onReady': jQuery.proxy(self._onReady, self) + } + }); + }; + } }; /** * Set autoplay option for video @@ -112,7 +134,7 @@ var et2_video = /** @class */ (function (_super) { * @param {string} _value true set the autoplay and false not to set */ et2_video.prototype.set_autoplay = function (_value) { - if (_value) { + if (_value && !this._isYoutube()) { this.video.attr("autoplay", _value); } }; @@ -122,7 +144,7 @@ var et2_video = /** @class */ (function (_super) { * @param {string} _value true set the autoplay and false not to set */ et2_video.prototype.set_controls = function (_value) { - if (_value) { + if (_value && !this._isYoutube()) { this.video.attr("controls", _value); } }; @@ -146,48 +168,80 @@ var et2_video = /** @class */ (function (_super) { * @param _vtime in seconds */ et2_video.prototype.seek_video = function (_vtime) { - this.video[0].currentTime = _vtime; + if (this._isYoutube()) { + this.youtube.seekTo(_vtime); + } + else { + this.video[0].currentTime = _vtime; + } }; /** * Play video */ et2_video.prototype.play_video = function () { - return this.video[0].play(); + return this._isYoutube() ? this.youtube.playVideo() : this.video[0].play(); }; /** * Pause video */ et2_video.prototype.pause_video = function () { - this.video[0].pause(); + if (this._isYoutube()) { + this.youtube.pauseVideo(); + } + else { + this.video[0].pause(); + } }; /** * play video * ***Internal use and should not be overriden in its extended class*** */ et2_video.prototype.play = function () { - return this.video[0].play(); + var _a; + return this._isYoutube() && ((_a = this.youtube) === null || _a === void 0 ? void 0 : _a.playVideo) ? this.youtube.playVideo() : this.video[0].play(); }; /** * Get/set current video time / position in seconds * @return returns currentTime */ et2_video.prototype.currentTime = function (_time) { - if (_time) - this.video[0].currentTime = _time; - return this.video[0].currentTime; + var _a; + if (_time) { + if (this._isYoutube()) { + this.youtube.seekTo(_time); + } + else { + this.video[0].currentTime = _time; + } + } + if (this._isYoutube()) { + return ((_a = this.youtube) === null || _a === void 0 ? void 0 : _a.getCurrentTime) ? this.youtube.getCurrentTime() : 0; + } + else { + return this.video[0].currentTime; + } }; /** * get duration time * @return returns duration time */ et2_video.prototype.duration = function () { - return this.video[0].duration; + var _a; + if (this._isYoutube()) { + return ((_a = this.youtube) === null || _a === void 0 ? void 0 : _a.getDuration) ? this.youtube.getDuration() : 0; + } + else { + return this.video[0].duration; + } }; /** * get pasued * @return returns paused flag */ et2_video.prototype.paused = function () { + if (this._isYoutube()) { + return this.youtube.getPlayerState() == et2_video.youtube_player_states.paused; + } return this.video[0].paused; }; /** @@ -195,6 +249,9 @@ var et2_video = /** @class */ (function (_super) { * @return returns ended flag */ et2_video.prototype.ended = function () { + if (this._isYoutube()) { + return this.youtube.getPlayerState() == et2_video.youtube_player_states.ended; + } return this.video[0].ended; }; /** @@ -210,9 +267,11 @@ var et2_video = /** @class */ (function (_super) { et2_video.prototype.doLoadingFinished = function () { _super.prototype.doLoadingFinished.call(this); var self = this; - this.video[0].addEventListener("loadedmetadata", function () { - self.videoLoadnigIsFinished(); - }); + if (!this._isYoutube()) { + this.video[0].addEventListener("loadedmetadata", function () { + self._onReady(); + }); + } return false; }; et2_video.prototype.videoLoadnigIsFinished = function () { @@ -220,6 +279,19 @@ var et2_video = /** @class */ (function (_super) { this.seek_video(this.options.starttime); } }; + et2_video.prototype._onReady = function () { + var event = document.createEvent("Event"); + event.initEvent('et2_video.onReady.' + this.id, true, true); + this.video[0].dispatchEvent(event); + }; + /** + * check if the video is a youtube type + * @return return true if it's a youtube type video + * @private + */ + et2_video.prototype._isYoutube = function () { + return !!this.options.src_type.match('youtube'); + }; et2_video._attributes = { "video_src": { "name": "Video", @@ -268,6 +340,14 @@ var et2_video = /** @class */ (function (_super) { "description": "Defines if the video should be played repeatedly" } }; + et2_video.youtube_player_states = { + unstarted: 0, + ended: 1, + playing: 2, + paused: 3, + buffering: 4, + video_cued: 5 + }; return et2_video; }(et2_core_baseWidget_1.et2_baseWidget)); exports.et2_video = et2_video; diff --git a/api/js/etemplate/et2_widget_video.ts b/api/js/etemplate/et2_widget_video.ts index 9a2bd89e6c..bd00b6b881 100644 --- a/api/js/etemplate/et2_widget_video.ts +++ b/api/js/etemplate/et2_widget_video.ts @@ -18,7 +18,6 @@ import { et2_baseWidget } from './et2_core_baseWidget' import {ClassWithAttributes} from "./et2_core_inheritance"; -import {et2_DOMWidget} from "./et2_core_DOMWidget"; import {WidgetConfig, et2_register_widget} from "./et2_core_widget"; /** @@ -100,7 +99,17 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode } }; - video: JQuery = null; + video: JQuery = null; + + youtube: any; + private static youtube_player_states = { + unstarted: 0, + ended: 1, + playing: 2, + paused: 3, + buffering: 4, + video_cued: 5 + }; /** * keeps internal state of previousTime video played @@ -113,12 +122,21 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode super(_parent, _attrs, ClassWithAttributes.extendAttributes(et2_video._attributes, _child || {})); //Create Video tag - this.video = jQuery(document.createElement("video")); - if (this.options.controls) + this.video = jQuery(document.createElement(this._isYoutube()?"div":"video")); + if (this._isYoutube()) + { + this.video.attr('id', this.id); + // 2. This code loads the IFrame Player API code asynchronously. + let tag = document.createElement('script'); + tag.src = "https://www.youtube.com/iframe_api"; + let firstScriptTag = document.getElementsByTagName('script')[0]; + firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); + } + if (!this._isYoutube() && this.options.controls) { this.video.attr("controls", 1); } - if (this.options.autoplay) + if (!this._isYoutube() && this.options.autoplay) { this.video.attr("autoplay", 1); } @@ -143,8 +161,8 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode * @param {string} _value url */ set_src(_value: string) { - - if (_value) + var self = this; + if (_value && !this._isYoutube()) { let source = jQuery(document.createElement('source')) .attr('src',_value) @@ -155,6 +173,20 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode source.attr('type', this.options.src_type); } } + else if(_value) + { + //initiate youtube Api object, it gets called automatically by iframe_api script from the api + window.onYouTubeIframeAPIReady = function() { + self.youtube = new YT.Player( self.id, { + height: '100%', + width: 'auto', + videoId: '', //TODO get youtube video id + events: { + 'onReady': jQuery.proxy(self._onReady, self) + } + }); + } + } } /** @@ -165,7 +197,7 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ set_autoplay(_value: string) { - if (_value) + if (_value && !this._isYoutube()) { this.video.attr("autoplay", _value); } @@ -178,7 +210,7 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ set_controls(_value: string) { - if (_value) + if (_value && !this._isYoutube()) { this.video.attr("controls", _value); } @@ -209,7 +241,14 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public seek_video(_vtime : number) { - this.video[0].currentTime = _vtime; + if (this._isYoutube()) + { + this.youtube.seekTo(_vtime); + } + else + { + (this.video[0]).currentTime = _vtime; + } } /** @@ -217,7 +256,7 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public play_video() : Promise { - return this.video[0].play(); + return this._isYoutube()?this.youtube.playVideo():(this.video[0]).play(); } /** @@ -225,7 +264,14 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public pause_video() { - this.video[0].pause(); + if (this._isYoutube()) + { + this.youtube.pauseVideo(); + } + else + { + (this.video[0]).pause(); + } } /** @@ -234,7 +280,7 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public play() : Promise { - return this.video[0].play(); + return this._isYoutube() && this.youtube?.playVideo ?this.youtube.playVideo():(this.video[0]).play(); } /** @@ -243,8 +289,25 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public currentTime(_time?) : number { - if (_time) this.video[0].currentTime = _time; - return this.video[0].currentTime; + if (_time) + { + if (this._isYoutube()) + { + this.youtube.seekTo(_time); + } + else + { + (this.video[0]).currentTime = _time; + } + } + if (this._isYoutube()) + { + return this.youtube?.getCurrentTime ? this.youtube.getCurrentTime() : 0; + } + else + { + return (this.video[0]).currentTime; + } } /** @@ -253,7 +316,14 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public duration() : number { - return this.video[0].duration; + if (this._isYoutube()) + { + return this.youtube?.getDuration ? this.youtube.getDuration() : 0; + } + else + { + return (this.video[0]).duration; + } } /** @@ -262,7 +332,11 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public paused() : boolean { - return this.video[0].paused; + if (this._isYoutube()) + { + return this.youtube.getPlayerState() == et2_video.youtube_player_states.paused; + } + return (this.video[0]).paused; } /** @@ -271,7 +345,11 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode */ public ended() : boolean { - return this.video[0].ended; + if (this._isYoutube()) + { + return this.youtube.getPlayerState() == et2_video.youtube_player_states.ended; + } + return (this.video[0]).ended; } /** @@ -289,10 +367,12 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode { super.doLoadingFinished(); let self = this; - - this.video[0].addEventListener("loadedmetadata", function(){ - self.videoLoadnigIsFinished(); - }); + if (!this._isYoutube()) + { + this.video[0].addEventListener("loadedmetadata", function(){ + self._onReady(); + }); + } return false; } @@ -303,5 +383,22 @@ export class et2_video extends et2_baseWidget implements et2_IDOMNode this.seek_video(this.options.starttime); } } + + private _onReady() + { + let event = document.createEvent("Event"); + event.initEvent('et2_video.onReady.'+this.id, true, true); + this.video[0].dispatchEvent(event); + } + + /** + * check if the video is a youtube type + * @return return true if it's a youtube type video + * @private + */ + private _isYoutube() : boolean + { + return !!this.options.src_type.match('youtube'); + } } et2_register_widget(et2_video, ["video"]); \ No newline at end of file