app options, page containers, templates debug, optimizations
app options, page containers, templates debug, optimizations

--- a/assets/js/iotcc.js
+++ b/assets/js/iotcc.js
@@ -1,3 +1,7 @@
+var appOptions = {
+    templateDebug: false,
+    pageContainer: true
+};
 
 var iotCC = {
     mqttDefaultConfig: {
@@ -88,10 +92,10 @@
                 iotCC.addPage(page);
                 if (json.widget == 'toggle') {
                     if ($('input[name="' + widgetId + '"]').exists() == false) {
-                        html = '<label class="switch switch--material">';
-                        html += '<input type="checkbox" name="' + widgetId + '" data-widget="toggle" data-status="' + (json.checked==true?'1':'0') + '" class="switch__input switch--material__input" ' + (json.checked==true?'checked="checked"':'') + '>';
-                        html += '<div class="switch__toggle switch--material__toggle">';
-                        html += '<div class="switch__handle switch--material__handle">';
+                        html = '<label class="switch switch--material {class4}">';
+                        html += '<input type="checkbox" name="' + widgetId + '" data-widget="toggle" data-status="' + (json.checked==true?'1':'0') + '" class="switch__input switch--material__input {class5}" ' + (json.checked==true?'checked="checked"':'') + '>';
+                        html += '<div class="switch__toggle switch--material__toggle {class6}">';
+                        html += '<div class="switch__handle switch--material__handle {class7}">';
                         html += '</div>';
                         html += '</div>';
                         html += '</label>';
@@ -114,7 +118,11 @@
                 } else if (json.widget == 'radios') {
                     html = '';
                     $(json.options).each(function(k, v) {
-                        html += '<label class="radio-button radio-button--material"><input type="radio" name="' + widgetId + '" data-widget="radios" data-status="' + v.status + '" class="radio-button__input radio-button--material__input" name="r" ' + (v.checked==true?'checked="checked"':'') + '><div class="radio-button__checkmark radio-button--material__checkmark"></div>'+ v.label +'</label>';
+                        html += '<label class="radio-button radio-button--material {class3}">';
+                        html += '<input type="radio" name="' + widgetId + '" data-widget="radios" data-status="' + v.status + '" class="radio-button__input radio-button--material__input {class4}" name="r" ' + (v.checked==true?'checked="checked"':'') + '>';
+                        html += '<div class="radio-button__checkmark radio-button--material__checkmark {class5}">';
+                        html += '</div>';
+                        html += v.label +'</label>';
                     });
                     if ($('input[name="' + widgetId + '"]').exists() == false) {
                         json.content = html;
@@ -129,9 +137,9 @@
                     }
                 } else if (json.widget == 'data' || json.widget == 'data-control') {
                     html = '';
-                    if (json.widget == 'data-control') html += '<button name="' + widgetId + '" data-widget="' + json.widget + '" data-action="-" class="button button--material">-</button> ';
-                    html += '<span name="' + widgetId + '" data-widget="' + json.widget + '" data-value="' + json.value + '" class="lead">' + json.value + '</span> ' + (json.valuedescription?'<span class="lead">' + json.valuedescription + '</lead>':'') + '';
-                    if (json.widget == 'data-control') html += ' <button name="' + widgetId + '" data-widget="' + json.widget + '" data-action="+" class="button button--material">+</button>';
+                    if (json.widget == 'data-control') html += '<button name="' + widgetId + '" data-widget="' + json.widget + '" data-action="-" class="button button--material btn-xs">-</button> ';
+                    html += '<span name="' + widgetId + '" data-widget="' + json.widget + '" data-value="' + json.value + '" class="text">' + json.value + '</span> ' + (json.valuedescription?'<span class="text">' + json.valuedescription + '</span>':'') + '';
+                    if (json.widget == 'data-control') html += ' <button name="' + widgetId + '" data-widget="' + json.widget + '" data-action="+" class="button button--material btn-xs">+</button>';
                     if ($('span[name="' + widgetId + '"]').exists() == false) {
                         json.content = html;
                         json.widgetId = widgetId;
@@ -139,7 +147,7 @@
                         json.callback = function() {
                             var action = $(this).data('action');
                             var value = $('span[name="' + $(this).attr('name') + '"]').data('value');
-                            value = action == '+' ? parseInt(value) + 1 : parseInt(value) - 1;
+                            value = action == '+' ? iotCC.formatData(value, json.format) + 1 : iotCC.formatData(value, json.format) - 1;
                             iotCC.mqttClient.publish(json.topic + '/data', '{"value":"' + value + '"}', {qos: 1, retained: false});
                         };
                         iotCC.addWidget(json);
@@ -200,16 +208,14 @@
         }
     },
     addHtml: function(json, html) {
-        for (var key in json) {
-            html = html.replace('{' + key + '}', json[key]);
-        }
-        html = html.replace(/{(\w*)}/g, '');
+        html = this.parseTemplate(json, html);
         var section = $('section.content').filter('[data-section="dashboard"]');
         // TODO: add after sort ?
         var widgets = $(section).find('div[data-page="' + json.pageId + '"]').find('div.widgetcontainer').length;
         if (widgets > 0 && widgets%2 == 0) {
             //$(section).find('div[data-page="' + json.pageId + '"]').append('<div class="clearfix visible-sm-block" data-order="' + json.order + '"></div>');
         }
+
         $(section).find('div[data-page="' + json.pageId + '"]').append(html);
         if (json.callback != undefined) {
             $(json.selector + '[name="' + json.widgetId + '"]').click(json.callback);
@@ -232,7 +238,21 @@
             } else {
                 var html = '<div class="row page hide" data-page="' + page.pageId + '"></div>';
             }
-            $('section.content').filter('[data-section="dashboard"]').append(html);
+            if (appOptions.pageContainer) {
+                var html2 = '<div class="box page {class}" data-pagecontainer="' + page.pageId + '">';
+                html2 += '<div class="box-header with-border {class1}">';
+                html2 += '<h3 class="box-title {class2}">' + page.pageName + '</h3>';
+                if (page.icon) html2 += '<div class="box-tools pull-right ' + page.icon + '"></div>';
+                html2 += '</div>';
+                html2 += '<div class="box-body {class4}">';
+                html2 += html;
+                html2 += '</div>';
+                html2 += '</div>';
+                html2 = this.parseTemplate(page, html2);
+                $('section.content').filter('[data-section="dashboard"]').append(html2);
+            } else {
+                $('section.content').filter('[data-section="dashboard"]').append(html);
+            }
         }
         if ($('div.pagination').find('label').filter('[data-pagination="' + page.pageId + '"]').exists() == false) {
             var html = '<label class="tab-bar__item tab-bar--material__item" data-pagination="' + page.pageId + '">';
@@ -247,6 +267,7 @@
                 var pageId = $(this).data('pagination');
                 $('div.page').addClass('hide');
                 $('div.page').filter('[data-page="' + pageId + '"]').removeClass('hide');
+                $('div.page').filter('[data-pagecontainer="' + pageId + '"]').removeClass('hide');
             });
         }
     },
@@ -307,14 +328,29 @@
             this.events.message.push(callback);
         }
     },
-    animate: function(element){
+    animate: function(element) {
         element.fadeTo("fast", 0.33 ).fadeTo("fast", 1);
+    },
+    formatData: function(v, f, d) {
+        if (f == 'int') {
+            return parseInt(v);
+        } else if (f == 'float') {
+            return parseFloat(v).toFixed(d);
+        }
+    },
+    parseTemplate: function(json, html) {
+        for (var key in json) {
+            html = html.replace('{' + key + '}', json[key]);
+        }
+        if (appOptions.templateDebug == false) {
+            html = html.replace(/{(\w*)}/g, '');
+        }
+        return html;
     }
 }
 
 jQuery.fn.exists = function(){return ($(this).length > 0);}
  $(document).ready(function(){
-    iotCC.init();
 
     $('.navigation').click(function(e){
         e.preventDefault();
@@ -334,10 +370,36 @@
         iotCC.saveConfig();
     });
 
+    $('#saveOptions').click(function(e){
+        e.preventDefault();
+        var config = {
+            'pageContainer': $('#pageContainer').prop('checked'),
+            'templateDebug': $('#templateDebug').prop('checked'),
+        };
+
+        try {
+            localStorage.setItem('appOptions', JSON.stringify(config));
+            iotCC.showNotification('Options', 'Data saved succesfully', 'settings', 'info', 3);
+        } catch(ex) {
+            iotCC.showNotification('Options', 'Cannot save data to local storage', 'settings', 'danger', 5);
+        }
+    });
+
+    appOptions = Object.assign(appOptions, JSON.parse(localStorage.getItem('appOptions')));
+    for(var key in appOptions) {
+        var value = appOptions[key];
+        if (value == true || false) {
+            $('input[name="' + key + '"]').prop("checked", value);
+        } else {
+            $('input[name="' + key + '"]').val(value);
+        }
+    }
+
     $('a').filter('[data-toggle="control-refresh"]').click(function(e){
         e.preventDefault();
         iotCC.refreshDevices();
     });
+    iotCC.init();
 });
 
 // custom console

--- a/assets/js/simulateDevices.js
+++ b/assets/js/simulateDevices.js
@@ -10,38 +10,38 @@
         return;
     }
     if (topicPath[2] == 'device') {
-        iotCC.mqttClient.publish('/iotcc/heater1/device', '{"name":"House heating 1","desc":"", "pages" : [{"pageId" : 10, "pageName" : "House heating", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/heater1/heater/config', '{"id":"100", "pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Hollway Heater", "topic":"/iotcc/heater1/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 40}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater1/device', '{"name":"House heating 1","desc":"", "pages" : [{"pageId": 10, "pageName": "House heating", "icon": "ion-ios-home", "class1":"bg-blue"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater1/heater/config', '{"pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Hollway Heater", "topic":"/iotcc/heater1/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 40}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/heater2/device', '{"name":"House heating 2","desc":"", "pages" : [{"pageId" : 10, "pageName" : "House heating", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/heater2/heater/config', '{"id":"101", "pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Kitchen Heater", "topic":"/iotcc/heater2/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 30}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater2/device', '{"name":"House heating 2","desc":"", "pages" : [{"pageId": 10, "pageName": "House heating", "icon": "ion-ios-home", "class1":"bg-blue"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater2/heater/config', '{"pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Kitchen Heater", "topic":"/iotcc/heater2/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 30}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/heater3/device', '{"name":"House heating 3","desc":"", "pages" : [{"pageId" : 10, "pageName" : "House heating", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/heater3/heater/config', '{"id":"102", "pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Bedroom Heater", "topic":"/iotcc/heater3/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 10}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater3/device', '{"name":"House heating 3","desc":"", "pages" : [{"pageId" : 10, "pageName" : "House heating", "icon": "ion-ios-home", "class1":"bg-blue"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater3/heater/config', '{"pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Bedroom Heater", "topic":"/iotcc/heater3/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 10}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/heater4/device', '{"name":"House heating 4","desc":"", "pages" : [{"pageId" : 10, "pageName" : "House heating", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/heater4/heater/config', '{"id":"103", "pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Living Heater", "topic":"/iotcc/heater4/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 20}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater4/device', '{"name":"House heating 4","desc":"", "pages" : [{"pageId" : 10, "pageName" : "House heating", "icon": "ion-ios-home", "class1":"bg-blue"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/heater4/heater/config', '{"pageName": "House heating", "pageId": 10, "widget":"radios", "title":"Living Heater", "topic":"/iotcc/heater4/heater", "options":[{"checked":true, "label": "Off", "status":"1"}, {"label": "Confort", "status":"2"}, {"label": "Anti freeze", "status":"3"}, {"label": "Confort -2", "status":"4"}], "template": "template-3", "icon": "ion-ios-home", "class": "bg-blue", "order": 20}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/dogsheating/device', '{"name":"Dogs heating","desc":"", "pages" : [{"pageId" : 20, "pageName" : "Dogs heating", "icon": "ion-ios-paw"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/dogsheating/toggle1/config', '{"id":"200", "pageName": "Dogs heating", "pageId": 20, "widget":"toggle", "title":"Mara", "topic":"/iotcc/dogsheating/toggle1", "checked":true, "template": "template-1", "icon": "ion-ios-paw", "class": "bg-green", "order" : 10}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/dogsheating/toggle2/config', '{"id":"201", "pageName": "Dogs Heating", "pageId": 20, "widget":"toggle", "title":"Linda", "topic":"/iotcc/dogsheating/toggle2", "template": "template-1", "icon": "ion-ios-paw", "class": "bg-green", "order" : 20}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/dogsheating/device', '{"name":"Dogs heating","desc":"", "pages" : [{"pageId" : 20, "pageName" : "Dogs heating", "icon": "ion-ios-paw", "class1":"bg-green"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/dogsheating/toggle1/config', '{"pageName": "Dogs heating", "pageId": 20, "widget":"toggle", "title":"Mara", "topic":"/iotcc/dogsheating/toggle1", "checked":true, "template": "template-1", "icon": "ion-ios-paw", "class": "bg-green", "order" : 10}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/dogsheating/toggle2/config', '{"pageName": "Dogs Heating", "pageId": 20, "widget":"toggle", "title":"Linda", "topic":"/iotcc/dogsheating/toggle2", "template": "template-1", "icon": "ion-ios-paw", "class": "bg-green", "order" : 20}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/outdoorlights1/device', '{"name":"Outdoor lighting 1","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/outdoorlights1/garage/config', '{"id":"300", "pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"Garage", "topic":"/iotcc/outdoorlights1/garage", "checked":true, "template": "template-1", "icon": "ion-model-s", "class": "bg-orange", "order": 40}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights1/device', '{"name":"Outdoor lighting 1","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home", "class1":"bg-orange"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights1/garage/config', '{"pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"Garage", "topic":"/iotcc/outdoorlights1/garage", "checked":true, "template": "template-1", "icon": "ion-model-s", "class": "bg-orange", "order": 40}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/outdoorlights2/device', '{"name":"Outdoor lighting 2","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/outdoorlights2/house1/config', '{"id":"301", "pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"House front", "topic":"/iotcc/outdoorlights2/house1", "template": "template-1", "icon": "ion-ios-home", "class": "bg-orange", "order": 10}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights2/device', '{"name":"Outdoor lighting 2","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home", "class1":"bg-green"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights2/house1/config', '{"pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"House front", "topic":"/iotcc/outdoorlights2/house1", "template": "template-1", "icon": "ion-ios-home", "class": "bg-orange", "order": 10}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/outdoorlights3/device', '{"name":"Outdoor lighting 3","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/outdoorlights3/house2/config', '{"id":"302", "pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"House back", "topic":"/iotcc/outdoorlights3/house2", "template": "template-1", "icon": "ion-ios-home", "class": "bg-orange", "order": 20}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights3/device', '{"name":"Outdoor lighting 3","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home", "class1":"bg-green"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights3/house2/config', '{"pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"House back", "topic":"/iotcc/outdoorlights3/house2", "template": "template-1", "icon": "ion-ios-home", "class": "bg-orange", "order": 20}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/outdoorlights4/device', '{"name":"Outdoor lighting 4","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/outdoorlights4/house3/config', '{"id":"303", "pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"House sides", "topic":"/iotcc/outdoorlights4/house3", "template": "template-1", "icon": "ion-ios-home", "class": "bg-orange", "order": 30}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights4/device', '{"name":"Outdoor lighting 4","desc":"", "pages" : [{"pageId" : 30, "pageName" : "Outdoor Lights", "icon": "ion-ios-home", "class1":"bg-green"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/outdoorlights4/house3/config', '{"pageName": "Outdoor lightling", "pageId": 30, "widget":"toggle", "title":"House sides", "topic":"/iotcc/outdoorlights4/house3", "template": "template-1", "icon": "ion-ios-home", "class": "bg-orange", "order": 30}', {qos: 1, retained: false});
 
-        iotCC.mqttClient.publish('/iotcc/greenhouse/device', '{"name":"Greenhouse","desc":"", "pages" : [{"pageId" : 40, "pageName" : "Greenhouse", "icon": "ion-ios-home"}]}', {qos: 1, retained: false});
-        iotCC.mqttClient.publish('/iotcc/greenhouse/tempsensor1/config', '{"id":"304", "pageName": "Greenhouse", "pageId": 40, "widget":"data", "title":"Temp sensor 1", "topic":"/iotcc/greenhouse/tempsensor1", "value": "22", "valuedescription": "degrees C", "template": "template-1", "icon": "ion-ios-home", "class": "bg-green", "order": 30}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/greenhouse/device', '{"name":"Greenhouse","desc":"", "pages" : [{"pageId" : 40, "pageName" : "Greenhouse", "icon": "ion-ios-home", "class1":"bg-green"}]}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/greenhouse/tempsensor1/config', '{"pageName": "Greenhouse", "pageId": 40, "widget":"data", "format":"int", "title":"Temp sensor 1", "topic":"/iotcc/greenhouse/tempsensor1", "value": "22", "valuedescription": "degrees C", "template": "template-1", "icon": "ion-ios-home", "class": "bg-green", "order": 30}', {qos: 1, retained: false});
         iotCC.mqttClient.publish('/iotcc/greenhouse/tempsensor1/data', '{"value":"' + (Math.floor(Math.random() * (10)) + 20) + '"}');
-        iotCC.mqttClient.publish('/iotcc/greenhouse/heater/config', '{"id":"305", "pageName": "Greenhouse", "pageId": 40, "widget":"data-control", "title":"Heater", "topic":"/iotcc/greenhouse/heater", "value": "22", "valuedescription": "degrees C", "template": "template-1", "icon": "ion-ios-home", "class": "bg-green", "order": 30}', {qos: 1, retained: false});
+        iotCC.mqttClient.publish('/iotcc/greenhouse/heater/config', '{"pageName": "Greenhouse", "pageId": 40, "widget":"data-control", "format":"int", "title":"Heater", "topic":"/iotcc/greenhouse/heater", "value": "22", "valuedescription": "degrees C", "template": "template-3", "icon": "ion-ios-home", "class": "bg-green", "class2": "text-center", "order": 30}', {qos: 1, retained: false});
         iotCC.mqttClient.publish('/iotcc/greenhouse/heater/data', '{"value":"' + (Math.floor(Math.random() * (10)) + 20) + '"}');
     }
 });

--- a/assets/template/template-1.html
+++ b/assets/template/template-1.html
@@ -1,4 +1,4 @@
-<div class="col-md-3 col-sm-6 col-xs-12 widgetcontainer" data-order="{order}">
+<div class="col-md-3 col-sm-6 col-xs-12 widgetcontainer" data-order="{order}"  data-template="{template}">
     <div class="info-box widget">
         <span class="info-box-icon {class}"><i class="ion {icon}"></i></span>
         <div class="info-box-content">

--- a/assets/template/template-2.html
+++ b/assets/template/template-2.html
@@ -1,4 +1,4 @@
-<div class="col-lg-3 col-xs-6 widgetcontainer" data-order="{order}">
+<div class="col-lg-3 col-xs-6 widgetcontainer" data-order="{order}"  data-template="{template}">
     <div class="small-box {class}">
         <div class="inner {class1}">
             <h3>{title}</h3>

--- a/assets/template/template-3.html
+++ b/assets/template/template-3.html
@@ -1,4 +1,4 @@
-<div class="col-md-3 col-sm-6 col-xs-12 widgetcontainer" data-order="{order}">
+<div class="col-md-3 col-sm-6 col-xs-12 widgetcontainer" data-order="{order}" data-template="{template}">
     <div class="info-box box">
         <div class="box-header with-border {class}">
             <span class="info-box-text {class1}"><b>{title}</b></span>

file:a/index.html -> file:b/index.html
--- a/index.html
+++ b/index.html
@@ -1,257 +1,285 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <meta charset="utf-8">
-  <meta http-equiv="X-UA-Compatible" content="IE=edge">
-  <title>IoT Control Center</title>
-  <!-- Tell the browser to be responsive to screen width -->
-  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
-  <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
-  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
-  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
-
-  <link rel="stylesheet" href="bower_components/AdminLTE/dist/css/AdminLTE.min.css">
-  <link rel="stylesheet" href="bower_components/AdminLTE/dist/css/skins/_all-skins.min.css">
-  <link rel="stylesheet" href="assets/css/iotcc.css">
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <title>IoT Control Center</title>
+    <!-- Tell the browser to be responsive to screen width -->
+    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
+    <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">
+
+    <link rel="stylesheet" href="bower_components/AdminLTE/dist/css/AdminLTE.min.css">
+    <link rel="stylesheet" href="bower_components/AdminLTE/dist/css/skins/_all-skins.min.css">
+    <link rel="stylesheet" href="assets/css/iotcc.css">
 </head>
 
 <body class="hold-transition skin-blue sidebar-mini sidebar-collapse">
 <div class="wrapper">
     <header class="main-header">
-    <!-- Logo -->
-    <a href="#dashboard" class="logo">
-      <!-- mini logo for sidebar mini 50x50 pixels -->
-      <span class="logo-mini"><b>IoT</b></span>
-      <!-- logo for regular state and mobile devices -->
-      <span class="logo-lg"><b>IoT</b> Control Center</span>
-    </a>
-
-    <!-- Header Navbar: style can be found in header.less -->
-    <nav class="navbar navbar-static-top">
-      <!-- Sidebar toggle button-->
-      <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
-        <span class="sr-only">Toggle navigation</span>
-      </a>
-      <!-- Navbar Right Menu -->
-      <div class="navbar-custom-menu">
-        <ul class="nav navbar-nav">
-          <!-- Control Sidebar Toggle Button -->
-          <li>
-            <a href="#" data-toggle="control-refresh" title="Refresh devices"><i class="fa fa-refresh"></i></a>
-          </li>
-          <li>
-            <a href="#" data-toggle="control-sidebar"><i class="fa fa-gear"></i></a>
-          </li>
+        <!-- Logo -->
+        <a href="#dashboard" class="logo">
+            <!-- mini logo for sidebar mini 50x50 pixels -->
+            <span class="logo-mini"><b>IoT</b></span>
+            <!-- logo for regular state and mobile devices -->
+            <span class="logo-lg"><b>IoT</b> Control Center</span>
+        </a>
+
+        <!-- Header Navbar: style can be found in header.less -->
+        <nav class="navbar navbar-static-top">
+            <!-- Sidebar toggle button-->
+            <a href="#" class="sidebar-toggle" data-toggle="offcanvas" role="button">
+                <span class="sr-only">Toggle navigation</span>
+            </a>
+            <!-- Navbar Right Menu -->
+            <div class="navbar-custom-menu">
+                <ul class="nav navbar-nav">
+                    <!-- Control Sidebar Toggle Button -->
+                    <li>
+                        <a href="#" data-toggle="control-refresh" title="Refresh devices"><i class="fa fa-refresh"></i></a>
+                    </li>
+                    <li>
+                        <a href="#" data-toggle="control-sidebar"><i class="fa fa-gear"></i></a>
+                    </li>
+                </ul>
+            </div>
+        </nav>
+    </header>
+    <!-- Left side column. contains the logo and sidebar -->
+    <aside class="main-sidebar">
+        <!-- sidebar: style can be found in sidebar.less -->
+        <section class="sidebar">
+            <!-- /.search form -->
+            <!-- sidebar menu: : style can be found in sidebar.less -->
+            <ul class="sidebar-menu">
+                <!--li class="header">Options</li-->
+                <li class="active">
+                    <a href="#" class="navigation" data-section="dashboard">
+                        <i class="fa fa-dashboard"></i> <span>Dashboard</span>
+                    </a>
+                </li>
+                <li>
+                    <a href="#" class="navigation" data-section="settings">
+                        <i class="fa fa-gears"></i> <span>Settings</span>
+                    </a>
+                </li>
+                <li>
+                    <a href="#" class="navigation" data-section="log">
+                        <i class="fa fa-align-justify"></i> <span>Log</span>
+                    </a>
+                </li>
+            </ul>
+        </section>
+        <!-- /.sidebar -->
+    </aside>
+
+    <!-- Content Wrapper. Contains page content -->
+    <div class="content-wrapper">
+        <section class="content-header" data-section="dashboard">
+            <h1>Dashboard</h1>
+            <ol class="breadcrumb">
+                <li class="active"><i class="fa fa-dashboard"></i> Dashboard</li>
+            </ol>
+        </section>
+
+        <section class="content-header hide" data-section="settings">
+            <h1>Settings</h1>
+            <ol class="breadcrumb">
+                <li class="active"><i class="fa fa-gears"></i> Settings</li>
+            </ol>
+        </section>
+
+        <section class="content-header hide" data-section="log">
+            <h1>Log</h1>
+            <ol class="breadcrumb">
+                <li class="active"><i class="fa fa-gears"></i> Logs</li>
+            </ol>
+        </section>
+
+        <!-- Dashboard content -->
+        <section class="content" data-section="dashboard">
+
+            <div class="row">
+                <div class="col-md-12">
+                    <div class="tab-bar tab-bar--top tab-bar--material pagination hide">
+                        <label class="tab-bar__item tab-bar--material__item" data-pagination="0">
+                            <input type="radio" name="tab-bar-material-a" checked="checked">
+                            <button class="tab-bar__button tab-bar--material__button">
+                                <i class="tab-bar__icon tab-bar--material__icon ion-drag"></i>
+                                <div class="tab-bar__label tab-bar--material__label">All</div>
+                            </button>
+                        </label>
+                    </div>
+                </div>
+            </div>
+
+            <div class="row">
+                <div class="col-md-12">
+                    <div class="callout notification-dashboard hide">
+                        <h4></h4>
+                        <span></span>
+                    </div>
+                </div>
+            </div>
+
+        </section>
+
+        <!-- Settings content -->
+        <section class="content hide" data-section="settings">
+
+            <div class="row">
+                <div class="col-md-12">
+                    <div class="callout notification-settings hide">
+                        <h4></h4>
+                        <span></span>
+                    </div>
+                </div>
+            </div>
+
+            <div class="row">
+                <div class="col-md-12">
+                    <div class="box box-primary">
+                        <div class="box-header with-border">
+                            <h3 class="box-title">MQTT connection data</h3>
+                        </div>
+                        <!-- /.box-header -->
+                        <!-- form start -->
+                        <form id="mqttConfig">
+                            <div class="box-body">
+                                <div class="form-group">
+                                    <label for="mqttClientId">Client ID</label>
+                                    <input type="text" class="form-control" id="mqttClientId" name="mqttClientId" placeholder="Client ID" />
+                                </div>
+                                <div class="form-group">
+                                    <label for="mqttHost">Host</label>
+                                    <input type="text" class="form-control" id="mqttHost" name="mqttHost" placeholder="Host" />
+                                </div>
+                                <div class="form-group">
+                                    <label for="mqttHost">Port</label>
+                                    <input type="text" class="form-control" id="mqttPort" name="mqttPort" placeholder="Port" />
+                                </div>
+                                <div class="form-group">
+                                    <label for="mqttUser">Username</label>
+                                    <input type="text" class="form-control" id="mqttUser" name="mqttUser" placeholder="Username" />
+                                </div>
+                                <div class="form-group">
+                                    <label for="mqttPass">Password</label>
+                                    <input type="text" class="form-control" id="mqttPass" name="mqttPass" placeholder="Password" />
+                                </div>
+                                <div class="checkbox">
+                                    <label for="mqttSecure">
+                                    <input type="checkbox" id="mqttSecure" name="mqttSecure" /> Secure
+                                </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label for="mqttDebug">
+                                    <input type="checkbox" id="mqttDebug" name="mqttDebug" /> Debug
+                                </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label for="mqttSimulateDevices">
+                                    <input type="checkbox" id="mqttSimulateDevices" name="mqttSimulateDevices" /> Simulate devices
+                                </label>
+                                </div>
+                            </div>
+                            <!-- /.box-body -->
+
+                            <div class="box-footer">
+                                <button type="submit" class="btn btn-primary" id="saveMqttConfig">Save</button>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+
+            <div class="row">
+                <div class="col-md-12">
+                    <div class="box box-primary">
+                        <div class="box-header with-border">
+                            <h3 class="box-title">Options</h3>
+                        </div>
+                        <!-- /.box-header -->
+                        <!-- form start -->
+                        <form id="options">
+                            <div class="box-body">
+                                <div class="checkbox">
+                                    <label for="pageContainer">
+                                        <input type="checkbox" id="pageContainer" name="pageContainer" /> Add page container
+                                    </label>
+                                </div>
+                                <div class="checkbox">
+                                    <label for="templateDebug">
+                                        <input type="checkbox" id="templateDebug" name="templateDebug" /> Template debug
+                                    </label>
+                                </div>
+                            </div>
+                            <!-- /.box-body -->
+
+                            <div class="box-footer">
+                                <button type="submit" class="btn btn-primary" id="saveOptions">Save</button>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </section>
+        <!-- /.content -->
+
+        <!-- Log content -->
+        <section class="content hide" data-section="log">
+            <pre class="console"></pre>
+        </section>
+        <!-- /.content -->
+    </div>
+    <!-- /.content-wrapper -->
+
+    <footer class="main-footer">
+        <div class="pull-right hidden-xs">
+            <b>Version</b> 0.1
+        </div>
+        <strong>Copyright &copy; 2017 <a href="http://www.razvi.ro">Razvan Stanga</a>.</strong> All rights reserved.
+    </footer>
+
+    <!-- Control Sidebar -->
+    <aside class="control-sidebar control-sidebar-dark">
+        <!-- Create the tabs -->
+        <ul class="nav nav-tabs nav-justified control-sidebar-tabs">
+            <li><a href="#control-sidebar-home-tab" data-toggle="tab"><i class="fa fa-gear"></i></a></li>
         </ul>
-      </div>
-    </nav>
-  </header>
-  <!-- Left side column. contains the logo and sidebar -->
-  <aside class="main-sidebar">
-    <!-- sidebar: style can be found in sidebar.less -->
-    <section class="sidebar">
-      <!-- /.search form -->
-      <!-- sidebar menu: : style can be found in sidebar.less -->
-      <ul class="sidebar-menu">
-        <!--li class="header">Options</li-->
-        <li class="active">
-            <a href="#" class="navigation" data-section="dashboard">
-                <i class="fa fa-dashboard"></i> <span>Dashboard</span>
-            </a>
-        </li>
-        <li>
-            <a href="#" class="navigation" data-section="settings">
-                <i class="fa fa-gears"></i> <span>Settings</span>
-            </a>
-        </li>
-        <li>
-            <a href="#" class="navigation" data-section="log">
-                <i class="fa fa-align-justify"></i> <span>Log</span>
-            </a>
-        </li>
-      </ul>
-    </section>
-    <!-- /.sidebar -->
-  </aside>
-
-<!-- Content Wrapper. Contains page content -->
-<div class="content-wrapper">
-    <section class="content-header" data-section="dashboard">
-        <h1>Dashboard</h1>
-        <ol class="breadcrumb">
-            <li class="active"><i class="fa fa-dashboard"></i> Dashboard</li>
-        </ol>
-    </section>
-
-    <section class="content-header hide" data-section="settings">
-        <h1>Settings</h1>
-        <ol class="breadcrumb">
-            <li class="active"><i class="fa fa-gears"></i> Settings</li>
-        </ol>
-    </section>
-
-    <section class="content-header hide" data-section="log">
-        <h1>Log</h1>
-        <ol class="breadcrumb">
-            <li class="active"><i class="fa fa-gears"></i> Logs</li>
-        </ol>
-    </section>
-
-    <!-- Dashboard content -->
-    <section class="content" data-section="dashboard">
-
-        <div class="row">
-          <div class="col-md-12">
-            <div class="tab-bar tab-bar--top tab-bar--material pagination hide">
-              <label class="tab-bar__item tab-bar--material__item" data-pagination="0">
-                <input type="radio" name="tab-bar-material-a" checked="checked">
-                <button class="tab-bar__button tab-bar--material__button">
-                  <i class="tab-bar__icon tab-bar--material__icon ion-drag"></i>
-                  <div class="tab-bar__label tab-bar--material__label">All</div>
-                </button>
-              </label>
-            </div>
-          </div>
+        <!-- Tab panes -->
+        <div class="tab-content">
+            <!-- Home tab content -->
+            <div class="tab-pane" id="control-sidebar-home-tab">
+
+            </div>
+            <!-- /.tab-pane -->
+
+            <!-- Settings tab content -->
+            <div class="tab-pane" id="control-sidebar-settings-tab">
+                <form method="post">
+                    <h3 class="control-sidebar-heading">General Settings</h3>
+
+                    <div class="form-group">
+                        <label class="control-sidebar-subheading">
+                            Debug templates
+                            <input type="checkbox" class="pull-right" name="debugTemplates" />
+                        </label>
+
+                        <p>
+                            Allow the user to show his name in blog posts
+                        </p>
+                    </div>
+                    <!-- /.form-group -->
+                </form>
+            </div>
+            <!-- /.tab-pane -->
         </div>
-
-        <div class="row">
-          <div class="col-md-12">
-            <div class="callout notification-dashboard hide">
-              <h4></h4>
-              <span></span>
-            </div>
-          </div>
-        </div>
-
-    </section>
-
-    <!-- Settings content -->
-    <section class="content hide" data-section="settings">
-
-      <div class="row">
-        <div class="col-md-12">
-          <div class="callout notification-settings hide">
-            <h4></h4>
-            <span></span>
-          </div>
-        </div>
-      </div>
-
-      <div class="row">
-        <div class="col-md-12">
-          <div class="box box-primary">
-            <div class="box-header with-border">
-              <h3 class="box-title">MQTT connection data</h3>
-            </div>
-            <!-- /.box-header -->
-            <!-- form start -->
-            <form id="mqttConfig">
-              <div class="box-body">
-                <div class="form-group">
-                  <label for="mqttClientId">Client ID</label>
-                  <input type="text" class="form-control" id="mqttClientId" name="mqttClientId" placeholder="Client ID" />
-                </div>
-                <div class="form-group">
-                  <label for="mqttHost">Host</label>
-                  <input type="text" class="form-control" id="mqttHost" name="mqttHost" placeholder="Host" />
-                </div>
-                <div class="form-group">
-                  <label for="mqttHost">Port</label>
-                  <input type="text" class="form-control" id="mqttPort" name="mqttPort" placeholder="Port" />
-                </div>
-                <div class="form-group">
-                  <label for="mqttUser">Username</label>
-                  <input type="text" class="form-control" id="mqttUser" name="mqttUser" placeholder="Username" />
-                </div>
-                <div class="form-group">
-                  <label for="mqttPass">Password</label>
-                  <input type="text" class="form-control" id="mqttPass" name="mqttPass" placeholder="Password" />
-                </div>
-                <div class="checkbox">
-                  <label for="mqttSecure">
-                    <input type="checkbox" id="mqttSecure" name="mqttSecure" /> Secure
-                  </label>
-                </div>
-                <div class="checkbox">
-                  <label for="mqttDebug">
-                    <input type="checkbox" id="mqttDebug" name="mqttDebug" /> Debug
-                  </label>
-                </div>
-                <div class="checkbox">
-                  <label for="mqttSimulateDevices">
-                    <input type="checkbox" id="mqttSimulateDevices" name="mqttSimulateDevices" /> Simulate devices
-                  </label>
-                </div>
-              </div>
-              <!-- /.box-body -->
-
-              <div class="box-footer">
-                <button type="submit" class="btn btn-primary" id="saveMqttConfig">Save</button>
-              </div>
-            </form>
-          </div>
-        </div>
-      </div>
-    </section>
-    <!-- /.content -->
-
-    <!-- Log content -->
-    <section class="content hide" data-section="log">
-      <pre class="console"></pre>
-    </section>
-    <!-- /.content -->
-
-  </div>
-  <!-- /.content-wrapper -->
-
-  <footer class="main-footer">
-    <div class="pull-right hidden-xs">
-      <b>Version</b> 0.1
-    </div>
-    <strong>Copyright &copy; 2017 <a href="http://www.razvi.ro">Razvan Stanga</a>.</strong> All rights reserved.
-  </footer>
-
-  <!-- Control Sidebar -->
-  <aside class="control-sidebar control-sidebar-dark">
-    <!-- Create the tabs -->
-    <ul class="nav nav-tabs nav-justified control-sidebar-tabs">
-      <li><a href="#control-sidebar-home-tab" data-toggle="tab"><i class="fa fa-home"></i></a></li>
-      <li><a href="#control-sidebar-settings-tab" data-toggle="tab"><i class="fa fa-gear"></i></a></li>
-    </ul>
-    <!-- Tab panes -->
-    <div class="tab-content">
-      <!-- Home tab content -->
-      <div class="tab-pane" id="control-sidebar-home-tab">
-
-      </div>
-      <!-- /.tab-pane -->
-
-      <!-- Settings tab content -->
-      <div class="tab-pane" id="control-sidebar-settings-tab">
-        <form method="post">
-          <h3 class="control-sidebar-heading">General Settings</h3>
-
-          <div class="form-group">
-            <label class="control-sidebar-subheading">
-              Expose author name in posts
-              <input type="checkbox" class="pull-right" checked>
-            </label>
-
-            <p>
-              Allow the user to show his name in blog posts
-            </p>
-          </div>
-          <!-- /.form-group -->
-        </form>
-      </div>
-      <!-- /.tab-pane -->
-    </div>
-  </aside>
-  <!-- /.control-sidebar -->
-  <!-- Add the sidebar's background. This div must be placed
+    </aside>
+    <!-- /.control-sidebar -->
+    <!-- Add the sidebar's background. This div must be placed
        immediately after the control sidebar -->
-  <div class="control-sidebar-bg"></div>
-
+    <div class="control-sidebar-bg"></div>
 </div>
 <!-- ./wrapper -->
 
@@ -273,4 +301,3 @@
 
 </body>
 </html>
-

comments