Widget API

Widget API

Widgets are key expansion points of any cinema8 interactive video. While You can use any widget from the widget library you can also develop your own customized widgets with the C8 Widget Development environment. This article  walks you through the  widget environment where you can develop unlimited solutions natively integrated with the video timeline and access all inner features of C8 client APIs.

Before starting you can read these articles ;


Widget Platform Overview 

Widgets are customizable and reusable elements within the cinema8 environment. Widgets are at the core of Cinema8, making the capabilities of integrating any technology, extending and integrating the platform for any use case. You can use any widget from the widget library and also develop your custom code base.
Widgets can be developed using the Widget development environment and the output will be a self-runnable-code-snippet that works in a sandbox inside the videos. 
Whenever you develop any widget, the widget will be accessible inside the creative studio, you can drag and drop and customize this widget within the creative studio. 



All Widgets have common functions & properties inherited from the core Cinema8 element.
Common properties inherited from core cinema8 element


  1. Name
  2. Start
  3. End
  4. Visible
  5. Onstart
  6. OnEnd
  7. OnClick
  8. Position (in percentage)





You can also add custom parameters inside your widgets to make the widget reusable between different videos.


Defining & Using Parameters

We can define properties in different data types in order to configure the widgets from within the studio. These properties allow the widgets to be modular and to be used by customizing them in different videos. 

Screenshot from widget props
What you see in Studio

Widget property development



Widget properties in creative studio



The property data types supported by the system are as follows.
  1.     Text (string)
  2.     Text Area (string)
  3.     Color (string)
  4.     Image  (Image selection)
  5.     Video  (Video selection)
  6.     Boolean (boolean)
  7.     Text List (array)  
  8.     Image List (array)  
  9.     Select (array)
  10.     Action (N/A)


Accessing parameters in HTML code

You can access all dynamic parameters within HTML content. HTML part of the widget development environment  uses "handle bars".
Handlebars is  a simple templating language . It uses a template and an input object to generate HTML or other text formats. Handlebars templates look like regular text with embedded Handlebars expressions. You can get more details about handlebars from this link.

You can use this expression to write any property value inside the HTML part.  

  1. {{text}}

To write text list, image list and select type property values , you can iterate using {{#each propKey}}...{{/each}} function.

  1.   <ul>
        {{#each people}}
          <li>{{this}}</li>
        {{/each}}
      </ul>
If user selects any property from a select property type , the selected value will be stored in a variable with the property name  prefixed with " selected " keyword.If the variable name is " color " the value will be stored in " selectedColor ".

You can also access to Authenticated User data within HTML code block.
  1. ${authenticatedUser.username} 


Accessing parameters from javascript code

You can access the widget properties from within the javascript code block. You can access the c8PlayerApi object to provide this access. c8PlayerApi defines functions that will list all widget properties and reach the runtime value of any property.
  1. c8PlayerApi.getWidgetProps()    //lists all available widget properties
  2. c8PlayerApi.getWidgetProp('textArea')  // returns the runtimevalue of 'textArea' property 
You can also access to uniqueID within javascript code with {{uid}}  template .
  1. // Widget Prop
    $('.c- {{uid}} .widget-prop-single').click(function() {
       console.log(c8PlayerApi.getWidgetProp('textArea'));
    });


Accessing  parameters in CSS code

As in the javascript code block, you can access the parameters from the CSS code block by using the parameter name between two double parentheses.
  1. {{parameterName}}
You can also access  uniqueID within CSS code with  {{uid}}   template .
  1. .c-{{uid}}{
      width: 100%;
      height: 100%;
      background: {{color}};
      padding: 1rem;
      overflow-y: scroll;
      display: flex;
      justify-content: space-between;
    }
It is important to have a unique id in the widget development processes. Making unique naming in the class names of HTML elements or in the id field allows you to use different configurations of the same widget in the video at the same time and prevents conflicts.
You can use the template identifier {{uid}} for this purpose. The {{uid}} template generates a unique code for you at runtime, which points to the same value in HTML, CSS, and Javascript code blocks in the widget instance.
HTML
  1. <div class='c-{{uid}}'>
CSS
  1. .c-{{uid}} .col > div{
      display: flex;
      flex-direction: column;
      margin-bottom: .75rem;
    }
Javascript

  1. $('.c-{{uid}} .widget-props').click(function() {
       console.log(c8PlayerApi.getWidgetProps());
    });

Cinema8 Javascript APIs accessible within widget JS code.

The following default functions are accessible from within the javascript code block in the widget editor. It can be called directly from within js.


  1.   c8PlayerApi.play(); // Play video
      c8PlayerApi.pause();  // Pause video
      c8PlayerApi.paused(); //  Checks whether the video is paused (true|false)
      c8PlayerApi.currentTime(); // Returns current position (in seconds) of the video
      c8PlayerApi.currentTime(sec); // Sets current position (in seconds) of the video
      c8PlayerApi.hideControls(); // Hide player controls
      c8PlayerApi.showControls(); // Show player controls
      c8PlayerApi.volume(); // Returns volume of the video (range 0 .. 1)
      c8PlayerApi.volume(vol); // Sets volume of the video  (range 0 .. 1)
      c8PlayerApi.subtitle(); // Returns value of current subtitle if exist, otherwise it returns null
      c8PlayerApi.subtitle("en"); // Sets subtitle ( Set "off" to turn off subtitles )
      c8PlayerApi.subtitles(); // Returns available subtitles if exist, otherwise it returns an empty array
        Sample response: 
          [
            {
              "value": "es",
              "label": "Spanish"
            },
            {
              "value": "en",
              "label": "English"
            }
          ]

      c8PlayerApi.audioTrack(); // Returns object of current audio track if exist, otherwise it returns null;
        Sample response:
        {
          "label": "Spanish",
          "value": "es"
        }

      c8PlayerApi.audioTrack(1); // Sets audio track of the video by given index
      c8PlayerApi.audioTracks(); // Returns available audio tracks if exist, otherwise it returns an empty array
        Sample response: 
        [
          {
            "label": "English",
            "value": "en"
          },
          {
            "label": "Spanish",
            "value": "es"
          }
        ]

      c8PlayerApi.launchFullscreen(); // Launch fullscreen
      c8PlayerApi.exitFullscreen(); // Exit fullscreen

      c8PlayerApi.playbackRate(); // Returns value of playback rate of the video
      c8PlayerApi.playbackRate(1); // Sets playback rate of the video (0.25, 1, 1.5 etc.)
      
      c8PlayerApi.qualityLevel(); // Returns current quality level of the video
      c8PlayerApi.qualityLevel(3); // Sets quality level of the video of given quality level ( Set "auto" for Auto level )
      c8PlayerApi.qualityLevels(); // Returns available quality levels if exist
        Sample response:
        {
          "auto": true,
          "levels": [
            {
              "level": 3,
              "height": 1080,
              "label": "1080p"
            },
            {
              "level": 1,
              "height": 360,
              "label": "360p"
            }
          ]
        } 

      //Access variables within js code
      c8PlayerApi.getVariable(key); // Returns variable of given variableKey
      c8PlayerApi.setVariable(key, value, persistent); // Sets variable for given key , use persistent=true for sticky variables.
      c8PlayerApi.getVariables(); // Returns all variables
      

    // Track Properties
    c8PlayerApi.getTrackProps(); // Returns track properties
      Sample response: 
      {
        duration: 15,
        end: 25,
        start: 10,
        visible: true
      }

    c8PlayerApi.getTrackProp(PROPERTY_NAME); // Returns track property of given property name
    c8PlayerApi.getTrackProp(PROPERTY_NAME, DEFAULT_VALUE); // Returns default value if given property does not exist


    // Returns widget properties
    c8PlayerApi.getWidgetProps(); 
    // Returns widget property of given property name
    c8PlayerApi.getWidgetProp(PROPERTY_NAME); 


     //Set the visibility of the widget instance on screen 
      c8PlayerApi.setVisible(); //show widget
      c8PlayerApi.setInvisible(); // hide widget
     
    // AuthenticatedUser 
      c8PlayerApi.getAuthenticatedUser();  // return any authenticated user info , returns null if empty

      Sample response: {
        name: 'John',
        surname: 'Doe',
        username: 'john.doe'
      }

    //Saving client data within widget context
       c8PlayerApi.postData(payload).then(function(res){ ... });

    // executes the actions added by the editor(Action Property type).
    c8PlayerApi.executeWidgetPropActions(PROPERTY_KEY)

    // Returns runtime platform (WIDGET_EDITOR, CREATIVE_STUDIO, PLAYER)
    c8PlayerApi.getRuntime();  

    //Events available within widget development environement
      //executes when video starts to play
      c8PlayerApi.on("play", function(){
        console.log("Play Event");
      })

      //executes on video pause
      c8PlayerApi.on("pause", function(){
        console.log("Pause Event");
      })

      //executes when the widget visibility changes on runtime
      c8PlayerApi.on("visibilityChange", function(visible){
        console.log("VisibilityChange Event:", visible)
      })
     
      //executes when the video playback rate changes on runtime
      c8PlayerApi.on("playbackRateChange", function(playbackRate){
        console.log("PlaybackRateChange Event:", playbackRate)
      })
      
      //executes when the video quality level changes on runtime
      c8PlayerApi.on("qualityLevelChange", function(quality){
        console.log("QualityLevelChange Event:", quality)
      })

      //executes when the video enters or exits the fullscreen state on runtime
      c8PlayerApi.on("fullscreenChange", function(fullscreen){
        console.log("FullscreenChange Event:", fullscreen)
      })
     
      //executes when the widget timeline life ends and the player removes the widget from DOM.
      c8PlayerApi.on("widgetDestroy", function(){
        console.log("WidgetDestroy Event")
      })

      //executes when the value of a variable change
      c8PlayerApi.on("variableChange", function(variableName, prevValue, newValue){
        console.log("VariableChange Event:", variableName, prevValue, newValue)
      })




Using 3rd party libraries

You can use the following predefined js libraries in the Javascript code block in the Cinema8 widget development environment.

Predefined Libraries:


Saving & Retrieving Data within widgets



You can use the " postData" and " getData "   methods in Cinema8 Widget API to save data securely at the widget runtime and then query the saved data again. 
  1. c8PlayerApi.postData(payload).then(function(res){
     }); 
    The payload object must be in the key(string) value(string) pair format.

postData Sample 
HTML
  1.      <form class="contact-form-{{uid}}">
          <textarea name="message"></textarea>
          <button type="submit">Send</button>
        </form>
Javascript
  1. function handleFormSubmit(event) {
        event.preventDefault();
        var data = new FormData(event.target); 
        var formJSON = Object.fromEntries(data.entries());
        
        c8PlayerApi.postData(formJSON).then(function(res){
          console.log(res);
        })
      }
      var form = document.querySelector('.contact-form-{{uid}} form');
      form.addEventListener('submit', handleFormSubmit);
     


Stored information can be exported as excel.
      It contains the data kept for all projects using the widget when downloaded from the "Download report" button in the action dropdown in the widget list.
      When downloaded from the "Tracks" tab on the analytics page of the project used, it contains only the data kept for that project.


To access the data stored through the widget we can use  c8PlayerApi.getData() function .

  1. c8PlayerApi.getData().then(function(res){
          console.log(res)
      });
If there is a real user logged in with authToken via the js api with login, the last data entered by the registered user will be returned in the data retrieved with getData.


Timeline integrations 

To access the data of the element (track) added to the layer in the creative studio we can use " c8PlayerApi.getTrackProp " function.
(currently returning; duration, start, end, visible)
 
  1.  // Access widget instance video timeline data ()
      c8PlayerApi.getTrackProps()  // get available track data as list
     // second parameter is default value for development purposes
      c8PlayerApi.getTrackProp('duration', 10) //get the length of the widget(second) instance on timeline 

c8PlayerApi has multiple  'hook' methods that allow you to customize the widget you have developed in parallel with the events that occur at the video runtime. Thanks to these methods, you can detect the state of the video and widget on runtime and trigger actions accordingly.

  1. //Events available within widget development environement ; 

      //executes when video starts to play
      c8PlayerApi.on("play", function(){
        console.log("Play Event");
      })

      //executes on video pause
      c8PlayerApi.on("pause", function(){
        console.log("Pause Event");
      })

      //executes when the widget visibility changes on runtime
      c8PlayerApi.on("visibilityChange", function(visible){
        console.log("VisibilityChange Event:", visible)
      })
     
      //executes when the video playback rate changes on runtime
      c8PlayerApi.on("playbackRateChange", function(playbackRate){
        console.log("PlaybackRateChange Event:", playbackRate)
      })
      
      //executes when the video quality level changes on runtime
      c8PlayerApi.on("qualityLevelChange", function(quality){
        console.log("QualityLevelChange Event:", quality)
      })

      //executes when the video enters or exits the fullscreen state on runtime
      c8PlayerApi.on("fullscreenChange", function(fullscreen){
        console.log("FullscreenChange Event:", fullscreen)
      })
     
      //executes when the widget timeline life ends and the player removes the widget from DOM.
      c8PlayerApi.on("widgetDestroy", function(){
        console.log("WidgetDestroy Event")
      })

      //executes when the value of a variable change
      c8PlayerApi.on("variableChange", function(variableName, prevValue, newValue){
        console.log("VariableChange Event:", variableName, prevValue, newValue)
      })
By using these hooks within your widget, you can develop any kind of animation within a video integrated with the video timeline.


Writing custom handlebar helpers 

You can develop custom handlebars helper methods to use in your HTML code blocks.
To write a Handlebars helper, place your custom codes between the <#Handlebars> ... </Handlebars> tags in the Javascript code block. 
Javascript Code

  1. <#Handlebars>

      Handlebars.registerHelper("loud", function(value) {
        return value.toUpperCase();
      });
       
    </Handlebars>
HTML Code
  1. {{loud 'Lorem ipsum dolor sit amet'}}   // for static usage
  2. {{loud textProperty}} // you can access to properties within this helper method.



Adding Clickable property types;

We can bind a dynamic click action to some property types by selecting the "is clickable" checkbox for each property.
When specifying the HTML element to be clicked for the clickable checkbox prop, the click event should be added as the attribute of the HTML tag to which the click event will be attached data-onclick-ref="PROP_KEY".

"is Clickable?" check box is available for the following property types ; 
  1. Text
  2. Text Area
  3. Image
  4. Text List
  5. Image List
While you can emulate the clickable functionality with an action property type, Clickable functionality is required to implement dynamic clickable list data types; Also when you add clickable to any property type, associating the user-configured action with HTML content and triggering this action will be implemented automatically by the system.

Adding Clickable Property Types



Clickable Property







Studio View


HTML code

  1.  <div>
          <span>Text List</span>
          <div class='text-list'>
          <ul>
            {{#each textList}}
              <li data-onclick-ref="textList">{{this}}</li>
            {{/each}}
          </ul>
          </div>
        </div> 
      <div>
          <span>Image List</span>
          <div class='image-list'>
            {{#each imageList}}
              <img data-onclick-ref="imageList" src='{{this}}'/>
            {{/each}}
          </div>
        </div>



Implementing custom configurable Actions within Widgets.

All the widgets inherit the onClick , onStart and onEnd functions of the cinema8 core element model. Sometimes you may need to implement custom actions other than the inherited onClick action or trigger an action without a click function. In this case, you can create Action variables within the widget properties as shown in the examples below. In this way, you can customize the behavior of the widgets you have developed.
For this we can use the  c8PlayerApi.executeWidgetPropActions(PROPERTY_KEY) method.

Adding Configurable Actions


Action property type







Studio View





Sample usecases ; 
There is an image in the widget and we want to run the actions selected by the video editor when a viewer moves the mouse on this image(onhover).
Javascript Code
 
  1.   $( ".img" ).mouseover(function() {
        c8PlayerApi.executeWidgetPropActions("onImageHover");
      });
In another example, we want to customize the functions that are triggered at the opening and closing moments of an overlay menu.

  1. function openMenu(){
        c8PlayerApi.executeWidgetPropActions("onMenuOpen");
      }
      function closeMenu(){
        c8PlayerApi.executeWidgetPropActions("onMenuClose");
      }


    • Related Articles

    • Creating A Fancy Button Widget - Cyberpunk Glitch Button

      In this article, we will explain step by step how to create and configure a button from scratch. 1- Create the Widget From Widgets Section Open Cinema8 Admin Panel Select Tools Menu Select 8 Widgets Link Select + New Widget Button Give a name to your ...
    • Getting started with C8 API

      Cinema8 APIs to build extensive digital experiences within your videos. Cinema8 has an extensive API to support your business and your customers’ needs while developing interactive video-based solutions. Whether you are developing a web application, ...
    • WebSocket API

      WebSocket powered widget development The WebSocket api within Cinema8 widget development environment allows you to create real-time communication and collaboration tools for your interactive videos. By leveraging websockets, you can create ...
    • Javascript API

      We will explain the basics of how to use the Cinema8 Player JavaScript API component of Cinema8 Player. It uses the same interface for HTML5 video player API and extends it with advanced features. Download js from cdn Download Cinema8 Player ...
    • Widget Development playground

      The following sample video contains the codes that exemplify the methods, property types and usage scenarios used in the widget development environment. . Playground Video Defined Properties for playground HTML Code <div class='c-{{uid}}'> <div ...