[:en]Signage Application Basics[:fr]Notions de base sur les applications de signalisation[:] | VESTEL B2B Support Portal

[:en]Signage Application Basics[:fr]Notions de base sur les applications de signalisation[:]

[:en]Signage Application Basics[:fr]Notions de base sur les applications de signalisation[:]

[:en]

In this tutorial we will make a scheduling application for Visual Solution clients. The application is basically a digital signage application in which it is possible to set layouts with different content and play them with a schedule. Application contains two basic schedule samples. One of them is a video, image and text layout and the other one is a image slider.

In order to run the application on Visual Solution clients, please extract the BasicScheduling.rar file, place the folder inside a server and simply configure the HTML code as a “starturl”. Starturl configuration for Visual Solution clients is explained on this Client Startup Guide-Overview document.

Application consists of threads and each thread has its own purpose. The threads and the inital page is as follows;

  • Initial HTML Code: The page that needs to configured as “starturl” to visual solution device. Initiates all the application.
  • Init.js: The file that starts the application with the given test datas.
  • LayoutManager.js: The file that consists of the layout functions such as creating,adding etc.
  • CustomDownloadManager.js: The file that consists of functions that runs the download processes.
  • ScheduleManager.js: The file that consists of schedule functions such as creating,removing etc.
  • Models.js: The file that plays the given layouts and schedules due to its scenarios.
  • TestData.js: The file that consists of the test datas and starts the test procedure.

In the following sections the Javascript codes for each thread and the initial HTML code will be shown and explianed.

Initial HTML Code

You could find the initial HTML page below. All the other Javascript files will be explained in the following sections.

As seen from the code below the external Javascript files are written for each thread and download lists are created. Afterwards the init() function is called which is the thread that starts the all application.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<link href="Schedule.css" rel="stylesheet" />
<script src="jquery-2.2.4.min.js"></script>
<script src="TestData.js"></script>
<script src="CustomDownloadManager.js"></script>
<script src="ScheduleManager.js"></script>
<script src="LayoutManager.js"></script>
<script src="Models.js?v=1"></script>
<script src="Init.js"></script>

<title></title>
</head>
<body>
<div id="defaultscreen"></div>
<div id="layout"></div>
<div id="root"></div>
<script type="text/javascript">
var downloadList;
var activeDownloadList;
$(document).ready(function () {
downloadList = new DownloadList();
activeDownloadList = new DownloadList();
init();
});
</script>
</body>
</html>

Schedule CSS

CSS code for the application is below.

body {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    top: 0;
    left: 0;
}

#defaultscreen {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    top: 0;
    left: 0;
    background-image: url('Vsign.jpg');
    background-size: cover;
    z-index: 100;
}

#layout {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    top: 0;
    left: 0;
    visibility: hidden;
}

In the following sections each of the external Javascript codes will be shown and explained.

Init.js

The application starts with the function init() which is defined in init.js file. Basically what this file do is to check the available storages and the active schedules. If there is an available storage and no active schedule, the code starts to create a schedule and a layout by using the given test datas.

This file also contains some Javascript plug-ins which are specially created for our TVs. For additional information and sample usage of these plug-ins, you could find necessary information on our HTML APP Supported Functionalities document.

var currentLayout;
var currentSchedule;
var pathToDownload;
var mediaInfos;
function init() {
    var availableStorageList = window.StorageManager.getListOfAvailableStorages();
    if (availableStorageList !== null) {
        StartScheduling();
    } else { console.log("No removable disk is plugged") };
};

function StartScheduling() {
    if (ScheduleManager.CheckActiveSchedules().length === 0)
        TestData.StartTest();
    currentSchedule = ScheduleManager.CheckActiveSchedules()[0];
    currentLayout = LayoutManager.GetlayoutById(currentSchedule.layoutId);

    mediaInfos = LayoutManager.GetMediaInfo(currentLayout.layout[0]);
	pathToDownload = window.StorageManager.getListOfAvailableStorages()[0].path + "vsign/";
    ScheduleManager.SetSchedule(currentSchedule);
}

CustomDownloadManager.addEventListener('downloadStateChange', function (url, status, destination, errorMessage) {

	switch (status) {
        case window.CustomDownloadManager.DOWNLOAD_COMPLETED:
            {
                downloadList.setDestinationOfDownload(url, destination);
                console.log('downloadCompleteEvent recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                if (activeDownloadList.getDownloadListLength() < 1) {
                    console.log("GenerateLayout Funtion Called");
                    LayoutManager.GenerateLayout(currentLayout);
                }
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_IN_PROGRESS:
            {
                console.log("Is in progress: ", window.CustomDownloadManager.isInProgress(destination));
                activeDownloadList.addDownload(new DownloadObject(url, destination));
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_CANCELED_BY_USER:
            {
                console.log("User canceled");
                console.log('downloadUserCanceled event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_FILE_WRITE_ERROR:
            {
                console.log('File Write Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_FILE_CREATION_ERROR:
            {
                console.log('File Creation Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_LOCAL_ERROR:
            {
                console.log('Local Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_REMOTE_ERROR:
            {
                console.log('Remote Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_NETWORK_ERROR:
            {
                console.log('Network Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_FAILED:
            {
                console.log('Download Failed Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        default:
            {
                console.log('unknown event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
            }
    }
    reloadActiveDownloads();
}
            );

StorageManager.addEventListener("mediaFileReadProgressEvent", function (myArray) {
    LayoutManager.StartDownloadProcesses(myArray);

});

StorageManager.addEventListener("removableDeviceConnected", function () {
    console.log("removable disk connected!");
    StartScheduling();
});

StorageManager.addEventListener("removableDeviceDisconnected", function () {
    console.log("removable disk disconnected!");
    lModel.ClearLayout();
    $('#defaultscreen').show();
});

function CheckFile(nameKey, myArray) {
    for (var i = 0; i < myArray.length; i++)
        if (myArray[i].name === nameKey)
            return true;
    return false;

The init.js file also sets the possible outcomes for downloading status. CustomDownloadManager is of the plug-ins written specifically for our clients and it is used to download a file from a url to a specific destination.

LayoutManager.js

LayoutManager.js file specifies the functions which can be used for the layouts(adding, removing, generating etc.). If the test procedure is started by init.js, by using the functions on LayoutManager.js the test datas are added to layouts and digital signage scenario is demonstrated.

var lModel = null;
var LayoutManager = {
    AddLayout: function (layout) {
        try {
            var allLayouts = [];
            var lStorageLayouts = JSON.parse(window.localStorage.getItem("layouts"));
            if (lStorageLayouts !== null)
                allLayouts = lStorageLayouts;

            allLayouts.push(layout);
            window.localStorage.setItem("layouts", JSON.stringify(allLayouts));
        } catch (e) { }
    },
    RemoveLayout: function (layout) {
        try {
            var allLayouts = [];
            var lStorageLayouts = JSON.parse(window.localStorage.getItem("layouts"));
            if (lStorageLayouts !== null)
                allLayouts = lStorageLayouts;

            allLayouts.removeValue("id", layout.id);
            window.localStorage.setItem("layouts", JSON.stringify(allLayouts));
            LayoutManager.RemoveLayoutContent(layout);
        } catch (e) { }
    },
    RemoveLayoutContent: function (layout) {
        var layoutMedias = LayoutManager.GetMediaInfo(layout.layout[0]);
        for (var i = 0; i < layoutMedias.length; i++) {
            console.log(layoutMedias.filename[i].filename + " deleted from: " + pathToDownload);
            window.StorageManager.delete(pathToDownload + layoutMedias[i].filename);
        }
    },
    GetlayoutById: function (id) {
        var allLayouts = JSON.parse(window.localStorage.getItem("layouts"));
        if (allLayouts !== null)
            for (var i = 0; i < allLayouts.length; i++)
                if (allLayouts[i].layout[0].id === id.toString()) return allLayouts[i];
        return "";
    },
    GetMediaInfo: function (layout) {
        var result = [];
        for (var i = 0; i < layout.region.length; i++)
            for (var j = 0; j < layout.region[i].media.length; j++) {
                if (layout.region[i].media[j].options && layout.region[i].media[j].type !== "text")
                    result.push(layout.region[i].media[j].options);
            }
        return result;
    },
    GenerateLayout: function (layout) {
        //var layoutElement = document.getElementById("layout");
        $('#defaultscreen').hide();
        if (lModel === null) {
            lModel = new LayoutModel(layout);
            lModel.Init();
        } else {
            lModel.SetNewLayout(layout);
        }
    },
    CheckMediaFilesOnDisk: function (path) {
        var makeDir = window.StorageManager.makeDir(path);

        if (makeDir === window.StorageManager.DirAlreadyExists || makeDir === window.StorageManager.NoError)
            var list = window.StorageManager.listFiles(path);
        if (list === 1)
            LayoutManager.StartDownloadProcesses([]);

    },
    SetDefaultLayout: function () {
        console.log("no vailable schedules, returning to default layout");
        $('#defaultscreen').hide();
        window.currentLayout = TestData.GetDefaultLayout();
        window.mediaInfos = LayoutManager.GetMediaInfo(window.currentLayout.layout[0]);
        var makeDir = window.StorageManager.makeDir(pathToDownload);
        if (makeDir === window.StorageManager.DirAlreadyExists || makeDir === window.StorageManager.NoError)
            LayoutManager.CheckMediaFilesOnDisk(pathToDownload);
    },
    StartDownloadProcesses: function (myArray) {
        if (CheckDownloadPossible() === window.CustomDownloadManager.DOWNLOAD_POSSIBLE) {
            for (var i = 0; i < mediaInfos.length; i++) {
                if (myArray.length === 0) {
                    downloadList.addDownload(new DownloadObject(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename));
                    window.CustomDownloadManager.registerDownloadURL(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename);
                    window.CustomDownloadManager.getDownloads();
                }
                else if (!CheckFile(mediaInfos[i].filename, myArray)) {

                    downloadList.addDownload(new DownloadObject(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename));
                    window.CustomDownloadManager.registerDownloadURL(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename);
                    window.CustomDownloadManager.getDownloads();
                }
            }

            if (activeDownloadList.getDownloadListLength() < 1) {
                console.log("GenerateLayout Funtion Called");
                LayoutManager.GenerateLayout(currentLayout);
            }
        }
    }
};

Array.prototype.removeValue = function (name, value) {
    var array = $.map(this, function (v, i) {
        return v[name] === value ? null : v;
    });
    this.length = 0; //clear original array
    this.push.apply(this, array); //push all elements except the one we want to delete

CustomDownloadManager.js

CustomDownloadManager.js file specifies the functions about downloading process and these functions are used to download the content to storages if any available. Also functions such as canceling download, checking whether download is possible or not are placed under this file.

On checking process the file also checks that if there is enough space on the storage device.  If not, the download fails and a warning is shown.

// Download Abstraction
// List of download objects
// URL is used as a handle
var DownloadList = function () {
    var list = [];

    this.addDownload = function (downloadObject) {
        for (var i = 0; i < list.length; i++) {
            if (downloadObject.getDestination() === list[i].getDestination()) {
                return;
            }
        }
        list.push(downloadObject);
    };

    this.removeDownload = function (destination) {
        for (var i = 0; i < list.length; i++) {
            if (destination === list[i].getDestination()) {
                list.splice(i, 1);
                break;
            }
        }
    }
    this.getDownloadListLength = function () {
        return list.length;
    };

    this.getDownloadObjectByIndex = function (index) {
        return list[index];
    };

    this.setDestinationOfDownload = function (url, destination) {
        for (var i = 0; i < list.length; i++) {
            if (list[i].getUrl() === url) {
                list[i].setDestination(destination);
            }
        }
    };

    this.getUrlOfDownloadByDestination = function (destination) {
        for (var i = 0; i < list.length; i++) {
            if (list[i].getDestination() === destination) {
                return list[i].getUrl();
            }
        }
        return null;
    };

    this.getDownloadItselfByDestination = function (destination) {
        for (var i = 0; i < list.length; i++) {
            if (list[i].getDestination() === destination) {
                return list[i].getUrl();
            }
        }
        return null;
    }
}
// Single download object abstraction
var DownloadObject = function (url, destination) {
    var uri = url;
    var dest = destination;

    this.getUrl = function () {
        return uri;
    };

    this.getDestination = function () {
        return dest;
    };

    this.setDestination = function (d) {
        dest = d;
    };
}

function CancelDownload() {
    window.CustomDownloadManager.remove(downloadList.getDownloadObjectByIndex(0).getDestination());
}

function CancelAllDownloads() {
    for (var i = 0; i < activeDownloadList.getDownloadListLength() ; i++) {
        window.CustomDownloadManager.remove(activeDownloadList.getDownloadObjectByIndex(i).getDestination());
    }
}

function isInProgressFirst() {
    var downloadObject = downloadList.getDownloadObjectByIndex(0);
    if (typeof downloadObject == "undefined") {
        console.log("Please insert a USB Storage and then reload the page!");
    }
    else {
        console.log("isInProgress called for first download! Result: " + window.CustomDownloadManager.isInProgress(downloadObject.getDestination()));
    }
}

function deleteFile(index) {
    var destination = downloadList.getDownloadObjectByIndex(index).getDestination();
    console.log(+ "destination is being deleted!!! Result: " + fs_error(window.StorageManager.delete(destination)));
}

function CheckDownloadPossible() {
    var myArray = window.StorageManager.getListOfAvailableStorages();
    if (myArray === null) {
        console.log("No mounted removable device is found!");
        return 0;
    }
   
    for (var i = 0; i < myArray.length; i++) {

        var sizeInGigaBytes = 1;
        var sizeInBytes = sizeInGigaBytes * 1024 * 1024 * 1024;
        var isPossible = window.CustomDownloadManager.checkDownloadPossible(myArray[i].path, sizeInBytes);
        switch (isPossible) {
            case window.CustomDownloadManager.DOWNLOAD_POSSIBLE:
                {

                    console.log("Download is possible. There is enough space for " + sizeInGigaBytes + "GB.");
                    break;
                }
            case window.CustomDownloadManager.DOWNLOAD_INSUFFICIENT_STORAGE:
                {

                    console.log("Download is NOT possible due to insufficient storage. " +
                "There is NOT enough space for " + sizeInGigaBytes + "GB");
                    break;
                }
            default:
                {

                    console.log("Storage not available.");
                }
        }

        return isPossible;
    }
};

ScheduleManager.js

ScheduleManager.js file contains schedule functions such as adding,removing and setting schedules. The application initially stores two schedules and by these schuedles the test layouts are played.

var ScheduleManager = {
    CurrentScheduleIndex: 0,
    CheckActiveSchedules: function () {
        var result = [];
        var allSchedules = JSON.parse(window.localStorage.getItem("schedules"));
        if (allSchedules !== null)
            for (var i = 0; i < allSchedules.length; i++) { if (Date.parse(allSchedules[i].endTime) > new Date())
                    result.push(allSchedules[i]);
            }
        return result;
    },
    IsScheduleActive: function (schedule) {
        if (Date.parse(schedule.endTime) > new Date()) {
            //console.log("next schedule is active");
            return true;
        } else {
            console.log("schedule" + schedule.id + " is expired");
            return false;
        }

    },
    AddSchedule: function (schedule) {
        try {
            var allSchedules = [];
            var lStorageSchedules = JSON.parse(window.localStorage.getItem("schedules"));
            if (lStorageSchedules !== null)
                allSchedules = lStorageSchedules;
            allSchedules.push(schedule);
            window.localStorage.setItem("schedules", JSON.stringify(allSchedules));
        } catch (e) { }
    },
    RemoveSchedule: function (schedule) {
        try {
            console.log("schedule: " + schedule.id + "is deleted!!!");
            var allSchedules;
            var lStorageSchedules = JSON.parse(window.localStorage.getItem("schedules"));
            if (lStorageSchedules !== null) {
                allSchedules = lStorageSchedules;
                allSchedules.removeValue("id", schedule.id);
                window.localStorage.setItem("schedules", JSON.stringify(allSchedules));
                //LayoutManager.RemoveLayout(window.currentLayout);
                ScheduleManager.SetNextSchedule();
            }
        } catch (e) { }
    },
    GetScheduleById: function (id) {
        var allSchedules = JSON.parse(window.localStorage.getItem("schedules"));
        for (var i = 0; i < allSchedules.length; i++)
            if (allSchedules[i].id === id.toString()) return allSchedules[i];
        return "";
    }, GetNextSchedule: function () {
        var activeSchedules = ScheduleManager.CheckActiveSchedules();
        ScheduleManager.CurrentScheduleIndex = (ScheduleManager.CurrentScheduleIndex + 1) % activeSchedules.length;
        return activeSchedules[ScheduleManager.CurrentScheduleIndex];
    }, SetNextSchedule: function () {
        if (ScheduleManager.CheckActiveSchedules().length !== 0) {
            var nextSchedule = ScheduleManager.GetNextSchedule();
            if (ScheduleManager.IsScheduleActive(nextSchedule)) {
                var nextlayoutId = nextSchedule.layoutId;
                window.currentLayout = LayoutManager.GetlayoutById(nextlayoutId);
                window.mediaInfos = LayoutManager.GetMediaInfo(window.currentLayout.layout[0]);
                LayoutManager.CheckMediaFilesOnDisk(pathToDownload);
            }
        } else {
            LayoutManager.SetDefaultLayout();
        }
    },
    SetSchedule: function (schedule) {
        if (ScheduleManager.IsScheduleActive(schedule)) {
            window.currentLayout = LayoutManager.GetlayoutById(schedule.layoutId);
            window.mediaInfos = LayoutManager.GetMediaInfo(window.currentLayout.layout[0]);
            LayoutManager.CheckMediaFilesOnDisk(pathToDownload);
        }
    }
};

function Schedule(id, layoutId, startDate, endDate) {
    var base = this;
    this.id = id;
    this.layoutId = layoutId;
    this.startTime = startDate;
    this.endTime = endDate;
    this.checkExpire = function () {

        this.expireControlInterval = setInterval(function () {
            if (ScheduleManager.IsScheduleActive(base))
                return;
            else {
                ScheduleManager.RemoveSchedule(base);
                clearInterval(base.expireControlInterval);

            }
        }, 1000);
    };
};
// ReSharper disable once NativeTypePrototypeExtending
Array.prototype.removeValue = function (name, value) {
    var array = $.map(this, function (v) {
        return v[name] === value ? null : v;
    });
    this.length = 0; //clear original array
    this.push.apply(this, array); //push all elements except the one we want to delete
}

Models.js

In Models.js file layout models are created based on the generic layout model data type which are initially set on TestData.js. After creating these models prototype playing scenarios have been made.

var LayoutModel = function (layoutData) {
    this.SlideEffects = [];
    this.layoutIndex = 0;
    this.clientSize = layoutData.clientSize;
    this.layoutData = layoutData.layout;
    this.leftOverX = 0;
    this.leftOverY = 0;
    this._scaleFactor = 1;
    this.root = document.getElementById("root");
    this.mediaTimers = new Array();
    this._orientation = 0;
    this.mediaPath = "http://localhost" + window.StorageManager.getListOfAvailableStorages()[0].path + "vsign/";

    if (layoutData.orientation === "0") {
        this._orientation = 0;
    } else if (layoutData.orientation === "1") {
        this._orientation = 1;
    } else if (layoutData.orientation === "8") {
        this._orientation = 8;
    } else if (layoutData.orientation === "9") {
        this._orientation = 9;
    }
    else {
        console.log("layoutData.orientation cannot be : " + layoutData.orientation);
        this._orientation = 0;
    }
    console.log("layoutData.orientation value is :" + this._orientation);

    this.playerTimer = null;
    this.PreInitLayout();
};

LayoutModel.prototype.CalculateScaleFactor = function () {
    console.log("In CalculateScaleFactor this._orientation is : " + this._orientation);

    var factor = 1.00;
    try {

        this.leftOverX = 0;
        this.leftOverY = 0;
        var leftOverX = 0;
        var leftOverY = 0;

        var layoutWidth = 0;
        var layoutHeight = 0;
        var backgroundWidth;
        var backgroundHeight;
        if (this._orientation === 1 || this._orientation === 9) {
            layoutWidth = this.layoutData[this.layoutIndex].height;
            layoutHeight = this.layoutData[this.layoutIndex].width;

            if (this.clientSize.SizeX === 0) { this.clientSize.SizeX = document.documentElement.clientWidth; }
            if (this.clientSize.SizeY === 0) { this.clientSize.SizeY = document.documentElement.clientHeight; }

            factor = Math.min(this.clientSize.SizeX / layoutWidth, this.clientSize.SizeY / layoutHeight);
            backgroundWidth = layoutWidth * factor;
            backgroundHeight = layoutHeight * factor;
            leftOverX = this.clientSize.SizeX - backgroundHeight;
            leftOverY = this.clientSize.SizeY - backgroundWidth;

            if (leftOverX !== 0) { this.leftOverX = leftOverX / 2; }
            if (leftOverY !== 0) { this.leftOverY = leftOverY / 2; }

        } else {
            // normal
            layoutWidth = this.layoutData[this.layoutIndex].width;
            layoutHeight = this.layoutData[this.layoutIndex].height;

            if (this.clientSize.SizeX === 0) { this.clientSize.SizeX = document.documentElement.clientWidth; }
            if (this.clientSize.SizeY === 0) { this.clientSize.SizeY = document.documentElement.clientHeight; }

            factor = Math.min(this.clientSize.SizeX / layoutWidth, this.clientSize.SizeY / layoutHeight);
            backgroundWidth = layoutWidth * factor;
            backgroundHeight = layoutHeight * factor;
            leftOverX = Math.abs(this.clientSize.SizeX - backgroundWidth);
            leftOverY = Math.abs(this.clientSize.SizeY - backgroundHeight);

            if (leftOverX !== 0) { this.leftOverX = leftOverX / 2; }
            if (leftOverY !== 0) { this.leftOverY = leftOverY / 2; }
        }

    }
    catch (err) {
        console.log(err);
        factor = 1.00;
    }
    finally {
        console.log('this.scaleFactor' + factor);
        this._scaleFactor = factor;
    }

}

LayoutModel.prototype.PreInitLayout = function () {
    try {
        if (this.layoutData.constructor !== Array) {
            var tempLayout = this.layoutData;
            this.layoutData = new Array();
            this.layoutData.push(tempLayout);
        }
        if (this.layoutData[this.layoutIndex].region.constructor !== Array) {
            var tempRegion = this.layoutData[this.layoutIndex].region;
            this.layoutData[this.layoutIndex].region = new Array();
            this.layoutData[this.layoutIndex].region.push(tempRegion);
        }
        for (var i = 0; i < this.layoutData[this.layoutIndex].region.length; i++) {
            if (this.layoutData[this.layoutIndex].region[i].media)
                if (this.layoutData[this.layoutIndex].region[i].media.constructor !== Array) {
                    var tempMedia = this.layoutData[this.layoutIndex].region[i].media;
                    this.layoutData[this.layoutIndex].region[i].media = new Array();
                    this.layoutData[this.layoutIndex].region[i].media.push(tempMedia);
                }
        }

        this.regionData = this.layoutData[this.layoutIndex].region;
    } catch (e) {

    }
};

LayoutModel.prototype.Init = function () {
    this.InitPlayer(0);
    this.CalculateScaleFactor();
    this.GenerateLayoutView();
    this.GenerateRegionView();
    this.GenerateMediaView();
    this.StartMediaFlow();
};

LayoutModel.prototype.ClearLayout = function () {
    if (this.html5VideoSupport) {
        this.player.src = "";
    } else {
        this.player.data = "";
        this.player.stop();
    }
    this.player = null;
    while (this.root.firstChild) {
        this.root.removeChild(this.root.firstChild);
    }

    for (var i = 0; i < this.mediaTimers.length; i++) {
        clearTimeout(this.mediaTimers[i]);
    }
    for (var j = 0; j < this.regionData.length; j++)
        this.regionData[j].regionEnded = 0;
    this.mediaTimers = [];
};

LayoutModel.prototype.CheckLayoutCycle = function () {
    var ended = false;
    for (var i = 0; i < this.regionData.length; i++) { console.log(' CheckLayoutCycle region ' + i + this.regionData[i].regionEnded); if (this.regionData[i].regionEnded) { ended = true; } else { return false; } } if (ended) { console.log("Layout Finished"); //this.layoutIndex = (this.layoutIndex + 1) % this.layoutData.length; ScheduleManager.SetNextSchedule(); //this.ClearLayout(); //this.PreInitLayout(); //this.Init(); return true; // added* } return false; // added* }; LayoutModel.prototype.SetNewLayout = function (data) { this.SlideEffects = []; this.clientSize = data.clientSize; this.layoutData = data.layout; this.mediaPath = "http://localhost" + window.StorageManager.getListOfAvailableStorages()[0].path + "vsign/"; if (data.orientation === "0") { this._orientation = 0; } else if (data.orientation === "1") { this._orientation = 1; } else if (data.orientation === "8") { this._orientation = 8; } else if (data.orientation === "9") { this._orientation = 9; } else { console.log("data.orientation cannot be : " + data.orientation); this._orientation = 0; } console.log("layoutData.orientation value is :" + this._orientation); this.layoutIndex = 0; this.ClearLayout(); this.PreInitLayout(); this.Init(); }; LayoutModel.prototype.InitPlayer = function (parent) { try { this.playerParent = !parent ? null : parent; if (!parent) { this.player = document.createElement("video"); this.html5VideoSupport = this.player.canPlayType('video/mp4') === "" ? false : true; if (!this.html5VideoSupport) { document.body.appendChild(this.player); this.player.parentNode.removeChild(this.player); this.player = document.createElement("object"); this.player.type = "video/mpeg"; } document.body.appendChild(this.player); } else { this.player.parentNode.removeChild(this.player); if (this.html5VideoSupport) this.player = document.createElement("video"); else { this.player = document.createElement("object"); this.player.type = "video/mp4"; } parent.regionElement.appendChild(this.player); } this.isPlayerPlaying = 0; var base = this; this.player.style.width = this.player.parentNode.style.width; this.player.style.height = this.player.parentNode.style.height; this.player.onplay = function () { base.isPlayerPlaying = 1 }; this.player.onerror = function (err) { base.isPlayerPlaying = 0; console.log('Player error:' + err); }; // this.player.OriginalDuration = 0 ; // ReSharper disable once Html.EventNotResolved this.player.addEventListener('loadedmetadata', function () { base.player.OriginalDuration = base.player.duration; }); // check tv player if (this.player.style.height.replace('px', '') >= this.player.style.width.replace('px', '')) {
            this.player.style.height = ((this.player.parentNode.style.width.replace('px', '') * 9) / 16) + "px";
        }
        var top = 0;
        top = (parent.regionElement.style.height.replace('px', '') - this.player.style.height.replace('px', '')) / 2;
        this.player.style.top = top + 'px';
        this.player.style.left = "0px";
        this.player.style.position = "absolute";
        this.player.onPlayStateChange = function () {// for ce-html player
            switch (base.player.playState) {
                case 5: // finished    
                    base.cehtmlPlayerFinished();
                    break;
                case 0: // stopped    
                case 6: // error   
                    base.isPlayerPlaying = 0;
                    base.player.data = "";
                    break;
                case 1: // playing    
                    base.isPlayerPlaying = 1;
                    break;
                case 2: // paused    
                case 3: // connecting    
                case 4: // buffering    
                default:
                    // do nothing    
                    break;
            }
        };

        this.cehtmlPlayerFinished = function () {
            if (base.playerTimer != null) {
                clearTimeout(base.playerTimer);
                base.playerTimer = null;
            }
            // base.layoutData.length > 1 idi önceden
            if (base.layoutData.length >= 1 && parent.media[parent.currentMediaIndex].lastItem) {
                parent.regionEnded = 1;
                base.CheckLayoutCycle();
            }

            parent.currentMediaIndex = (parent.currentMediaIndex + 1) % parent.media.length;
            if (base.GetMediaElementType(parent.media[parent.currentMediaIndex].type) !== "video") {
                parent.media[parent.currentMediaIndex].mediaElement.style.display = "inline";
            }
            base.isPlayerPlaying = 0;
            base.player.data = "";
            base.SetTimeoutOptions(base.playerParent);
        };

        this.OnDurationEnded = function () {
            console.log("Video Duration is Ended!");
            if (base.playerTimer != null) {
                clearTimeout(base.playerTimer);
                base.playerTimer = null;
            }
            var refreshLayout = false;

            // base.layoutData.length > 1 idi önceden
            if (base.layoutData.length >= 1 && parent.media[parent.currentMediaIndex].lastItem) {
                console.log("Region Ended");
                parent.regionEnded = 1;
                refreshLayout = base.CheckLayoutCycle();
            }
            if (!refreshLayout) {
                parent.currentMediaIndex = (parent.currentMediaIndex + 1) % parent.media.length;
                if (base.GetMediaElementType(parent.media[parent.currentMediaIndex].type) !== "video") {
                    // parent.media[parent.currentMediaIndex].mediaElement.style.display = "inline";	
                    parent.media[parent.currentMediaIndex].mediaElement.style.visibility = "visible";
                }
                base.isPlayerPlaying = 0;
                base.player.src = "";

                base.SetTimeoutOptions(base.playerParent);
            }

        };

        this.player.onended = function () { //html5 player 

            console.log("Video is onended.Checking loop value");

            if (base.player.IsZeroDuration) {
                base.player.style.display = "none";
                console.log('base.player.IsZeroDuration detected');
                base.OnDurationEnded();
            }
            else {
                if (base.player.isLoop) {
                    console.log("base.player.isLoop = " + base.player.isLoop);
                    base.player.src = base.player.src;
                    base.player.play();
                }
                else {
                    base.player.style.display = "none";
                }
            }

        };
    } catch (e) { console.log(e.message); }

};

LayoutModel.prototype.GenerateLayoutView = function () {
    try {
        var layoutElement = document.createElement("div");
        layoutElement.id = "mainLayout";
        layoutElement.style.position = "absolute";

        if (this._orientation === 1 || this._orientation === 9) {
            layoutElement.style.width = this._scaleFactor * this.layoutData[this.layoutIndex].width + "px";
            layoutElement.style.height = this._scaleFactor * this.layoutData[this.layoutIndex].height + "px";
        } else {
            // normal 
            layoutElement.style.width = this._scaleFactor * this.layoutData[this.layoutIndex].width + "px";
            layoutElement.style.height = this._scaleFactor * this.layoutData[this.layoutIndex].height + "px";
        }

        layoutElement.style.left = parseInt(this.clientSize.OffsetX) + this.leftOverX + "px";
        layoutElement.style.top = parseInt(this.clientSize.OffsetY) + this.leftOverY + "px";

        layoutElement.style.backgroundColor = this.layoutData[this.layoutIndex].bgcolor;
        layoutElement.style.backgroundImage = "url('" + this.mediaPath + this.layoutData[this.layoutIndex].background + "')";
        layoutElement.style.backgroundRepeat = "no-repeat";
        layoutElement.style.backgroundSize = layoutElement.style.width + " " + layoutElement.style.height;
        layoutElement.style.zIndex = this.layoutData[this.layoutIndex].zindex;
        if (this._orientation === 0) {
        } else if (this._orientation === 1) {
            layoutElement.style.transform = "rotate(90deg)";
        } else if (this._orientation === 8) {
            layoutElement.style.transform = "rotate(180deg)";
        } else if (this._orientation === 9) {
            layoutElement.style.transform = "rotate(-90deg)";
        }

        this.root.appendChild(layoutElement);
        this.layoutData[this.layoutIndex].layoutElement = layoutElement;
    } catch (e) { console.log(e.message); }
};

LayoutModel.prototype.GenerateRegionView = function () {
    try {

        this.regionElement = new Array();
        for (var i = 0; i < this.regionData.length; i++) {
            var regionElement = document.createElement("div");
            regionElement.id = this.regionData[i].id;
            regionElement.style.position = "absolute";
            regionElement.style.top = this._scaleFactor * this.regionData[i].top + parseInt(this.clientSize.OffsetY) + "px";
            regionElement.style.left = this._scaleFactor * this.regionData[i].left + parseInt(this.clientSize.OffsetX) + "px";

            if (this._orientation === 1 || this._orientation === 9) {
                regionElement.style.width = this._scaleFactor * this.regionData[i].width + "px";
                regionElement.style.height = this._scaleFactor * this.regionData[i].height + "px";
                ;
            } else {
                // normal
                regionElement.style.width = this._scaleFactor * this.regionData[i].width + "px";
                regionElement.style.height = this._scaleFactor * this.regionData[i].height + "px";

            }

            regionElement.style.zIndex = this.regionData[i].zindex;
            this.regionData[i].regionElement = regionElement;
            this.regionData[i].regionEnded = 0;
            this.regionData[i].currentMediaIndex = 0;
            this.layoutData[this.layoutIndex].layoutElement.appendChild(regionElement);
        }

    } catch (e) {
        console.log(e.message);

    }
};

LayoutModel.prototype.GenerateMediaView = function () {
    try {
        var mediaElementType;
        var mediaElement;
        var i;

        for (i = 0; i < this.regionData.length; i++) {
            if (this.regionData[i].media) {
                for (var j = 0; j < this.regionData[i].media.length; j++) { mediaElementType = this.GetMediaElementType(this.regionData[i].media[j].type); mediaElement = this.GenerateMediaElement(this.regionData[i], this.regionData[i].media[j], mediaElementType, j === 0 ? 1 : 0); if (mediaElement !== "video") { this.regionData[i].regionElement.appendChild(mediaElement); this.regionData[i].media[j].mediaElement = mediaElement; } if (j === this.regionData[i].media.length - 1) this.regionData[i].media[j].lastItem = true; else this.regionData[i].media[j].lastItem = false; } } } } catch (e) { console.log(e); } }; LayoutModel.prototype.GenerateMediaElement2 = function (regiondata, mediadata, mediaElementType, isVisible) { try { if (mediaElementType !== "video") { var media = document.createElement(mediaElementType); media.id = mediadata.id; media.style.position = "absolute"; media.style.top = "0px"; media.style.left = "0px"; media.style.width = "inherit"; media.style.height = "inherit"; switch (mediaElementType) { case "img": if (!isVisible) media.style.display = "none"; media.src = this.mediaPath + mediadata.options.filename; break; case "div": if (!isVisible) media.style.display = "none"; media.innerHTML = mediadata.raw.text; break; default: } return media; } else { return "video"; } } catch (e) { e.message(); } return null; }; LayoutModel.prototype.GenerateMediaElement = function (regiondata, mediadata, mediaElementType, isVisible) { try { var media; if (mediaElementType === "img") { media = document.createElement(mediaElementType); media.id = mediadata.id; media.src = this.mediaPath + mediadata.options.filename; media.style.position = "absolute"; media.style.top = "0px"; media.style.left = "0px"; var img = new Image(); img.src = media.src; var imageProportion = 1920 / 1920; // chrome does not support naturalHeight & naturalWidth // for test purpose imageProportion is set a value if (img.naturalWidth !== 0 && img.naturalHeight !== 0) imageProportion = img.naturalWidth / img.naturalHeight; var regionProportion = regiondata.width / regiondata.height; var x = 0; var y = 0; var width = regiondata.width * this._scaleFactor; var height = regiondata.height * this._scaleFactor; if (mediadata.options.scaleType === "stretch") { media.style.width = "inherit"; media.style.height = "inherit"; } else if (mediadata.options.scaleType === "center") { if (imageProportion > regionProportion) {
                    height = (regiondata.width * this._scaleFactor) / imageProportion;
                    if (mediadata.options.valign === "middle") {
                        x = x + ((regiondata.height * this._scaleFactor - height) / 2);
                    }
                    else if (mediadata.options.valign === "bottom") {
                        x = x + (regiondata.height * this._scaleFactor - height);
                    }
                }
                else {
                    width = (imageProportion * regiondata.height * this._scaleFactor);

                    if (mediadata.options.align === "center") {
                        y = y + ((regiondata.width * this._scaleFactor - width) / 2);
                    }
                    else if (mediadata.options.align === "right") {
                        y = y + (regiondata.width * this._scaleFactor - width);
                    }
                }

            }
            else {
                console.log('mediadata.options.scaleType ');
                // if options NULL
                if (imageProportion > regionProportion) {
                    height = (regiondata.width * this._scaleFactor) / imageProportion;
                    x = x + ((regiondata.height * this._scaleFactor - height) / 2);
                }
                else {
                    width = (imageProportion * regiondata.height * this._scaleFactor);
                    y = y + ((regiondata.width * this._scaleFactor - width) / 2);
                }

            }

            media.style.width = width + "px";;
            media.style.height = height + "px";;
            media.style.left = y + "px";
            media.style.top = x + "px";

            if (!isVisible) {
                media.style.visibility = "hidden";
            }

            return media;

        } else if (mediaElementType === "div") {
            //media = document.createElement('IFRAME');
            //media.id = mediadata.id;
            //media.style.position = "absolute";
            //media.style.top = "0px";
            //media.style.left = "0px";
            //media.style.width = "inherit";
            //media.style.height = "inherit";
            //media.setAttribute("src", this.mediaPath + mediadata.id + '-cache.html');
            //media.setAttribute("frameBorder", "0");
            media = document.createElement('div');
            media.id = mediadata.id;
            media.style.position = "absolute";
            media.style.top = "0px";
            media.style.left = "0px";
            media.style.width = "inherit";
            media.style.height = "inherit";
            media.innerHTML = mediadata.raw.text;

            if (!isVisible) {
                media.style.visibility = "hidden";
            }

            return media;

        } else if (mediaElementType === "video") {
            return "video";
        }
    } catch (e) {
        e.message();
    }

    return null;

};

LayoutModel.prototype.GetMediaElementType = function (type) {
    console.log('GetMediaElementType' + type);
    switch (type) {
        case "video":
        case "localvideo":
            return "video";
        case "image":
            return "img";
        case "text":
        case "clock":
        case "datasetview":
            return "div";
        default:
            return "div";
    }
};

LayoutModel.prototype.StartMediaFlow = function () {
    try {
        var base = this;
        for (var i = 0; i < this.regionData.length; i++) { if (this.regionData[i].media) this.SetTimeoutOptions(base.regionData[i]); } } catch (e) { console.log(e.message); } }; LayoutModel.prototype.SetTimeoutOptions = function (data) { try { var t, previousParent, duration; var base = this; switch (data.media[data.currentMediaIndex].type) { case "localvideo": case "video": //console.log('type is : video '); if (this.html5VideoSupport) { if (!this.isPlayerPlaying || this.player.src === "") { previousParent = this.playerParent; this.playerParent = data; duration = data.media[data.currentMediaIndex].duration ? data.media[data.currentMediaIndex].duration * 1000 : null; this.player.style.display = "inline"; // check for mute if (data.media[data.currentMediaIndex].options.mute === '1') { this.player.muted = true; } if (previousParent === null || previousParent.regionElement.id !== this.playerParent.regionElement.id) { this.InitPlayer(this.playerParent); this.player.src = this.mediaPath + data.media[data.currentMediaIndex].options.filename; base.isPlayerPlaying = 1; if (data.media[data.currentMediaIndex].options.loop === "1") { this.player.isLoop = 'true'; } setTimeout(function () { base.player.play(); }, 200); } else { this.player.src = this.mediaPath + data.media[data.currentMediaIndex].options.filename; base.isPlayerPlaying = 1; if (data.media[data.currentMediaIndex].options.loop === "1") { this.player.isLoop = 'true'; } setTimeout(function () { base.player.play(); }, 200); } if (duration === 0) { this.player.IsZeroDuration = true; console.log('this.player.IsZeroDuration' + this.player.IsZeroDuration); } if (duration != null && data.media[data.currentMediaIndex].duration > 0) {
                            base.playerTimer = setTimeout(function () {
                                base.OnDurationEnded();
                            }, duration);
                        };
                    }

                } else if (!this.isPlayerPlaying || this.player.data === "") {
                    previousParent = this.playerParent;
                    this.playerParent = data;
                    this.player.style.display = "inline";
                    if (previousParent === null || previousParent.regionElement.id !== this.playerParent.regionElement.id) {
                        this.InitPlayer(this.playerParent);
                        this.player.data = this.mediaPath + data.media[data.currentMediaIndex].options.filename;
                        base.isPlayerPlaying = 1;
                        setTimeout(function () {
                            base.player.play(1);
                        }, 200);

                    } else {
                        this.player.data = this.mediaPath + data.media[data.currentMediaIndex].options.filename;
                        base.isPlayerPlaying = 1;
                        setTimeout(function () {
                            base.player.play(1);
                        }, 200);
                    }

                    if (duration === 0) {
                        this.player.IsZeroDuration = true;
                        console.log('this.player.IsZeroDuration' + this.player.IsZeroDuration);
                    }

                    if (duration != null && data.media[data.currentMediaIndex].duration > 0) {
                        base.playerTimer = setTimeout(function () {
                            base.cehtmlPlayerFinished();
                        }, duration);
                        base.mediaTimers.push(t);
                    }
                }

                console.log("this.player.src is :" + this.player.src);
                break;
            case "text":
            case "image":
            case "clock":
            case "datasetview":
            case "forecastio":
            case "finance":
                if (data.media[data.currentMediaIndex].duration) {
                    duration = data.media[data.currentMediaIndex].duration * 1000;
                    if (duration > 0) {
                        // console.log('type is :' + data.media[data.currentMediaIndex].type);
                        t = setTimeout(function (j) {
                            var refreshLayout = false;
                            if (base.layoutData.length >= 1 && j.media[j.currentMediaIndex].lastItem) {
                                j.regionEnded = 1;
                                refreshLayout = base.CheckLayoutCycle();
                            }

                            if (!refreshLayout) {  // added * 

                                if (data.media[data.currentMediaIndex].type !== 'video')
                                    try {
                                        j.media[j.currentMediaIndex].mediaElement.style.visibility = "hidden";

                                    }
                                    catch (err) {
                                    }

                                j.currentMediaIndex = j.media.length > 1 ? (j.currentMediaIndex + 1) % j.media.length : 0;
                                if (base.GetMediaElementType(j.media[j.currentMediaIndex].type) !== 'video') {

                                    j.media[j.currentMediaIndex].mediaElement.style.visibility = "visible";

                                }
                                base.SetTimeoutOptions(j);
                            }

                        }, duration, data);
                        base.mediaTimers.push(t);
                    } else {
                        if (data.media.length === 1)
                            data.regionEnded = 1;
                    }
                }

                break;
            default:
        }
    } catch (e) {
        console.log(e.message + " " + e.lineno);
    }
};

Test Data.js

TestData.js file contains two initial layouts which are default layouts and custom layouts can be created based on these layouts. The layouts consist of video, image, text and an image slider.

This file is created to configure the test datas. The initially given test datas are layout1 and layout2. By starting the init.js, the test datas are used to create the layouts and schedules. After creating the scenarios, models.js file uses these informations and start playing them with the given scenarios.

var TestData = {
    StartTest: function () {
        LayoutManager.AddLayout(testLayout1);
        LayoutManager.AddLayout(testLayout2);

        var schedule1 = new Schedule(1, testLayout1.layout[0].id, new Date, new Date(new Date().getTime() + (30 * 60000)));
        ScheduleManager.AddSchedule(schedule1);
        var schedule2 = new Schedule(2, testLayout2.layout[0].id, new Date, new Date(new Date().getTime() + (30 * 60000)));
        ScheduleManager.AddSchedule(schedule2);
        schedule1.checkExpire();
        schedule2.checkExpire();
    },
    GetDefaultLayout: function () {
        return defaultLayout;
    }
}

var testLayout1 = {
    "layout": [
        {
            "id": "1",
            "width": "1920",
            "resolutionid": "9",
            "region": [
                {
                    "media": [
                        {
                            "render": "native",
                            "userId": "1",
                            "lkid": "117",
                            "options": {
                                "uri": "http://portal-tv.com/cdn2/vestel_venus_5-4_HDaspect.mp4",
                                "loop": "1",
                                "mute": "0",
                                "filename": "vestel_venus_5-4_HDaspect.mp4"
                            },
                            "raw": null,
                            "duration": "180",
                            "schemaVersion": "1",
                            "type": "video",
                            "id": "137"
                        }
                    ],
                    "top": "180",
                    "userId": "1",
                    "height": "720",
                    "width": "1280",
                    "id": "20780943595732e87d6bc291",
                    "left": "0"
                },
            {
                "media": [
                {
                    "render": "native",
                    "userId": "1",
                    "lkid": "18",
                    "options": {
                        "align": "center",
                        "valign": "middle",
                        "uri": "http://portal-tv.com/cdn2/vsign/venus1.jpg",
                        "scaleType": "center",
                        "filename": "venus1.jpg"
                    },
                    "raw": null,
                    "duration": "2",
                    "schemaVersion": "1",
                    "type": "image",
                    "id": "23"
                },
                {
                    "render": "native",
                    "userId": "1",
                    "lkid": "19",
                    "options": {
                        "align": "center",
                        "valign": "middle",
                        "uri": "http://portal-tv.com/cdn2/vsign/venus2.jpg",
                        "scaleType": "center",
                        "filename": "venus2.jpg"
                    },
                    "raw": null,
                    "duration": "2",
                    "schemaVersion": "1",
                    "type": "image",
                    "id": "26"
                },
                {
                    "render": "native",
                    "userId": "1",
                    "lkid": "20",
                    "options": {
                        "align": "center",
                        "valign": "middle",
                        "uri": "http://portal-tv.com/cdn2/vsign/venus3.jpg",
                        "scaleType": "center",
                        "filename": "venus3.jpg"
                    },
                    "raw": null,
                    "duration": "2",
                    "schemaVersion": "1",
                    "type": "image",
                    "id": "21"
                }
                ],
                "top": "0",
                "userId": "1",
                "height": "1080",
                "width": "640",
                "id": "4399400705733040fad0ed",
                "left": "1280"
            },
            {
                "media": [{
                    "render": "native",
                    "userId": "1",
                    "lkid": "",
                    "options": {
                        "name": "t1",
                        "speed": "0",
                        "effect": null,
                        "xmds": "1",
                        "backgroundColor": null
                    },
                    "raw": {
                        
                    },
                    "duration": "180",
                    "schemaVersion": "1",
                    "type": "text",
                    "id": "580af17ff30e2e53f4c003de4a576772"
                }],
                "top": "0",
                "userId": "1",
                "height": "180",
                "width": "1280",
                "id": "137195303057330d3c980ea",
                "left": "0"
            }, {
                "media": [{
                    "render": "native",
                    "userId": "1",
                    "lkid": "",
                    "options": {
                        "name": "t2",
                        "speed": "0",
                        "effect": null,
                        "xmds": "1",
                        "backgroundColor": null
                    },
                    "raw": {
                        
                    },
                    "duration": "180",
                    "schemaVersion": "1",
                    "type": "text",
                    "id": "580af17ff30e2e53f4c003de4a5767712"
                }],
                "top": "900",
                "userId": "1",
                "height": "180",
                "width": "1280",
                "id": "137195303057330d3c980eb",
                "left": "0"
            }
            ],
            "height": "1080",
            "bgcolor": "gray",
            "schemaVersion": "2"
        }
    ],
    "orientation": "0",
    "offline": "False",
    "clientSize": {
        "OffsetX": 0,
        "SizeX": 0,
        "SizeY": 0,
        "OffsetY": 0

    }
};

var testLayout2 = {
    "layout": [{
        "width": "1920",
        "height": "1080",
        "resolutionid": "9",
        "bgcolor": "#000000",
        "schemaVersion": "2",
        "id": "2",
        "region": [{
            "id": "576bdf146832a",
            "userId": "1",
            "width": "1920",
            "height": "1080",
            "top": "0",
            "left": "0",
            "media": [
                {
                    "id": "647",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2184",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/647.jpg", "filename": "647.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "649",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2185",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/649.jpg", "filename": "647.jpg" }
                },
                {
                    "id": "651",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2187",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/651.jpg", "filename": "651.jpg" }
                },
                {
                    "id": "652",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2188",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/652.jpg", "filename": "652.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "650",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2189",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/650.jpg", "filename": "650.jpg" }
                },
                {
                    "id": "658",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2190",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/658.jpg", "filename": "658.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "654",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2191",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/654.jpg", "filename": "654.jpg" }
                },
                {
                    "id": "657",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2192",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/657.jpg", "filename": "657.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "655",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2193",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/655.jpg", "filename": "655.jpg" }
                },
                {
                    "id": "656",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2194",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/656.jpg", "filename": "656.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "653",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2195",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/653.jpg", "filename": "653.jpg" }
                },
                {
                    "id": "661",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2196",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/661.jpg", "filename": "661.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "660",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2197",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/660.jpg", "filename": "660.jpg" }
                },
                {
                    "id": "659",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2198",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/659.jpg", "filename": "659.jpg", "scaleType": "stretch" }
                }
            ]
        }]
    }],
    "orientation": "0",
    "offline": "False",
    "clientSize": {
        "OffsetX": 0,
        "SizeX": 0,
        "SizeY": 0,
        "OffsetY": 0

    }
};

var defaultLayout = {
    "layout": [{
        "width": "1920",
        "height": "1080",
        "resolutionid": "9",
        "bgcolor": "#000000",
        "schemaVersion": "2",
        "id": "2",
        "region": [{
            "id": "576bdf146832a",
            "userId": "1",
            "width": "1920",
            "height": "1080",
            "top": "0",
            "left": "0",
            "media": [
                 {
                     "render": "native",
                     "userId": "1",
                     "lkid": "1126",
                     "options": {
                         "uri": "http://portal-tv.com/cdn2/vsign/sign.png",
                         "filename": "sign.png",
                         "scaleType": "stretch"
                     },
                     "raw": null,
                     "duration": "0",
                     "schemaVersion": "1",
                     "type": "image",
                     "id": "11122"
                 }

            ]
        }]
    }],
    "orientation": "0",
    "offline": "False",
    "clientSize": {
        "OffsetX": 0,
        "SizeX": 0,
        "SizeY": 0,
        "OffsetY": 0

    }
};

 

[:fr]

Dans ce didacticiel, nous allons créer une application de programmation pour les clients Visual Solution. L’application est essentiellement une application de signalisation numérique dans laquelle il est possible de définir des mises en page avec un contenu différent et de les lire avec un calendrier. L’application contient deux exemples de calendrier de base. L’un d’eux est une mise en page vidéo, image et texte et l’autre est une galerie d’images.

Pour exécuter l’application sur des clients Visual Solution, décompressez le fichier BasicScheduling.rar, placez le dossier à l’intérieur d’un serveur et définissez simplement le code HTML comme starturl. La configuration de starturl pour les clients Visual Solution est expliquée dans le document Guide de démarrage pour les clients – Vue d’ensemble.

L’application se compose de threads, et chaque thread a son propre objectif. Les threads et la page initiale sont les suivants :

  • Code HTML initial : La page qui doit être configurée en tant que « starturl » pour l’appareil Visual Solution. Lance toutes les applications.
  • Init.js : Le fichier qui démarre l’application avec les données de test fournies.
  • LayoutManager.js : Ce fichier comprend les fonctions de mise en page, telles que la création, l’ajout, etc.
  • CustomDownloadManager.js : Ce fichier comprend les fonctions qui exécutent les processus de téléchargement.
  • ScheduleManager.js : Ce fichier comprend les fonctions de programmation telles que la création, la suppression, etc.
  • Models.js : Ce fichier lit les mises en page et les horaires donnés en raison des scénarios.
  • TestData.js : Ce fichier se compose de données de test et démarre la procédure de test.

Dans les sections suivantes, les codes JavaScript pour chaque thread et le code HTML initial sont indiqués et expliqués.

Code HTML initial

Vous pouvez trouver la page HTML initiale ci-dessous. Tous les autres fichiers JavaScript seront expliqués dans les sections suivantes.

Comme le montre le code ci-dessous, des fichiers JavaScript externes sont écrits pour chaque thread, et des listes de téléchargement sont créées. Ensuite, la fonction init() est appelée. C’est le thread qui démarre toutes les applications.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<link href="Schedule.css" rel="stylesheet" />
<script src="jquery-2.2.4.min.js"></script>
<script src="TestData.js"></script>
<script src="CustomDownloadManager.js"></script>
<script src="ScheduleManager.js"></script>
<script src="LayoutManager.js"></script>
<script src="Models.js?v=1"></script>
<script src="Init.js"></script>

<title></title>
</head>
<body>
<div id="defaultscreen"></div>
<div id="layout"></div>
<div id="root"></div>
<script type="text/javascript">
var downloadList;
var activeDownloadList;
$(document).ready(function () {
downloadList = new DownloadList();
activeDownloadList = new DownloadList();
init();
});
</script>
</body>
</html>

CSS du programme

Le code CSS de l’application est ci-dessous.

body {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    top: 0;
    left: 0;
}

#defaultscreen {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    top: 0;
    left: 0;
    background-image: url('Vsign.jpg');
    background-size: cover;
    z-index: 100;
}

#layout {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    top: 0;
    left: 0;
    visibility: hidden;
}

Dans les sections suivantes, chacun des codes JavaScript externes sera présenté et expliqué.

Init.js

L’application démarre avec la fonction init() qui est définie dans le fichier init.js. Fondamentalement, ce fichier vérifie les stockages disponibles et les programmes actifs. S’il y a un stockage disponible et aucun programme actif, le code commence à créer un programme et une mise en page en utilisant les données de test fournies.

Ce fichier contient également des plug-ins JavaScript spécialement créés pour nos téléviseurs. Pour plus d’informations et des exemples d’utilisation de ces plug-ins, vous pouvez trouver les informations nécessaires dans notre document Fonctionnalités prises en charge par l’application HTML.

var currentLayout;
var currentSchedule;
var pathToDownload;
var mediaInfos;
function init() {
    var availableStorageList = window.StorageManager.getListOfAvailableStorages();
    if (availableStorageList !== null) {
        StartScheduling();
    } else { console.log("No removable disk is plugged") };
};

function StartScheduling() {
    if (ScheduleManager.CheckActiveSchedules().length === 0)
        TestData.StartTest();
    currentSchedule = ScheduleManager.CheckActiveSchedules()[0];
    currentLayout = LayoutManager.GetlayoutById(currentSchedule.layoutId);

    mediaInfos = LayoutManager.GetMediaInfo(currentLayout.layout[0]);
	pathToDownload = window.StorageManager.getListOfAvailableStorages()[0].path + "vsign/";
    ScheduleManager.SetSchedule(currentSchedule);
}

CustomDownloadManager.addEventListener('downloadStateChange', function (url, status, destination, errorMessage) {

	switch (status) {
        case window.CustomDownloadManager.DOWNLOAD_COMPLETED:
            {
                downloadList.setDestinationOfDownload(url, destination);
                console.log('downloadCompleteEvent recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                if (activeDownloadList.getDownloadListLength() < 1) {
                    console.log("GenerateLayout Funtion Called");
                    LayoutManager.GenerateLayout(currentLayout);
                }
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_IN_PROGRESS:
            {
                console.log("Is in progress: ", window.CustomDownloadManager.isInProgress(destination));
                activeDownloadList.addDownload(new DownloadObject(url, destination));
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_CANCELED_BY_USER:
            {
                console.log("User canceled");
                console.log('downloadUserCanceled event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_FILE_WRITE_ERROR:
            {
                console.log('File Write Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_FILE_CREATION_ERROR:
            {
                console.log('File Creation Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_LOCAL_ERROR:
            {
                console.log('Local Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_REMOTE_ERROR:
            {
                console.log('Remote Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_NETWORK_ERROR:
            {
                console.log('Network Error Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        case window.CustomDownloadManager.DOWNLOAD_FAILED:
            {
                console.log('Download Failed Event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
                break;
            }
        default:
            {
                console.log('unknown event recieved for url: ' + url + ' with destination : ' + destination + "Error Message:" + errorMessage);
                activeDownloadList.removeDownload(destination);
            }
    }
    reloadActiveDownloads();
}
            );

StorageManager.addEventListener("mediaFileReadProgressEvent", function (myArray) {
    LayoutManager.StartDownloadProcesses(myArray);

});

StorageManager.addEventListener("removableDeviceConnected", function () {
    console.log("removable disk connected!");
    StartScheduling();
});

StorageManager.addEventListener("removableDeviceDisconnected", function () {
    console.log("removable disk disconnected!");
    lModel.ClearLayout();
    $('#defaultscreen').show();
});

function CheckFile(nameKey, myArray) {
    for (var i = 0; i < myArray.length; i++)
        if (myArray[i].name === nameKey)
            return true;
    return false;

Le fichier init.js définit également les résultats possibles pour le statut de téléchargement. CustomDownloadManager fait partie des plug-ins écrits spécifiquement pour nos clients et est utilisé pour télécharger un fichier d’une URL vers une destination spécifique.

LayoutManager.js

Le fichier LayoutManager.js spécifie les fonctions qui peuvent être utilisées pour les mises en page (ajout, suppression, génération, etc.). Si la procédure de test est lancée par init.js, en utilisant les fonctions sur LayoutManager.js, les données de test sont ajoutées aux mises en page et le scénario de signalisation numérique est illustré.

var lModel = null;
var LayoutManager = {
    AddLayout: function (layout) {
        try {
            var allLayouts = [];
            var lStorageLayouts = JSON.parse(window.localStorage.getItem("layouts"));
            if (lStorageLayouts !== null)
                allLayouts = lStorageLayouts;

            allLayouts.push(layout);
            window.localStorage.setItem("layouts", JSON.stringify(allLayouts));
        } catch (e) { }
    },
    RemoveLayout: function (layout) {
        try {
            var allLayouts = [];
            var lStorageLayouts = JSON.parse(window.localStorage.getItem("layouts"));
            if (lStorageLayouts !== null)
                allLayouts = lStorageLayouts;

            allLayouts.removeValue("id", layout.id);
            window.localStorage.setItem("layouts", JSON.stringify(allLayouts));
            LayoutManager.RemoveLayoutContent(layout);
        } catch (e) { }
    },
    RemoveLayoutContent: function (layout) {
        var layoutMedias = LayoutManager.GetMediaInfo(layout.layout[0]);
        for (var i = 0; i < layoutMedias.length; i++) {
            console.log(layoutMedias.filename[i].filename + " deleted from: " + pathToDownload);
            window.StorageManager.delete(pathToDownload + layoutMedias[i].filename);
        }
    },
    GetlayoutById: function (id) {
        var allLayouts = JSON.parse(window.localStorage.getItem("layouts"));
        if (allLayouts !== null)
            for (var i = 0; i < allLayouts.length; i++)
                if (allLayouts[i].layout[0].id === id.toString()) return allLayouts[i];
        return "";
    },
    GetMediaInfo: function (layout) {
        var result = [];
        for (var i = 0; i < layout.region.length; i++)
            for (var j = 0; j < layout.region[i].media.length; j++) {
                if (layout.region[i].media[j].options && layout.region[i].media[j].type !== "text")
                    result.push(layout.region[i].media[j].options);
            }
        return result;
    },
    GenerateLayout: function (layout) {
        //var layoutElement = document.getElementById("layout");
        $('#defaultscreen').hide();
        if (lModel === null) {
            lModel = new LayoutModel(layout);
            lModel.Init();
        } else {
            lModel.SetNewLayout(layout);
        }
    },
    CheckMediaFilesOnDisk: function (path) {
        var makeDir = window.StorageManager.makeDir(path);

        if (makeDir === window.StorageManager.DirAlreadyExists || makeDir === window.StorageManager.NoError)
            var list = window.StorageManager.listFiles(path);
        if (list === 1)
            LayoutManager.StartDownloadProcesses([]);

    },
    SetDefaultLayout: function () {
        console.log("no vailable schedules, returning to default layout");
        $('#defaultscreen').hide();
        window.currentLayout = TestData.GetDefaultLayout();
        window.mediaInfos = LayoutManager.GetMediaInfo(window.currentLayout.layout[0]);
        var makeDir = window.StorageManager.makeDir(pathToDownload);
        if (makeDir === window.StorageManager.DirAlreadyExists || makeDir === window.StorageManager.NoError)
            LayoutManager.CheckMediaFilesOnDisk(pathToDownload);
    },
    StartDownloadProcesses: function (myArray) {
        if (CheckDownloadPossible() === window.CustomDownloadManager.DOWNLOAD_POSSIBLE) {
            for (var i = 0; i < mediaInfos.length; i++) {
                if (myArray.length === 0) {
                    downloadList.addDownload(new DownloadObject(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename));
                    window.CustomDownloadManager.registerDownloadURL(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename);
                    window.CustomDownloadManager.getDownloads();
                }
                else if (!CheckFile(mediaInfos[i].filename, myArray)) {

                    downloadList.addDownload(new DownloadObject(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename));
                    window.CustomDownloadManager.registerDownloadURL(mediaInfos[i].uri, pathToDownload + mediaInfos[i].filename);
                    window.CustomDownloadManager.getDownloads();
                }
            }

            if (activeDownloadList.getDownloadListLength() < 1) {
                console.log("GenerateLayout Funtion Called");
                LayoutManager.GenerateLayout(currentLayout);
            }
        }
    }
};

Array.prototype.removeValue = function (name, value) {
    var array = $.map(this, function (v, i) {
        return v[name] === value ? null : v;
    });
    this.length = 0; //clear original array
    this.push.apply(this, array); //push all elements except the one we want to delete

CustomDownloadManager.js

Le fichier CustomDownloadManager.js spécifie les fonctions relatives au processus de téléchargement et ces fonctions sont utilisées pour télécharger le contenu vers les stockages, le cas échéant. Des fonctions telles que l’annulation du téléchargement, la vérification de la possibilité ou non du téléchargement sont également placées sous ce fichier.

Lors de la vérification du processus, le fichier vérifie également s’il y a suffisamment d’espace sur le périphérique de stockage.  Sinon, le téléchargement échoue et un avertissement s’affiche.

// Download Abstraction
// List of download objects
// URL is used as a handle
var DownloadList = function () {
    var list = [];

    this.addDownload = function (downloadObject) {
        for (var i = 0; i < list.length; i++) {
            if (downloadObject.getDestination() === list[i].getDestination()) {
                return;
            }
        }
        list.push(downloadObject);
    };

    this.removeDownload = function (destination) {
        for (var i = 0; i < list.length; i++) {
            if (destination === list[i].getDestination()) {
                list.splice(i, 1);
                break;
            }
        }
    }
    this.getDownloadListLength = function () {
        return list.length;
    };

    this.getDownloadObjectByIndex = function (index) {
        return list[index];
    };

    this.setDestinationOfDownload = function (url, destination) {
        for (var i = 0; i < list.length; i++) {
            if (list[i].getUrl() === url) {
                list[i].setDestination(destination);
            }
        }
    };

    this.getUrlOfDownloadByDestination = function (destination) {
        for (var i = 0; i < list.length; i++) {
            if (list[i].getDestination() === destination) {
                return list[i].getUrl();
            }
        }
        return null;
    };

    this.getDownloadItselfByDestination = function (destination) {
        for (var i = 0; i < list.length; i++) {
            if (list[i].getDestination() === destination) {
                return list[i].getUrl();
            }
        }
        return null;
    }
}
// Single download object abstraction
var DownloadObject = function (url, destination) {
    var uri = url;
    var dest = destination;

    this.getUrl = function () {
        return uri;
    };

    this.getDestination = function () {
        return dest;
    };

    this.setDestination = function (d) {
        dest = d;
    };
}

function CancelDownload() {
    window.CustomDownloadManager.remove(downloadList.getDownloadObjectByIndex(0).getDestination());
}

function CancelAllDownloads() {
    for (var i = 0; i < activeDownloadList.getDownloadListLength() ; i++) {
        window.CustomDownloadManager.remove(activeDownloadList.getDownloadObjectByIndex(i).getDestination());
    }
}

function isInProgressFirst() {
    var downloadObject = downloadList.getDownloadObjectByIndex(0);
    if (typeof downloadObject == "undefined") {
        console.log("Please insert a USB Storage and then reload the page!");
    }
    else {
        console.log("isInProgress called for first download! Result: " + window.CustomDownloadManager.isInProgress(downloadObject.getDestination()));
    }
}

function deleteFile(index) {
    var destination = downloadList.getDownloadObjectByIndex(index).getDestination();
    console.log(+ "destination is being deleted!!! Result: " + fs_error(window.StorageManager.delete(destination)));
}

function CheckDownloadPossible() {
    var myArray = window.StorageManager.getListOfAvailableStorages();
    if (myArray === null) {
        console.log("No mounted removable device is found!");
        return 0;
    }
   
    for (var i = 0; i < myArray.length; i++) {

        var sizeInGigaBytes = 1;
        var sizeInBytes = sizeInGigaBytes * 1024 * 1024 * 1024;
        var isPossible = window.CustomDownloadManager.checkDownloadPossible(myArray[i].path, sizeInBytes);
        switch (isPossible) {
            case window.CustomDownloadManager.DOWNLOAD_POSSIBLE:
                {

                    console.log("Download is possible. There is enough space for " + sizeInGigaBytes + "GB.");
                    break;
                }
            case window.CustomDownloadManager.DOWNLOAD_INSUFFICIENT_STORAGE:
                {

                    console.log("Download is NOT possible due to insufficient storage. " +
                "There is NOT enough space for " + sizeInGigaBytes + "GB");
                    break;
                }
            default:
                {

                    console.log("Storage not available.");
                }
        }

        return isPossible;
    }
};

ScheduleManager.js

Le fichier ScheduleManager.js contient des fonctions de programmation telles que l’ajout, la suppression et la définition de programmes. L’application stocke initialement deux programmes, et les mises en page de test sont illustrées suivant ces programmes.

var ScheduleManager = {
    CurrentScheduleIndex: 0,
    CheckActiveSchedules: function () {
        var result = [];
        var allSchedules = JSON.parse(window.localStorage.getItem("schedules"));
        if (allSchedules !== null)
            for (var i = 0; i < allSchedules.length; i++) { if (Date.parse(allSchedules[i].endTime) > new Date())
                    result.push(allSchedules[i]);
            }
        return result;
    },
    IsScheduleActive: function (schedule) {
        if (Date.parse(schedule.endTime) > new Date()) {
            //console.log("next schedule is active");
            return true;
        } else {
            console.log("schedule" + schedule.id + " is expired");
            return false;
        }

    },
    AddSchedule: function (schedule) {
        try {
            var allSchedules = [];
            var lStorageSchedules = JSON.parse(window.localStorage.getItem("schedules"));
            if (lStorageSchedules !== null)
                allSchedules = lStorageSchedules;
            allSchedules.push(schedule);
            window.localStorage.setItem("schedules", JSON.stringify(allSchedules));
        } catch (e) { }
    },
    RemoveSchedule: function (schedule) {
        try {
            console.log("schedule: " + schedule.id + "is deleted!!!");
            var allSchedules;
            var lStorageSchedules = JSON.parse(window.localStorage.getItem("schedules"));
            if (lStorageSchedules !== null) {
                allSchedules = lStorageSchedules;
                allSchedules.removeValue("id", schedule.id);
                window.localStorage.setItem("schedules", JSON.stringify(allSchedules));
                //LayoutManager.RemoveLayout(window.currentLayout);
                ScheduleManager.SetNextSchedule();
            }
        } catch (e) { }
    },
    GetScheduleById: function (id) {
        var allSchedules = JSON.parse(window.localStorage.getItem("schedules"));
        for (var i = 0; i < allSchedules.length; i++)
            if (allSchedules[i].id === id.toString()) return allSchedules[i];
        return "";
    }, GetNextSchedule: function () {
        var activeSchedules = ScheduleManager.CheckActiveSchedules();
        ScheduleManager.CurrentScheduleIndex = (ScheduleManager.CurrentScheduleIndex + 1) % activeSchedules.length;
        return activeSchedules[ScheduleManager.CurrentScheduleIndex];
    }, SetNextSchedule: function () {
        if (ScheduleManager.CheckActiveSchedules().length !== 0) {
            var nextSchedule = ScheduleManager.GetNextSchedule();
            if (ScheduleManager.IsScheduleActive(nextSchedule)) {
                var nextlayoutId = nextSchedule.layoutId;
                window.currentLayout = LayoutManager.GetlayoutById(nextlayoutId);
                window.mediaInfos = LayoutManager.GetMediaInfo(window.currentLayout.layout[0]);
                LayoutManager.CheckMediaFilesOnDisk(pathToDownload);
            }
        } else {
            LayoutManager.SetDefaultLayout();
        }
    },
    SetSchedule: function (schedule) {
        if (ScheduleManager.IsScheduleActive(schedule)) {
            window.currentLayout = LayoutManager.GetlayoutById(schedule.layoutId);
            window.mediaInfos = LayoutManager.GetMediaInfo(window.currentLayout.layout[0]);
            LayoutManager.CheckMediaFilesOnDisk(pathToDownload);
        }
    }
};

function Schedule(id, layoutId, startDate, endDate) {
    var base = this;
    this.id = id;
    this.layoutId = layoutId;
    this.startTime = startDate;
    this.endTime = endDate;
    this.checkExpire = function () {

        this.expireControlInterval = setInterval(function () {
            if (ScheduleManager.IsScheduleActive(base))
                return;
            else {
                ScheduleManager.RemoveSchedule(base);
                clearInterval(base.expireControlInterval);

            }
        }, 1000);
    };
};
// ReSharper disable once NativeTypePrototypeExtending
Array.prototype.removeValue = function (name, value) {
    var array = $.map(this, function (v) {
        return v[name] === value ? null : v;
    });
    this.length = 0; //clear original array
    this.push.apply(this, array); //push all elements except the one we want to delete
}

Models.js

Dans le fichier Models.js, les modèles de mise en page sont créés sur la base du type de données du modèle de mise en page générique initialement défini sur TestData.js. Après avoir créé ces modèles, des scénarios d’illustration des prototypes ont été réalisés.

var LayoutModel = function (layoutData) {
    this.SlideEffects = [];
    this.layoutIndex = 0;
    this.clientSize = layoutData.clientSize;
    this.layoutData = layoutData.layout;
    this.leftOverX = 0;
    this.leftOverY = 0;
    this._scaleFactor = 1;
    this.root = document.getElementById("root");
    this.mediaTimers = new Array();
    this._orientation = 0;
    this.mediaPath = "http://localhost" + window.StorageManager.getListOfAvailableStorages()[0].path + "vsign/";

    if (layoutData.orientation === "0") {
        this._orientation = 0;
    } else if (layoutData.orientation === "1") {
        this._orientation = 1;
    } else if (layoutData.orientation === "8") {
        this._orientation = 8;
    } else if (layoutData.orientation === "9") {
        this._orientation = 9;
    }
    else {
        console.log("layoutData.orientation cannot be : " + layoutData.orientation);
        this._orientation = 0;
    }
    console.log("layoutData.orientation value is :" + this._orientation);

    this.playerTimer = null;
    this.PreInitLayout();
};

LayoutModel.prototype.CalculateScaleFactor = function () {
    console.log("In CalculateScaleFactor this._orientation is : " + this._orientation);

    var factor = 1.00;
    try {

        this.leftOverX = 0;
        this.leftOverY = 0;
        var leftOverX = 0;
        var leftOverY = 0;

        var layoutWidth = 0;
        var layoutHeight = 0;
        var backgroundWidth;
        var backgroundHeight;
        if (this._orientation === 1 || this._orientation === 9) {
            layoutWidth = this.layoutData[this.layoutIndex].height;
            layoutHeight = this.layoutData[this.layoutIndex].width;

            if (this.clientSize.SizeX === 0) { this.clientSize.SizeX = document.documentElement.clientWidth; }
            if (this.clientSize.SizeY === 0) { this.clientSize.SizeY = document.documentElement.clientHeight; }

            factor = Math.min(this.clientSize.SizeX / layoutWidth, this.clientSize.SizeY / layoutHeight);
            backgroundWidth = layoutWidth * factor;
            backgroundHeight = layoutHeight * factor;
            leftOverX = this.clientSize.SizeX - backgroundHeight;
            leftOverY = this.clientSize.SizeY - backgroundWidth;

            if (leftOverX !== 0) { this.leftOverX = leftOverX / 2; }
            if (leftOverY !== 0) { this.leftOverY = leftOverY / 2; }

        } else {
            // normal
            layoutWidth = this.layoutData[this.layoutIndex].width;
            layoutHeight = this.layoutData[this.layoutIndex].height;

            if (this.clientSize.SizeX === 0) { this.clientSize.SizeX = document.documentElement.clientWidth; }
            if (this.clientSize.SizeY === 0) { this.clientSize.SizeY = document.documentElement.clientHeight; }

            factor = Math.min(this.clientSize.SizeX / layoutWidth, this.clientSize.SizeY / layoutHeight);
            backgroundWidth = layoutWidth * factor;
            backgroundHeight = layoutHeight * factor;
            leftOverX = Math.abs(this.clientSize.SizeX - backgroundWidth);
            leftOverY = Math.abs(this.clientSize.SizeY - backgroundHeight);

            if (leftOverX !== 0) { this.leftOverX = leftOverX / 2; }
            if (leftOverY !== 0) { this.leftOverY = leftOverY / 2; }
        }

    }
    catch (err) {
        console.log(err);
        factor = 1.00;
    }
    finally {
        console.log('this.scaleFactor' + factor);
        this._scaleFactor = factor;
    }

}

LayoutModel.prototype.PreInitLayout = function () {
    try {
        if (this.layoutData.constructor !== Array) {
            var tempLayout = this.layoutData;
            this.layoutData = new Array();
            this.layoutData.push(tempLayout);
        }
        if (this.layoutData[this.layoutIndex].region.constructor !== Array) {
            var tempRegion = this.layoutData[this.layoutIndex].region;
            this.layoutData[this.layoutIndex].region = new Array();
            this.layoutData[this.layoutIndex].region.push(tempRegion);
        }
        for (var i = 0; i < this.layoutData[this.layoutIndex].region.length; i++) {
            if (this.layoutData[this.layoutIndex].region[i].media)
                if (this.layoutData[this.layoutIndex].region[i].media.constructor !== Array) {
                    var tempMedia = this.layoutData[this.layoutIndex].region[i].media;
                    this.layoutData[this.layoutIndex].region[i].media = new Array();
                    this.layoutData[this.layoutIndex].region[i].media.push(tempMedia);
                }
        }

        this.regionData = this.layoutData[this.layoutIndex].region;
    } catch (e) {

    }
};

LayoutModel.prototype.Init = function () {
    this.InitPlayer(0);
    this.CalculateScaleFactor();
    this.GenerateLayoutView();
    this.GenerateRegionView();
    this.GenerateMediaView();
    this.StartMediaFlow();
};

LayoutModel.prototype.ClearLayout = function () {
    if (this.html5VideoSupport) {
        this.player.src = "";
    } else {
        this.player.data = "";
        this.player.stop();
    }
    this.player = null;
    while (this.root.firstChild) {
        this.root.removeChild(this.root.firstChild);
    }

    for (var i = 0; i < this.mediaTimers.length; i++) {
        clearTimeout(this.mediaTimers[i]);
    }
    for (var j = 0; j < this.regionData.length; j++)
        this.regionData[j].regionEnded = 0;
    this.mediaTimers = [];
};

LayoutModel.prototype.CheckLayoutCycle = function () {
    var ended = false;
    for (var i = 0; i < this.regionData.length; i++) { console.log(' CheckLayoutCycle region ' + i + this.regionData[i].regionEnded); if (this.regionData[i].regionEnded) { ended = true; } else { return false; } } if (ended) { console.log("Layout Finished"); //this.layoutIndex = (this.layoutIndex + 1) % this.layoutData.length; ScheduleManager.SetNextSchedule(); //this.ClearLayout(); //this.PreInitLayout(); //this.Init(); return true; // added* } return false; // added* }; LayoutModel.prototype.SetNewLayout = function (data) { this.SlideEffects = []; this.clientSize = data.clientSize; this.layoutData = data.layout; this.mediaPath = "http://localhost" + window.StorageManager.getListOfAvailableStorages()[0].path + "vsign/"; if (data.orientation === "0") { this._orientation = 0; } else if (data.orientation === "1") { this._orientation = 1; } else if (data.orientation === "8") { this._orientation = 8; } else if (data.orientation === "9") { this._orientation = 9; } else { console.log("data.orientation cannot be : " + data.orientation); this._orientation = 0; } console.log("layoutData.orientation value is :" + this._orientation); this.layoutIndex = 0; this.ClearLayout(); this.PreInitLayout(); this.Init(); }; LayoutModel.prototype.InitPlayer = function (parent) { try { this.playerParent = !parent ? null : parent; if (!parent) { this.player = document.createElement("video"); this.html5VideoSupport = this.player.canPlayType('video/mp4') === "" ? false : true; if (!this.html5VideoSupport) { document.body.appendChild(this.player); this.player.parentNode.removeChild(this.player); this.player = document.createElement("object"); this.player.type = "video/mpeg"; } document.body.appendChild(this.player); } else { this.player.parentNode.removeChild(this.player); if (this.html5VideoSupport) this.player = document.createElement("video"); else { this.player = document.createElement("object"); this.player.type = "video/mp4"; } parent.regionElement.appendChild(this.player); } this.isPlayerPlaying = 0; var base = this; this.player.style.width = this.player.parentNode.style.width; this.player.style.height = this.player.parentNode.style.height; this.player.onplay = function () { base.isPlayerPlaying = 1 }; this.player.onerror = function (err) { base.isPlayerPlaying = 0; console.log('Player error:' + err); }; // this.player.OriginalDuration = 0 ; // ReSharper disable once Html.EventNotResolved this.player.addEventListener('loadedmetadata', function () { base.player.OriginalDuration = base.player.duration; }); // check tv player if (this.player.style.height.replace('px', '') >= this.player.style.width.replace('px', '')) {
            this.player.style.height = ((this.player.parentNode.style.width.replace('px', '') * 9) / 16) + "px";
        }
        var top = 0;
        top = (parent.regionElement.style.height.replace('px', '') - this.player.style.height.replace('px', '')) / 2;
        this.player.style.top = top + 'px';
        this.player.style.left = "0px";
        this.player.style.position = "absolute";
        this.player.onPlayStateChange = function () {// for ce-html player
            switch (base.player.playState) {
                case 5: // finished    
                    base.cehtmlPlayerFinished();
                    break;
                case 0: // stopped    
                case 6: // error   
                    base.isPlayerPlaying = 0;
                    base.player.data = "";
                    break;
                case 1: // playing    
                    base.isPlayerPlaying = 1;
                    break;
                case 2: // paused    
                case 3: // connecting    
                case 4: // buffering    
                default:
                    // do nothing    
                    break;
            }
        };

        this.cehtmlPlayerFinished = function () {
            if (base.playerTimer != null) {
                clearTimeout(base.playerTimer);
                base.playerTimer = null;
            }
            // base.layoutData.length > 1 idi önceden
            if (base.layoutData.length >= 1 && parent.media[parent.currentMediaIndex].lastItem) {
                parent.regionEnded = 1;
                base.CheckLayoutCycle();
            }

            parent.currentMediaIndex = (parent.currentMediaIndex + 1) % parent.media.length;
            if (base.GetMediaElementType(parent.media[parent.currentMediaIndex].type) !== "video") {
                parent.media[parent.currentMediaIndex].mediaElement.style.display = "inline";
            }
            base.isPlayerPlaying = 0;
            base.player.data = "";
            base.SetTimeoutOptions(base.playerParent);
        };

        this.OnDurationEnded = function () {
            console.log("Video Duration is Ended!");
            if (base.playerTimer != null) {
                clearTimeout(base.playerTimer);
                base.playerTimer = null;
            }
            var refreshLayout = false;

            // base.layoutData.length > 1 idi önceden
            if (base.layoutData.length >= 1 && parent.media[parent.currentMediaIndex].lastItem) {
                console.log("Region Ended");
                parent.regionEnded = 1;
                refreshLayout = base.CheckLayoutCycle();
            }
            if (!refreshLayout) {
                parent.currentMediaIndex = (parent.currentMediaIndex + 1) % parent.media.length;
                if (base.GetMediaElementType(parent.media[parent.currentMediaIndex].type) !== "video") {
                    // parent.media[parent.currentMediaIndex].mediaElement.style.display = "inline";	
                    parent.media[parent.currentMediaIndex].mediaElement.style.visibility = "visible";
                }
                base.isPlayerPlaying = 0;
                base.player.src = "";

                base.SetTimeoutOptions(base.playerParent);
            }

        };

        this.player.onended = function () { //html5 player 

            console.log("Video is onended.Checking loop value");

            if (base.player.IsZeroDuration) {
                base.player.style.display = "none";
                console.log('base.player.IsZeroDuration detected');
                base.OnDurationEnded();
            }
            else {
                if (base.player.isLoop) {
                    console.log("base.player.isLoop = " + base.player.isLoop);
                    base.player.src = base.player.src;
                    base.player.play();
                }
                else {
                    base.player.style.display = "none";
                }
            }

        };
    } catch (e) { console.log(e.message); }

};

LayoutModel.prototype.GenerateLayoutView = function () {
    try {
        var layoutElement = document.createElement("div");
        layoutElement.id = "mainLayout";
        layoutElement.style.position = "absolute";

        if (this._orientation === 1 || this._orientation === 9) {
            layoutElement.style.width = this._scaleFactor * this.layoutData[this.layoutIndex].width + "px";
            layoutElement.style.height = this._scaleFactor * this.layoutData[this.layoutIndex].height + "px";
        } else {
            // normal 
            layoutElement.style.width = this._scaleFactor * this.layoutData[this.layoutIndex].width + "px";
            layoutElement.style.height = this._scaleFactor * this.layoutData[this.layoutIndex].height + "px";
        }

        layoutElement.style.left = parseInt(this.clientSize.OffsetX) + this.leftOverX + "px";
        layoutElement.style.top = parseInt(this.clientSize.OffsetY) + this.leftOverY + "px";

        layoutElement.style.backgroundColor = this.layoutData[this.layoutIndex].bgcolor;
        layoutElement.style.backgroundImage = "url('" + this.mediaPath + this.layoutData[this.layoutIndex].background + "')";
        layoutElement.style.backgroundRepeat = "no-repeat";
        layoutElement.style.backgroundSize = layoutElement.style.width + " " + layoutElement.style.height;
        layoutElement.style.zIndex = this.layoutData[this.layoutIndex].zindex;
        if (this._orientation === 0) {
        } else if (this._orientation === 1) {
            layoutElement.style.transform = "rotate(90deg)";
        } else if (this._orientation === 8) {
            layoutElement.style.transform = "rotate(180deg)";
        } else if (this._orientation === 9) {
            layoutElement.style.transform = "rotate(-90deg)";
        }

        this.root.appendChild(layoutElement);
        this.layoutData[this.layoutIndex].layoutElement = layoutElement;
    } catch (e) { console.log(e.message); }
};

LayoutModel.prototype.GenerateRegionView = function () {
    try {

        this.regionElement = new Array();
        for (var i = 0; i < this.regionData.length; i++) {
            var regionElement = document.createElement("div");
            regionElement.id = this.regionData[i].id;
            regionElement.style.position = "absolute";
            regionElement.style.top = this._scaleFactor * this.regionData[i].top + parseInt(this.clientSize.OffsetY) + "px";
            regionElement.style.left = this._scaleFactor * this.regionData[i].left + parseInt(this.clientSize.OffsetX) + "px";

            if (this._orientation === 1 || this._orientation === 9) {
                regionElement.style.width = this._scaleFactor * this.regionData[i].width + "px";
                regionElement.style.height = this._scaleFactor * this.regionData[i].height + "px";
                ;
            } else {
                // normal
                regionElement.style.width = this._scaleFactor * this.regionData[i].width + "px";
                regionElement.style.height = this._scaleFactor * this.regionData[i].height + "px";

            }

            regionElement.style.zIndex = this.regionData[i].zindex;
            this.regionData[i].regionElement = regionElement;
            this.regionData[i].regionEnded = 0;
            this.regionData[i].currentMediaIndex = 0;
            this.layoutData[this.layoutIndex].layoutElement.appendChild(regionElement);
        }

    } catch (e) {
        console.log(e.message);

    }
};

LayoutModel.prototype.GenerateMediaView = function () {
    try {
        var mediaElementType;
        var mediaElement;
        var i;

        for (i = 0; i < this.regionData.length; i++) {
            if (this.regionData[i].media) {
                for (var j = 0; j < this.regionData[i].media.length; j++) { mediaElementType = this.GetMediaElementType(this.regionData[i].media[j].type); mediaElement = this.GenerateMediaElement(this.regionData[i], this.regionData[i].media[j], mediaElementType, j === 0 ? 1 : 0); if (mediaElement !== "video") { this.regionData[i].regionElement.appendChild(mediaElement); this.regionData[i].media[j].mediaElement = mediaElement; } if (j === this.regionData[i].media.length - 1) this.regionData[i].media[j].lastItem = true; else this.regionData[i].media[j].lastItem = false; } } } } catch (e) { console.log(e); } }; LayoutModel.prototype.GenerateMediaElement2 = function (regiondata, mediadata, mediaElementType, isVisible) { try { if (mediaElementType !== "video") { var media = document.createElement(mediaElementType); media.id = mediadata.id; media.style.position = "absolute"; media.style.top = "0px"; media.style.left = "0px"; media.style.width = "inherit"; media.style.height = "inherit"; switch (mediaElementType) { case "img": if (!isVisible) media.style.display = "none"; media.src = this.mediaPath + mediadata.options.filename; break; case "div": if (!isVisible) media.style.display = "none"; media.innerHTML = mediadata.raw.text; break; default: } return media; } else { return "video"; } } catch (e) { e.message(); } return null; }; LayoutModel.prototype.GenerateMediaElement = function (regiondata, mediadata, mediaElementType, isVisible) { try { var media; if (mediaElementType === "img") { media = document.createElement(mediaElementType); media.id = mediadata.id; media.src = this.mediaPath + mediadata.options.filename; media.style.position = "absolute"; media.style.top = "0px"; media.style.left = "0px"; var img = new Image(); img.src = media.src; var imageProportion = 1920 / 1920; // chrome does not support naturalHeight & naturalWidth // for test purpose imageProportion is set a value if (img.naturalWidth !== 0 && img.naturalHeight !== 0) imageProportion = img.naturalWidth / img.naturalHeight; var regionProportion = regiondata.width / regiondata.height; var x = 0; var y = 0; var width = regiondata.width * this._scaleFactor; var height = regiondata.height * this._scaleFactor; if (mediadata.options.scaleType === "stretch") { media.style.width = "inherit"; media.style.height = "inherit"; } else if (mediadata.options.scaleType === "center") { if (imageProportion > regionProportion) {
                    height = (regiondata.width * this._scaleFactor) / imageProportion;
                    if (mediadata.options.valign === "middle") {
                        x = x + ((regiondata.height * this._scaleFactor - height) / 2);
                    }
                    else if (mediadata.options.valign === "bottom") {
                        x = x + (regiondata.height * this._scaleFactor - height);
                    }
                }
                else {
                    width = (imageProportion * regiondata.height * this._scaleFactor);

                    if (mediadata.options.align === "center") {
                        y = y + ((regiondata.width * this._scaleFactor - width) / 2);
                    }
                    else if (mediadata.options.align === "right") {
                        y = y + (regiondata.width * this._scaleFactor - width);
                    }
                }

            }
            else {
                console.log('mediadata.options.scaleType ');
                // if options NULL
                if (imageProportion > regionProportion) {
                    height = (regiondata.width * this._scaleFactor) / imageProportion;
                    x = x + ((regiondata.height * this._scaleFactor - height) / 2);
                }
                else {
                    width = (imageProportion * regiondata.height * this._scaleFactor);
                    y = y + ((regiondata.width * this._scaleFactor - width) / 2);
                }

            }

            media.style.width = width + "px";;
            media.style.height = height + "px";;
            media.style.left = y + "px";
            media.style.top = x + "px";

            if (!isVisible) {
                media.style.visibility = "hidden";
            }

            return media;

        } else if (mediaElementType === "div") {
            //media = document.createElement('IFRAME');
            //media.id = mediadata.id;
            //media.style.position = "absolute";
            //media.style.top = "0px";
            //media.style.left = "0px";
            //media.style.width = "inherit";
            //media.style.height = "inherit";
            //media.setAttribute("src", this.mediaPath + mediadata.id + '-cache.html');
            //media.setAttribute("frameBorder", "0");
            media = document.createElement('div');
            media.id = mediadata.id;
            media.style.position = "absolute";
            media.style.top = "0px";
            media.style.left = "0px";
            media.style.width = "inherit";
            media.style.height = "inherit";
            media.innerHTML = mediadata.raw.text;

            if (!isVisible) {
                media.style.visibility = "hidden";
            }

            return media;

        } else if (mediaElementType === "video") {
            return "video";
        }
    } catch (e) {
        e.message();
    }

    return null;

};

LayoutModel.prototype.GetMediaElementType = function (type) {
    console.log('GetMediaElementType' + type);
    switch (type) {
        case "video":
        case "localvideo":
            return "video";
        case "image":
            return "img";
        case "text":
        case "clock":
        case "datasetview":
            return "div";
        default:
            return "div";
    }
};

LayoutModel.prototype.StartMediaFlow = function () {
    try {
        var base = this;
        for (var i = 0; i < this.regionData.length; i++) { if (this.regionData[i].media) this.SetTimeoutOptions(base.regionData[i]); } } catch (e) { console.log(e.message); } }; LayoutModel.prototype.SetTimeoutOptions = function (data) { try { var t, previousParent, duration; var base = this; switch (data.media[data.currentMediaIndex].type) { case "localvideo": case "video": //console.log('type is : video '); if (this.html5VideoSupport) { if (!this.isPlayerPlaying || this.player.src === "") { previousParent = this.playerParent; this.playerParent = data; duration = data.media[data.currentMediaIndex].duration ? data.media[data.currentMediaIndex].duration * 1000 : null; this.player.style.display = "inline"; // check for mute if (data.media[data.currentMediaIndex].options.mute === '1') { this.player.muted = true; } if (previousParent === null || previousParent.regionElement.id !== this.playerParent.regionElement.id) { this.InitPlayer(this.playerParent); this.player.src = this.mediaPath + data.media[data.currentMediaIndex].options.filename; base.isPlayerPlaying = 1; if (data.media[data.currentMediaIndex].options.loop === "1") { this.player.isLoop = 'true'; } setTimeout(function () { base.player.play(); }, 200); } else { this.player.src = this.mediaPath + data.media[data.currentMediaIndex].options.filename; base.isPlayerPlaying = 1; if (data.media[data.currentMediaIndex].options.loop === "1") { this.player.isLoop = 'true'; } setTimeout(function () { base.player.play(); }, 200); } if (duration === 0) { this.player.IsZeroDuration = true; console.log('this.player.IsZeroDuration' + this.player.IsZeroDuration); } if (duration != null && data.media[data.currentMediaIndex].duration > 0) {
                            base.playerTimer = setTimeout(function () {
                                base.OnDurationEnded();
                            }, duration);
                        };
                    }

                } else if (!this.isPlayerPlaying || this.player.data === "") {
                    previousParent = this.playerParent;
                    this.playerParent = data;
                    this.player.style.display = "inline";
                    if (previousParent === null || previousParent.regionElement.id !== this.playerParent.regionElement.id) {
                        this.InitPlayer(this.playerParent);
                        this.player.data = this.mediaPath + data.media[data.currentMediaIndex].options.filename;
                        base.isPlayerPlaying = 1;
                        setTimeout(function () {
                            base.player.play(1);
                        }, 200);

                    } else {
                        this.player.data = this.mediaPath + data.media[data.currentMediaIndex].options.filename;
                        base.isPlayerPlaying = 1;
                        setTimeout(function () {
                            base.player.play(1);
                        }, 200);
                    }

                    if (duration === 0) {
                        this.player.IsZeroDuration = true;
                        console.log('this.player.IsZeroDuration' + this.player.IsZeroDuration);
                    }

                    if (duration != null && data.media[data.currentMediaIndex].duration > 0) {
                        base.playerTimer = setTimeout(function () {
                            base.cehtmlPlayerFinished();
                        }, duration);
                        base.mediaTimers.push(t);
                    }
                }

                console.log("this.player.src is :" + this.player.src);
                break;
            case "text":
            case "image":
            case "clock":
            case "datasetview":
            case "forecastio":
            case "finance":
                if (data.media[data.currentMediaIndex].duration) {
                    duration = data.media[data.currentMediaIndex].duration * 1000;
                    if (duration > 0) {
                        // console.log('type is :' + data.media[data.currentMediaIndex].type);
                        t = setTimeout(function (j) {
                            var refreshLayout = false;
                            if (base.layoutData.length >= 1 && j.media[j.currentMediaIndex].lastItem) {
                                j.regionEnded = 1;
                                refreshLayout = base.CheckLayoutCycle();
                            }

                            if (!refreshLayout) {  // added * 

                                if (data.media[data.currentMediaIndex].type !== 'video')
                                    try {
                                        j.media[j.currentMediaIndex].mediaElement.style.visibility = "hidden";

                                    }
                                    catch (err) {
                                    }

                                j.currentMediaIndex = j.media.length > 1 ? (j.currentMediaIndex + 1) % j.media.length : 0;
                                if (base.GetMediaElementType(j.media[j.currentMediaIndex].type) !== 'video') {

                                    j.media[j.currentMediaIndex].mediaElement.style.visibility = "visible";

                                }
                                base.SetTimeoutOptions(j);
                            }

                        }, duration, data);
                        base.mediaTimers.push(t);
                    } else {
                        if (data.media.length === 1)
                            data.regionEnded = 1;
                    }
                }

                break;
            default:
        }
    } catch (e) {
        console.log(e.message + " " + e.lineno);
    }
};

Test Data.js

Le fichier TestData.js contient deux mises en page initiales qui sont des mises en page par défaut. Des mises en page personnalisées peuvent être créées en partant de ces mises en page. Les mises en page se composent de vidéo, d’images, de texte et d’une galerie d’images.

Ce fichier est créé pour configurer les données de test. Les données de test initialement fournies sont layout1 et layout2. En démarrant init.js, les données de test sont utilisées pour créer les mises en page et les programmes. Après avoir créé les scénarios, le fichier models.js utilise ces informations et commence à les lire avec les scénarios donnés.

var TestData = {
    StartTest: function () {
        LayoutManager.AddLayout(testLayout1);
        LayoutManager.AddLayout(testLayout2);

        var schedule1 = new Schedule(1, testLayout1.layout[0].id, new Date, new Date(new Date().getTime() + (30 * 60000)));
        ScheduleManager.AddSchedule(schedule1);
        var schedule2 = new Schedule(2, testLayout2.layout[0].id, new Date, new Date(new Date().getTime() + (30 * 60000)));
        ScheduleManager.AddSchedule(schedule2);
        schedule1.checkExpire();
        schedule2.checkExpire();
    },
    GetDefaultLayout: function () {
        return defaultLayout;
    }
}

var testLayout1 = {
    "layout": [
        {
            "id": "1",
            "width": "1920",
            "resolutionid": "9",
            "region": [
                {
                    "media": [
                        {
                            "render": "native",
                            "userId": "1",
                            "lkid": "117",
                            "options": {
                                "uri": "http://portal-tv.com/cdn2/vestel_venus_5-4_HDaspect.mp4",
                                "loop": "1",
                                "mute": "0",
                                "filename": "vestel_venus_5-4_HDaspect.mp4"
                            },
                            "raw": null,
                            "duration": "180",
                            "schemaVersion": "1",
                            "type": "video",
                            "id": "137"
                        }
                    ],
                    "top": "180",
                    "userId": "1",
                    "height": "720",
                    "width": "1280",
                    "id": "20780943595732e87d6bc291",
                    "left": "0"
                },
            {
                "media": [
                {
                    "render": "native",
                    "userId": "1",
                    "lkid": "18",
                    "options": {
                        "align": "center",
                        "valign": "middle",
                        "uri": "http://portal-tv.com/cdn2/vsign/venus1.jpg",
                        "scaleType": "center",
                        "filename": "venus1.jpg"
                    },
                    "raw": null,
                    "duration": "2",
                    "schemaVersion": "1",
                    "type": "image",
                    "id": "23"
                },
                {
                    "render": "native",
                    "userId": "1",
                    "lkid": "19",
                    "options": {
                        "align": "center",
                        "valign": "middle",
                        "uri": "http://portal-tv.com/cdn2/vsign/venus2.jpg",
                        "scaleType": "center",
                        "filename": "venus2.jpg"
                    },
                    "raw": null,
                    "duration": "2",
                    "schemaVersion": "1",
                    "type": "image",
                    "id": "26"
                },
                {
                    "render": "native",
                    "userId": "1",
                    "lkid": "20",
                    "options": {
                        "align": "center",
                        "valign": "middle",
                        "uri": "http://portal-tv.com/cdn2/vsign/venus3.jpg",
                        "scaleType": "center",
                        "filename": "venus3.jpg"
                    },
                    "raw": null,
                    "duration": "2",
                    "schemaVersion": "1",
                    "type": "image",
                    "id": "21"
                }
                ],
                "top": "0",
                "userId": "1",
                "height": "1080",
                "width": "640",
                "id": "4399400705733040fad0ed",
                "left": "1280"
            },
            {
                "media": [{
                    "render": "native",
                    "userId": "1",
                    "lkid": "",
                    "options": {
                        "name": "t1",
                        "speed": "0",
                        "effect": null,
                        "xmds": "1",
                        "backgroundColor": null
                    },
                    "raw": {
                        
                    },
                    "duration": "180",
                    "schemaVersion": "1",
                    "type": "text",
                    "id": "580af17ff30e2e53f4c003de4a576772"
                }],
                "top": "0",
                "userId": "1",
                "height": "180",
                "width": "1280",
                "id": "137195303057330d3c980ea",
                "left": "0"
            }, {
                "media": [{
                    "render": "native",
                    "userId": "1",
                    "lkid": "",
                    "options": {
                        "name": "t2",
                        "speed": "0",
                        "effect": null,
                        "xmds": "1",
                        "backgroundColor": null
                    },
                    "raw": {
                        
                    },
                    "duration": "180",
                    "schemaVersion": "1",
                    "type": "text",
                    "id": "580af17ff30e2e53f4c003de4a5767712"
                }],
                "top": "900",
                "userId": "1",
                "height": "180",
                "width": "1280",
                "id": "137195303057330d3c980eb",
                "left": "0"
            }
            ],
            "height": "1080",
            "bgcolor": "gray",
            "schemaVersion": "2"
        }
    ],
    "orientation": "0",
    "offline": "False",
    "clientSize": {
        "OffsetX": 0,
        "SizeX": 0,
        "SizeY": 0,
        "OffsetY": 0

    }
};

var testLayout2 = {
    "layout": [{
        "width": "1920",
        "height": "1080",
        "resolutionid": "9",
        "bgcolor": "#000000",
        "schemaVersion": "2",
        "id": "2",
        "region": [{
            "id": "576bdf146832a",
            "userId": "1",
            "width": "1920",
            "height": "1080",
            "top": "0",
            "left": "0",
            "media": [
                {
                    "id": "647",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2184",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/647.jpg", "filename": "647.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "649",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2185",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/649.jpg", "filename": "647.jpg" }
                },
                {
                    "id": "651",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2187",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/651.jpg", "filename": "651.jpg" }
                },
                {
                    "id": "652",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2188",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/652.jpg", "filename": "652.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "650",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2189",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/650.jpg", "filename": "650.jpg" }
                },
                {
                    "id": "658",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2190",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/658.jpg", "filename": "658.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "654",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2191",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/654.jpg", "filename": "654.jpg" }
                },
                {
                    "id": "657",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2192",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/657.jpg", "filename": "657.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "655",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2193",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/655.jpg", "filename": "655.jpg" }
                },
                {
                    "id": "656",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2194",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/656.jpg", "filename": "656.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "653",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2195",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/653.jpg", "filename": "653.jpg" }
                },
                {
                    "id": "661",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2196",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/661.jpg", "filename": "661.jpg", "scaleType": "stretch" }
                },
                {
                    "id": "660",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2197",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/660.jpg", "filename": "660.jpg" }
                },
                {
                    "id": "659",
                    "type": "image",
                    "render": "native",
                    "duration": "7",
                    "lkid": "2198",
                    "userId": "1",
                    "schemaVersion": "1",
                    "options": { "uri": "http://portal-tv.com/cdn2/vsign/659.jpg", "filename": "659.jpg", "scaleType": "stretch" }
                }
            ]
        }]
    }],
    "orientation": "0",
    "offline": "False",
    "clientSize": {
        "OffsetX": 0,
        "SizeX": 0,
        "SizeY": 0,
        "OffsetY": 0

    }
};

var defaultLayout = {
    "layout": [{
        "width": "1920",
        "height": "1080",
        "resolutionid": "9",
        "bgcolor": "#000000",
        "schemaVersion": "2",
        "id": "2",
        "region": [{
            "id": "576bdf146832a",
            "userId": "1",
            "width": "1920",
            "height": "1080",
            "top": "0",
            "left": "0",
            "media": [
                 {
                     "render": "native",
                     "userId": "1",
                     "lkid": "1126",
                     "options": {
                         "uri": "http://portal-tv.com/cdn2/vsign/sign.png",
                         "filename": "sign.png",
                         "scaleType": "stretch"
                     },
                     "raw": null,
                     "duration": "0",
                     "schemaVersion": "1",
                     "type": "image",
                     "id": "11122"
                 }

            ]
        }]
    }],
    "orientation": "0",
    "offline": "False",
    "clientSize": {
        "OffsetX": 0,
        "SizeX": 0,
        "SizeY": 0,
        "OffsetY": 0

    }
};

[:]​