1/* 2 * Hash Player -- api.v2.js, no mesmo contrato da api.v2.js do Panda. 3 * 4 * Os sites (tema-wordpress-hashtag, lps-hashtag, capacitaciones, fnat) fazem: 5 * 6 * new PandaPlayer(idDoIframe, { onReady, onError }) 7 * player.onEvent(({ message, currentTime, isMutedIndicator }) => ...) // "panda_timeupdate" 8 * player.getCurrentTime(); player.getDuration(); player.play(); ... 9 * 10 * e e so isso que precisa continuar funcionando quando o host do iframe e o 11 * deste script trocarem (F3). O protocolo entre esta pagina e o iframe e o 12 * MESMO do Panda (medido em 19/09/2026 na api.v2.js deles): o iframe manda 13 * `{ message: "panda_allData", video, playerData: {...} }` e 14 * `{ message: "panda_timeupdate", video, currentTime, isMutedIndicator }`; 15 * o pai manda `{ type: "play" | "pause" | "togglePlay" | "currentTime" | 16 * "volume" | "speed" | "fullscreen.toggle", parameter }`. Assim a api.v2.js 17 * deles tambem toca o nosso embed, e a nossa toca o deles. 18 * 19 * Sem dependencia, sem build: e servido como esta em /api.v2.js. 20 */ 21(function () { 22 "use strict"; 23 24 function idDoVideo(iframe) { 25 try { 26 return new URL(iframe.src, location.href).searchParams.get("v") || ""; 27 } catch (e) { 28 return ""; 29 } 30 } 31 32 function PandaPlayer(elementId, opcoes) { 33 var self = this; 34 opcoes = opcoes || {}; 35 this.element_id = elementId; 36 this.onReady = opcoes.onReady; 37 this.onError = opcoes.onError; 38 this.ready = false; 39 this.paused = true; 40 this.muted = false; 41 this.volume = 1; 42 this.currentTime = 0; 43 this.duration = 0; 44 this.speed = 1; 45 this.fullscreen = false; 46 this.captions = null; 47 this.callbacks = []; 48 this._filaEventos = []; 49 this._filaChamadas = []; 50 51 var iframe = document.getElementById(elementId); 52 if (!iframe || iframe.tagName !== "IFRAME") { 53 if (this.onError) this.onError({ message: "panda_error", error: "iframe nao encontrado: " + elementId }); 54 return; 55 } 56 this.iframe = iframe; 57 this.video_external_id = idDoVideo(iframe); 58 try { 59 this.origin = new URL(iframe.src, location.href).origin; 60 } catch (e) { 61 this.origin = "*"; 62 } 63 64 this._ouvir = function (ev) { 65 var d = ev.data; 66 if (!d || typeof d !== "object" || !d.message) return; 67 if (ev.source !== iframe.contentWindow) return; 68 if (d.video && self.video_external_id && d.video !== self.video_external_id) return; 69 if (d.message === "panda_error" && self.onError) self.onError(d); 70 if (d.message === "panda_allData" && d.playerData) { 71 var p = d.playerData; 72 self.paused = !!p.paused; 73 self.muted = !!p.muted; 74 self.volume = p.volume; 75 self.currentTime = p.currentTime; 76 self.duration = p.duration; 77 self.speed = p.speed; 78 self.fullscreen = !!p.fullscreen; 79 self.captions = p.captions; 80 if (!self.ready && p.duration > 0) { 81 self.ready = true; 82 if (self.onReady) self.onReady(); 83 self._filaChamadas.forEach(function (f) { f(); }); 84 self._filaChamadas = []; 85 } 86 } 87 if (d.message === "panda_timeupdate") self.currentTime = d.currentTime; 88 if (self.ready) { 89 if (self._filaEventos.length) { 90 self._filaEventos.forEach(function (e) { self.callbacks.forEach(function (cb) { cb(e); }); }); 91 self._filaEventos = []; 92 } 93 self.callbacks.forEach(function (cb) { cb(d); }); 94 } else { 95 self._filaEventos.push(d); 96 } 97 }; 98 window.addEventListener("message", this._ouvir); 99 // Instanciado DEPOIS de o iframe carregar, os allData iniciais ja se 100 // foram e `ready` nunca viraria: pergunta o estado agora, fora da fila 101 // (que so anda depois do ready). Se o iframe ainda nao carregou, a 102 // pergunta se perde e o proprio loadedmetadata dele traz o allData. 103 try { 104 if (iframe.contentWindow) iframe.contentWindow.postMessage({ type: "allData" }, this.origin); 105 } catch (e) {} 106 } 107 108 PandaPlayer.prototype._mandar = function (msg) { 109 var self = this; 110 var envia = function () { 111 if (self.iframe && self.iframe.contentWindow) self.iframe.contentWindow.postMessage(msg, self.origin); 112 }; 113 if (this.ready) envia(); 114 else this._filaChamadas.push(envia); 115 }; 116 117 PandaPlayer.prototype.onEvent = function (cb) { 118 if (typeof cb === "function") this.callbacks.push(cb); 119 }; 120 PandaPlayer.prototype.play = function () { this._mandar({ type: "play" }); }; 121 PandaPlayer.prototype.pause = function () { this._mandar({ type: "pause" }); }; 122 PandaPlayer.prototype.togglePlay = function () { this._mandar({ type: "togglePlay" }); }; 123 PandaPlayer.prototype.setCurrentTime = function (t) { this._mandar({ type: "currentTime", parameter: Number(t) || 0 }); }; 124 PandaPlayer.prototype.getCurrentTime = function () { return this.currentTime; }; 125 PandaPlayer.prototype.getDuration = function () { return this.duration; }; 126 PandaPlayer.prototype.setVolume = function (v) { this._mandar({ type: "volume", parameter: Number(v) }); }; 127 PandaPlayer.prototype.getVolume = function () { return this.volume; }; 128 PandaPlayer.prototype.setSpeed = function (s) { this._mandar({ type: "speed", parameter: Number(s) || 1 }); }; 129 PandaPlayer.prototype.getSpeed = function () { return this.speed; }; 130 PandaPlayer.prototype.isPaused = function () { return this.paused; }; 131 PandaPlayer.prototype.isMuted = function () { return this.muted; }; 132 PandaPlayer.prototype.toggleFullscreen = function () { this._mandar({ type: "fullscreen.toggle" }); }; 133 PandaPlayer.prototype.exitFullscreen = function () { this._mandar({ type: "fullscreen.exit" }); }; 134 PandaPlayer.prototype.destroy = function () { 135 window.removeEventListener("message", this._ouvir); 136 this.callbacks = []; 137 }; 138 // Existem na api do Panda; aqui sao no-op declarados, para nao quebrar quem chama.
139 PandaPlayer.prototype.loadButtonInTime = function () {}; 140 PandaPlayer.prototype.loadWindowScreen = function () {}; 141 142 window.PandaPlayer = PandaPlayer; 143 window.HashPlayer = PandaPlayer; 144})();
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.