1(function($, window, document, undefined) { 2 var JW_IOL_Version = "2.4.2"; 3 var cssURL = `https://cdn.iol.pt/js/utils/JW8/assets/style/iol.player.min.css?v${JW_IOL_Version}`; 4 var jwplayerURL = "https://content.jwplatform.com/libraries/giBojDlP.js"; 5 var noPubProducts = [13,14]; 6 7 // Default Options for JW8 8 var defaultPlayerOptions = { 9 /* IOL Variables */ 10 video: undefined, // Array of JSON videos object 11 imageId: undefined, // ID or IDs(array) of the video thumbnail 12 imageUrl: undefined, // URL or URLS(array) of the video thumbnail 13 smartToken: undefined, // SmartTop token or tokens(array) of the videos 14 hasAdvertising: true, // By default has advertising 15 waitForConsent: true, // By default wait for consent 16 pub: undefined, // Advertising Segmentation 17 sharingLink: "", // Sets the sharing link 18 embedPlatform: undefined, // Indicates the type of YOUTUBE|INSTAGRAM|FACEBOOK|INCONTENT VIDEO 19 playerPlatform: "WEB", // Available values WEB|AMP|IA|APP 20 shouldSendEvents: true, // Define if we want to register the events on the Google Analytics 21 pageContentType: "", // Defines the page where the player is contained (VIDEO, ARTICLE, ...) 22 project: "", // Defines the project Name (tvi24, selfie, ...) 23 playOnViewable: false, // Start playing when visible 24 videoRedirect: true, 25 relatedRSS: "", 26 27 /* JWPlayer Variables https://developer.jwplayer.com/jw-player/docs/developer-guide/customization/configuration-reference/#setup */ 28 /*** Media ***/ 29 file: "", //URL to a single video file, audio file, or live stream to play. Can also be c
29onfigured inside of a sources array 30 image: "", //URL to a poster image to display before playback starts. 31 title: "", //The title of your video or audio item 32 description: "", //A description of your video or audio item 33 34 /*** Behavior ***/ 35 mute: false, //Configures if the player should be muted during playback 36 autostart: false, //Whether the player will attempt to begin playback automatically when a page is loaded. Set to 'viewable' to have player autostart if 50% is viewable. 37 nextupoffset: "85%", //Configures when the Next Up card displays during playback. A positive value is an offset from the start of the video. A negative number is an offset from the end of the video 38 repeat: false, //Configures if the player should loop content after a playlist completes 39 abouttext: "", //Custom text to display in the right-click menu 40 aboutlink: "", //Custom URL to link to when clicking the right-click menu 41 playbackRateControls: false, //Whether to display a settings menu to adjust playback speed. If true, the pre-defined options available in the menu are 0.5x, 1x, 1.25x, 1.5x, and 2x. An array can be passed to customize the menu options using playbackRates. Note: This feature is not currently supported in Android with HLS streams. 42 playbackRates: [0.25, 0.75, 1, 1.25], //Custom playback rate options to display in the settings menu. 43 44 /*** Appearance ***/ 45 controls: true, //Whether to display the video controls (control bar and display icons) 46 localization: {}, //Changes text for the player in certain locations 47 aspectratio: "16:9", //Maintains proportions when width is a percentage. Will not be used if the player is a static size. Must be entered in ratio "x:y" format. 48 height: 360, //The desired height of your video player (In pixels). Can be omitted when aspectratio is configured 49 width: "100%", //The desired height of your video player (In pixels or percentage) 50 displaytitle: false, //Configures if the title of a media file should be displayed 51 displaydescription: false, //Configures if the description title of a media file should be displayed 52 stretching: "uniform", //Resize images and video to fit player dimensions. "uniform"/"exactfit"/"fill"/"none" 53 nextUpDisplay: true, //Configures whether the Next Up modal is displayed 54 qualityLabels: {}, //By default, the JW Player will set video quality levels using information from the manifest files. Use this configuration option to apply a custom quality label to a desired bandwidth in kbps, works for HLS and DASH. For example: "qualityLabels":{"2500":"High","1000":"Medium"} 55 56 /*** Rendering and Loading ***/ 57 preload: "auto", //Tells the player if content should be loaded prior to playback. "none"/"metadata"/"auto" 58 flashplayer: "//ssl.p.jwpcdn.com/player/v/8.3.0/jwplayer.flash.swf", //Specifies an alternate directory of jwplayer.flash.swf 59 hlsjsdefault: true, 60 61 /*** Cast ***/ 62 //"cast": {}, //Enable casting from directly within the video. 63 64 /*** Skin ***/ 65 skin: { 66 //Color can be specified as a hex value, RGBA color value, or color name 67 controlbar: { 68 text: "#F2F2F2", //Color can be specified as a hex value, RGBA color value, or color name 69 icons: "rgba(255,255,255,0.8)", //The default, inactive color of all icons in the control bar. This option also controls the color of the play, pause, and replay icons in the inactive and complete states. 70 iconsActive: "#FFFFFF", //The color of hovered or selected icons in the control bar. 71 background: "rgba(54, 55, 56, 0.5)" //The background color of the control bar and the volume slider. The default background is transparent. 72 }, 73 timeslider: { 74 rail: "rgba(0,0,0,0.6)", //The color of the base of the timeslider, known as the rail. 75 progress: "#4f13c6" //The color of the bar in the time slider filled in from the beginning of the video through the current position. 76 }, 77 menus: { 78 text: "rgba(255, 255, 255, 0.8)", //The color of inactive, default text in menus and the Next Up overlay. 79 textActive: "#FFFFFF", //The color of hovered or selected text in menus. 80 background: "rgba(54, 55, 56, 0.7)" //The background color of menus and the Next Up overlay. 81 }, 82 tooltips: { 83 text: "#000000", //The text color of tooltips. 84 background: "rgba(199, 194, 194, 0.94)" //The background color of tooltips. 85 }, 86 87 /* IOL Variables */ 88 playlist: { 89 background: "#222222", //The background color for the playlist wrapper 90 text: "#F2F2F2", //The text color 91 playing: "#E8E8E8", //The color for the "A TOCAR" 92 playingShadow: "#252525", //The shadow for the "A TOCAR" 93 duration: "#E8E8E8", //The text color for the duration
94 durationBackground: "rgba(0,0,0,.6)", //The background color for the duration 95 durationShadow: "#252525", //The shadow for the duration 96 scroll: "#7DB5E9" //The scroll bar color 97 } 98 }, 99 100 /*** Logo ***/ 101 logo: { 102 file: "", //The URL of an external JPG, PNG or GIF image to be used as watermark (e.g. /assets/logo.png). We recommend using 24 bit PNG images with transparency 103 hide: true, //When this option is set to true, the logo will automatically show and hide along with the other player controls 104 link: "", //The URL to visit when the watermark image is clicked. Clicking a logo will have no affect unless this is configured 105 margin: "10", //The distance, in pixels, of the logo from the edges of the display 106 position: "top-right" //This sets the corner in which to display the watermark. 107 }, 108 109 /*** Sharing ***/ 110 sharing: { 111 //This options block controls a settings submenu with social sharing options: copy embed code, copy video link and share video to social networks. 112 sites: ["facebook", "twitter", "googleplus", "email", "interest", "linkedin"] 113 }, 114 115 /*** Google Analytics ***/ 116 ga: {}, //This options block configures the built-in integration with Google Analytics. 117 118 intl: { 119 pt: { 120 nextUp: "A seguir" 121 } 122 }, 123 124 /*** Callbacks for the events ***/ 125 onReady: function() {}, 126 onPlay: function() {}, 127 onFirstPlay: function() {}, 128 onPause: function() {}, 129 onIdle: function() {}, 130 onComplete: function() {}, 131 onError: function(event) {}, 132 onSeek: function(event) {}, 133 onTime: function(event) {}, 134 onPlaylistComplete: function(event) {}, 135 onPlaylistItem: function(event) {}, 136 onAdPlay: function(event) {}, 137 onAdImpression: function(event) {}, 138 onAdComplete: function(event) {}, 139 onAdPause: function(event) {}, 140 onVisualQuality: function(event) {}, 141 onViewable: function(event) {}, 142 onTime: function(event) {} 143 }; 144 145 /** 146 * Adds the function iolplayer to the JQuery prototype 147 * @param {object} playerOptions 148 */ 149 $.fn.iolplayer = function(playerOptions) { 150 //API access 151 if (typeof playerOptions === "string") { 152 var args = arguments; 153 var result; 154 155 this.each(function() { 156 var instance = $.data(this, "iolplayer"); 157 158 // check if a valid instance and if public method exists 159 if (instance instanceof IOLPlayer && typeof instance[playerOptions] === "function") { 160 //Call API Method for the instance, with the args passed to this function call 161 result = instance[playerOptions].apply(instance, Array.prototype.slice.call(args, 1)); 162 } 163 }); 164 165 return result !== undefined ? result : this; 166 } 167 168 //Validates the player options 169 var msg = isAValidPlayer(playerOptions); 170 if (typeof playerOptions === "object" && !msg) { 171 //Workaround for iOS due to NonioBar error 172 var ua = window.navigator.userAgent; 173 var iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i); 174 var webkit = !!ua.match(/WebKit/i); 175 var iOSSafari = iOS && webkit && !ua.match(/CriOS/i); 176 177 if (iOSSafari) { 178 var _this = this; 179 window.setTimeout(function() { 180 $(_this).data("iolplayer", new IOLPlayer(_this, playerOptions)); 181 }, 1000); 182 } else { 183 $(this).data("iolplayer", new IOLPlayer(this, playerOptions)); 184 } 185 } else { 186 if (!playerOptions) { 187 console.log("JW: Player Options are empty."); 188 //this.sendMonitoringErrorEvent("Validating Options", { "message": "JW: Player Options are empty." }); 189 $(this).data("iolplayer-error", "JW: Player Options are empty."); 190 } 191 192 //this.sendMonitoringErrorEvent("Validating Options", { "message": `JW: ${msg}` }); 193 $(this).data("iolplayer-error", "JW: " + msg); 194 } 195 }; 196 197 /** 198 * Valides the player options 199 * Currently validates the video property and sets the mute to true if the autostart option is true 200 * @param {object} playerOptions 201 */ 202 function isAValidPlayer(playerOptions) { 203 if (!playerOptions.video || playerOptions.video.length == 0) { 204 return "No sources available"; 205 } 206 207 if (playerOptions.autostart && playerOptions.autostart === 'true') { 208 playerOptions.mute = true; 209 } 210 211 return; 212 } 213 214 /** 215 * Creates a IOLPlayer object 216 * @param {string} elem 217 * @param {object} playerOptions 218 */ 219 var IOLPlayer = function(elem, playerOptions) { 220 this.iolJWPlayer = {}; 221 $("head").append(`<link rel="stylesheet" type="text/css" href="${cssURL}">`); 222 223 /* Registering the HTML element that contains the player */ 224 this.iolJWPlayer.playerElement = $(elem); 225 226 /* Merging the default player options with the choosen options */ 227 this.iolJWPlayer.options = $.extend(true, {}, defaultPlayerOptions, playerOptions); 228 229 /* Setting default imageUrl */ 230 if (this.iolJWPlayer.options.imageId && !this.iolJWPlayer.options.imageUrl) { 231 var screenWidth = window.innerWidth >= 1024 ? 1300 : window.innerWidth * 2; 232 this.iolJWPlayer.options.imageWidth = Number.isInteger(this.iolJWPlayer.options.width) 233 ? this.iolJWPlayer.options.width 234 : screenWidth; 235 this.iolJWPlayer.options.imageUrl = 236 "https://www.iol.pt/multimedia/oratvi/multimedia/imagem/id/" + 237 this.iolJWPlayer.options.imageId + 238 "/" + 239 this.iolJWPlayer.options.imageWidth; 240 } 241 242 if (["nit", "embed"].includes(this.iolJWPlayer.options.project.toLowerCase())) { 243 this.initIOLPlayer(); 244 return; 245 } 246 247 var u = this.getUser(); 248 249 this.iolJWPlayer.options.hasAdvertising = this.shouldPlayAds(u); 250 251 var _this = this; 252 this.canAccessToMultimedia(function() { 253 _this.validateCookie(u); 254 }); 255 }; 256 257 /** 258 * Defines the IOLPlayer Object 259 */ 260 IOLPlayer.prototype = {
261 validateCookie: function(u) { 262 /* Check if the token cookie exists */ 263 var tk = $.cookie("jwiol"); 264 265 if (tk) { 266 var tk_i = $.cookie("jwiol_i"); 267 268 if (tk_i !== u["i"]) { 269 tk = ""; 270 } 271 } 272 273 if (!tk) { 274 var _this = this; 275 var reqUrl = 276 this.iolJWPlayer.options.project.toLowerCase() === "beachcam" 277 ? `https://services.iol.pt/matrix?userId=${_this.iolJWPlayer.user.uname}` 278 : `https://services.iol.pt/matrix?userId=${_this.iolJWPlayer.user.uname}`; 279 280 $.ajax({ 281 url: reqUrl, 282 async: false, 283 contentType: "text/plain", 284 success: function(data) { 285 _this.iolJWPlayer.playerTK = `?wmsAuthSign=${data}`; 286 var creationDate = new Date(); 287 var expirationDate = new Date(); 288 expirationDate.setTime(expirationDate.getTime() + 20 * 3600 * 1000); 289 /* Create token cookie and creation token cookie*/ 290 $.cookie("jwiol", data, { 291 expires: expirationDate, 292 domain: "iol.pt", 293 path: "/" 294 }); 295 $.cookie("jwiol_i", u["i"], { 296 expires: expirationDate, 297 domain: "iol.pt", 298 path: "/" 299 }); 300 $.cookie("jwiol_c", creationDate, { 301 expires: expirationDate, 302 domain: "iol.pt", 303 path: "/" 304 }); 305 _this.initIOLPlayer(); 306 }, 307 error: function(data) { 308 //_this.sendMonitoringErrorEvent("Matrix Options", { message: data.statusText }); 309 } 310 }); 311 } else { 312 this.iolJWPlayer.playerTK = `?wmsAuthSign=${tk}`; 313 this.initIOLPlayer(); 314 } 315 }, 316 317 canAccessToMultimedia: function(callback) { 318 if (this.iolJWPlayer.options.video[0].liveType.toLowerCase() === "onlive") { 319 callback(); 320 return; 321 } 322 323 if (!this.iolJWPlayer.user) this.getUser(); 324 325 var videoType = this.iolJWPlayer.options.video[0].liveType.toLowerCase() === "vod" ? "vod" : "live"; 326 var user = this.iolJWPlayer.options.user ? this.iolJWPlayer.options.user : this.iolJWPlayer.user.uid; 327 var _this = this; 328 329 $.ajax({ 330 url: `https://services.iol.pt/direitos/rights/${videoType}?id=${this.iolJWPlayer.options.video[0].id}&host=${this.iolJWPlayer.options.project}`, 331 type: "GET", 332 dataType: "json", 333 headers: { 334 userid: user 335 }, 336 error: function(jqXHR, textStatus, errorThrown) { 337 var data = jqXHR.responseJSON; 338 if (data && data.code) { 339 var errorMsg = "Lamentamos mas ocorreu um erro."; 340 var errorImg = "https://cdn.iol.pt/js/utils/JW8/assets/img/error_smile.jpg"; 341 var errorCode = "(000)"; 342 343 switch (data.code) { 344 case "100": 345 errorMsg = 346 "Lamentamos mas não existem direitos de transmissão via internet no país onde se encontra."; 347 errorImg = "https://cdn.iol.pt/js/utils/JW8/assets/img/geoblock.jpg"; 348 errorCode = "(geoblock-100)"; 349 break; 350 351 case "101": 352 errorMsg = 353 "Lamentamos mas não existem direitos de transmissão via internet para este programa"; 354 errorImg = "https://cdn.iol.pt/js/utils/JW8/assets/img/geoblock.jpg"; 355 errorCode = "(geoblock-101)"; 356 break; 357 358 case "200": 359 var errorMssageTviPlayer = `Subscreva o TVI Player Internacional para poder ver este conteúdo. 360 Clique <a href="https://tviplayer.iol.pt/subscricao">aqui</a> para conhecer todas as vantagens. 361 Se já tem uma subscrição, por favor, clique <a href="#/iol/login">aqui</a> para efetuar login.`; 362 363 var errorMssageClubeMca = `Tens que fazer parte do Clube Morangos com Açúcar para poderes ver este conteúdo.
364 <a href="https://tvi.iol.pt/clubemca/subscricao" class="bt-more">Junta-te ao clube!</a> 365 Se já tens uma subscrição, por favor, clica <a href="#/iol/login">aqui</a> para entrares.` 366 errorMsg = _this.iolJWPlayer.options.project === 'clubemca' ? errorMssageClubeMca : errorMssageTviPlayer; 367 errorImg = "https://cdn.iol.pt/js/utils/JW8/assets/img/error.jpg"; 368 errorCode = "(prd-200)"; 369 break; 370 371 case "201": 372 var messageErrorMca201 = `Tens que fazer parte do Clube Morangos com Açúcar para poderes ver este conteúdo. 373 <a href="https://tvi.iol.pt/clubemca/subscricao" class="bt-more">Junta-te ao clube!</a>`; 374 var messageErrorTviplayer201 = `Subscreve o TVI Player Internacional para poder ver este conteúdo. 375 Clique <a href="https://tviplayer.iol.pt/subscricao">aqui</a> para conhecer todas as vantagens.`; 376 errorMsg = errorMsg = _this.iolJWPlayer.options.project === 'clubemca' ? messageErrorMca201 : messageErrorTviplayer201; 377 errorImg = "https://cdn.iol.pt/js/utils/JW8/assets/img/error.jpg"; 378 errorCode = "(prd-201)"; 379 break; 380 381 case "300": 382 errorMsg = "Lamentamos mas o vídeo não está disponível."; 383 errorImg = "https://cdn.iol.pt/js/utils/JW8/assets/img/error_smile.jpg"; 384 errorCode = "(block-300)"; 385 break; 386 } 387 388 var element = `<div id="iolplayer-blocked" style="background: url('${errorImg}') center/cover;"> 389 <div class="iolplayer-blocked-text"> 390 ${errorMsg} <small style="font-size: 10px;">${errorCode}</small> 391 </div> 392 </div>`; 393 _this.iolJWPlayer.playerElement.html(element); 394 } else { 395 callback(); 396 } 397 }, 398 success: function(data) { 399 callback(); 400 } 401 }); 402 }, 403 404 /** 405 * Initializes the Player Container 406 */ 407 initIOLPlayer: function() { 408 if (!this.iolJWPlayer.options.video) { 409 return false; 410 } 411 412 /* Defining is a playlist is being played */ 413 this.iolJWPlayer.isPlaylist = this.iolJWPlayer.options.video.length > 1; 414 415 /* Creates the DIV for the player, based in the current date */ 416 this.iolJWPlayer.playerDivId = "iolplayer_" + Date.now(); 417 this.iolJWPlayer.playlistDivId = "iolplaylist_" + Date.now(); 418 this.iolJWPlayer.playerElement.html( 419 `<div id='${this.iolJWPlayer.playerDivId}' class='iolplayer_instance'></div><div id='${this.iolJWPlayer.playlistDivId}' class='iolplaylist-wrapper' style='display:none;'></div>` 420 ); 421 this.iolJWPlayer.playlistElement = $(`#${this.iolJWPlayer.playlistDivId}`); 422 423 this.showIOLPlayer(this.iolJWPlayer.playerDivId, this.iolJWPlayer.options.showPreroll); 424 }, 425 426 /** 427 * Setups the Player with the Playlist and Advertising 428 */ 429 showIOLPlayer: function() { 430 var related = this.getRelated(); 431 if (related) this.iolJWPlayer.options.related = related; 432 433 var playlist = this.getPlaylist(); 434 if (playlist) this.iolJWPlayer.options.playlist = playlist; 435 436 this.iolJWPlayer.firstPlay = true; 437 this.iolJWPlayer.adPlaying = false; 438 this.iolJWPlayer.tvAdPlaying = false; 439 this.iolJWPlayer.liveMidNum = 0; 440 this.iolJWPlayer.isStoppable = this.isAStoppableVideo(); 441 this.iolJWPlayer.consentString = ""; 442 443 this.iolJWPlayer.playerInstance = jwplayer(this.iolJWPlayer.playerDivId); 444 let development = document.location.host.includes("localhost") || document.location.host.includes("dev.") || document.location.host.includes("stg.") || document.location.host.includes("tst."); 445 446 if (!development) { 447 if(this.iolJWPlayer.waitForConsent) { 448 this.waitForQuantcast(); 449 } else { 450 this.obtainAdvertisingAndSetup(); 451 } 452 } else { 453 console.info("IOLPlayer: DEV MODE"); 454 this.obtainAdvertisingAndSetup(); 455 } 456 }, 457 458 waitForQuantcast() { 459 let count = 0; 460 const consentCheckInterval = setInterval(() => { 461 if (window["__tcfapi"] || count == 60) { 462 try { 463 window["__tcfapi"]("addEventListener", 2, (tcData, success) => { 464 if (success && tcData.tcString) { 465 this.iolJWPlayer.consentString = tcData.tcString; 466 this.obtainAdvertisingAndSetup(); 467 window["__tcfapi"]( 468 "removeEventListener", 469 2, 470 success => { 471 if (success) console.info("IOLPlayer: CMP listener removed"); 472 }, 473 tcData.listenerId 474 ); 475 } 476 }); 477 clearInterval(consentCheckInterval); 478 } catch(error) { 479 console.error(error); 480 clearInterval(consentCheckInterval); 481 console.error("IOLPlayer: CMP not loaded"); 482 this.obtainAdvertisingAndSetup(); 483 } 484 } 485 count++; 486 }, 100); 487 }, 488 489 obtainAdvertisingAndSetup: function() { 490 if(this.iolJWPlayer.options.hasAdvertising) { 491 this.iolJWPlayer.options.advertising = this.getAdvertising(); 492 } 493 494 495 this.iolJWPlayer.playerInstance.setup(this.iolJWPlayer.options); 496 497 this.setIOLPlayerEvents(); 498 }, 499 500 /** 501 * Validades if should stop the video after an ammount of time 502 */ 503 isAStoppableVideo: function() { 504 for (var index = 0; index < this.iolJWPlayer.options.video.length; index++) { 505 if (/beachcam/.test(this.iolJWPlayer.options.video[index].videoUrl)) { 506 this.iolJWPlayer.options.preload = "metadata"; 507 return { 508 name: "beachcam", 509 time: 300000 510 }; 511 } 512 } 513 return; 514 }, 515 516 /** 517 * Add related videos to the player. 518 * When the page content type is VIDEO redirects to video url. 519 */ 520 getRelated: function() { 521 var relatedObject = {}; 522 523 if ( 524 (this.iolJWPlayer.options.project === "tvi" || this.iolJWPlayer.options.project === "nit") && 525 !this.iolJWPlayer.options.relatedRSS 526 ) 527 return; 528 529 if (this.iolJWPlayer.options.relatedRSS) { 530 relatedObject.file = this.iolJWPlayer.options.relatedRSS; 531 relatedObject.onclick = "link"; 532 relatedObject.oncomplete = "none"; 533 return relatedObject; 534 } 535 536 if (this.iolJWPlayer.options.pageContentType === "VIDEO" && this.iolJWPlayer.options.project) { 537 relatedObject.file = `https://front-api.iol.pt/api/v1/recomended?project=${this.iolJWPlayer.options.project.toLowerCase()}&mid=${ 538 this.iolJWPlayer.options.video[0].id 539 }`; 540 //relatedObject.file = `https://www.iol.pt/jwplayer.xml?project=${this.iolJWPlayer.options.project.toLowerCase()}&mid=${ 541 // this.iolJWPlayer.options.video[0].id 542 //}`; 543 relatedObject.onclick = "link"; 544 relatedObject.oncomplete = this.iolJWPlayer.options.videoRedirect ? "none" : "show"; 545 return relatedObject; 546 } 547 548 if ( 549 this.iolJWPlayer.options.pageContentType === "ARTICLE" && 550 !this.iolJWPlayer.isPlaylist && 551 this.iolJWPlayer.options.project 552 ) { 553 relatedObject.file = `https://front-api.iol.pt/api/v1/recomended?project=${this.iolJWPlayer.options.project.toLowerCase()}&mid=${ 554 this.iolJWPlayer.options.video[0].id 555 }`; 556 //relatedObject.file = `https://www.iol.pt/jwplayer.xml?project=${this.iolJWPlayer.options.project.toLowerCase()}&mid=${ 557 // this.iolJWPlayer.options.video[0].id 558 //}`; 559 relatedObject.onclick = "link"; 560 relatedObject.oncomplete = "show"; 561 this.iolJWPlayer.options.nextUpDisplay = false;
562 return relatedObject; 563 } 564 565 return; 566 }, 567 568 /** 569 * Creates a JWPlayer Playlist 570 */ 571 getPlaylist: function() { 572 var playlistObject = {}; 573 574 if (!this.iolJWPlayer.isPlaylist) { 575 this.iolJWPlayer.options.file = 576 this.iolJWPlayer.options.video[0].videoUrl + 577 (["nit", "embed"].includes(this.iolJWPlayer.options.project.toLowerCase()) ? "" : this.iolJWPlayer.playerTK); 578 this.iolJWPlayer.options.image = this.iolJWPlayer.options.imageUrl 579 ? this.iolJWPlayer.options.imageUrl 580 : this.iolJWPlayer.options.video[0].cover; 581 this.iolJWPlayer.options.title = this.iolJWPlayer.options.video[0].title; 582 return; 583 } 584 585 playlistObject.playlist = []; 586 587 for (var index = 0; index < this.iolJWPlayer.options.video.length; index++) { 588 playlistObject.playlist.push({ 589 description: decodeURI(this.iolJWPlayer.options.video[index].description), 590 tags: this.iolJWPlayer.options.video[index].tags, 591 image: this.iolJWPlayer.options.video[index].cover, 592 title: decodeURI(this.iolJWPlayer.options.video[index].title), 593 sources: [ 594 { 595 file: 596 this.iolJWPlayer.options.video[index].videoUrl + 597 (["nit", "embed"].includes(this.iolJWPlayer.options.project.toLowerCase()) === "nit" 598 ? "" 599 : this.iolJWPlayer.playerTK) 600 } 601 ], 602 duration: this.iolJWPlayer.options.video[index].duration 603 }); 604 } 605 return playlistObject; 606 }, 607 608 /** 609 * Sets the Advertising options 610 */ 611 getAdvertising: function() { 612 var advertising = new Object(); 613 var videoIndex = 614 this.iolJWPlayer.playerInstance && this.iolJWPlayer.playerInstance.getPlaylistIndex() 615 ? this.iolJWPlayer.playerInstance.getPlaylistIndex() 616 : 0; 617 618 var videoDuration = this.iolJWPlayer.options.video[videoIndex].duration; 619 var videoDurationRounded = this.roundToQuarter(videoDuration); 620 const adTags = this.iolJWPlayer.options.video[videoIndex].adTags ? encodeURIComponent(this.iolJWPlayer.options.video[videoIndex].adTags) : ""; 621 622 if (this.iolJWPlayer.options.pub) { 623 var url = window.encodeURIComponent(window.location.href); 624 var videoSizes = "720x576"; 625 626 var creativeProfile = "ALLvideos"; 627 var gdpr = this.iolJWPlayer.consentString ? `&gdpr=1&gdpr_consent=${this.iolJWPlayer.consentString}` : ''; 628 629 //Url ads VMAP 2 630 var adUrlNew = `https://pubads.g.doubleclick.net/gampad/ads?&sz=${videoSizes}&iu=${ 631 this.iolJWPlayer.options.pub 632 }&ciu_szs&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&description_url=${url}&url=${url}${gdpr}&plcmt=1&correlator=${Math.floor( 633 Math.random() * 100000 634 ) + 1}&vid_d=${videoDurationRounded}&cust_params=category%3D${adTags}`; 635 636 advertising.client = "googima"; 637 advertising.admessage = "Esta publicidade termina em xx segundos."; 638 advertising.vpaidcontrols = true; 639 //Added for VMAP 640 advertising.schedule = adUrlNew; 641 642 advertising.companiondiv = { 643 id: "MPU1", 644 width: 300, 645 height: 250 646 }; 647 648 return advertising; 649 } 650 651 return; 652 }, 653 654 getLiveMidRoll() { 655 var url = window.encodeURIComponent(window.location.href); 656 var videoSizes = "720x576"; 657 var creativeProfile = "ALLvideos"; 658 var gdpr = this.iolJWPlayer.consentString ? `&gdpr=1&gdpr_consent=${this.iolJWPlayer.consentString}`:''; 659 var midrollUrl = `https://pubads.g.doubleclick.net/gampad/ads?sz=${videoSizes}&iu=${this.iolJWPlayer.options.pub}&ciu_szs&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&plcmt=1&description_url=${url}&url=${url}${gdpr}&vpos=midroll&ad_rule=0`; 660 661 var correlator = Math.floor(Math.random() * 100000) + 1; 662 return `${midrollUrl}&liveMid=true&mridx=${this.iolJWPlayer.liveMidNum++}&correlator=${correlator}`; 663 }, 664 /** 665 * Defines all the events to be caught 666 */ 667 setIOLPlayerEvents: function() { 668 //due to scope 669 var _this = this; 670 671 /**** SETUP EVENTS ****/ 672 this.iolJWPlayer.playerInstance.on("relatedReady", function(event) { 673 _this.iolJWPlayer.relatedPlugin = jwplayer().getPlugin("related"); 674 675 _this.iolJWPlayer.relatedPlugin.on("play", function(event) { 676 var actionName = `recomendados jw ${event.auto ? "auto" : "click"}`; 677 try { 678 IOLAnalytics.setInternalOrigin(actionName, true); //old version 679 } catch (err) { 680 if (window.iol_analytics) { 681 //new version 682 window.iol_analytics.setInternalOrigin(actionName, true); 683 } else { 684 console.log("analytics module not loaded"); 685 } 686 } 687 }); 688 }); 689 690 this.iolJWPlayer.playerInstance.on("ready", function(event) { 691 $(".jw-nextup").on("click", function() { 692 try { 693 IOLAnalytics.setInternalOrigin(`playlist overlay`, false); 694 } catch (err) { 695 if (window.iol_analytics) { 696 //new version 697 window.iol_analytics.setInternalOrigin(`playlist overlay`, false); 698 } else { 699 console.log("analytics module not loaded"); 700 } 701 } 702 }); 703 _this.iolJWPlayer.options.onReady.call(this, event); 704 }); 705 706 this.iolJWPlayer.playerInstance.on("setupError", function(event) { 707 //_this.sendMonitoringErrorEvent("Setup Error", event); 708 }); 709 710 /**** AD EVENTS ****/ 711 this.iolJWPlayer.playerInstance.on("adRequest", function(event) { 712 _this.iolJWPlayer.adPlaying = true; 713 //_this.iolJWPlayer.options.onAdPlay.call(this, event); 714 }); 715 716 this.iolJWPlayer.playerInstance.on("adPlay", function(event) { 717 _this.iolJWPlayer.options.onAdPlay.call(this, event); 718 }); 719 720 this.iolJWPlayer.playerInstance.on("adImpression", function(event) { 721 _this.sendGAEvent("JW Player Ad Impression", "Impression", event.adposition); 722 _this.iolJWPlayer.options.onAdImpression.call(this, event); 723 }); 724 725 this.iolJWPlayer.playerInstance.on("adPause", function(event) { 726 _this.iolJWPlayer.options.onAdPause.call(this, event); 727 }); 728 729 this.iolJWPlayer.playerInstance.on("adComplete", function(event) { 730 _this.iolJWPlayer.adPlaying = false;
731 _this.sendGAEvent("JW Player Ad Complete", "Complete", event.adposition); 732 733 if (event.tag.includes("liveMid=true") && _this.iolJWPlayer.tvAdPlaying && _this.iolJWPlayer.consentString) { 734 if (_this.iolJWPlayer.tvAdPlaying) _this.iolJWPlayer.playerInstance.playAd(_this.getLiveMidRoll()); 735 } 736 _this.iolJWPlayer.options.onAdComplete.call(this, event); 737 }); 738 739 this.iolJWPlayer.playerInstance.on("adClick", function(event) { 740 _this.sendGAEvent("JW Player Ad Click", "Click", event.adposition); 741 _this.iolJWPlayer.options.onAdClick.call(this, event); 742 }); 743 744 this.iolJWPlayer.playerInstance.on("adError", function(event) { 745 _this.iolJWPlayer.adPlaying = false; 746 _this.sendGAEvent("JW Player Ad Error", event.message, event.adposition); 747 _this.iolJWPlayer.options.onAdComplete.call(this, event); 748 }); 749 750 /**** PLAY EVENTS ****/ 751 this.iolJWPlayer.playerInstance.on("buffer", function(event) { 752 //_this.sendMonitoringEvent("Buffer", { bufferState: event }); 753 }); 754 755 //**** TimeStamp Feature ****// 756 if (_this.iolJWPlayer.options.video[0].liveType == "VOD") { 757 let playerTime = _this.iolJWPlayer.playerInstance; 758 playerTime.on("beforePlay", () => { 759 window.addEventListener('contextmenu', (event) => { 760 let btnTime = document.querySelector('.jw-btn-time'); 761 let leftClick = document.querySelector('ul.jw-rightclick-list'); 762 763 //create new right click menu option 764 if(btnTime == null){ 765 let li = document.createElement("li"); 766 li.setAttribute('class', 'jw-reset jw-rightclick-item'); 767 let btnTime = document.createElement('button') 768 btnTime.setAttribute('class', 'jw-reset-text jw-rightclick-link jw-btn-time'); 769 btnTime.textContent = "Copiar link com tempo"; 770 li.appendChild(btnTime); 771 leftClick.appendChild(li); 772 event.stopPropagation(); 773 btnTime.addEventListener('click', (ev) =>{ 774 getTimeLink(leftClick); 775 }); 776 } 777 // get url time param 778 function getTimeLink(leftClick){ 779 let seconds = new URLSearchParams(window.location.search).getAll("t"); 780 let link = window.location.href; 781 if( seconds <= 0 ){ 782 let totalSeconds = playerTime.getPosition(); 783 let convertedTime = secondsConverter(totalSeconds); 784 link = window.location.href + '?t=' + convertedTime; 785 } 786 else{ 787 let totalSeconds = playerTime.getPosition(); 788 let convertedTime = secondsConverter(totalSeconds); 789 link = link.replace(seconds, convertedTime); 790 } 791 try{ 792 navigator.clipboard.writeText(link); 793 } 794 catch(error){ 795 console.error('Error copying link to clipboard:', error); 796 } 797 798 //close right click menu after click 799 let parent = leftClick.parentNode; 800 parent.classList.remove('jw-open'); 801 802 } 803 804 // convert seconds in hours and minutes 805 function secondsConverter(totalSeconds){ 806 const totalMinutes = Math.floor(totalSeconds / 60); 807 const hours = Math.floor(totalMinutes / 60); 808 const minutes = String(totalMinutes % 60).padStart(2, '0'); 809 const seconds = String(Math.floor(totalSeconds % 60)).padStart(2, '0'); 810 const time = `${hours}:${minutes}:${seconds}`; 811 812 return time; 813 } 814 }); 815 816 let urlTime = new URLSearchParams(window.location.search).get("t"); 817 let matches = urlTime ? urlTime.match(/\d+/g) : null; 818 // convert hours and minutes in seconds 819 let hours = parseInt(matches[0]); 820 let minutes = parseInt(matches[1]); 821 let seconds = parseInt(matches[2]); 822 823 let timestamp = hours * 3600 + minutes * 60 + seconds; 824 825 var videoDuration = _this.iolJWPlayer.options.video[0].duration; 826 827 function seekTime(){ 828 if (timestamp > 0 && timestamp < videoDuration) { 829 _this.hasplayer = true; 830 playerTime.seek(timestamp); 831 } 832 } 833 playerTime.on('firstFrame', () => { 834 seekTime(); 835 }); 836 }); 837 }
838 //**** END TimeStamp Feature ****// 839 840 this.iolJWPlayer.playerInstance.on("play", function(event) { 841 var videoIndex = _this.iolJWPlayer.playerInstance ? _this.iolJWPlayer.playerInstance.getPlaylistIndex() : 0; 842 var el = _this.iolJWPlayer.options.embedPlatform ? _this.iolJWPlayer.options.embedPlatform : "Video"; 843 844 if (_this.iolJWPlayer.firstPlay && ["INCONTENT VIDEO", "Video"].includes(el)) { 845 if ( 846 _this.iolJWPlayer.isPlaylist && 847 (event.playReason === "related-interaction" || event.playReason === "playlist") 848 ) { 849 /* 850 event.playReason: 'related-interaction' -> related screen 851 event.playReason: 'playlist' -> autoplay 852 */ 853 var playType = 854 event.playReason === "interaction" 855 ? "overlay" 856 : event.playReason === "related-interaction" 857 ? "related" 858 : "auto"; 859 860 try { 861 IOLAnalytics.setInternalOrigin(`playlist ${playType}`, false); 862 } catch (err) { 863 if (window.iol_analytics) { 864 //new version 865 window.iol_analytics.setInternalOrigin(`playlist ${playType}`, false); 866 } else { 867 console.log("analytics module not loaded"); 868 } 869 } 870 } 871 872 _this.sendGAEvent("JW Player Video Plays", "Play", el); 873 _this.sendGAEvent("Play Programa", "Play", el); 874 875 /* Call SmartTop service if a smartoken is provided*/ 876 if (_this.iolJWPlayer.options.smartToken) { 877 var ST = Array.isArray(_this.iolJWPlayer.options.smartToken) 878 ? _this.iolJWPlayer.options.smartToken[videoIndex] 879 : _this.iolJWPlayer.options.smartToken; 880 var URLVisit = "https://mais-vistos-producer.iol.pt/mais-vistos-producer?token=" + ST; 881 _this.iolJWPlayer.playerElement.append( 882 "<img class='smarttop' style='display:none;' src='" + URLVisit + "' height='1' width='1'/>" 883 ); 884 } 885 886 _this.iolJWPlayer.firstPlay = false; 887 _this.iolJWPlayer.options.onFirstPlay.call(this, event); 888 } 889 890 /* Pauses the player if is a stoppable playlist */ 891 if (_this.iolJWPlayer.isStoppable) { 892 setTimeout(function() { 893 _this.iolJWPlayer.playerInstance.stop(); 894 }, _this.iolJWPlayer.isStoppable.time); 895 } 896 897 _this.iolJWPlayer.options.onPlay.call(this, event); 898 }); 899 900 this.iolJWPlayer.playerInstance.on("pause", function(event) { 901 _this.iolJWPlayer.options.onPause.call(this, event); 902 }); 903 904 this.iolJWPlayer.playerInstance.on("idle", function(event) { 905 _this.iolJWPlayer.options.onIdle.call(this, event); 906 }); 907 908 this.iolJWPlayer.playerInstance.on("seek", function(event) { 909 _this.iolJWPlayer.options.onSeek.call(this, event); 910 }); 911 912 this.iolJWPlayer.playerInstance.on("playAttemptFailed", function(event) { 913 //_this.sendMonitoringErrorEvent("Play Attempt Failed", event); 914 }); 915 916 this.iolJWPlayer.playerInstance.on("time", function(event) { 917 _this.iolJWPlayer.options.onTime.call(this, event); 918 }); 919 920 this.iolJWPlayer.playerInstance.on("complete", function(event) { 921 var videoIndex = _this.iolJWPlayer.playerInstance ? _this.iolJWPlayer.playerInstance.getPlaylistIndex() : 0; 922 var el = _this.iolJWPlayer.options.embedPlatform ? _this.iolJWPlayer.options.embedPlatform : "Video"; 923 924 if (["INCONTENT VIDEO", "Video"].includes(el)) { 925 _this.sendGAEvent("JW Player Video Completes", "Complete", el); 926 } 927 _this.iolJWPlayer.options.onComplete.call(this, event); 928 }); 929 930 this.iolJWPlayer.playerInstance.on("error", function(event) { 931 var videoIndex = _this.iolJWPlayer.playerInstance ? _this.iolJWPlayer.playerInstance.getPlaylistIndex() : 0; 932 var el = _this.iolJWPlayer.options.embedPlatform ? _this.iolJWPlayer.options.embedPlatform : "Video"; 933 if (["INCONTENT VIDEO", "Video"].includes(el)) { 934 _this.sendGAEvent("JW Player Video Error", event.message, el); 935 } 936 937 //_this.sendMonitoringErrorEvent("Error", event); 938 _this.iolJWPlayer.options.onError.call(this, event); 939 }); 940 941 /**** APPEAREANCE EVENTS ****/ 942 this.iolJWPlayer.playerInstance.on("visualQuality", function(event) { 943 _this.sendGAEvent("JW Player Visual Quality", event.mode, event.level.height + " | " + event.level.bitrate); 944 _this.iolJWPlayer.options.onVisualQuality.call(this, event); 945 }); 946 947 this.iolJWPlayer.playerInstance.on("viewable", function(event) { 948 //pause ad when isn't visible 949 event.viewable === 0 950 ? _this.iolJWPlayer.playerInstance.pauseAd(true) 951 : _this.iolJWPlayer.playerInstance.pauseAd(false); 952 953 if (_this.iolJWPlayer.options.playOnViewable) { 954 event.viewable === 0 ? _this.iolJWPlayer.playerInstance.pause() : _this.iolJWPlayer.playerInstance.play(); 955 } 956 }); 957 958 /**** PLAYLIST EVENTS ****/ 959 this.iolJWPlayer.playerInstance.on("playlistItem", function(event) { 960 _this.iolJWPlayer.firstPlay = true; 961 _this.iolJWPlayer.options.onPlaylistItem.call(this, event); 962 }); 963 964 this.iolJWPlayer.playerInstance.on("playlistComplete", function(event) { 965 _this.openRelated(); 966 _this.iolJWPlayer.options.onPlaylistComplete.call(this, event); 967 }); 968 969 var prevTagId; 970 this.iolJWPlayer.playerInstance.on('meta', (event) => { 971 if(!this.iolJWPlayer.options.hasAdvertising) { 972 return 973 } 974 const metadata = event?.metadata; 975 976 if (metadata?.tag !== 'EXT-X-DATERANGE' || (!metadata.content?.includes('SCTE35-OUT') && !metadata.content?.includes('SCTE35-IN'))) { 977 return; 978 } 979 980 981 const idMatch = metadata.content.match(/ID="([^"]+)"/); 982 const currentTagId = idMatch?.[1] ?? null; 983 984 if (currentTagId && currentTagId === prevTagId) { 985 return; 986 } 987 prevTagId = currentTagId; 988 989 const isCueOut = metadata.content.includes('SCTE35-OUT'); 990 const isCueIn = metadata.content.includes('SCTE35-IN'); 991 992 const rawDuration = metadata.duration > 0 ? metadata.duration * 1000 : 120_000; 993 const duration = Math.max(rawDuration - 10_000, 0); 994
995 console.log(`[SCTE-35] ${new Date().toLocaleString('sv-SE', { timeZone: 'Europe/Lisbon' })} | tag=${metadata.tag} | id=${currentTagId} | duration=${metadata.duration}s | content=${metadata.content}`); 996 997 if(isCueOut) { 998 const adUrlMidroll = _this.getMidrollUrl(); 999 if (!adUrlMidroll) { 1000 console.warn('[SCTE-35] No midroll URL available, skipping ad.'); 1001 return; 1002 } 1003 1004 const adString = `${adUrlMidroll}&pmnd=0&pmxd=${duration}&pmad=10&pod=2`; 1005 1006 try { 1007 _this.iolJWPlayer.playerInstance.playAd(adString); 1008 } catch (error) { 1009 console.error('[SCTE-35] playAd failed:', error); 1010 } 1011 } 1012 }); 1013 }, 1014 1015 /** 1016 * Sends the Google Analytics Events 1017 */ 1018 sendGAEvent: function(category, action, label) { 1019 var playerVersion = this.iolJWPlayer.playerInstance.version.split("+")[0]; 1020 var videoIndex = 1021 this.iolJWPlayer.playerInstance && this.iolJWPlayer.playerInstance.getPlaylistIndex() 1022 ? this.iolJWPlayer.playerInstance.getPlaylistIndex() 1023 : 0; 1024 1025 if (this.iolJWPlayer.options.shouldSendEvents) { 1026 if (typeof dataLayer !== "undefined") { 1027 if (window.iol_analytics) { 1028 this.sendGAEventByIOLAnalytics(category, action, label, playerVersion, videoIndex); 1029 } else { 1030 this.sendGAEventByDataLayer(category, action, label, playerVersion, videoIndex); 1031 } 1032 } else if (typeof ga !== "undefined") { 1033 ga("send", "event", category, label, action); 1034 } 1035 } 1036 }, 1037 1038 sendGAEventByDataLayer: function(category, action, label, playerVersion, videoIndex) { 1039 dataLayer.push({ 1040 "versao player": `JW_${playerVersion}|IOL_${JW_IOL_Version}`, 1041 eventCategory: category, 1042 eventLabel: label, 1043 eventAction: action, 1044 Programa_Id: decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].program.id), 1045 Programa_Nome: decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].program.name), 1046 Temporada_Id: decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].program.season), 1047 Episodio_Id: decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].program.ep), 1048 Multimedia_Id: decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].id), 1049 Titulo: this.limitEncodedText(this.iolJWPlayer.options.video[videoIndex].title, 150), 1050 Videoplay_Simultaneo: "S", //S|N 1051 Tipo: this.iolJWPlayer.options.video[videoIndex].videoType, //Clip|Integra|Live|Macro 1052 Live: this.iolJWPlayer.options.video[videoIndex].liveType, //DIRETO|ONLIVE|VOD 1053 AdUnit: this.iolJWPlayer.options.pub, //PUB|undefined 1054 Video_Play: 1, 1055 Plataforma: this.iolJWPlayer.options.playerPlatform, 1056 Duracao: this.roundToQuarter(this.iolJWPlayer.options.video[videoIndex].duration), 1057 event: "gaEvent" 1058 }); 1059 dataLayer.push({ 1060 "versao player": "" 1061 }); 1062 }, 1063 sendGAEventByIOLAnalytics: function(category, action, label, playerVersion, videoIndex) { 1064 let iolAnalytics = window.iol_analytics; 1065 iolAnalytics.sendEvent( 1066 category, 1067 label, 1068 action, 1069 "gaEvent", 1070 iolAnalytics.createDataLayerObjectWithDuration( 1071 "Video", 1072 decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].title ? this.iolJWPlayer.options.video[videoIndex].title.replace("%", "") : ""), 1073 decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].id), 1074 decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].program.ep), 1075 decodeURIComponent(this.iolJWPlayer.options.video[videoIndex].program.name), 1076 "", 1077 "", 1078 "S", 1079 this.iolJWPlayer.options.video[videoIndex].videoType, 1080 this.iolJWPlayer.options.video[videoIndex].liveType, 1081 `JW_${playerVersion}|IOL_${JW_IOL_Version}`, 1082 this.iolJWPlayer.options.playerPlatform, 1083 this.iolJWPlayer.options.pub, 1084 "", 1085 false, 1086 this.roundToQuarter(this.iolJWPlayer.options.video[videoIndex].duration) 1087 ) 1088 ); 1089 iolAnalytics.sendEvent("", "", "", "", undefined, { 1090 "versao player": "" 1091 }); 1092 }, 1093 1094 limitEncodedText: function(string) { 1095 var decodedStr = string.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); 1096 decodedStr = encodeURIComponent(decodedStr); 1097 if (decodedStr.length > 150) { 1098 decodedStr = decodedStr.substring(0, 150); 1099 while (!this.isAValidEncodedText(decodedStr)) { 1100 decodedStr = this.limitEncodedTextdText(decodedStr); 1101 } 1102 } 1103 return decodeURIComponent(decodedStr); 1104 }, 1105 1106 isAValidEncodedText: function(string) {
1107 try { 1108 decodeURIComponent(string); 1109 return true; 1110 } catch (err) { 1111 return false; 1112 } 1113 }, 1114 1115 limitEncodedTextdText: function(string) { 1116 return string.substring(0, string.lastIndexOf("%")); 1117 }, 1118 /** 1119 * Sends an event to the Graylog 1120 * @param {string} segmentation 1121 * @param {string} event 1122 */ 1123 sendMonitoringEvent: function(segmentation, event) { 1124 var playerVersion = this.iolJWPlayer.playerInstance 1125 ? this.iolJWPlayer.playerInstance.version.split("+")[0] 1126 : "Error"; 1127 var userAgent = navigator.userAgent; 1128 var host = window.location.href; 1129 var quality = this.iolJWPlayer.playerInstance ? this.iolJWPlayer.playerInstance.getVisualQuality() : undefined; 1130 1131 var videoIndex = 1132 this.iolJWPlayer.playerInstance && this.iolJWPlayer.playerInstance.getPlaylistIndex() 1133 ? this.iolJWPlayer.playerInstance.getPlaylistIndex() 1134 : 0; 1135 if (!this.iolJWPlayer.user) this.getUser(); 1136 1137 var errorObj = { 1138 message: `INFO | ${segmentation}`, 1139 host: `${host}`, 1140 "user-agent": `${userAgent}`, 1141 _u: this.iolJWPlayer.user.uname, 1142 _file: this.iolJWPlayer.options.video[videoIndex].videoUrl, 1143 _bufferState: !event.bufferState ? "" : event.bufferState, 1144 _network: { 1145 downlink: navigator.connection.downlink, 1146 effectiveType: navigator.connection.effectiveType 1147 }, 1148 _resolution: !quality 1149 ? "" 1150 : { 1151 mode: quality.mode, 1152 height: quality.level.height 1153 }, 1154 _version: `JW_${playerVersion}|IOL_${JW_IOL_Version}` 1155 }; 1156 1157 var _this = this; 1158 1159 errorObj["_ip"] = _this.iolJWPlayer.user.IPCode; 1160 errorObj["_countryCode"] = _this.iolJWPlayer.user.IPCountryCode; 1161 1162 $.ajax({ 1163 type: "POST", 1164 url: "https://services.iol.pt/pevents", 1165 data: JSON.stringify(errorObj), 1166 contentType: "application/json", 1167 dataType: "json" 1168 }); 1169 }, 1170 1171 /** 1172 * Sends an error event to the Graylog 1173 * @param {string} segmentation 1174 * @param {string} event 1175 * @param {function} callback 1176 */ 1177 sendMonitoringErrorEvent: function(segmentation, event, callback) { 1178 var playerVersion = this.iolJWPlayer.playerInstance 1179 ? this.iolJWPlayer.playerInstance.version.split("+")[0] 1180 : "Error"; 1181 var userAgent = navigator.userAgent; 1182 var host = window.location.href; 1183 var quality = this.iolJWPlayer.playerInstance ? this.iolJWPlayer.playerInstance.getVisualQuality() : undefined; 1184 var videoIndex = 1185 this.iolJWPlayer.playerInstance && this.iolJWPlayer.playerInstance.getPlaylistIndex() 1186 ? this.iolJWPlayer.playerInstance.getPlaylistIndex() 1187 : 0; 1188 1189 if (!this.iolJWPlayer.user) this.getUser(); 1190 1191 var errorObj = { 1192 message: `${segmentation} | ${event.message}`, 1193 host: `${host}`, 1194 "user-agent": `${userAgent}`, 1195 _code: event.code ? `${event.code}` : "", 1196 _type: event.type ? `${event.type}` : "", 1197 _u: this.iolJWPlayer.user.uname, 1198 _file: this.iolJWPlayer.options.video[videoIndex].videoUrl, 1199 _sourceError: !event.sourceError 1200 ? "" 1201 : { 1202 type: `${event.sourceError.type}`, 1203 details: `${event.sourceError.details}`, 1204 fatal: `${event.sourceError.fatal}`, 1205 url: `${event.sourceError.url}` 1206 }, 1207 _bufferState: !event.bufferState ? "" : event.bufferState, 1208 _network: { 1209 downlink: navigator.connection.downlink, 1210 effectiveType: navigator.connection.effectiveType 1211 }, 1212 _resolution: !quality 1213 ? "" 1214 : { 1215 mode: quality.mode, 1216 level: quality.level 1217 }, 1218 _version: `JW_${playerVersion}|IOL_${JW_IOL_Version}` 1219 }; 1220 1221 var _this = this; 1222 1223 errorObj["_ip"] = _this.iolJWPlayer.user.IPCode; 1224 errorObj["_countryCode"] = _this.iolJWPlayer.user.IPCountryCode; 1225 1226 this.errorValidation(errorObj, callback); 1227 }, 1228 1229 /** 1230 * Validates the different types of error 1231 * @param {JSON} errorObj 1232 * @param {function} callback 1233 */ 1234 errorValidation: function(errorObj, callback) { 1235 /* Validates cookie creation date */ 1236 var cookieExp = $.cookie("jwiol_c"); 1237 var videoIndex = 1238 this.iolJWPlayer.playerInstance && this.iolJWPlayer.playerInstance.getPlaylistIndex() 1239 ? this.iolJWPlayer.playerInstance.getPlaylistIndex() 1240 : 0; 1241 1242 if (cookieExp) { 1243 var creationDate = Date.parse(cookieExp); 1244 var currentDate = new Date(); 1245 1246 if ((currentDate.getTime() - creationDate) / 1000 / 3600 > 20) { 1247 errorObj["_mcdError"] = "errorExpired"; 1248 $.ajax({ 1249 type: "POST", 1250 url: "https://services.iol.pt/pevents", 1251 data: JSON.stringify(errorObj), 1252 contentType: "application/json", 1253 dataType: "json" 1254 }); 1255 1256 if (callback) callback(errorObj["_mcdError"]); 1257 } 1258 } 1259 1260 /* If is a live transmition with the error cod 232403 validates the rights of the transmission */ 1261 if (this.iolJWPlayer.options.video[videoIndex].liveType == "DIRETO" && errorObj["_
1261code"] == "232403") { 1262 this.getErrorDetails(errorObj, callback); 1263 } else { 1264 errorObj["_mcdError"] = "errorDefault"; 1265 $.ajax({ 1266 type: "POST", 1267 url: "https://services.iol.pt/pevents", 1268 data: JSON.stringify(errorObj), 1269 contentType: "application/json", 1270 dataType: "json" 1271 }); 1272 1273 if (callback) callback(errorObj["_mcdError"]); 1274 } 1275 }, 1276 1277 /** 1278 * Determines the error reason 1279 * @param {JSON} errorObj 1280 * @param {function} callback 1281 */ 1282 getErrorDetails: function(errorObj, callback) { 1283 var videoIndex = 1284 this.iolJWPlayer.playerInstance && this.iolJWPlayer.playerInstance.getPlaylistIndex() 1285 ? this.iolJWPlayer.playerInstance.getPlaylistIndex() 1286 : 0; 1287 1288 $.get( 1289 `https://services.iol.pt/videoMonitoring?canal=${this.iolJWPlayer.options.video[videoIndex].channel}&countrycode=${errorObj["_countryCode"]}`, 1290 function(data) { 1291 data = JSON.parse(data); 1292 errorObj["_mcdError"] = data["error"]; 1293 errorObj["_mcdDetails"] = data["programa"]; 1294 1295 $.ajax({ 1296 type: "POST", 1297 url: "https://services.iol.pt/pevents", 1298 data: JSON.stringify(errorObj), 1299 contentType: "application/json", 1300 dataType: "json" 1301 }); 1302 1303 if (callback) callback(errorObj["_mcdError"]); 1304 } 1305 ).fail(function() { 1306 errorObj["_mcdError"] = "errorFailed"; 1307 $.ajax({ 1308 type: "POST", 1309 url: "https://services.iol.pt/pevents", 1310 data: JSON.stringify(errorObj), 1311 contentType: "application/json", 1312 dataType: "json" 1313 }); 1314 1315 if (callback) callback(errorObj["_mcdError"]); 1316 }); 1317 }, 1318 1319 /** 1320 * Gets the Username 1321 */ 1322 getUser: function() { 1323 var user = { u: "", id: "id" , subscribedProducts:[]}; 1324 this.iolJWPlayer.user = {}; 1325 1326 var sluserx1 = localStorage.getItem("userx1"); 1327 var slx1user = localStorage.getItem("x1user"); 1328 1329 if (sluserx1 != null) { 1330 sl = JSON.parse(sluserx1); 1331 user["u"] = sl.userName ? sl.userName : ""; 1332 user["id"] = sl.id ? sl.id : ""; 1333 user["subscribedProducts"] = sl.subscribedProducts ? sl.subscribedProducts : []; 1334 } 1335 if (slx1user != null) { 1336 sl = JSON.parse(slx1user); 1337 user["u"] = sl.userName ? sl.userName : ""; 1338 user["id"] = sl.id ? sl.id : ""; 1339 user["subscribedProducts"] = sl.subscribedProducts ? sl.subscribedProducts : []; 1340 } 1341 1342 this.iolJWPlayer.user.uname = user["u"]; 1343 this.iolJWPlayer.user.uid = user["id"]; 1344 var _this = this; 1345 $.ajax({ 1346 url: "https://services.iol.pt/getgcc/ipdetails", 1347 type: "get", 1348 async: false, 1349 success: function(data) { 1350 data = data.split("|"); 1351 _this.iolJWPlayer.user.IPCode = data[0]; 1352 _this.iolJWPlayer.user.IPCountryCode = data[1]; 1353 user["i"] = btoa(data[0]); 1354 }, 1355 error: function() { 1356 console.log("error"); 1357 } 1358 }); 1359 1360 return user; 1361 }, 1362 1363 shouldPlayAds(user) { 1364 return !(user && user["subscribedProducts"] != null && user["subscribedProducts"].length > 0 && noPubProducts.some(r=> user["subscribedProducts"].includes(r))); 1365 }, 1366 1367 getMidrollUrl: function () { 1368 var url = window.encodeURIComponent(window.location.href); 1369 var videoSizes = "720x576"; 1370 var gdpr = this.iolJWPlayer.consentString ? `&gdpr=1&gdpr_consent=${this.iolJWPlayer.consentString}` : ''; 1371 //Url ads VAST 1372 let adUrlMidroll = `https://pubads.g.doubleclick.net/gampad/ads?sz=${videoSizes}&iu=${this.iolJWPlayer.options.pub}&ciu_szs&impl=s&gdfp_req=1&env=vp&output=vast&unviewed_position_start=1&plcmt=1&url=${url}${gdpr}&vpos=midroll&correlator=${Math.floor(1e5 * Math.random()) + 1}&ad_rule=0`; 1373 1374 return adUrlMidroll; 1375 }, 1376 1377 roundToQuarter : function(seconds) { 1378 const num = Number(seconds); 1379 1380 if (isNaN(num) || num < 0) { 1381 return; 1382 } 1383 1384 var remainder = num % 15; 1385 1386 var rounded = remainder === 0 ? num : num + (15 - remainder); 1387 1388 return rounded; 1389 }, 1390 jwplayer: function() { 1391 return this.iolJWPlayer.playerInstance; 1392 }, 1393 1394 play: function() { 1395 return jwplayer(this.iolJWPlayer.playerDivId).play(); 1396 }, 1397 1398 pause: function() { 1399 return jwplayer(this.iolJWPlayer.playerDivId).pause(); 1400 }, 1401 1402 stop: function() { 1403 return jwplayer(this.iolJWPlayer.playerDivId).stop(); 1404 }, 1405 1406 change: function(videoIndex) { 1407 return jwplayer(this.iolJWPlayer.playerDivId).playlistItem(videoIndex); 1408 }, 1409 1410 mute: function() { 1411 return jwplayer(this.iolJWPlayer.playerDivId).setMute(true); 1412 }, 1413 1414 unmute: function() { 1415 return jwplayer(this.iolJWPlayer.playerDivId).setMute(false); 1416 }, 1417 1418 openRelated: function() { 1419 jwplayer(this.iolJWPlayer.playerDivId) 1420 .getPlugin("related") 1421 .open(); 1422 }, 1423 1424 getPosition: function() { 1425 return jwplayer(this.iolJWPlayer.playerDivId).getPosition(); 1426 }, 1427 1428 getState: function() { 1429 return jwplayer(this.iolJWPlayer.playerDivId).getState(); 1430 }, 1431 1432 seek: function(position) { 1433 return jwplayer(this.iolJWPlayer.playerDivId).seek(position); 1434 } 1435 }; 1436})(jQuery, window, document);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.