Procházet zdrojové kódy

Fresh Web GUI (based on bootstrap.js) (#19812)

Mauro před 3 roky
rodič
revize
4fe4fb0585
No account linked to committer's email address

+ 6
- 0
data/www/bootstrap.min.css
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 6
- 0
data/www/bootstrap.min.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 10
- 0
data/www/bootstrap4-toggle.min.js Zobrazit soubor

@@ -0,0 +1,10 @@
1
+/*\
2
+|*| ========================================================================
3
+|*| Bootstrap Toggle: bootstrap4-toggle.js v3.6.1
4
+|*| https://gitbrent.github.io/bootstrap4-toggle/
5
+|*| ========================================================================
6
+|*| Copyright 2018-2019 Brent Ely
7
+|*| Licensed under MIT
8
+|*| ========================================================================
9
+\*/
10
+!function(a){"use strict";function l(t,e){this.$element=a(t),this.options=a.extend({},this.defaults(),e),this.render()}l.VERSION="3.6.0",l.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"light",size:"normal",style:"",width:null,height:null},l.prototype.defaults=function(){return{on:this.$element.attr("data-on")||l.DEFAULTS.on,off:this.$element.attr("data-off")||l.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||l.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||l.DEFAULTS.offstyle,size:this.$element.attr("data-size")||l.DEFAULTS.size,style:this.$element.attr("data-style")||l.DEFAULTS.style,width:this.$element.attr("data-width")||l.DEFAULTS.width,height:this.$element.attr("data-height")||l.DEFAULTS.height}},l.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var t="large"===this.options.size||"lg"===this.options.size?"btn-lg":"small"===this.options.size||"sm"===this.options.size?"btn-sm":"mini"===this.options.size||"xs"===this.options.size?"btn-xs":"",e=a('<label for="'+this.$element.prop("id")+'" class="btn">').html(this.options.on).addClass(this._onstyle+" "+t),s=a('<label for="'+this.$element.prop("id")+'" class="btn">').html(this.options.off).addClass(this._offstyle+" "+t),o=a('<span class="toggle-handle btn btn-light">').addClass(t),i=a('<div class="toggle-group">').append(e,s,o),l=a('<div class="toggle btn" data-toggle="toggle" role="button">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(t).addClass(this.options.style);this.$element.wrap(l),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:e,$toggleOff:s,$toggleGroup:i}),this.$toggle.append(i);var n=this.options.width||Math.max(e.outerWidth(),s.outerWidth())+o.outerWidth()/2,h=this.options.height||Math.max(e.outerHeight(),s.outerHeight());e.addClass("toggle-on"),s.addClass("toggle-off"),this.$toggle.css({width:n,height:h}),this.options.height&&(e.css("line-height",e.height()+"px"),s.css("line-height",s.height()+"px")),this.update(!0),this.trigger(!0)},l.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},l.prototype.on=function(t){if(this.$element.prop("disabled"))return!1;this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),t||this.trigger()},l.prototype.off=function(t){if(this.$element.prop("disabled"))return!1;this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),t||this.trigger()},l.prototype.enable=function(){this.$toggle.removeClass("disabled"),this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},l.prototype.disable=function(){this.$toggle.addClass("disabled"),this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},l.prototype.update=function(t){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(t):this.off(t)},l.prototype.trigger=function(t){this.$element.off("change.bs.toggle"),t||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},l.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var t=a.fn.bootstrapToggle;a.fn.bootstrapToggle=function(o){var i=Array.prototype.slice.call(arguments,1)[0];return this.each(function(){var t=a(this),e=t.data("bs.toggle"),s="object"==typeof o&&o;e||t.data("bs.toggle",e=new l(this,s)),"string"==typeof o&&e[o]&&"boolean"==typeof i?e[o](i):"string"==typeof o&&e[o]&&e[o]()})},a.fn.bootstrapToggle.Constructor=l,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=t,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(t){a(this).find("input[type=checkbox]").bootstrapToggle("toggle"),t.preventDefault()})}(jQuery);

+ 234
- 0
data/www/chart.lineargauge.js Zobrazit soubor

@@ -0,0 +1,234 @@
1
+(function(Chart) {
2
+	var helpers = Chart.helpers;
3
+	var plugins = Chart.plugins;
4
+	Chart.defaults.global.animation.duration = 1000;
5
+
6
+	Chart.defaults._set('linearGauge', {
7
+		scale: {
8
+			type: 'linearGauge',
9
+			horizontal: false,
10
+			range: {
11
+				startValue: -100,
12
+				endValue: 500
13
+			},
14
+			responsive: true,
15
+			font: {
16
+				fontName: 'Arial',
17
+				fontSize: 12
18
+			},
19
+			axisWidth: 6,
20
+			ticks: {
21
+				majorTicks: {
22
+					interval: 100,
23
+					height: 1,
24
+				}
25
+			},
26
+			scaleLabel: {
27
+				display: true,
28
+				interval: 100,
29
+				units: '',
30
+				customValues: [],
31
+				offset: -10,
32
+				color: '#777b80'
33
+			}
34
+		},
35
+		padding: {
36
+			top: 0,
37
+			bottom: 0,
38
+			left: 0,
39
+			right: 0
40
+		},
41
+		tooltips: {
42
+			callbacks: {
43
+				label: function(tooltipItem, data) {
44
+					var label = data.datasets[tooltipItem.datasetIndex].label || '';
45
+
46
+					if (label) {
47
+						label += ': ';
48
+					}
49
+					label += Math.round(data.datasets[tooltipItem.datasetIndex].data[0] * 100) / 100;
50
+					return label;
51
+				}
52
+			}
53
+		},
54
+		legend: {
55
+			display: true,
56
+			labels: {
57
+				fontColor: 'rgb(0, 0, 0)'
58
+			},
59
+			position: 'bottom'
60
+		}
61
+	});
62
+
63
+	Chart.controllers.linearGauge = Chart.DatasetController.extend({
64
+
65
+		dataElementType: Chart.elements.Gaugerect,
66
+
67
+		initialize: function() {
68
+			var me = this;
69
+			var meta;
70
+
71
+			Chart.DatasetController.prototype.initialize.apply(me, arguments);
72
+
73
+			meta = me.getMeta();
74
+
75
+		},
76
+
77
+		linkScales: helpers.noop,
78
+
79
+		update: function(reset) {
80
+			var me = this;
81
+			var rects = me.getMeta().data;
82
+			var i, ilen;
83
+			me.datashifts = 0;
84
+
85
+			for (i = 0, ilen = rects.length; i < ilen; ++i) {
86
+				me.updateElement(rects[i], i, me.datashifts);
87
+				me.datashifts += 10;
88
+			}
89
+		},
90
+
91
+		updateElement: function(rectangle, index, reset) {
92
+			var me = this;
93
+			var chart = me.chart;
94
+			var meta = me.getMeta();
95
+			var dataset = me.getDataset();
96
+
97
+			var custom = rectangle.custom || {};
98
+			var rectangleOptions = chart.options.elements.rectangle;
99
+			var gaugeOptions = chart.options.elements.gaugerect;
100
+			rectangle._Scale = me.getScaleForId(chart.options.scale.id || 'gaugescale');
101
+			rectangle._datasetIndex = me.index;
102
+			rectangle._index = index;
103
+			rectangle.rangeColorImage = null;
104
+
105
+			//	Init element model
106
+			rectangle._model = {
107
+				datasetLabel: dataset.label,
108
+				label: chart.data.labels[index],
109
+				borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleOptions.borderSkipped,
110
+				backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, gaugeOptions.backgroundColor),
111
+				borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleOptions.borderColor),
112
+				borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleOptions.borderWidth)
113
+			};
114
+
115
+			//	Set empty view as start point for animation
116
+			if(typeof rectangle._view === 'undefined') rectangle._view = {};
117
+
118
+			me.updateElementGeometry(rectangle, index, reset);
119
+
120
+		},
121
+
122
+		updateElementGeometry: function(rectangle, index, reset) {
123
+			var me = this;
124
+			var model = rectangle._model;
125
+			var start = rectangle._view;
126
+			var dataset = me.getDataset().data;
127
+			var dopt = me.getDataset();
128
+			var chart = me.chart;
129
+			var datasets = chart.data.datasets;
130
+			var gaugeOptions = chart.options.elements.gaugerect;
131
+			var vscale = me.getScaleForId(chart.options.scale.id || 'gaugescale');
132
+			//var base = vscale.getBasePixel();
133
+			var base = vscale.getBase();
134
+			var horizontal = rectangle._Scale.isHorizontal();
135
+			//var ruler = me._ruler || me.getRuler();
136
+			var vpixels = me.calculateBarValuePixels(me.index, index, horizontal);
137
+
138
+			model.horizontal = horizontal;
139
+			model.base = base;
140
+			model.head = vpixels.head;
141
+			model.x = horizontal ? vpixels.base : vpixels.offset;
142
+			model.y = horizontal ? (vpixels.offset - (dopt.width || gaugeOptions.width)) : vpixels.head;
143
+			model.height = horizontal ? (dopt.width || gaugeOptions.width) : (vpixels.base - vpixels.head);
144
+			model.width = horizontal ? (vpixels.head - vpixels.base) : (dopt.width || gaugeOptions.width);
145
+			model.value = vscale.getRightValue(datasets[me.index].data[index]);
146
+
147
+			model.scaleValue = 0;
148
+			if (horizontal) {
149
+				model.scaleValue = vscale.width / (vscale.options.range.endValue - vscale.options.range.startValue);
150
+			} else {
151
+				model.scaleValue = vscale.height / (vscale.options.range.endValue - vscale.options.range.startValue);
152
+			}
153
+
154
+			if(typeof start.x === 'undefined' && typeof start.y === 'undefined'){
155
+				if(horizontal){
156
+					start.x = vpixels.base;
157
+					start.width = 0;
158
+				} else {
159
+					start.y = vpixels.base;
160
+					start.height = 0;
161
+				}
162
+			}
163
+
164
+		},
165
+
166
+		calculateBarValuePixels: function(datasetIndex, index, horizontal) {
167
+			var me = this;
168
+			var chart = me.chart;
169
+			var scale = me.getScaleForId(chart.options.scale.id || 'gaugescale');
170
+			var datasets = chart.data.datasets;
171
+			var dopt = datasets[datasetIndex];
172
+			var value = scale.getRightValue(datasets[datasetIndex].data[index]);
173
+			var stacked = scale.options.stacked;
174
+			var start = 0;
175
+			var i, imeta, ivalue, base, head, size, offset;
176
+
177
+			base = scale.scalePoint(start);
178
+			head = scale.scalePoint(start + value);
179
+			size = (head - base) / 2;
180
+			offset = horizontal ? scale.yCenter - dopt.offset : scale.xCenter + dopt.offset;
181
+
182
+			return {
183
+				size: size,
184
+				base: base,
185
+				head: head,
186
+				center: head + size / 2,
187
+				offset: offset
188
+			};
189
+		},
190
+
191
+		draw: function() {
192
+			var me = this;
193
+			var chart = me.chart;
194
+			var rects = me.getMeta().data;
195
+			var dataset = me.getDataset();
196
+			var ilen = rects.length;
197
+			var i = 0;
198
+
199
+			helpers.canvas.clipArea(chart.ctx, chart.chartArea);
200
+
201
+			for (; i < ilen; ++i) {
202
+				if (!isNaN(dataset.data[i])) {
203
+					rects[i].draw();
204
+				}
205
+			}
206
+
207
+			helpers.canvas.unclipArea(chart.ctx);
208
+		},
209
+
210
+		setHoverStyle: function(rectangle) {
211
+			var dataset = this.chart.data.datasets[rectangle._datasetIndex];
212
+			var index = rectangle._index;
213
+			var custom = rectangle.custom || {};
214
+			var model = rectangle._model;
215
+
216
+			model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.valueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
217
+			model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.valueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));
218
+			model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.valueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
219
+		},
220
+
221
+		removeHoverStyle: function(rectangle) {
222
+			var dataset = this.chart.data.datasets[rectangle._datasetIndex];
223
+			var index = rectangle._index;
224
+			var custom = rectangle.custom || {};
225
+			var model = rectangle._model;
226
+			var rectangleElementOptions = this.chart.options.elements.gaugerect;
227
+
228
+			model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);
229
+			model.borderColor = custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);
230
+			model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);
231
+		}
232
+
233
+	});
234
+}).call(this, Chart);

+ 7
- 0
data/www/chart.min.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 1
- 0
data/www/filesaver.min.js Zobrazit soubor

@@ -0,0 +1 @@
1
+(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open("","_blank"),g&&(g.document.title=g.document.body.innerText="downloading..."),"string"==typeof b)return c(b,d,e);var h="application/octet-stream"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\/[\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&"undefined"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g,"undefined"!=typeof module&&(module.exports=g)});

+ 22
- 0
data/www/index-ie.html Zobrazit soubor

@@ -0,0 +1,22 @@
1
+<!doctype html>
2
+<html lang="en">
3
+  <head>
4
+    <meta charset="UTF-8" />
5
+    <meta name="Title" content="Marlin WebUI" />
6
+    <meta name="Description" content="Marlin WebUI based on E4d@box WebUI" />
7
+    <meta name="Generator" content="E4d@box" />
8
+    <meta name="Owner" content="E4d@box" />
9
+    <meta name="Author" content="MandrakeDesign" />
10
+    <meta name="google" content="notranslate" />
11
+    <meta http-equiv="Content-Language" content="en_GB" />
12
+    <title>Marlin WebUI</title>
13
+    <link rel="shortcut icon" href="#" />
14
+  </head>
15
+  <body>
16
+    <div style="padding-top:100px; text-align:center">
17
+      <h1>Sorry, but MS Internet Explorer browser is not supported by this web application.<br>Please upgrade to Edge or use another browser</h1>
18
+      <br><br><br>
19
+      <h1>Marlin WebUI</h1>
20
+    </div>
21
+  </body>
22
+</html>

+ 737
- 25
data/www/index.html Zobrazit soubor

@@ -1,37 +1,749 @@
1
-<!doctype html>
2
-<html lang=en>
1
+<!doctype html>
2
+<html lang="en">
3 3
 <head>
4
-  <meta charset=utf-8>
5
-  <title>Marlin</title>
6
-
7
-  <link rel="stylesheet" type="text/css" href="marlin.css" />
8
-
9
-  <script type="text/javascript" src="marlin.js"></script>
4
+  <meta charset="UTF-8" />
5
+  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimal-ui,shrink-to-fit=no" />
6
+  <meta name="Title" content="Marlin WebUI" />
7
+  <meta name="Description" content="Marlin WebUI based on E4d@box WebUI" />
8
+  <meta name="Generator" content="E4d@box" />
9
+  <meta name="Owner" content="E4d@box" />
10
+  <meta name="Author" content="MandrakeDesign" />
11
+  <meta name="google" content="notranslate" />
12
+  <meta http-equiv="Content-Language" content="en_GB" />
13
+  <title>Marlin WebUI</title>
14
+  <link rel="shortcut icon" href="#" />
15
+  <link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
16
+  <link rel="stylesheet" type="text/css" href="webmarlin-font.css">
17
+  <link rel="stylesheet" type="text/css" href="webmarlin.css" />
18
+  <script>
19
+    var ua = window.navigator.userAgent;
20
+    var msie = ua.indexOf("MSIE ");
21
+    if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)){ top.location.replace('index-ie.html'); }
22
+    function hideAddressBar() { if(!window.location.hash) { if(document.height < window.outerHeight) { document.body.style.height = (window.outerHeight + 50) + 'px'; }
23
+        setTimeout( function(){ window.scrollTo(0, 1); }, 50 );
24
+    }}
25
+    window.addEventListener("load", function(){ if(!window.pageYOffset){ hideAddressBar(); } } );
26
+    window.addEventListener("orientationchange", hideAddressBar );
27
+  </script>
28
+  <script src="moment.min.js"></script>
29
+  <script src="webmarlin-class.js"></script>
10 30
 </head>
11 31
 <body>
12
-  <div class="tabs">
13
-    <div id="logo"></div>
14
-    <input class="input" name="tabs" type="radio" id="tab-1" checked="checked"/>
15
-    <label class="label" for="tab-1">console</label>
16
-    <div class="panel">
17
-      <div class="panel-content">
18
-        <ul id="serial-output"></ul>
32
+  <!-- Javascript sources ========================================================================================== -->
33
+  <script type="text/javascript" src="jquery-3.5.1.slim.min.js"></script>
34
+  <script type="text/javascript" src="jquery.browser.min.js"></script>
35
+  <script type="text/javascript" src="bootstrap.min.js"></script>
36
+  <script type="text/javascript" src="bootstrap4-toggle.min.js"></script>
37
+  <script async="" src="filesaver.min.js"></script>
38
+  <script type="text/javascript" src="chart.min.js"></script>
39
+  <script type="text/javascript" src="webmarlin.js"></script>
40
+
41
+  <!-- Accordion =================================================================================================== -->
42
+  <div id="main-panel" class="h-100 bg-secondary m-0 p-0">
43
+    <div class="container-fluid h-100 p-0">
44
+      <div class="accordion accordion-always-open h-100 d-flex flex-column bg-light" id="accordion-panels">
45
+
46
+        <!-- PANEL: Fixed Title ==================================================================================== -->
47
+        <div class="bg-dark text-light text-left p-2">
48
+          <span class="h4">Marlin WebUI </span> by atbox.tech
49
+          <button type="button" class="btn btn-sm btn-success float-right ml-1" data-toggle="modal" data-target="#modal-info" style="width:35px; height:33px"><i class="icon icon-info"></i></button>
50
+          <a href="http://marlinfw.org/" target="_blank" class="float-right"><img src="marlin-logo-dark.png" alt="MarlinLogo" width="100" height="33" /></a>
51
+        </div>
52
+
53
+        <!-- PANEL: Fixed connection status bar ==================================================================== -->
54
+        <div id="div-conn-statusbar" class="bg-danger text-light text-left p-1">
55
+          <div class="float-left font-italic h5 my-0 pl-1">
56
+            <span id="div-conn-statusico" class="badge badge-light mr-2" style="width:30px;"><i class="icon icon-plug"></i></span><span id="div-conn-statusmsg">Disconnected</span>
57
+          </div>
58
+          <div class="btn-toolbar float-right mr-1" role="toolbar">
59
+            <div class="btn-group mr-1" role="group">
60
+              <button type="button" id="btn-wsconnect" class="btn btn-sm btn-dark" style="width:35px; height:30px"><span id="btn-connect-status"><i class="icon icon-bolt"></i></span></button>
61
+            </div>
62
+            <div class="btn-group" role="group">
63
+              <button type="button" id="btn-settings" class="btn btn-sm btn-dark" style="width:35px; height:30px" data-toggle="modal" data-target="#modal-settings"><i class="icon icon-sliders"></i></button>
64
+            </div>
65
+          </div>
66
+        </div>
67
+
68
+        <!-- PANEL: Printer status ================================================================================= -->
69
+        <div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-status-head">
70
+          <button class="btn btn-sm btn-dark btn-block text-left" type="button" data-toggle="collapse" data-target="#accordion-panel-status-body" aria-expanded="true" aria-controls="accordion-panel-status-body">
71
+            <span class="h5"><span class="badge badge-success" style="width:30px;"><i class="icon icon-info-circled"></i></span><span class="ml-2">Status</span></span>
72
+            <div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
73
+          </button>
74
+        </div>
75
+        <div id="accordion-panel-status-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-status-head" data-parent="#accordion-panels">
76
+          <div class="card-body h-100 border-bottom p-1 text-left">
77
+            <div class="card mb-1 border-0">
78
+              <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-info mr-1 ml-1"></i>Printer status</div>
79
+              <div class="card-body px-0 py-1 bg-light badge-description">
80
+                <div class="border-bottom pb-1">
81
+                  Printing status <div id="div-pstatus-sdprint" class="badge badge-danger badge-description float-right pb-1">Idle</div>
82
+                </div>
83
+                <div id="div-pstatus-timer" class="border-bottom py-1 collapse">
84
+                  Printing timer
85
+                  <div class="float-right ml-1">Remain: <span id="div-pstatus-timer-remain" class="badge badge-info badge-description pb-1">0:45:12</span></div>
86
+                  <div class="float-right ml-1">Estimated: <span id="div-pstatus-timer-estimated" class="badge badge-info badge-description pb-1">1:12:34</span></div>
87
+                  <div class="float-right">Elapsed: <span id="div-pstatus-timer-elapsed" class="badge badge-info badge-description pb-1">0:00:00</span></div>
88
+                </div>
89
+                <div id="div-pstatus-progress" class="pt-1 collapse">
90
+                  Printing progress:
91
+                  <div id="div-pstatus-progress-percent" class="badge badge-info badge-description float-right pb-1">10%</div>
92
+                  <div id="div-pstatus-progress-bytes" class="badge badge-info badge-description float-right pb-1 mr-1">1 of 123456</div>
93
+                  <div class="progress mt-1" style="height: 10px;"><div class="progress-bar bg-success" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div></div>
94
+                </div>
95
+              </div>
96
+            </div>
97
+            <div class="card mb-1 border-0">
98
+              <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-thermometer mr-1 ml-1"></i>Temperatures</div>
99
+              <div class="card-body px-0 py-1 bg-light">
100
+                <div>
101
+                  Auto temperature detection
102
+                  <div class="float-right form-inline">
103
+                    <select id="auto-temp-interval" class="form-control form-control-sm mr-1" style="width:80px;" disabled>
104
+                      <option value="1">1 sec</option>
105
+                      <option value="5">5 sec</option>
106
+                      <option value="10">10 sec</option>
107
+                      <option value="30">30 sec</option>
108
+                      <option value="60">60 sec</option>
109
+                    </select>
110
+                    <input type="checkbox" id="set-auto-temp" data-input-type="togglebtn" data-size="sm" data-width="80" data-toggle="toggle" data-onstyle="success" data-offstyle="outline-dark" data-on="ON" data-off="OFF" disabled>
111
+                  </div>
112
+                </div>
113
+                <canvas id="chart-temps" height="150"></canvas>
114
+                <table class="w-100" cellpadding="0" cellspacing="0">
115
+                  <tr>
116
+                    <td width="40%">
117
+                      <div class="card mr-1">
118
+                        <div class="card-header py-0 px-1 bg-info text-light card-header-description">Sensor</div>
119
+                        <div class="card-body py-0 px-1 card-header-description">
120
+                          <table class="w-100">
121
+                            <tr><td class="border-bottom" style="height:28px;">Hotend (extruder) sensor</td></tr>
122
+                            <tr><td style="height:28px;">Bed sensor</td></tr>
123
+                          </table>
124
+                        </div>
125
+                      </div>
126
+                    </td>
127
+                    <td width="15%">
128
+                      <div class="card mr-1">
129
+                        <div class="card-header py-0 px-1 bg-info text-light card-header-description">Detected</div>
130
+                        <div class="card-body py-0 px-1 card-header-description text-right">
131
+                          <table class="w-100">
132
+                            <tr><td class="border-bottom" style="height:28px;"><div id="div-temp-extruder-detect">-</div></td></tr>
133
+                            <tr><td style="height:28px;"><div id="div-temp-bed-detect">-</div></td></tr>
134
+                          </table>
135
+                        </div>
136
+                      </div>
137
+                    </td>
138
+                    <td width="15%">
139
+                      <div class="card mr-1">
140
+                        <div class="card-header py-0 px-1 bg-info text-light card-header-description">Set</div>
141
+                        <div class="card-body py-0 px-1 card-header-description text-right">
142
+                          <table class="w-100">
143
+                            <tr><td class="border-bottom" style="height:28px;"><div id="div-temp-extruder-set">-</div></td></tr>
144
+                            <tr><td style="height:28px;"><div id="div-temp-bed-set">-</div></td></tr>
145
+                          </table>
146
+                        </div>
147
+                      </div>
148
+                    </td>
149
+                    <td width="15%">
150
+                      <div class="card mr-1">
151
+                        <div class="card-header py-0 px-1 bg-info text-light card-header-description">Unit</div>
152
+                        <div class="card-body py-0 px-1 card-header-description text-center">
153
+                          <table class="w-100">
154
+                            <tr><td class="border-bottom" style="height:28px;"><div id="div-temp-extruder-unit">-</div></td></tr>
155
+                            <tr><td style="height:28px;"><div id="div-temp-bed-unit">-</div></td></tr>
156
+                          </table>
157
+                        </div>
158
+                      </div>
159
+                    </td>
160
+                    <td width="20%">
161
+                      <div class="card">
162
+                        <div class="card-header py-0 px-1 bg-info text-light card-header-description">Chart display</div>
163
+                        <div class="card-body py-0 px-1 card-header-description text-center">
164
+                          <table class="w-100">
165
+                            <tr>
166
+                              <td class="border-bottom" style="height:28px;">
167
+                                <div class="custom-control custom-switch">
168
+                                  <input type="checkbox" class="custom-control-input" id="chart-show-extruder" checked disabled>
169
+                                  <label id="chart-show-extruder-label" class="custom-control-label" for="chart-show-extruder">Show</label>
170
+                                </div>
171
+                              </td>
172
+                            </tr>
173
+                            <tr>
174
+                              <td style="height:28px;">
175
+                                <div class="custom-control custom-switch">
176
+                                  <input type="checkbox" class="custom-control-input" id="chart-show-bed" checked disabled>
177
+                                  <label id="chart-show-bed-label" class="custom-control-label" for="chart-show-bed">Show</label>
178
+                                </div>
179
+                              </td>
180
+                            </tr>
181
+                          </table>
182
+                        </div>
183
+                      </div>
184
+                    </td>
185
+                  </tr>
186
+                </table>
187
+              </div>
188
+              <div class="card mb-1 border-0">
189
+                <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-refresh mr-1 ml-1"></i>Hotend fan speed</div>
190
+                <div class="card-body px-0 py-1 bg-light">
191
+                  <table width="100%" cellspacing="0" cellpadding="0" border="0">
192
+                    <tr>
193
+                      <td width="70%" valign="top" class="pr-2">
194
+                        <table class="w-100" cellspacing="0" cellpadding="0" border="0">
195
+                          <tr style="height:20px;">
196
+                            <td class="border-bottom card-header-description">Current fan speed</td>
197
+                            <td class="border-bottom card-header-description text-right"><div id="div-fan-speed-current">-</div></td>
198
+                          </tr>
199
+                          <tr style="height:20px;">
200
+                            <td class="border-bottom card-header-description">Set fan speed</td>
201
+                            <td class="border-bottom card-header-description text-right"><div id="div-fan-speed-set">-</div></td>
202
+                          </tr>
203
+                          <tr>
204
+                            <td colspan="2" class="card-header-description">
205
+                              <table class="w-100">
206
+                                <tr>
207
+                                  <td width="9%" class="text-left">OFF</td>
208
+                                  <td width="9%" class="text-center">10%</td>
209
+                                  <td width="9%" class="text-center">20%</td>
210
+                                  <td width="9%" class="text-center">30%</td>
211
+                                  <td width="9%" class="text-center">40%</td>
212
+                                  <td width="10%" class="text-center">50%</td>
213
+                                  <td width="9%" class="text-center">60%</td>
214
+                                  <td width="9%" class="text-center">70%</td>
215
+                                  <td width="9%" class="text-center">80%</td>
216
+                                  <td width="9%" class="text-center">90%</td>
217
+                                  <td width="9%" class="text-right">FULL</td>
218
+                                </tr>
219
+                              </table>
220
+                            </td>
221
+                          </tr>
222
+                          <tr><td colspan="2"><input type="range" class="custom-range" min="0" max="100" step="1" value="0" id="fan-speed-range" disabled></td></tr>
223
+                        </table>
224
+                      </td>
225
+                      <td width="30%"><canvas id="chart-fanspeed" height="70" width="100"></canvas></td>
226
+                    </tr>
227
+                  </table>
228
+                </div>
229
+              </div>
230
+            </div>
231
+          </div>
232
+        </div>
233
+
234
+        <!-- PANEL: Printer controls =============================================================================== -->
235
+        <div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-controls-head">
236
+          <button class="btn btn-sm btn-dark btn-block text-left" type="button" data-toggle="collapse" data-target="#accordion-panel-controls-body" aria-expanded="true" aria-controls="accordion-panel-controls-body">
237
+            <span class="h5"><span class="badge badge-success" style="width:30px;"><i class="icon icon-tasks"></i></span><span class="ml-2">Controls</span></span>
238
+            <div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
239
+          </button>
240
+        </div>
241
+        <div id="accordion-panel-controls-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-controls-head" data-parent="#accordion-panels">
242
+          <div class="card-body h-100 border-bottom p-1 text-left">
243
+
244
+            <div class="card mb-1 border-0">
245
+              <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-home mr-1 ml-1"></i>Home positioning</div>
246
+              <div class="card-body px-0 py-1 bg-light badge-description">
247
+                <table class="w-100" cellpadding="0" cellspacing="0">
248
+                  <tr>
249
+                    <td class="text-center text-light bg-info rounded-top">All axis</td>
250
+                    <td style="width:2px"></td>
251
+                    <td class="text-center text-light bg-info rounded-top">X axis</td>
252
+                    <td style="width:2px"></td>
253
+                    <td class="text-center text-light bg-info rounded-top">Y axis</td>
254
+                    <td style="width:2px"></td>
255
+                    <td class="text-center text-light bg-info rounded-top">Z axis</td>
256
+                  </tr>
257
+                  <tr>
258
+                    <td class="text-center"><button id="btn-move-home-all" type="button" class="btn btn-block btn-dark" style="border-radius:0px 0px 5px 5px;" disabled><i class="icon icon-home mr-1"></i><i class="icon icon-arrows"></i></button></td>
259
+                    <td style="width:2px"></td>
260
+                    <td class="text-center"><button id="btn-move-home-x" type="button" class="btn btn-block btn-dark" style="border-radius:0px 0px 5px 5px;" disabled><i class="icon icon-home mr-1"></i><i class="icon icon-arrows-h"></i></button></td>
261
+                    <td style="width:2px"></td>
262
+                    <td class="text-center"><button id="btn-move-home-y" type="button" class="btn btn-block btn-dark" style="border-radius:0px 0px 5px 5px;" disabled><i class="icon icon-home mr-1"></i><i class="icon icon-arrows-v"></i></button></td>
263
+                    <td style="width:2px"></td>
264
+                    <td class="text-center"><button id="btn-move-home-z" type="button" class="btn btn-block btn-dark" style="border-radius:0px 0px 5px 5px;" disabled><i class="icon icon-home mr-1"></i><i class="icon icon-angle-double-down"></i></button></td>
265
+                  </tr>
266
+                </table>
267
+              </div>
268
+            </div>
269
+
270
+            <div class="card mb-1 border-0">
271
+              <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-arrows-alt mr-1 ml-1"></i>Movements</div>
272
+              <div class="card-body px-0 py-1 bg-light badge-description">
273
+                <div class="list-group list-group-flush">
274
+                  <div class="list-group-item bg-light px-0 py-1">
275
+                    <label for="txt-move-steps" class="">Steps movements size (mm)</label>
276
+
277
+                    <div class="form-group">
278
+                      <input type="text" id="txt-move-steps" class="form-control form-control-sm float-right" value="10" style="width:80px"/>
279
+                      <input type="range" class="form-control-range" min="0" max="50" step="1" id="customRange3" value="10">
280
+                    </div>
281
+                  </div>
282
+                  <div class="list-group-item bg-light px-0 py-1">
283
+                    Move on X axis
284
+                    <button type="button" id="btn-move-xr" class="btn btn-sm btn-dark float-right" style="width:80px;"><i class="icon icon-long-arrow-right"></i></button>
285
+                    <button type="button" id="btn-move-xl" class="btn btn-sm btn-dark float-right mr-1" style="width:80px;"><i class="icon icon-long-arrow-left"></i></button>
286
+                  </div>
287
+                  <div class="list-group-item bg-light px-0 py-1">
288
+                    Move on Y axis
289
+                    <button type="button" id="btn-move-yb" class="btn btn-sm btn-dark float-right" style="width:80px;"><i class="icon icon-long-arrow-down"></i></button>
290
+                    <button type="button" id="btn-move-yf" class="btn btn-sm btn-dark float-right mr-1" style="width:80px;"><i class="icon icon-long-arrow-up"></i></button>
291
+                  </div>
292
+                  <div class="list-group-item bg-light px-0 py-1">
293
+                    Move on Z axis
294
+                    <button type="button" id="btn-move-zd" class="btn btn-sm btn-dark float-right" style="width:80px;"><i class="icon icon-angle-double-down"></i></button>
295
+                    <button type="button" id="btn-move-zu" class="btn btn-sm btn-dark float-right mr-1" style="width:80px;"><i class="icon icon-angle-double-up"></i></button>
296
+                  </div>
297
+                </div>
298
+              </div>
299
+            </div>
300
+
301
+            <div class="card mb-1 border-0">
302
+              <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-cog mr-1 ml-1"></i>Steppers locking</div>
303
+              <div class="card-body px-0 py-1 bg-light badge-description">
304
+                <table class="w-100" cellpadding="0" cellspacing="0">
305
+                  <tr>
306
+                    <td colspan="6" class="pb-1">
307
+                      Lock/Unlock all steppers (X, Y, Z, E)
308
+                    </td>
309
+                    <td class="pb-1">
310
+                      <input type="checkbox" class="float-right" id="set-stepper-all" data-input-type="togglebtn" data-size="sm" data-width="100%" data-toggle="toggle" data-onstyle="success" data-offstyle="outline-dark" data-on="Lock" data-off="Unlock" disabled>
311
+                    </td>
312
+                  </tr>
313
+                  <tr>
314
+                    <td class="text-center text-light bg-info rounded-top">X stepper</td>
315
+                    <td style="width:2px"></td>
316
+                    <td class="text-center text-light bg-info rounded-top">Y stepper</td>
317
+                    <td style="width:2px"></td>
318
+                    <td class="text-center text-light bg-info rounded-top">Z stepper</td>
319
+                    <td style="width:2px"></td>
320
+                    <td class="text-center text-light bg-info rounded-top">E stepper</td>
321
+                  </tr>
322
+                  <tr>
323
+                    <td class="text-center pt-1"><input type="checkbox" id="set-stepper-x" data-input-type="togglebtn" data-size="sm" data-width="100%" data-toggle="toggle" data-onstyle="success" data-offstyle="outline-dark" data-on="Locked" data-off="Unlocked" disabled></td>
324
+                    <td style="width:2px"></td>
325
+                    <td class="text-center pt-1"><input type="checkbox" id="set-stepper-y" data-input-type="togglebtn" data-size="sm" data-width="100%" data-toggle="toggle" data-onstyle="success" data-offstyle="outline-dark" data-on="Locked" data-off="Unlocked" disabled></td>
326
+                    <td style="width:2px"></td>
327
+                    <td class="text-center pt-1"><input type="checkbox" id="set-stepper-z" data-input-type="togglebtn" data-size="sm" data-width="100%" data-toggle="toggle" data-onstyle="success" data-offstyle="outline-dark" data-on="Locked" data-off="Unlocked" disabled></td>
328
+                    <td style="width:2px"></td>
329
+                    <td class="text-center pt-1"><input type="checkbox" id="set-stepper-e" data-input-type="togglebtn" data-size="sm" data-width="100%" data-toggle="toggle" data-onstyle="success" data-offstyle="outline-dark" data-on="Locked" data-off="Unlocked" disabled></td>
330
+                  </tr>
331
+                </table>
332
+
333
+                <div class="row mb-1">
334
+                  <div class="col">
335
+                  </div>
336
+                </div>
337
+              </div>
338
+            </div>
339
+
340
+            <div class="card mb-1 border-0">
341
+              <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-tencent-weibo mr-1 ml-1"></i>Filament</div>
342
+              <div class="card-body px-0 py-1 bg-light badge-description">
343
+              </div>
344
+            </div>
345
+
346
+          </div>
347
+        </div>
348
+
349
+        <!-- PANEL: File management ================================================================================ -->
350
+        <div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-file-head">
351
+          <button class="btn btn-sm btn-dark btn-block text-left" type="button" data-toggle="collapse" data-target="#accordion-panel-file-body" aria-expanded="true" aria-controls="accordion-panel-file-body">
352
+            <span class="h5"><span class="badge badge-success" style="width:30px;"><i class="icon icon-file"></i></span><span class="ml-2">File management</span></span>
353
+            <div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
354
+          </button>
355
+        </div>
356
+        <div id="accordion-panel-file-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-file-head" data-parent="#accordion-panels">
357
+          <div class="card-body h-100 p-1 text-left">
358
+            <div class="card mb-1 border-0">
359
+              <div class="card-header card-header-title text-light bg-secondary m-0 p-1"><i class="icon icon-upload mr-1 ml-1"></i>Upload...</div>
360
+              <div class="card-body px-0 py-1 bg-light">
361
+                <div class="input-group input-group-sm mb-1">
362
+                  <div class="custom-file">
363
+                    <input type="file" class="custom-file-input" id="file-upload" accept=".g,.gco,.gcode" aria-describedby="btn-file-upload" disabled>
364
+                    <label id="file-upload-label" class="custom-file-label" for="file-upload" data-browse='Pick'>Choose file</label>
365
+                  </div>
366
+                  <div class="input-group-append">
367
+                    <button id="btn-file-upload" class="btn btn-sm btn-success" type="button" disabled>Upload<i class="icon icon-upload ml-1"></i></button>
368
+                  </div>
369
+                </div>
370
+                <div id="upload-process-collapse" class="collapse mt-1">
371
+                  <table class="w-100 mb-1" cellspacing="0" cellpadding="0">
372
+                    <tr>
373
+                      <td width="34%">
374
+                        <div class="card mr-1">
375
+                          <div class="card-header py-0 px-1 bg-info text-light card-header-description">Filename (DOS8 Format)</div>
376
+                          <div id="div-upload-fname" class="card-body py-0 px-1 card-header-description text-center">-</div>
377
+                        </div>
378
+                      </td>
379
+                      <td width="33%">
380
+                        <div class="card">
381
+                          <div class="card-header py-0 px-1 bg-info text-light card-header-description">File size</div>
382
+                          <div id="div-upload-fsize" class="card-body py-0 px-1 card-header-description text-center">-</div>
383
+                        </div>
384
+                      </td>
385
+                      <td width="33%">
386
+                        <div class="card ml-1">
387
+                          <div class="card-header py-0 px-1 bg-info text-light card-header-description">GCode Lines</div>
388
+                          <div id="div-upload-fproc" class="card-body py-0 px-1 card-header-description text-center">-</div>
389
+                        </div>
390
+                      </td>
391
+                    </tr>
392
+                  </table>
393
+                  <div class="card">
394
+                    <div class="card-header py-0 px-1 bg-info text-light card-header-description">File processing</div>
395
+                    <table class="w-100" cellspacing="0" cellpadding="0">
396
+                      <tr>
397
+                        <td width="60%" class="p-1">
398
+                          <div id="upload-progress-text" class="card-header-description">&nbsp;</div>
399
+                          <div class="progress">
400
+                            <div id="upload-progressbar" class="progress-bar progress-bar-striped progress-bar-animated bg-info" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div>
401
+                          </div>
402
+                        </td>
403
+                        <td width="40%" class="p-1 text-right">
404
+                          <button id="btn-file-proc-cancel" class="btn btn-sm btn-danger" type="button" disabled>Cancel<i class="icon icon-ban ml-1"></i></button>
405
+                          <button id="btn-file-proc" class="btn btn-sm btn-info" type="button" disabled>Process<i class="icon icon-cog ml-1"></i></button>
406
+                        </td>
407
+                      </tr>
408
+                    </table>
409
+                  </div>
410
+                </div>
411
+              </div>
412
+            </div>
413
+            <div class="card mb-0 border-0">
414
+              <div class="card-header card-header-title text-white bg-secondary m-0 p-1"><i class="icon icon-file ml-1 mr-1"></i>SD Content management</div>
415
+              <div class="card-body px-0 py-1 bg-light">
416
+                <div>
417
+                  <button id="btn-get-sdcontent" class="btn btn-sm btn-success" disabled><i class="icon icon-angle-double-down mr-1"></i>Get content</button>
418
+                  <div class="btn-group float-right" role="group">
419
+                    <button id="btn-set-sdinit" class="btn btn-sm btn-outline-success" style="width:120px" disabled><i class="icon icon-long-arrow-down mr-1"></i>SD Init</button>
420
+                    <button id="btn-set-sdrelease" class="btn btn-sm btn-outline-success"  style="width:120px" disabled><i class="icon icon-long-arrow-up mr-1"></i>SD Release</button>
421
+                  </div>
422
+                </div>
423
+                <div id="div-sd-selected-file" class="collapse mt-1 show">
424
+                  <div class="input-group input-group-sm">
425
+                    <div class="input-group-prepend"><span class="input-group-text" id="lbl-sdfile-selected">Selected file:</span></div>
426
+                    <input type="text" id="txt-sdfile-selected" class="form-control" aria-describedby="lbl-sdfile-selected" value="" readonly/>
427
+                    <div class="input-group-append">
428
+                      <button id="btn-set-sdprint" class="btn btn-sm btn-success" data-toggle="modal" data-target="#modal-sdfile-print" onclick="WmButtons.PrintSdConfirm();" disabled><i class="icon icon-print"></i></button>
429
+                      <button id="btn-set-sddelete" class="btn btn-sm btn-danger" data-toggle="modal" data-target="#modal-sdfile-delete" onclick="WmButtons.DeleteSdConfirm();" disabled><i class="icon icon-trash"></i></button>
430
+                    </div>
431
+                  </div>
432
+                </div>
433
+              </div>
434
+            </div>
435
+            <div class="card mb-0 border-0">
436
+              <div class="card-header card-header-title text-white bg-secondary m-0 p-1">
437
+                <div class="float-right">Files: <div id="div-sdlist-file-count" class="badge badge-light">0</div></div>
438
+                <div class="float-right mr-1">Folders: <div id="div-sdlist-folder-count" class="badge badge-light">0</div></div>
439
+                <i class="icon icon-file ml-1 mr-1"></i>SD File list
440
+              </div>
441
+              <div class="card-body px-0 py-1 bg-light"><div id="list-sd-content" class="list-group list-group-flush"></div></div>
442
+            </div>
443
+          </div>
444
+        </div>
445
+
446
+        <!-- PANEL: Console ======================================================================================== -->
447
+        <div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-console-head">
448
+          <button class="btn btn-sm btn-dark btn-block text-left" type="button" data-toggle="collapse" data-target="#accordion-panel-console-body" aria-expanded="true" aria-controls="accordion-panel-console-body">
449
+            <span class="h5"><span class="badge badge-success" style="width:30px;"><i class="icon icon-terminal"></i></span><span class="ml-2">Console</span></span>
450
+            <div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
451
+            <div id="div-counter-badge" class="badge badge-secondary float-right mr-1"><span id="log-counter-badge" class="h5">0</span></div>
452
+          </button>
453
+        </div>
454
+        <div id="accordion-panel-console-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-console-head" data-parent="#accordion-panels">
455
+          <div class="card-body h-100 p-1 text-left">
456
+            <label for="text-gcommand" class="mb-0 field-labels">G-Code command:</label>
457
+            <div class="input-group">
458
+              <div class="input-group-prepend">
459
+                <a class="btn btn-sm btn-dark" target="_blank" href="http://marlinfw.org/meta/gcode/"><i class="icon icon-info"></i></a>
460
+                <button class="btn btn-sm btn-outline-dark" type="button" id="btn-gcommand-preset" data-toggle="modal" data-target="#modal-presets"><i class="icon icon-tasks"></i></button>
461
+              </div>
462
+              <input type="text" id="text-gcommand" class="form-control form-control-sm border-dark text-uppercase" value="" required>
463
+              <div class="input-group-append">
464
+                <button class="btn btn-sm btn-outline-dark" type="button" id="btn-gcommand-checksum" data-toggle="button" aria-pressed="false" onclick="WmButtons.ToggleChecksumDiv();"><i class="icon icon-check-square"></i></button>
465
+                <button class="btn btn-sm btn-dark mr-1" type="button" id="btn-gcommand">Send <i class="icon icon-chevron-right"></i></button>
466
+              </div>
467
+            </div>
468
+            <div id="checksum-gcommand-div" class="collapse m-0 pr-1 text-right">
469
+              <span class="field-description mr-1">GCode checksum value:</span>
470
+              <span class="h5"><span class="badge badge-secondary" id="checksum-gcommand-value" style="width:100px;">&nbsp;</span></span>
471
+            </div>
472
+            <div id="checksum-gcommand-div" class="input-group input-group-sm collapse my-1">
473
+              <input type="text" class="form-control" aria-describedby="checksum-gcommand-value" placeholder="GCode checksum value" readonly/>
474
+              <div class="input-group-append text-center"><span class="input-group-text" id="checksum-gcommand-value" style="width:100px;"></span></div>
475
+            </div>
476
+            <label for="btn-gcommand" class="mb-0 field-labels">Console output:</label>
477
+            <div class="border rounded p-0 mb-1 console-listbox text-left">
478
+              <ul class="list-group list-group-flush" id="gcommand-console-list"></ul>
479
+            </div>
480
+            <div class="row">
481
+              <div class="col"><button class="btn btn-sm btn-secondary btn-block" type="button" id="btn-clear-console"><i class="icon icon-ban mr-1"></i> Clear list</button></div>
482
+              <div class="col"><button class="btn btn-sm btn-success btn-block" type="button" id="btn-export-console"><i class="icon icon-angle-double-down mr-1"></i>Save..</button></div>
483
+            </div>
484
+          </div>
485
+        </div>
486
+
487
+      </div>
488
+    </div>
489
+  </div>
490
+
491
+  <!-- MODAL: About window ========================================================================================= -->
492
+  <div class="modal fade" id="modal-info" tabindex="-1" role="dialog" aria-hidden="true">
493
+    <div class="modal-dialog modal-popup" role="document">
494
+      <div class="modal-content">
495
+        <div class="modal-header bg-secondary text-light m-0 px-2 py-1">
496
+          <span class="h5 font-italic mt-1"><i class="icon icon-info mr-2"></i>Info...</span>
497
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
498
+        </div>
499
+        <div class="modal-body p-2 text-left">
500
+          <span class="h3">Marlin WebUI</span>
501
+          <p>Release date: January, 1 2020</p>
502
+          <p>
503
+            <i class="icon icon-github"></i> Github project: <a href="https://github.com/exilaus/E4d-box-project" target="_blank">E4d-box-project</a><br />
504
+            <i class="icon icon-facebook-square"></i> Facebook: <a href="https://www.facebook.com/groups/372792116726814/about/" target="_blank">E4d@box</a>
505
+          </p>
506
+          <p>Open source dependencies:</p>
507
+          <ul>
508
+            <li><a href="https://marlinfw.org/" target="_blank">Marlin firmware</a></li>
509
+            <li><a href="https://jquery.com/" target="_blank">JQuery 3.5.1 (slim version)</a></li>
510
+            <li><a href="https://getbootstrap.com/" target="_blank">Bootstrap v4.5.0</a></li>
511
+            <li><a href="https://gitbrent.github.io/bootstrap4-toggle/" target="_blank">Bootstrap4 toggle switch v3.6.1</a></li>
512
+            <li><a href="http://fontastic.me/">Fontastic</a>
513
+            <li><a href="https://www.chartjs.org/" target="_blank">Chart.js</a></li>
514
+            <li><a href="https://github.com/eligrey/FileSaver.js" target="_blank">FileSaver.js</a></li>
515
+          </ul>
516
+        </div>
517
+        <div class="modal-footer bg-secondary m-0 p-1"><button type="button" class="btn btn-dark btn-block" data-dismiss="modal">Close</button></div>
518
+      </div>
519
+    </div>
520
+  </div>
521
+
522
+  <!-- MODAL: Settings ============================================================================================= -->
523
+  <div class="modal fade" id="modal-settings" data-backdrop="static" tabindex="-1" role="dialog" aria-hidden="true">
524
+    <div class="modal-dialog modal-popup" role="document">
525
+      <div class="modal-content">
526
+        <div class="modal-header bg-secondary text-light m-0 px-2 py-1">
527
+          <span class="h5 font-italic mt-1"><i class="icon icon-sliders mr-2"></i>Settings..</span>
528
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
529
+        </div>
530
+        <div class="modal-body p-1 text-left">
531
+          <ul class="list-group list-group-flush">
532
+            <li class="list-group-item p-1">
533
+              <div class="row">
534
+                <div class="col-5 m-0">Auto connect:</div>
535
+                <div class="col-7 m-0"><input type="checkbox" id="set-auto-connect" data-size="sm" data-width="100" data-toggle="toggle" data-onstyle="success" data-offstyle="outline-dark" data-on="ON" data-off="OFF"></div>
536
+              </div>
537
+              <small class="form-text text-muted font-italic mt-0">If ON the application will try to connect automatically on start</small>
538
+            </li>
539
+            <li class="list-group-item p-1">
540
+              <div class="row">
541
+                <div class="col-5 m-0">Temp interval:</div>
542
+                <div class="col-7 m-0">
543
+                  <select class="form-control form-control-sm mb-1" id="set-default-autotemp">
544
+                    <option value="1">1 sec</option>
545
+                    <option value="5">5 sec</option>
546
+                    <option value="10">10 sec</option>
547
+                    <option value="30">30 sec</option>
548
+                    <option value="60">60 sec</option>
549
+                  </select>
550
+                </div>
551
+              </div>
552
+              <small class="form-text text-muted font-italic mt-0">Set the default temperature detection interval (secs)</small>
553
+            </li>
554
+            <li class="list-group-item p-1">
555
+              <div class="row">
556
+                <div class="col-5 m-0">Temp unit:</div>
557
+                <div class="col-7 m-0">
558
+                  <select class="form-control form-control-sm mb-1" id="set-default-tempunit">
559
+                    <option value="0">Celsius (default)</option>
560
+                    <option value="1">Fahrenheit</option>
561
+                    <option value="2">Kelvin</option>
562
+                  </select>
563
+                </div>
564
+              </div>
565
+              <small class="form-text text-muted font-italic mt-0">Set the default temperature unit</small>
566
+            </li>
567
+            <li class="list-group-item p-1">
568
+              <div class="row mb-0">
569
+                <div class="col-5 m-0">Default panel:</div>
570
+                <div class="col-7 m-0">
571
+                  <select class="form-control form-control-sm mb-1" id="set-default-panel">
572
+                    <option value="4">Console</option>
573
+                    <option value="1">Controls</option>
574
+                    <option value="0">Status (default)</option>
575
+                    <option value="2">Temperature</option>
576
+                    <option value="3">Upload</option>
577
+                  </select>
578
+                </div>
579
+              </div>
580
+              <small class="form-text text-muted font-italic mt-0">Set the default shown panel on start</small>
581
+            </li>
582
+            <li class="list-group-item p-1">
583
+              <div class="row">
584
+                <div class="col-5 m-0">Trace direction:</div>
585
+                <div class="col-7 m-0">
586
+                  <div class="btn-group btn-group-toggle" data-toggle="buttons">
587
+                    <label class="btn btn-sm btn-secondary"><input type="radio" name="set-trace-mode" id="set-trace-mode-append"><i class="icon icon-angle-double-down mr-1"></i>Append</label>
588
+                    <label class="btn btn-sm btn-secondary"><input type="radio" name="set-trace-mode" id="set-trace-mode-prepend"><i class="icon icon-angle-double-up mr-1"></i>Prepend</label>
589
+                  </div>
590
+                </div>
591
+              </div>
592
+              <small class="form-text text-muted font-italic mt-0">Set the console trace direction</small>
593
+            </li>
594
+            <li class="list-group-item p-1">
595
+              <div class="row">
596
+                <div class="col-5 m-0">Trace symbol</div>
597
+                <div class="col-7 m-0">
598
+                  <select class="form-control form-control-sm mb-1" id="set-log-symbol">
599
+                    <option value="icon">Icon</option>
600
+                    <option value="letter">Letter</option>
601
+                  </select>
602
+                  <div id="div-log-symbol-icon" class="collapse form-check-inline mb-0 h4">
603
+                    <select class="form-control form-control-sm mb-0 mr-1" id="set-log-symbol-icon">
604
+                      <option value="0">Chevron: U/D</option>
605
+                      <option value="2">Chevron: L/R</option>
606
+                      <option value="1">Arrow: U/D</option>
607
+                      <option value="3">Arrow: L/R</option>
608
+                    </select>
609
+                    <div id="div-log-symbol-icon-sample-s" class="badge badge-success mr-1"></div>
610
+                    <div id="div-log-symbol-icon-sample-r" class="badge badge-danger"></div>
611
+                  </div>
612
+                </div>
613
+              </div>
614
+              <small class="form-text text-muted font-italic mt-0">Set the console message direction symbol</small>
615
+            </li>
616
+            <li class="list-group-item p-1">
617
+              <div class="row">
618
+                <div class="col-5 m-0">Logging level</div>
619
+                <div class="col-7 m-0">
620
+                  <select class="form-control form-control-sm mb-1" id="set-log-level">
621
+                    <option value="0">Info (default)</option>
622
+                    <option value="1">Warning</option>
623
+                    <option value="2">Error</option>
624
+                    <option value="3">Debug</option>
625
+                    <option value="4">Verbose</option>
626
+                  </select>
627
+                </div>
628
+              </div>
629
+              <small class="form-text text-muted font-italic mt-0">Set the JavaScript logging level</small>
630
+            </li>
631
+          </ul>
632
+          <div class="collapse mt-2" id="div-save-setting-rs"><div class="card card-body border-success p-1 text-success text-center">Settings saved successfully</div></div>
633
+        </div>
634
+        <div class="modal-footer bg-secondary m-0 p-1">
635
+          <div class="row w-100">
636
+            <div class="col"><button type="button" class="btn btn-dark btn-block" id="btn-close-settings" data-dismiss="modal">Close</button></div>
637
+            <div class="col"><button type="button" class="btn btn-success btn-block" id="btn-save-settings">Save</button></div>
638
+          </div>
639
+        </div>
640
+      </div>
641
+    </div>
642
+  </div>
19 643
 
20
-        <form id="serial-command-form" autocomplete="off">
21
-          <div class="form-wrapper">
22
-            <input type="text" id="serial-command">
23
-            <input type="submit" value="Send">
644
+  <!-- MODAL: Presets command ====================================================================================== -->
645
+  <div class="modal fade" id="modal-presets" tabindex="-1" role="dialog" aria-labelledby="modal-presets-label" aria-hidden="true">
646
+    <div class="modal-dialog modal-popup" role="document">
647
+      <div class="modal-content">
648
+        <div class="modal-header bg-secondary text-light m-0 px-2 py-1">
649
+          <span class="h5 font-italic mt-1"><i class="icon icon-sliders mr-2"></i>GCommand presets</span>
650
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
651
+        </div>
652
+        <div class="modal-body p-1 text-left">
653
+          <div id="list-presets" class="list-group list-group-flush">
654
+            <li class="list-group-item p-1 bg-light field-labels">Replace {N} chars with the specific parameter that you need if present (ie: G1 X{0} => G1 X10)</li>
24 655
           </div>
25
-        </form>
656
+        </div>
657
+        <div class="modal-footer bg-secondary m-0 p-1"><button type="button" class="btn btn-dark btn-block" data-dismiss="modal">Close</button></div>
26 658
       </div>
27 659
     </div>
28
-    <input class="input" name="tabs" type="radio" id="tab-2"/>
29
-    <label class="label" for="tab-2">controls</label>
30
-    <div class="panel">
31
-      <div class="panel-content">
32
-        #controls
660
+  </div>
661
+
662
+  <!-- MODAL: Connect ============================================================================================== -->
663
+  <div class="modal fade" id="modal-connect" data-backdrop="static" tabindex="-1" role="dialog" aria-hidden="true">
664
+    <div class="modal-dialog modal-popup" role="document">
665
+      <div class="modal-content">
666
+        <div class="modal-header bg-warning text-dark m-0 px-2 py-1">
667
+          <span class="h5 font-italic mt-1"><i class="icon icon-exchange mr-2"></i>Connect...</span>
668
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
669
+        </div>
670
+        <div class="modal-body p-2 text-center my-4">
671
+          <i class="icon icon-exclamation-triangle"></i><br>Ooopsss!<br />Marlin firmware Web Socket is not connected.<br />Would you like connect it now?
672
+        </div>
673
+        <div class="modal-footer bg-secondary m-0 p-1">
674
+          <div class="row w-100">
675
+            <div class="col"><button type="button" class="btn btn-sm btn-dark btn-block" data-dismiss="modal">Cancel</button></div>
676
+            <div class="col"><button id="btn-wsconnect-modal" type="button" class="btn btn-sm btn-warning btn-block" data-dismiss="modal"><i class="icon icon-bolt mr-1"></i>Connect now</button></div>
677
+          </div>
678
+        </div>
33 679
       </div>
34 680
     </div>
35 681
   </div>
682
+
683
+  <!-- MODAL: SD file deletion confirmation  ======================================================================= -->
684
+  <div class="modal fade" id="modal-sdfile-delete" data-backdrop="static" role="dialog" tabindex="-1" aria-labelledby="modal-sdfile-label" aria-hidden="true">
685
+    <div class="modal-dialog modal-popup">
686
+      <div class="modal-content">
687
+        <div class="modal-header bg-secondary text-light m-0 px-2 py-1">
688
+          <span class="h5 font-italic mt-1"><i class="icon icon-exclamation-triangle mr-2"></i>Deletion confirmation</span>
689
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
690
+        </div>
691
+        <div class="modal-body p-1 text-center mt-4 mb-1">
692
+          <span class="h5"><i class="icon icon-exclamation-triangle"></i><br>Are you sure to delete<br><div id="div-sdfile-delete-badge" class="badge badge-danger"></div><br>SD card file?<br>
693
+          This operation cannot be undone.</span>
694
+          <div id="div-sdfile-delete-rs" class="collapse mt-2"><div class="card card-body border-success p-1 text-success text-center">File deleted successfully</div></div>
695
+        </div>
696
+        <div class="modal-footer bg-secondary m-0 p-1">
697
+          <div class="row w-100">
698
+            <div class="col"><button type="button" class="btn btn-sm btn-dark btn-block" data-dismiss="modal">No</button></div>
699
+            <div class="col"><button id="btn-sdfile-delete-modal" type="button" class="btn btn-sm btn-success btn-block"><i class="icon icon-trash mr-1"></i>Yes</button></div>
700
+          </div>
701
+        </div>
702
+      </div>
703
+    </div>
704
+  </div>
705
+
706
+  <!-- MODAL: SD file print confirmation  ======================================================================= -->
707
+  <div class="modal fade" id="modal-sdfile-print" data-backdrop="static" role="dialog" tabindex="-1" aria-labelledby="modal-sdfile-print" aria-hidden="true">
708
+    <div class="modal-dialog modal-popup">
709
+      <div class="modal-content">
710
+        <div class="modal-header bg-secondary text-light m-0 px-2 py-1">
711
+          <span class="h5 font-italic mt-1"><i class="icon icon-print mr-2"></i>Print confirmation</span>
712
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
713
+        </div>
714
+        <div class="modal-body p-1 text-center my-4">
715
+          <span class="h5"><i class="icon icon-print"></i><br>Are you sure to start printing of<br><div id="div-sdfile-print-badge" class="badge badge-success"></div></span>
716
+        </div>
717
+        <div id="div-sdfile-print-rs" class="collapse mt-2"><div class="card card-body border-success p-1 m-2 text-success text-center">Printing started successfully</div></div>
718
+        <div class="modal-footer bg-secondary m-0 p-1">
719
+          <div class="row w-100">
720
+            <div class="col"><button type="button" class="btn btn-sm btn-dark btn-block" data-dismiss="modal">No</button></div>
721
+            <div class="col"><button id="btn-sdfile-print-modal" type="button" class="btn btn-sm btn-success btn-block"><i class="icon icon-print mr-1"></i>Yes</button></div>
722
+          </div>
723
+        </div>
724
+      </div>
725
+    </div>
726
+  </div>
727
+
728
+  <!-- MODAL: Alert message  ======================================================================= -->
729
+  <div class="modal fade" id="modal-alert" data-backdrop="static" role="dialog" tabindex="-1" aria-labelledby="modal-alert" aria-hidden="true">
730
+    <div class="modal-dialog modal-popup">
731
+      <div class="modal-content">
732
+        <div class="modal-header bg-secondary text-light m-0 px-2 py-1">
733
+          <span class="h5 font-italic mt-1"><i class="icon icon-info-circled mr-2"></i>Message</span>
734
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
735
+        </div>
736
+        <div class="modal-body p-1 text-center my-4">
737
+          <span class="h5"><i class="icon icon-info-circled"></i><br><div id="div-alert-message"></div></span>
738
+        </div>
739
+        <div class="modal-footer bg-secondary m-0 p-1">
740
+          <div class="row w-100">
741
+            <div class="col"><button type="button" class="btn btn-sm btn-success btn-block" data-dismiss="modal">OK</button></div>
742
+          </div>
743
+        </div>
744
+      </div>
745
+    </div>
746
+  </div>
747
+
36 748
 </body>
37 749
 </html>

+ 2
- 0
data/www/jquery-3.5.1.slim.min.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 10
- 0
data/www/jquery.browser.min.js Zobrazit soubor

@@ -0,0 +1,10 @@
1
+/*!
2
+ * jQuery Browser Plugin 0.1.0
3
+ * https://github.com/gabceb/jquery-browser-plugin
4
+ * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors
5
+ * http://jquery.org/license
6
+ * Modifications Copyright 2015 Gabriel Cebrian
7
+ * https://github.com/gabceb
8
+ * Released under the MIT license
9
+ * Date: 23-11-2015
10
+ */!function(a){"function"==typeof define&&define.amd?define(["jquery"],function(b){return a(b)}):"object"==typeof module&&"object"==typeof module.exports?module.exports=a(require("jquery")):a(window.jQuery)}(function(a){"use strict";function b(a){void 0===a&&(a=window.navigator.userAgent),a=a.toLowerCase();var b=/(edge)\/([\w.]+)/.exec(a)||/(opr)[\/]([\w.]+)/.exec(a)||/(chrome)[ \/]([\w.]+)/.exec(a)||/(iemobile)[\/]([\w.]+)/.exec(a)||/(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("trident")>=0&&/(rv)(?::| )([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[],c=/(ipad)/.exec(a)||/(ipod)/.exec(a)||/(windows phone)/.exec(a)||/(iphone)/.exec(a)||/(kindle)/.exec(a)||/(silk)/.exec(a)||/(android)/.exec(a)||/(win)/.exec(a)||/(mac)/.exec(a)||/(linux)/.exec(a)||/(cros)/.exec(a)||/(playbook)/.exec(a)||/(bb)/.exec(a)||/(blackberry)/.exec(a)||[],d={},e={browser:b[5]||b[3]||b[1]||"",version:b[2]||b[4]||"0",versionNumber:b[4]||b[2]||"0",platform:c[0]||""};if(e.browser&&(d[e.browser]=!0,d.version=e.version,d.versionNumber=parseInt(e.versionNumber,10)),e.platform&&(d[e.platform]=!0),(d.android||d.bb||d.blackberry||d.ipad||d.iphone||d.ipod||d.kindle||d.playbook||d.silk||d["windows phone"])&&(d.mobile=!0),(d.cros||d.mac||d.linux||d.win)&&(d.desktop=!0),(d.chrome||d.opr||d.safari)&&(d.webkit=!0),d.rv||d.iemobile){var f="msie";e.browser=f,d[f]=!0}if(d.edge){delete d.edge;var g="msedge";e.browser=g,d[g]=!0}if(d.safari&&d.blackberry){var h="blackberry";e.browser=h,d[h]=!0}if(d.safari&&d.playbook){var i="playbook";e.browser=i,d[i]=!0}if(d.bb){var j="blackberry";e.browser=j,d[j]=!0}if(d.opr){var k="opera";e.browser=k,d[k]=!0}if(d.safari&&d.android){var l="android";e.browser=l,d[l]=!0}if(d.safari&&d.kindle){var m="kindle";e.browser=m,d[m]=!0}if(d.safari&&d.silk){var n="silk";e.browser=n,d[n]=!0}return d.name=e.browser,d.platform=e.platform,d}return window.jQBrowser=b(window.navigator.userAgent),window.jQBrowser.uaMatch=b,a&&(a.browser=window.jQBrowser),window.jQBrowser});

binární
data/www/marlin-logo-dark.png Zobrazit soubor


binární
data/www/marlin-logo.png Zobrazit soubor


+ 0
- 166
data/www/marlin.css Zobrazit soubor

@@ -1,166 +0,0 @@
1
-/* CSS reset */
2
-
3
-html, body, div, span, applet, object, iframe,
4
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
5
-a, abbr, acronym, address, big, cite, code,
6
-del, dfn, em, img, ins, kbd, q, s, samp,
7
-small, strike, strong, sub, sup, tt, var,
8
-b, u, i, center,
9
-dl, dt, dd, ol, ul, li,
10
-fieldset, form, label, legend,
11
-table, caption, tbody, tfoot, thead, tr, th, td,
12
-article, aside, canvas, details, embed,
13
-figure, figcaption, footer, header, hgroup,
14
-menu, nav, output, ruby, section, summary,
15
-time, mark, audio, video {
16
-  margin: 0;
17
-  padding: 0;
18
-  border: 0;
19
-  font-size: 100%;
20
-  font: inherit;
21
-  vertical-align: baseline;
22
-  font-family: Impact, Charcoal, sans-serif;
23
-  }
24
-article, aside, details, figcaption, figure,
25
-footer, header, hgroup, menu, nav, section {
26
-  display: block;
27
-  }
28
-body { line-height: 1; }
29
-ol, ul { list-style: none; }
30
-blockquote, q { quotes: none; }
31
-blockquote:before, blockquote:after,
32
-q:before, q:after { content: ''; content: none; }
33
-table {
34
-  border-collapse: collapse;
35
-  border-spacing: 0;
36
-  }
37
-
38
-/* Custom */
39
-
40
-/* Tabs */
41
-* { box-sizing: border-box; }
42
-body {
43
-  display: flex;
44
-  justify-content: center;
45
-  padding: 0px;
46
-  background: #1e1e1e;
47
-  color: #efefef;
48
-  }
49
-h1 {
50
-  margin: 0;
51
-  font-size: 2em;
52
-  }
53
-.tabs {
54
-  display: flex;
55
-  width: 100%;
56
-  flex-wrap: wrap;
57
-  background: #e5e5e5;
58
-  }
59
-.input {
60
-  position: absolute;
61
-  opacity: 0;
62
-  }
63
-.label {
64
-  width: 100%;
65
-  padding: 18px 28px;
66
-  background: #e5e5e5;
67
-  cursor: pointer;
68
-  font-weight: bold;
69
-  font-size: 18px;
70
-  color: #7f7f7f;
71
-  transition: background 0.1s, color 0.1s;
72
-  border-style: solid;
73
-  border-width: 0 0 4px 0;
74
-  border-color: #acacac;
75
-  }
76
-.label:hover {
77
-  background: #d8d8d8;
78
-  }
79
-.label:active {
80
-  background: #ccc;
81
-  }
82
-.input:focus + .label {
83
-  z-index: 1;
84
-  }
85
-.input:checked + .label {
86
-  background: #1e1e1e;
87
-  color: #efefef;
88
-  border-width: 4px 0 0 0;
89
-  border-color: #65a57d;
90
-  }
91
-.panel {
92
-  display: none;
93
-  width: 100%;
94
-  padding: 20px 30px 30px;
95
-  background: #1e1e1e;
96
-  color: #e5e5e5;
97
-  }
98
-.panel .panel-content {
99
-  width: 100%;
100
-  max-width: 800px;
101
-  }
102
-
103
-@media (min-width: 600px) {
104
-  .label { width: auto; }
105
-  .panel { order: 99; }
106
-}
107
-
108
-.input:checked + .label + .panel { display: block; }
109
-
110
-#logo {
111
-  width: 130px;
112
-  height: 58px;
113
-  margin-right: 20px;
114
-  background: url(marlin-logo.png) no-repeat center center;
115
-  }
116
-
117
-input[type="text"], textarea {
118
-  background-color: #2c2c2c;
119
-  border: solid 2px #314b3b;
120
-  color: #e5e5e5;
121
-  outline: none;
122
-  }
123
-
124
-input[type="text"]:focus, textarea:focus {
125
-  border-color: #4d7a5e;
126
-  }
127
-
128
-ul#serial-output {
129
-  width: 100%;
130
-  height: 300px;
131
-  overflow-y: scroll;
132
-  background-color: #2c2c2c;
133
-  border: solid 2px #314b3b;
134
-  }
135
-
136
-ul#serial-output li {
137
-  padding: 4px;
138
-  font-family: "Lucida Console", Monaco, monospace;
139
-  font-size: 0.8em;
140
-  }
141
-
142
-ul#serial-output li:nth-child(odd) {
143
-  background-color: #3c3c3c;
144
-  }
145
-
146
-div.form-wrapper {
147
-  display: flex;
148
-  width: 100%;
149
-  margin: 6px 0;
150
-  }
151
-
152
-div.form-wrapper input {
153
-  font-size: 1.2em;
154
-  padding: 4px 6px;
155
-  }
156
-
157
-div.form-wrapper input[type="text"] {
158
-  flex: 1 1 auto;
159
-  }
160
-
161
-div.form-wrapper input[type="submit"],
162
-div.form-wrapper button {
163
-  border: solid 2px #314b3b;
164
-  background-color: #4d7a5e;
165
-  color: #e5e5e5;
166
-  }

+ 0
- 24
data/www/marlin.js Zobrazit soubor

@@ -1,24 +0,0 @@
1
-document.addEventListener('DOMContentLoaded', () => {
2
-  const ws = new WebSocket(`ws://${location.host}/ws`);
3
-
4
-  ws.onmessage = (e) => {
5
-    if (typeof e.data === 'string') {
6
-      let node = document.createElement('li');
7
-      let text = document.createTextNode(e.data);
8
-      node.appendChild(text);
9
-      document.getElementById('serial-output').appendChild(node);
10
-    }
11
-  };
12
-
13
-  document.getElementById('serial-command-form').addEventListener('submit', (e) => {
14
-    e.preventDefault();
15
-
16
-    let value = document.getElementById('serial-command').value.trim();
17
-
18
-    if (!value) return;
19
-
20
-    ws.send(`${value}\n`);
21
-
22
-    document.getElementById('serial-command').value = '';
23
-  });
24
-});

binární
data/www/marlinui.eot Zobrazit soubor


+ 56
- 0
data/www/marlinui.svg Zobrazit soubor

@@ -0,0 +1,56 @@
1
+<?xml version="1.0" standalone="no"?>
2
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
3
+<svg xmlns="http://www.w3.org/2000/svg">
4
+<metadata>Generated by Fontastic.me</metadata>
5
+<defs>
6
+<font id="marlinui" horiz-adv-x="512">
7
+<font-face font-family="marlinui" units-per-em="512" ascent="480" descent="-32"/>
8
+<missing-glyph horiz-adv-x="512" />
9
+
10
+<glyph glyph-name="home" unicode="&#97;" d="M421 229l0-138c0-5-2-9-6-12-3-4-8-6-13-6l-109 0 0 110-74 0 0-110-109 0c-5 0-10 2-13 6-4 3-6 7-6 12l0 138c0 0 0 0 0 0 0 1 0 1 0 1l164 136 165-136c0 0 0-1 0-1z m63 19l-17-21c-2-2-4-3-6-3l-1 0c-3 0-5 1-6 2l-198 165-198-165c-2-2-4-2-7-2-2 0-4 1-6 3l-17 21c-2 2-2 4-2 7 0 3 1 5 3 6l205 171c6 5 14 8 22 8 8 0 16-3 22-8l69-58 0 56c0 2 1 5 3 6 2 2 4 3 7 3l54 0c3 0 5-1 7-3 2-1 3-4 3-6l0-117 62-52c2-1 3-3 3-6 0-3 0-5-2-7z"/>
11
+<glyph glyph-name="info" unicode="&#98;" d="M318 512c17 0 29-5 38-14 9-9 14-21 14-35 0-17-7-32-20-45-14-13-30-20-49-20-16 0-29 5-38 14-9 9-13 21-12 37 0 15 6 30 18 43 12 13 28 20 49 20m-105-512c-34 0-43 30-28 91 0 0 31 130 31 130 5 19 5 29 0 29-4 0-13-3-28-9-14-7-26-13-36-20 0 0-14 23-14 23 31 26 63 48 97 64 34 17 60 25 77 25 27 0 33-28 19-83 0 0-36-136-36-136-6-22-5-33 3-33 15 0 35 10 60 31 0 0 16-21 16-21-29-29-59-52-90-67-31-16-55-24-71-24"/>
12
+<glyph glyph-name="cog" unicode="&#99;" d="M329 256c0 20-7 37-21 52-15 14-32 21-52 21-20 0-37-7-52-21-14-15-21-32-21-52 0-20 7-37 21-52 15-14 32-21 52-21 20 0 37 7 52 21 14 15 21 32 21 52z m146 31l0-63c0-3 0-5-2-7-1-2-3-3-6-4l-52-8c-4-10-8-19-12-26 7-9 17-22 31-39 2-2 3-5 3-7 0-3-1-5-3-7-5-7-14-17-28-31-14-13-23-20-27-20-2 0-5 1-7 3l-40 31c-8-5-17-8-26-11-3-26-6-44-8-53-1-6-5-8-10-8l-64 0c-2 0-5 0-7 2-2 2-3 4-3 6l-8 53c-9 3-18 6-26 10l-40-30c-2-2-4-3-7-3-3 0-5 1-7 3-24 22-40 38-47 48-2 2-2 4-2 7 0 2 0 4 2 6 3 4 8 11 14 19 7 9 12 16 16 21-5 9-9 19-12 28l-52 8c-3 0-5 1-6 3-2 2-2 4-2 7l0 63c0 3 0 5 2 7 1 2 3 3 5 4l53 8c3 8 7 17 12 26-8 11-18 24-31 39-2 3-3 5-3 7 0 2 1 4 3 7 5 7 14 17 28 30 14 14 23 21 27 21 2 0 5-1 7-3l40-31c8 5 17 8 26 11 3 26 6 44 8 53 1 6 5 8 10 8l64 0c2 0 5 0 7-2 2-2 3-4 3-6l8-53c9-3 18-6 26-10l40 30c2 2 4 3 7 3 3 0 5-1 7-3 25-23 41-39 47-49 2-1 2-3 2-6 0-2 0-4-2-6-3-4-8-11-14-19-7-9-12-16-16-21 5-9 9-18 12-28l52-8c3 0 5-1 6-3 2-2 2-4 2-7z"/>
13
+<glyph glyph-name="tasks" unicode="&#100;" d="M293 110l182 0 0 36-182 0z m-110 146l292 0 0 37-292 0z m183 146l109 0 0 37-109 0z m146-237l0-74c0-5-2-9-5-12-4-4-8-6-13-6l-476 0c-5 0-9 2-13 6-3 3-5 7-5 12l0 74c0 5 2 9 5 12 4 4 8 6 13 6l476 0c5 0 9-2 13-6 3-3 5-7 5-12z m0 146l0-73c0-5-2-10-5-13-4-4-8-6-13-6l-476 0c-5 0-9 2-13 6-3 3-5 8-5 13l0 73c0 5 2 9 5 13 4 3 8 5 13 5l476 0c5 0 9-2 13-5 3-4 5-8 5-13z m0 146l0-73c0-5-2-9-5-13-4-3-8-5-13-5l-476 0c-5 0-9 2-13 5-3 4-5 8-5 13l0 73c0 5 2 9 5 13 4 4 8 5 13 5l476 0c5 0 9-1 13-5 3-4 5-8 5-13z"/>
14
+<glyph glyph-name="chevron-down" unicode="&#102;" d="M481 281l-212-212c-4-3-8-5-13-5-5 0-9 2-13 5l-212 212c-3 4-5 8-5 13 0 5 2 10 5 13l48 47c3 4 7 6 12 6 5 0 10-2 13-6l152-151 152 151c3 4 8 6 13 6 5 0 9-2 12-6l48-47c3-3 5-8 5-13 0-5-2-9-5-13z"/>
15
+<glyph glyph-name="chevron-left" unicode="&#103;" d="M408 426l-152-152 152-151c3-4 5-8 5-13 0-5-2-10-5-13l-48-48c-3-3-8-5-13-5-5 0-9 2-12 5l-212 212c-4 4-6 8-6 13 0 5 2 10 6 13l212 212c3 4 7 6 12 6 5 0 10-2 13-6l48-47c3-4 5-8 5-13 0-5-2-9-5-13z"/>
16
+<glyph glyph-name="chevron-right" unicode="&#104;" d="M389 261l-212-212c-3-3-7-5-12-5-5 0-10 2-13 5l-48 48c-3 3-5 8-5 13 0 5 2 9 5 13l152 151-152 152c-3 4-5 8-5 13 0 5 2 9 5 13l48 47c3 4 8 6 13 6 5 0 9-2 12-6l212-212c4-3 6-8 6-13 0-5-2-9-6-13z"/>
17
+<glyph glyph-name="chevron-up" unicode="&#105;" d="M481 132l-48-47c-3-4-7-6-12-6-5 0-10 2-13 6l-152 151-152-151c-3-4-8-6-13-6-5 0-9 2-12 6l-48 47c-3 3-5 8-5 13 0 5 2 9 5 13l212 211c4 4 8 6 13 6 5 0 9-2 13-6l212-211c3-4 5-8 5-13 0-5-2-10-5-13z"/>
18
+<glyph glyph-name="arrows-alt" unicode="&#106;" d="M403 357l-101-101 101-101 41 41c6 6 12 7 20 4 8-4 11-9 11-17l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-8 0-13 3-17 11-3 7-2 14 4 20l41 41-101 101-101-101 41-41c6-6 7-13 4-20-4-8-9-11-17-11l-128 0c-5 0-9 1-13 5-4 4-5 8-5 13l0 128c0 8 3 13 11 17 7 3 14 2 20-4l41-41 101 101-101 101-41-41c-4-3-8-5-13-5-2 0-5 0-7 1-8 4-11 9-11 17l0 128c0 5 1 9 5 13 4 4 8 5 13 5l128 0c8 0 13-3 17-11 3-7 2-14-4-20l-41-41 101-101 101 101-41 41c-6 6-7 13-4 20 4 8 9 11 17 11l128 0c5 0 9-1 13-5 4-4 5-8 5-13l0-128c0-8-3-13-11-17-2-1-5-1-7-1-5 0-9 2-13 5z"/>
19
+<glyph glyph-name="upload" unicode="&#107;" d="M384 91c0 5-2 10-5 13-4 4-8 6-13 6-5 0-10-2-13-6-4-3-6-8-6-13 0-5 2-9 6-12 3-4 8-6 13-6 5 0 9 2 13 6 3 3 5 7 5 12z m73 0c0 5-2 10-5 13-4 4-8 6-13 6-5 0-9-2-13-6-4-3-5-8-5-13 0-5 1-9 5-12 4-4 8-6 13-6 5 0 9 2 13 6 3 3 5 7 5 12z m37 64l0-91c0-8-3-14-8-19-6-6-12-8-20-8l-420 0c-8 0-14 2-20 8-5 5-8 11-8 19l0 91c0 8 3 15 8 20 6 5 12 8 20 8l122 0c4-11 10-20 20-26 9-7 20-11 31-11l74 0c11 0 22 4 31 11 10 6 16 15 20 26l122 0c8 0 14-3 20-8 5-5 8-12 8-20z m-93 186c-3-8-9-12-17-12l-73 0 0-128c0-5-2-9-6-13-3-3-7-5-12-5l-74 0c-5 0-9 2-12 5-4 4-6 8-6 13l0 128-73 0c-8 0-14 4-17 12-3 7-2 14 4 19l128 128c4 4 8 6 13 6 5 0 9-2 13-6l128-128c6-5 7-12 4-19z"/>
20
+<glyph glyph-name="ban" unicode="&#109;" d="M411 257c0 31-8 59-24 84l-216-215c26-17 55-25 85-25 21 0 41 4 60 12 20 8 36 19 50 33 14 14 25 31 33 50 8 19 12 40 12 61z m-285-86l216 216c-26 17-55 26-86 26-28 0-54-7-78-21-24-14-43-33-57-57-13-24-20-50-20-78 0-31 8-59 25-86z m349 86c0-30-5-59-17-86-12-27-27-51-47-70-19-20-43-35-70-47-27-12-55-17-85-17-30 0-58 5-85 17-27 12-51 27-70 47-20 19-35 43-47 70-12 27-17 56-17 86 0 30 5 58 17 85 12 28 27 51 47 71 19 19 43 35 70 46 27 12 55 18 85 18 30 0 58-6 85-18 27-11 51-27 70-46 20-20 35-43 47-71 12-27 17-55 17-85z"/>
21
+<glyph glyph-name="github" unicode="&#110;" d="M475 256c0-48-14-91-41-129-28-38-64-65-109-79-5-1-8-1-11 2-2 2-3 5-3 8l0 61c0 18-5 32-15 40 11 1 20 3 29 5 9 3 18 6 27 11 9 6 17 12 23 19 6 8 11 18 15 30 4 13 6 27 6 43 0 23-8 43-23 59 7 18 7 37-2 59-5 1-13 0-23-4-10-3-19-8-26-12l-11-7c-18 5-36 7-55 7-19 0-37-2-55-7-3 2-7 5-12 8-5 3-13 6-24 11-11 4-19 5-24 4-9-22-9-41-2-59-15-16-23-36-23-59 0-16 2-30 6-42 4-13 9-23 15-30 6-8 14-14 23-20 9-5 18-8 27-11 8-2 18-4 29-5-8-7-12-17-14-29-4-2-8-4-13-5-4-1-10-1-16-1-6 0-13 2-19 6-6 4-11 10-16 18-3 6-8 11-14 15-5 4-10 6-14 7l-5 1c-4 0-7-1-9-2-1-1-2-2-1-3 0-1 1-3 2-4 2-1 3-2 4-3l2-2c4-2 8-5 13-11 4-5 7-10 9-14l2-7c3-7 7-13 13-17 6-5 12-8 19-9 7-1 14-2 20-2 6 0 12 0 16 1l6 1c0-7 0-16 1-25 0-10 0-15 0-16 0-3-2-6-4-8-2-3-6-3-11-2-45 14-81 41-109 79-27 38-41 81-41 129 0 40 9 77 29 110 20 34 46 60 80 80 33 20 70 29 110 29 40 0 77-9 110-29 34-20 60-46 80-80 20-33 29-70 29-110z"/>
22
+<glyph glyph-name="thermometer" unicode="&#111;" d="M323 259c21-12 39-29 52-50 13-21 19-45 19-71 0-38-13-71-40-98-27-27-60-40-98-40-38 0-71 13-98 40-27 27-40 60-40 98 0 26 6 50 19 71 13 21 31 38 52 50 0 0 0 227 0 227 0 17 7 26 21 26 0 0 87 0 87 0 7 0 13-3 18-8 5-5 8-11 8-18 0 0 0-227 0-227m-67-208c24 0 44 9 61 26 18 17 26 37 26 61 0 19-5 36-16 51-11 15-26 26-43 31 0 0 0 190 0 190 0 0-52 0-52 0 0 0 0-189 0-189-18-5-33-16-45-31-12-15-18-33-18-52 0-24 8-44 26-61 17-17 37-26 61-26"/>
23
+<glyph glyph-name="bolt" unicode="&#101;" d="M381 350c3-4 4-8 2-12l-154-331c-3-5-7-7-12-7-1 0-3 0-4 1-4 1-6 2-8 5-1 3-2 6-1 9l56 230-116-28c0-1-2-1-3-1-4 0-7 1-9 3-3 3-5 7-4 12l58 235c0 3 2 5 4 7 3 2 5 2 8 2l94 0c4 0 7-1 9-3 3-3 4-5 4-9 0-1-1-3-2-5l-48-132 113 28c1 0 2 1 3 1 4 0 7-2 10-5z"/>
24
+<glyph glyph-name="sort-asc" unicode="&#112;" d="M402 311c0-5-2-9-5-13-4-4-8-5-13-5l-256 0c-5 0-9 1-13 5-3 4-5 8-5 13 0 5 2 9 5 13l128 128c4 3 8 5 13 5 5 0 9-2 13-5l128-128c3-4 5-8 5-13z"/>
25
+<glyph glyph-name="sort-desc" unicode="&#113;" d="M402 201c0-5-2-9-5-13l-128-128c-4-3-8-5-13-5-5 0-9 2-13 5l-128 128c-3 4-5 8-5 13 0 5 2 9 5 13 4 4 8 5 13 5l256 0c5 0 9-1 13-5 3-4 5-8 5-13z"/>
26
+<glyph glyph-name="long-arrow-left" unicode="&#114;" d="M512 283l0-54c0-3-1-5-3-7-1-2-3-3-6-3l-357 0 0-64c0-4-2-6-5-8-4-1-7-1-10 2l-110 100c-2 1-3 4-3 6 0 3 1 5 3 7l110 101c3 3 6 3 10 2 3-2 5-5 5-8l0-64 357 0c3 0 5-1 6-3 2-2 3-4 3-7z"/>
27
+<glyph glyph-name="long-arrow-down" unicode="&#115;" d="M365 141c1-4 1-7-2-10l-100-110c-1-2-4-3-6-3-3 0-5 1-7 3l-101 110c-3 3-3 6-2 10 2 3 5 5 8 5l64 0 0 357c0 3 1 5 3 6 2 2 4 3 7 3l54 0c3 0 5-1 7-3 2-1 3-3 3-6l0-357 64 0c4 0 6-2 8-5z"/>
28
+<glyph glyph-name="long-arrow-right" unicode="&#116;" d="M494 257c0-3-1-5-3-7l-110-101c-3-3-6-3-10-2-3 2-5 5-5 8l0 64-357 0c-3 0-5 1-6 3-2 2-3 4-3 7l0 54c0 3 1 5 3 7 1 2 3 3 6 3l357 0 0 64c0 4 2 6 5 8 4 1 7 1 10-2l110-100c2-1 3-4 3-6z"/>
29
+<glyph glyph-name="long-arrow-up" unicode="&#117;" d="M365 371c-2-3-5-5-8-5l-64 0 0-357c0-3-1-5-3-6-2-2-4-3-7-3l-54 0c-3 0-5 1-7 3-2 1-3 3-3 6l0 357-64 0c-4 0-6 2-8 5-1 4-1 7 2 10l100 110c1 2 4 3 6 3 3 0 5-1 7-3l101-110c3-3 3-6 2-10z"/>
30
+<glyph glyph-name="arrows" unicode="&#118;" d="M512 256c0-5-2-9-5-13l-74-73c-3-4-7-5-12-5-5 0-10 1-13 5-4 4-6 8-6 13l0 36-109 0 0-109 36 0c5 0 9-2 13-6 4-3 5-8 5-13 0-5-1-9-5-12l-73-74c-4-3-8-5-13-5-5 0-9 2-13 5l-73 74c-4 3-5 7-5 12 0 5 1 10 5 13 4 4 8 6 13 6l36 0 0 109-109 0 0-36c0-5-2-9-6-13-3-4-8-5-13-5-5 0-9 1-12 5l-74 73c-3 4-5 8-5 13 0 5 2 9 5 13l74 73c3 4 7 5 12 5 5 0 10-1 13-5 4-4 6-8 6-13l0-36 109 0 0 109-36 0c-5 0-9 2-13 6-4 3-5 8-5 13 0 5 1 9 5 12l73 74c4 3 8 5 13 5 5 0 9-2 13-5l73-74c4-3 5-7 5-12 0-5-1-10-5-13-4-4-8-6-13-6l-36 0 0-109 109 0 0 36c0 5 2 9 6 13 3 4 8 5 13 5 5 0 9-1 12-5l74-73c3-4 5-8 5-13z"/>
31
+<glyph glyph-name="arrows-v" unicode="&#119;" d="M347 421c0-5-1-10-5-13-4-4-8-6-13-6l-36 0 0-292 36 0c5 0 9-2 13-6 4-3 5-8 5-13 0-5-1-9-5-12l-73-74c-4-3-8-5-13-5-5 0-9 2-13 5l-73 74c-4 3-5 7-5 12 0 5 1 10 5 13 4 4 8 6 13 6l36 0 0 292-36 0c-5 0-9 2-13 6-4 3-5 8-5 13 0 5 1 9 5 12l73 74c4 3 8 5 13 5 5 0 9-2 13-5l73-74c4-3 5-7 5-12z"/>
32
+<glyph glyph-name="arrows-h" unicode="&#120;" d="M512 256c0-5-2-9-5-13l-74-73c-3-4-7-5-12-5-5 0-10 1-13 5-4 4-6 8-6 13l0 36-292 0 0-36c0-5-2-9-6-13-3-4-8-5-13-5-5 0-9 1-12 5l-74 73c-3 4-5 8-5 13 0 5 2 9 5 13l74 73c3 4 7 5 12 5 5 0 10-1 13-5 4-4 6-8 6-13l0-36 292 0 0 36c0 5 2 9 6 13 3 4 8 5 13 5 5 0 9-1 12-5l74-73c3-4 5-8 5-13z"/>
33
+<glyph glyph-name="angle-double-up" unicode="&#121;" d="M399 137c0-2-1-5-3-6l-15-15c-1-2-4-3-6-3-3 0-5 1-7 3l-112 113-112-113c-2-2-4-3-7-3-2 0-5 1-6 3l-15 15c-2 1-3 4-3 6 0 3 1 5 3 7l133 133c2 2 5 3 7 3 2 0 5-1 7-3l133-133c2-2 3-4 3-7z m0 110c0-3-1-5-3-7l-15-14c-1-2-4-3-6-3-3 0-5 1-7 3l-112 112-112-112c-2-2-4-3-7-3-2 0-5 1-6 3l-15 14c-2 2-3 4-3 7 0 2 1 5 3 6l133 134c2 1 5 2 7 2 2 0 5-1 7-2l133-134c2-1 3-4 3-6z"/>
34
+<glyph glyph-name="angle-double-down" unicode="&#122;" d="M399 265c0-2-1-5-3-6l-133-134c-2-1-5-2-7-2-2 0-5 1-7 2l-133 134c-2 1-3 4-3 6 0 3 1 5 3 7l15 14c1 2 4 3 6 3 3 0 5-1 7-3l112-112 112 112c2 2 4 3 7 3 2 0 5-1 6-3l15-14c2-2 3-4 3-7z m0 110c0-3-1-5-3-7l-133-133c-2-2-5-3-7-3-2 0-5 1-7 3l-133 133c-2 2-3 4-3 7 0 2 1 5 3 6l15 15c1 2 4 3 6 3 3 0 5-1 7-3l112-113 112 113c2 2 4 3 7 3 2 0 5-1 6-3l15-15c2-1 3-4 3-6z"/>
35
+<glyph glyph-name="tencent-weibo" unicode="&#65;" d="M314 349c0-16-6-29-17-39-10-11-23-17-38-17-12 0-22 4-32 10-12-12-23-26-33-41-47-71-66-153-58-246 0-4-1-8-3-11-3-3-6-5-10-5l-2 0c-3 0-7 1-10 4-2 2-4 6-4 9-3 24-3 48-1 71 2 23 4 44 8 62 4 18 9 36 15 53 7 18 14 32 20 45 7 12 14 24 21 35 12 18 24 33 38 48-3 6-5 14-5 22 0 15 6 28 17 39 10 10 23 16 39 16 15 0 28-6 39-16 10-11 16-24 16-39z m109-4c0-30-8-57-23-83-15-26-35-46-60-61-26-14-54-22-84-22-12 0-25 1-37 4-4 1-8 3-10 7-2 3-3 7-2 11 1 4 4 7 7 9 3 2 7 3 11 2 10-2 20-3 31-3 18 0 36 3 53 10 17 8 32 17 44 30 12 12 22 26 29 43 7 17 11 35 11 53 0 19-4 37-11 54-7 17-17 31-29 43-12 12-27 22-44 29-17 8-35 11-53 11-18 0-36-3-53-11-17-7-32-17-44-29-12-12-22-26-29-43-7-17-11-35-11-54 0-21 5-42 15-62 2-4 2-7 1-11-1-4-4-7-7-9-4-2-8-2-12-1-3 2-6 4-8 8-12 23-19 48-19 75 0 23 5 45 14 65 9 21 20 39 35 53 15 15 33 27 53 36 21 9 43 13 65 13 30 0 58-7 84-22 25-15 45-35 60-61 15-26 23-53 23-84z"/>
36
+<glyph glyph-name="playback-fast-forward" unicode="&#66;" d="M64 128l192 128-192 128z m384 128l-192 128 0-256z"/>
37
+<glyph glyph-name="fire" unicode="&#67;" d="M457 27l0-18c0-2-1-4-3-6-1-2-4-3-6-3l-384 0c-2 0-5 1-6 3-2 2-3 4-3 6l0 18c0 3 1 5 3 7 1 2 4 3 6 3l384 0c2 0 5-1 6-3 2-2 3-4 3-7z m-73 302c0-15-2-28-7-41-5-13-11-23-18-32-8-9-16-17-25-25-9-8-19-16-28-22-9-7-17-14-25-21-7-7-13-15-18-23-5-9-7-18-7-28 0-18 6-39 19-64l-1 0 0 0c-17 8-32 16-45 24-14 8-27 17-40 28-13 11-24 23-32 35-9 13-16 27-21 43-5 17-8 34-8 53 0 15 2 29 7 41 5 13 11 23 18 32 8 9 16 18 25 25 9 8 19 16 28 23 9 6 17 13 25 20 7 7 13 15 18 23 5 9 7 18 7 28 0 18-6 39-19 64l1 0 0 0c17-8 32-16 45-24 14-8 27-17 40-28 13-11 24-23 32-35 9-13 16-27 21-43 5-17 8-34 8-53z"/>
38
+<glyph glyph-name="forward" unicode="&#68;" d="M31 40c-3-3-7-5-9-3-2 1-4 4-4 9l0 420c0 5 2 8 4 9 2 2 6 0 9-3l203-203c2-2 3-3 4-6l0 203c0 5 1 8 3 9 3 2 6 0 10-3l202-203c4-4 6-8 6-13 0-5-2-9-6-13l-202-203c-4-3-7-5-10-3-2 1-3 4-3 9l0 203c-1-2-2-4-4-6z"/>
39
+<glyph glyph-name="terminal" unicode="&#69;" d="M448 448l-384 0c-18 0-32-14-32-32l0-320c0-17 14-32 32-32l384 0c17 0 32 15 32 32l0 320c0 18-15 32-32 32z m-352-224l64 64-64 64 32 32 96-96-96-96z m256-32l-128 0 0 32 128 0z"/>
40
+<glyph glyph-name="info-circled" unicode="&#108;" d="M253 492c65 0 120-22 167-67 46-45 70-100 72-165 0-65-22-121-68-167-45-47-100-71-165-73-65 0-121 22-167 68-47 45-71 100-72 165-1 65 21 121 67 167 46 47 101 71 166 72m27-78c-15 0-26-4-34-13-8-8-12-16-12-25 0-10 2-17 8-23 6-5 14-8 25-8 13 0 24 4 31 11 8 8 12 17 12 28 0 20-10 30-30 30m-62-304c10 0 25 4 43 13 19 9 37 22 54 40 0 0-9 12-9 12-16-12-28-18-37-18-4 0-5 6-2 19 0 0 22 82 22 82 9 33 5 49-11 49-11 0-26-5-46-15-20-10-40-22-59-38 0 0 8-13 8-13 18 11 31 17 38 17 4 0 4-6 0-17 0 0-18-78-18-78-9-36-3-53 17-53"/>
41
+<glyph glyph-name="exclamation-triangle" unicode="&#70;" d="M293 119l0 54c0 3-1 5-3 7-2 2-4 3-7 3l-54 0c-3 0-5-1-7-3-2-2-3-4-3-7l0-54c0-3 1-5 3-7 2-1 4-2 7-2l54 0c3 0 5 1 7 2 2 2 3 4 3 7z m-1 107l5 131c0 2-1 4-3 6-2 2-4 3-7 3l-62 0c-3 0-5-1-7-3-2-2-3-4-3-6l5-131c0-2 1-3 3-5 1-1 4-2 6-2l53 0c3 0 5 1 7 2 2 2 3 3 3 5z m-4 267l219-402c7-12 7-24 0-36-3-6-8-10-13-14-6-3-12-4-19-4l-438 0c-7 0-13 1-19 4-5 4-10 8-13 14-7 12-7 24 0 36l219 402c3 6 8 10 13 14 6 3 12 5 19 5 7 0 13-2 19-5 5-4 10-8 13-14z"/>
42
+<glyph glyph-name="exchange" unicode="&#71;" d="M512 174l0-55c0-3-1-5-3-7-2-1-4-2-6-2l-393 0 0-55c0-3-1-5-3-7-2-1-4-2-6-2-3 0-5 1-7 3l-91 91c-2 2-3 4-3 6 0 3 1 5 3 7l91 91c2 2 4 3 7 3 2 0 4-1 6-3 2-2 3-4 3-6l0-55 393 0c2 0 4-1 6-3 2-2 3-4 3-6z m0 155c0-3-1-5-3-6l-91-92c-2-2-4-2-7-2-2 0-4 0-6 2-2 2-3 4-3 7l0 55-393 0c-2 0-4 0-6 2-2 2-3 4-3 7l0 55c0 2 1 4 3 6 2 2 4 3 6 3l393 0 0 55c0 2 1 4 3 6 2 2 4 3 6 3 3 0 5-1 7-3l91-91c2-2 3-4 3-7z"/>
43
+<glyph glyph-name="plus" unicode="&#72;" d="M457 302l0-55c0-8-3-14-8-20-5-5-12-8-19-8l-119 0 0-118c0-8-3-15-8-20-5-5-12-8-20-8l-54 0c-8 0-15 3-20 8-5 5-8 12-8 20l0 118-119 0c-7 0-14 3-19 8-5 6-8 12-8 20l0 55c0 7 3 14 8 19 5 5 12 8 19 8l119 0 0 119c0 8 3 14 8 19 5 6 12 8 20 8l54 0c8 0 15-2 20-8 5-5 8-11 8-19l0-119 119 0c7 0 14-3 19-8 5-5 8-12 8-19z"/>
44
+<glyph glyph-name="minus" unicode="&#73;" d="M457 302l0-55c0-8-3-14-8-20-5-5-12-8-19-8l-348 0c-7 0-14 3-19 8-5 6-8 12-8 20l0 55c0 7 3 14 8 19 5 5 12 8 19 8l348 0c7 0 14-3 19-8 5-5 8-12 8-19z"/>
45
+<glyph glyph-name="check-square" unicode="&#74;" d="M232 141l176 175c3 4 5 8 5 13 0 5-2 9-5 13l-29 29c-4 4-8 6-13 6-5 0-10-2-13-6l-134-133-60 60c-3 4-8 5-13 5-5 0-9-1-13-5l-29-29c-3-4-5-8-5-13 0-5 2-9 5-13l103-102c3-4 7-6 12-6 5 0 10 2 13 6z m243 252l0-274c0-23-8-42-24-58-16-16-35-24-58-24l-274 0c-23 0-42 8-58 24-16 16-24 35-24 58l0 274c0 23 8 42 24 58 16 16 35 24 58 24l274 0c23 0 42-8 58-24 16-16 24-35 24-58z"/>
46
+<glyph glyph-name="facebook-square" unicode="&#75;" d="M393 475c23 0 42-8 58-24 16-16 24-35 24-58l0-274c0-23-8-42-24-58-16-16-35-24-58-24l-54 0 0 170 57 0 9 66-66 0 0 42c0 11 3 19 7 24 5 5 13 8 26 8l35 0 0 60c-12 1-29 2-51 2-26 0-46-7-62-23-15-15-23-36-23-64l0-49-57 0 0-66 57 0 0-170-152 0c-23 0-42 8-58 24-16 16-24 35-24 58l0 274c0 23 8 42 24 58 16 16 35 24 58 24z"/>
47
+<glyph glyph-name="file" unicode="&#76;" d="M329 366l0 135c4-3 8-6 10-8l117-117c3-3 5-6 8-10z m-36-9c0-8 2-15 8-20 5-5 11-8 19-8l155 0 0-302c0-7-2-14-8-19-5-5-11-8-19-8l-384 0c-8 0-14 3-19 8-6 5-8 12-8 19l0 458c0 7 2 14 8 19 5 5 11 8 19 8l229 0z"/>
48
+<glyph glyph-name="trash" unicode="&#77;" d="M201 119l0 201c0 3-1 5-2 7-2 1-4 2-7 2l-18 0c-3 0-5-1-7-2-2-2-2-4-2-7l0-201c0-3 0-5 2-7 2-1 4-2 7-2l18 0c3 0 5 1 7 2 1 2 2 4 2 7z m73 0l0 201c0 3-1 5-2 7-2 1-4 2-7 2l-18 0c-3 0-5-1-7-2-1-2-2-4-2-7l0-201c0-3 1-5 2-7 2-1 4-2 7-2l18 0c3 0 5 1 7 2 1 2 2 4 2 7z m73 0l0 201c0 3 0 5-2 7-2 1-4 2-7 2l-18 0c-3 0-5-1-7-2-1-2-2-4-2-7l0-201c0-3 1-5 2-7 2-1 4-2 7-2l18 0c3 0 5 1 7 2 2 2 2 4 2 7z m-155 283l128 0-14 34c-1 1-3 2-5 3l-90 0c-2-1-4-2-5-3z m265-9l0-18c0-3-1-5-2-7-2-1-4-2-7-2l-27 0 0-271c0-16-5-30-14-41-9-12-20-17-32-17l-238 0c-12 0-23 5-32 16-9 11-14 25-14 41l0 272-27 0c-3 0-5 1-7 2-1 2-2 4-2 7l0 18c0 3 1 5 2 7 2 1 4 2 7 2l88 0 20 48c3 7 8 13 16 18 7 5 15 7 22 7l92 0c7 0 15-2 22-7 8-5 13-11 16-18l20-48 88 0c3 0 5-1 7-2 1-2 2-4 2-7z"/>
49
+<glyph glyph-name="print" unicode="&#78;" d="M128 73l256 0 0 73-256 0z m0 183l256 0 0 110-46 0c-7 0-14 2-19 8-5 5-8 12-8 19l0 46-183 0z m329-18c0 5-2 9-5 13-4 3-8 5-13 5-5 0-9-2-13-5-4-4-5-8-5-13 0-5 1-10 5-13 4-4 8-6 13-6 5 0 9 2 13 6 3 3 5 8 5 13z m37 0l0-119c0-3-1-5-3-7-2-1-4-2-6-2l-64 0 0-46c0-8-3-14-8-19-6-6-12-8-20-8l-274 0c-8 0-14 2-20 8-5 5-8 11-8 19l0 46-64 0c-2 0-4 1-6 2-2 2-3 4-3 7l0 119c0 15 6 28 16 38 11 11 24 17 39 17l18 0 0 155c0 8 3 14 8 19 6 6 12 8 20 8l192 0c7 0 16-1 25-5 9-4 16-9 22-14l43-43c5-6 10-13 14-22 4-9 6-18 6-25l0-73 18 0c15 0 28-6 39-17 10-10 16-23 16-38z"/>
50
+<glyph glyph-name="refresh" unicode="&#79;" d="M468 210c0-1 0-1 0-2-12-51-38-92-77-124-38-32-84-47-136-47-28 0-55 5-81 15-26 11-49 26-69 45l-37-37c-4-3-8-5-13-5-5 0-9 2-13 5-4 4-5 8-5 13l0 128c0 5 1 9 5 13 4 4 8 5 13 5l128 0c5 0 9-1 13-5 3-4 5-8 5-13 0-5-2-9-5-13l-39-39c13-12 28-22 46-29 17-7 35-10 53-10 26 0 49 6 71 18 23 13 40 30 54 51 2 4 7 15 15 34 1 4 4 6 8 6l55 0c3 0 5 0 7-2 1-2 2-4 2-7z m7 229l0-128c0-5-1-9-5-13-4-4-8-5-13-5l-128 0c-5 0-9 1-13 5-3 4-5 8-5 13 0 5 2 9 5 13l40 39c-28 26-62 39-100 39-26 0-49-6-71-18-23-13-40-30-54-51-2-4-7-15-15-34-1-4-4-6-8-6l-57 0c-3 0-5 0-7 2-1 2-2 4-2 7l0 2c12 51 38 92 77 124 39 32 85 47 137 47 28 0 55-5 81-15 26-11 50-26 70-45l37 37c4 3 8 5 13 5 5 0 9-2 13-5 4-4 5-8 5-13z"/>
51
+<glyph glyph-name="plug" unicode="&#81;" d="M502 410l-1 0c-12 12-32 12-45 0l-22-23-46 46 23 22c13 13 13 33 0 45l0 1c-13 12-33 12-45 0l-24-24c-31 20-73 17-101-11l-12-12c-55-54-61-139-20-200l-2-2c-31-32-31-82 0-113 6-7 6-17 0-23-6-7-16-6-22 0l-45 44c-31 32-82 32-114 1-31-31-31-82 0-113l5-5c12-12 32-12 44 0l1 1c12 12 12 32 0 45l-4 4c-6 6-7 16-1 22 6 7 17 7 23 1l45-45c31-31 83-32 114 0 31 31 31 81 0 113-7 6-7 16 0 22l2 2c61-41 146-35 200 20l13 12c27 28 30 70 10 101l24 24c12 12 12 32 0 45z m-57-147c-19-19-49-19-68 0l-113 113c-19 19-19 49 0 68 15 15 37 18 55 9l-21-21c-13-12-13-32 0-45l0 0c12-12 32-12 45 0l23 23 45-45-23-23c-12-13-12-33 0-45l1 0c12-13 32-13 44 0l21 20c9-17 6-39-9-54z"/>
52
+<glyph glyph-name="wifi" unicode="&#82;" d="M256 416c-80 0-156-30-214-84l-10-10 10-9 32-32 10-10 9 9c45 41 102 64 163 64 60 0 118-23 163-64l9-9 10 10 32 32 10 9-10 10c-58 54-134 84-214 84z m141-160c-38 35-88 54-141 54l-9 0 0 0c-49-2-96-21-132-54l-11-10 10-10 33-32 9-9 10 8c25 22 57 35 90 35 33 0 65-13 91-35l9-8 9 9 33 32 10 10z m-141-160l10 9 53 53 10 10-11 10c-16 11-33 20-62 20-29 0-45-10-61-20l-12-10 11-10 53-53z"/>
53
+<glyph glyph-name="sliders" unicode="&#80;" d="M137 110l0-37-100 0 0 37z m101 36c5 0 9-2 13-5 3-4 5-8 5-13l0-73c0-5-2-9-5-13-4-4-8-5-13-5l-73 0c-5 0-10 1-13 5-4 4-6 8-6 13l0 73c0 5 2 9 6 13 3 3 8 5 13 5z m45 110l0-37-246 0 0 37z m-182 146l0-36-64 0 0 36z m374-292l0-37-210 0 0 37z m-274 329c5 0 9-2 13-6 4-3 5-7 5-12l0-74c0-5-1-9-5-12-4-4-8-6-13-6l-73 0c-5 0-9 2-13 6-3 3-5 7-5 12l0 74c0 5 2 9 5 12 4 4 8 6 13 6z m183-146c5 0 9-2 13-6 3-3 5-8 5-13l0-73c0-5-2-9-5-13-4-3-8-5-13-5l-73 0c-5 0-9 2-13 5-4 4-5 8-5 13l0 73c0 5 1 10 5 13 4 4 8 6 13 6z m91-37l0-37-64 0 0 37z m0 146l0-36-246 0 0 36z"/>
54
+<glyph glyph-name="folder-open" unicode="&#84;" d="M501 241c0-5-3-11-8-18l-90-105c-7-9-18-17-32-23-14-7-26-10-38-10l-290 0c-6 0-12 1-16 4-5 2-8 6-8 11 0 6 3 12 9 18l89 105c8 10 19 17 32 24 14 6 27 9 39 9l290 0c6 0 11-1 16-3 5-3 7-7 7-12z m-91 92l0-43-222 0c-17 0-34-4-53-13-18-8-33-19-44-31l-89-106-2-2c0 1 0 2 0 4 0 1 0 2 0 3l0 256c0 16 6 30 18 42 11 12 25 18 42 18l85 0c16 0 30-6 42-18 12-12 18-26 18-42l0-8 145 0c16 0 30-6 42-18 12-12 18-26 18-42z"/>
55
+<glyph glyph-name="code-download" unicode="&#83;" d="M331 228c6 6 6 17 0 23-7 7-17 7-24 0l-35-34 0 118c0 10-7 17-16 17-9 0-16-7-16-17l0-118-35 34c-6 7-17 7-24 0-6-6-6-17 0-23l63-63c0 0 0 0 0 0 1-1 2-2 3-2 0 0 0 0 0 0 0-1 1-1 1-1 0 0 0 0 0 0 1 0 1-1 2-1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 1-1 3-1 4-1 2 0 3 0 4 1 1 0 1 0 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 1 0 1 1 2 1 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 1 0 1 0 2 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0z m-163-108c-6 0-12 2-17 7l-112 112c-9 9-9 25 0 34l112 112c9 9 25 9 34 0 9-9 9-25 0-34l-95-95 95-95c9-9 9-25 0-34-5-5-11-7-17-7z m176 0c6 0 12 2 17 7l112 112c9 9 9 25 0 34l-112 112c-9 9-25 9-34 0-9-9-9-25 0-34l95-95-95-95c-9-9-9-25 0-34 5-5 11-7 17-7z"/>
56
+</font></defs></svg>

binární
data/www/marlinui.ttf Zobrazit soubor


binární
data/www/marlinui.woff Zobrazit soubor


+ 7
- 0
data/www/moment.min.js
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 426
- 0
data/www/webmarlin-class.js Zobrazit soubor

@@ -0,0 +1,426 @@
1
+var wmEnums = {
2
+  Panels           : { STATUS:0, CONTROLS:1, FILES:2, CONSOLE:3 },
3
+  ConsoleDirection : { APPEND:0, PREPEND:1 },
4
+  ConsoleLevels    : { ERROR:0, SUCCESS:1, INFO:2, MONITOR:3, WARNING:4},
5
+  WSMsgDirection   : { SENT:0, RECEIVED:1 },
6
+  WsMsgSymbols     : { SENT:{LETTER:"S",ICON:null}, RECEIVED:{LETTER:"R",ICON:null} },
7
+  WSSatuses        : { CONNECTING:0, OPEN:1, CLOSING:2, CLOSED:3 },
8
+  LogLevels        : { INFO:0, WARNING:1, ERROR:2, DEBUG:3, VERBOSE:4},
9
+  TempUnits        : { CELSIUS: {LABEL:"Celsius",VALUE:0,GP:"C"}, FAHRENHEIT:{LABEL:"Fahrenheit",VALUE:1,GP:"F"}, KELVIN:{LABEL:"Kelvin",VALUE:2,GP:"K"} }
10
+};
11
+
12
+var wmSettings = {
13
+  AppName: "Marlin WebUI",
14
+  AppRelease: "January, 1 2020",
15
+  AppVersion: "1.1",
16
+  AutoConnect: false,
17
+  ConsoleDirection: wmEnums.ConsoleDirection.PREPEND,
18
+  DefaultPanel: wmEnums.Panels.CONTROLS,
19
+  LogLevel: wmEnums.LogLevels.VERBOSE,
20
+  SymbolMode: 'letter',
21
+  SymbolSend: wmEnums.WsMsgSymbols.SENT.LETTER,
22
+  SymbolReceive: wmEnums.WsMsgSymbols.RECEIVED.LETTER,
23
+  AutoTempInterval: 1,
24
+  TempUnit: wmEnums.TempUnits.CELSIUS
25
+};
26
+
27
+class wmLogItem {
28
+  constructor(text, mdir, mrs, gcmd=null, bgclass=null, ficon=null) {
29
+    this.DateTime = wmTools.GetDateTime();
30
+    this.Text = text;
31
+    this.Direction = mdir;
32
+    this.RsType = mrs;
33
+    this.GCode = gcmd;
34
+    this.BgClass = bgclass === null ? 'console-list-items-info': bgclass;
35
+    this.FontIcon = ficon === null ? wmIcons.InfoCircle : ficon;
36
+    this.SdFile = null;
37
+  }
38
+  SetValues(text=null, mdir=null, mrs=null, gcmd=null, bgclass=null, ficon=null) {
39
+    if(text !== null) { this.Text = text; };
40
+    if(mdir !== null) { this.Direction = mdir; };
41
+    if(mrs !== null) { this.RsType = mrs; };
42
+    if(gcmd !== null) { this.GCode = gcmd; };
43
+    if(bgclass !== null) { this.BgClass = bgclass; };
44
+    if(ficon !== null) { this.FontIcon = ficon; };
45
+  }
46
+  ToJson() { return JSON.stringify(this); }
47
+  ToCsv() { return wmTools.StringFormatCsv(this); }
48
+  ToString() { return wmTools.Stringfy(this); }
49
+  ToLoglist(){
50
+    switch (this.RsType) {
51
+      case wmEnums.ConsoleLevels.INFO:
52
+        this.BgClass = "console-list-items-info";
53
+        this.FontIcon = wmIcons.InfoCircle;
54
+        break;
55
+      case wmEnums.ConsoleLevels.SUCCESS:
56
+        this.BgClass = "console-list-items-success";
57
+        this.FontIcon = wmIcons.CheckSquare;
58
+        break;
59
+      case wmEnums.ConsoleLevels.ERROR:
60
+        this.BgClass = "console-list-items-error";
61
+        this.FontIcon = wmIcons.Triangle;
62
+        break;
63
+      case wmEnums.ConsoleLevels.MONITOR:
64
+        this.BgClass = "console-list-items-terminal";
65
+        this.FontIcon = wmIcons.Terminal;
66
+        break;
67
+      case wmEnums.ConsoleLevels.WARNING:
68
+        this.BgClass = "console-list-items-warning";
69
+        this.FontIcon = wmIcons.Triangle;
70
+        break;
71
+    }
72
+    let strout = '<li class="list-group-item console-list-items '+this.BgClass+'">';
73
+    strout += '<span class="badge badge-light mr-1">'+this.FontIcon.ToHtml()+"</span>";
74
+    strout += '<span class="badge badge-secondary mr-1">'+this.DateTime+'</span>';
75
+    strout += '<span class="badge badge-'+(this.Direction === wmEnums.WSMsgDirection.SENT ? "danger" : "success")+' mr-1">';
76
+    strout += this.Direction === wmEnums.WSMsgDirection.SENT ? wmSettings.SymbolSend : wmSettings.SymbolReceive;
77
+    strout += '</span>' + this.Text + '</li>';
78
+    return strout;
79
+  }
80
+  ToSdFileList() {
81
+    if(this.SdFile !== "Begin file list" && this.SdFile !== "End file list") {
82
+      let a = this.SdFile.split(" ");
83
+      let strout = '<a href="javascript:void(0);" class="list-group-item list-group-item-action list-group-item-light p-1" data-sdfile="'+a[0]+'" onclick="WmButtons.SetSdSelected(this)">';
84
+      strout += '<i class="icon icon-file mr-1"></i>'+a[0]+'<div class="badge badge-secondary float-right">'+wmTools.FileSizeFormat(a[1])+'</div>';
85
+      strout += '</a>';
86
+      return strout;
87
+    }
88
+  }
89
+  static ParseWsMessage(msg) {
90
+    let li = new wmLogItem();
91
+    li.Direction = wmEnums.WSMsgDirection.RECEIVED;
92
+    li.RsType = wmEnums.ConsoleLevels.SUCCESS;
93
+    if (msg === "ok") {
94
+      jsLog.Debug("WSMessage match: ok => " + msg);
95
+      li.Text = "Acknowledge: "+msg;
96
+    }
97
+    else if (msg === "Not SD printing") {
98
+      jsLog.Debug("WSMessage match: " + msg);
99
+      li.Text = "Ack: "+msg;
100
+      WmControls.SetPrinterStatusInfo(false, msg);
101
+    }
102
+    else if (msg.substring(0, 5) === "echo:") {
103
+      if (msg.substring(5, 21) === "busy: processing") {
104
+        jsLog.Debug("WSMessage match: echo:busy: processing: => " + msg);
105
+        li.Text = msg.substring(5, msg.length);
106
+        li.RsType = wmEnums.ConsoleLevels.WARNING;
107
+      }
108
+      else if (msg.substring(5, 21) === "Unknown command:") {
109
+        jsLog.Debug("WSMessage match: echo:Unknown command: => " + msg);
110
+        li.Text = msg.substring(5, msg.length);
111
+        li.RsType = wmEnums.ConsoleLevels.WARNING;
112
+      }
113
+      else if (msg.substring(5,20) === "Now fresh file:") {
114
+        jsLog.Debug("WSMessage match: echo:Now fresh file: => " + msg);
115
+        li.Text = "SD: "+msg.substring(5, msg.length);
116
+      }
117
+      else if (msg==="File selected") {
118
+        jsLog.Debug("WSMessage match: echo:File selected: => " + msg);
119
+        li.Text = "SD: "+msg.substring(5, msg.length);
120
+      }
121
+    }
122
+    else if (msg.substring(0, 6) === "Error:") {
123
+      jsLog.Debug("WSMessage match: error => " + msg);
124
+      li.Text = msg.substring(6, msg.length);
125
+      li.RsType = wmEnums.ConsoleLevels.ERROR;
126
+    }
127
+    else if (msg.substring(0, 12) === "File opened:" || msg === "File selected") {
128
+      jsLog.Debug("WSMessage match: File opened/selected => " + msg);
129
+      li.Text = "SD: "+msg;
130
+    }
131
+    else if (msg.includes("open failed, File:")) {
132
+      jsLog.Error("WSMessage match: open file error => " + msg);
133
+      li.Text = "SD Error: "+msg;
134
+      li.RsType = wmEnums.ConsoleLevels.ERROR;
135
+    }
136
+    else if (msg.toLowerCase().includes(".gco") || msg.toLowerCase().includes(".gcode") || msg.toLowerCase().includes(".g") || msg==="Begin file list" || msg==="End file list") {
137
+      if(msg.substring(0,16)==="Writing to file:") { WmUpload.ReadyToWrite = true; }
138
+      li.Text = "SD: "+msg;
139
+      li.SdFile = msg;
140
+    }
141
+    //else if() {
142
+    //}
143
+    else {
144
+      let rgx_rtemp_eb = /^T:\d{1,3}\.\d{1,2}\s+\/\d{1,3}\.\d{1,2}\s+B:\d{1,3}\.\d{1,2}\s+\/\d{1,3}\.\d{1,2}/;
145
+      let rgx_rtemp_e  = /^T:\d{1,3}\.\d{1,2}\s+\/\d{1,3}\.\d{1,2}/;
146
+
147
+      if(rgx_rtemp_eb.test(msg) || rgx_rtemp_e.test(msg)){
148
+        jsLog.Verbose("Extruder temperatore report: "+msg);
149
+        msg = msg.replace(/\//g,"");
150
+        let tarr = msg.split(/\s/);
151
+        WmCharts.SetTempReport(tarr);
152
+        li.Text = "Temp report: "+msg;
153
+      }
154
+      else { li.Text = msg; }
155
+    }
156
+    jsLog.Verbose(li.ToString());
157
+    return li;
158
+  }
159
+}
160
+
161
+class wmGCommandItem {
162
+  constructor(g,p,v,d,s=null) {
163
+    this.GCode = g;
164
+    this.GParams = p;
165
+    this.Values = v;
166
+    this.Description = d;
167
+    this.Supported = s===null ? true : s;
168
+  }
169
+  ToJson() { return JSON.stringify(this); }
170
+  ToString() { return wmTools.Stringfy(this); }
171
+  static CalcChecksum(gc) {
172
+    let cs = 0;
173
+    gc = gc.toUpperCase().replace(/\s/g, '');
174
+    for(let i=0; gc[i]!=='*' && gc[i]!==null && i<gc.length; i++) { cs = cs ^ gc.charCodeAt(i); }
175
+    jsLog.Verbose("Calculate GCommand checksum of: "+gc+" => "+cs);
176
+    return cs;
177
+  }
178
+  static GetCommandItemByCode(gc) {
179
+    jsLog.Verbose("GetCommandItemByCode: Find preset for: "+gc);
180
+    let sgc = gc.split(/\s/);
181
+    jsLog.Verbose("GetCommandItemByCode: Command to find: "+sgc[0]);
182
+    for (let [k, v] of Object.entries(wmGCommands)) {
183
+      if(v.GCode.indexOf(sgc[0]) > -1) { return v; }
184
+    }
185
+    return null;
186
+  }
187
+}
188
+
189
+class wmFontIcon {
190
+  constructor(ico, mc = null) {
191
+    this.ico = ico;
192
+    this.mClass = mc !== null ? " "+mc : "";
193
+  }
194
+  ToString() { return wmTools.Stringfy(this); }
195
+  ToHtml() { return "<i class=\"icon icon-"+ this.ico + this.mClass+"\"></i>"; }
196
+  AddClass(acl) { return "<i class=\"icon icon-"+ this.ico + " "+ acl+"\"></i>"; }
197
+}
198
+
199
+class wmTools {
200
+  static Stringfy(obj) {
201
+    if(obj !== null && obj !== "undefined") {
202
+      let rt = "";
203
+      for (let [k, v] of Object.entries(obj)) { rt += `${k}=${v};`; }
204
+      return rt;
205
+    } else {
206
+      return obj;
207
+    }
208
+  }
209
+  static StringFormat() {
210
+    var args = Array.prototype.slice.call(arguments, 1);
211
+    return arguments[0].replace(/\{(\d+)\}/g, function (match, index) { return args[index]; });
212
+  }
213
+  static StringFormatJson(str) {
214
+    return JSON.stringify(str);
215
+  }
216
+  static StringFormatCsv(obj) {
217
+    let rt = "";
218
+    for (let [k, v] of Object.entries(obj)) { rt += `${v},`; }
219
+    return rt;
220
+  }
221
+  static StringRemoveSpecials(str) {
222
+    var spc = [".","~","{","}"];
223
+    for (var i=0; i<spc.length; i++) { str = str.replace(spc[i],""); }
224
+    return str;
225
+  }
226
+  static FileDownload(fname, ftype, fdata){
227
+    var blob = new Blob(fdata, {type: ftype});
228
+    window.saveAs(blob, fname);
229
+  }
230
+  static FileSizeFormat(size) {
231
+    if(size>0) {
232
+      var i = Math.floor( Math.log(size) / Math.log(1000) );
233
+      return ( size / Math.pow(1000, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
234
+    } else {
235
+      return size+" B";
236
+    }
237
+  }
238
+  static EscapeHtml(unsafe) {
239
+    unsafe = unsafe.replace(/&/g, "&amp;");
240
+    unsafe = unsafe.replace(/</g, "&lt;");
241
+    unsafe = unsafe.replace(/>/g, "&gt;");
242
+    unsafe = unsafe.replace(/"/g, "&quot;");
243
+    unsafe = unsafe.replace(/'/g, "&#039;");
244
+    return unsafe;
245
+  }
246
+  static GetDateTime() {
247
+    var dt = new Date();
248
+    var hr = dt.getHours() < 10 ? "0" + dt.getHours() : dt.getHours();
249
+    var mn = dt.getMinutes() < 10 ? "0" + dt.getMinutes() : dt.getMinutes();
250
+    var sc = dt.getSeconds() < 10 ? "0" + dt.getSeconds() : dt.getSeconds();
251
+    return hr + ":" + mn + ":" + sc;
252
+  }
253
+  static GetBrowser() {
254
+    return $.browser.name+" v"+$.browser.versionNumber+" on "+$.browser.platform;
255
+  }
256
+  static GetScreenSize() {
257
+    let bwsize = "Viewport="+$(window).width()+"x"+$(window).height();
258
+    bwsize += " Document="+$(document).width()+"x"+$(document).height();
259
+    bwsize += " Screen="+window.screen.width+"x"+window.screen.height;
260
+    return bwsize;
261
+  }
262
+  static GetNumPercent(p,n) {
263
+     return (p / 100) * n;
264
+  }
265
+  static GetPercentage(p,n) {
266
+     return (p * 100) / n;
267
+  }
268
+  static FormatNumber(v,d) {
269
+    v = parseFloat(v);
270
+    return v.toFixed(d).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.');
271
+  }
272
+  static CelsiusToFahrenheit(n) {
273
+    return n * 9 / 5 + 32;
274
+  }
275
+  static CelsiusToKelvin(n) {
276
+    return n+273.15;
277
+  }
278
+}
279
+
280
+class wmCookie {
281
+  static Read(cname) {
282
+    let decCookie = decodeURIComponent(document.cookie);
283
+    let carr = decCookie.split(';');
284
+    for (let i=0; i<carr.length; i++) {
285
+      while (carr[i].charAt(0)===' ') { carr[i] = carr[i].substring(1); }
286
+      if (carr[i].indexOf(cname)===0) {
287
+        let r = carr[i].substring(cname.length+1, carr[i].length);
288
+        jsLog.Verbose("Load cookie '"+cname+"' => "+r);
289
+        return r;
290
+      }
291
+    }
292
+    return null;
293
+  }
294
+  static Write(cvalue, cname=null) {
295
+    let d = new Date();
296
+    d.setTime(d.getTime() + (365 * 24 * 60 * 60 * 1000));
297
+    let expires = "expires=" + d.toGMTString();
298
+    let cn = cname === null ? "E4dWUI" : cname;
299
+    let cv = cn+ "=" + escape(cvalue) + "; " + expires + ";path=/; SameSite=None; Secure;";
300
+    document.cookie = cv;
301
+    jsLog.Verbose("Add/Update cookie => "+cv);
302
+  }
303
+  static CheckBrowser() {
304
+    wmCookie.Write('1','check_browser_cookie');
305
+    return (document.cookie.indexOf('check_browser_cookie') !== -1) ? true : false;
306
+  }
307
+  static Check() {
308
+    jsLog.Verbose("Checking for browser supported cookie");
309
+    if(wmCookie.CheckBrowser()===true) {
310
+      jsLog.Debug("Cookies supported. Looking for custom settings");
311
+      var cStr = wmCookie.Read("E4dWUI");
312
+      if(cStr === null){
313
+        jsLog.Verbose("No settings cookie found. Define defaults");
314
+        wmCookie.Write(JSON.stringify(wmSettings));
315
+      } else {
316
+        jsLog.Debug("Settings cookie found. Loading customized settings");
317
+        var cv = JSON.parse(cStr);
318
+        wmSettings.AutoConnect = cv.AutoConnect;
319
+        wmSettings.DefaultPanel = cv.DefaultPanel;
320
+        wmSettings.ConsoleDirection = cv.ConsoleDirection;
321
+        wmSettings.LogLevel = cv.LogLevel;
322
+        wmSettings.SymbolMode = cv.SymbolMode,
323
+        jsLog.Verbose("Customized cookie stored settings loaded");
324
+        jsLog.Verbose(wmTools.Stringfy(wmSettings));
325
+      }
326
+    } else {
327
+      jsLog.Warning("Cookies are not supported by the browser. Use default settings");
328
+    }
329
+  }
330
+}
331
+
332
+class jsLog {
333
+  static Info(logmsg) {
334
+    if(wmSettings.LogLevel >= wmEnums.LogLevels.INFO) { console.log("[INFO   ] "+logmsg); }
335
+  }
336
+  static Warning(logmsg) {
337
+    if(wmSettings.LogLevel >= wmEnums.LogLevels.WARNING) { console.log("[WARN   ] "+logmsg); }
338
+  }
339
+  static Error(logmsg) {
340
+    if(wmSettings.LogLevel >= wmEnums.LogLevels.ERROR)   { console.log("[ERROR  ] "+logmsg); }
341
+  }
342
+  static Debug(logmsg) {
343
+    if(wmSettings.LogLevel >= wmEnums.LogLevels.DEBUG)   { console.log("[DEBUG  ] "+logmsg); }
344
+  }
345
+  static Verbose(logmsg) {
346
+    if(wmSettings.LogLevel >= wmEnums.LogLevels.VERBOSE) { console.log("[VERBOSE] "+logmsg); }
347
+  }
348
+}
349
+
350
+var wmGCommands = {
351
+  CustomCmd     : new wmGCommandItem('',null,null,'Custom command'),
352
+  MoveFw        : new wmGCommandItem('G1','Y{0}',10,'Move forward on Y axis'),
353
+  MoveBw        : new wmGCommandItem('G1','Y-{0}',10,'Move backward on Y axis'),
354
+  MoveSx        : new wmGCommandItem('G1','X{0}',10,'Move left on X axis'),
355
+  MoveDx        : new wmGCommandItem('G1','X-{0}',10,'Move right on X axis'),
356
+  MoveUp        : new wmGCommandItem('G1','Z{0}',10,'Move up on Z axis'),
357
+  MoveDw        : new wmGCommandItem('G1','Z-{0}',10,'Move down on Z axis'),
358
+  FillRetrive   : new wmGCommandItem('G10',null,null,'Retract filament'),
359
+  FillExtrude   : new wmGCommandItem('GYYYY',null,null,'Extrude filament'),
360
+  MoveHome      : new wmGCommandItem('G28',null,null,'Go home on all axis'),
361
+  MoveHomeX     : new wmGCommandItem('G28','X',null,'Go home on X axis'),
362
+  MoveHomeY     : new wmGCommandItem('G28','Y',null,'Go home on Y axis'),
363
+  MoveHomeZ     : new wmGCommandItem('G28','Z',null,'Go home on Z axis'),
364
+  StepEnable    : new wmGCommandItem('M17','{0}','E X Y Z','Enable stepper'),
365
+  StepEnableAll : new wmGCommandItem('M17',null,null,'Enable all steppers'),
366
+  StepDisable   : new wmGCommandItem('M18','{0}','E X Y Z','Disable stepper'),
367
+  StepDisableAll: new wmGCommandItem('M18',null,null,'Disable all steppers'),
368
+  SdGetList     : new wmGCommandItem('M20',null,null,'Get SD card content'),
369
+  SdInit        : new wmGCommandItem('M21',null,null,'Init SD card'),
370
+  SdRelease     : new wmGCommandItem('M22',null,null,'Release SD card'),
371
+  SdFileSel     : new wmGCommandItem('M23','{0}','','Select an SD file'),
372
+  SdFilePrint   : new wmGCommandItem('M24','{0}','','Start an SD print'),
373
+  SdPrintStatus : new wmGCommandItem('M27',null,null,'SD print status'),
374
+  SdPrintReport : new wmGCommandItem('M27','S{0}',5,'SD print status report'),
375
+  SdFileStart   : new wmGCommandItem('M28','{0}','','Start SD write'),
376
+  SdFileStop    : new wmGCommandItem('M29',null,null,'Stop SD write'),
377
+  SdFileDel     : new wmGCommandItem('M30','{0}','','Delete an SD file'),
378
+  PrintTime     : new wmGCommandItem('M31',null,null,'Print time'),
379
+  FanOn         : new wmGCommandItem('M106','S{0}',128,'Set fan on with speed'),
380
+  FanOff        : new wmGCommandItem('M107',null,null,'Set fan off'),
381
+  GetPosition   : new wmGCommandItem('M114',null,null,'Get Current Position'),
382
+  FWInfo        : new wmGCommandItem('M115',null,null,'Get firmware info',false),
383
+  SetTempUnit   : new wmGCommandItem('M149','{0}','C','Set temperature units'),
384
+  SetTempOff    : new wmGCommandItem('M155','S0','','Turn off temperature status'),
385
+  SetTempOn     : new wmGCommandItem('M155','S{0}',1,'Get temp status (1 sec default)'),
386
+  GetSetting    : new wmGCommandItem('M503',null,null,'Get settings report')
387
+};
388
+
389
+var wmIcons = {
390
+  Wifi: new wmFontIcon('wifi'),
391
+  Plug: new wmFontIcon('plug'),
392
+  Ban: new wmFontIcon('ban'),
393
+  Bolt: new wmFontIcon('bolt'),
394
+  Info: new wmFontIcon('info'),
395
+  InfoCircle: new wmFontIcon('info-circled'),
396
+  Triangle: new wmFontIcon('exclamation-triangle'),
397
+  CheckSquare: new wmFontIcon('check-square'),
398
+  Terminal: new wmFontIcon('terminal'),
399
+  Exchange: new wmFontIcon('exchange'),
400
+  ChevronUp: new wmFontIcon('chevron-up'),
401
+  ChevronDown: new wmFontIcon('chevron-down'),
402
+  ChevronLeft: new wmFontIcon('chevron-left'),
403
+  ChevronRight: new wmFontIcon('chevron-right'),
404
+  LongArrowUp: new wmFontIcon('long-arrow-up'),
405
+  LongArrowDown: new wmFontIcon('long-arrow-down'),
406
+  LongArrowLeft: new wmFontIcon('long-arrow-left'),
407
+  LongArrowRight: new wmFontIcon('long-arrow-right')
408
+};
409
+
410
+var wmColors = {
411
+  Black   : 'rgb(0, 0, 0)',
412
+  Blue    : 'rgb(54, 162, 235)',
413
+  Green   : 'rgb(0, 255, 0)',
414
+  GreenSuc: 'rgb(92, 184, 92)',
415
+  GreenTur: 'rgb(75, 192, 192)',
416
+  Grey    : 'rgb(201, 203, 207)',
417
+  Yellow  : 'rgb(255, 205, 86)',
418
+  Orange  : 'rgb(255, 159, 64)',
419
+  Purple  : 'rgb(153, 102, 255)',
420
+  Red     : 'rgb(255, 0, 0)',
421
+  RedCoral: 'rgb(255, 99, 132)'
422
+};
423
+// Define default setting onject
424
+jsLog.Verbose("JS Classes initializzation completed");
425
+jsLog.Debug("Default settings loaded: "+wmTools.Stringfy(wmSettings));
426
+wmCookie.Check();

+ 169
- 0
data/www/webmarlin-font.css Zobrazit soubor

@@ -0,0 +1,169 @@
1
+@charset "UTF-8";
2
+@font-face {
3
+  font-family: "marlinui";
4
+  src:url("marlinui.eot");
5
+  src:url("marlinui.eot?#iefix") format("embedded-opentype"), url("marlinui.woff") format("woff"), url("marlinui.ttf") format("truetype"), url("marlinui.svg#marlinui") format("svg");
6
+  font-weight: normal;
7
+  font-style: normal;
8
+}
9
+[data-icon]:before {
10
+  font-family: "marlinui" !important;
11
+  content: attr(data-icon);
12
+  font-style: normal !important;
13
+  font-weight: normal !important;
14
+  font-variant: normal !important;
15
+  text-transform: none !important;
16
+  speak: none;
17
+  line-height: 1;
18
+  -webkit-font-smoothing: antialiased;
19
+  -moz-osx-font-smoothing: grayscale;
20
+}
21
+[class^="icon-"]:before, [class*=" icon-"]:before {
22
+  font-family: "marlinui" !important;
23
+  font-style: normal !important;
24
+  font-weight: normal !important;
25
+  font-variant: normal !important;
26
+  text-transform: none !important;
27
+  speak: none;
28
+  line-height: 1;
29
+  -webkit-font-smoothing: antialiased;
30
+  -moz-osx-font-smoothing: grayscale;
31
+}
32
+.icon-home:before {
33
+  content: "\61";
34
+}
35
+.icon-info:before {
36
+  content: "\62";
37
+}
38
+.icon-cog:before {
39
+  content: "\63";
40
+}
41
+.icon-tasks:before {
42
+  content: "\64";
43
+}
44
+.icon-chevron-down:before {
45
+  content: "\66";
46
+}
47
+.icon-chevron-left:before {
48
+  content: "\67";
49
+}
50
+.icon-chevron-right:before {
51
+  content: "\68";
52
+}
53
+.icon-chevron-up:before {
54
+  content: "\69";
55
+}
56
+.icon-arrows-alt:before {
57
+  content: "\6a";
58
+}
59
+.icon-upload:before {
60
+  content: "\6b";
61
+}
62
+.icon-ban:before {
63
+  content: "\6d";
64
+}
65
+.icon-github:before {
66
+  content: "\6e";
67
+}
68
+.icon-thermometer:before {
69
+  content: "\6f";
70
+}
71
+.icon-bolt:before {
72
+  content: "\65";
73
+}
74
+.icon-sort-asc:before {
75
+  content: "\70";
76
+}
77
+.icon-sort-desc:before {
78
+  content: "\71";
79
+}
80
+.icon-long-arrow-left:before {
81
+  content: "\72";
82
+}
83
+.icon-long-arrow-down:before {
84
+  content: "\73";
85
+}
86
+.icon-long-arrow-right:before {
87
+  content: "\74";
88
+}
89
+.icon-long-arrow-up:before {
90
+  content: "\75";
91
+}
92
+.icon-arrows:before {
93
+  content: "\76";
94
+}
95
+.icon-arrows-v:before {
96
+  content: "\77";
97
+}
98
+.icon-arrows-h:before {
99
+  content: "\78";
100
+}
101
+.icon-angle-double-up:before {
102
+  content: "\79";
103
+}
104
+.icon-angle-double-down:before {
105
+  content: "\7a";
106
+}
107
+.icon-tencent-weibo:before {
108
+  content: "\41";
109
+}
110
+.icon-playback-fast-forward:before {
111
+  content: "\42";
112
+}
113
+.icon-fire:before {
114
+  content: "\43";
115
+}
116
+.icon-forward:before {
117
+  content: "\44";
118
+}
119
+.icon-terminal:before {
120
+  content: "\45";
121
+}
122
+.icon-info-circled:before {
123
+  content: "\6c";
124
+}
125
+.icon-exclamation-triangle:before {
126
+  content: "\46";
127
+}
128
+.icon-exchange:before {
129
+  content: "\47";
130
+}
131
+.icon-plus:before {
132
+  content: "\48";
133
+}
134
+.icon-minus:before {
135
+  content: "\49";
136
+}
137
+.icon-check-square:before {
138
+  content: "\4a";
139
+}
140
+.icon-facebook-square:before {
141
+  content: "\4b";
142
+}
143
+.icon-file:before {
144
+  content: "\4c";
145
+}
146
+.icon-trash:before {
147
+  content: "\4d";
148
+}
149
+.icon-print:before {
150
+  content: "\4e";
151
+}
152
+.icon-refresh:before {
153
+  content: "\4f";
154
+}
155
+.icon-plug:before {
156
+  content: "\51";
157
+}
158
+.icon-wifi:before {
159
+  content: "\52";
160
+}
161
+.icon-sliders:before {
162
+  content: "\50";
163
+}
164
+.icon-folder-open:before {
165
+  content: "\54";
166
+}
167
+.icon-code-download:before {
168
+  content: "\53";
169
+}

+ 45
- 0
data/www/webmarlin.css Zobrazit soubor

@@ -0,0 +1,45 @@
1
+/*
2
+Bootstrap Toggle: bootstrap4-toggle.css v3.6.1
3
+https://gitbrent.github.io/bootstrap4-toggle/
4
+*/
5
+.btn-group-xs>.btn,.btn-xs{padding:.35rem .4rem .25rem .4rem;font-size:.875rem;line-height:.5;border-radius:.2rem}.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-1.25rem;margin-right:.35rem}.toggle{position:relative;overflow:hidden}.toggle.btn.btn-light,.toggle.btn.btn-outline-light{border-color:rgba(0,0,0,.15)}.toggle input[type=checkbox]{display:none}.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}.toggle-group label,.toggle-group span{cursor:pointer}.toggle.off .toggle-group{left:-100%}.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0;box-shadow:none}.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px;background-color:#fff}.toggle.btn-outline-primary .toggle-handle{background-color:var(--primary);border-color:var(--primary)}.toggle.btn-outline-secondary .toggle-handle{background-color:var(--secondary);border-color:var(--secondary)}.toggle.btn-outline-success .toggle-handle{background-color:var(--success);border-color:var(--success)}.toggle.btn-outline-danger .toggle-handle{background-color:var(--danger);border-color:var(--danger)}.toggle.btn-outline-warning .toggle-handle{background-color:var(--warning);border-color:var(--warning)}.toggle.btn-outline-info .toggle-handle{background-color:var(--info);border-color:var(--info)}.toggle.btn-outline-light .toggle-handle{background-color:var(--light);border-color:var(--light)}.toggle.btn-outline-dark .toggle-handle{background-color:var(--dark);border-color:var(--dark)}.toggle[class*=btn-outline]:hover .toggle-handle{background-color:var(--light);opacity:.5}.toggle.btn{min-width:3.7rem;min-height:2.15rem}.toggle-on.btn{padding-right:1.5rem}.toggle-off.btn{padding-left:1.5rem}.toggle.btn-lg{min-width:5rem;min-height:2.815rem}.toggle-on.btn-lg{padding-right:2rem}.toggle-off.btn-lg{padding-left:2rem}.toggle-handle.btn-lg{width:2.5rem}.toggle.btn-sm{min-width:3.125rem;min-height:1.938rem}.toggle-on.btn-sm{padding-right:1rem}.toggle-off.btn-sm{padding-left:1rem}.toggle.btn-xs{min-width:2.19rem;min-height:1.375rem}.toggle-on.btn-xs{padding-right:.8rem}.toggle-off.btn-xs{padding-left:.8rem}
6
+
7
+/*
8
+E4d@box Marlin WUI
9
+*/
10
+html, body { height: 100%; margin: 0; }
11
+
12
+@media all and (min-width: 500px) {
13
+  #main-panel{ text-align: center; }
14
+  #accordion-panels { width: 500px; height:100%; display: block;  margin-left: auto;  margin-right: auto;}
15
+  .modal-popup { width:400px; }
16
+}
17
+
18
+.console-listbox { height: 450px; }
19
+@media all and (max-height: 400px) { .console-listbox { height: 245px; } }
20
+@media all and (min-height:401px) and (max-height: 500px) { .console-listbox { height: 280px; } }
21
+@media all and (min-height:501px) and (max-height: 600px) { .console-listbox { height: 350px; } }
22
+@media all and (min-height:601px) and (max-height: 700px) { .console-listbox { height: 350px; } }
23
+@media all and (min-height:701px) and (max-height: 800px) { .console-listbox { height: 400px; } }
24
+@media all and (min-height:801px) and (max-height: 900px) { .console-listbox { height: 445px; } }
25
+@media all and (min-height:901px) and (max-height: 1000px) { .console-listbox { height: 480px; } }
26
+@keyframes tgle { 0% { opacity: 0; } 49.99% { opacity: 0; } 50% { opacity: 1; } 99.99% { opacity: 1; } 100% { opacity: 0; } }
27
+@keyframes blink-info { 0% { background-color: #17a2b8; } 50% { opacity: #f8f9fa; } 75% { opacity: #17a2b8; } 100% { opacity: #f8f9fa; } }
28
+
29
+.blink { animation-duration: 500ms; animation-name: tgle; animation-iteration-count: infinite; }
30
+.bg-info-blink { animation-duration: 500ms; animation-name: blink-info; animation-iteration-count: infinite;}
31
+.modal-popup { width:calc(100%-100px); }
32
+.field-labels { font-size: 10pt; font-weight: bold; }
33
+.field-description { font-size: 10pt; font-style: italic; }
34
+.action-description { font-size: 10pt; }
35
+.console-listbox { overflow-y: scroll; overflow-x: hidden; }
36
+.console-list-items-success { background-color: lightgreen; }
37
+.console-list-items-info { background-color: lightsteelblue; }
38
+.console-list-items-error { background-color: lightcoral; }
39
+.console-list-items-terminal { background-color: lightgray; }
40
+.console-list-items-warning { background-color: orange; }
41
+.console-list-items { font-size: 9pt; padding-left: 4px; padding-right: 4px; padding-top: 0px; padding-bottom: 4px; }
42
+.collapse-panel { overflow-y: scroll; overflow-x: hidden; }
43
+.card-header-title { font-size: 10pt; font-weight: bold; }
44
+.card-header-description { font-size: 8pt; }
45
+.badge-description { font-size: 9pt; }

+ 872
- 0
data/www/webmarlin.js Zobrazit soubor

@@ -0,0 +1,872 @@
1
+var wmLogBuffer = new Array();
2
+var wmSdListCounter = {
3
+  FILES:0,
4
+  FOLDERS:0,
5
+  Reset: function() {
6
+    wmSdListCounter.FILES = 0;
7
+    wmSdListCounter.FOLDERS = 0;
8
+    $('#list-sd-content').empty();
9
+    $('#div-sdlist-file-count').text(wmSdListCounter.FILES);
10
+    $('#div-sdlist-folder-count').text(wmSdListCounter.FOLDERS);
11
+  }
12
+};
13
+
14
+var WmButtonGroups = {
15
+  FileManagement: ["#btn-get-sdcontent","#btn-set-sdinit","#btn-set-sdrelease","#file-upload","#btn-file-upload"],
16
+  FileActions: ["#btn-set-sdprint","#btn-set-sddelete"],
17
+  FileProcess: ["#btn-file-proc","#btn-file-proc-cancel"],
18
+  TempStatus: ["#set-auto-temp","#auto-temp-interval","#chart-show-extruder","#chart-show-bed"],
19
+  FanSpeed: ["#fan-speed-range"],
20
+  MoveHome: ["#btn-move-home-all","#btn-move-home-x","#btn-move-home-y","#btn-move-home-z"],
21
+  Move: ["#btn-move-xl","#btn-move-xr","#btn-move-yf","#btn-move-yb","#btn-move-zu","#btn-move-zd"],
22
+  StepperAll: ["#set-stepper-all","#set-stepper-x","#set-stepper-y","#set-stepper-z","#set-stepper-e"],
23
+  Stepper: ["#set-stepper-x","#set-stepper-y","#set-stepper-z","#set-stepper-e"],
24
+
25
+  All: function() {
26
+    let all = [];
27
+    all = all.concat(
28
+      WmButtonGroups.FileManagement,
29
+      WmButtonGroups.FileActions,
30
+      WmButtonGroups.FileProcess,
31
+      WmButtonGroups.TempStatus,
32
+      WmButtonGroups.FanSpeed,
33
+      WmButtonGroups.MoveHome,
34
+      WmButtonGroups.Move,
35
+      WmButtonGroups.StepperAll
36
+    );
37
+    return all;
38
+  }
39
+};
40
+
41
+var wmWebSoket = {
42
+  WSObject: null,
43
+  Connect: function() {
44
+	WsUrl=`ws://${location.host}/ws`;
45
+    try {
46
+      if(wmWebSoket.WSObject === null) {
47
+        jsLog.Debug("WebSocket: Trying connecting to " + WsUrl);
48
+        wmWebSoket.WSObject = new WebSocket(WsUrl);
49
+        wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
50
+        wmWebSoket.WSObject.onopen = function () {
51
+          jsLog.Info("WebSocket: Successfully connected to " + WsUrl);
52
+          wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
53
+          WmControls.Enable(WmButtonGroups.All());
54
+          wmWebSoket.Send(wmGCommands.SdPrintStatus);
55
+        };
56
+        wmWebSoket.WSObject.onclose = function () {
57
+          jsLog.Info("WebSocket: Disconnected from "+WsUrl);
58
+          wmWebSoket.SetWsStatusBar(null);
59
+          wmWebSoket.WSObject = null;
60
+          WmControls.Disable(WmButtonGroups.All());
61
+        };
62
+        wmWebSoket.WSObject.onerror = function () {
63
+          jsLog.Error("WebSocket: Connection error");
64
+          WmConsole.Trace(new wmLogItem("WebSoket connection error", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
65
+        };
66
+        wmWebSoket.WSObject.onmessage = function (event) {
67
+          jsLog.Info("WebSocket: Message received: "+event.data);
68
+          wmWebSoket.OnMessage(event.data.trim());
69
+        };
70
+      }
71
+    }
72
+    catch (exception) {
73
+      jsLog.Error("WebSocket: Exception: "+exception);
74
+      wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
75
+      WmConsole.Trace(new wmLogItem("WebSocket: Connection exception", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
76
+    }
77
+  },
78
+  Disconnect: function() {
79
+    try {
80
+      if(wmWebSoket.WSObject !== null && wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) {
81
+        jsLog.Debug("WebSocket: Disconnecting from "+WsUrl);
82
+        WmConsole.Trace(new wmLogItem("WebSoket disconnecting...", wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.INFO));
83
+        wmWebSoket.WSObject.close();
84
+        wmWebSoket.WSObject = null;
85
+      }
86
+    }
87
+    catch (exception) {
88
+      jsLog.Error("WebSocket: Exception: "+exception);
89
+      wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
90
+      WmConsole.Trace(new wmLogItem("WebSoket connection exception", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
91
+    }
92
+  },
93
+  Send: function(gCmd) {
94
+    if(wmWebSoket.WSObject !== null && wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) {
95
+      let strcmd = gCmd.GCode;
96
+      if (gCmd.GParams === null) { jsLog.Verbose('WebSocket: Send: Command with no params detected'); }
97
+      else {
98
+        jsLog.Verbose('WebSocket: Send: Arguments detected:'+gCmd.GParams);
99
+        gCmd.GParams = wmTools.StringFormat(gCmd.GParams, gCmd.Value);
100
+        strcmd = strcmd +" "+gCmd.GParams;
101
+      }
102
+      jsLog.Debug('WebSocket: Send commandstring: '+strcmd);
103
+      WmConsole.Trace(new wmLogItem("GCmd: <span class=\"badge badge-light\">" + strcmd + "</span> " + gCmd.Description, wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.SUCCESS));
104
+      try { wmWebSoket.WSObject.send(strcmd + '\n'); }
105
+      catch (exception) {
106
+        jsLog.Error('WebSocket: Exception:' + exception);
107
+        WmConsole.Trace(new wmLogItem("WebSoket: Command exception: "+exception, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
108
+      }
109
+    } else { $('#modal-connect').modal('show'); }
110
+  },
111
+  OnMessage: function(mdt) {
112
+    if(mdt === "") { jsLog.Debug("WSMessage match: Empty message (skipped)"); }
113
+    else {
114
+      let litem = wmLogItem.ParseWsMessage(mdt);
115
+      WmConsole.Trace(litem);
116
+      if(litem.SdFile !== null) { WmConsole.TraceSdFile(litem); }
117
+    }
118
+  },
119
+  SetWsStatusBar: function(rs) {
120
+    let cli = new wmLogItem();
121
+    let ctrls = { div:$('#div-conn-statusmsg'), ico:$('#div-conn-statusico'), btn:$('#btn-connect-status'), bar:$('#div-conn-statusbar') };
122
+    switch (rs) {
123
+      case wmEnums.WSSatuses.CONNECTING:
124
+        cli.SetValues("Connecting to "+WsUrl, wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.INFO);
125
+        ctrls.ico.html("<span class=\"blink\">"+wmIcons.Exchange.AddClass('')+"</span>");
126
+        ctrls.div.html("Connecting...");
127
+        ctrls.btn.html("<span class=\"spinner-border spinner-border-sm\"></span>");
128
+        ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-warning text-dark");
129
+        break;
130
+      case wmEnums.WSSatuses.OPEN:
131
+        cli.SetValues("Connected to "+WsUrl, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.SUCCESS);
132
+        ctrls.ico.html(wmIcons.Wifi.AddClass(''));
133
+        ctrls.div.html("Connected");
134
+        ctrls.btn.html(wmIcons.Ban.ToHtml());
135
+        ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-success text-light");
136
+        break;
137
+      case wmEnums.WSSatuses.CLOSED:
138
+        cli.SetValues("Disconnected from "+WsUrl, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR);
139
+        ctrls.ico.html(wmIcons.Plug.AddClass(''));
140
+        ctrls.div.html("Disconnected");
141
+        ctrls.btn.html(wmIcons.Bolt.ToHtml());
142
+        ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-danger text-light");
143
+        break;
144
+      case wmEnums.WSSatuses.CLOSING:
145
+        cli.SetValues("Disconnecting from "+WsUrl, wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.WARNING);
146
+        ctrls.ico.html("<span class=\"blink\">"+wmIcons.Wifi.AddClass('')+"</span>");
147
+        ctrls.div.html("Disconnecting...");
148
+        ctrls.btn.html("<span class=\"spinner-border spinner-border-sm\"></span>");
149
+        ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-warning text-dark");
150
+        break;
151
+      default:
152
+        cli.SetValues("Disconnected from "+WsUrl, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR);
153
+        ctrls.ico.html(wmIcons.Plug.AddClass(''));
154
+        ctrls.div.html("Disconnected");
155
+        ctrls.btn.html(wmIcons.Bolt.ToHtml());
156
+        ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-danger text-light");
157
+        break;
158
+    }
159
+    WmConsole.Trace(cli);
160
+  }
161
+};
162
+
163
+var WmUpload = {
164
+  Reader: null,
165
+  FileName: null,
166
+  FileSize: null,
167
+  FileContent: null,
168
+  ReadyToWrite: false,
169
+  Cancelled: false,
170
+  Load: function() {
171
+    let [fn,fe] = $("#file-upload-label").text().toUpperCase().split(".");
172
+    WmUpload.FileName = fn.substring(0,7)+".GCO";
173
+    let input = $('#file-upload').get(0);
174
+    if (input.files.length) {
175
+      let tfile = input.files[0];
176
+      WmUpload.Reader = new FileReader();
177
+      WmUpload.Reader.onloadstart = function() {
178
+        jsLog.Debug("File uploading starting");
179
+        $('#div-upload-fname').html(WmUpload.FileName);
180
+        if(!$('#upload-process-collapse').hasClass("show")){ $('#upload-process-collapse').collapse('show'); }
181
+      };
182
+      WmUpload.Reader.onload = function(e) {
183
+        jsLog.Debug("File uploading completed");
184
+        WmUpload.FileSize = e.loaded;
185
+        WmUpload.FileContent = e.target.result.split("\n");
186
+        WmUpload.Cancelled = false;
187
+        $('#div-upload-fsize').html(wmTools.FileSizeFormat(WmUpload.FileSize));
188
+        $('#div-upload-fproc').html(wmTools.FormatNumber(WmUpload.FileContent.length,0));
189
+        WmControls.Enable(WmButtonGroups.FileProcess);
190
+        WmUpload.FileProgress(0,"Ready to process...");
191
+
192
+      };
193
+      WmUpload.Reader.onloadend = function(e) {
194
+        jsLog.Debug("File uploading finished");
195
+        jsLog.Debug("___________________onloadend");
196
+      };
197
+      WmUpload.Reader.readAsText(tfile);
198
+      return true;
199
+    } else {
200
+      WmControls.ShowModalAlert('Please select the upload file before continuing');
201
+      WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
202
+      return false;
203
+    }
204
+  },
205
+  Cancel: function() {
206
+    jsLog.Debug("File uploading aborted");
207
+    WmUpload.Reader = null;
208
+    WmUpload.FileName = null;
209
+    WmUpload.FileSize = null;
210
+    WmUpload.Cancelled = true;
211
+    WmControls.Disable(WmButtonGroups.FileProcess);
212
+    WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
213
+    $('#div-upload-fsize').html("-");
214
+    $('#div-upload-fproc').html("-");
215
+    $('#div-upload-fname').html("-");
216
+    WmUpload.FileProgress(0,"&nbsp;");
217
+    if($('#upload-process-collapse').hasClass("show")){ $('#upload-process-collapse').collapse('hide'); }
218
+  },
219
+  FileProcess: function() {
220
+    WmControls.Disable([$("#btn-file-proc")]);
221
+    let fl = WmUpload.FileContent.length;
222
+    jsLog.Debug("Start process GCode lines ("+WmUpload.FileSize+" total)");
223
+    WmUpload.FileProgress(0,"Start analyzing uploaded GCode...");
224
+    wmGCommands.SdFileStart.GParams = WmUpload.FileName;
225
+    wmWebSoket.Send(wmGCommands.SdFileStart);
226
+    var i = 0;
227
+    var n = 1;
228
+    (function pgline() {
229
+      if(WmUpload.Cancelled){
230
+        wmWebSoket.Send(wmGCommands.SdFileStop);
231
+        return;
232
+      }
233
+      else if(!WmUpload.ReadyToWrite){
234
+        jsLog.Debug("WmUpload.FileProcess: Waiting ready to write...");
235
+        WmUpload.FileProgress(0,"Waiting ready to write...");
236
+        setTimeout(pgline, 500);
237
+      }
238
+      else {
239
+        let p = wmTools.GetPercentage(i+1,fl);
240
+        WmUpload.FileProgress(p,"Analyzing line "+(i+1)+" of "+fl);
241
+        let gitem = { line:WmUpload.FileContent[i], process:false, cksum:0 };
242
+
243
+        if(gitem.line.trim()==="" || gitem.line.match(/^ *$/)) { jsLog.Verbose("GLine: "+i+": "+gitem.line+" => Empty line (skip)"); }
244
+        else if(gitem.line.substring(0,1)===";") { jsLog.Verbose("GLine: "+i+": "+gitem.line+" => Comment line (skip)"); }
245
+        else if(gitem.line.indexOf(";") > -1) { gitem.line = gitem.line.substring(0,gitem.line.indexOf(";")); gitem.process=true; }
246
+        else { gitem.process = true; }
247
+
248
+        if(gitem.process) {
249
+          gitem.line = "N"+n+" "+gitem.line.trim();
250
+          gitem.line = gitem.line+"*"+wmGCommandItem.CalcChecksum(gitem.line);
251
+          jsLog.Verbose("GLINE TO SEND: "+gitem.line);
252
+          wmGCommands.CustomCmd.GCode = gitem.line;
253
+          wmWebSoket.Send(wmGCommands.CustomCmd);
254
+          n++;
255
+        }
256
+        i++;
257
+        if (i < fl) { setTimeout(pgline, 10); }
258
+        else {
259
+          WmUpload.FileProgress(100,"GCode Analysis completed!");
260
+          WmUpload.ReadyToWrite = false;
261
+          wmWebSoket.Send(wmGCommands.SdFileStop);
262
+          WmUpload.FileCompleted();
263
+        }
264
+      }
265
+    })();
266
+  },
267
+  FileProgress: function(p,m) {
268
+    p = wmTools.FormatNumber(p,0);
269
+    $('#upload-progressbar').text(p+"%");
270
+    $('#upload-progressbar').css('width',p+'%').attr('aria-valuenow', p);
271
+    $('#upload-progress-text').html(m);
272
+    if(p===100) { $('#upload-progressbar').removeClass("progress-bar-animated"); }
273
+  },
274
+  FileCompleted: function() {
275
+    WmControls.Disable(WmButtonGroups.FileProcess);
276
+    WmButtons.GetSdContentList();
277
+  },
278
+};
279
+
280
+var WmButtons = {
281
+  ConsoleListClear: function() { WmConsole.Clear(); },
282
+  ConsoleListExport: function() { WmConsole.Export(); },
283
+  DeleteSdConfirm: function() {
284
+    $('#div-sdfile-delete-badge').html($('#txt-sdfile-selected').val());
285
+  },
286
+  DeleteSdSelected: function() {
287
+    jsLog.Debug("DeleteSdSelected: Delete file:"+$("#txt-sdfile-selected").val());
288
+    WmControls.Disable(WmButtonGroups.FileActions);
289
+    $('#div-sdfile-delete-rs').collapse('show');
290
+    wmGCommands.SdFileDel.GParams = $("#txt-sdfile-selected").val();
291
+    wmWebSoket.Send(wmGCommands.SdFileDel);
292
+    setTimeout(function(){
293
+      $('#modal-sdfile-delete').modal('hide');
294
+      $('#div-sdfile-delete-rs').collapse('hide');
295
+      WmButtons.GetSdContentList();
296
+    }, 2000);
297
+  },
298
+  GCommandSetPreset: function(gc) {
299
+    jsLog.Debug("Set preset GCommand ("+gc+")");
300
+    $('#text-gcommand').val(gc);
301
+    $('#modal-presets').modal('hide');
302
+    WmAutostart.SetGCommandChecksum();
303
+  },
304
+  GetSdContentList: function() {
305
+    wmSdListCounter.Reset();
306
+    $('#txt-sdfile-selected').val('');
307
+    WmControls.Disable(WmButtonGroups.FileManagement);
308
+    wmWebSoket.Send(wmGCommands.SdGetList);
309
+  },
310
+  PrintSdConfirm: function() {
311
+    $('#div-sdfile-print-badge').html($('#txt-sdfile-selected').val());
312
+  },
313
+  PrintSdSelected: function() {
314
+    jsLog.Debug("PrintSdSelected: Print file:"+$("#txt-sdfile-selected").val());
315
+    WmControls.Disable(WmButtonGroups.FileActions);
316
+    $('#div-sdfile-print-rs').collapse('show');
317
+    wmGCommands.SdFilePrint.GParams = $("#txt-sdfile-selected").val();
318
+    wmWebSoket.Send(wmGCommands.SdFilePrint);
319
+    setTimeout(function(){
320
+      $('#modal-sdfile-print').modal('hide');
321
+      $('#div-sdfile-print-rs').collapse('hide');
322
+      WmAutostart.SetShownPanel(wmEnums.Panels.STATUS);
323
+    }, 2000);
324
+  },
325
+  SaveSettings: function() {
326
+    jsLog.Verbose("Button 'btn-save-settings' clicked");
327
+    WmControls.Disable(['#btn-save-settings','#btn-close-settings']);
328
+    wmSettings.AutoConnect = document.getElementById('set-auto-connect').checked;
329
+    wmSettings.DefaultPanel = parseInt($('#set-default-panel').val());
330
+    wmSettings.LogLevel = parseInt($('#set-log-level').val());
331
+    wmSettings.SymbolMode = $('#set-log-symbol').val();
332
+    wmSettings.AutoTempInterval = $('#set-default-autotemp').val();
333
+    if($('#set-default-tempunit').val()===0) { wmSettings.TempUnit = wmEnums.TempUnits.CELSIUS; }
334
+    else if($('#set-default-tempunit').val()===1) { wmSettings.TempUnit = wmEnums.TempUnits.FAHRENHEIT; }
335
+    else if( $('#set-default-tempunit').val()===2) { wmSettings.TempUnit = wmEnums.TempUnits.KELVIN; }
336
+
337
+    if(wmSettings.SymbolMode==='letter') {
338
+      wmSettings.SymbolSend = wmEnums.WsMsgSymbols.SENT.LETTER;
339
+      wmSettings.SymbolReceive = wmEnums.WsMsgSymbols.RECEIVED.LETTER;
340
+    } else {
341
+      wmSettings.SymbolSend = $('#div-log-symbol-icon-sample-s').html();
342
+      wmSettings.SymbolReceive = $('#div-log-symbol-icon-sample-r').html();
343
+    }
344
+    if(document.getElementById('set-trace-mode-append').checked) {
345
+      wmSettings.ConsoleDirection = wmEnums.ConsoleDirection.APPEND;
346
+    } else {
347
+      wmSettings.ConsoleDirection = wmEnums.ConsoleDirection.PREPEND;
348
+    }
349
+    wmCookie.Write(wmTools.StringFormatJson(wmSettings));
350
+    $('#div-save-setting-rs').collapse('show');
351
+    setTimeout(function(){
352
+      $('#modal-settings').modal('hide');
353
+      $('#div-save-setting-rs').collapse('hide');
354
+      WmControls.Enable(['#btn-save-settings','#btn-close-settings']);
355
+    }, 2000);
356
+  },
357
+  SdInit: function() {
358
+    wmWebSoket.Send(wmGCommands.SdInit);
359
+  },
360
+  SdRelease: function() {
361
+    wmWebSoket.Send(wmGCommands.SdRelease);
362
+  },
363
+  SendGcommand: function() {
364
+    if(wmWebSoket.WSObject !== null && wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) {
365
+      WmControls.Disable(["#btn-gcommand"]);
366
+      let gcmd = $('#text-gcommand');
367
+      if (gcmd.val() === "") {
368
+        gcmd.removeClass('border-dark').addClass('border-danger');
369
+        jsLog.Warning("Empty custom command string detected");
370
+        gcmd.focus();
371
+      } else {
372
+        gcmd.removeClass('border-danger').addClass('border-dark');
373
+        let gc = wmGCommandItem.GetCommandItemByCode(gcmd.val().trim().toUpperCase());
374
+        if(gc === null) {
375
+          wmGCommands.CustomCmd.GCode = gcmd.val().trim().toUpperCase();
376
+          jsLog.Debug("Sending custom command: " + wmGCommands.CustomCmd.GCode);
377
+          wmWebSoket.Send(wmGCommands.CustomCmd);
378
+        } else {
379
+          if(gc.Supported) {
380
+            wmGCommands.CustomCmd.GCode = gcmd.val().trim().toUpperCase();
381
+            jsLog.Debug("Sending custom command: " + wmGCommands.CustomCmd.GCode);
382
+            wmWebSoket.Send(wmGCommands.CustomCmd);
383
+          } else {
384
+            jsLog.Warning("Unsupported command: " + wmGCommands.CustomCmd.GCode);
385
+            WmConsole.Trace(new wmLogItem("GCmd: <span class=\"badge badge-light\">" + gcmd.val() + "</span> Unsupported command", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
386
+          }
387
+        }
388
+        gcmd.val('');
389
+        $('#checksum-gcommand-value').html('&nbsp;');
390
+        WmControls.Enable(["#btn-gcommand"]);
391
+      }
392
+    } else { $('#modal-connect').modal('show'); }
393
+  },
394
+  SetPositionHome: function(b) {
395
+    if(b.id==="btn-move-home-all"){ wmWebSoket.Send(wmGCommands.MoveHome); }
396
+    else if (b.id==="btn-move-home-x"){ wmWebSoket.Send(wmGCommands.MoveHomeX); }
397
+    else if (b.id==="btn-move-home-y"){ wmWebSoket.Send(wmGCommands.MoveHomeY);}
398
+    else if (b.id==="btn-move-home-z"){ wmWebSoket.Send(wmGCommands.MoveHomeZ);}
399
+  },
400
+  SetSdSelected: function(sdi) {
401
+    jsLog.Debug("SetSdSelected: Selected file:"+$(sdi).attr("data-sdfile"));
402
+    $('#txt-sdfile-selected').val($(sdi).attr("data-sdfile"));
403
+    let lip = document.getElementById("list-sd-content").getElementsByTagName("a");
404
+    for (let i=0; i<lip.length; i++) { $(lip[i]).removeClass('list-group-item-success').addClass("list-group-item-light"); }
405
+    $(sdi).removeClass('list-group-item-light').addClass("list-group-item-success");
406
+    WmControls.Enable(WmButtonGroups.FileActions);
407
+    if(!$('#div-sd-selected-file').hasClass("show")) { $('#div-sd-selected-file').collapse("show"); }
408
+    wmGCommands.SdFileSel.GParams = $(sdi).attr("data-sdfile");
409
+    wmWebSoket.Send(wmGCommands.SdFileSel);
410
+  },
411
+  ToggleChecksumDiv: function() {
412
+    let csdiv = $('#checksum-gcommand-div');
413
+    if($('#btn-gcommand-checksum').hasClass('active')===true) { csdiv.collapse('hide'); } else { csdiv.collapse('show'); }
414
+  },
415
+  UploadSdFile: function() {
416
+    WmControls.Disable(WmButtonGroups.FileManagement);
417
+    WmControls.Disable(WmButtonGroups.FileActions);
418
+    if (!window.FileReader) {
419
+        jsLog.Error('Your browser do not support JS file uploading');
420
+        alert('Your browser do not support JS file uploading');
421
+        WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
422
+    } else {
423
+      jsLog.Debug("Starting upload file process");
424
+      if(WmUpload.Load()) { jsLog.Debug("Upload completed"); }
425
+      else {
426
+        jsLog.Error("Upload failed");
427
+        WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
428
+      }
429
+    }
430
+  },
431
+  WsConnect: function() {
432
+    if(wmWebSoket.WSObject === null) { wmWebSoket.Connect(); }
433
+    else { if(wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) { wmWebSoket.Disconnect(); } }
434
+  },
435
+};
436
+
437
+var WmControls = {
438
+  Enable: function() {
439
+    if(arguments.length > 0) {
440
+      for(let i=0; i<arguments.length; i++) {
441
+        let fld = arguments[i];
442
+        for(let c=0; c<fld.length; c++) { WmControls.SetInputStatus(fld[c],'enabled'); }
443
+      }
444
+    } else { jsLog.Warning("WmControls.Enable: Missing input arguments"); }
445
+  },
446
+  Disable: function() {
447
+    if(arguments.length > 0) {
448
+      for(let i=0; i<arguments.length; i++) {
449
+        let fld = arguments[i];
450
+        for(let c=0; c<fld.length; c++) { WmControls.SetInputStatus(fld[c],'disabled'); }
451
+      }
452
+    } else { jsLog.Warning("WmControls.Disable: Missing input arguments"); }
453
+  },
454
+  SetInputStatus(inid,st) {
455
+    if($(inid).attr("data-input-type")==="togglebtn"){
456
+      if(st==="enabled") { $(inid).bootstrapToggle('enable'); } else { $(inid).bootstrapToggle('disable'); }
457
+    } else {
458
+      if(st==="enabled") { $(inid).prop("disabled", false); } else { $(inid).prop("disabled", true); }
459
+    }
460
+  },
461
+  SetCheckStatus: function(ao,b) {
462
+    let cs="off";
463
+    if(b) { cs="on"; }
464
+    for(let i=0; i<ao.length; i++) { $(ao[i]).bootstrapToggle(cs); }
465
+  },
466
+  SetUpload: function() {
467
+    let f = $("#file-upload").val();
468
+    jsLog.Debug("SetUploadFilename: Ready to upload file:"+f);
469
+    $("#file-upload-label").html(f.split("\\").pop());
470
+    WmControls.Enable(WmButtonGroups.FileManagement);
471
+    WmControls.Disable(WmButtonGroups.FileProcess);
472
+  },
473
+  ShowModalAlert: function(m) {
474
+    $('#div-alert-message').html(m);
475
+    $('#modal-alert').modal('show');
476
+  },
477
+  SetAutoTemp: function() {
478
+    if($('#set-auto-temp').prop('checked')) {
479
+      wmGCommands.SetTempOn.GParams = "S"+$('#auto-temp-interval').val();
480
+      wmWebSoket.Send(wmGCommands.SetTempOn);
481
+    } else { wmWebSoket.Send(wmGCommands.SetTempOff); }
482
+  },
483
+  SetFanSpeed: function(rv) {
484
+    rv = parseInt(rv);
485
+    jsLog.Debug("Set fan speed to: "+rv+"%");
486
+    let fsv = wmTools.FormatNumber(wmTools.GetNumPercent(rv,255),0);
487
+    $('#div-fan-speed-current').html(rv+"%<span class='badge badge-success ml-1'>"+fsv+"</span>");
488
+    $('#div-fan-speed-set').html(rv+"%<span class='badge badge-success ml-1'>"+fsv+"</span>");
489
+    if(rv===0) { wmWebSoket.Send(wmGCommands.FanOff); }
490
+    else {
491
+      wmGCommands.FanOn.GParams = "S"+fsv;
492
+      wmWebSoket.Send(wmGCommands.FanOn);
493
+    }
494
+    WmChartsData.FanSpeed.DataUpdate(rv);
495
+  },
496
+  ResetSdFileCounters() {
497
+    $('#list-sd-content').empty();
498
+    $('#div-sdlist-file-count').text(0);
499
+    $('#div-sdlist-folder-count').text(0);
500
+  },
501
+  UpdateTemperatures: function(dt){
502
+    $('#div-temp-extruder-detect').text(dt.ExtruderTemp);
503
+    $('#div-temp-extruder-set').text(dt.ExtruderSet);
504
+    $('#div-temp-extruder-unit').text(wmSettings.TempUnit.LABEL);
505
+    if(dt.BedTemp !== null) {
506
+      $('#div-temp-bed-detect').text(dt.BedTemp);
507
+      $('#div-temp-bed-set').text(dt.BedSet);
508
+      $('#div-temp-bed-unit').text(wmSettings.TempUnit.LABEL);
509
+    }
510
+  },
511
+  SetPrinterStatusInfo: function(s, m) {
512
+    if(!s) {
513
+      $('#div-pstatus-sdprint').removeClass("badge-danger").addClass("badge-info");
514
+      $('#div-pstatus-sdprint').html("Ready to print");
515
+      $('#div-pstatus-timer').collapse('hide');
516
+      $('#div-pstatus-progress').collapse('hide');
517
+    } else {
518
+      $('#div-pstatus-sdprint').removeClass("badge-danger badge-info").addClass("badge-success");
519
+      $('#div-pstatus-sdprint').html("Printing in progress");
520
+      $('#div-pstatus-timer').collapse('show');
521
+      $('#div-pstatus-progress').collapse('show');
522
+    }
523
+  },
524
+  SetSteppers: function(o) {
525
+    if(o.id==="set-stepper-all") {
526
+      WmControls.SetCheckStatus(WmButtonGroups.Stepper,o.checked);
527
+      if(o.checked) { wmWebSoket.Send(wmGCommands.StepEnableAll); } else { wmWebSoket.Send(wmGCommands.StepDisableAll); }
528
+    } else {
529
+      if(o.id==="set-stepper-x") { wmGCommands.StepEnable.GParams = "X"; }
530
+      else if(o.id==="set-stepper-y") { wmGCommands.StepEnable.GParams = "Y"; }
531
+      else if(o.id==="set-stepper-z") { wmGCommands.StepEnable.GParams = "Z"; }
532
+      else if(o.id==="set-stepper-e") { wmGCommands.StepEnable.GParams = "E"; }
533
+      if(o.checked) { wmWebSoket.Send(wmGCommands.StepEnable); } else { wmWebSoket.Send(wmGCommands.StepDisable); }
534
+    }
535
+  },
536
+};
537
+
538
+var WmChartsData = {
539
+  Temperatures: {
540
+    TimeFormat: 'HH:mm:ss',
541
+    Speed: 1000,
542
+    Scale: 1,
543
+    Extruder: {
544
+      Label: "Extruder",
545
+      BorderColor: wmColors.RedCoral,
546
+      BgColor: wmColors.RedCoral,
547
+      Data:[]
548
+    },
549
+    Bed: {
550
+      Label: "Bed",
551
+      BorderColor: wmColors.Blue,
552
+      BgColor: wmColors.Blue,
553
+      Data:[]
554
+    },
555
+    AddEmpty: function(arr, n) {
556
+      for(var i = 0; i < n; i++) {
557
+        let xd = moment().subtract((n - i) * WmChartsData.Temperatures.Speed, 'milliseconds').toDate();
558
+        arr.push({ x: xd, y: null });
559
+      }
560
+    },
561
+    DataUpdate(di) {
562
+      let dt = new Date();
563
+      WmChartsData.Temperatures.Extruder.Data.push({ x: dt, y: di.ExtruderTemp });
564
+      WmChartsData.Temperatures.Extruder.Data.shift();
565
+      if(di.BedTemp !== null) {
566
+        WmChartsData.Temperatures.Bed.Data.push({ x: dt, y: di.BedTemp });
567
+        WmChartsData.Temperatures.Bed.Data.shift();
568
+      }
569
+      requestAnimationFrame(WmCharts.Advance);
570
+    }
571
+  },
572
+  FanSpeed: {
573
+    Values: {
574
+      Label: ["Fan speed",""],
575
+      BgColor: [wmColors.GreenSuc, wmColors.Grey],
576
+      Data: [0,100]
577
+    },
578
+    DataUpdate(di) {
579
+      WmChartsData.FanSpeed.Values.Data[0] = di;
580
+      WmChartsData.FanSpeed.Values.Data[1] = 100 - di;
581
+      if(di < 30) { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.GreenSuc; }
582
+      else if(di < 60) { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.Yellow; }
583
+      else if(di < 80) { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.Orange; }
584
+      else { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.Red; }
585
+      requestAnimationFrame(function() { WmCharts.FanSpeed.CanvasItem.update()});
586
+    }
587
+  }
588
+};
589
+
590
+var WmCharts = {
591
+  Temperatures: {
592
+    CanvasItem: null,
593
+    Config: {
594
+      type: 'line',
595
+      data: {
596
+        datasets: [{
597
+          label: WmChartsData.Temperatures.Extruder.Label,
598
+          data: WmChartsData.Temperatures.Extruder.Data,
599
+          backgroundColor: WmChartsData.Temperatures.Extruder.BgColor,
600
+          borderColor: WmChartsData.Temperatures.Extruder.BorderColor,
601
+          borderWidth: 2,
602
+          fill: false,
603
+          pointRadius: 1.5
604
+        },{
605
+          label: WmChartsData.Temperatures.Bed.Label,
606
+          data: WmChartsData.Temperatures.Bed.Data,
607
+          backgroundColor: WmChartsData.Temperatures.Bed.BgColor,
608
+          borderColor: WmChartsData.Temperatures.Bed.BorderColor,
609
+          borderWidth: 2,
610
+          fill: false,
611
+          pointRadius: 1.5
612
+        }]
613
+      },
614
+      options: {
615
+        responsive: true,
616
+        animation: { duration: WmChartsData.Temperatures.Speed * 1.5, easing:'linear' },
617
+        scales: {
618
+          xAxes: [{ type:'time', time:{ displayFormats: { second: 'HH:mm:ss'} }, scaleLabel: { display: false } }],
619
+          yAxes: [{ ticks: { min: 0} }]
620
+        }
621
+      }
622
+    },
623
+    DisplayAxis: function(ck) {
624
+      if(ck.id==="chart-show-extruder") {
625
+        WmCharts.Temperatures.CanvasItem.getDatasetMeta(0).hidden = ck.checked===true ? false : true;
626
+        $('#chart-show-extruder-label').text(ck.checked===true ? "Show" : "Hide");
627
+      }
628
+      else if(ck.id==="chart-show-bed") {
629
+        WmCharts.Temperatures.CanvasItem.getDatasetMeta(1).hidden = ck.checked===true ? false : true;
630
+        $('#chart-show-bed-label').text(ck.checked===true ? "Show" : "Hide");
631
+      }
632
+      if(!$('#set-auto-temp').prop('checked')){ WmCharts.Temperatures.CanvasItem.update(); }
633
+    }
634
+  },
635
+  FanSpeed: {
636
+    CanvasItem: null,
637
+    Config: {
638
+      type: 'doughnut',
639
+      data: {
640
+        datasets: [{
641
+          data: WmChartsData.FanSpeed.Values.Data,
642
+          backgroundColor: WmChartsData.FanSpeed.Values.BgColor,
643
+        }],
644
+        labels: WmChartsData.FanSpeed.Values.Label
645
+      },
646
+      options: {
647
+        responsive: true,
648
+        circumference: Math.PI,
649
+        rotation: -Math.PI,
650
+        legend: { display: false },
651
+        tooltips: { enabled: false },
652
+        title: { display: false },
653
+        animation: {
654
+          animateScale: true,
655
+          animateRotate: true,
656
+          onComplete: function () {
657
+            var ctx = this.chart.ctx;
658
+            ctx.font = "14pt Verdana";
659
+            ctx.textAlign = 'center';
660
+            ctx.textBaseline = 'bottom';
661
+            ctx.fillStyle = wmColors.Black;
662
+            let ds = this.data.datasets;
663
+            let model = ds[0]._meta[Object.keys(ds[0]._meta)[0]].data[0]._model;
664
+            let xp = wmTools.FormatNumber(model.x,0), yp = wmTools.FormatNumber(model.y,0);
665
+            jsLog.Debug("Drawing speed gauge percentage label position (x,y): "+xp+","+yp);
666
+            ctx.fillText(WmChartsData.FanSpeed.Values.Data[0]+'%', xp, yp);
667
+          }
668
+        }
669
+      }
670
+    }
671
+  },
672
+  Init: function() {
673
+    WmChartsData.Temperatures.AddEmpty(WmChartsData.Temperatures.Extruder.Data, 20);
674
+    WmChartsData.Temperatures.AddEmpty(WmChartsData.Temperatures.Bed.Data, 20);
675
+    WmCharts.Temperatures.CanvasItem = new Chart(document.getElementById('chart-temps'), WmCharts.Temperatures.Config);
676
+    WmCharts.FanSpeed.CanvasItem = new Chart(document.getElementById('chart-fanspeed'), WmCharts.FanSpeed.Config);
677
+  },
678
+  Advance: function() {
679
+    if (WmChartsData.Temperatures.Extruder.Data[0] !== null && WmChartsData.Temperatures.Extruder.Scale < 4) { WmCharts.Temperatures.CanvasItem.update(); }
680
+    WmCharts.Temperatures.CanvasItem.update();
681
+  },
682
+  SetTempReport: function(tr) {
683
+    let temps = {
684
+      ExtruderTemp: tr[0].replace(/T:/,""),
685
+      ExtruderSet: tr[1],
686
+      BedTemp: tr[2]==="undefined" ? null : tr[2].replace(/B:/,""),
687
+      BedSet: tr[3]==="undefined" ? null : tr[3]
688
+    };
689
+    WmChartsData.Temperatures.DataUpdate(temps);
690
+    WmControls.UpdateTemperatures(temps);
691
+  }
692
+};
693
+
694
+var WmConsole = {
695
+  Clear: function() {
696
+    jsLog.Debug("Clearing console message list...");
697
+    $('#gcommand-console-list').empty();
698
+    wmLogBuffer.length = 0;
699
+    WmConsole.Trace(new wmLogItem("Console list cleared by user", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.SUCCESS));
700
+  },
701
+  Export: function() {
702
+    jsLog.Debug("Exporting console message list...");
703
+    var fdt = new Array();
704
+    // DA FINIRE LA PRIMA RIGA NOMI CAMPI
705
+    for(i=0; i<wmLogBuffer.length; i++) { fdt.push(wmLogBuffer[i].ToCsv()+"\n"); }
706
+    wmTools.FileDownload("e4dbox_log.csv", "text/csv;charset=utf-8", fdt);
707
+  },
708
+  SetMessageSymbol: function() {
709
+    if($('#set-log-symbol').val()==="icon") {
710
+      jsLog.Verbose("Set message symbol icon collapse panel to 'show'",this);
711
+      WmConsole.SetSymbolIcon();
712
+      $('#div-log-symbol-icon').collapse('show');
713
+    } else {
714
+      jsLog.Verbose("Set message symbol icon collapse panel to 'hide'",this);
715
+      $('#div-log-symbol-icon').collapse('hide');
716
+    }
717
+  },
718
+  SetSymbolIcon: function() {
719
+    let ctrl = parseInt($('#set-log-symbol-icon').val());
720
+    let hc = {s:null, r:null};
721
+    jsLog.Verbose("Set settings symbol sample fields ("+ctrl+")");
722
+    if(ctrl===0) { hc.s = wmIcons.ChevronUp.ToHtml(); hc.r = wmIcons.ChevronDown.ToHtml(); }
723
+    else if(ctrl===1) { hc.s = wmIcons.LongArrowUp.ToHtml(); hc.r = wmIcons.LongArrowDown.ToHtml(); }
724
+    else if(ctrl===2) { hc.s = wmIcons.ChevronLeft.ToHtml(); hc.r = wmIcons.ChevronRight.ToHtml(); }
725
+    else if(ctrl===3) { hc.s = wmIcons.LongArrowLeft.ToHtml(); hc.r = wmIcons.LongArrowRight.ToHtml(); }
726
+    $('#div-log-symbol-icon-sample-s').html(hc.s);
727
+    $('#div-log-symbol-icon-sample-r').html(hc.r);
728
+  },
729
+  Trace: function(litem) {
730
+    wmLogBuffer.push(litem);
731
+    let clist = $('#gcommand-console-list');
732
+    if (wmSettings.ConsoleDirection === wmEnums.ConsoleDirection.APPEND) { clist.append(litem.ToLoglist()); } else { clist.prepend(litem.ToLoglist()); }
733
+    $('#log-counter-badge').text(wmLogBuffer.length);
734
+  },
735
+  TraceSdFile: function(litem) {
736
+    if(litem.SdFile === "Begin file list") { wmSdListCounter.Reset(); }
737
+    if(litem.SdFile !== "Begin file list" && litem.SdFile !== "End file list") {
738
+      wmSdListCounter.FILES++;
739
+      if(litem.SdFile.indexOf("/")>-1) { wmSdListCounter.FOLDERS++; }
740
+    }
741
+    $('#list-sd-content').append(litem.ToSdFileList());
742
+    $('#div-sdlist-file-count').text(wmSdListCounter.FILES);
743
+    $('#div-sdlist-folder-count').text(wmSdListCounter.FOLDERS);
744
+    if(litem.SdFile === "End file list") { WmControls.Enable(WmButtonGroups.FileManagement); }
745
+  }
746
+};
747
+
748
+var WmAutostart = {
749
+  SetDefaultPanel: function() {
750
+    jsLog.Verbose("Set default shown panel ("+wmSettings.DefaultPanel+")");
751
+    if (wmSettings.DefaultPanel == wmEnums.Panels.STATUS) { $('#accordion-panel-status-body').addClass("show"); }
752
+    else if (wmSettings.DefaultPanel === wmEnums.Panels.CONTROLS) { $('#accordion-panel-controls-body').addClass("show"); }
753
+    else if (wmSettings.DefaultPanel === wmEnums.Panels.TEMP) { $('#accordion-panel-temp-body').addClass("show"); }
754
+    else if (wmSettings.DefaultPanel === wmEnums.Panels.FILES) { $('#accordion-panel-file-body').addClass("show"); }
755
+    else if (wmSettings.DefaultPanel === wmEnums.Panels.CONSOLE) { $('#accordion-panel-console-body').addClass("show"); }
756
+  },
757
+  SetShownPanel: function(p) {
758
+    jsLog.Verbose("Set shown panel ("+p+")");
759
+    if (p === wmEnums.Panels.STATUS) { $('#accordion-panel-status-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-status-body').removeClass("show").addClass("hide"); }
760
+    if (p === wmEnums.Panels.CONTROLS) { $('#accordion-panel-controls-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-controls-body').removeClass("show").addClass("hide"); }
761
+    if (p === wmEnums.Panels.TEMP) { $('#accordion-panel-temp-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-temp-body').removeClass("show").addClass("hide"); }
762
+    if (p === wmEnums.Panels.FILES) { $('#accordion-panel-file-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-file-body').removeClass("show").addClass("hide"); }
763
+    if (p === wmEnums.Panels.CONSOLE) { $('#accordion-panel-console-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-console-body').removeClass("show").addClass("hide"); }
764
+  },
765
+  SetGCommandChecksum: function() {
766
+    cs = wmGCommandItem.CalcChecksum($('#text-gcommand').val());
767
+    $('#checksum-gcommand-value').text(cs);
768
+    jsLog.Debug("Set GCommand checksum ("+cs+")");
769
+  },
770
+  SetGCommandPresetList: function() {
771
+    jsLog.Verbose("Fill GCommand preset list");
772
+    let lip = document.getElementById("list-presets").getElementsByTagName("li");
773
+    let i=0;
774
+    if(lip.length === 1) {
775
+      Object.keys(wmGCommands).forEach(key => {
776
+        if(wmGCommands[key].GCode != "" && wmGCommands[key].Supported) {
777
+          let gp = wmGCommands[key].GParams !== null ? wmTools.StringFormat(wmGCommands[key].GParams,wmGCommands[key].Values) : '';
778
+          var lib = "<button type=\"button\" class=\"list-group-item list-group-item-action p-1\" onclick=\"WmButtons.GCommandSetPreset('"+wmGCommands[key].GCode+" "+gp+"')\">";
779
+          lib += "<span class=\"h5\"><span class=\"badge badge-success mr-1\" style=\"width:100px;\">"+wmGCommands[key].GCode+" "+gp+"</span></span>";
780
+          lib += wmGCommands[key].Description+"</button>";
781
+          $('#list-presets').append(lib);
782
+          i++;
783
+        }
784
+      });
785
+    }
786
+    jsLog.Verbose("Fill GCommand preset list completed ("+i+" items)");
787
+  },
788
+  SetWmSettingsControls: function() {
789
+    jsLog.Verbose("Set settings controls fields");
790
+    $('#set-default-panel').val(wmSettings.DefaultPanel);
791
+    $('#set-auto-connect').bootstrapToggle(wmSettings.AutoConnect==true ? "on" : "off");
792
+    $('#set-default-autotemp').val(wmSettings.AutoTempInterval);
793
+    $('#set-default-tempunit').val(wmSettings.TempUnit.VALUE);
794
+    $('#set-log-level').val(wmSettings.LogLevel);
795
+    if(wmSettings.ConsoleDirection===wmEnums.ConsoleDirection.APPEND) {
796
+      $('#set-trace-mode-prepend').prop('checked',false);
797
+      $('#set-trace-mode-append').prop('checked',true);
798
+    } else {
799
+      $('#set-trace-mode-append').prop('checked',false);
800
+      $('#set-trace-mode-prepend').prop('checked',true);
801
+    }
802
+    $('#set-log-symbol').val(wmSettings.SymbolMode);
803
+    if(wmSettings.SymbolMode==='letter') { $('#div-log-symbol-icon').collapse('hide'); }
804
+    else { $('#div-log-symbol-icon').collapse('show'); SetConsoleSymbolIcon(); }
805
+  },
806
+  SetAutotempDefault: function() {
807
+    $('#auto-temp-interval').val(wmSettings.AutoTempInterval);
808
+  }
809
+};
810
+
811
+$(document).ready(function () {
812
+  $('.accordion-always-open').on('show.bs.collapse', function () { $(this).data('isShowing', true); });
813
+  $('.accordion-always-open').on('hide.bs.collapse', function (event) {
814
+    if (!$(this).data('isShowing')) { event.preventDefault(); }
815
+    $(this).data('isShowing', false);
816
+  });
817
+  jsLog.Debug("Browser in use: "+wmTools.GetBrowser());
818
+  jsLog.Debug("Browser sizes: "+wmTools.GetScreenSize());
819
+
820
+  // AutoStar Actions
821
+  WmAutostart.SetWmSettingsControls();
822
+  WmAutostart.SetDefaultPanel();
823
+  WmAutostart.SetGCommandPresetList();
824
+  WmAutostart.SetAutotempDefault();
825
+
826
+  // EVENTS: Buttons
827
+  $('#btn-clear-console').click(function() { WmButtons.ConsoleListClear(); });
828
+  $('#btn-export-console').click(function() { WmButtons.ConsoleListExport(); });
829
+  $('#btn-file-proc').click(function(){ WmUpload.FileProcess(); });
830
+  $('#btn-file-proc-cancel').click(function() { WmUpload.Cancel(); });
831
+  $('#btn-file-upload').click(function(){ WmButtons.UploadSdFile(); });
832
+  $('#btn-gcommand').click(function() { WmButtons.SendGcommand(); });
833
+  $('#btn-get-sdcontent').click(function() { WmButtons.GetSdContentList(); });
834
+  $('#btn-move-home-all').click(function() { WmButtons.SetPositionHome(this); });
835
+  $('#btn-move-home-x').click(function() { WmButtons.SetPositionHome(this); });
836
+  $('#btn-move-home-y').click(function() { WmButtons.SetPositionHome(this); });
837
+  $('#btn-move-home-z').click(function() { WmButtons.SetPositionHome(this); });
838
+  $('#btn-save-settings').click(function() { WmButtons.SaveSettings(); });
839
+  $('#btn-sdfile-delete-modal').click(function() { WmButtons.DeleteSdSelected(); });
840
+  $('#btn-sdfile-print-modal').click(function() { WmButtons.PrintSdSelected(); });
841
+  $('#btn-set-sdinit').click(function() { WmButtons.SdInit(); });
842
+  $('#btn-set-sdrelease').click(function() { WmButtons.SdRelease(); });
843
+  $('#btn-wsconnect').click(function() { WmButtons.WsConnect(); });
844
+  $('#btn-wsconnect-modal').click(function() { WmButtons.WsConnect(); });
845
+
846
+  // EVENTS: Inputs fields
847
+  $('#text-gcommand').keyup(function()  { WmAutostart.SetGCommandChecksum(); });
848
+  $('#text-gcommand').change(function() { WmAutostart.SetGCommandChecksum(); });
849
+  $('#set-log-symbol').change(function() { WmConsole.SetMessageSymbol(); });
850
+  $('#set-log-symbol-icon').change(function() { WmConsole.SetSymbolIcon(); });
851
+  $('#file-upload').change( function() { WmControls.SetUpload(); });
852
+  $('#set-auto-temp').change( function() { WmControls.SetAutoTemp(); });
853
+  $('#auto-temp-interval').change( function() { WmControls.SetAutoTemp();} );
854
+  $('#chart-show-extruder').change( function() { WmCharts.Temperatures.DisplayAxis(this); });
855
+  $('#chart-show-bed').change( function() { WmCharts.Temperatures.DisplayAxis(this); });
856
+  $('#fan-speed-range').on("change", function() { WmControls.SetFanSpeed(this.value); });
857
+  $('#set-stepper-all').change( function() { WmControls.SetSteppers(this); });
858
+  $('#set-stepper-e').change( function() { WmControls.SetSteppers(this); });
859
+  $('#set-stepper-x').change( function() { WmControls.SetSteppers(this); });
860
+  $('#set-stepper-y').change( function() { WmControls.SetSteppers(this); });
861
+  $('#set-stepper-z').change( function() { WmControls.SetSteppers(this); });
862
+
863
+  // Autorun onload
864
+  WmConsole.Trace(new wmLogItem("Ready", wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.SUCCESS));
865
+  if(wmSettings.AutoConnect===true) { wmWebSoket.Connect(); }
866
+  window.onload = function() {
867
+    WmCharts.Init();
868
+    WmCharts.Advance();
869
+  };
870
+
871
+  WmControls.Enable(WmButtonGroups.All());
872
+});

Loading…
Zrušit
Uložit