Skip to main content

Developing HTML pages containing updatable values

HTML pages containing updatable values

The page must be divided into markup:

<html>
<head>
<meta charset="utf-8" />
</head>

<body>
Temperature in Moscow: <span id="temperature"></span> °C

<script>
window.setData = function(data) {
document.getElementById("temperature").innerHTML = data["temperature"];
}
</script>
</body>
</html>

And data:

{
"temperature": -14
}

The player will call the setData function in the context of the page when it is first displayed (by the onload event), and also when the data is updated.

The page should not contain links to external resources, all of them should be packed together with it. Data may contain links to external resources, but they must be formatted in a special way. For example, instead of:

{
"temperature": -14,
"icon": "https://yastatic.net/weather/i/icons/blueye/color/svg/ovc.svg"
}

You must send:

{
"temperature": -14,
"icon": {"$playback-data-resource": "https://yastatic.net/weather/i/icons/blueye/color/svg/ovc.svg"}
}

The player will download external resources to its storage and replace the resource URI:

{
"temperature": -14,
"icon": "file:///visiobox/tmp/playback-data/resources/yastatic.net/weather/i/icons/blueye/color/svg/ovc.svg"
}

External resources are cached indefinitely on the player.

Recommendations for HTML page layout for Windows and Android

Resizing. Different resolutions

If the layout is static, there may be output problems. In this case, you need to take care of the proportional size of the page content. Therefore, we recommend adding a script that will solve this problem. One of the JS script options:

const BASE_WIDTH = 1920;
const BASE_HEIGHT = 1080;

function resize(){
kx = window.innerWidth/BASE_WIDTH;
ky = window.innerHeight/BASE_HEIGHT;
document.body.style.webkitTransform = 'scale('+ kx + ',' + ky +')';
document.body.style.transform = 'scale('+ kx + ',' + ky +')';
}

function ready() {
window.addEventListener("resize", resize);
resize();
}

document.addEventListener("DOMContentLoaded", ready);

Despite the fact that the script contains constants that are designed for Full HD, the output will be correct even in portrait orientation. This is due to the fact that the player places objects on a 1920x1080 grid regardless of orientation. If your device is of a different format, distortion will be observed if the content size does not match the display resolution.

NOTE! To correctly format the output in the script, you need to take into account that the size changes relative to the Full HD display.

Time

If the layout/application is related to time, then you need to understand that the time in the browser is the system time of the device. The device may have the wrong time. The issue of time accuracy must be resolved at the layout/application level. One option is to adjust the time. It is best to set the exact time on the device. You can also adjust the time when calling the setData() method, in addition to the data, two numbers are passed to this method: the exact time in the device's time zone and in UTC. An example of working with the method:

    function setData(data, now, utcNow){
console.log({data, now, utcNow});
}

Outdated data

The player always displays data, if the data is not updated, the latest known data is taken. It may happen that the data has become outdated, and new data has not arrived (no connection with the source or other problems). In this case, we recommend monitoring this by setting the data lifetime. This information can be sent from the data server or a known value can be stored in the layout. The check can be performed by a timer or when calling the setData() function.

NOTE! do not lose sight of the time issue

Libraries and resources

There are no restrictions. However, we recommend placing all the necessary resources next to the layout so that nothing is loaded over the network.


Oohdesk CMS applications (embedded in the marketplace)

Attention! Applications can be embedded in the marketplace only after pre-moderation by Oohdesk CMS specialists

The VisioBox application is a regular HTML page containing the setData function, called by the player after loading the application, as well as when updating the data on the page. The function has one argument — data, which looks like:

{
options: {
// Application settings
color: "red",
fontSize: "14px",
username: "XiaoMi"
},
data: {
// Data displayed in the application
profile: {
location: "Russia, Moscow"
},
repos: [
{
name: "mace"
}
]
}
}

In addition, the application contains a manifest, which describes the application settings and the URL from which it will collect data.

Example application:

<html>
<head>
<meta charset="utf-8" />

<script id="manifest" type="application/json">
{
"name": "example",
"version": 1,

"title": "Example application",
"description": "",

"options": [
{
"title": "Color",
"name": "color",
"type": "choice",
"options": {
"choices": [
["red", "Красный"],
["green", "Синий"]
]
},
"example": "red"
},
{
"title": "Font size",
"name": "fontSize",
"type": "text",
"options": {},
"example": "14px"
},
{
"title": "Username GitHub",
"name": "username",
"type": "text",
"options": {},
"example": "Xiaomi"
}
],
"playback_data": {
"profile": {
"url": "'https://api.github.com/users/' .. options['username']",
"interval": 3600
},
"repos": {
"url": "'https://api.github.com/users/' .. options['username'] .. '/repos'",
"interval": 300
}
},

"preview": {
"width": 1920,
"height": 1080
}
}
</script>
</head>
<body>
<div id="text"></div>

<script>
var div = document.getElementById("text");

window.setData = function(data) {
div.style.color = data.options.color;

div.innerHTML = 'Hi, I live in ' + data.data.profile.location + ' and work on ' + data.data.repos[0].name;
}
</script>
</body>
</html>

Debugging applications

Add the following code before </body>:

<script id="application-debug" src="https://testing.visiobox.cloud/utils/application-debug.js" data-access-token="YGc7uf5Agi5LRc6yaE8dcQIuZh0HCX7g"></script>

After the page loads, the setData function will be called with the required parameters. You can override the default application settings:

<script id="application-debug" src="https://testing.visiobox.cloud/utils/application-debug.js" data-access-token="YGc7uf5Agi5LRc6yaE8dcQIuZh0HCX7g" data-options='{"username": "torvalds"}'></script>

RSS

Example of an application using RSS

<html>
<head>
<meta charset="utf-8" />

<script id="manifest" type="application/json">
{
"name": "rss-example",
"version": 1,

"title": "Example of an application that outputs news from RSS",
"description": "",

"options": [
{
"title": "URL",
"name": "url",
"type": "url",
"options": {},
"example": "http://static.feed.rbc.ru/rbc/logical/footer/news.rss"
}
],

"playback_data": {
"url": "options['url']",
"format": "rss",
"interval": 300
},

"preview": {
"width": 1920,
"height": 1080
}
}
</script>
</head>
<body>
<div id="text"></div>

<script>
var div = document.getElementById("text");

window.setData = function(data) {
var s = "";
for (var i = 0; i < data.data.entries.length; i++) {
s += '<h1>' + data.data.entries[i].title + '</h1>' + (data.data.entries[i].summary || "");
}
div.innerHTML = s;
}
</script>
</body>
</html>

Animations (this option is relevant if you need to start an animation when HTML starts showing)

The player loads applications a few seconds before they are displayed on the screen, so that everything has time to load. If the application has any animations, they should be launched not when the page opens, but when the visio-ready event is received:

<html>
<head>
<script>
window.addEventListener('visio-ready', function() {
document.body.style.backgroundColor = '#ff0000';
});
</script>
</head>
<body style="background-color: #000000;">
</body>
</html>

Playback reports

In order to attach some data to the playback report, you can use the setOutput function:

setOutput("scene_1")

Example: there is HTML that contains many scenes. Each scene is launched depending on the trigger conditions that are embedded in the layout logic. In order to keep track of the playback statistics of each scene, for one pass setOutput("scene_1"), for another setOutput("scene_2"), etc. (depending on the number of scenes)