MyCujoo LiveServices logo
HomeProductsPricingHelp Center
Create your accountSign in
Sign In

Home

Products

Pricing

Help Center

Welcome

Product & Features

Getting started

Glossary

API Documentation

Working with zoid guide

Working with zoid guide

This guide attempts to help with the integration of MCLS Zoid Player component. In MCLS there are 3 ways of embedding a video event:

  • using the React Player component from @mycujoo/mcls-components

  • using an iframe for https://embed.mls.mycujoo.tv/player/<event-id>?autoplay=true&publicKey=<org-public-key>

  • using the zoid embed solution

The guide below will focus on the 3rd option.

1. What is zoid and how does it work?

Zoid is a powerful, open-source library that simplifies the process of building modular, cross-domain components and provides a secure, performant solution for communicating with iframes.

To facilitate communication between the parent window and the child iframe, Zoid uses the postMessage API provided by the browser.

The library provides a set of message handlers that listen for specific events or messages sent by the child iframe, and respond accordingly and also provides a set of APIs that can be used within the child iframe to communicate with the parent window. These APIs allow the child iframe to send messages and request data from the parent window, and receive responses in return.

2. MCLS player embed solution

There are 3 parts to the MCLS Zoid implementation

  • the hosted player app

  • the zoid child context definition

  • the zoid parent context definition

The player app is available at https://embed.mls.mycujoo.tv/player/<event-id>. This page will render the video player.

1. Child context definition

On the same page where the player is rendered we're also defining the Zoid child context. This is how we tell zoid what properties does the component have, what is the tag (the component identifier) and few other configuration options. The definition has the following shape:

const eventId = "<EVENT-ID>"; const host = "https://embed.mls.mycujoo.tv"; const url = `${host}/player/${eventId}`; const tag = `embed-${eventId}`; const ZoidComponent = zoid.create({ tag, url, dimensions: { width: "100%", height: "100%", }, autoResize: { height: true, }, props: { autoplay: { type: "boolean", queryParam: "autoplay", }, debug: { type: "boolean", queryParam: "debug", }, defaultVolume: { type: "number", }, eventId: { type: "string", }, publicKey: { type: "string", }, identityToken: { type: "string", }, primaryColor: { type: "string", }, secondaryColor: { type: "string", }, adUnit: { type: "string", }, adCustParams: { type: "string", }, showBackForwardButtons: { type: "boolean", }, showEventInfoButton: { type: "boolean", }, showLiveViewers: { type: "boolean", }, showSeekbar: { type: "boolean", }, showFullscreen: { type: "boolean", }, showQualitySelector: { type: "boolean", }, showVolume: { type: "boolean", }, showTimers: { type: "boolean", }, showChromecast: { type: "boolean", }, showPictureInPicture: { type: "boolean", }, enableAnnotations: { type: "boolean", }, analyticsType: { type: "string", }, analyticsAccount: { type: "string", }, analyticsUserId: { type: "string", }, startPosition: { type: "number", }, onTimeUpdate: { type: "function", }, onViewChange: { type: "function", }, annotations: { type: "array", }, customPlaylistUrl: { type: "string", }, seekTo: { type: "number", }, }, attributes: { iframe: { allow: `autoplay ${host}; fullscreen ${host}`, allowfullscreen: "", }, }, });

This is everything needed for the child component definition. At this point the app renders a video player and register a Zoid component.

2. Parent context definition

For the other half of the communication we need to define the parent Zoid context. This is already defined in https://embed.mls.mycujoo.tv/embed.js.

The un minified version of this script has the following shape:

// import zoid library ;((d, w, z) => { if (!d || !w || !z) return console.log('[Zoid parent] document.fullscreenEnabled', document.fullscreenEnabled) d.querySelectorAll('div[data-embed-id]').forEach((e) => { const id = e.dataset.embedId || '' const host = 'https://embed.mls.mycujoo.tv' const url = `${host}/player/${id}` const tag = `embed-${id}` const autoplay = e.dataset.autoplay === 'false' ? false : true const publicKey = e.dataset.publicKey || '' const identityToken = e.dataset.identityToken || '' const debug = ['true', ''].includes(e.dataset.debug) || false const defaultVolume = +e.dataset.defaultVolume || 0 const startPosition = e.dataset.startPosition || 0 const primaryColor = e.dataset.primaryColor || '#FFF' const secondaryColor = e.dataset.secondaryColor || '#FFF' const adUnit = e.dataset.adUnit || '' const adCustParams = e.dataset.adCustParams || '' const showBackForwardButtons = e.dataset.showBackForwardButtons === 'false' ? false : true const showEventInfoButton = e.dataset.showEventInfoButton === 'false' ? false : true const showLiveViewers = e.dataset.showLiveViewers === 'false' ? false : true const showSeekbar = e.dataset.showSeekbar === 'false' ? false : true const showFullscreen = e.dataset.showFullscreen === 'false' ? false : true const showQualitySelector = e.dataset.showQualitySelector === 'false' ? false : true const showVolume = e.dataset.showVolume === 'false' ? false : true const showTimers = e.dataset.showTimers === 'false' ? false : true const showChromecast = e.dataset.showChromecast === 'false' ? false : true const showPictureInPicture = e.dataset.showPictureInPicture === 'false' ? false : true const enableAnnotations = e.dataset.enableAnnotations === 'false' ? false : true const analyticsType = e.dataset.analyticsType || '' const analyticsAccount = e.dataset.analyticsAccount || '' const analyticsUserId = e.dataset.analyticsUserId || '' const customPlaylistUrl = e.dataset.customPlaylistUrl const annotations = [] const seekTo = 0 const containerHeight = e.clientHeight || 315 e.style.lineHeight = 0 e.style.minHeight = 'inherit' e.style.height = 'inherit' const c = z.create({ tag, url, dimensions: { width: '100%', height: containerHeight, }, attributes: { iframe: { allow: `autoplay ${host}; fullscreen ${host}`, allowfullscreen: '', }, }, }) debug && console.log('[Zoid parent] component created: ', { autoplay, debug, defaultVolume, eventId: id, publicKey, identityToken, primaryColor, secondaryColor, adUnit, adCustParams, showEventInfoButton, showLiveViewers, showBackForwardButtons, showSeekbar, showFullscreen, showQualitySelector, showVolume, showTimers, showChromecast, showPictureInPicture, enableAnnotations, analyticsAccount, analyticsType, analyticsUserId, startPosition, customPlaylistUrl, annotations, seekTo, }) w.MLSEmbeds = w.MLSEmbeds || {} w.MLSEmbeds[tag] = c const onTimeUpdate = (currentTime, totalTime) => { // example of implementation const event = new CustomEvent('timeUpdate', { detail: { currentTime, totalTime, }, }) e.dispatchEvent(event) } const onViewChange = (view) => { console.log(view) } c({ autoplay, debug, defaultVolume, eventId: id, publicKey, identityToken, primaryColor, secondaryColor, adUnit, adCustParams, showEventInfoButton, showLiveViewers, showBackForwardButtons, showSeekbar, showFullscreen, showQualitySelector, showVolume, showTimers, showChromecast, showPictureInPicture, enableAnnotations, analyticsAccount, analyticsType, analyticsUserId, startPosition, onTimeUpdate, onViewChange, annotations, seekTo, customPlaylistUrl, }).render(`div[data-embed-id='${id}']`) })})(document, window, zoid)

The script is intended to work with multiple player instances on the same page. When loading this on your page the script will look up for divs with the attribute data-embed-id, extract all properties specified via data-* attributes and pass those to zoid.

At this point if the parent and child context definitions match and the zoid version on the child context matches the zoid version on the parent context, the communication should be functional.

3. Advanced scenarios

While the above parent context definition is convenient to use for static text properties, might not be as convenient for changing properties or callback properties like onTimeUpdate or onViewChange which predefined embed.js solution above have to use event listeners. When implementing the parent context definition one can make use of zoid's flexible architecture that can be adapted to integrate with different frontend frameworks like React, Angular or Vue.

Supported function props:

const onTimeUpdate = ( currentVideoProgress: number, totalVideoDuration: number ) => {};

/** * @param { PlayerView } activeView - The type of view rendered on the player. * * The possible values are: * 'NOT_FOUND' - passed when the public key and event id combination is invalid or when the domain where the player is hosted is not valid for your organization * 'GEOBLOCKED' - passed when the event geoblocking settings are not valid from the country the request was made * 'AUTHORIZATION' - passed when the event is behind a paywall and the current user (identityToken) does not have access to the event * 'CONCURRENCY_LIMIT' - passed when the number of simultaneus sessions for watching an event by a user (identityToken) has been reached * 'UPCOMING' - passed when the event stream has not started yet * 'VIDEO' - passed when displaying the video player * 'LOADING' - passed when showing a spinner * * @returns {void} */ type PlayerView = | "NOT_FOUND" | "GEOBLOCKED" | "AUTHORIZATION" | "CONCURRENCY_LIMIT" | "UPCOMING" | "VIDEO" | "LOADING"; const onViewChange = (activeView: PlayerView) => {};

The steps for using any of the two function props are:

  1. Install and load Zoid Make sure the version of the library matches that on the client. In case it doesn't zoid will show an error with details of the versions missmatch.

import * as zoid from 'zoid/dist/zoid'

  1. Create the zoid parent context

const eventId = ""; const containerHeight = 315; const host = "https://embed.mls.mycujoo.tv"; const url = `${host}/player/${eventId}`; const tag = `embed-${eventId}`; const zoidComponent = zoid.create({ tag, url, dimensions: { width: "100%", height: containerHeight, }, attributes: { iframe: { allow: `autoplay ${host}; fullscreen ${host}`, allowfullscreen: "", }, }, });

2. Trigger property updates using vanilla javascript

zoidComponent({ autoplay, debug, defaultVolume, eventId: id, publicKey, identityToken, primaryColor, secondaryColor, adUnit, adCustParams, showEventInfoButton, showLiveViewers, showBackForwardButtons, showSeekbar, showFullscreen, showQualitySelector, showVolume, showTimers, showChromecast, showPictureInPicture, enableAnnotations, analyticsAccount, analyticsType, analyticsUserId, startPosition, onTimeUpdate, onViewChange, annotations, seekTo, customPlaylistUrl, }).render(`div[data-embed-id='${id}']`);

Alternatively zoid includes driver definitions for React, Angular and Vue. The step from above is equivalent to the following:

React:

const PlayerComponent = zoidComponent.driver("react", { React, ReactDOM, }); const ComponentInYourApp = (props) => { const onTimeUpdate = useCallback((currentTime, totalTime) => { console.log(currentTime, totalTime); }, []); const onViewChange = useCallback((activeView) => { console.log(activeView); }, []); return ( <div> <h1>MCLS Player</h1> <PlayerComponent {...props} onTimeUpdate={onTimeUpdate} onViewChange={onViewChange} /> </div> ); }; Angular 2: const PlayerComponentNg2 = MyLoginZoidComponent.driver( "angular2", ng.core );

Fore more details please refer to following examples of Zoid parent context implementations: Angular Angular 2 React Vue Vue 3