src/widgets/videojs_plugins/Dailymotion.js
changeset 1076 510fd2a482f4
child 1079 d4f0681c4ff1
equal deleted inserted replaced
1075:92cb33eb7a75 1076:510fd2a482f4
       
     1 // Adapted from https://github.com/lawchihon/videojs-dailymotion
       
     2 /*global define, dailymotion*/
       
     3 import videojs from "video.js";
       
     4 
       
     5 var _isOnMobile = videojs.browser.IS_IOS || videojs.browser.IS_NATIVE_ANDROID;
       
     6 var Tech = videojs.getTech("Tech");
       
     7 
       
     8 
       
     9 class Dailymotion extends Tech {
       
    10   constructor(options, ready) {
       
    11     super(options, ready);
       
    12 
       
    13     this.setSrc(this.options_.source);
       
    14     console.log(this.options_.source)
       
    15 
       
    16     // Set the vjs-dailymotion class to the player
       
    17     // Parent is not set yet so we have to wait a tick
       
    18     setTimeout( () => {
       
    19       if (this.el_) {
       
    20         this.el_.parentNode.className += " vjs-dailymotion";
       
    21 
       
    22         if (_isOnMobile) {
       
    23           this.el_.parentNode.className += " vjs-dailymotion-mobile";
       
    24         }
       
    25 
       
    26         if (Dailymotion.isSdkReady) {
       
    27             this.initDMPlayer();
       
    28         } else {
       
    29           Dailymotion.sdkReadyQueue.push(this);
       
    30         }
       
    31       }
       
    32     });
       
    33   };
       
    34 
       
    35   _getPlayerParams() {
       
    36     var playerParams = {
       
    37       autoplay: false,
       
    38       mute: false,
       
    39       controls: false,
       
    40       "enable-playback-controls": false,
       
    41       "queue-autoplay-next": false,
       
    42       "queue-enable": false,
       
    43     };
       
    44     // Let the user set any Dailymotion parameter
       
    45     // https://developer.dailymotion.com/player/#player-parameters
       
    46     // To use Dailymotion controls, you must use dmControls instead
       
    47 
       
    48     var params = [
       
    49       "api",
       
    50       "autoplay",
       
    51       "autoplay-mute",
       
    52       "id",
       
    53       "mute",
       
    54       "origin",
       
    55       "quality",
       
    56       "queue-autoplay-next",
       
    57       "queue-enable",
       
    58       "sharing-enable",
       
    59       "start",
       
    60       "subtitles-default",
       
    61       "syndication",
       
    62       "ui-highlight",
       
    63       "ui-logo",
       
    64       "ui-start-screen-info",
       
    65       "ui-theme",
       
    66       "apimode",
       
    67       "playlist",
       
    68     ];
       
    69     var options = this.options_;
       
    70     params.forEach(function (param) {
       
    71       if (typeof options[param] === "undefined") {
       
    72         return;
       
    73       }
       
    74       playerParams[param] = options[param];
       
    75     });
       
    76 
       
    77     if (typeof this.options_.dmControls !== "undefined") {
       
    78       playerParams.controls = this.options_.dmControls;
       
    79     }
       
    80 
       
    81     // Overwriting playlist if it is included in url
       
    82     if (this.url && typeof this.url.playlist !== "undefined") {
       
    83       playerParams.playlist = this.url.playlist;
       
    84     }
       
    85 
       
    86     // Allow undocumented options to be passed along via customVars
       
    87     if (typeof this.options_.customVars !== "undefined") {
       
    88       var customVars = this.options_.customVars;
       
    89       Object.keys(customVars).forEach(function (key) {
       
    90         playerParams[key] = customVars[key];
       
    91       });
       
    92     }
       
    93 
       
    94     return playerParams;
       
    95   }
       
    96 
       
    97   _getPlayerConfig() {
       
    98     var playerConfig = {
       
    99       width: "100%",
       
   100       height: "100%",
       
   101       params: this._getPlayerParams(),
       
   102     };
       
   103 
       
   104     if (this.url && typeof this.url.video !== "undefined") {
       
   105       playerConfig.video = this.url.video;
       
   106     } else if (typeof this.options_.video !== "undefined") {
       
   107       playerConfig.video = this.options_.video;
       
   108     }
       
   109 
       
   110     return playerConfig;
       
   111   }
       
   112 
       
   113   async initDMPlayer() {
       
   114     console.log("INIT DM Player", this._getPlayerConfig());
       
   115     if (this.dmPlayer) {
       
   116       return;
       
   117     }
       
   118     const eventMapping = {
       
   119       [dailymotion.events.VIDEO_DURATIONCHANGE]: [ "durationchange" ],
       
   120       [dailymotion.events.PLAYER_END]: [ "ended" ],
       
   121       [dailymotion.events.PLAYER_ERROR]: [ "error" ],
       
   122       [dailymotion.events.PLAYER_VIDEOCHANGE]: [ "loadeddata", "loadedmetadata"],
       
   123       [dailymotion.events.VIDEO_PAUSE]: [ "pause" ],
       
   124       //[dailymotion.events.VIDEO_PLAY]: [ "loadstart", "play", "playing", "waiting" ],
       
   125       [dailymotion.events.VIDEO_PLAY]: [ "loadstart", "play", "playing" ],
       
   126       [dailymotion.events.VIDEO_PLAYING]: [ "playing" ],
       
   127       [dailymotion.events.VIDEO_TIMECHANGE]: [ "timeupdate" ],
       
   128       [dailymotion.events.PLAYER_VOLUMECHANGE]: [ "volumechange", "mute" ],
       
   129     };    
       
   130     this.dmPlayer = await dailymotion.createPlayer(
       
   131       this.options_.techId,
       
   132       this._getPlayerConfig()
       
   133     );
       
   134     this.dmState = await this.getPlayerState();
       
   135     //var vm = this;
       
   136     this.isApiReady = true;
       
   137     this.dmPlayer.enable_playback_controls = false;
       
   138     console.log("AUTONEXT", this.dmPlayer.enable_playback_controls);
       
   139 
       
   140     for (const ev in eventMapping) {
       
   141       this.dmPlayer.on(ev, (s) => {
       
   142         this.dmState = s;
       
   143         for (const tev of eventMapping[ev]) {
       
   144           this.trigger(tev)
       
   145         }
       
   146       });
       
   147     }
       
   148     this.dmPlayer.on(dailymotion.events.PLAYER_ERROR, (s) => {
       
   149       vm.trigger("error", s.playerError);
       
   150     });
       
   151     this.triggerReady();
       
   152   }
       
   153 
       
   154   autoplay(autoplay) {
       
   155     if (typeof autoplay !== "undefined") {
       
   156       return this.setAutoplay(autoplay);
       
   157     }
       
   158 
       
   159     return this.options_.autoplay;
       
   160   }
       
   161 
       
   162   setAutoplay(val) {
       
   163     return (this.options_.autoplay = val);
       
   164   }
       
   165 
       
   166   buffered() {
       
   167     if (!this.dmPlayer || !this.dmPlayer.bufferedTime) {
       
   168       return videojs.createTimeRange();
       
   169     }
       
   170 
       
   171     return videojs.createTimeRange(0, this.dmPlayer.bufferedTime);
       
   172   }
       
   173 
       
   174   createEl() {
       
   175     var div = document.createElement("div");
       
   176     div.setAttribute("id", this.options_.techId);
       
   177     div.setAttribute(
       
   178       "style",
       
   179       "width:100%;height:100%;top:0;left:0;position:absolute"
       
   180     );
       
   181     div.setAttribute("class", "vjs-tech");
       
   182 
       
   183     var divWrapper = document.createElement("div");
       
   184     divWrapper.appendChild(div);
       
   185 
       
   186     if (!_isOnMobile && !this.options_.dmControls) {
       
   187       // var divBlocker = document.createElement('div');
       
   188       // divBlocker.setAttribute('class', 'vjs-iframe-blocker');
       
   189       // divBlocker.setAttribute('style', 'position:absolute;top:0;left:0;width:100%;height:100%');
       
   190       //
       
   191       // // In case the blocker is still there and we want to pause
       
   192       // divBlocker.onclick = function() {
       
   193       //   this.pause();
       
   194       // }.bind(this);
       
   195       //
       
   196       // divWrapper.appendChild(divBlocker);
       
   197     }
       
   198 
       
   199     return divWrapper;
       
   200   }
       
   201 
       
   202   currentSrc() {
       
   203     return this.source && this.source.src;
       
   204   }
       
   205 
       
   206   currentTime() {
       
   207 
       
   208     return this.dmPlayer && this.dmState && this.dmState.videoTime;
       
   209   }
       
   210 
       
   211   setCurrentTime(seconds) {
       
   212     if (!this.dmPlayer || !this.dmPlayer.seek) {
       
   213       return;
       
   214     }
       
   215 
       
   216     return this.dmPlayer.seek(seconds);
       
   217   }
       
   218 
       
   219   dispose() {
       
   220     if (this.dmPlayer) {
       
   221       //Destroy the Dailymotion Player
       
   222       this.dmPlayer.destroy(this.options_.techId);
       
   223       Tech.prototype.dispose.call(this);
       
   224     } else {
       
   225       //Dailymotion API hasn't finished loading or the player is already disposed
       
   226       var index = Dailymotion.sdkReadyQueue.indexOf(this);
       
   227       if (index !== -1) {
       
   228         Dailymotion.sdkReadyQueue.splice(index, 1);
       
   229       }
       
   230     }
       
   231     this.dmPlayer = undefined;
       
   232 
       
   233     this.el_.parentNode.className = this.el_.parentNode.className
       
   234       .replace(" vjs-dailymotion", "")
       
   235       .replace(" vjs-dailymotion-mobile", "");
       
   236     this.el_.parentNode.removeChild(this.el_);
       
   237 
       
   238     // Needs to be called after the Dailymotion player is destroyed,
       
   239     // otherwise there will be a undefined reference exception
       
   240     Tech.prototype.dispose.call(this);
       
   241   }
       
   242 
       
   243   duration() {
       
   244     return this.dmState ? this.dmState.videoDuration : 0;
       
   245   }
       
   246 
       
   247   setDuration(seconds) {
       
   248   }
       
   249 
       
   250   ended() {
       
   251   }
       
   252 
       
   253   enterFullWindow() {
       
   254     if (!this.dmPlayer || !this.dmPlayer.setFullscreen) {
       
   255       return;
       
   256     }
       
   257     return this.dmPlayer.setFullscreen(true);
       
   258   }
       
   259 
       
   260   error() {
       
   261     return this.dmState && this.dmState.playerError;
       
   262   }
       
   263 
       
   264   exitFullscreen() {
       
   265     if (!this.dmPlayer || !this.dmPlayer.setFullscreen) {
       
   266       return;
       
   267     }
       
   268     return this.dmPlayer.setFullscreen(false);
       
   269   }
       
   270 
       
   271   isFullscreen() {
       
   272     return this.dmState && this.dmState.playerPresentationMode === "fullscreen";
       
   273   }
       
   274 
       
   275   // Not supported by Dailymotion
       
   276   language() {
       
   277   }
       
   278 
       
   279   // Not supported by Dailymotion
       
   280   languages() {
       
   281   }
       
   282 
       
   283   load() {
       
   284     if (!this.dmPlayer || !this.dmPlayer.loadContent) {
       
   285       return;
       
   286     }
       
   287     return this.dmPlayer.loadContent(this._getPlayerConfig());
       
   288   }
       
   289 
       
   290   // Not supported by Dailymotion
       
   291   loop() {
       
   292   }
       
   293 
       
   294   async muted() {
       
   295     
       
   296     if(!this.dmState) {
       
   297       return false;
       
   298     }
       
   299     return this.dmState.playerIsMuted;
       
   300   }
       
   301 
       
   302   async setMuted(mute) {
       
   303     if (typeof mute === "undefined") {
       
   304       const state = await this.getPlayerState();
       
   305       mute = state.playerIsMuted ? false : true;
       
   306     }
       
   307 
       
   308     await this.dmPlayer.setMute(mute);
       
   309   }
       
   310 
       
   311   networkState() {
       
   312   }
       
   313 
       
   314   async pause() {
       
   315     if (!this.dmPlayer || !this.dmPlayer.pause) {
       
   316       return;
       
   317     }
       
   318 
       
   319     return await this.dmPlayer.pause();
       
   320   }
       
   321 
       
   322   paused() {
       
   323     return this.dmState && this.dmState.playerIsPlaying === false;
       
   324   }
       
   325 
       
   326   play() {
       
   327     if (!this.isApiReady || !this.dmPlayer || !this.dmPlayer.play) {
       
   328       return;
       
   329     }
       
   330 
       
   331     return this.dmPlayer.play();
       
   332   }
       
   333 
       
   334   // Playback rate is not support by Dailymotion
       
   335   playbackRate() {
       
   336     return 1;
       
   337   }
       
   338 
       
   339   // Not supported by Dailymotion
       
   340   poster() {
       
   341     return undefined;
       
   342   }
       
   343 
       
   344   // Not supported by Dailymotion
       
   345   preload() {
       
   346     return undefined;
       
   347   }
       
   348 
       
   349   // TODO: Confirm if it can be more detail
       
   350   readyState() {
       
   351     if (!this.dmState || this.dmState.playerError) {
       
   352       return 0; //NETWORK_EMPTY
       
   353     }
       
   354 
       
   355     return 4; //HAVE_ENOUGH_DATA
       
   356   }
       
   357 
       
   358   remainingTime() {
       
   359     return this.dmState && this.dmState.videoDuration - this.dmState.videoTime;
       
   360   }
       
   361 
       
   362   requestFullscreen() {
       
   363     return this.enterFullWindow();
       
   364   }
       
   365 
       
   366   enterFullScreen() {
       
   367     return this.enterFullWindow();
       
   368   }
       
   369 
       
   370   reset() {
       
   371     this.load();
       
   372   }
       
   373 
       
   374   seekable() {
       
   375   }
       
   376 
       
   377   seeking() {
       
   378   }
       
   379 
       
   380   src(source) {
       
   381     if (typeof source !== "undefined") {
       
   382       return this.setSrc(source);
       
   383     }
       
   384 
       
   385     return this.source;
       
   386   }
       
   387 
       
   388   setSrc(source) {
       
   389     if (typeof source === "undefined") {
       
   390       return;
       
   391     }
       
   392 
       
   393     this.source = source;
       
   394     this.url = Dailymotion.parseUrl(source.src || source);
       
   395 
       
   396     // Load the video if sdk is ready
       
   397     if (Dailymotion.isSdkReady) {
       
   398       this.load();
       
   399     }
       
   400     return this.source;
       
   401   }
       
   402 
       
   403   supportsFullScreen() {
       
   404     return true;
       
   405   }
       
   406 
       
   407   async volume() {
       
   408     if(!this.dmPlayer ) {
       
   409       return 1
       
   410     }
       
   411     const state = await this.dmPlayer.getState();
       
   412     return state.playerVolume;
       
   413   }
       
   414 
       
   415   setVolume(percentAsDecimal) {
       
   416     if (!this.dmPlayer || !this.dmPlayer.setMute || !this.dmPlayer.setVolume) {
       
   417       return;
       
   418     }
       
   419 
       
   420     if (percentAsDecimal > 0) {
       
   421       this.dmPlayer.setMute(false);
       
   422     } else {
       
   423       this.dmPlayer.setMute(true);
       
   424     }
       
   425     this.dmPlayer.setVolume(percentAsDecimal);
       
   426   }
       
   427 
       
   428   async getPlayerState() {
       
   429     if (!this.dmPlayer) {
       
   430       return {};
       
   431     }
       
   432     return await this.dmPlayer.getState();
       
   433   }
       
   434 };
       
   435 
       
   436 Dailymotion.isSupported = function () {
       
   437   return true;
       
   438 };
       
   439 
       
   440 Dailymotion.canPlaySource = function (e) {
       
   441   return Dailymotion.canPlayType(e.type);
       
   442 };
       
   443 
       
   444 Dailymotion.canPlayType = function (e) {
       
   445   return e === "video/dailymotion";
       
   446 };
       
   447 
       
   448 Dailymotion.parseUrl = function (url) {
       
   449   var result = {};
       
   450 
       
   451   var regex = /video\/[^?|^\/]*/;
       
   452   var match = url.match(regex);
       
   453 
       
   454   if (match && match[0]) {
       
   455     result.video = match[0].replace("video/", "");
       
   456   }
       
   457 
       
   458   var regPlaylist = /playlist(=|\/)[^&]*/;
       
   459   match = url.match(regPlaylist);
       
   460 
       
   461   if (match && match[0]) {
       
   462     result.playlist = match[0].replace(/playlist(=|\/)/, "");
       
   463   }
       
   464 
       
   465   return result;
       
   466 };
       
   467 
       
   468 async function apiLoaded() {
       
   469     Dailymotion.isSdkReady = true;
       
   470 
       
   471     for (var i = 0; i < Dailymotion.sdkReadyQueue.length; ++i) {
       
   472       await Dailymotion.sdkReadyQueue[i].initDMPlayer();
       
   473     }
       
   474 }
       
   475 
       
   476 function loadScript(src, callback) {
       
   477   var loaded = false;
       
   478   var tag = document.createElement("script");
       
   479   var firstScriptTag = document.getElementsByTagName("script")[0];
       
   480   if (!firstScriptTag) {
       
   481     // when loaded in jest without jsdom setup it doesn't get any element.
       
   482     // In jest it doesn't really make sense to do anything, because no one is watching dailymotion in jest
       
   483     return;
       
   484   }
       
   485   firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
       
   486   tag.onload = function () {
       
   487     if (!loaded) {
       
   488       loaded = true;
       
   489       callback();
       
   490     }
       
   491   };
       
   492   tag.onreadystatechange = function () {
       
   493     if (
       
   494       !loaded &&
       
   495       (this.readyState === "complete" || this.readyState === "loaded")
       
   496     ) {
       
   497       loaded = true;
       
   498       callback();
       
   499     }
       
   500   };
       
   501   tag.src = src;
       
   502 }
       
   503 
       
   504 function injectCss() {
       
   505   var css = // iframe blocker to catch mouse events
       
   506     ".vjs-dailymotion .vjs-iframe-blocker { display: none; }" +
       
   507     ".vjs-dailymotion.vjs-user-inactive .vjs-iframe-blocker { display: block; }" +
       
   508     ".vjs-dailymotion .vjs-poster { background-size: cover; }" +
       
   509     ".vjs-dailymotion-mobile .vjs-big-play-button { display: none; }";
       
   510 
       
   511   var head = document.head || document.getElementsByTagName("head")[0];
       
   512 
       
   513   var style = document.createElement("style");
       
   514   style.setAttribute("type", "text/css");
       
   515 
       
   516   if (style.styleSheet) {
       
   517     style.styleSheet.cssText = css;
       
   518   } else {
       
   519     style.appendChild(document.createTextNode(css));
       
   520   }
       
   521 
       
   522   head.appendChild(style);
       
   523 }
       
   524 
       
   525 Dailymotion.sdkReadyQueue = [];
       
   526 
       
   527 // x10ckq
       
   528 Dailymotion.loadLibrary = function(playerId) {
       
   529 
       
   530   if (typeof document !== "undefined") {
       
   531     loadScript(`https://geo.dailymotion.com/libs/player/${playerId}.js`, () => {
       
   532       if (window.dailymotion === undefined) {
       
   533         window.dailymotion = { 
       
   534           onScriptLoaded: apiLoaded
       
   535         }
       
   536       } else {
       
   537         apiLoaded();
       
   538       }  
       
   539     });
       
   540     injectCss();
       
   541   }  
       
   542 }
       
   543 
       
   544 videojs.registerTech("Dailymotion", Dailymotion);
       
   545 
       
   546 export default Dailymotion;