HTML content scheduling

You are here:

The following article describes the best practices for creating HTML content for Admira Player HTML5.

Disclaimer

The HTML content playback engine may vary depending on the player’s platform. Thus, a player running on WebOS will use a certain version of Webkit depending on the firmware, Windows will run on another, some platforms do not accept Flash plugins, etc.

Admira is constantly working on the list of each of the particularities for each platform, operating system or firmware. In general, most platforms in their latest versions (WebOS 4.0+, Tizen / SSSP5 +, Windows, Linux NWJS 0.17.6 and Android) run with Chrome v53.

For specific needs, you can contact support@admira.com for more information. We recommend, once the engine where the content is going to run, has been identified, review the requirements from the web www.caniuse.com. Tools like https://babeljs.io/repl can be helpful in making the JS compatible.

Limitations

File structure

The current file structure for playback on HTML5 player limits the use of subfolders, any file necessary for the HTML content must remain in the same folder as this, including files: css, js, png, jpg, mp4, ogg, etc…

In other words, the structure would be:

  • main_12345.html
  • script_12345.js
  • image_12345.png
  • style_12345.css
  • ….

Not being able to use subfolders makes the correct naming of files essential, each content being a unique file with its associates also unique. The example uses “12345” to uniquely identify the content.

Important

Attached script file names cannot contain "." That is, it is not accepted: "socket.io.js" It must be uploaded renamed to "socket_io.js"

Good Practices

Important

You must use exception control with try / catch. Unhandled exceptions could disable the HTML5 player in some of its functions. If errors occur that may impair the normal performance of the player, Admira will not be held responsible for the consequences. 

Iframe

The execution of contents or WebApps occurs within a sandboxed <iframe> HTML TAG. This iframe sandbox contains the following enabled permissions: 

  • allow-forms Re-enables form submission
  • allow-pointer-lock Re-enables APIs
  • allow-same-origin Allows the iframe content to be treated as being from the same origin
  • allow-scripts Re-enables scripts

By cons are not allowed: 

  • top-navigation; (that is, you can only use “_self” in target links)
  • popups

Access to external resources

Each casuistry is different. In the case of wanting to access resources from other “sites”, the execution policies from an <iframe> must be taken into account. This means that options such as X-Frame-Options or CORS must be set correctly on the server to which we want to make the request. In short, the WebApps that we want to run in admira <iframe> do not run as in a browser, but rather in an “unattended window”. 

ASYNC requests

It is important to note that any request made either abroad (url on the internet) or locally (file in filesystem) must be done ASYNCRONA, since the HTML content shares THREAD of execution with the player. Therefore, in the case of a SYNC request, the player would stop until the request was finished. This can cause serious problems in the execution of player. Therefore, ALL requests must be made ASYNCRONO, just as any execution of SYNCRONO blocking code must be avoided so that it does not cause an unusual stop to the player.

On this website we can simulate request blocking:

http://slowwly.robertomurray.co.uk/delay/3000/url/http://api.admira.com

Where 3000 is the delay in milliseconds.

Admira API Content HTML5

Admira API content HTML5 is the service available to communicate from HTML content to the Admira player via Javascript. The basic functions of this API are described below.

In order to use the Admira API Content HTML5 functionalities, you need the script, provided by Admira. 

Once added as an attachment and included in the main HTML, it can be invoked as follows: 

<script>
var api_obj = null;

function on_load(){
    api_obj = new admira_api_content();
    api_obj.onReady = function(){
        console.log(«Ready !»);
    };
    api_obj.onStart = function(){
        console.log(«Start !»);
    };
}
</script>
<body onLoad=”on_load();”>
…

Events

The basic events of API Content are explained here.

  • onReady: occurs when the player has successfully preloaded the HTML content, that is, the HTML has been loaded into the iFrame. At this point the iFrame is still on DISPLAY: NONE
  • onStart: it occurs when the player puts the content on “PLAY”. Any animation or playback of elements must start here. At this point the iFrame is still on DISPLAY: INLINE

Functionalities

API content also allows to send messages to HTML5 player to indicate different actions to perform:

  • API_DURATION: Changes the duration of the content that is being reproduced
  • API_FINISH: Finish the content that is being played
  • API_CONDITION: Write a condition to be read later by the player with the capabilities of Conditional Playlist and Condition Triggers
  • API_WRITE_FILE: It allows writing text data to a local file
  • API_READ_FILE: Allows to read a local text file

Note

These functionalities are in constant development and improvement. For any question, do not hesitate to report to support@admira.com.

Note

For app versions lower than z19.05.30, when you want to get the player's id, it is necessary to put the call inside onStrat. For versions after z19.05.30, it is included, it can be put inside onReady. Below is an example of how the player's id should be requested in both cases.

Application version prior to z19.05.30

my_api.onReady = function(){
    console.log("Ready !”);
};

my_api.onStart = function(){

console.log(“onStart”);

my_api.send("api_command",{command:my_api.API_PLAYER_INFO,params:{'callback':"onGetInfo"}});

};

Application version equal to or greater than z19.05.30

my_api.onReady = function(){
    console.log("Ready !”);

    my_api.send("api_command",{
        command:my_api.API_PLAYER_INFO,params:{
        'callback':"onGetInfo"
            }
        });
    };

    my_api.onStart = function(){

    console.log(“onStart”);
};

Function examples

# API_DURATION:

api_obj.send("api_command",{
    command:api_obj.API_DURATION,
    params: {
        duration:30
    }
});

→ It will change the duration, where 30 is the number of seconds from the moment of the API call.

# API_FINISH:

api_obj.send("api_command",{
    command:api_obj.API_FINISH
});

→ Finish content immediately.

# API_CONDITION:

var condition_object = {
    'id': ‘01’,
    'filename': ‘internet_connected.xml’,
    'value':1,
    ‘write’:true
};

api_obj.send("api_command",{
    command:api_obj.API_CONDITION,
    params:condition_object
});

→ It will write the value of the condition for “Internet Connected”.

# API_WRITE_FILE:

var file_object = {
    'path': ‘./log’,
    'filename': ‘hello.txt’,
    'text':’ Hello World !’
};

api_obj.send("api_command",{
    command:api_obj.API_WRITE_FILE,
    params:file_object
});

→ It will write “Hello World!“ in ./content/hello.txt

# API_READ_FILE:

function onFileReadComplete(data){
    console.log("HTML onFileReadComplete data : "+data);
}

var file_object = {
    'path': ‘./log’,
    'filename': ‘hello.txt’,
    'callback': ‘onFileReadComplete’
};

api_obj.send("api_command",{
    command:api_obj.API_READ_FILE,
    params:file_object
});

→ It will read ./content/hello.txt and send the result to the callback: onFileReadComplete

# API_PLAYER_INFO:
**Complete example get player_id and use it (app versions lower than z19.05.30)

<script>

my_api = new admira_api_content();

var started = false;
var playerId = 0;

if (typeof(Storage) !== "undefined") {
    playerId = localStorage.getItem("playerID");
    myFunction(playerId);
}

if(playerId == 0){
    //Cuando inicia el player (Carga el HTML)
    my_api.onReady = function () {
        setTimeout(function(){my_api.onStart()},time);
    };

    //Cuando emite el HTML
    my_api.onStart = function () {
        clearTimeout(time)
        if(!started){
            my_api.send("api_command", { 
                command: my_api.API_PLAYER_INFO, params: { 'callback': "onGetInfo" 
                } 
            });
        }
    started = true;
    };
    
    my_api.onEvent = function (e) {
        if (started) {
         if (e.action == my_api.API_PLAYER_INFO) {
                if (typeof (e.msg.callback) !== "undefined") {
                    eval(e.msg.callback)(e.msg.data);
                }
            }
        }
    };
}


function onGetInfo(data) {
    try {
        if (data) {
            if (data.PlayerController && data.PlayerController.player_id) {
                playerId = data.PlayerController.player_id;
                localStorage.setItem("playerID", playerId);
                myFunction(playerId);
            }
        }
    }
    catch (e) {
        document.getElementById("contenedor").innerHTML = e;
    }
};

</script>
# API_PLAYER_INFO:
**Complete example get player_id and use it (app versions equal to or higher than z19.05.30)

<script>

my_api = new admira_api_content();

var started = false;
var playerId = 0;
var time = 2000;

if (typeof(Storage) !== "undefined") {
    playerId = localStorage.getItem("playerID");
    myFunction(playerId);</p>
}

if(playerId == 0){
    //Cuando inicia el player (Carga el HTML)
    my_api.onReady = function () {
        my_api.send("api_command", { 
            command: my_api.API_PLAYER_INFO, params: { 
                'callback': "onGetInfo" 
            }
        });
    };

    //Cuando emite el HTML
    my_api.onStart = function () {
        started = true;
    };
    my_api.onEvent = function (e) {
        if (started) {
            if (e.action == my_api.API_PLAYER_INFO) {
                if (typeof (e.msg.callback) !== "undefined") {
                    eval(e.msg.callback)(e.msg.data);
                }
            }
        }
    };
}

function onGetInfo(data) {
    try {
        if (data) {
            if (data.PlayerController && data.PlayerController.player_id) {
                playerId = data.PlayerController.player_id;
                localStorage.setItem("playerID", playerId);
                myFunction(playerId);
            }
        }
    }
    catch (e) {
        document.getElementById("contenedor").innerHTML = e;
    }
};
</script>

Nomenclature

FileRequired base files: 

  • PROJECTID_H0001.html (the base HTML)
  • PROJECTID_H0001.xml (xml that contains the attachment data and fastcontent settings)
  • PROJECTID_H0001.css (style file that will be applied to the fastcontent)
  • Attachment_1.png (can have any file name)
  • Attachment_2.mp4 (can have any file name)

(IT IS RECOMMENDED TO EMBED THE CODE OF ANY JS FILE DIRECTLY INTO THE HTML TO AVOID COLLISIONS BETWEEN FILES) 

XML Structure 

To see an example of XML for Fastcontent (HTML / SWF), see in this repo.

Basic HTML structure for template

The fastcontent HTML is distributed in the following sections: 

### HEAD

Global for all Fastcontent.

<style>
/* FASTCONTENT GLOBALS */

body { 
    margin: 0 0 0 0; 
    font-family: sans-serif;
}

#chrome_flags{ 
    background-color: #c33e3e; 
    width: 100%; 
    height: 100%; 
    text-align: center; 
    font-size: 1vw;
}

#chrome_flasgs_inner{ 
    padding: 20px; 
    background-color: #AAAAAA;
    margin-left: 20%; 
    width: 60%; 
    text-align: left; 
    font-size: 1vw;
}

#chrome_info{ 
    background-color: #228a33db;
    width: 100%; 
    height: 100%; 
    text-align: center; 
    font-size: 1vw;
}

.image{
    width:100%;
    height: 100%;
}

.video{
    width:100%;
    height: 100%;
    object-fit: fill
}

.shape{
    width:100%;
    height: 100%;
}

</style>
### FASTCONTENT UNIVERSAL SCRIPT

This script must be copied from the repo provided above.

<!-- FASTCONTENT HTML5 GENERIC UNIVERSAL SCRIPT - INCLUDES CONTENT & JQUERY API -->

<script>
    …… (add the repo code here)

</script>>
### FASTCONTENT CUSTOMIZATION

<!-- SPECIFIC SCRIPT FOR THIS CONTENT -->

<script>
    …… (add here the specific code for the fastcontent)

</script>
### CUSTOMIZATION EVENTS IN RELATION TO PLAYER

<!-- ADDITIONAL SCRIPTS TO BE EXECUTED AT THE MOMENT OF RENDERING (PLAY) OF THE CONTENT -->

<!-- the event onRender will fire when the player plays the content -->

<script>

function onRender(slide_index){
    console.log("Fastcontent is rendering slide : "+slide_index);
    ...(add here the necessary code to be executed when the player triggers the content)
}

</script>
### BODY

Create the necessary and correctly set variables that will be reflected in the XML.

<div id="background" class=""> </div>
<div id="product" class="text"> </div>
<div id="image"> </div>
<div id="price" class="text" style="opacity: 0;"> </div>
<div id="description" class="text"> </div>
<div id="promo"> </div>

URL contents

In cases where it is required to load a web page as content on the player and its preload affects the emission of its elements, a content has been created so that this load is compatible with the Admira player. The content is made up of a series of files, including access with the player’s api, for loading the content according to its broadcast. In one of them we must add the URL that we want to emit and upload the content as HTML + attachments.

Example:

Content

You can request the content from the department at qa@admira.com.

Once we have the content, we just have to open thefile variables.json

Variables

And then modify the URL for the one of the content that we want to upload.

Once this is done, we must upload the content to the platform as HTML + attachments.

Print Friendly, PDF & Email
Previous Best practices for content creation
Table of Contents