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

This commit is contained in:
Mauro 2020-10-21 20:51:14 +02:00 committed by GitHub
parent cf74248949
commit 4fe4fb0585
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 2612 additions and 217 deletions

6
data/www/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

6
data/www/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

10
data/www/bootstrap4-toggle.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
/*\
|*| ========================================================================
|*| Bootstrap Toggle: bootstrap4-toggle.js v3.6.1
|*| https://gitbrent.github.io/bootstrap4-toggle/
|*| ========================================================================
|*| Copyright 2018-2019 Brent Ely
|*| Licensed under MIT
|*| ========================================================================
\*/
!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);

View File

@ -0,0 +1,234 @@
(function(Chart) {
var helpers = Chart.helpers;
var plugins = Chart.plugins;
Chart.defaults.global.animation.duration = 1000;
Chart.defaults._set('linearGauge', {
scale: {
type: 'linearGauge',
horizontal: false,
range: {
startValue: -100,
endValue: 500
},
responsive: true,
font: {
fontName: 'Arial',
fontSize: 12
},
axisWidth: 6,
ticks: {
majorTicks: {
interval: 100,
height: 1,
}
},
scaleLabel: {
display: true,
interval: 100,
units: '',
customValues: [],
offset: -10,
color: '#777b80'
}
},
padding: {
top: 0,
bottom: 0,
left: 0,
right: 0
},
tooltips: {
callbacks: {
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
label += Math.round(data.datasets[tooltipItem.datasetIndex].data[0] * 100) / 100;
return label;
}
}
},
legend: {
display: true,
labels: {
fontColor: 'rgb(0, 0, 0)'
},
position: 'bottom'
}
});
Chart.controllers.linearGauge = Chart.DatasetController.extend({
dataElementType: Chart.elements.Gaugerect,
initialize: function() {
var me = this;
var meta;
Chart.DatasetController.prototype.initialize.apply(me, arguments);
meta = me.getMeta();
},
linkScales: helpers.noop,
update: function(reset) {
var me = this;
var rects = me.getMeta().data;
var i, ilen;
me.datashifts = 0;
for (i = 0, ilen = rects.length; i < ilen; ++i) {
me.updateElement(rects[i], i, me.datashifts);
me.datashifts += 10;
}
},
updateElement: function(rectangle, index, reset) {
var me = this;
var chart = me.chart;
var meta = me.getMeta();
var dataset = me.getDataset();
var custom = rectangle.custom || {};
var rectangleOptions = chart.options.elements.rectangle;
var gaugeOptions = chart.options.elements.gaugerect;
rectangle._Scale = me.getScaleForId(chart.options.scale.id || 'gaugescale');
rectangle._datasetIndex = me.index;
rectangle._index = index;
rectangle.rangeColorImage = null;
// Init element model
rectangle._model = {
datasetLabel: dataset.label,
label: chart.data.labels[index],
borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleOptions.borderSkipped,
backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, gaugeOptions.backgroundColor),
borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleOptions.borderColor),
borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleOptions.borderWidth)
};
// Set empty view as start point for animation
if(typeof rectangle._view === 'undefined') rectangle._view = {};
me.updateElementGeometry(rectangle, index, reset);
},
updateElementGeometry: function(rectangle, index, reset) {
var me = this;
var model = rectangle._model;
var start = rectangle._view;
var dataset = me.getDataset().data;
var dopt = me.getDataset();
var chart = me.chart;
var datasets = chart.data.datasets;
var gaugeOptions = chart.options.elements.gaugerect;
var vscale = me.getScaleForId(chart.options.scale.id || 'gaugescale');
//var base = vscale.getBasePixel();
var base = vscale.getBase();
var horizontal = rectangle._Scale.isHorizontal();
//var ruler = me._ruler || me.getRuler();
var vpixels = me.calculateBarValuePixels(me.index, index, horizontal);
model.horizontal = horizontal;
model.base = base;
model.head = vpixels.head;
model.x = horizontal ? vpixels.base : vpixels.offset;
model.y = horizontal ? (vpixels.offset - (dopt.width || gaugeOptions.width)) : vpixels.head;
model.height = horizontal ? (dopt.width || gaugeOptions.width) : (vpixels.base - vpixels.head);
model.width = horizontal ? (vpixels.head - vpixels.base) : (dopt.width || gaugeOptions.width);
model.value = vscale.getRightValue(datasets[me.index].data[index]);
model.scaleValue = 0;
if (horizontal) {
model.scaleValue = vscale.width / (vscale.options.range.endValue - vscale.options.range.startValue);
} else {
model.scaleValue = vscale.height / (vscale.options.range.endValue - vscale.options.range.startValue);
}
if(typeof start.x === 'undefined' && typeof start.y === 'undefined'){
if(horizontal){
start.x = vpixels.base;
start.width = 0;
} else {
start.y = vpixels.base;
start.height = 0;
}
}
},
calculateBarValuePixels: function(datasetIndex, index, horizontal) {
var me = this;
var chart = me.chart;
var scale = me.getScaleForId(chart.options.scale.id || 'gaugescale');
var datasets = chart.data.datasets;
var dopt = datasets[datasetIndex];
var value = scale.getRightValue(datasets[datasetIndex].data[index]);
var stacked = scale.options.stacked;
var start = 0;
var i, imeta, ivalue, base, head, size, offset;
base = scale.scalePoint(start);
head = scale.scalePoint(start + value);
size = (head - base) / 2;
offset = horizontal ? scale.yCenter - dopt.offset : scale.xCenter + dopt.offset;
return {
size: size,
base: base,
head: head,
center: head + size / 2,
offset: offset
};
},
draw: function() {
var me = this;
var chart = me.chart;
var rects = me.getMeta().data;
var dataset = me.getDataset();
var ilen = rects.length;
var i = 0;
helpers.canvas.clipArea(chart.ctx, chart.chartArea);
for (; i < ilen; ++i) {
if (!isNaN(dataset.data[i])) {
rects[i].draw();
}
}
helpers.canvas.unclipArea(chart.ctx);
},
setHoverStyle: function(rectangle) {
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
var index = rectangle._index;
var custom = rectangle.custom || {};
var model = rectangle._model;
model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.valueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor));
model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.valueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor));
model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.valueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth);
},
removeHoverStyle: function(rectangle) {
var dataset = this.chart.data.datasets[rectangle._datasetIndex];
var index = rectangle._index;
var custom = rectangle.custom || {};
var model = rectangle._model;
var rectangleElementOptions = this.chart.options.elements.gaugerect;
model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor);
model.borderColor = custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor);
model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth);
}
});
}).call(this, Chart);

7
data/www/chart.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
data/www/filesaver.min.js vendored Normal file
View File

@ -0,0 +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
data/www/index-ie.html Normal file
View File

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

View File

@ -1,37 +1,749 @@
<!doctype html>
<html lang=en>
<!doctype html>
<html lang="en">
<head>
<meta charset=utf-8>
<title>Marlin</title>
<link rel="stylesheet" type="text/css" href="marlin.css" />
<script type="text/javascript" src="marlin.js"></script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimal-ui,shrink-to-fit=no" />
<meta name="Title" content="Marlin WebUI" />
<meta name="Description" content="Marlin WebUI based on E4d@box WebUI" />
<meta name="Generator" content="E4d@box" />
<meta name="Owner" content="E4d@box" />
<meta name="Author" content="MandrakeDesign" />
<meta name="google" content="notranslate" />
<meta http-equiv="Content-Language" content="en_GB" />
<title>Marlin WebUI</title>
<link rel="shortcut icon" href="#" />
<link rel="stylesheet" type="text/css" href="bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="webmarlin-font.css">
<link rel="stylesheet" type="text/css" href="webmarlin.css" />
<script>
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)){ top.location.replace('index-ie.html'); }
function hideAddressBar() { if(!window.location.hash) { if(document.height < window.outerHeight) { document.body.style.height = (window.outerHeight + 50) + 'px'; }
setTimeout( function(){ window.scrollTo(0, 1); }, 50 );
}}
window.addEventListener("load", function(){ if(!window.pageYOffset){ hideAddressBar(); } } );
window.addEventListener("orientationchange", hideAddressBar );
</script>
<script src="moment.min.js"></script>
<script src="webmarlin-class.js"></script>
</head>
<body>
<div class="tabs">
<div id="logo"></div>
<input class="input" name="tabs" type="radio" id="tab-1" checked="checked"/>
<label class="label" for="tab-1">console</label>
<div class="panel">
<div class="panel-content">
<ul id="serial-output"></ul>
<!-- Javascript sources ========================================================================================== -->
<script type="text/javascript" src="jquery-3.5.1.slim.min.js"></script>
<script type="text/javascript" src="jquery.browser.min.js"></script>
<script type="text/javascript" src="bootstrap.min.js"></script>
<script type="text/javascript" src="bootstrap4-toggle.min.js"></script>
<script async="" src="filesaver.min.js"></script>
<script type="text/javascript" src="chart.min.js"></script>
<script type="text/javascript" src="webmarlin.js"></script>
<form id="serial-command-form" autocomplete="off">
<div class="form-wrapper">
<input type="text" id="serial-command">
<input type="submit" value="Send">
<!-- Accordion =================================================================================================== -->
<div id="main-panel" class="h-100 bg-secondary m-0 p-0">
<div class="container-fluid h-100 p-0">
<div class="accordion accordion-always-open h-100 d-flex flex-column bg-light" id="accordion-panels">
<!-- PANEL: Fixed Title ==================================================================================== -->
<div class="bg-dark text-light text-left p-2">
<span class="h4">Marlin WebUI </span> by atbox.tech
<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>
<a href="http://marlinfw.org/" target="_blank" class="float-right"><img src="marlin-logo-dark.png" alt="MarlinLogo" width="100" height="33" /></a>
</div>
<!-- PANEL: Fixed connection status bar ==================================================================== -->
<div id="div-conn-statusbar" class="bg-danger text-light text-left p-1">
<div class="float-left font-italic h5 my-0 pl-1">
<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>
</div>
</form>
</div>
</div>
<input class="input" name="tabs" type="radio" id="tab-2"/>
<label class="label" for="tab-2">controls</label>
<div class="panel">
<div class="panel-content">
#controls
<div class="btn-toolbar float-right mr-1" role="toolbar">
<div class="btn-group mr-1" role="group">
<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>
</div>
<div class="btn-group" role="group">
<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>
</div>
</div>
</div>
<!-- PANEL: Printer status ================================================================================= -->
<div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-status-head">
<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">
<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>
<div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
</button>
</div>
<div id="accordion-panel-status-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-status-head" data-parent="#accordion-panels">
<div class="card-body h-100 border-bottom p-1 text-left">
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light badge-description">
<div class="border-bottom pb-1">
Printing status <div id="div-pstatus-sdprint" class="badge badge-danger badge-description float-right pb-1">Idle</div>
</div>
<div id="div-pstatus-timer" class="border-bottom py-1 collapse">
Printing timer
<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>
<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>
<div class="float-right">Elapsed: <span id="div-pstatus-timer-elapsed" class="badge badge-info badge-description pb-1">0:00:00</span></div>
</div>
<div id="div-pstatus-progress" class="pt-1 collapse">
Printing progress:
<div id="div-pstatus-progress-percent" class="badge badge-info badge-description float-right pb-1">10%</div>
<div id="div-pstatus-progress-bytes" class="badge badge-info badge-description float-right pb-1 mr-1">1 of 123456</div>
<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>
</div>
</div>
</div>
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light">
<div>
Auto temperature detection
<div class="float-right form-inline">
<select id="auto-temp-interval" class="form-control form-control-sm mr-1" style="width:80px;" disabled>
<option value="1">1 sec</option>
<option value="5">5 sec</option>
<option value="10">10 sec</option>
<option value="30">30 sec</option>
<option value="60">60 sec</option>
</select>
<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>
</div>
</div>
<canvas id="chart-temps" height="150"></canvas>
<table class="w-100" cellpadding="0" cellspacing="0">
<tr>
<td width="40%">
<div class="card mr-1">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">Sensor</div>
<div class="card-body py-0 px-1 card-header-description">
<table class="w-100">
<tr><td class="border-bottom" style="height:28px;">Hotend (extruder) sensor</td></tr>
<tr><td style="height:28px;">Bed sensor</td></tr>
</table>
</div>
</div>
</td>
<td width="15%">
<div class="card mr-1">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">Detected</div>
<div class="card-body py-0 px-1 card-header-description text-right">
<table class="w-100">
<tr><td class="border-bottom" style="height:28px;"><div id="div-temp-extruder-detect">-</div></td></tr>
<tr><td style="height:28px;"><div id="div-temp-bed-detect">-</div></td></tr>
</table>
</div>
</div>
</td>
<td width="15%">
<div class="card mr-1">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">Set</div>
<div class="card-body py-0 px-1 card-header-description text-right">
<table class="w-100">
<tr><td class="border-bottom" style="height:28px;"><div id="div-temp-extruder-set">-</div></td></tr>
<tr><td style="height:28px;"><div id="div-temp-bed-set">-</div></td></tr>
</table>
</div>
</div>
</td>
<td width="15%">
<div class="card mr-1">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">Unit</div>
<div class="card-body py-0 px-1 card-header-description text-center">
<table class="w-100">
<tr><td class="border-bottom" style="height:28px;"><div id="div-temp-extruder-unit">-</div></td></tr>
<tr><td style="height:28px;"><div id="div-temp-bed-unit">-</div></td></tr>
</table>
</div>
</div>
</td>
<td width="20%">
<div class="card">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">Chart display</div>
<div class="card-body py-0 px-1 card-header-description text-center">
<table class="w-100">
<tr>
<td class="border-bottom" style="height:28px;">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="chart-show-extruder" checked disabled>
<label id="chart-show-extruder-label" class="custom-control-label" for="chart-show-extruder">Show</label>
</div>
</td>
</tr>
<tr>
<td style="height:28px;">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="chart-show-bed" checked disabled>
<label id="chart-show-bed-label" class="custom-control-label" for="chart-show-bed">Show</label>
</div>
</td>
</tr>
</table>
</div>
</div>
</td>
</tr>
</table>
</div>
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td width="70%" valign="top" class="pr-2">
<table class="w-100" cellspacing="0" cellpadding="0" border="0">
<tr style="height:20px;">
<td class="border-bottom card-header-description">Current fan speed</td>
<td class="border-bottom card-header-description text-right"><div id="div-fan-speed-current">-</div></td>
</tr>
<tr style="height:20px;">
<td class="border-bottom card-header-description">Set fan speed</td>
<td class="border-bottom card-header-description text-right"><div id="div-fan-speed-set">-</div></td>
</tr>
<tr>
<td colspan="2" class="card-header-description">
<table class="w-100">
<tr>
<td width="9%" class="text-left">OFF</td>
<td width="9%" class="text-center">10%</td>
<td width="9%" class="text-center">20%</td>
<td width="9%" class="text-center">30%</td>
<td width="9%" class="text-center">40%</td>
<td width="10%" class="text-center">50%</td>
<td width="9%" class="text-center">60%</td>
<td width="9%" class="text-center">70%</td>
<td width="9%" class="text-center">80%</td>
<td width="9%" class="text-center">90%</td>
<td width="9%" class="text-right">FULL</td>
</tr>
</table>
</td>
</tr>
<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>
</table>
</td>
<td width="30%"><canvas id="chart-fanspeed" height="70" width="100"></canvas></td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- PANEL: Printer controls =============================================================================== -->
<div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-controls-head">
<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">
<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>
<div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
</button>
</div>
<div id="accordion-panel-controls-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-controls-head" data-parent="#accordion-panels">
<div class="card-body h-100 border-bottom p-1 text-left">
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light badge-description">
<table class="w-100" cellpadding="0" cellspacing="0">
<tr>
<td class="text-center text-light bg-info rounded-top">All axis</td>
<td style="width:2px"></td>
<td class="text-center text-light bg-info rounded-top">X axis</td>
<td style="width:2px"></td>
<td class="text-center text-light bg-info rounded-top">Y axis</td>
<td style="width:2px"></td>
<td class="text-center text-light bg-info rounded-top">Z axis</td>
</tr>
<tr>
<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>
<td style="width:2px"></td>
<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>
<td style="width:2px"></td>
<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>
<td style="width:2px"></td>
<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>
</tr>
</table>
</div>
</div>
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light badge-description">
<div class="list-group list-group-flush">
<div class="list-group-item bg-light px-0 py-1">
<label for="txt-move-steps" class="">Steps movements size (mm)</label>
<div class="form-group">
<input type="text" id="txt-move-steps" class="form-control form-control-sm float-right" value="10" style="width:80px"/>
<input type="range" class="form-control-range" min="0" max="50" step="1" id="customRange3" value="10">
</div>
</div>
<div class="list-group-item bg-light px-0 py-1">
Move on X axis
<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>
<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>
</div>
<div class="list-group-item bg-light px-0 py-1">
Move on Y axis
<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>
<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>
</div>
<div class="list-group-item bg-light px-0 py-1">
Move on Z axis
<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>
<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>
</div>
</div>
</div>
</div>
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light badge-description">
<table class="w-100" cellpadding="0" cellspacing="0">
<tr>
<td colspan="6" class="pb-1">
Lock/Unlock all steppers (X, Y, Z, E)
</td>
<td class="pb-1">
<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>
</td>
</tr>
<tr>
<td class="text-center text-light bg-info rounded-top">X stepper</td>
<td style="width:2px"></td>
<td class="text-center text-light bg-info rounded-top">Y stepper</td>
<td style="width:2px"></td>
<td class="text-center text-light bg-info rounded-top">Z stepper</td>
<td style="width:2px"></td>
<td class="text-center text-light bg-info rounded-top">E stepper</td>
</tr>
<tr>
<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>
<td style="width:2px"></td>
<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>
<td style="width:2px"></td>
<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>
<td style="width:2px"></td>
<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>
</tr>
</table>
<div class="row mb-1">
<div class="col">
</div>
</div>
</div>
</div>
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light badge-description">
</div>
</div>
</div>
</div>
<!-- PANEL: File management ================================================================================ -->
<div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-file-head">
<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">
<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>
<div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
</button>
</div>
<div id="accordion-panel-file-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-file-head" data-parent="#accordion-panels">
<div class="card-body h-100 p-1 text-left">
<div class="card mb-1 border-0">
<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>
<div class="card-body px-0 py-1 bg-light">
<div class="input-group input-group-sm mb-1">
<div class="custom-file">
<input type="file" class="custom-file-input" id="file-upload" accept=".g,.gco,.gcode" aria-describedby="btn-file-upload" disabled>
<label id="file-upload-label" class="custom-file-label" for="file-upload" data-browse='Pick'>Choose file</label>
</div>
<div class="input-group-append">
<button id="btn-file-upload" class="btn btn-sm btn-success" type="button" disabled>Upload<i class="icon icon-upload ml-1"></i></button>
</div>
</div>
<div id="upload-process-collapse" class="collapse mt-1">
<table class="w-100 mb-1" cellspacing="0" cellpadding="0">
<tr>
<td width="34%">
<div class="card mr-1">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">Filename (DOS8 Format)</div>
<div id="div-upload-fname" class="card-body py-0 px-1 card-header-description text-center">-</div>
</div>
</td>
<td width="33%">
<div class="card">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">File size</div>
<div id="div-upload-fsize" class="card-body py-0 px-1 card-header-description text-center">-</div>
</div>
</td>
<td width="33%">
<div class="card ml-1">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">GCode Lines</div>
<div id="div-upload-fproc" class="card-body py-0 px-1 card-header-description text-center">-</div>
</div>
</td>
</tr>
</table>
<div class="card">
<div class="card-header py-0 px-1 bg-info text-light card-header-description">File processing</div>
<table class="w-100" cellspacing="0" cellpadding="0">
<tr>
<td width="60%" class="p-1">
<div id="upload-progress-text" class="card-header-description">&nbsp;</div>
<div class="progress">
<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>
</div>
</td>
<td width="40%" class="p-1 text-right">
<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>
<button id="btn-file-proc" class="btn btn-sm btn-info" type="button" disabled>Process<i class="icon icon-cog ml-1"></i></button>
</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div class="card mb-0 border-0">
<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>
<div class="card-body px-0 py-1 bg-light">
<div>
<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>
<div class="btn-group float-right" role="group">
<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>
<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>
</div>
</div>
<div id="div-sd-selected-file" class="collapse mt-1 show">
<div class="input-group input-group-sm">
<div class="input-group-prepend"><span class="input-group-text" id="lbl-sdfile-selected">Selected file:</span></div>
<input type="text" id="txt-sdfile-selected" class="form-control" aria-describedby="lbl-sdfile-selected" value="" readonly/>
<div class="input-group-append">
<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>
<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>
</div>
</div>
</div>
</div>
</div>
<div class="card mb-0 border-0">
<div class="card-header card-header-title text-white bg-secondary m-0 p-1">
<div class="float-right">Files: <div id="div-sdlist-file-count" class="badge badge-light">0</div></div>
<div class="float-right mr-1">Folders: <div id="div-sdlist-folder-count" class="badge badge-light">0</div></div>
<i class="icon icon-file ml-1 mr-1"></i>SD File list
</div>
<div class="card-body px-0 py-1 bg-light"><div id="list-sd-content" class="list-group list-group-flush"></div></div>
</div>
</div>
</div>
<!-- PANEL: Console ======================================================================================== -->
<div class="card-header flex-shrink-1 p-0 bg-dark text-light" id="accordion-panel-console-head">
<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">
<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>
<div class="badge badge-secondary float-right"><span class="h5 icon icon-chevron-down"></span></div>
<div id="div-counter-badge" class="badge badge-secondary float-right mr-1"><span id="log-counter-badge" class="h5">0</span></div>
</button>
</div>
<div id="accordion-panel-console-body" class="collapse flex-grow-1 collapse-panel" aria-labelledby="accordion-panel-console-head" data-parent="#accordion-panels">
<div class="card-body h-100 p-1 text-left">
<label for="text-gcommand" class="mb-0 field-labels">G-Code command:</label>
<div class="input-group">
<div class="input-group-prepend">
<a class="btn btn-sm btn-dark" target="_blank" href="http://marlinfw.org/meta/gcode/"><i class="icon icon-info"></i></a>
<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>
</div>
<input type="text" id="text-gcommand" class="form-control form-control-sm border-dark text-uppercase" value="" required>
<div class="input-group-append">
<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>
<button class="btn btn-sm btn-dark mr-1" type="button" id="btn-gcommand">Send <i class="icon icon-chevron-right"></i></button>
</div>
</div>
<div id="checksum-gcommand-div" class="collapse m-0 pr-1 text-right">
<span class="field-description mr-1">GCode checksum value:</span>
<span class="h5"><span class="badge badge-secondary" id="checksum-gcommand-value" style="width:100px;">&nbsp;</span></span>
</div>
<div id="checksum-gcommand-div" class="input-group input-group-sm collapse my-1">
<input type="text" class="form-control" aria-describedby="checksum-gcommand-value" placeholder="GCode checksum value" readonly/>
<div class="input-group-append text-center"><span class="input-group-text" id="checksum-gcommand-value" style="width:100px;"></span></div>
</div>
<label for="btn-gcommand" class="mb-0 field-labels">Console output:</label>
<div class="border rounded p-0 mb-1 console-listbox text-left">
<ul class="list-group list-group-flush" id="gcommand-console-list"></ul>
</div>
<div class="row">
<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>
<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>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- MODAL: About window ========================================================================================= -->
<div class="modal fade" id="modal-info" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-popup" role="document">
<div class="modal-content">
<div class="modal-header bg-secondary text-light m-0 px-2 py-1">
<span class="h5 font-italic mt-1"><i class="icon icon-info mr-2"></i>Info...</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body p-2 text-left">
<span class="h3">Marlin WebUI</span>
<p>Release date: January, 1 2020</p>
<p>
<i class="icon icon-github"></i> Github project: <a href="https://github.com/exilaus/E4d-box-project" target="_blank">E4d-box-project</a><br />
<i class="icon icon-facebook-square"></i> Facebook: <a href="https://www.facebook.com/groups/372792116726814/about/" target="_blank">E4d@box</a>
</p>
<p>Open source dependencies:</p>
<ul>
<li><a href="https://marlinfw.org/" target="_blank">Marlin firmware</a></li>
<li><a href="https://jquery.com/" target="_blank">JQuery 3.5.1 (slim version)</a></li>
<li><a href="https://getbootstrap.com/" target="_blank">Bootstrap v4.5.0</a></li>
<li><a href="https://gitbrent.github.io/bootstrap4-toggle/" target="_blank">Bootstrap4 toggle switch v3.6.1</a></li>
<li><a href="http://fontastic.me/">Fontastic</a>
<li><a href="https://www.chartjs.org/" target="_blank">Chart.js</a></li>
<li><a href="https://github.com/eligrey/FileSaver.js" target="_blank">FileSaver.js</a></li>
</ul>
</div>
<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>
</div>
</div>
</div>
<!-- MODAL: Settings ============================================================================================= -->
<div class="modal fade" id="modal-settings" data-backdrop="static" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-popup" role="document">
<div class="modal-content">
<div class="modal-header bg-secondary text-light m-0 px-2 py-1">
<span class="h5 font-italic mt-1"><i class="icon icon-sliders mr-2"></i>Settings..</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body p-1 text-left">
<ul class="list-group list-group-flush">
<li class="list-group-item p-1">
<div class="row">
<div class="col-5 m-0">Auto connect:</div>
<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>
</div>
<small class="form-text text-muted font-italic mt-0">If ON the application will try to connect automatically on start</small>
</li>
<li class="list-group-item p-1">
<div class="row">
<div class="col-5 m-0">Temp interval:</div>
<div class="col-7 m-0">
<select class="form-control form-control-sm mb-1" id="set-default-autotemp">
<option value="1">1 sec</option>
<option value="5">5 sec</option>
<option value="10">10 sec</option>
<option value="30">30 sec</option>
<option value="60">60 sec</option>
</select>
</div>
</div>
<small class="form-text text-muted font-italic mt-0">Set the default temperature detection interval (secs)</small>
</li>
<li class="list-group-item p-1">
<div class="row">
<div class="col-5 m-0">Temp unit:</div>
<div class="col-7 m-0">
<select class="form-control form-control-sm mb-1" id="set-default-tempunit">
<option value="0">Celsius (default)</option>
<option value="1">Fahrenheit</option>
<option value="2">Kelvin</option>
</select>
</div>
</div>
<small class="form-text text-muted font-italic mt-0">Set the default temperature unit</small>
</li>
<li class="list-group-item p-1">
<div class="row mb-0">
<div class="col-5 m-0">Default panel:</div>
<div class="col-7 m-0">
<select class="form-control form-control-sm mb-1" id="set-default-panel">
<option value="4">Console</option>
<option value="1">Controls</option>
<option value="0">Status (default)</option>
<option value="2">Temperature</option>
<option value="3">Upload</option>
</select>
</div>
</div>
<small class="form-text text-muted font-italic mt-0">Set the default shown panel on start</small>
</li>
<li class="list-group-item p-1">
<div class="row">
<div class="col-5 m-0">Trace direction:</div>
<div class="col-7 m-0">
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<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>
<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>
</div>
</div>
</div>
<small class="form-text text-muted font-italic mt-0">Set the console trace direction</small>
</li>
<li class="list-group-item p-1">
<div class="row">
<div class="col-5 m-0">Trace symbol</div>
<div class="col-7 m-0">
<select class="form-control form-control-sm mb-1" id="set-log-symbol">
<option value="icon">Icon</option>
<option value="letter">Letter</option>
</select>
<div id="div-log-symbol-icon" class="collapse form-check-inline mb-0 h4">
<select class="form-control form-control-sm mb-0 mr-1" id="set-log-symbol-icon">
<option value="0">Chevron: U/D</option>
<option value="2">Chevron: L/R</option>
<option value="1">Arrow: U/D</option>
<option value="3">Arrow: L/R</option>
</select>
<div id="div-log-symbol-icon-sample-s" class="badge badge-success mr-1"></div>
<div id="div-log-symbol-icon-sample-r" class="badge badge-danger"></div>
</div>
</div>
</div>
<small class="form-text text-muted font-italic mt-0">Set the console message direction symbol</small>
</li>
<li class="list-group-item p-1">
<div class="row">
<div class="col-5 m-0">Logging level</div>
<div class="col-7 m-0">
<select class="form-control form-control-sm mb-1" id="set-log-level">
<option value="0">Info (default)</option>
<option value="1">Warning</option>
<option value="2">Error</option>
<option value="3">Debug</option>
<option value="4">Verbose</option>
</select>
</div>
</div>
<small class="form-text text-muted font-italic mt-0">Set the JavaScript logging level</small>
</li>
</ul>
<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>
</div>
<div class="modal-footer bg-secondary m-0 p-1">
<div class="row w-100">
<div class="col"><button type="button" class="btn btn-dark btn-block" id="btn-close-settings" data-dismiss="modal">Close</button></div>
<div class="col"><button type="button" class="btn btn-success btn-block" id="btn-save-settings">Save</button></div>
</div>
</div>
</div>
</div>
</div>
<!-- MODAL: Presets command ====================================================================================== -->
<div class="modal fade" id="modal-presets" tabindex="-1" role="dialog" aria-labelledby="modal-presets-label" aria-hidden="true">
<div class="modal-dialog modal-popup" role="document">
<div class="modal-content">
<div class="modal-header bg-secondary text-light m-0 px-2 py-1">
<span class="h5 font-italic mt-1"><i class="icon icon-sliders mr-2"></i>GCommand presets</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body p-1 text-left">
<div id="list-presets" class="list-group list-group-flush">
<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>
</div>
</div>
<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>
</div>
</div>
</div>
<!-- MODAL: Connect ============================================================================================== -->
<div class="modal fade" id="modal-connect" data-backdrop="static" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-popup" role="document">
<div class="modal-content">
<div class="modal-header bg-warning text-dark m-0 px-2 py-1">
<span class="h5 font-italic mt-1"><i class="icon icon-exchange mr-2"></i>Connect...</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body p-2 text-center my-4">
<i class="icon icon-exclamation-triangle"></i><br>Ooopsss!<br />Marlin firmware Web Socket is not connected.<br />Would you like connect it now?
</div>
<div class="modal-footer bg-secondary m-0 p-1">
<div class="row w-100">
<div class="col"><button type="button" class="btn btn-sm btn-dark btn-block" data-dismiss="modal">Cancel</button></div>
<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>
</div>
</div>
</div>
</div>
</div>
<!-- MODAL: SD file deletion confirmation ======================================================================= -->
<div class="modal fade" id="modal-sdfile-delete" data-backdrop="static" role="dialog" tabindex="-1" aria-labelledby="modal-sdfile-label" aria-hidden="true">
<div class="modal-dialog modal-popup">
<div class="modal-content">
<div class="modal-header bg-secondary text-light m-0 px-2 py-1">
<span class="h5 font-italic mt-1"><i class="icon icon-exclamation-triangle mr-2"></i>Deletion confirmation</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body p-1 text-center mt-4 mb-1">
<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>
This operation cannot be undone.</span>
<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>
</div>
<div class="modal-footer bg-secondary m-0 p-1">
<div class="row w-100">
<div class="col"><button type="button" class="btn btn-sm btn-dark btn-block" data-dismiss="modal">No</button></div>
<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>
</div>
</div>
</div>
</div>
</div>
<!-- MODAL: SD file print confirmation ======================================================================= -->
<div class="modal fade" id="modal-sdfile-print" data-backdrop="static" role="dialog" tabindex="-1" aria-labelledby="modal-sdfile-print" aria-hidden="true">
<div class="modal-dialog modal-popup">
<div class="modal-content">
<div class="modal-header bg-secondary text-light m-0 px-2 py-1">
<span class="h5 font-italic mt-1"><i class="icon icon-print mr-2"></i>Print confirmation</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body p-1 text-center my-4">
<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>
</div>
<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>
<div class="modal-footer bg-secondary m-0 p-1">
<div class="row w-100">
<div class="col"><button type="button" class="btn btn-sm btn-dark btn-block" data-dismiss="modal">No</button></div>
<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>
</div>
</div>
</div>
</div>
</div>
<!-- MODAL: Alert message ======================================================================= -->
<div class="modal fade" id="modal-alert" data-backdrop="static" role="dialog" tabindex="-1" aria-labelledby="modal-alert" aria-hidden="true">
<div class="modal-dialog modal-popup">
<div class="modal-content">
<div class="modal-header bg-secondary text-light m-0 px-2 py-1">
<span class="h5 font-italic mt-1"><i class="icon icon-info-circled mr-2"></i>Message</span>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body p-1 text-center my-4">
<span class="h5"><i class="icon icon-info-circled"></i><br><div id="div-alert-message"></div></span>
</div>
<div class="modal-footer bg-secondary m-0 p-1">
<div class="row w-100">
<div class="col"><button type="button" class="btn btn-sm btn-success btn-block" data-dismiss="modal">OK</button></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

2
data/www/jquery-3.5.1.slim.min.js vendored Normal file

File diff suppressed because one or more lines are too long

10
data/www/jquery.browser.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
/*!
* jQuery Browser Plugin 0.1.0
* https://github.com/gabceb/jquery-browser-plugin
* Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors
* http://jquery.org/license
* Modifications Copyright 2015 Gabriel Cebrian
* https://github.com/gabceb
* Released under the MIT license
* Date: 23-11-2015
*/!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});

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -1,166 +0,0 @@
/* CSS reset */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
font-family: Impact, Charcoal, sans-serif;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body { line-height: 1; }
ol, ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after,
q:before, q:after { content: ''; content: none; }
table {
border-collapse: collapse;
border-spacing: 0;
}
/* Custom */
/* Tabs */
* { box-sizing: border-box; }
body {
display: flex;
justify-content: center;
padding: 0px;
background: #1e1e1e;
color: #efefef;
}
h1 {
margin: 0;
font-size: 2em;
}
.tabs {
display: flex;
width: 100%;
flex-wrap: wrap;
background: #e5e5e5;
}
.input {
position: absolute;
opacity: 0;
}
.label {
width: 100%;
padding: 18px 28px;
background: #e5e5e5;
cursor: pointer;
font-weight: bold;
font-size: 18px;
color: #7f7f7f;
transition: background 0.1s, color 0.1s;
border-style: solid;
border-width: 0 0 4px 0;
border-color: #acacac;
}
.label:hover {
background: #d8d8d8;
}
.label:active {
background: #ccc;
}
.input:focus + .label {
z-index: 1;
}
.input:checked + .label {
background: #1e1e1e;
color: #efefef;
border-width: 4px 0 0 0;
border-color: #65a57d;
}
.panel {
display: none;
width: 100%;
padding: 20px 30px 30px;
background: #1e1e1e;
color: #e5e5e5;
}
.panel .panel-content {
width: 100%;
max-width: 800px;
}
@media (min-width: 600px) {
.label { width: auto; }
.panel { order: 99; }
}
.input:checked + .label + .panel { display: block; }
#logo {
width: 130px;
height: 58px;
margin-right: 20px;
background: url(marlin-logo.png) no-repeat center center;
}
input[type="text"], textarea {
background-color: #2c2c2c;
border: solid 2px #314b3b;
color: #e5e5e5;
outline: none;
}
input[type="text"]:focus, textarea:focus {
border-color: #4d7a5e;
}
ul#serial-output {
width: 100%;
height: 300px;
overflow-y: scroll;
background-color: #2c2c2c;
border: solid 2px #314b3b;
}
ul#serial-output li {
padding: 4px;
font-family: "Lucida Console", Monaco, monospace;
font-size: 0.8em;
}
ul#serial-output li:nth-child(odd) {
background-color: #3c3c3c;
}
div.form-wrapper {
display: flex;
width: 100%;
margin: 6px 0;
}
div.form-wrapper input {
font-size: 1.2em;
padding: 4px 6px;
}
div.form-wrapper input[type="text"] {
flex: 1 1 auto;
}
div.form-wrapper input[type="submit"],
div.form-wrapper button {
border: solid 2px #314b3b;
background-color: #4d7a5e;
color: #e5e5e5;
}

View File

@ -1,24 +0,0 @@
document.addEventListener('DOMContentLoaded', () => {
const ws = new WebSocket(`ws://${location.host}/ws`);
ws.onmessage = (e) => {
if (typeof e.data === 'string') {
let node = document.createElement('li');
let text = document.createTextNode(e.data);
node.appendChild(text);
document.getElementById('serial-output').appendChild(node);
}
};
document.getElementById('serial-command-form').addEventListener('submit', (e) => {
e.preventDefault();
let value = document.getElementById('serial-command').value.trim();
if (!value) return;
ws.send(`${value}\n`);
document.getElementById('serial-command').value = '';
});
});

BIN
data/www/marlinui.eot Normal file

Binary file not shown.

56
data/www/marlinui.svg Normal file
View File

@ -0,0 +1,56 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by Fontastic.me</metadata>
<defs>
<font id="marlinui" horiz-adv-x="512">
<font-face font-family="marlinui" units-per-em="512" ascent="480" descent="-32"/>
<missing-glyph horiz-adv-x="512" />
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<glyph glyph-name="playback-fast-forward" unicode="&#66;" d="M64 128l192 128-192 128z m384 128l-192 128 0-256z"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
<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"/>
</font></defs></svg>

After

Width:  |  Height:  |  Size: 21 KiB

BIN
data/www/marlinui.ttf Normal file

Binary file not shown.

BIN
data/www/marlinui.woff Normal file

Binary file not shown.

7
data/www/moment.min.js vendored Normal file

File diff suppressed because one or more lines are too long

426
data/www/webmarlin-class.js Normal file
View File

@ -0,0 +1,426 @@
var wmEnums = {
Panels : { STATUS:0, CONTROLS:1, FILES:2, CONSOLE:3 },
ConsoleDirection : { APPEND:0, PREPEND:1 },
ConsoleLevels : { ERROR:0, SUCCESS:1, INFO:2, MONITOR:3, WARNING:4},
WSMsgDirection : { SENT:0, RECEIVED:1 },
WsMsgSymbols : { SENT:{LETTER:"S",ICON:null}, RECEIVED:{LETTER:"R",ICON:null} },
WSSatuses : { CONNECTING:0, OPEN:1, CLOSING:2, CLOSED:3 },
LogLevels : { INFO:0, WARNING:1, ERROR:2, DEBUG:3, VERBOSE:4},
TempUnits : { CELSIUS: {LABEL:"Celsius",VALUE:0,GP:"C"}, FAHRENHEIT:{LABEL:"Fahrenheit",VALUE:1,GP:"F"}, KELVIN:{LABEL:"Kelvin",VALUE:2,GP:"K"} }
};
var wmSettings = {
AppName: "Marlin WebUI",
AppRelease: "January, 1 2020",
AppVersion: "1.1",
AutoConnect: false,
ConsoleDirection: wmEnums.ConsoleDirection.PREPEND,
DefaultPanel: wmEnums.Panels.CONTROLS,
LogLevel: wmEnums.LogLevels.VERBOSE,
SymbolMode: 'letter',
SymbolSend: wmEnums.WsMsgSymbols.SENT.LETTER,
SymbolReceive: wmEnums.WsMsgSymbols.RECEIVED.LETTER,
AutoTempInterval: 1,
TempUnit: wmEnums.TempUnits.CELSIUS
};
class wmLogItem {
constructor(text, mdir, mrs, gcmd=null, bgclass=null, ficon=null) {
this.DateTime = wmTools.GetDateTime();
this.Text = text;
this.Direction = mdir;
this.RsType = mrs;
this.GCode = gcmd;
this.BgClass = bgclass === null ? 'console-list-items-info': bgclass;
this.FontIcon = ficon === null ? wmIcons.InfoCircle : ficon;
this.SdFile = null;
}
SetValues(text=null, mdir=null, mrs=null, gcmd=null, bgclass=null, ficon=null) {
if(text !== null) { this.Text = text; };
if(mdir !== null) { this.Direction = mdir; };
if(mrs !== null) { this.RsType = mrs; };
if(gcmd !== null) { this.GCode = gcmd; };
if(bgclass !== null) { this.BgClass = bgclass; };
if(ficon !== null) { this.FontIcon = ficon; };
}
ToJson() { return JSON.stringify(this); }
ToCsv() { return wmTools.StringFormatCsv(this); }
ToString() { return wmTools.Stringfy(this); }
ToLoglist(){
switch (this.RsType) {
case wmEnums.ConsoleLevels.INFO:
this.BgClass = "console-list-items-info";
this.FontIcon = wmIcons.InfoCircle;
break;
case wmEnums.ConsoleLevels.SUCCESS:
this.BgClass = "console-list-items-success";
this.FontIcon = wmIcons.CheckSquare;
break;
case wmEnums.ConsoleLevels.ERROR:
this.BgClass = "console-list-items-error";
this.FontIcon = wmIcons.Triangle;
break;
case wmEnums.ConsoleLevels.MONITOR:
this.BgClass = "console-list-items-terminal";
this.FontIcon = wmIcons.Terminal;
break;
case wmEnums.ConsoleLevels.WARNING:
this.BgClass = "console-list-items-warning";
this.FontIcon = wmIcons.Triangle;
break;
}
let strout = '<li class="list-group-item console-list-items '+this.BgClass+'">';
strout += '<span class="badge badge-light mr-1">'+this.FontIcon.ToHtml()+"</span>";
strout += '<span class="badge badge-secondary mr-1">'+this.DateTime+'</span>';
strout += '<span class="badge badge-'+(this.Direction === wmEnums.WSMsgDirection.SENT ? "danger" : "success")+' mr-1">';
strout += this.Direction === wmEnums.WSMsgDirection.SENT ? wmSettings.SymbolSend : wmSettings.SymbolReceive;
strout += '</span>' + this.Text + '</li>';
return strout;
}
ToSdFileList() {
if(this.SdFile !== "Begin file list" && this.SdFile !== "End file list") {
let a = this.SdFile.split(" ");
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)">';
strout += '<i class="icon icon-file mr-1"></i>'+a[0]+'<div class="badge badge-secondary float-right">'+wmTools.FileSizeFormat(a[1])+'</div>';
strout += '</a>';
return strout;
}
}
static ParseWsMessage(msg) {
let li = new wmLogItem();
li.Direction = wmEnums.WSMsgDirection.RECEIVED;
li.RsType = wmEnums.ConsoleLevels.SUCCESS;
if (msg === "ok") {
jsLog.Debug("WSMessage match: ok => " + msg);
li.Text = "Acknowledge: "+msg;
}
else if (msg === "Not SD printing") {
jsLog.Debug("WSMessage match: " + msg);
li.Text = "Ack: "+msg;
WmControls.SetPrinterStatusInfo(false, msg);
}
else if (msg.substring(0, 5) === "echo:") {
if (msg.substring(5, 21) === "busy: processing") {
jsLog.Debug("WSMessage match: echo:busy: processing: => " + msg);
li.Text = msg.substring(5, msg.length);
li.RsType = wmEnums.ConsoleLevels.WARNING;
}
else if (msg.substring(5, 21) === "Unknown command:") {
jsLog.Debug("WSMessage match: echo:Unknown command: => " + msg);
li.Text = msg.substring(5, msg.length);
li.RsType = wmEnums.ConsoleLevels.WARNING;
}
else if (msg.substring(5,20) === "Now fresh file:") {
jsLog.Debug("WSMessage match: echo:Now fresh file: => " + msg);
li.Text = "SD: "+msg.substring(5, msg.length);
}
else if (msg==="File selected") {
jsLog.Debug("WSMessage match: echo:File selected: => " + msg);
li.Text = "SD: "+msg.substring(5, msg.length);
}
}
else if (msg.substring(0, 6) === "Error:") {
jsLog.Debug("WSMessage match: error => " + msg);
li.Text = msg.substring(6, msg.length);
li.RsType = wmEnums.ConsoleLevels.ERROR;
}
else if (msg.substring(0, 12) === "File opened:" || msg === "File selected") {
jsLog.Debug("WSMessage match: File opened/selected => " + msg);
li.Text = "SD: "+msg;
}
else if (msg.includes("open failed, File:")) {
jsLog.Error("WSMessage match: open file error => " + msg);
li.Text = "SD Error: "+msg;
li.RsType = wmEnums.ConsoleLevels.ERROR;
}
else if (msg.toLowerCase().includes(".gco") || msg.toLowerCase().includes(".gcode") || msg.toLowerCase().includes(".g") || msg==="Begin file list" || msg==="End file list") {
if(msg.substring(0,16)==="Writing to file:") { WmUpload.ReadyToWrite = true; }
li.Text = "SD: "+msg;
li.SdFile = msg;
}
//else if() {
//}
else {
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}/;
let rgx_rtemp_e = /^T:\d{1,3}\.\d{1,2}\s+\/\d{1,3}\.\d{1,2}/;
if(rgx_rtemp_eb.test(msg) || rgx_rtemp_e.test(msg)){
jsLog.Verbose("Extruder temperatore report: "+msg);
msg = msg.replace(/\//g,"");
let tarr = msg.split(/\s/);
WmCharts.SetTempReport(tarr);
li.Text = "Temp report: "+msg;
}
else { li.Text = msg; }
}
jsLog.Verbose(li.ToString());
return li;
}
}
class wmGCommandItem {
constructor(g,p,v,d,s=null) {
this.GCode = g;
this.GParams = p;
this.Values = v;
this.Description = d;
this.Supported = s===null ? true : s;
}
ToJson() { return JSON.stringify(this); }
ToString() { return wmTools.Stringfy(this); }
static CalcChecksum(gc) {
let cs = 0;
gc = gc.toUpperCase().replace(/\s/g, '');
for(let i=0; gc[i]!=='*' && gc[i]!==null && i<gc.length; i++) { cs = cs ^ gc.charCodeAt(i); }
jsLog.Verbose("Calculate GCommand checksum of: "+gc+" => "+cs);
return cs;
}
static GetCommandItemByCode(gc) {
jsLog.Verbose("GetCommandItemByCode: Find preset for: "+gc);
let sgc = gc.split(/\s/);
jsLog.Verbose("GetCommandItemByCode: Command to find: "+sgc[0]);
for (let [k, v] of Object.entries(wmGCommands)) {
if(v.GCode.indexOf(sgc[0]) > -1) { return v; }
}
return null;
}
}
class wmFontIcon {
constructor(ico, mc = null) {
this.ico = ico;
this.mClass = mc !== null ? " "+mc : "";
}
ToString() { return wmTools.Stringfy(this); }
ToHtml() { return "<i class=\"icon icon-"+ this.ico + this.mClass+"\"></i>"; }
AddClass(acl) { return "<i class=\"icon icon-"+ this.ico + " "+ acl+"\"></i>"; }
}
class wmTools {
static Stringfy(obj) {
if(obj !== null && obj !== "undefined") {
let rt = "";
for (let [k, v] of Object.entries(obj)) { rt += `${k}=${v};`; }
return rt;
} else {
return obj;
}
}
static StringFormat() {
var args = Array.prototype.slice.call(arguments, 1);
return arguments[0].replace(/\{(\d+)\}/g, function (match, index) { return args[index]; });
}
static StringFormatJson(str) {
return JSON.stringify(str);
}
static StringFormatCsv(obj) {
let rt = "";
for (let [k, v] of Object.entries(obj)) { rt += `${v},`; }
return rt;
}
static StringRemoveSpecials(str) {
var spc = [".","~","{","}"];
for (var i=0; i<spc.length; i++) { str = str.replace(spc[i],""); }
return str;
}
static FileDownload(fname, ftype, fdata){
var blob = new Blob(fdata, {type: ftype});
window.saveAs(blob, fname);
}
static FileSizeFormat(size) {
if(size>0) {
var i = Math.floor( Math.log(size) / Math.log(1000) );
return ( size / Math.pow(1000, i) ).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
} else {
return size+" B";
}
}
static EscapeHtml(unsafe) {
unsafe = unsafe.replace(/&/g, "&amp;");
unsafe = unsafe.replace(/</g, "&lt;");
unsafe = unsafe.replace(/>/g, "&gt;");
unsafe = unsafe.replace(/"/g, "&quot;");
unsafe = unsafe.replace(/'/g, "&#039;");
return unsafe;
}
static GetDateTime() {
var dt = new Date();
var hr = dt.getHours() < 10 ? "0" + dt.getHours() : dt.getHours();
var mn = dt.getMinutes() < 10 ? "0" + dt.getMinutes() : dt.getMinutes();
var sc = dt.getSeconds() < 10 ? "0" + dt.getSeconds() : dt.getSeconds();
return hr + ":" + mn + ":" + sc;
}
static GetBrowser() {
return $.browser.name+" v"+$.browser.versionNumber+" on "+$.browser.platform;
}
static GetScreenSize() {
let bwsize = "Viewport="+$(window).width()+"x"+$(window).height();
bwsize += " Document="+$(document).width()+"x"+$(document).height();
bwsize += " Screen="+window.screen.width+"x"+window.screen.height;
return bwsize;
}
static GetNumPercent(p,n) {
return (p / 100) * n;
}
static GetPercentage(p,n) {
return (p * 100) / n;
}
static FormatNumber(v,d) {
v = parseFloat(v);
return v.toFixed(d).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1.');
}
static CelsiusToFahrenheit(n) {
return n * 9 / 5 + 32;
}
static CelsiusToKelvin(n) {
return n+273.15;
}
}
class wmCookie {
static Read(cname) {
let decCookie = decodeURIComponent(document.cookie);
let carr = decCookie.split(';');
for (let i=0; i<carr.length; i++) {
while (carr[i].charAt(0)===' ') { carr[i] = carr[i].substring(1); }
if (carr[i].indexOf(cname)===0) {
let r = carr[i].substring(cname.length+1, carr[i].length);
jsLog.Verbose("Load cookie '"+cname+"' => "+r);
return r;
}
}
return null;
}
static Write(cvalue, cname=null) {
let d = new Date();
d.setTime(d.getTime() + (365 * 24 * 60 * 60 * 1000));
let expires = "expires=" + d.toGMTString();
let cn = cname === null ? "E4dWUI" : cname;
let cv = cn+ "=" + escape(cvalue) + "; " + expires + ";path=/; SameSite=None; Secure;";
document.cookie = cv;
jsLog.Verbose("Add/Update cookie => "+cv);
}
static CheckBrowser() {
wmCookie.Write('1','check_browser_cookie');
return (document.cookie.indexOf('check_browser_cookie') !== -1) ? true : false;
}
static Check() {
jsLog.Verbose("Checking for browser supported cookie");
if(wmCookie.CheckBrowser()===true) {
jsLog.Debug("Cookies supported. Looking for custom settings");
var cStr = wmCookie.Read("E4dWUI");
if(cStr === null){
jsLog.Verbose("No settings cookie found. Define defaults");
wmCookie.Write(JSON.stringify(wmSettings));
} else {
jsLog.Debug("Settings cookie found. Loading customized settings");
var cv = JSON.parse(cStr);
wmSettings.AutoConnect = cv.AutoConnect;
wmSettings.DefaultPanel = cv.DefaultPanel;
wmSettings.ConsoleDirection = cv.ConsoleDirection;
wmSettings.LogLevel = cv.LogLevel;
wmSettings.SymbolMode = cv.SymbolMode,
jsLog.Verbose("Customized cookie stored settings loaded");
jsLog.Verbose(wmTools.Stringfy(wmSettings));
}
} else {
jsLog.Warning("Cookies are not supported by the browser. Use default settings");
}
}
}
class jsLog {
static Info(logmsg) {
if(wmSettings.LogLevel >= wmEnums.LogLevels.INFO) { console.log("[INFO ] "+logmsg); }
}
static Warning(logmsg) {
if(wmSettings.LogLevel >= wmEnums.LogLevels.WARNING) { console.log("[WARN ] "+logmsg); }
}
static Error(logmsg) {
if(wmSettings.LogLevel >= wmEnums.LogLevels.ERROR) { console.log("[ERROR ] "+logmsg); }
}
static Debug(logmsg) {
if(wmSettings.LogLevel >= wmEnums.LogLevels.DEBUG) { console.log("[DEBUG ] "+logmsg); }
}
static Verbose(logmsg) {
if(wmSettings.LogLevel >= wmEnums.LogLevels.VERBOSE) { console.log("[VERBOSE] "+logmsg); }
}
}
var wmGCommands = {
CustomCmd : new wmGCommandItem('',null,null,'Custom command'),
MoveFw : new wmGCommandItem('G1','Y{0}',10,'Move forward on Y axis'),
MoveBw : new wmGCommandItem('G1','Y-{0}',10,'Move backward on Y axis'),
MoveSx : new wmGCommandItem('G1','X{0}',10,'Move left on X axis'),
MoveDx : new wmGCommandItem('G1','X-{0}',10,'Move right on X axis'),
MoveUp : new wmGCommandItem('G1','Z{0}',10,'Move up on Z axis'),
MoveDw : new wmGCommandItem('G1','Z-{0}',10,'Move down on Z axis'),
FillRetrive : new wmGCommandItem('G10',null,null,'Retract filament'),
FillExtrude : new wmGCommandItem('GYYYY',null,null,'Extrude filament'),
MoveHome : new wmGCommandItem('G28',null,null,'Go home on all axis'),
MoveHomeX : new wmGCommandItem('G28','X',null,'Go home on X axis'),
MoveHomeY : new wmGCommandItem('G28','Y',null,'Go home on Y axis'),
MoveHomeZ : new wmGCommandItem('G28','Z',null,'Go home on Z axis'),
StepEnable : new wmGCommandItem('M17','{0}','E X Y Z','Enable stepper'),
StepEnableAll : new wmGCommandItem('M17',null,null,'Enable all steppers'),
StepDisable : new wmGCommandItem('M18','{0}','E X Y Z','Disable stepper'),
StepDisableAll: new wmGCommandItem('M18',null,null,'Disable all steppers'),
SdGetList : new wmGCommandItem('M20',null,null,'Get SD card content'),
SdInit : new wmGCommandItem('M21',null,null,'Init SD card'),
SdRelease : new wmGCommandItem('M22',null,null,'Release SD card'),
SdFileSel : new wmGCommandItem('M23','{0}','','Select an SD file'),
SdFilePrint : new wmGCommandItem('M24','{0}','','Start an SD print'),
SdPrintStatus : new wmGCommandItem('M27',null,null,'SD print status'),
SdPrintReport : new wmGCommandItem('M27','S{0}',5,'SD print status report'),
SdFileStart : new wmGCommandItem('M28','{0}','','Start SD write'),
SdFileStop : new wmGCommandItem('M29',null,null,'Stop SD write'),
SdFileDel : new wmGCommandItem('M30','{0}','','Delete an SD file'),
PrintTime : new wmGCommandItem('M31',null,null,'Print time'),
FanOn : new wmGCommandItem('M106','S{0}',128,'Set fan on with speed'),
FanOff : new wmGCommandItem('M107',null,null,'Set fan off'),
GetPosition : new wmGCommandItem('M114',null,null,'Get Current Position'),
FWInfo : new wmGCommandItem('M115',null,null,'Get firmware info',false),
SetTempUnit : new wmGCommandItem('M149','{0}','C','Set temperature units'),
SetTempOff : new wmGCommandItem('M155','S0','','Turn off temperature status'),
SetTempOn : new wmGCommandItem('M155','S{0}',1,'Get temp status (1 sec default)'),
GetSetting : new wmGCommandItem('M503',null,null,'Get settings report')
};
var wmIcons = {
Wifi: new wmFontIcon('wifi'),
Plug: new wmFontIcon('plug'),
Ban: new wmFontIcon('ban'),
Bolt: new wmFontIcon('bolt'),
Info: new wmFontIcon('info'),
InfoCircle: new wmFontIcon('info-circled'),
Triangle: new wmFontIcon('exclamation-triangle'),
CheckSquare: new wmFontIcon('check-square'),
Terminal: new wmFontIcon('terminal'),
Exchange: new wmFontIcon('exchange'),
ChevronUp: new wmFontIcon('chevron-up'),
ChevronDown: new wmFontIcon('chevron-down'),
ChevronLeft: new wmFontIcon('chevron-left'),
ChevronRight: new wmFontIcon('chevron-right'),
LongArrowUp: new wmFontIcon('long-arrow-up'),
LongArrowDown: new wmFontIcon('long-arrow-down'),
LongArrowLeft: new wmFontIcon('long-arrow-left'),
LongArrowRight: new wmFontIcon('long-arrow-right')
};
var wmColors = {
Black : 'rgb(0, 0, 0)',
Blue : 'rgb(54, 162, 235)',
Green : 'rgb(0, 255, 0)',
GreenSuc: 'rgb(92, 184, 92)',
GreenTur: 'rgb(75, 192, 192)',
Grey : 'rgb(201, 203, 207)',
Yellow : 'rgb(255, 205, 86)',
Orange : 'rgb(255, 159, 64)',
Purple : 'rgb(153, 102, 255)',
Red : 'rgb(255, 0, 0)',
RedCoral: 'rgb(255, 99, 132)'
};
// Define default setting onject
jsLog.Verbose("JS Classes initializzation completed");
jsLog.Debug("Default settings loaded: "+wmTools.Stringfy(wmSettings));
wmCookie.Check();

169
data/www/webmarlin-font.css Normal file
View File

@ -0,0 +1,169 @@
@charset "UTF-8";
@font-face {
font-family: "marlinui";
src:url("marlinui.eot");
src:url("marlinui.eot?#iefix") format("embedded-opentype"), url("marlinui.woff") format("woff"), url("marlinui.ttf") format("truetype"), url("marlinui.svg#marlinui") format("svg");
font-weight: normal;
font-style: normal;
}
[data-icon]:before {
font-family: "marlinui" !important;
content: attr(data-icon);
font-style: normal !important;
font-weight: normal !important;
font-variant: normal !important;
text-transform: none !important;
speak: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: "marlinui" !important;
font-style: normal !important;
font-weight: normal !important;
font-variant: normal !important;
text-transform: none !important;
speak: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-home:before {
content: "\61";
}
.icon-info:before {
content: "\62";
}
.icon-cog:before {
content: "\63";
}
.icon-tasks:before {
content: "\64";
}
.icon-chevron-down:before {
content: "\66";
}
.icon-chevron-left:before {
content: "\67";
}
.icon-chevron-right:before {
content: "\68";
}
.icon-chevron-up:before {
content: "\69";
}
.icon-arrows-alt:before {
content: "\6a";
}
.icon-upload:before {
content: "\6b";
}
.icon-ban:before {
content: "\6d";
}
.icon-github:before {
content: "\6e";
}
.icon-thermometer:before {
content: "\6f";
}
.icon-bolt:before {
content: "\65";
}
.icon-sort-asc:before {
content: "\70";
}
.icon-sort-desc:before {
content: "\71";
}
.icon-long-arrow-left:before {
content: "\72";
}
.icon-long-arrow-down:before {
content: "\73";
}
.icon-long-arrow-right:before {
content: "\74";
}
.icon-long-arrow-up:before {
content: "\75";
}
.icon-arrows:before {
content: "\76";
}
.icon-arrows-v:before {
content: "\77";
}
.icon-arrows-h:before {
content: "\78";
}
.icon-angle-double-up:before {
content: "\79";
}
.icon-angle-double-down:before {
content: "\7a";
}
.icon-tencent-weibo:before {
content: "\41";
}
.icon-playback-fast-forward:before {
content: "\42";
}
.icon-fire:before {
content: "\43";
}
.icon-forward:before {
content: "\44";
}
.icon-terminal:before {
content: "\45";
}
.icon-info-circled:before {
content: "\6c";
}
.icon-exclamation-triangle:before {
content: "\46";
}
.icon-exchange:before {
content: "\47";
}
.icon-plus:before {
content: "\48";
}
.icon-minus:before {
content: "\49";
}
.icon-check-square:before {
content: "\4a";
}
.icon-facebook-square:before {
content: "\4b";
}
.icon-file:before {
content: "\4c";
}
.icon-trash:before {
content: "\4d";
}
.icon-print:before {
content: "\4e";
}
.icon-refresh:before {
content: "\4f";
}
.icon-plug:before {
content: "\51";
}
.icon-wifi:before {
content: "\52";
}
.icon-sliders:before {
content: "\50";
}
.icon-folder-open:before {
content: "\54";
}
.icon-code-download:before {
content: "\53";
}

45
data/www/webmarlin.css Normal file
View File

@ -0,0 +1,45 @@
/*
Bootstrap Toggle: bootstrap4-toggle.css v3.6.1
https://gitbrent.github.io/bootstrap4-toggle/
*/
.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}
/*
E4d@box Marlin WUI
*/
html, body { height: 100%; margin: 0; }
@media all and (min-width: 500px) {
#main-panel{ text-align: center; }
#accordion-panels { width: 500px; height:100%; display: block; margin-left: auto; margin-right: auto;}
.modal-popup { width:400px; }
}
.console-listbox { height: 450px; }
@media all and (max-height: 400px) { .console-listbox { height: 245px; } }
@media all and (min-height:401px) and (max-height: 500px) { .console-listbox { height: 280px; } }
@media all and (min-height:501px) and (max-height: 600px) { .console-listbox { height: 350px; } }
@media all and (min-height:601px) and (max-height: 700px) { .console-listbox { height: 350px; } }
@media all and (min-height:701px) and (max-height: 800px) { .console-listbox { height: 400px; } }
@media all and (min-height:801px) and (max-height: 900px) { .console-listbox { height: 445px; } }
@media all and (min-height:901px) and (max-height: 1000px) { .console-listbox { height: 480px; } }
@keyframes tgle { 0% { opacity: 0; } 49.99% { opacity: 0; } 50% { opacity: 1; } 99.99% { opacity: 1; } 100% { opacity: 0; } }
@keyframes blink-info { 0% { background-color: #17a2b8; } 50% { opacity: #f8f9fa; } 75% { opacity: #17a2b8; } 100% { opacity: #f8f9fa; } }
.blink { animation-duration: 500ms; animation-name: tgle; animation-iteration-count: infinite; }
.bg-info-blink { animation-duration: 500ms; animation-name: blink-info; animation-iteration-count: infinite;}
.modal-popup { width:calc(100%-100px); }
.field-labels { font-size: 10pt; font-weight: bold; }
.field-description { font-size: 10pt; font-style: italic; }
.action-description { font-size: 10pt; }
.console-listbox { overflow-y: scroll; overflow-x: hidden; }
.console-list-items-success { background-color: lightgreen; }
.console-list-items-info { background-color: lightsteelblue; }
.console-list-items-error { background-color: lightcoral; }
.console-list-items-terminal { background-color: lightgray; }
.console-list-items-warning { background-color: orange; }
.console-list-items { font-size: 9pt; padding-left: 4px; padding-right: 4px; padding-top: 0px; padding-bottom: 4px; }
.collapse-panel { overflow-y: scroll; overflow-x: hidden; }
.card-header-title { font-size: 10pt; font-weight: bold; }
.card-header-description { font-size: 8pt; }
.badge-description { font-size: 9pt; }

872
data/www/webmarlin.js Normal file
View File

@ -0,0 +1,872 @@
var wmLogBuffer = new Array();
var wmSdListCounter = {
FILES:0,
FOLDERS:0,
Reset: function() {
wmSdListCounter.FILES = 0;
wmSdListCounter.FOLDERS = 0;
$('#list-sd-content').empty();
$('#div-sdlist-file-count').text(wmSdListCounter.FILES);
$('#div-sdlist-folder-count').text(wmSdListCounter.FOLDERS);
}
};
var WmButtonGroups = {
FileManagement: ["#btn-get-sdcontent","#btn-set-sdinit","#btn-set-sdrelease","#file-upload","#btn-file-upload"],
FileActions: ["#btn-set-sdprint","#btn-set-sddelete"],
FileProcess: ["#btn-file-proc","#btn-file-proc-cancel"],
TempStatus: ["#set-auto-temp","#auto-temp-interval","#chart-show-extruder","#chart-show-bed"],
FanSpeed: ["#fan-speed-range"],
MoveHome: ["#btn-move-home-all","#btn-move-home-x","#btn-move-home-y","#btn-move-home-z"],
Move: ["#btn-move-xl","#btn-move-xr","#btn-move-yf","#btn-move-yb","#btn-move-zu","#btn-move-zd"],
StepperAll: ["#set-stepper-all","#set-stepper-x","#set-stepper-y","#set-stepper-z","#set-stepper-e"],
Stepper: ["#set-stepper-x","#set-stepper-y","#set-stepper-z","#set-stepper-e"],
All: function() {
let all = [];
all = all.concat(
WmButtonGroups.FileManagement,
WmButtonGroups.FileActions,
WmButtonGroups.FileProcess,
WmButtonGroups.TempStatus,
WmButtonGroups.FanSpeed,
WmButtonGroups.MoveHome,
WmButtonGroups.Move,
WmButtonGroups.StepperAll
);
return all;
}
};
var wmWebSoket = {
WSObject: null,
Connect: function() {
WsUrl=`ws://${location.host}/ws`;
try {
if(wmWebSoket.WSObject === null) {
jsLog.Debug("WebSocket: Trying connecting to " + WsUrl);
wmWebSoket.WSObject = new WebSocket(WsUrl);
wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
wmWebSoket.WSObject.onopen = function () {
jsLog.Info("WebSocket: Successfully connected to " + WsUrl);
wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
WmControls.Enable(WmButtonGroups.All());
wmWebSoket.Send(wmGCommands.SdPrintStatus);
};
wmWebSoket.WSObject.onclose = function () {
jsLog.Info("WebSocket: Disconnected from "+WsUrl);
wmWebSoket.SetWsStatusBar(null);
wmWebSoket.WSObject = null;
WmControls.Disable(WmButtonGroups.All());
};
wmWebSoket.WSObject.onerror = function () {
jsLog.Error("WebSocket: Connection error");
WmConsole.Trace(new wmLogItem("WebSoket connection error", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
};
wmWebSoket.WSObject.onmessage = function (event) {
jsLog.Info("WebSocket: Message received: "+event.data);
wmWebSoket.OnMessage(event.data.trim());
};
}
}
catch (exception) {
jsLog.Error("WebSocket: Exception: "+exception);
wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
WmConsole.Trace(new wmLogItem("WebSocket: Connection exception", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
}
},
Disconnect: function() {
try {
if(wmWebSoket.WSObject !== null && wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) {
jsLog.Debug("WebSocket: Disconnecting from "+WsUrl);
WmConsole.Trace(new wmLogItem("WebSoket disconnecting...", wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.INFO));
wmWebSoket.WSObject.close();
wmWebSoket.WSObject = null;
}
}
catch (exception) {
jsLog.Error("WebSocket: Exception: "+exception);
wmWebSoket.SetWsStatusBar(wmWebSoket.WSObject.readyState);
WmConsole.Trace(new wmLogItem("WebSoket connection exception", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
}
},
Send: function(gCmd) {
if(wmWebSoket.WSObject !== null && wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) {
let strcmd = gCmd.GCode;
if (gCmd.GParams === null) { jsLog.Verbose('WebSocket: Send: Command with no params detected'); }
else {
jsLog.Verbose('WebSocket: Send: Arguments detected:'+gCmd.GParams);
gCmd.GParams = wmTools.StringFormat(gCmd.GParams, gCmd.Value);
strcmd = strcmd +" "+gCmd.GParams;
}
jsLog.Debug('WebSocket: Send commandstring: '+strcmd);
WmConsole.Trace(new wmLogItem("GCmd: <span class=\"badge badge-light\">" + strcmd + "</span> " + gCmd.Description, wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.SUCCESS));
try { wmWebSoket.WSObject.send(strcmd + '\n'); }
catch (exception) {
jsLog.Error('WebSocket: Exception:' + exception);
WmConsole.Trace(new wmLogItem("WebSoket: Command exception: "+exception, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
}
} else { $('#modal-connect').modal('show'); }
},
OnMessage: function(mdt) {
if(mdt === "") { jsLog.Debug("WSMessage match: Empty message (skipped)"); }
else {
let litem = wmLogItem.ParseWsMessage(mdt);
WmConsole.Trace(litem);
if(litem.SdFile !== null) { WmConsole.TraceSdFile(litem); }
}
},
SetWsStatusBar: function(rs) {
let cli = new wmLogItem();
let ctrls = { div:$('#div-conn-statusmsg'), ico:$('#div-conn-statusico'), btn:$('#btn-connect-status'), bar:$('#div-conn-statusbar') };
switch (rs) {
case wmEnums.WSSatuses.CONNECTING:
cli.SetValues("Connecting to "+WsUrl, wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.INFO);
ctrls.ico.html("<span class=\"blink\">"+wmIcons.Exchange.AddClass('')+"</span>");
ctrls.div.html("Connecting...");
ctrls.btn.html("<span class=\"spinner-border spinner-border-sm\"></span>");
ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-warning text-dark");
break;
case wmEnums.WSSatuses.OPEN:
cli.SetValues("Connected to "+WsUrl, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.SUCCESS);
ctrls.ico.html(wmIcons.Wifi.AddClass(''));
ctrls.div.html("Connected");
ctrls.btn.html(wmIcons.Ban.ToHtml());
ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-success text-light");
break;
case wmEnums.WSSatuses.CLOSED:
cli.SetValues("Disconnected from "+WsUrl, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR);
ctrls.ico.html(wmIcons.Plug.AddClass(''));
ctrls.div.html("Disconnected");
ctrls.btn.html(wmIcons.Bolt.ToHtml());
ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-danger text-light");
break;
case wmEnums.WSSatuses.CLOSING:
cli.SetValues("Disconnecting from "+WsUrl, wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.WARNING);
ctrls.ico.html("<span class=\"blink\">"+wmIcons.Wifi.AddClass('')+"</span>");
ctrls.div.html("Disconnecting...");
ctrls.btn.html("<span class=\"spinner-border spinner-border-sm\"></span>");
ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-warning text-dark");
break;
default:
cli.SetValues("Disconnected from "+WsUrl, wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR);
ctrls.ico.html(wmIcons.Plug.AddClass(''));
ctrls.div.html("Disconnected");
ctrls.btn.html(wmIcons.Bolt.ToHtml());
ctrls.bar.removeClass('bg-success bg-warning bg-danger text-light text-dark').addClass("bg-danger text-light");
break;
}
WmConsole.Trace(cli);
}
};
var WmUpload = {
Reader: null,
FileName: null,
FileSize: null,
FileContent: null,
ReadyToWrite: false,
Cancelled: false,
Load: function() {
let [fn,fe] = $("#file-upload-label").text().toUpperCase().split(".");
WmUpload.FileName = fn.substring(0,7)+".GCO";
let input = $('#file-upload').get(0);
if (input.files.length) {
let tfile = input.files[0];
WmUpload.Reader = new FileReader();
WmUpload.Reader.onloadstart = function() {
jsLog.Debug("File uploading starting");
$('#div-upload-fname').html(WmUpload.FileName);
if(!$('#upload-process-collapse').hasClass("show")){ $('#upload-process-collapse').collapse('show'); }
};
WmUpload.Reader.onload = function(e) {
jsLog.Debug("File uploading completed");
WmUpload.FileSize = e.loaded;
WmUpload.FileContent = e.target.result.split("\n");
WmUpload.Cancelled = false;
$('#div-upload-fsize').html(wmTools.FileSizeFormat(WmUpload.FileSize));
$('#div-upload-fproc').html(wmTools.FormatNumber(WmUpload.FileContent.length,0));
WmControls.Enable(WmButtonGroups.FileProcess);
WmUpload.FileProgress(0,"Ready to process...");
};
WmUpload.Reader.onloadend = function(e) {
jsLog.Debug("File uploading finished");
jsLog.Debug("___________________onloadend");
};
WmUpload.Reader.readAsText(tfile);
return true;
} else {
WmControls.ShowModalAlert('Please select the upload file before continuing');
WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
return false;
}
},
Cancel: function() {
jsLog.Debug("File uploading aborted");
WmUpload.Reader = null;
WmUpload.FileName = null;
WmUpload.FileSize = null;
WmUpload.Cancelled = true;
WmControls.Disable(WmButtonGroups.FileProcess);
WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
$('#div-upload-fsize').html("-");
$('#div-upload-fproc').html("-");
$('#div-upload-fname').html("-");
WmUpload.FileProgress(0,"&nbsp;");
if($('#upload-process-collapse').hasClass("show")){ $('#upload-process-collapse').collapse('hide'); }
},
FileProcess: function() {
WmControls.Disable([$("#btn-file-proc")]);
let fl = WmUpload.FileContent.length;
jsLog.Debug("Start process GCode lines ("+WmUpload.FileSize+" total)");
WmUpload.FileProgress(0,"Start analyzing uploaded GCode...");
wmGCommands.SdFileStart.GParams = WmUpload.FileName;
wmWebSoket.Send(wmGCommands.SdFileStart);
var i = 0;
var n = 1;
(function pgline() {
if(WmUpload.Cancelled){
wmWebSoket.Send(wmGCommands.SdFileStop);
return;
}
else if(!WmUpload.ReadyToWrite){
jsLog.Debug("WmUpload.FileProcess: Waiting ready to write...");
WmUpload.FileProgress(0,"Waiting ready to write...");
setTimeout(pgline, 500);
}
else {
let p = wmTools.GetPercentage(i+1,fl);
WmUpload.FileProgress(p,"Analyzing line "+(i+1)+" of "+fl);
let gitem = { line:WmUpload.FileContent[i], process:false, cksum:0 };
if(gitem.line.trim()==="" || gitem.line.match(/^ *$/)) { jsLog.Verbose("GLine: "+i+": "+gitem.line+" => Empty line (skip)"); }
else if(gitem.line.substring(0,1)===";") { jsLog.Verbose("GLine: "+i+": "+gitem.line+" => Comment line (skip)"); }
else if(gitem.line.indexOf(";") > -1) { gitem.line = gitem.line.substring(0,gitem.line.indexOf(";")); gitem.process=true; }
else { gitem.process = true; }
if(gitem.process) {
gitem.line = "N"+n+" "+gitem.line.trim();
gitem.line = gitem.line+"*"+wmGCommandItem.CalcChecksum(gitem.line);
jsLog.Verbose("GLINE TO SEND: "+gitem.line);
wmGCommands.CustomCmd.GCode = gitem.line;
wmWebSoket.Send(wmGCommands.CustomCmd);
n++;
}
i++;
if (i < fl) { setTimeout(pgline, 10); }
else {
WmUpload.FileProgress(100,"GCode Analysis completed!");
WmUpload.ReadyToWrite = false;
wmWebSoket.Send(wmGCommands.SdFileStop);
WmUpload.FileCompleted();
}
}
})();
},
FileProgress: function(p,m) {
p = wmTools.FormatNumber(p,0);
$('#upload-progressbar').text(p+"%");
$('#upload-progressbar').css('width',p+'%').attr('aria-valuenow', p);
$('#upload-progress-text').html(m);
if(p===100) { $('#upload-progressbar').removeClass("progress-bar-animated"); }
},
FileCompleted: function() {
WmControls.Disable(WmButtonGroups.FileProcess);
WmButtons.GetSdContentList();
},
};
var WmButtons = {
ConsoleListClear: function() { WmConsole.Clear(); },
ConsoleListExport: function() { WmConsole.Export(); },
DeleteSdConfirm: function() {
$('#div-sdfile-delete-badge').html($('#txt-sdfile-selected').val());
},
DeleteSdSelected: function() {
jsLog.Debug("DeleteSdSelected: Delete file:"+$("#txt-sdfile-selected").val());
WmControls.Disable(WmButtonGroups.FileActions);
$('#div-sdfile-delete-rs').collapse('show');
wmGCommands.SdFileDel.GParams = $("#txt-sdfile-selected").val();
wmWebSoket.Send(wmGCommands.SdFileDel);
setTimeout(function(){
$('#modal-sdfile-delete').modal('hide');
$('#div-sdfile-delete-rs').collapse('hide');
WmButtons.GetSdContentList();
}, 2000);
},
GCommandSetPreset: function(gc) {
jsLog.Debug("Set preset GCommand ("+gc+")");
$('#text-gcommand').val(gc);
$('#modal-presets').modal('hide');
WmAutostart.SetGCommandChecksum();
},
GetSdContentList: function() {
wmSdListCounter.Reset();
$('#txt-sdfile-selected').val('');
WmControls.Disable(WmButtonGroups.FileManagement);
wmWebSoket.Send(wmGCommands.SdGetList);
},
PrintSdConfirm: function() {
$('#div-sdfile-print-badge').html($('#txt-sdfile-selected').val());
},
PrintSdSelected: function() {
jsLog.Debug("PrintSdSelected: Print file:"+$("#txt-sdfile-selected").val());
WmControls.Disable(WmButtonGroups.FileActions);
$('#div-sdfile-print-rs').collapse('show');
wmGCommands.SdFilePrint.GParams = $("#txt-sdfile-selected").val();
wmWebSoket.Send(wmGCommands.SdFilePrint);
setTimeout(function(){
$('#modal-sdfile-print').modal('hide');
$('#div-sdfile-print-rs').collapse('hide');
WmAutostart.SetShownPanel(wmEnums.Panels.STATUS);
}, 2000);
},
SaveSettings: function() {
jsLog.Verbose("Button 'btn-save-settings' clicked");
WmControls.Disable(['#btn-save-settings','#btn-close-settings']);
wmSettings.AutoConnect = document.getElementById('set-auto-connect').checked;
wmSettings.DefaultPanel = parseInt($('#set-default-panel').val());
wmSettings.LogLevel = parseInt($('#set-log-level').val());
wmSettings.SymbolMode = $('#set-log-symbol').val();
wmSettings.AutoTempInterval = $('#set-default-autotemp').val();
if($('#set-default-tempunit').val()===0) { wmSettings.TempUnit = wmEnums.TempUnits.CELSIUS; }
else if($('#set-default-tempunit').val()===1) { wmSettings.TempUnit = wmEnums.TempUnits.FAHRENHEIT; }
else if( $('#set-default-tempunit').val()===2) { wmSettings.TempUnit = wmEnums.TempUnits.KELVIN; }
if(wmSettings.SymbolMode==='letter') {
wmSettings.SymbolSend = wmEnums.WsMsgSymbols.SENT.LETTER;
wmSettings.SymbolReceive = wmEnums.WsMsgSymbols.RECEIVED.LETTER;
} else {
wmSettings.SymbolSend = $('#div-log-symbol-icon-sample-s').html();
wmSettings.SymbolReceive = $('#div-log-symbol-icon-sample-r').html();
}
if(document.getElementById('set-trace-mode-append').checked) {
wmSettings.ConsoleDirection = wmEnums.ConsoleDirection.APPEND;
} else {
wmSettings.ConsoleDirection = wmEnums.ConsoleDirection.PREPEND;
}
wmCookie.Write(wmTools.StringFormatJson(wmSettings));
$('#div-save-setting-rs').collapse('show');
setTimeout(function(){
$('#modal-settings').modal('hide');
$('#div-save-setting-rs').collapse('hide');
WmControls.Enable(['#btn-save-settings','#btn-close-settings']);
}, 2000);
},
SdInit: function() {
wmWebSoket.Send(wmGCommands.SdInit);
},
SdRelease: function() {
wmWebSoket.Send(wmGCommands.SdRelease);
},
SendGcommand: function() {
if(wmWebSoket.WSObject !== null && wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) {
WmControls.Disable(["#btn-gcommand"]);
let gcmd = $('#text-gcommand');
if (gcmd.val() === "") {
gcmd.removeClass('border-dark').addClass('border-danger');
jsLog.Warning("Empty custom command string detected");
gcmd.focus();
} else {
gcmd.removeClass('border-danger').addClass('border-dark');
let gc = wmGCommandItem.GetCommandItemByCode(gcmd.val().trim().toUpperCase());
if(gc === null) {
wmGCommands.CustomCmd.GCode = gcmd.val().trim().toUpperCase();
jsLog.Debug("Sending custom command: " + wmGCommands.CustomCmd.GCode);
wmWebSoket.Send(wmGCommands.CustomCmd);
} else {
if(gc.Supported) {
wmGCommands.CustomCmd.GCode = gcmd.val().trim().toUpperCase();
jsLog.Debug("Sending custom command: " + wmGCommands.CustomCmd.GCode);
wmWebSoket.Send(wmGCommands.CustomCmd);
} else {
jsLog.Warning("Unsupported command: " + wmGCommands.CustomCmd.GCode);
WmConsole.Trace(new wmLogItem("GCmd: <span class=\"badge badge-light\">" + gcmd.val() + "</span> Unsupported command", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.ERROR));
}
}
gcmd.val('');
$('#checksum-gcommand-value').html('&nbsp;');
WmControls.Enable(["#btn-gcommand"]);
}
} else { $('#modal-connect').modal('show'); }
},
SetPositionHome: function(b) {
if(b.id==="btn-move-home-all"){ wmWebSoket.Send(wmGCommands.MoveHome); }
else if (b.id==="btn-move-home-x"){ wmWebSoket.Send(wmGCommands.MoveHomeX); }
else if (b.id==="btn-move-home-y"){ wmWebSoket.Send(wmGCommands.MoveHomeY);}
else if (b.id==="btn-move-home-z"){ wmWebSoket.Send(wmGCommands.MoveHomeZ);}
},
SetSdSelected: function(sdi) {
jsLog.Debug("SetSdSelected: Selected file:"+$(sdi).attr("data-sdfile"));
$('#txt-sdfile-selected').val($(sdi).attr("data-sdfile"));
let lip = document.getElementById("list-sd-content").getElementsByTagName("a");
for (let i=0; i<lip.length; i++) { $(lip[i]).removeClass('list-group-item-success').addClass("list-group-item-light"); }
$(sdi).removeClass('list-group-item-light').addClass("list-group-item-success");
WmControls.Enable(WmButtonGroups.FileActions);
if(!$('#div-sd-selected-file').hasClass("show")) { $('#div-sd-selected-file').collapse("show"); }
wmGCommands.SdFileSel.GParams = $(sdi).attr("data-sdfile");
wmWebSoket.Send(wmGCommands.SdFileSel);
},
ToggleChecksumDiv: function() {
let csdiv = $('#checksum-gcommand-div');
if($('#btn-gcommand-checksum').hasClass('active')===true) { csdiv.collapse('hide'); } else { csdiv.collapse('show'); }
},
UploadSdFile: function() {
WmControls.Disable(WmButtonGroups.FileManagement);
WmControls.Disable(WmButtonGroups.FileActions);
if (!window.FileReader) {
jsLog.Error('Your browser do not support JS file uploading');
alert('Your browser do not support JS file uploading');
WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
} else {
jsLog.Debug("Starting upload file process");
if(WmUpload.Load()) { jsLog.Debug("Upload completed"); }
else {
jsLog.Error("Upload failed");
WmControls.Enable(WmButtonGroups.FileManagement,WmButtonGroups.FileActions);
}
}
},
WsConnect: function() {
if(wmWebSoket.WSObject === null) { wmWebSoket.Connect(); }
else { if(wmWebSoket.WSObject.readyState === wmEnums.WSSatuses.OPEN) { wmWebSoket.Disconnect(); } }
},
};
var WmControls = {
Enable: function() {
if(arguments.length > 0) {
for(let i=0; i<arguments.length; i++) {
let fld = arguments[i];
for(let c=0; c<fld.length; c++) { WmControls.SetInputStatus(fld[c],'enabled'); }
}
} else { jsLog.Warning("WmControls.Enable: Missing input arguments"); }
},
Disable: function() {
if(arguments.length > 0) {
for(let i=0; i<arguments.length; i++) {
let fld = arguments[i];
for(let c=0; c<fld.length; c++) { WmControls.SetInputStatus(fld[c],'disabled'); }
}
} else { jsLog.Warning("WmControls.Disable: Missing input arguments"); }
},
SetInputStatus(inid,st) {
if($(inid).attr("data-input-type")==="togglebtn"){
if(st==="enabled") { $(inid).bootstrapToggle('enable'); } else { $(inid).bootstrapToggle('disable'); }
} else {
if(st==="enabled") { $(inid).prop("disabled", false); } else { $(inid).prop("disabled", true); }
}
},
SetCheckStatus: function(ao,b) {
let cs="off";
if(b) { cs="on"; }
for(let i=0; i<ao.length; i++) { $(ao[i]).bootstrapToggle(cs); }
},
SetUpload: function() {
let f = $("#file-upload").val();
jsLog.Debug("SetUploadFilename: Ready to upload file:"+f);
$("#file-upload-label").html(f.split("\\").pop());
WmControls.Enable(WmButtonGroups.FileManagement);
WmControls.Disable(WmButtonGroups.FileProcess);
},
ShowModalAlert: function(m) {
$('#div-alert-message').html(m);
$('#modal-alert').modal('show');
},
SetAutoTemp: function() {
if($('#set-auto-temp').prop('checked')) {
wmGCommands.SetTempOn.GParams = "S"+$('#auto-temp-interval').val();
wmWebSoket.Send(wmGCommands.SetTempOn);
} else { wmWebSoket.Send(wmGCommands.SetTempOff); }
},
SetFanSpeed: function(rv) {
rv = parseInt(rv);
jsLog.Debug("Set fan speed to: "+rv+"%");
let fsv = wmTools.FormatNumber(wmTools.GetNumPercent(rv,255),0);
$('#div-fan-speed-current').html(rv+"%<span class='badge badge-success ml-1'>"+fsv+"</span>");
$('#div-fan-speed-set').html(rv+"%<span class='badge badge-success ml-1'>"+fsv+"</span>");
if(rv===0) { wmWebSoket.Send(wmGCommands.FanOff); }
else {
wmGCommands.FanOn.GParams = "S"+fsv;
wmWebSoket.Send(wmGCommands.FanOn);
}
WmChartsData.FanSpeed.DataUpdate(rv);
},
ResetSdFileCounters() {
$('#list-sd-content').empty();
$('#div-sdlist-file-count').text(0);
$('#div-sdlist-folder-count').text(0);
},
UpdateTemperatures: function(dt){
$('#div-temp-extruder-detect').text(dt.ExtruderTemp);
$('#div-temp-extruder-set').text(dt.ExtruderSet);
$('#div-temp-extruder-unit').text(wmSettings.TempUnit.LABEL);
if(dt.BedTemp !== null) {
$('#div-temp-bed-detect').text(dt.BedTemp);
$('#div-temp-bed-set').text(dt.BedSet);
$('#div-temp-bed-unit').text(wmSettings.TempUnit.LABEL);
}
},
SetPrinterStatusInfo: function(s, m) {
if(!s) {
$('#div-pstatus-sdprint').removeClass("badge-danger").addClass("badge-info");
$('#div-pstatus-sdprint').html("Ready to print");
$('#div-pstatus-timer').collapse('hide');
$('#div-pstatus-progress').collapse('hide');
} else {
$('#div-pstatus-sdprint').removeClass("badge-danger badge-info").addClass("badge-success");
$('#div-pstatus-sdprint').html("Printing in progress");
$('#div-pstatus-timer').collapse('show');
$('#div-pstatus-progress').collapse('show');
}
},
SetSteppers: function(o) {
if(o.id==="set-stepper-all") {
WmControls.SetCheckStatus(WmButtonGroups.Stepper,o.checked);
if(o.checked) { wmWebSoket.Send(wmGCommands.StepEnableAll); } else { wmWebSoket.Send(wmGCommands.StepDisableAll); }
} else {
if(o.id==="set-stepper-x") { wmGCommands.StepEnable.GParams = "X"; }
else if(o.id==="set-stepper-y") { wmGCommands.StepEnable.GParams = "Y"; }
else if(o.id==="set-stepper-z") { wmGCommands.StepEnable.GParams = "Z"; }
else if(o.id==="set-stepper-e") { wmGCommands.StepEnable.GParams = "E"; }
if(o.checked) { wmWebSoket.Send(wmGCommands.StepEnable); } else { wmWebSoket.Send(wmGCommands.StepDisable); }
}
},
};
var WmChartsData = {
Temperatures: {
TimeFormat: 'HH:mm:ss',
Speed: 1000,
Scale: 1,
Extruder: {
Label: "Extruder",
BorderColor: wmColors.RedCoral,
BgColor: wmColors.RedCoral,
Data:[]
},
Bed: {
Label: "Bed",
BorderColor: wmColors.Blue,
BgColor: wmColors.Blue,
Data:[]
},
AddEmpty: function(arr, n) {
for(var i = 0; i < n; i++) {
let xd = moment().subtract((n - i) * WmChartsData.Temperatures.Speed, 'milliseconds').toDate();
arr.push({ x: xd, y: null });
}
},
DataUpdate(di) {
let dt = new Date();
WmChartsData.Temperatures.Extruder.Data.push({ x: dt, y: di.ExtruderTemp });
WmChartsData.Temperatures.Extruder.Data.shift();
if(di.BedTemp !== null) {
WmChartsData.Temperatures.Bed.Data.push({ x: dt, y: di.BedTemp });
WmChartsData.Temperatures.Bed.Data.shift();
}
requestAnimationFrame(WmCharts.Advance);
}
},
FanSpeed: {
Values: {
Label: ["Fan speed",""],
BgColor: [wmColors.GreenSuc, wmColors.Grey],
Data: [0,100]
},
DataUpdate(di) {
WmChartsData.FanSpeed.Values.Data[0] = di;
WmChartsData.FanSpeed.Values.Data[1] = 100 - di;
if(di < 30) { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.GreenSuc; }
else if(di < 60) { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.Yellow; }
else if(di < 80) { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.Orange; }
else { WmChartsData.FanSpeed.Values.BgColor[0] = wmColors.Red; }
requestAnimationFrame(function() { WmCharts.FanSpeed.CanvasItem.update()});
}
}
};
var WmCharts = {
Temperatures: {
CanvasItem: null,
Config: {
type: 'line',
data: {
datasets: [{
label: WmChartsData.Temperatures.Extruder.Label,
data: WmChartsData.Temperatures.Extruder.Data,
backgroundColor: WmChartsData.Temperatures.Extruder.BgColor,
borderColor: WmChartsData.Temperatures.Extruder.BorderColor,
borderWidth: 2,
fill: false,
pointRadius: 1.5
},{
label: WmChartsData.Temperatures.Bed.Label,
data: WmChartsData.Temperatures.Bed.Data,
backgroundColor: WmChartsData.Temperatures.Bed.BgColor,
borderColor: WmChartsData.Temperatures.Bed.BorderColor,
borderWidth: 2,
fill: false,
pointRadius: 1.5
}]
},
options: {
responsive: true,
animation: { duration: WmChartsData.Temperatures.Speed * 1.5, easing:'linear' },
scales: {
xAxes: [{ type:'time', time:{ displayFormats: { second: 'HH:mm:ss'} }, scaleLabel: { display: false } }],
yAxes: [{ ticks: { min: 0} }]
}
}
},
DisplayAxis: function(ck) {
if(ck.id==="chart-show-extruder") {
WmCharts.Temperatures.CanvasItem.getDatasetMeta(0).hidden = ck.checked===true ? false : true;
$('#chart-show-extruder-label').text(ck.checked===true ? "Show" : "Hide");
}
else if(ck.id==="chart-show-bed") {
WmCharts.Temperatures.CanvasItem.getDatasetMeta(1).hidden = ck.checked===true ? false : true;
$('#chart-show-bed-label').text(ck.checked===true ? "Show" : "Hide");
}
if(!$('#set-auto-temp').prop('checked')){ WmCharts.Temperatures.CanvasItem.update(); }
}
},
FanSpeed: {
CanvasItem: null,
Config: {
type: 'doughnut',
data: {
datasets: [{
data: WmChartsData.FanSpeed.Values.Data,
backgroundColor: WmChartsData.FanSpeed.Values.BgColor,
}],
labels: WmChartsData.FanSpeed.Values.Label
},
options: {
responsive: true,
circumference: Math.PI,
rotation: -Math.PI,
legend: { display: false },
tooltips: { enabled: false },
title: { display: false },
animation: {
animateScale: true,
animateRotate: true,
onComplete: function () {
var ctx = this.chart.ctx;
ctx.font = "14pt Verdana";
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
ctx.fillStyle = wmColors.Black;
let ds = this.data.datasets;
let model = ds[0]._meta[Object.keys(ds[0]._meta)[0]].data[0]._model;
let xp = wmTools.FormatNumber(model.x,0), yp = wmTools.FormatNumber(model.y,0);
jsLog.Debug("Drawing speed gauge percentage label position (x,y): "+xp+","+yp);
ctx.fillText(WmChartsData.FanSpeed.Values.Data[0]+'%', xp, yp);
}
}
}
}
},
Init: function() {
WmChartsData.Temperatures.AddEmpty(WmChartsData.Temperatures.Extruder.Data, 20);
WmChartsData.Temperatures.AddEmpty(WmChartsData.Temperatures.Bed.Data, 20);
WmCharts.Temperatures.CanvasItem = new Chart(document.getElementById('chart-temps'), WmCharts.Temperatures.Config);
WmCharts.FanSpeed.CanvasItem = new Chart(document.getElementById('chart-fanspeed'), WmCharts.FanSpeed.Config);
},
Advance: function() {
if (WmChartsData.Temperatures.Extruder.Data[0] !== null && WmChartsData.Temperatures.Extruder.Scale < 4) { WmCharts.Temperatures.CanvasItem.update(); }
WmCharts.Temperatures.CanvasItem.update();
},
SetTempReport: function(tr) {
let temps = {
ExtruderTemp: tr[0].replace(/T:/,""),
ExtruderSet: tr[1],
BedTemp: tr[2]==="undefined" ? null : tr[2].replace(/B:/,""),
BedSet: tr[3]==="undefined" ? null : tr[3]
};
WmChartsData.Temperatures.DataUpdate(temps);
WmControls.UpdateTemperatures(temps);
}
};
var WmConsole = {
Clear: function() {
jsLog.Debug("Clearing console message list...");
$('#gcommand-console-list').empty();
wmLogBuffer.length = 0;
WmConsole.Trace(new wmLogItem("Console list cleared by user", wmEnums.WSMsgDirection.RECEIVED, wmEnums.ConsoleLevels.SUCCESS));
},
Export: function() {
jsLog.Debug("Exporting console message list...");
var fdt = new Array();
// DA FINIRE LA PRIMA RIGA NOMI CAMPI
for(i=0; i<wmLogBuffer.length; i++) { fdt.push(wmLogBuffer[i].ToCsv()+"\n"); }
wmTools.FileDownload("e4dbox_log.csv", "text/csv;charset=utf-8", fdt);
},
SetMessageSymbol: function() {
if($('#set-log-symbol').val()==="icon") {
jsLog.Verbose("Set message symbol icon collapse panel to 'show'",this);
WmConsole.SetSymbolIcon();
$('#div-log-symbol-icon').collapse('show');
} else {
jsLog.Verbose("Set message symbol icon collapse panel to 'hide'",this);
$('#div-log-symbol-icon').collapse('hide');
}
},
SetSymbolIcon: function() {
let ctrl = parseInt($('#set-log-symbol-icon').val());
let hc = {s:null, r:null};
jsLog.Verbose("Set settings symbol sample fields ("+ctrl+")");
if(ctrl===0) { hc.s = wmIcons.ChevronUp.ToHtml(); hc.r = wmIcons.ChevronDown.ToHtml(); }
else if(ctrl===1) { hc.s = wmIcons.LongArrowUp.ToHtml(); hc.r = wmIcons.LongArrowDown.ToHtml(); }
else if(ctrl===2) { hc.s = wmIcons.ChevronLeft.ToHtml(); hc.r = wmIcons.ChevronRight.ToHtml(); }
else if(ctrl===3) { hc.s = wmIcons.LongArrowLeft.ToHtml(); hc.r = wmIcons.LongArrowRight.ToHtml(); }
$('#div-log-symbol-icon-sample-s').html(hc.s);
$('#div-log-symbol-icon-sample-r').html(hc.r);
},
Trace: function(litem) {
wmLogBuffer.push(litem);
let clist = $('#gcommand-console-list');
if (wmSettings.ConsoleDirection === wmEnums.ConsoleDirection.APPEND) { clist.append(litem.ToLoglist()); } else { clist.prepend(litem.ToLoglist()); }
$('#log-counter-badge').text(wmLogBuffer.length);
},
TraceSdFile: function(litem) {
if(litem.SdFile === "Begin file list") { wmSdListCounter.Reset(); }
if(litem.SdFile !== "Begin file list" && litem.SdFile !== "End file list") {
wmSdListCounter.FILES++;
if(litem.SdFile.indexOf("/")>-1) { wmSdListCounter.FOLDERS++; }
}
$('#list-sd-content').append(litem.ToSdFileList());
$('#div-sdlist-file-count').text(wmSdListCounter.FILES);
$('#div-sdlist-folder-count').text(wmSdListCounter.FOLDERS);
if(litem.SdFile === "End file list") { WmControls.Enable(WmButtonGroups.FileManagement); }
}
};
var WmAutostart = {
SetDefaultPanel: function() {
jsLog.Verbose("Set default shown panel ("+wmSettings.DefaultPanel+")");
if (wmSettings.DefaultPanel == wmEnums.Panels.STATUS) { $('#accordion-panel-status-body').addClass("show"); }
else if (wmSettings.DefaultPanel === wmEnums.Panels.CONTROLS) { $('#accordion-panel-controls-body').addClass("show"); }
else if (wmSettings.DefaultPanel === wmEnums.Panels.TEMP) { $('#accordion-panel-temp-body').addClass("show"); }
else if (wmSettings.DefaultPanel === wmEnums.Panels.FILES) { $('#accordion-panel-file-body').addClass("show"); }
else if (wmSettings.DefaultPanel === wmEnums.Panels.CONSOLE) { $('#accordion-panel-console-body').addClass("show"); }
},
SetShownPanel: function(p) {
jsLog.Verbose("Set shown panel ("+p+")");
if (p === wmEnums.Panels.STATUS) { $('#accordion-panel-status-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-status-body').removeClass("show").addClass("hide"); }
if (p === wmEnums.Panels.CONTROLS) { $('#accordion-panel-controls-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-controls-body').removeClass("show").addClass("hide"); }
if (p === wmEnums.Panels.TEMP) { $('#accordion-panel-temp-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-temp-body').removeClass("show").addClass("hide"); }
if (p === wmEnums.Panels.FILES) { $('#accordion-panel-file-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-file-body').removeClass("show").addClass("hide"); }
if (p === wmEnums.Panels.CONSOLE) { $('#accordion-panel-console-body').removeClass("hide").addClass("show"); } else { $('#accordion-panel-console-body').removeClass("show").addClass("hide"); }
},
SetGCommandChecksum: function() {
cs = wmGCommandItem.CalcChecksum($('#text-gcommand').val());
$('#checksum-gcommand-value').text(cs);
jsLog.Debug("Set GCommand checksum ("+cs+")");
},
SetGCommandPresetList: function() {
jsLog.Verbose("Fill GCommand preset list");
let lip = document.getElementById("list-presets").getElementsByTagName("li");
let i=0;
if(lip.length === 1) {
Object.keys(wmGCommands).forEach(key => {
if(wmGCommands[key].GCode != "" && wmGCommands[key].Supported) {
let gp = wmGCommands[key].GParams !== null ? wmTools.StringFormat(wmGCommands[key].GParams,wmGCommands[key].Values) : '';
var lib = "<button type=\"button\" class=\"list-group-item list-group-item-action p-1\" onclick=\"WmButtons.GCommandSetPreset('"+wmGCommands[key].GCode+" "+gp+"')\">";
lib += "<span class=\"h5\"><span class=\"badge badge-success mr-1\" style=\"width:100px;\">"+wmGCommands[key].GCode+" "+gp+"</span></span>";
lib += wmGCommands[key].Description+"</button>";
$('#list-presets').append(lib);
i++;
}
});
}
jsLog.Verbose("Fill GCommand preset list completed ("+i+" items)");
},
SetWmSettingsControls: function() {
jsLog.Verbose("Set settings controls fields");
$('#set-default-panel').val(wmSettings.DefaultPanel);
$('#set-auto-connect').bootstrapToggle(wmSettings.AutoConnect==true ? "on" : "off");
$('#set-default-autotemp').val(wmSettings.AutoTempInterval);
$('#set-default-tempunit').val(wmSettings.TempUnit.VALUE);
$('#set-log-level').val(wmSettings.LogLevel);
if(wmSettings.ConsoleDirection===wmEnums.ConsoleDirection.APPEND) {
$('#set-trace-mode-prepend').prop('checked',false);
$('#set-trace-mode-append').prop('checked',true);
} else {
$('#set-trace-mode-append').prop('checked',false);
$('#set-trace-mode-prepend').prop('checked',true);
}
$('#set-log-symbol').val(wmSettings.SymbolMode);
if(wmSettings.SymbolMode==='letter') { $('#div-log-symbol-icon').collapse('hide'); }
else { $('#div-log-symbol-icon').collapse('show'); SetConsoleSymbolIcon(); }
},
SetAutotempDefault: function() {
$('#auto-temp-interval').val(wmSettings.AutoTempInterval);
}
};
$(document).ready(function () {
$('.accordion-always-open').on('show.bs.collapse', function () { $(this).data('isShowing', true); });
$('.accordion-always-open').on('hide.bs.collapse', function (event) {
if (!$(this).data('isShowing')) { event.preventDefault(); }
$(this).data('isShowing', false);
});
jsLog.Debug("Browser in use: "+wmTools.GetBrowser());
jsLog.Debug("Browser sizes: "+wmTools.GetScreenSize());
// AutoStar Actions
WmAutostart.SetWmSettingsControls();
WmAutostart.SetDefaultPanel();
WmAutostart.SetGCommandPresetList();
WmAutostart.SetAutotempDefault();
// EVENTS: Buttons
$('#btn-clear-console').click(function() { WmButtons.ConsoleListClear(); });
$('#btn-export-console').click(function() { WmButtons.ConsoleListExport(); });
$('#btn-file-proc').click(function(){ WmUpload.FileProcess(); });
$('#btn-file-proc-cancel').click(function() { WmUpload.Cancel(); });
$('#btn-file-upload').click(function(){ WmButtons.UploadSdFile(); });
$('#btn-gcommand').click(function() { WmButtons.SendGcommand(); });
$('#btn-get-sdcontent').click(function() { WmButtons.GetSdContentList(); });
$('#btn-move-home-all').click(function() { WmButtons.SetPositionHome(this); });
$('#btn-move-home-x').click(function() { WmButtons.SetPositionHome(this); });
$('#btn-move-home-y').click(function() { WmButtons.SetPositionHome(this); });
$('#btn-move-home-z').click(function() { WmButtons.SetPositionHome(this); });
$('#btn-save-settings').click(function() { WmButtons.SaveSettings(); });
$('#btn-sdfile-delete-modal').click(function() { WmButtons.DeleteSdSelected(); });
$('#btn-sdfile-print-modal').click(function() { WmButtons.PrintSdSelected(); });
$('#btn-set-sdinit').click(function() { WmButtons.SdInit(); });
$('#btn-set-sdrelease').click(function() { WmButtons.SdRelease(); });
$('#btn-wsconnect').click(function() { WmButtons.WsConnect(); });
$('#btn-wsconnect-modal').click(function() { WmButtons.WsConnect(); });
// EVENTS: Inputs fields
$('#text-gcommand').keyup(function() { WmAutostart.SetGCommandChecksum(); });
$('#text-gcommand').change(function() { WmAutostart.SetGCommandChecksum(); });
$('#set-log-symbol').change(function() { WmConsole.SetMessageSymbol(); });
$('#set-log-symbol-icon').change(function() { WmConsole.SetSymbolIcon(); });
$('#file-upload').change( function() { WmControls.SetUpload(); });
$('#set-auto-temp').change( function() { WmControls.SetAutoTemp(); });
$('#auto-temp-interval').change( function() { WmControls.SetAutoTemp();} );
$('#chart-show-extruder').change( function() { WmCharts.Temperatures.DisplayAxis(this); });
$('#chart-show-bed').change( function() { WmCharts.Temperatures.DisplayAxis(this); });
$('#fan-speed-range').on("change", function() { WmControls.SetFanSpeed(this.value); });
$('#set-stepper-all').change( function() { WmControls.SetSteppers(this); });
$('#set-stepper-e').change( function() { WmControls.SetSteppers(this); });
$('#set-stepper-x').change( function() { WmControls.SetSteppers(this); });
$('#set-stepper-y').change( function() { WmControls.SetSteppers(this); });
$('#set-stepper-z').change( function() { WmControls.SetSteppers(this); });
// Autorun onload
WmConsole.Trace(new wmLogItem("Ready", wmEnums.WSMsgDirection.SENT, wmEnums.ConsoleLevels.SUCCESS));
if(wmSettings.AutoConnect===true) { wmWebSoket.Connect(); }
window.onload = function() {
WmCharts.Init();
WmCharts.Advance();
};
WmControls.Enable(WmButtonGroups.All());
});