overhaul of client files to 'www' dir. This dir will now as a 'bin' dir of sorts. Outside of the 'www' dir there will be old files, temp files and also shell scripts which support continuous compilation and minification of css and js files
45
www/css/debug.css
Normal file
@ -0,0 +1,45 @@
|
||||
.debugContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 500;
|
||||
background-color: #f0f;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#debug_textArea {
|
||||
position:absolute;
|
||||
bottom: 0;
|
||||
/*width: 800px; */
|
||||
z-index: 500;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.debugBtn {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
background-color: #03b;
|
||||
float:left;
|
||||
}
|
||||
|
||||
.agentInfo {
|
||||
background: #fff;
|
||||
border: 1px #333 solid;
|
||||
display: none;
|
||||
float:left;
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.agentInfoToggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#debug_display {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: none;
|
||||
background-color: #fff;
|
||||
opacity: .7;
|
||||
color: #000;
|
||||
}
|
104
www/css/settings.css
Normal file
@ -0,0 +1,104 @@
|
||||
form {
|
||||
margin: 10px;
|
||||
max-width: 600px;
|
||||
}
|
||||
form input {
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
body,th,td {
|
||||
font-family: Helvetica, Arial, "Nimbus Sans L", sans-serif;
|
||||
font-size: 13px;
|
||||
}
|
||||
.settingsContainer {
|
||||
position:relative;
|
||||
/*min-width: 370px;*/
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
/*form#settingsForm {*/
|
||||
/*width: 100% auto;*/
|
||||
/*}*/
|
||||
form fieldset {
|
||||
max-width: 600px;
|
||||
border: 1px solid rgb(187, 187, 187);
|
||||
border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
padding: 8px;
|
||||
/*padding-right: 8px;*/
|
||||
}
|
||||
form fieldset fieldset{
|
||||
max-width: 580px;
|
||||
margin: 15px 0 5px 0;
|
||||
clear: left;
|
||||
float: left;
|
||||
}
|
||||
form fieldset legend {
|
||||
margin-left: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
form label {
|
||||
min-width: 150px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin: 1px 0 0 0;
|
||||
clear: left;
|
||||
}
|
||||
form div {
|
||||
float: left;
|
||||
}
|
||||
form input[type="text"], form input[type="number"], form input[type="password"] {
|
||||
border: 1px solid rgb(144, 192, 255);
|
||||
margin-right: 5px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
form input[type="text"].small, form input[type="number"].small, form input[type="password"].small {
|
||||
width: 50px;
|
||||
}
|
||||
form input[type="text"].large, form input[type="number"].large, form input[type="password"].large {
|
||||
width: 250px;
|
||||
}
|
||||
form input[type="radio"] {
|
||||
margin: 4px 4px 0 0;
|
||||
}
|
||||
|
||||
form textarea {
|
||||
border: 1px solid rgb(144, 192, 255);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
form .startgcode_left {
|
||||
float:left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
form textarea.gcode {
|
||||
width: 252px;
|
||||
/*max-width: 262px;*/
|
||||
/*min-width: 200px;*/
|
||||
height: 150px;
|
||||
}
|
||||
form small {
|
||||
margin: 3px 0 0 0;
|
||||
display: block;
|
||||
clear: left;
|
||||
}
|
||||
form .button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
form #passwordLabel, form #password {
|
||||
display: none;
|
||||
}
|
||||
|
||||
form input.error, form textarea.error, form select.error {
|
||||
border: #f00 solid 2px;
|
||||
}
|
||||
form .errorMsg {
|
||||
color: #f00;
|
||||
margin: 0 0 0 1em;
|
||||
}
|
892
www/css/styles.css
Normal file
@ -0,0 +1,892 @@
|
||||
/*
|
||||
|
||||
GLOBAL CONTAINER
|
||||
|
||||
*/
|
||||
body {
|
||||
background-color: #fcfcfc;
|
||||
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; /* disable cut copy paste */
|
||||
/* disable cut copy paste */
|
||||
overflow: hidden; /* This chops off any overhanging divs */
|
||||
}
|
||||
|
||||
img {
|
||||
z-index: 5; /*pointer-events: none;
|
||||
*/
|
||||
/*-webkit-touch-callout: none;
|
||||
*/
|
||||
/*disable callout, image save panel */
|
||||
/*-webkit-tap-highlight-color: transparent;
|
||||
*/
|
||||
/* "turn off" link highlight */
|
||||
}
|
||||
|
||||
/* http://stackoverflow.com/questions/5348092/prevent-default-press-but-not-default-drag-in-ios-mobilesafari */
|
||||
.btn {
|
||||
background-repeat: no-repeat; /* -webkit-user-select: none;
|
||||
*/
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#landscape {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
max-width: 1024px;
|
||||
max-height: 768px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 5;
|
||||
overflow: hidden;
|
||||
margin: 0px auto;
|
||||
outline: 2px solid #5e8c71;
|
||||
|
||||
-webkit-box-shadow: 0 0 8px rgba(8, 8, 8, 0.25);
|
||||
box-shadow: 0 0 8px rgba(8, 8, 8, 0.25);
|
||||
}
|
||||
|
||||
#portrait {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bgContainer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bgTop,.bgMiddle,.bgBottom {
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
|
||||
filter: alpha(opacity=100);
|
||||
opacity: 1.0;
|
||||
|
||||
-webkit-transition: opacity .35s linear;
|
||||
-moz-transition: opacity .35s linear;
|
||||
-o-transition: opacity .35s linear;
|
||||
-ms-transition: opacity .35s linear;
|
||||
transition: opacity .35s linear;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
z-index: -5;
|
||||
}
|
||||
|
||||
.bgTop {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.bgMiddle {
|
||||
top: 30%;
|
||||
}
|
||||
|
||||
.bgBottom {
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
CENTER PANEL
|
||||
|
||||
*/
|
||||
.centerpanel {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -33%;
|
||||
width: 66%;
|
||||
height: 100%;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.logopanel {
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.d3dlogo {
|
||||
position: relative;
|
||||
top: 15%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0px auto;
|
||||
max-width: 399px;
|
||||
height: 139px;
|
||||
background: url('../img/logo/logo_full.png') no-repeat center center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#verticalShapes {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 15px;
|
||||
margin-right: -8.5%;
|
||||
width: 8%;
|
||||
}
|
||||
|
||||
#verticalShapes > div {
|
||||
border: 2px solid #333;
|
||||
border-radius: 0px 5px 5px 0px;
|
||||
margin-top: 4px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#verticalShapes > div img.verticalshape {
|
||||
width: 100%;
|
||||
max-width: 50px;
|
||||
height: auto;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.drawareacontainer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 65%;
|
||||
background-color: #fff;
|
||||
border: 4px solid #000;
|
||||
border-radius: 15px;
|
||||
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
#canvasContainers {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mycanvasContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 78%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#mycanvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-right: 2px solid #333;
|
||||
}
|
||||
|
||||
#previewContainer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 22%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#preview {
|
||||
min-width: 50px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* DEBUG THING */
|
||||
#preview_tmp {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 500;
|
||||
border: 1px solid #f80;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.bottompanel {
|
||||
position: relative;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
/*
|
||||
DOODLE UP/DOWN/LEFT/RIGHT buttons
|
||||
*/
|
||||
.manipulationBtns {
|
||||
margin: 2px 5px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
max-width: 340px;
|
||||
max-height: 70px;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
.manipulationBtn {
|
||||
width: 45%;
|
||||
height: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#btnsUpDown {
|
||||
float: left;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
#btnsUpDown > div {
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#btnsTurnLeftRight {
|
||||
float: right;
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
#btnsTurnLeftRight > div {
|
||||
float: left;
|
||||
padding-right: 8px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#btnMoveUp {
|
||||
max-width: 65px;
|
||||
}
|
||||
|
||||
#btnMoveDown {
|
||||
max-width: 64px;
|
||||
}
|
||||
|
||||
#btnTwistLeft {
|
||||
max-width: 59px;
|
||||
}
|
||||
|
||||
#btnTwistRight {
|
||||
max-width: 64px;
|
||||
}
|
||||
|
||||
/*
|
||||
HEIGHT-related RESPONSIVE STUFF
|
||||
*/
|
||||
@media screen and (max-height: 700px) {
|
||||
.logopanel {
|
||||
height: 22%;
|
||||
}
|
||||
|
||||
.doodlecontainer {
|
||||
height: 68%;
|
||||
}
|
||||
|
||||
.d3dlogo {
|
||||
top: 25%;
|
||||
max-width: 399px;
|
||||
height: 74px;
|
||||
background-image: url('../img/logo/logo_small.png');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 655px) {
|
||||
.bgMiddle {
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 525px) {
|
||||
.d3dlogo {
|
||||
top: 20%;
|
||||
height: 57px;
|
||||
max-width: 307px;
|
||||
background-image: url('../img/logo/logo_smaller.png');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-height: 375px) {
|
||||
.d3dlogo {
|
||||
height: 40px;
|
||||
max-width: 216px;
|
||||
background-image: url('../img/logo/logo_smallest.png');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
LEFT PANEL
|
||||
|
||||
*/
|
||||
.leftpanel {
|
||||
position: absolute;
|
||||
width: 17%; /* background-color: rgba(67, 204, 67, 0.4);
|
||||
*/
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.btnNew {
|
||||
margin: 5% 0% 1% 5%;
|
||||
width: 100%;
|
||||
max-width: 180px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnsPrevNext {
|
||||
margin: 1% 7%;
|
||||
max-width: 160px;
|
||||
}
|
||||
|
||||
.btnPrevious {
|
||||
width: 40%;
|
||||
max-width: 56px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnNext {
|
||||
width: 40%;
|
||||
max-width: 56px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.btnSave {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
max-width: 144px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnOops {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
max-width: 144px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
RIGHT PANEL
|
||||
|
||||
*/
|
||||
.rightpanel {
|
||||
position: absolute;
|
||||
width: 17%; /* background-color: rgba(255, 0, 254, 0.4);
|
||||
*/
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.btnPrint {
|
||||
margin: 1% 5% 5% 0%;
|
||||
width: 100%;
|
||||
max-width: 163px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.btnStop {
|
||||
margin: 5% 10% 1% 5%;
|
||||
float: right;
|
||||
width: 90%;
|
||||
max-width: 98px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnsSettingsInfo {
|
||||
position: absolute;
|
||||
bottom: 25px;
|
||||
right: 5px;
|
||||
width: 80%;
|
||||
margin: 1% 5%;
|
||||
max-width: 160px;
|
||||
}
|
||||
|
||||
.btnInfo {
|
||||
width: 40%;
|
||||
max-width: 53px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.btnSettings {
|
||||
width: 40%;
|
||||
max-width: 53px;
|
||||
height: auto;
|
||||
float: right;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
PROGRESSGUAGE AND THERMOMETER SHARED STYLES
|
||||
|
||||
*/
|
||||
.progressbarAppear {
|
||||
/*margin-right: 1.5% !important;
|
||||
*/
|
||||
right: -0.5% !important;
|
||||
}
|
||||
|
||||
.thermometerAppear {
|
||||
/*margin-right: 1.5% !important;
|
||||
*/
|
||||
right: -6.5% !important;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
PROGRESS GUAGE
|
||||
|
||||
*/
|
||||
.progressbarCanvasContainerParent {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#progressbarCanvasContainer {
|
||||
position: relative;
|
||||
width: 50%;
|
||||
float: right;
|
||||
border: solid #000;
|
||||
border-width: 2px 0 2px 2px;
|
||||
border-radius: 15px 0 0 15px; /*padding: 5px 0px 5px 5px;
|
||||
*/
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
|
||||
-webkit-box-shadow: 0 2px 5px rgba(37, 37, 37, 0.35);
|
||||
box-shadow: 0 2px 5px rgba(37, 37, 37, 0.35);
|
||||
|
||||
-webkit-transition: right 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
-moz-transition: right 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
-o-transition: right 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
-ms-transition: right 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
transition: right 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
right: -60%;
|
||||
margin-top: 5%;
|
||||
}
|
||||
|
||||
#progressbarCanvas {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
THERMOMETER
|
||||
|
||||
*/
|
||||
.thermometerContainerParent {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
#thermometerContainer {
|
||||
position: relative;
|
||||
width: 45%;
|
||||
float: right;
|
||||
background-color: #fff;
|
||||
border: solid #000;
|
||||
border-width: 2px 0 2px 2px;
|
||||
border-radius: 15px 0 0 15px;
|
||||
padding: 5px;
|
||||
|
||||
-webkit-box-shadow: 0 2px 5px rgba(37, 37, 37, 0.35);
|
||||
box-shadow: 0 2px 5px rgba(37, 37, 37, 0.35);
|
||||
|
||||
-webkit-transition: right 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
-moz-transition: right 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
-o-transition: right 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
-ms-transition: right 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
transition: right 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
right: -55%;
|
||||
}
|
||||
|
||||
#thermometerCanvas {
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/*
|
||||
under all the above styles w.r.t. the cascading effect
|
||||
*/
|
||||
.disabled {
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
|
||||
filter: alpha(opacity=30);
|
||||
opacity: 0.3;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#btnStop.disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
REST
|
||||
|
||||
*/
|
||||
/* CLEARFIX */
|
||||
/* http://nicolasgallagher.com/micro-clearfix-hack/ */
|
||||
.clearfix:before,.clearfix:after {
|
||||
content: " "; /* 1 */
|
||||
display: table; /* 2 */
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* For IE 6/7 only*/
|
||||
.clearfix {
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
SETTINGS POPUP
|
||||
|
||||
*/
|
||||
#contentOverlay {
|
||||
background-color: rgba(255, 255, 255, 0.65);
|
||||
z-index: 20;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#contentOverlay #settings {
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 15;
|
||||
max-width: 775px;
|
||||
max-height: 540px;
|
||||
width: 80%;
|
||||
height: 75%;
|
||||
margin: 7% 8%;
|
||||
|
||||
-webkit-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
border: 2px solid #222;
|
||||
border-radius: 15px;
|
||||
padding: 2%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .toppanel {
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .toppanel .settingsLabelContainer {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 1%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .toppanel .settingsLabelContainer .settingsLabelImg {
|
||||
width: 45%;
|
||||
max-width: 373px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel {
|
||||
width: 100%;
|
||||
height: 90%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel > .settingsContainer {
|
||||
float: left;
|
||||
width: 83%;
|
||||
height: 98%;
|
||||
margin: .5%;
|
||||
|
||||
-ms-overflow-y: scroll;
|
||||
overflow-y: scroll;
|
||||
border: 1px solid #bbbbbb;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel > .btnContainer {
|
||||
width: 15%;
|
||||
height: 100%;
|
||||
float: right;
|
||||
position: relative;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#contentOverlay #settings .bottompanel > .btnContainer > .btnOK {
|
||||
position: absolute;
|
||||
bottom: 3%;
|
||||
right: 7%;
|
||||
max-width: 85px;
|
||||
min-width: 42px;
|
||||
width: 88%;
|
||||
height: auto;
|
||||
margin: 0 2% 2% 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#message {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 0.4em 0.5em;
|
||||
border-radius: 0 0 0 10px;
|
||||
border: 2px solid #333;
|
||||
border-width: 0 0 2px 2px;
|
||||
font-weight: bold;
|
||||
|
||||
-webkit-box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
box-shadow: 0px 2px 6px 0px rgba(16, 16, 16, 0.65);
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#message.error {
|
||||
background: #EB313C;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#message.warning {
|
||||
background: #E9A86E;
|
||||
}
|
||||
|
||||
#message.notice {
|
||||
background: #93CAF4;
|
||||
}
|
||||
|
||||
#message.info {
|
||||
background: #97DD8A;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px),only screen and (max-width: 720px) and (min-device-pixel-ratio: 1.5),only screen and (max-width: 720px) and (-webkit-min-device-pixel-ratio: 1.5) {
|
||||
/*
|
||||
TOP LOGO
|
||||
*/
|
||||
.centerpanel {
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
width: 100%; /* background-color: rgba(0, 135, 255, 0.4);
|
||||
*/
|
||||
}
|
||||
|
||||
.logopanel {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.d3dlogo {
|
||||
top: 0;
|
||||
height: 40px;
|
||||
max-width: 216px;
|
||||
background-image: url('../img/logo/logo_smallest.png');
|
||||
}
|
||||
|
||||
.drawareacontainer {
|
||||
/* position: absolute;
|
||||
*/
|
||||
height: 70%;
|
||||
}
|
||||
|
||||
.bottompanel {
|
||||
height: 10%;
|
||||
}
|
||||
|
||||
.bottompanel .manipulationBtns {
|
||||
margin: 2px -27;
|
||||
right: 22%;
|
||||
width: 38%;
|
||||
}
|
||||
|
||||
/*
|
||||
LEFT
|
||||
*/
|
||||
.leftpanel {
|
||||
width: 100px;
|
||||
background-color: #fff;
|
||||
z-index: 50;
|
||||
|
||||
-webkit-transition: left 0.3s ease-out;
|
||||
-moz-transition: left 0.3s ease-out;
|
||||
-o-transition: left 0.3s ease-out;
|
||||
-ms-transition: left 0.3s ease-out;
|
||||
transition: left 0.3s ease-out;
|
||||
}
|
||||
|
||||
.hideleft {
|
||||
left: -101px;
|
||||
}
|
||||
|
||||
.shadowright {
|
||||
-webkit-box-shadow: 2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
box-shadow: 2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
}
|
||||
|
||||
.btnNew {
|
||||
margin: 5% 5% 1% 5%;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.btnSave {
|
||||
margin-left: 9%;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.btnOops {
|
||||
margin-left: 6%;
|
||||
width: 71%;
|
||||
}
|
||||
|
||||
/*
|
||||
RIGHT
|
||||
*/
|
||||
.rightpanel {
|
||||
width: 100px;
|
||||
background-color: #fff;
|
||||
z-index: 50;
|
||||
|
||||
-webkit-transition: right 0.3s ease-out;
|
||||
-moz-transition: right 0.3s ease-out;
|
||||
-o-transition: right 0.3s ease-out;
|
||||
-ms-transition: right 0.3s ease-out;
|
||||
transition: right 0.3s ease-out;
|
||||
}
|
||||
|
||||
.hideright {
|
||||
right: -101px;
|
||||
}
|
||||
|
||||
.shadowleft {
|
||||
-webkit-box-shadow: -2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
box-shadow: -2px 0 4px rgba(42, 42, 41, 0.6);
|
||||
}
|
||||
|
||||
.btnPrint {
|
||||
margin: 1% 5% 5% 5%;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.btnStop {
|
||||
margin: 5% 6% 1% 5%;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
/*
|
||||
REST
|
||||
*/
|
||||
.sidebutton {
|
||||
display: block;
|
||||
position: absolute; /* top: 50%;
|
||||
*/
|
||||
/* margin-top: -20px;
|
||||
*/
|
||||
top: 40px; /*float: right;
|
||||
*/
|
||||
width: 25px;
|
||||
height: 38px;
|
||||
border: 1px solid #808;
|
||||
background: url('../img/arrows.png') no-repeat;
|
||||
background-color: #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sidebutton:active {
|
||||
background-color: #aaa;
|
||||
}
|
||||
|
||||
.leftpanel .sidebutton {
|
||||
right: -27px;
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
|
||||
.rightpanel .sidebutton {
|
||||
left: -27px;
|
||||
background-position: -25px 0px;
|
||||
}
|
||||
|
||||
.sidebuttonin:active {
|
||||
background-color: #888;
|
||||
}
|
||||
|
||||
.leftpanel .sidebuttonin {
|
||||
background-color: #ccc;
|
||||
background-position: -25px 0px;
|
||||
}
|
||||
|
||||
.rightpanel .sidebuttonin {
|
||||
background-color: #ccc;
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
SETTINGS POPUP -MOBILE
|
||||
|
||||
*/
|
||||
#contentOverlay {
|
||||
z-index: 200;
|
||||
}
|
||||
|
||||
#contentOverlay #settings {
|
||||
width: 87%;
|
||||
height: 82%;
|
||||
margin: 6% 4%;
|
||||
}
|
||||
|
||||
#contentOverlay #settings > .right {
|
||||
width: 14%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (orientation: portrait) {
|
||||
#landscape {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#portrait {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.vertImage {
|
||||
margin: 0px;
|
||||
padding: 0px; /*border: 2px solid #f0f;
|
||||
*/
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
width: auto; /* for ie9 */
|
||||
}
|
||||
|
||||
}
|
1
www/css/styles.min.css
vendored
Normal file
BIN
www/favicon.ico
Executable file
After Width: | Height: | Size: 1.1 KiB |
BIN
www/favicon.png
Normal file
After Width: | Height: | Size: 814 B |
BIN
www/favicon_alt.ico
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
www/img/arrows.png
Normal file
After Width: | Height: | Size: 726 B |
BIN
www/img/bg_bottom.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
www/img/bg_middle.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
www/img/bg_top.png
Normal file
After Width: | Height: | Size: 7.4 KiB |
BIN
www/img/bg_vertical.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
www/img/buttons/btnDown.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
www/img/buttons/btnInfo.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
www/img/buttons/btnLeft.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
www/img/buttons/btnNew.png
Executable file
After Width: | Height: | Size: 9.7 KiB |
BIN
www/img/buttons/btnOk.png
Executable file
After Width: | Height: | Size: 5.1 KiB |
BIN
www/img/buttons/btnOk_settings.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
www/img/buttons/btnOops.png
Executable file
After Width: | Height: | Size: 5.6 KiB |
BIN
www/img/buttons/btnOops2.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
www/img/buttons/btnOops_disabled.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
www/img/buttons/btnPrint.png
Executable file
After Width: | Height: | Size: 7.0 KiB |
BIN
www/img/buttons/btnPrint2.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
BIN
www/img/buttons/btnPrint_disabled.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
www/img/buttons/btnRight.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
www/img/buttons/btnSave.png
Executable file
After Width: | Height: | Size: 5.4 KiB |
BIN
www/img/buttons/btnSettings.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
www/img/buttons/btnStop.png
Executable file
After Width: | Height: | Size: 4.5 KiB |
BIN
www/img/buttons/btnStop2.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
www/img/buttons/btnStop_disabled.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
www/img/buttons/btnTurnLeft.png
Executable file
After Width: | Height: | Size: 1.8 KiB |
BIN
www/img/buttons/btnTurnRight.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
www/img/buttons/btnUp.png
Executable file
After Width: | Height: | Size: 1.4 KiB |
BIN
www/img/buttons/btnZoomIn.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
www/img/buttons/btnZoomOut.png
Executable file
After Width: | Height: | Size: 1.5 KiB |
BIN
www/img/buttons/settings_lable.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
www/img/icon.png
Executable file
After Width: | Height: | Size: 21 KiB |
BIN
www/img/logo/logo_full.png
Executable file
After Width: | Height: | Size: 66 KiB |
BIN
www/img/logo/logo_small.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
www/img/logo/logo_smaller.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
www/img/logo/logo_smallest.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
www/img/progress_bg.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
www/img/progress_fg.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
www/img/settings_lable.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
www/img/thermometer_fg_overlay.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
www/img/vertical_shape_icons/converging.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
www/img/vertical_shape_icons/diverging.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
www/img/vertical_shape_icons/sinus.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
www/img/vertical_shape_icons/straight.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
www/img/webpage_icons/apple-touch-icon-114x114-precomposed.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
www/img/webpage_icons/apple-touch-icon-144x144-precomposed.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
www/img/webpage_icons/apple-touch-icon-72x72-precomposed.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
www/img/webpage_icons/apple-touch-icon-precomposed.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
150
www/index.html
Executable file
@ -0,0 +1,150 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Doodle3D</title>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||
<link rel="icon" type="image/ico" href="favicon_alt.ico"/>
|
||||
<link href="./img/webpage_icons/apple-touch-icon-144x144-precomposed.png" rel="apple-touch-icon-precomposed" sizes="144x144" />
|
||||
|
||||
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
|
||||
|
||||
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||
<link href="css/debug.css" rel="stylesheet" media="screen">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="landscape" class="clearfix">
|
||||
|
||||
<!-- background images -->
|
||||
<div class="bgContainer">
|
||||
<img class="bgTop" src="img/bg_top.png" />
|
||||
<img class="bgMiddle" src="img/bg_middle.png" />
|
||||
<img class="bgBottom" src="img/bg_bottom.png" />
|
||||
</div>
|
||||
|
||||
<!-- left panel -->
|
||||
<div class="leftpanel shadowright">
|
||||
<div class='sidebutton shadowright'></div>
|
||||
<img class="btnNew btn" src="img/buttons/btnNew.png" /><br/>
|
||||
<div class="btnsPrevNext">
|
||||
<img class="btnPrevious btn" src="img/buttons/btnLeft.png">
|
||||
<img class="btnNext btn" src="img/buttons/btnRight.png">
|
||||
</div>
|
||||
<img class="btnSave btn" src="img/buttons/btnSave.png" /><br/>
|
||||
<img class="btnOops btn" src="img/buttons/btnOops.png" /><br/>
|
||||
</div>
|
||||
|
||||
<!-- right panel -->
|
||||
<div class="rightpanel shadowleft">
|
||||
<!--<div class='sidebutton shadowleft'></div>-->
|
||||
<img class="btnPrint btn clearfix" src="img/buttons/btnPrint.png" />
|
||||
<img class="btnStop btn clearfix disabled" src="img/buttons/btnStop.png" />
|
||||
|
||||
<div class="progressbarCanvasContainerParent clearfix">
|
||||
<div id="progressbarCanvasContainer">
|
||||
<canvas id="progressbarCanvas" width="93" height="82"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="thermometerContainerParent clearfix">
|
||||
<div id="thermometerContainer">
|
||||
<canvas id="thermometerCanvas" width="90" height="120"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<div id="thermometerContainer" class="clearfix">-->
|
||||
<!--<canvas id="thermometerCanvas" width="90" height="120"></canvas>-->
|
||||
<!--</div>-->
|
||||
<!-- 2013-10-16 tmp backup
|
||||
<div id="thermometerContainer">
|
||||
<canvas id="thermometerCanvas" width="100" height="125"></canvas>
|
||||
</div>
|
||||
-->
|
||||
<div class="btnsSettingsInfo">
|
||||
<img class="btnSettings btn" src="img/buttons/btnSettings.png">
|
||||
<img class="btnInfo btn" src="img/buttons/btnInfo.png">
|
||||
</div>
|
||||
|
||||
<div id="message"></div>
|
||||
</div>
|
||||
|
||||
<!-- center panel -->
|
||||
<div class="centerpanel">
|
||||
<div class="logopanel">
|
||||
<div class="d3dlogo" onclick="location.reload()"></div>
|
||||
</div>
|
||||
<div class="drawareacontainer">
|
||||
<div id="canvasContainers">
|
||||
<div id="mycanvasContainer">
|
||||
<canvas id="mycanvas"></canvas>
|
||||
</div>
|
||||
<div id="previewContainer">
|
||||
<canvas id="preview"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<canvas id="preview_tmp"></canvas>
|
||||
<div id="verticalShapes">
|
||||
<div><img class="verticalshape straight" src="img/vertical_shape_icons/straight.png" /></div>
|
||||
<div><img class="verticalshape diverging" src="img/vertical_shape_icons/diverging.png" /></div>
|
||||
<div><img class="verticalshape converging" src="img/vertical_shape_icons/converging.png" /></div>
|
||||
<div><img class="verticalshape sinus" src="img/vertical_shape_icons/sinus.png" /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottompanel">
|
||||
<div class="manipulationBtns clearfix">
|
||||
<div id="btnsUpDown">
|
||||
<img class="manipulationBtn" id="btnMoveUp" src="img/buttons/btnUp.png" />
|
||||
<img class="manipulationBtn" id="btnMoveDown" src="img/buttons/btnDown.png" />
|
||||
</div>
|
||||
<div id="btnsTurnLeftRight">
|
||||
<img class="manipulationBtn" id="btnTwistLeft" src="img/buttons/btnTurnLeft.png" />
|
||||
<img class="manipulationBtn" id="btnTwistRight" src="img/buttons/btnTurnRight.png" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="debug_textArea">
|
||||
<textarea rows="5" cols="60" id="textdump"></textarea>
|
||||
</div>
|
||||
<div id="debug_display">
|
||||
</div>
|
||||
<div id="contentOverlay">
|
||||
<div id="settings">
|
||||
<div class="toppanel">
|
||||
<div class="settingsLabelContainer">
|
||||
<img class="settingsLabelImg" src="img/settings_lable.png" alt="settings" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottompanel">
|
||||
<div class="settingsContainer"></div>
|
||||
<div class="btnContainer">
|
||||
<img src="img/buttons/btnOk_settings.png" class="btnOK" alt="settings"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="portrait">
|
||||
<img class="vertImage" src="img/bg_vertical.png"/>
|
||||
</div>
|
||||
<script src="js/libs/jquery-1.8.3.min.js"></script>
|
||||
<script src="js/SettingsWindow.js"></script>
|
||||
<script src="js/d3dServerInterfacing.js"></script>
|
||||
<script src="js/verticalShapes.js"></script>
|
||||
<script src="js/buttonbehaviors.js"></script>
|
||||
<script src="js/canvasDrawing.js"></script>
|
||||
<script src="js/previewRendering.js"></script>
|
||||
<script src="js/gcodeGenerating.js"></script>
|
||||
<script src="js/init_layout.js"></script>
|
||||
<script src="js/Printer.js"></script>
|
||||
<script src="js/Progressbar.js"></script>
|
||||
<script src="js/Thermometer.js"></script>
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/sidebar.js"></script>
|
||||
<script src="js/message.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
323
www/js/Printer.js
Normal file
@ -0,0 +1,323 @@
|
||||
/* not using this now
|
||||
var $printProgressContainer = $("#printProgressContainer");
|
||||
var $progressbar = $("#progressbar");
|
||||
var $progressAmount = $(".progressAmount");
|
||||
function setPrintprogress(val) {
|
||||
if (isNaN(val)) return;
|
||||
// console.log("f:setPrintprogress() >> val " + val);
|
||||
$progressbar.css("width", val*100 + "%");
|
||||
$progressAmount.text(Math.floor(val*100) + "%");
|
||||
}
|
||||
//*/
|
||||
|
||||
function Printer() {
|
||||
|
||||
Printer.WIFIBOX_DISCONNECTED_STATE = "wifibox disconnected";
|
||||
Printer.UNKNOWN_STATE = "unknown"; // happens when a printer is connection but there isn't communication yet
|
||||
Printer.DISCONNECTED_STATE = "disconnected"; // printer disconnected
|
||||
Printer.IDLE_STATE = "idle"; // printer found, but idle
|
||||
Printer.BUFFERING_STATE = "buffering"; // printer is buffering (recieving) data, but not yet printing
|
||||
Printer.PRINTING_STATE = "printing";
|
||||
Printer.STOPPING_STATE = "stopping"; // when you stop (abort) a print it prints the endcode
|
||||
|
||||
Printer.ON_BEFORE_UNLOAD_MESSAGE = "You're doodle is still being send to the printer, leaving will result in a incomplete 3D print";
|
||||
|
||||
this.temperature = 0;
|
||||
this.targetTemperature = 0;
|
||||
this.currentLine = 0;
|
||||
this.totalLines = 0;
|
||||
this.bufferedLines = 0;
|
||||
this.state = Printer.UNKNOWN_STATE;
|
||||
this.hasControl = true; // whether this client has control access
|
||||
|
||||
this.wifiboxURL;
|
||||
|
||||
this.checkStatusInterval = 3000;
|
||||
this.checkStatusDelay;
|
||||
this.timeoutTime = 3000;
|
||||
this.sendPrintPartTimeoutTime = 5000;
|
||||
|
||||
this.gcode; // gcode to be printed
|
||||
this.sendLength = 1500; // max amount of gcode lines per post (limited because WiFi box can't handle to much)
|
||||
|
||||
this.retryDelay = 2000; // retry setTimout delay
|
||||
this.retrySendPrintPartDelay; // retry setTimout instance
|
||||
this.retryCheckStatusDelay; // retry setTimout instance
|
||||
this.retryStopDelay; // retry setTimout instance
|
||||
this.retryPreheatDelay; // retry setTimout instance
|
||||
|
||||
this.maxGCodeSize = 10; // max size of gcode in MB's (estimation)
|
||||
|
||||
this.stateOverruled = false;
|
||||
|
||||
// Events
|
||||
Printer.UPDATE = "update";
|
||||
|
||||
var self = this;
|
||||
|
||||
this.init = function() {
|
||||
console.log("Printer:init");
|
||||
//this.wifiboxURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
|
||||
//this.wifiboxURL = "http://192.168.5.1/cgi-bin/d3dapi";
|
||||
this.wifiboxURL = wifiboxURL;
|
||||
//this.wifiboxURL = "proxy5.php";
|
||||
console.log(" wifiboxURL: ",this.wifiboxURL);
|
||||
|
||||
if(autoUpdate) {
|
||||
this.startStatusCheckInterval();
|
||||
}
|
||||
}
|
||||
|
||||
this.preheat = function() {
|
||||
console.log("Printer:preheat");
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/heatup",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:preheat response: ",data);
|
||||
if(data.status == "error") {
|
||||
clearTimeout(self.retryPreheatDelay);
|
||||
self.retryPreheatDelay = setTimeout(function() { self.preheat() },self.retryDelay); // retry after delay
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:preheat: failed");
|
||||
clearTimeout(self.retryPreheatDelay);
|
||||
self.retryPreheatDelay = setTimeout(function() { self.preheat() },self.retryDelay); // retry after delay
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:preheat() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
|
||||
this.print = function(gcode) {
|
||||
console.log("Printer:print");
|
||||
console.log(" gcode total # of lines: " + gcode.length);
|
||||
|
||||
message.set("Sending doodle to printer...",Message.NOTICE);
|
||||
self.addLeaveWarning();
|
||||
|
||||
/*for (i = 0; i < gcode.length; i++) {
|
||||
gcode[i] += " (" + i + ")";
|
||||
}*/
|
||||
|
||||
this.sendIndex = 0;
|
||||
this.gcode = gcode;
|
||||
|
||||
//console.log(" gcode[20]: ",gcode[20]);
|
||||
var gcodeLineSize = this.byteSize(gcode[20]);
|
||||
//console.log(" gcodeLineSize: ",gcodeLineSize);
|
||||
var gcodeSize = gcodeLineSize*gcode.length/1024/1024; // estimate gcode size in MB's
|
||||
console.log(" gcodeSize: ",gcodeSize);
|
||||
|
||||
if(gcodeSize > this.maxGCodeSize) {
|
||||
console.log("Error: Printer:print: gcode file is probably to big ("+gcodeSize+"MB) (max: "+this.maxGCodeSize+"MB)");
|
||||
return;
|
||||
}
|
||||
|
||||
//this.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||
|
||||
this.sendPrintPart(this.sendIndex, this.sendLength);
|
||||
}
|
||||
this.byteSize = function(s){
|
||||
return~-encodeURI(s).split(/%..|./).length;
|
||||
}
|
||||
this.sendPrintPart = function(sendIndex,sendLength) {
|
||||
console.log("Printer:sendPrintPart sendIndex: " + sendIndex + "/" + this.gcode.length + ", sendLength: " + sendLength);
|
||||
|
||||
var firstOne = (sendIndex == 0)? true : false;
|
||||
var start = firstOne; // start printing right away
|
||||
|
||||
var completed = false;
|
||||
if (this.gcode.length < (sendIndex + sendLength)) {
|
||||
console.log(" sending less than max sendLength (and last)");
|
||||
sendLength = this.gcode.length - sendIndex;
|
||||
//lastOne = true;
|
||||
completed = true;
|
||||
}
|
||||
var gcodePart = this.gcode.slice(sendIndex, sendIndex+sendLength);
|
||||
|
||||
var postData = { gcode: gcodePart.join("\n"), first: firstOne, start: start};
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/print",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
timeout: this.sendPrintPartTimeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:sendPrintPart response: ",data);
|
||||
|
||||
if(data.status == "success") {
|
||||
if (completed) {
|
||||
console.log("Printer:sendPrintPart:gcode sending completed");
|
||||
this.gcode = [];
|
||||
btnStop.css("display","block"); // hack
|
||||
self.removeLeaveWarning();
|
||||
message.set("Doodle is send to printer...",Message.INFO,true);
|
||||
//self.targetTemperature = settings["printer.temperature"]; // slight hack
|
||||
} else {
|
||||
// only if the state hasn't bin changed (by for example pressing stop) we send more gcode
|
||||
|
||||
console.log("Printer:sendPrintPart:gcode part received (state: ",self.state,")");
|
||||
if(self.state == Printer.PRINTING_STATE || self.state == Printer.BUFFERING_STATE) {
|
||||
console.log("Printer:sendPrintPart:sending next part");
|
||||
self.sendPrintPart(sendIndex + sendLength, sendLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
// after we know the first gcode packed has bin received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
if(sendIndex == 0) {
|
||||
self.startStatusCheckInterval();
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:sendPrintPart: failed");
|
||||
clearTimeout(self.retrySendPrintPartDelay);
|
||||
self.retrySendPrintPartDelay = setTimeout(function() {
|
||||
console.log("request printer:sendPrintPart failed retry");
|
||||
self.sendPrintPart(sendIndex, sendLength)
|
||||
},self.retryDelay); // retry after delay
|
||||
|
||||
// after we know the gcode packed has bin received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
self.startStatusCheckInterval();
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:sendPrintPart() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
|
||||
this.stop = function() {
|
||||
console.log("Printer:stop");
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/printer/stop",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(data){
|
||||
console.log("Printer:stop response: ", data);
|
||||
|
||||
// after we know the stop has bin received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
self.startStatusCheckInterval();
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:stop: failed");
|
||||
clearTimeout(self.retryStopDelay);
|
||||
self.retryStopDelay = setTimeout(function() { self.stop() },self.retryDelay); // retry after delay
|
||||
|
||||
// after we know the stop has bin received or failed
|
||||
// (and the driver had time to update the printer.state)
|
||||
// we start checking the status again
|
||||
self.startStatusCheckInterval();
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:communicateWithWifibox() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
this.startStatusCheckInterval = function() {
|
||||
console.log("Printer:startStatusCheckInterval");
|
||||
self.checkStatus();
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval);
|
||||
}
|
||||
this.stopStatusCheckInterval = function() {
|
||||
console.log("Printer:stopStatusCheckInterval");
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
}
|
||||
this.checkStatus = function() {
|
||||
console.log("Printer:checkStatus");
|
||||
this.stateOverruled = false;
|
||||
//console.log(" stateOverruled: ",this.stateOverruled);
|
||||
var self = this;
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/info/status",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(response){
|
||||
//console.log(" Printer:status: ",response.data.state); //," response: ",response);
|
||||
|
||||
self.handleStatusUpdate(response);
|
||||
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.checkStatusDelay = setTimeout(function() { self.checkStatus() }, self.checkStatusInterval);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Printer:checkStatus: failed");
|
||||
self.state = Printer.WIFIBOX_DISCONNECTED_STATE;
|
||||
clearTimeout(self.checkStatusDelay);
|
||||
clearTimeout(self.retryCheckStatusDelay);
|
||||
self.retryCheckStatusDelay = setTimeout(function() { self.checkStatus() },self.retryDelay); // retry after delay
|
||||
$(document).trigger(Printer.UPDATE);
|
||||
});
|
||||
} else {
|
||||
console.log ("Printer >> f:checkStatus() >> communicateWithWifibox is false, so not executing this function");
|
||||
}
|
||||
}
|
||||
this.handleStatusUpdate = function(response) {
|
||||
console.log("Printer:handleStatusUpdate response: ",response);
|
||||
var data = response.data;
|
||||
if(response.status != "success") {
|
||||
self.state = Printer.UNKNOWN_STATE;
|
||||
} else {
|
||||
// state
|
||||
//console.log(" stateOverruled: ",this.stateOverruled);
|
||||
if(!this.stateOverruled) {
|
||||
self.state = data.state;
|
||||
//console.log(" state > ",self.state);
|
||||
}
|
||||
|
||||
// temperature
|
||||
self.temperature = data.hotend;
|
||||
self.targetTemperature = data.hotend_target;
|
||||
|
||||
// progress
|
||||
self.currentLine = data.current_line;
|
||||
self.totalLines = data.total_lines;
|
||||
self.bufferedLines = data.buffered_lines
|
||||
|
||||
// access
|
||||
self.hasControl = data.has_control;
|
||||
|
||||
if(self.state == Printer.PRINTING_STATE || self.state == Printer.STOPPING_STATE) {
|
||||
console.log("progress: ",self.currentLine+"/"+self.totalLines+" ("+self.bufferedLines+") ("+self.state+")");
|
||||
}
|
||||
}
|
||||
$(document).trigger(Printer.UPDATE);
|
||||
}
|
||||
this.overruleState = function(newState) {
|
||||
this.stateOverruled = true;
|
||||
console.log(" stateOverruled: ",this.stateOverruled);
|
||||
|
||||
self.state = newState;
|
||||
|
||||
$(document).trigger(Printer.UPDATE);
|
||||
|
||||
this.stopStatusCheckInterval();
|
||||
}
|
||||
|
||||
this.removeLeaveWarning = function() {
|
||||
window.onbeforeunload = null;
|
||||
}
|
||||
this.addLeaveWarning = function() {
|
||||
window.onbeforeunload = function() {
|
||||
return Printer.ON_BEFORE_UNLOAD_MESSAGE;
|
||||
};
|
||||
}
|
||||
}
|
106
www/js/Progressbar.js
Normal file
@ -0,0 +1,106 @@
|
||||
function Progressbar() {
|
||||
this.currProgress = 0; // default val
|
||||
|
||||
this.progressbarFGImg = new Image();
|
||||
this.progressbarFGImgSrc = "img/progress_fg.png";
|
||||
this.progressbarBGImg = new Image();
|
||||
this.progressbarBGImgSrc = "img/progress_bg.png";
|
||||
|
||||
this.progressWidth= 93;
|
||||
this.progressHeight = 82;
|
||||
|
||||
this.quartPI = .5 * Math.PI;
|
||||
this.twoPI = 2 * Math.PI;
|
||||
|
||||
|
||||
this.$canvas;
|
||||
this.canvas;
|
||||
this.context;
|
||||
this.$container;
|
||||
|
||||
this.isInitted = false;
|
||||
|
||||
this.enabled = true;
|
||||
|
||||
this.init = function(targCanvas, targCanvasContainer) {
|
||||
console.log("Thermometer.init()");
|
||||
|
||||
this.$container = targCanvasContainer;
|
||||
|
||||
this.$canvas = targCanvas;
|
||||
this.canvas = this.$canvas[0];
|
||||
this.context = this.canvas.getContext('2d');
|
||||
|
||||
|
||||
var self = this;
|
||||
this.progressbarBGImg.onload = function() {
|
||||
console.log("progressbarBGImg img loaded");
|
||||
// self.isInitted = true;
|
||||
// self.update(self.currentTemperature, self.targetTemperature);
|
||||
|
||||
self.progressbarFGImg.onload = function() {
|
||||
console.log("progressbarFGImg img loaded");
|
||||
self.isInitted = true;
|
||||
self.update(0, 100);
|
||||
};
|
||||
self.progressbarFGImg.src = self.progressbarFGImgSrc;
|
||||
};
|
||||
this.progressbarBGImg.src = this.progressbarBGImgSrc;
|
||||
}
|
||||
|
||||
this.update = function(part, total) {
|
||||
//console.log("Progressbar.update(" + part + "," + total + ")");
|
||||
|
||||
var pct = part / total;
|
||||
if (this.isInitted) {
|
||||
if (part == undefined) part = 0;
|
||||
if (total== undefined) total = 100; // prevent divide by zero
|
||||
|
||||
var progress = part / total;
|
||||
progress = Math.min(progress, 1.0);
|
||||
progress = Math.max(progress, 0);
|
||||
//console.log("progressbar >> f:update() >> progress: " + progress);
|
||||
|
||||
// clear
|
||||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
|
||||
this.context.drawImage(this.progressbarBGImg, 0, 0);
|
||||
|
||||
this.context.font = "7pt sans-serif";
|
||||
|
||||
// draw the progressbar foreground's clipping path
|
||||
this.context.save();
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(45, 45);
|
||||
this.context.lineTo(45, 0);
|
||||
this.context.arc(45, 45, 45, -this.quartPI, -this.quartPI + (progress * (this.twoPI)), false); // circle bottom of thermometer
|
||||
this.context.lineTo(45, 45);
|
||||
this.context.clip();
|
||||
|
||||
this.context.drawImage(this.progressbarFGImg, 0, 0);
|
||||
this.context.restore();
|
||||
|
||||
if (debugMode) {
|
||||
this.context.fillStyle = '#222';
|
||||
this.context.strokeStyle = '#fff';
|
||||
this.context.lineWidth = 3;
|
||||
this.context.textAlign="center";
|
||||
this.context.strokeText(part + " / " + total, 45, 45, 90);
|
||||
this.context.fillText(part + " / " + total, 45, 45, 90);
|
||||
}
|
||||
|
||||
} else {
|
||||
console.log("Progressbar.setTemperature() -> thermometer not initialized!");
|
||||
}
|
||||
}
|
||||
this.show = function() {
|
||||
this.$container.addClass("progressbarAppear");
|
||||
// this.$container.show();
|
||||
this.enabled = true;
|
||||
}
|
||||
this.hide = function() {
|
||||
this.$container.removeClass("progressbarAppear");
|
||||
// this.$container.hide();
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
651
www/js/SettingsWindow.js
Normal file
@ -0,0 +1,651 @@
|
||||
//these settings are defined in the firmware (conf_defaults.lua) and will be initialized in loadSettings()
|
||||
var settings = {
|
||||
"network.ap.ssid": "d3d-ap-%%MAC_ADDR_TAIL%%",
|
||||
"network.ap.address": "192.168.10.1",
|
||||
"network.ap.netmask": "255.255.255.0",
|
||||
"printer.temperature": 220,
|
||||
"printer.maxObjectHeight": 150,
|
||||
"printer.layerHeight": 0.2,
|
||||
"printer.wallThickness": 0.7,
|
||||
"printer.screenToMillimeterScale": 0.3,
|
||||
"printer.speed": 50,
|
||||
"printer.travelSpeed": 200,
|
||||
"printer.filamentThickness": 2.85,
|
||||
"printer.enableTraveling": true,
|
||||
"printer.useSubLayers": true,
|
||||
"printer.firstLayerSlow": true,
|
||||
"printer.autoWarmUp": true,
|
||||
"printer.simplify.iterations": 10,
|
||||
"printer.simplify.minNumPoints": 15,
|
||||
"printer.simplify.minDistance": 3,
|
||||
"printer.retraction.enabled": true,
|
||||
"printer.retraction.speed": 50,
|
||||
"printer.retraction.minDistance": 1,
|
||||
"printer.retraction.amount": 5,
|
||||
"printer.autoWarmUpCommand": "M104 S220 (hardcoded temperature)"
|
||||
}
|
||||
|
||||
|
||||
function SettingsWindow() {
|
||||
this.wifiboxURL;
|
||||
this.wifiboxCGIBinURL
|
||||
this.window;
|
||||
this.form;
|
||||
this.timeoutTime = 3000;
|
||||
this.retryDelay = 2000; // retry setTimout delay
|
||||
this.retryRetrieveNetworkStatusDelayTime = 1000;// retry setTimout delay
|
||||
|
||||
this.retryLoadSettingsDelay; // retry setTimout instance
|
||||
this.retrySaveSettingsDelay; // retry setTimout instance
|
||||
this.retryRetrieveNetworkStatusDelay;// retry setTimout instance
|
||||
|
||||
|
||||
this.apFieldSet;
|
||||
this.clientFieldSet;
|
||||
this.networks;
|
||||
this.currentNetwork; // the ssid of the network the box is on
|
||||
this.selectedNetwork; // the ssid of the selected network in the client mode settings
|
||||
this.currentLocalIP = "";
|
||||
this.clientModeState = SettingsWindow.NOT_CONNECTED;
|
||||
this.currentAP;
|
||||
this.apModeState = SettingsWindow.NO_AP;
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch
|
||||
this.retrieveNetworkStatusDelay; // setTimout delay
|
||||
this.retrieveNetworkStatusDelayTime = 1000;
|
||||
|
||||
// Events
|
||||
SettingsWindow.SETTINGS_LOADED = "settingsLoaded";
|
||||
|
||||
// network client mode states
|
||||
SettingsWindow.NOT_CONNECTED = "not connected"; // also used as first item in networks list
|
||||
SettingsWindow.CONNECTED = "connected";
|
||||
SettingsWindow.CONNECTING = "connecting";
|
||||
SettingsWindow.CONNECTING_FAILED = "connecting failed"
|
||||
|
||||
// network access point mode states
|
||||
SettingsWindow.NO_AP = "no ap";
|
||||
SettingsWindow.AP = "ap";
|
||||
SettingsWindow.CREATING_AP = "creating ap";
|
||||
|
||||
|
||||
SettingsWindow.API_CONNECTING_FAILED = -1
|
||||
SettingsWindow.API_NOT_CONNECTED = 0
|
||||
SettingsWindow.API_CONNECTING = 1
|
||||
SettingsWindow.API_CONNECTED = 2
|
||||
SettingsWindow.API_CREATING = 3
|
||||
SettingsWindow.API_CREATED = 4
|
||||
|
||||
var self = this;
|
||||
|
||||
this.init = function(wifiboxURL,wifiboxCGIBinURL) {
|
||||
this.wifiboxURL = wifiboxURL;
|
||||
this.wifiboxCGIBinURL = wifiboxCGIBinURL;
|
||||
|
||||
this.window = $("#settings");
|
||||
this.window.find(".btnOK").click(this.submitwindow);
|
||||
this.window.find(".settingsContainer").load("settings.html", function() {
|
||||
console.log("Settings:finished loading settings.html, now loading settings...");
|
||||
|
||||
self.form = self.window.find("form");
|
||||
self.form.submit(function (e) { self.submitwindow(e) });
|
||||
|
||||
self.loadSettings();
|
||||
|
||||
var btnAP = self.form.find("label[for='ap']");
|
||||
var btnClient = self.form.find("label[for='client']");
|
||||
var btnRefresh = self.form.find("#refreshNetworks");
|
||||
var btnConnect = self.form.find("#connectToNetwork");
|
||||
var btnCreate = self.form.find("#createAP");
|
||||
var networkSelector = self.form.find("#network");
|
||||
self.apFieldSet = self.form.find("#apSettings");
|
||||
self.clientFieldSet = self.form.find("#clientSettings");
|
||||
|
||||
btnAP.on('touchstart mousedown',self.showAPSettings);
|
||||
btnClient.on('touchstart mousedown',self.showClientSettings);
|
||||
btnRefresh.on('touchstart mousedown',self.refreshNetworks);
|
||||
btnConnect.on('touchstart mousedown',self.connectToNetwork);
|
||||
btnCreate.on('touchstart mousedown',self.createAP);
|
||||
networkSelector.change(self.networkSelectorChanged);
|
||||
});
|
||||
}
|
||||
this.submitwindow = function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
self.saveSettings(self.readForm(),function(){
|
||||
self.hideSettings();
|
||||
});
|
||||
|
||||
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
||||
}
|
||||
|
||||
this.showSettings = function() {
|
||||
console.log("f:showSettings()");
|
||||
|
||||
this.loadSettings(); // reload settings
|
||||
// this.window.css("display","table");
|
||||
$("#contentOverlay").fadeIn(375, function() {
|
||||
document.body.removeEventListener('touchmove',prevent,false);
|
||||
});
|
||||
}
|
||||
this.hideSettings = function() {
|
||||
$("#contentOverlay").fadeOut(375, function() {
|
||||
document.body.addEventListener('touchmove',prevent,false);
|
||||
// self.window.css("display","none");
|
||||
});
|
||||
}
|
||||
|
||||
this.loadSettings = function() {
|
||||
if (!communicateWithWifibox) {
|
||||
console.log(" communicateWithWifibox is false: settings aren't being loaded from wifibox...")
|
||||
return;
|
||||
}
|
||||
console.log("Settings:loadSettings() >> getting new data...");
|
||||
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/config/all",
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:loadSettings response: ",response);
|
||||
settings = response.data;
|
||||
console.log(" settings: ",settings);
|
||||
self.fillForm();
|
||||
$(document).trigger(SettingsWindow.SETTINGS_LOADED);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:loadSettings: failed");
|
||||
clearTimeout(self.retryLoadSettingsDelay);
|
||||
self.retryLoadSettingsDelay = setTimeout(function() { self.loadSettings() },self.retryDelay); // retry after delay
|
||||
});
|
||||
|
||||
this.refreshNetworks();
|
||||
this.retrieveNetworkStatus(false);
|
||||
}
|
||||
this.fillForm = function() {
|
||||
console.log("SettingsWindow:fillForm");
|
||||
|
||||
//fill form with loaded settings
|
||||
var selects = this.form.find("select");
|
||||
selects.each( function(index,element) {
|
||||
var element = $(element);
|
||||
element.val(settings[element.attr('name')]);
|
||||
});
|
||||
var inputs = this.form.find("input");
|
||||
inputs.each( function(index,element) {
|
||||
var element = $(element);
|
||||
//console.log("printer setting input: ",index,element.attr("type"),element.attr('name')); //,element);
|
||||
switch(element.attr("type")) {
|
||||
case "text":
|
||||
case "number":
|
||||
element.val(settings[element.attr('name')]);
|
||||
break;
|
||||
case "checkbox":
|
||||
element.prop('checked', settings[element.attr('name')]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
var textareas = this.form.find("textarea");
|
||||
textareas.each( function(index,element) {
|
||||
var element = $(element);
|
||||
var value = settings[element.attr('name')];
|
||||
element.val(value);
|
||||
});
|
||||
}
|
||||
|
||||
this.saveSettings = function(newSettings,complete) {
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: this.wifiboxURL + "/config",
|
||||
type: "POST",
|
||||
data: newSettings,
|
||||
dataType: 'json',
|
||||
timeout: this.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:saveSettings response: ",response);
|
||||
if(response.status == "error") {
|
||||
clearTimeout(self.retrySaveSettingsDelay);
|
||||
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings(settings) },self.retryDelay); // retry after delay
|
||||
} else {
|
||||
var data = response.data;
|
||||
var validation = data.validation;
|
||||
self.clearValidationErrors();
|
||||
var validated = true;
|
||||
$.each(validation, function(key, val) {
|
||||
if (val != "ok") {
|
||||
console.log("ERROR: setting '" + key + "' not successfully set. Message: " + val);
|
||||
self.displayValidationError(key,val);
|
||||
validated = false;
|
||||
}
|
||||
});
|
||||
settings.substituted_ssid = data.substituted_ssid;
|
||||
if(complete && validated) complete();
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:saveSettings: failed");
|
||||
clearTimeout(self.retrySaveSettingsDelay);
|
||||
self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings(settings) },self.retryDelay); // retry after delay
|
||||
});
|
||||
}
|
||||
}
|
||||
this.displayValidationError = function(key,msg) {
|
||||
var formElement = self.form.find("[name|='"+key+"']");
|
||||
console.log("formElement: ",formElement);
|
||||
formElement.addClass("error");
|
||||
var errorMsg = "<p class='errorMsg'>"+msg+"</p>"
|
||||
formElement.after(errorMsg);
|
||||
}
|
||||
this.clearValidationErrors = function() {
|
||||
var formElements = self.form.find(".error");
|
||||
formElements.each( function(index,element) {
|
||||
$(element).removeClass("error");
|
||||
});
|
||||
}
|
||||
|
||||
this.readForm = function() {
|
||||
//console.log("SettingsWindow:readForm");
|
||||
var settings = {};
|
||||
var selects = self.form.find("select");
|
||||
selects.each( function(index,element) {
|
||||
var element = $(element);
|
||||
if(element.attr('name') != "network.client.network") {
|
||||
settings[element.attr('name')] = element.val();
|
||||
}
|
||||
});
|
||||
|
||||
var inputs = self.form.find("input");
|
||||
inputs.each( function(index,element) {
|
||||
var element = $(element);
|
||||
switch(element.attr("type")) {
|
||||
case "text":
|
||||
case "number":
|
||||
settings[element.attr('name')] = element.val();
|
||||
break;
|
||||
case "checkbox":
|
||||
settings[element.attr('name')] = element.prop('checked')
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
var textareas = self.form.find("textarea");
|
||||
textareas.each( function(index,element) {
|
||||
var element = $(element);
|
||||
settings[element.attr('name')] = element.val();
|
||||
});
|
||||
//console.log(settings);
|
||||
return settings;
|
||||
}
|
||||
|
||||
/*
|
||||
* Networks ui
|
||||
*/
|
||||
this.showAPSettings = function() {
|
||||
self.apFieldSet.show();
|
||||
self.clientFieldSet.hide();
|
||||
}
|
||||
this.showClientSettings = function() {
|
||||
self.clientFieldSet.show();
|
||||
self.apFieldSet.hide();
|
||||
}
|
||||
this.refreshNetworks = function() {
|
||||
console.log("Settings:refreshNetworks");
|
||||
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/network/scan",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:refreshNetworks response: ",response);
|
||||
if(response.status == "error") {
|
||||
//clearTimeout(self.retrySaveSettingsDelay);
|
||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
} else {
|
||||
var networks = response.data.networks
|
||||
self.networks = {};
|
||||
var foundCurrentNetwork = false;
|
||||
var networkSelector = self.form.find("#network");
|
||||
networkSelector.empty();
|
||||
networkSelector.append(
|
||||
$("<option></option>").val(SettingsWindow.NOT_CONNECTED).html("not connected")
|
||||
);
|
||||
$.each(networks, function(index,element) {
|
||||
if(element.ssid == self.currentNetwork) {
|
||||
foundCurrentNetwork = true;
|
||||
}
|
||||
networkSelector.append(
|
||||
$("<option></option>").val(element.ssid).html(element.ssid)
|
||||
);
|
||||
self.networks[element.ssid] = element;
|
||||
});
|
||||
if(foundCurrentNetwork) {
|
||||
networkSelector.val(self.currentNetwork);
|
||||
self.selectNetwork(self.currentNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.retrieveNetworkStatus = function(connecting) {
|
||||
//console.log("Settings:retrieveNetworkStatus");
|
||||
if (communicateWithWifibox) {
|
||||
$.ajax({
|
||||
url: self.wifiboxURL + "/network/status",
|
||||
type: "GET",
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:retrieveNetworkStatus response: ",response);
|
||||
if(response.status == "error") {
|
||||
|
||||
} else {
|
||||
var data = response.data;
|
||||
|
||||
if(typeof data.status === 'string') {
|
||||
data.status = parseInt(data.status);
|
||||
}
|
||||
//console.log(" data.status: ",data.status,data.statusMessage);
|
||||
|
||||
// Determine which network settings to show
|
||||
switch(data.status) {
|
||||
case SettingsWindow.API_NOT_CONNECTED:
|
||||
//console.log(" not connected & not a access point");
|
||||
self.apFieldSet.show();
|
||||
self.clientFieldSet.show();
|
||||
break;
|
||||
case SettingsWindow.API_CONNECTING_FAILED:
|
||||
case SettingsWindow.API_CONNECTING:
|
||||
case SettingsWindow.API_CONNECTED:
|
||||
//console.log(" client mode");
|
||||
self.form.find("#client").prop('checked',true);
|
||||
|
||||
self.apFieldSet.hide();
|
||||
self.clientFieldSet.show();
|
||||
|
||||
if(data.status == SettingsWindow.API_CONNECTED) {
|
||||
var networkSelector = self.form.find("#network");
|
||||
networkSelector.val(data.ssid);
|
||||
|
||||
self.currentNetwork = data.ssid;
|
||||
self.currentLocalIP = data.localip;
|
||||
self.selectNetwork(data.ssid);
|
||||
} else {
|
||||
self.currentLocalIP = ""
|
||||
}
|
||||
|
||||
break;
|
||||
case SettingsWindow.API_CREATING:
|
||||
case SettingsWindow.API_CREATED:
|
||||
//console.log(" access point mode");
|
||||
self.form.find("#ap").prop('checked',true);
|
||||
|
||||
self.apFieldSet.show();
|
||||
self.clientFieldSet.hide();
|
||||
|
||||
self.currentNetwork = undefined;
|
||||
self.selectNetwork(SettingsWindow.NOT_CONNECTED);
|
||||
var networkSelector = self.form.find("#network");
|
||||
networkSelector.val(SettingsWindow.NOT_CONNECTED);
|
||||
|
||||
if(data.ssid && data.status == SettingsWindow.API_CREATED) {
|
||||
self.currentAP = data.ssid;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// update status message
|
||||
switch(data.status) {
|
||||
case SettingsWindow.API_CONNECTING_FAILED:
|
||||
self.setClientModeState(SettingsWindow.CONNECTING_FAILED,data.statusMessage);
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_NOT_CONNECTED:
|
||||
self.setClientModeState(SettingsWindow.NOT_CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CONNECTING:
|
||||
self.setClientModeState(SettingsWindow.CONNECTING,"");
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CONNECTED:
|
||||
self.setClientModeState(SettingsWindow.CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.NO_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CREATING:
|
||||
self.setClientModeState(SettingsWindow.NOT_CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.CREATING_AP,"");
|
||||
break;
|
||||
case SettingsWindow.API_CREATED:
|
||||
self.setClientModeState(SettingsWindow.NOT_CONNECTED,"");
|
||||
self.setAPModeState(SettingsWindow.AP,"");
|
||||
break;
|
||||
}
|
||||
|
||||
// Keep checking for updates?
|
||||
if(connecting) {
|
||||
switch(data.status) {
|
||||
case SettingsWindow.API_CONNECTING:
|
||||
case SettingsWindow.API_CREATING:
|
||||
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
||||
self.retryRetrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(connecting) },self.retryRetrieveNetworkStatusDelayTime); // retry after delay
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:retrieveNetworkStatus: failed");
|
||||
clearTimeout(self.retryRetrieveNetworkStatusDelay);
|
||||
self.retryRetrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(connecting) },self.retryDelay); // retry after delay
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.networkSelectorChanged = function(e) {
|
||||
var selectedOption = $(this).find("option:selected");
|
||||
self.selectNetwork(selectedOption.val());
|
||||
}
|
||||
|
||||
this.selectNetwork = function(ssid) {
|
||||
console.log("select network: ",ssid);
|
||||
this.selectedNetwork = ssid;
|
||||
if(this.networks == undefined || ssid == SettingsWindow.NOT_CONNECTED) {
|
||||
this.hideWiFiPassword();
|
||||
} else {
|
||||
var network = this.networks[ssid];
|
||||
if(network.encryption == "none") {
|
||||
this.hideWiFiPassword();
|
||||
} else {
|
||||
this.showWiFiPassword();
|
||||
}
|
||||
this.form.find("#password").val("");
|
||||
}
|
||||
}
|
||||
this.showWiFiPassword = function() {
|
||||
this.form.find("#passwordLabel").show();
|
||||
this.form.find("#password").show();
|
||||
}
|
||||
this.hideWiFiPassword = function() {
|
||||
this.form.find("#passwordLabel").hide();
|
||||
this.form.find("#password").hide();
|
||||
}
|
||||
|
||||
this.setClientModeState = function(state,msg) {
|
||||
var field = this.form.find("#clientModeState");
|
||||
var btnConnect = self.form.find("#connectToNetwork");
|
||||
switch(state) {
|
||||
case SettingsWindow.NOT_CONNECTED:
|
||||
btnConnect.removeAttr("disabled");
|
||||
field.html("Not connected");
|
||||
break;
|
||||
case SettingsWindow.CONNECTED:
|
||||
btnConnect.removeAttr("disabled");
|
||||
|
||||
var fieldText = "Connected to: <b>"+this.currentNetwork+"</b>.";
|
||||
if(this.currentLocalIP != undefined && this.currentLocalIP != "") {
|
||||
var a = "<a href='http://"+this.currentLocalIP+"' target='_black'>"+this.currentLocalIP+"</a>";
|
||||
fieldText += " (IP: "+a+")";
|
||||
}
|
||||
field.html(fieldText);
|
||||
break;
|
||||
case SettingsWindow.CONNECTING:
|
||||
btnConnect.attr("disabled", true);
|
||||
field.html("Connecting... Reconnect by connecting your device to <b>"+this.selectedNetwork+"</b> and going to <a href='http://connect.doodle3d.com'>connect.doodle3d.com</a>");
|
||||
break;
|
||||
case SettingsWindow.CONNECTING_FAILED:
|
||||
btnConnect.removeAttr("disabled");
|
||||
field.html(msg);
|
||||
break;
|
||||
}
|
||||
this.clientModeState = state;
|
||||
}
|
||||
this.setAPModeState = function(state,msg) {
|
||||
var field = this.form.find("#apModeState");
|
||||
var btnCreate = this.form.find("#createAP");
|
||||
switch(state) {
|
||||
case SettingsWindow.NO_AP:
|
||||
btnCreate.removeAttr("disabled");
|
||||
field.html("Not currently a access point");
|
||||
break;
|
||||
case SettingsWindow.AP:
|
||||
btnCreate.removeAttr("disabled");
|
||||
field.html("Is access point: <b>"+this.currentAP+"</b>");
|
||||
break;
|
||||
case SettingsWindow.CREATING_AP:
|
||||
btnCreate.attr("disabled", true);
|
||||
field.html("Creating access point... Reconnect by connecting your device to <b>"+settings.substituted_ssid+"</b> and going to <a href='http://draw.doodle3d.com'>draw.doodle3d.com</a>");
|
||||
break;
|
||||
}
|
||||
this.apModeState = state;
|
||||
}
|
||||
|
||||
this.connectToNetwork = function() {
|
||||
console.log("connectToNetwork");
|
||||
if(self.selectedNetwork == undefined) return;
|
||||
var postData = {
|
||||
ssid:self.selectedNetwork,
|
||||
phrase:self.form.find("#password").val(),
|
||||
recreate:true
|
||||
}
|
||||
console.log(" postData: ",postData);
|
||||
if (communicateWithWifibox) {
|
||||
|
||||
// save network related settings and on complete, connect to network
|
||||
self.saveSettings(self.readForm(),function() {
|
||||
|
||||
$.ajax({
|
||||
url: self.wifiboxCGIBinURL + "/network/associate",
|
||||
type: "POST",
|
||||
data: postData,
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:connectToNetwork response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:connectToNetwork: timeout (normal behavior)");
|
||||
//clearTimeout(self.retrySaveSettingsDelay);
|
||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
});
|
||||
});
|
||||
}
|
||||
self.setClientModeState(SettingsWindow.CONNECTING,"");
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch
|
||||
clearTimeout(self.retrieveNetworkStatusDelay);
|
||||
self.retrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(true) },self.retrieveNetworkStatusDelayTime);
|
||||
}
|
||||
|
||||
this.createAP = function() {
|
||||
console.log("createAP");
|
||||
if (communicateWithWifibox) {
|
||||
|
||||
// save network related settings and on complete, create access point
|
||||
self.saveSettings(self.readForm(),function() {
|
||||
self.setAPModeState(SettingsWindow.CREATING_AP); // get latest substituted ssid
|
||||
$.ajax({
|
||||
url: self.wifiboxCGIBinURL + "/network/openap",
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
timeout: self.timeoutTime,
|
||||
success: function(response){
|
||||
console.log("Settings:createAP response: ",response);
|
||||
}
|
||||
}).fail(function() {
|
||||
console.log("Settings:createAP: timeout (normal behavior)");
|
||||
//clearTimeout(self.retrySaveSettingsDelay);
|
||||
//self.retrySaveSettingsDelay = setTimeout(function() { self.saveSettings() },self.retryDelay); // retry after delay
|
||||
});
|
||||
|
||||
self.setAPModeState(SettingsWindow.CREATING_AP,"");
|
||||
|
||||
// after switching wifi network or creating a access point we delay the status retrieval
|
||||
// because the webserver needs time to switch
|
||||
clearTimeout(self.retrieveNetworkStatusDelay);
|
||||
self.retrieveNetworkStatusDelay = setTimeout(function() { self.retrieveNetworkStatus(true) },self.retrieveNetworkStatusDelayTime);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*************************
|
||||
*
|
||||
*
|
||||
* FROM DOODLE3D.INI
|
||||
*
|
||||
*/
|
||||
//TODO: find all references to these variables, replace them and finally remove these.
|
||||
var objectHeight = 20;
|
||||
var layerHeight = .2;
|
||||
//var wallThickness = .5;
|
||||
//var hop = 0;
|
||||
//var speed = 70;
|
||||
//var travelSpeed = 200;
|
||||
var enableTraveling = true;
|
||||
//var filamentThickness = 2.89;
|
||||
var minScale = .3;
|
||||
var maxScale = 1;
|
||||
var shape = "%";
|
||||
var twists = 0;
|
||||
//var useSubLayers = true;
|
||||
//var debug = false; // debug moved to main.js
|
||||
var loglevel = 2;
|
||||
//var zOffset = 0;
|
||||
var serverport = 8888;
|
||||
var autoLoadImage = "hand.txt";
|
||||
var loadOffset = [0, 0]; // x en y ?
|
||||
var showWarmUp = true;
|
||||
var loopAlways = false;
|
||||
var firstLayerSlow = true;
|
||||
var useSubpathColors = false;
|
||||
var autoWarmUp = true;
|
||||
//var maxObjectHeight = 150;
|
||||
var maxScaleDifference = .1;
|
||||
var frameRate = 60;
|
||||
var quitOnEscape = true;
|
||||
var screenToMillimeterScale = .3; // 0.3
|
||||
//var targetTemperature = 220;
|
||||
//var simplifyiterations = 10;
|
||||
//var simplifyminNumPoints = 15;
|
||||
//var simplifyminDistance = 3;
|
||||
//var retractionspeed = 50;
|
||||
//var retractionminDistance = 5;
|
||||
//var retractionamount = 3;
|
||||
var sideis3D = true;
|
||||
var sidevisible = true;
|
||||
var sidebounds = [900, 210, 131, 390];
|
||||
var sideborder = [880, 169, 2, 471];
|
||||
var windowbounds = [0, 0, 800, 500];
|
||||
var windowcenter = true;
|
||||
var windowfullscreen = false;
|
||||
var autoWarmUpCommand = "M104 S230";
|
||||
//var checkTemperatureInterval = 3;
|
||||
var autoWarmUpDelay = 3;
|
138
www/js/Thermometer.js
Normal file
@ -0,0 +1,138 @@
|
||||
// TODO assess if this var is still necessary
|
||||
var $displayThermometer = $("#thermometerContainer");
|
||||
|
||||
|
||||
//TODO 2013-09-18 allow displaying temperatures HIGHER than the targTemp (it's now being capped at targTemp).
|
||||
function Thermometer() {
|
||||
this.currentTemperature = 0; // default val
|
||||
this.targetTemperature = 0; // default val
|
||||
|
||||
this.thermoOverlayImg = new Image();
|
||||
this.thermoOverlayImgSrc = "img/thermometer_fg_overlay.png"; // ../img/thermometer_fg_overlay.png
|
||||
|
||||
this.thermoWidth= 40;
|
||||
this.thermoHeight = 100;
|
||||
|
||||
this.$canvas;
|
||||
this.canvas;
|
||||
this.context;
|
||||
this.$container;
|
||||
|
||||
this.isInitted = false;
|
||||
|
||||
this.enabled = true;
|
||||
|
||||
this.thermoColors = [
|
||||
[50, 200, 244], // 'cold'
|
||||
[244, 190, 10], // 'warming up'
|
||||
[244, 50, 50] // 'ready / hot'
|
||||
];
|
||||
|
||||
this.init = function(targCanvas, targCanvasContainer) {
|
||||
console.log("Thermometer.init()");
|
||||
|
||||
this.$container = targCanvasContainer;
|
||||
|
||||
this.$canvas = targCanvas;
|
||||
this.canvas = this.$canvas[0];
|
||||
this.context = this.canvas.getContext('2d');
|
||||
|
||||
|
||||
var self = this;
|
||||
this.thermoOverlayImg.onload = function() {
|
||||
console.log("canvasThermoOverlay img loaded");
|
||||
self.isInitted = true;
|
||||
self.update(self.currentTemperature, self.targetTemperature);
|
||||
};
|
||||
this.thermoOverlayImg.src = this.thermoOverlayImgSrc;
|
||||
}
|
||||
|
||||
this.update = function(curr, targ) {
|
||||
// console.log("Thermometer.update(" + curr + "," + targ + ")");
|
||||
|
||||
if (this.isInitted) {
|
||||
if(!this.enabled) return;
|
||||
if (curr == undefined) curr = 0;
|
||||
if (targ== undefined) targ = 180; // prevent divide by zero
|
||||
|
||||
var progress = curr / targ;
|
||||
|
||||
progress = Math.min(progress, 1.0);
|
||||
progress = Math.max(progress, 0);
|
||||
|
||||
var h = this.thermoHeight; // 94 // px
|
||||
var paddingUnder = 15; // how far is beginpoint from bottom of thermometer
|
||||
var paddingAbove = 25; // how far is endpoint from top of thermometer
|
||||
var endPoint = h * .8;
|
||||
var p = Math.floor((h - paddingUnder - paddingAbove) * progress); // %
|
||||
// var tempHeight =
|
||||
|
||||
var currColor = this.thermoColors[0];
|
||||
if (progress > 0.98) {
|
||||
currColor = this.thermoColors[2];
|
||||
} else if (progress > 0.25) {
|
||||
currColor = this.thermoColors[1];
|
||||
}
|
||||
|
||||
// clear
|
||||
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||
this.context.font = "10pt sans-serif";
|
||||
|
||||
// draw the thermometer clipping path
|
||||
this.context.save();
|
||||
this.context.beginPath();
|
||||
this.context.arc(40, 80, 16, 0, 2 * Math.PI, false); // circle bottom of thermometer
|
||||
this.context.arc(40, 10, 4, 0, 2 * Math.PI, false); // circle at top of thermometer tube
|
||||
this.context.rect(36, 11, 8, 70); // thermometer tube
|
||||
this.context.fillStyle = '#fff';
|
||||
this.context.fill();
|
||||
this.context.clip();
|
||||
|
||||
// draw rectangle which represents temperature
|
||||
// rect will be clipped by the thermometer outlines
|
||||
this.context.beginPath();
|
||||
this.context.rect(20, h - paddingUnder - p, 60, p + paddingUnder);
|
||||
//console.log(" currColor: " + currColor);
|
||||
//todo Math.floor??
|
||||
this.context.fillStyle = "rgb(" + currColor[0] + "," + currColor[1] + "," + currColor[2] + ")";
|
||||
this.context.fill();
|
||||
this.context.restore();
|
||||
|
||||
// additional text labels
|
||||
this.context.save();
|
||||
this.context.beginPath();
|
||||
this.context.moveTo(32, paddingAbove);
|
||||
this.context.lineTo(52, paddingAbove);
|
||||
this.context.lineWidth = 2;
|
||||
this.context.strokeStyle = '#000';
|
||||
this.context.stroke();
|
||||
this.context.fillStyle = '#000';
|
||||
this.context.textAlign = "left";
|
||||
this.context.textBaseline = "middle";
|
||||
this.context.fillText(targ + "°", 55, paddingAbove);
|
||||
this.context.restore();
|
||||
|
||||
// the thermometer outline png
|
||||
this.context.drawImage(this.thermoOverlayImg, 20, 0);
|
||||
|
||||
// text
|
||||
this.context.fillStyle = '#000';
|
||||
this.context.textAlign="center";
|
||||
this.context.fillText(curr + "°", 40, h + paddingUnder);
|
||||
} else {
|
||||
console.log("Thermometer.setTemperature() -> thermometer not initialized!");
|
||||
}
|
||||
}
|
||||
this.show = function() {
|
||||
this.$container.addClass("thermometerAppear");
|
||||
// $("#progressbarCanvasContainer").addClass("thermometerAppear");
|
||||
// this.$container.show();
|
||||
this.enabled = true;
|
||||
}
|
||||
this.hide = function() {
|
||||
this.$container.removeClass("thermometerAppear");
|
||||
// $("#progressbarCanvasContainer").removeClass("thermometerAppear");
|
||||
// this.$container.hide();
|
||||
this.enabled = false;
|
||||
}
|
||||
}
|
386
www/js/buttonbehaviors.js
Normal file
@ -0,0 +1,386 @@
|
||||
var btnMoveUpInterval;
|
||||
var btnMoveDownInterval;
|
||||
|
||||
var btnTwistLeftInterval;
|
||||
var btnTwistRightInterval;
|
||||
var twistIncrement = Math.PI/1800;
|
||||
|
||||
var btnOopsInterval;
|
||||
|
||||
var btnNew, btnPrevious, btnNext;
|
||||
var btnOops, btnStop, btnClear;
|
||||
var btnMoveUp, btnMoveDown, btnTwistLeft, btnTwistRight;
|
||||
var btnInfo, btnSettings;
|
||||
//var btnDebug; // debug
|
||||
|
||||
var state;
|
||||
var prevState;
|
||||
var hasControl;
|
||||
|
||||
var gcodeGenerateDelayer;
|
||||
var gcodeGenerateDelay = 50;
|
||||
|
||||
function initButtonBehavior() {
|
||||
console.log("f:initButtonBehavior");
|
||||
|
||||
// btnClear= $(".btnClear");
|
||||
btnOops = $(".btnOops");
|
||||
btnMoveUp = $("#btnMoveUp");
|
||||
btnMoveDown = $("#btnMoveDown");
|
||||
btnTwistLeft = $("#btnTwistLeft");
|
||||
btnTwistRight = $("#btnTwistRight");
|
||||
btnInfo = $(".btnInfo");
|
||||
btnSettings = $(".btnSettings");
|
||||
btnNew = $(".btnNew");
|
||||
btnPrint= $(".btnPrint");
|
||||
btnStop = $(".btnStop");
|
||||
|
||||
btnPrevious = $(".btnPrevious");
|
||||
btnNext = $(".btnNext");
|
||||
|
||||
//debug
|
||||
//btnDebug = $(".debugBtn");
|
||||
|
||||
btnNew.on('touchstart mousedown', clearDoodle);
|
||||
btnPrint.on('touchstart mousedown', print);
|
||||
|
||||
// not using these at the moment
|
||||
$("#btnPrevious").css("opacity", "0.3");
|
||||
btnNext.css("opacity", "0.3");
|
||||
$("#btnSave").css("opacity", "0.3");
|
||||
btnInfo.css("opacity", "0.3");
|
||||
|
||||
// btnClear.click(function(e) {
|
||||
// e.preventDefault();
|
||||
// // console.log("clear");
|
||||
//
|
||||
// clearDoodle();
|
||||
// });
|
||||
|
||||
function startOops(e) {
|
||||
// console.log("btnOops mouse down");
|
||||
e.preventDefault();
|
||||
btnOopsInterval = setInterval( function() {
|
||||
oopsUndo();
|
||||
}, 1000/50);
|
||||
}
|
||||
function stopOops(e) {
|
||||
// console.log("btnOops mouse up");
|
||||
e.preventDefault();
|
||||
clearInterval(btnOopsInterval);
|
||||
}
|
||||
btnOops.on('touchstart', function(e) { startOops(e); });
|
||||
btnOops.on('touchend', function(e) { stopOops(e); });
|
||||
btnOops.mousedown(function(e) { startOops(e); });
|
||||
btnOops.mouseup(function(e) { stopOops(e); });
|
||||
|
||||
function startMoveUp(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnMoveUp mouse down");
|
||||
previewUp(true);
|
||||
clearInterval(btnMoveUpInterval);
|
||||
btnMoveUpInterval = setInterval( function() {
|
||||
previewUp(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopMoveUp(e) {
|
||||
e.preventDefault();
|
||||
console.log("btnMoveUp mouse up");
|
||||
clearInterval(btnMoveUpInterval);
|
||||
previewUp();
|
||||
}
|
||||
btnMoveUp.mousedown(function(e) { startMoveUp(e) });
|
||||
btnMoveUp.mouseup(function(e) { stopMoveUp(e) });
|
||||
btnMoveUp.on('touchstart', function(e) { startMoveUp(e) });
|
||||
btnMoveUp.on('touchend', function(e) { stopMoveUp(e) });
|
||||
|
||||
function startMoveDown(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnMoveDown mouse down");
|
||||
previewDown(true);
|
||||
clearInterval(btnMoveDownInterval);
|
||||
btnMoveDownInterval = setInterval( function() {
|
||||
previewDown(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopMoveDown(e) {
|
||||
e.preventDefault();
|
||||
console.log("btnMoveDown mouse up");
|
||||
clearInterval(btnMoveDownInterval);
|
||||
previewDown();
|
||||
}
|
||||
btnMoveDown.mousedown(function(e) { startMoveDown(e) });
|
||||
btnMoveDown.mouseup(function(e) { stopMoveDown(e) });
|
||||
btnMoveDown.on('touchstart', function(e) { startMoveDown(e) });
|
||||
btnMoveDown.on('touchend', function(e) { stopMoveDown(e) });
|
||||
|
||||
function startTwistLeft(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistLeft mouse down");
|
||||
previewTwistLeft(true);
|
||||
clearInterval(btnTwistLeftInterval);
|
||||
btnTwistLeftInterval = setInterval( function() {
|
||||
previewTwistLeft(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopTwistLeft(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistLeft mouse up");
|
||||
clearInterval(btnTwistLeftInterval);
|
||||
previewTwistLeft();
|
||||
}
|
||||
btnTwistLeft.mousedown(function(e) { startTwistLeft(e) });
|
||||
btnTwistLeft.mouseup(function(e) { stopTwistLeft(e) });
|
||||
btnTwistLeft.on('touchstart', function(e) { startTwistLeft(e) });
|
||||
btnTwistLeft.on('touchend', function(e) { stopTwistLeft(e) });
|
||||
|
||||
function startTwistRight(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistRight mouse down");
|
||||
previewTwistRight(true);
|
||||
clearInterval(btnTwistRightInterval);
|
||||
btnTwistRightInterval = setInterval( function() {
|
||||
previewTwistRight(true);
|
||||
}, 1000/30);
|
||||
}
|
||||
function stopTwistRight(e) {
|
||||
e.preventDefault();
|
||||
// console.log("btnTwistRight mouse up");
|
||||
clearInterval(btnTwistRightInterval);
|
||||
previewTwistRight();
|
||||
}
|
||||
btnTwistRight.mousedown(function(e) { startTwistRight(e) });
|
||||
btnTwistRight.mouseup(function(e) { stopTwistRight(e) });
|
||||
btnTwistRight.on('touchstart', function(e) { startTwistRight(e) });
|
||||
btnTwistRight.on('touchend', function(e) { stopTwistRight(e) });
|
||||
|
||||
/*function openSettings() {
|
||||
console.log("f:openSettings()");
|
||||
$("#contentOverlay").fadeIn(1000, function() {
|
||||
loadSettings();
|
||||
});
|
||||
}*/
|
||||
btnSettings.bind('touchstart mousedown',function () {
|
||||
//e.preventDefault();
|
||||
//console.log("btnSettings clicked");
|
||||
settingsWindow.showSettings();
|
||||
});
|
||||
// btnSettings.on('touchend', function(e) {
|
||||
// e.preventDefault();
|
||||
// console.log("btnSettings touchend");
|
||||
// });
|
||||
|
||||
btnInfo.mouseup(function(e) {
|
||||
e.preventDefault();
|
||||
console.log("btnInfo mouse up");
|
||||
});
|
||||
|
||||
// DEBUG
|
||||
/*
|
||||
// $(".agentInfo").css("display", "none");
|
||||
btnDebug.click(function(e) {
|
||||
console.log("debugClick");
|
||||
$(".agentInfo").toggleClass("agentInfoToggle");
|
||||
e.preventDefault();
|
||||
})
|
||||
//*/
|
||||
|
||||
//btnStop.on('touchstart mousedown',stopPrint);
|
||||
}
|
||||
function stopPrint() {
|
||||
console.log("f:stopPrint() >> sendPrintCommands = " + sendPrintCommands);
|
||||
//if (!confirm("Weet je zeker dat je huidige print wilt stoppen?")) return;
|
||||
if (sendPrintCommands) printer.stop();
|
||||
//setState(Printer.STOPPING_STATE,printer.hasControl);
|
||||
printer.overruleState(Printer.STOPPING_STATE);
|
||||
}
|
||||
|
||||
|
||||
function prevDoodle(e) {
|
||||
console.log("f:prevDoodle()");
|
||||
console.log("f:prevDoodle()");
|
||||
}
|
||||
function nextDoodle(e) {
|
||||
console.log("f:nextDoodle()");
|
||||
}
|
||||
|
||||
function print(e) {
|
||||
console.log("f:print() >> sendPrintCommands = " + sendPrintCommands);
|
||||
|
||||
//$(".btnPrint").css("display","none");
|
||||
|
||||
if (_points.length > 2) {
|
||||
|
||||
//setState(Printer.BUFFERING_STATE,printer.hasControl);
|
||||
printer.overruleState(Printer.BUFFERING_STATE);
|
||||
|
||||
btnStop.css("display","none"); // hack
|
||||
|
||||
// we put the gcode generation in a little delay
|
||||
// so that for example the print button is disabled right away
|
||||
clearTimeout(gcodeGenerateDelayer);
|
||||
gcodeGenerateDelayer = setTimeout(function() {
|
||||
|
||||
var gcode = generate_gcode();
|
||||
if (sendPrintCommands) {
|
||||
if(gcode.length > 0) {
|
||||
printer.print(gcode);
|
||||
} else {
|
||||
printer.overruleState(Printer.IDLE_STATE);
|
||||
printer.startStatusCheckInterval();
|
||||
}
|
||||
} else {
|
||||
console.log("sendPrintCommands is false: not sending print command to 3dprinter");
|
||||
}
|
||||
|
||||
if (debugMode) {
|
||||
$("#textdump").text("");
|
||||
$("#textdump").text(gcode.join("\n"));
|
||||
}
|
||||
|
||||
}, gcodeGenerateDelay);
|
||||
} else {
|
||||
console.log("f:print >> not enough points!");
|
||||
}
|
||||
|
||||
//alert("Je tekening zal nu geprint worden");
|
||||
//$(".btnPrint").css("display","block");
|
||||
|
||||
|
||||
// $.post("/doodle3d.of", { data:output }, function(data) {
|
||||
// btnPrint.disabled = false;
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
function clearMainView() {
|
||||
// console.log("f:clearMainView()");
|
||||
ctx.save();
|
||||
ctx.clearRect(0,0,canvas.width, canvas.height);
|
||||
ctx.restore();
|
||||
}
|
||||
function resetPreview() {
|
||||
// console.log("f:resetPreview()");
|
||||
|
||||
// clear preview canvas
|
||||
previewCtx.save();
|
||||
previewCtx.clearRect(0,0,canvas.width, canvas.height);
|
||||
previewCtx.restore();
|
||||
|
||||
// reset height and rotation to default values
|
||||
numLayers = previewDefaults.numLayers; // current number of preview layers
|
||||
rStep = previewDefaults.rotation; // Math.PI/180; //Math.PI/40; //
|
||||
}
|
||||
|
||||
function oopsUndo() {
|
||||
// console.log("f:oopsUndo()");
|
||||
_points.pop();
|
||||
redrawDoodle();
|
||||
redrawPreview();
|
||||
}
|
||||
function previewUp(redrawLess) {
|
||||
// console.log("f:previewUp()");
|
||||
if (numLayers < maxNumLayers) {
|
||||
numLayers++;
|
||||
}
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
function previewDown(redrawLess) {
|
||||
// console.log("f:previewDown()");
|
||||
if (numLayers > minNumLayers) {
|
||||
numLayers--;
|
||||
}
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
function previewTwistLeft(redrawLess) {
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
// console.log("f:previewTwistLeft()");
|
||||
if (rStep > -previewRotationLimit) rStep -= twistIncrement;
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
function previewTwistRight(redrawLess) {
|
||||
// console.log("f:previewTwistRight()");
|
||||
if (rStep < previewRotationLimit) rStep += twistIncrement;
|
||||
// redrawPreview(redrawLess);
|
||||
redrawRenderedPreview(redrawLess);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function update() {
|
||||
setState(printer.state,printer.hasControl);
|
||||
|
||||
thermometer.update(printer.temperature, printer.targetTemperature);
|
||||
progressbar.update(printer.currentLine, printer.totalLines);
|
||||
}
|
||||
|
||||
function setState(newState,newHasControl) {
|
||||
if(newState == state && newHasControl == hasControl) return;
|
||||
|
||||
prevState = state;
|
||||
|
||||
console.log("setState: ",prevState," > ",newState," ( ",newHasControl,")");
|
||||
setDebugText("State: "+newState);
|
||||
|
||||
// print button
|
||||
var printEnabled = (newState == Printer.IDLE_STATE && newHasControl);
|
||||
if(printEnabled) {
|
||||
btnPrint.removeClass("disabled"); // enable print button
|
||||
btnPrint.unbind('touchstart mousedown');
|
||||
btnPrint.bind('touchstart mousedown',print);
|
||||
} else {
|
||||
btnPrint.addClass("disabled"); // disable print button
|
||||
btnPrint.unbind('touchstart mousedown');
|
||||
}
|
||||
|
||||
// stop button
|
||||
var stopEnabled = ((newState == Printer.PRINTING_STATE || newState == Printer.BUFFERING_STATE) && newHasControl);
|
||||
if(stopEnabled) {
|
||||
btnStop.removeClass("disabled");
|
||||
btnStop.unbind('touchstart mousedown');
|
||||
btnStop.bind('touchstart mousedown',stopPrint);
|
||||
} else {
|
||||
btnStop.addClass("disabled");
|
||||
btnStop.unbind('touchstart mousedown');
|
||||
}
|
||||
|
||||
// thermometer
|
||||
switch(newState) {
|
||||
case Printer.IDLE_STATE:
|
||||
case Printer.BUFFERING_STATE:
|
||||
case Printer.PRINTING_STATE:
|
||||
case Printer.STOPPING_STATE:
|
||||
thermometer.show();
|
||||
break;
|
||||
default:
|
||||
thermometer.hide();
|
||||
break;
|
||||
}
|
||||
|
||||
// progress indicator
|
||||
switch(newState) {
|
||||
case Printer.PRINTING_STATE:
|
||||
progressbar.show();
|
||||
break;
|
||||
default:
|
||||
progressbar.hide();
|
||||
break;
|
||||
}
|
||||
|
||||
if(newState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||
message.set("Lost connection to WiFi box",Message.ERROR);
|
||||
} else if(prevState == Printer.WIFIBOX_DISCONNECTED_STATE) {
|
||||
message.set("Connected to WiFi box",Message.INFO,true);
|
||||
} else if(newState == Printer.DISCONNECTED_STATE) {
|
||||
message.set("Printer disconnected",Message.WARNING,true);
|
||||
} else if(prevState == Printer.DISCONNECTED_STATE && newState == Printer.IDLE_STATE ||
|
||||
prevState == Printer.UNKNOWN_STATE && newState == Printer.IDLE_STATE) {
|
||||
message.set("Printer connected",Message.INFO,true);
|
||||
}
|
||||
|
||||
state = newState;
|
||||
hasControl = newHasControl;
|
||||
}
|
484
www/js/canvasDrawing.js
Normal file
@ -0,0 +1,484 @@
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* VARS
|
||||
*
|
||||
* * * * * * * * * */
|
||||
var preview;
|
||||
var previewCtx;
|
||||
|
||||
var svgPathRegExp = /[LM]\d* \d*/ig;
|
||||
var svgPathParamsRegExp = /([LM])(\d*) (\d*)/;
|
||||
|
||||
var dragging = false;
|
||||
|
||||
var $canvas, canvas, ctx;
|
||||
var canvasWidth, canvasHeight;
|
||||
|
||||
var drawCanvas;
|
||||
var drawCanvasTopLeftCoords = [0, 0];
|
||||
|
||||
var doodleBounds = [-1, -1, -1, -1]; // left, top, right, bottom
|
||||
// var doodleScaleVals = [[0, 0], [1.0, 1.0]]; // [ [x, y], [scaleX, scaleY] ]
|
||||
var doodleTransform = [0, 0, 1.0, 1.0]; // [ x, y, scaleX, scaleY ]
|
||||
|
||||
var _points = [];
|
||||
|
||||
var prevCountingTime = 0;
|
||||
var movementCounter = 0;
|
||||
|
||||
var drawVariableLineWeight = false; // set to true to have the momentum of the mouse/touch movement result in larger/smaller strokes
|
||||
var lineweight = 2;
|
||||
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* INIT
|
||||
*
|
||||
* * * * * * * * * */
|
||||
function initDoodleDrawing() {
|
||||
console.log("f:initDoodleDrawing()");
|
||||
|
||||
$canvas = $("#mycanvas");
|
||||
canvas = $canvas[0];
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
canvasWidth = canvas.width;
|
||||
canvasHeight = canvas.height;
|
||||
|
||||
|
||||
//*
|
||||
//TODO make these jquery eventhandlers (works for all)
|
||||
if (!canvas.addEventListener) {
|
||||
canvas.attachEvent('onmousedown',onCanvasMouseDown);
|
||||
canvas.attachEvent('onmousemove',onCanvasMouseMove);
|
||||
canvas.attachEvent('onmouseup',onCanvasMouseUp);
|
||||
canvas.attachEvent('ontouchstart',onCanvasTouchDown);
|
||||
canvas.attachEvent('ontouchmove',onCanvasTouchMove);
|
||||
canvas.attachEvent('ontouchend',onCanvasTouchEnd);
|
||||
document.body.attachEvent('ontouchmove',prevent);
|
||||
} else {
|
||||
canvas.addEventListener('mousedown',onCanvasMouseDown,false);
|
||||
canvas.addEventListener('mousemove',onCanvasMouseMove,false);
|
||||
canvas.addEventListener('mouseup',onCanvasMouseUp,false);
|
||||
canvas.addEventListener('touchstart',onCanvasTouchDown,false);
|
||||
canvas.addEventListener('touchmove',onCanvasTouchMove,false);
|
||||
canvas.addEventListener('touchend',onCanvasTouchEnd,false);
|
||||
if (!debugMode) document.body.addEventListener('touchmove',prevent,false);
|
||||
}
|
||||
//*/
|
||||
|
||||
// drawCanvas = $(".drawareacontainer");
|
||||
drawCanvas = $("#mycanvasContainer"); // $("#drawAreaContainer")
|
||||
|
||||
console.log("drawCanvasTopLeftCoords: " + drawCanvasTopLeftCoords);
|
||||
// drawCanvasTopLeftCoords[0] = drawCanvas.css("left").match(/[0-9]/g).join("");
|
||||
// drawCanvasTopLeftCoords[1] = drawCanvas.css("top").match(/[0-9]/g).join("");
|
||||
drawCanvasTopLeftCoords[0] = drawCanvas.offset().left;
|
||||
drawCanvasTopLeftCoords[1] = drawCanvas.offset().top;
|
||||
// drawCanvasTopLeftCoords[0] = drawCanvas[0].offsetParent.offsetLeft;
|
||||
// drawCanvasTopLeftCoords[1] = drawCanvas[0].offsetParent.offsetTop;
|
||||
|
||||
console.log("f:initDoodleDrawing() >> canvasWidth: " + canvasWidth);
|
||||
console.log("f:initDoodleDrawing() >> canvasHeight: " + canvasHeight);
|
||||
|
||||
}
|
||||
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* CANVAS DRAWING FUNCTION
|
||||
*
|
||||
* * * * * * * * * */
|
||||
function draw(_x, _y, _width) {
|
||||
// console.log("f:draw() >> _width: " + _width);
|
||||
|
||||
if (prevX == 0 && prevY ==0) {
|
||||
prevX = _x;
|
||||
prevY = _y;
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(prevX, prevY);
|
||||
ctx.lineTo(_x, _y);
|
||||
|
||||
if (_width != undefined) {
|
||||
ctx.lineWidth = _width;
|
||||
} else {
|
||||
if (drawVariableLineWeight) {
|
||||
var dist = Math.sqrt(Math.pow((prevX - _x), 2) + Math.pow((prevY - _y), 2));
|
||||
if (dist < 10) {
|
||||
lineweight += .25;
|
||||
} else if (dist < 20) {
|
||||
lineweight += .5;
|
||||
} else if (dist < 30) {
|
||||
lineweight += .75;
|
||||
} else if (dist < 50) {
|
||||
lineweight += 1;
|
||||
} else if (dist < 80) {
|
||||
lineweight += 1.5;
|
||||
} else if (dist < 120) {
|
||||
lineweight += 2.25;
|
||||
} else if (dist < 170) {
|
||||
lineweight += 3.5;
|
||||
} else {
|
||||
lineweight += 2;
|
||||
}
|
||||
lineweight = Math.min(lineweight, 30);
|
||||
lineweight *= 0.90;
|
||||
lineweight = Math.max(lineweight, 1.0);
|
||||
} else {
|
||||
lineweight = 2;
|
||||
}
|
||||
|
||||
ctx.lineWidth = lineweight;
|
||||
}
|
||||
ctx.lineCap = 'round';
|
||||
ctx.stroke();
|
||||
|
||||
prevX = _x;
|
||||
prevY = _y;
|
||||
}
|
||||
|
||||
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* SUPPORTING FUNCTIONS
|
||||
*
|
||||
* * * * * * * * * */
|
||||
function clearDoodle() {
|
||||
console.log("f:clearDoodle");
|
||||
|
||||
_points = [];
|
||||
|
||||
prevX = 0;
|
||||
prevY = 0;
|
||||
|
||||
updatePrevX = -1;
|
||||
updatePrevY = -1;
|
||||
|
||||
doodleBounds = [-1, -1, -1, -1]; // left, top, right, bottom
|
||||
doodleTransform = [0, 0, 1.0, 1.0]; // [ x, y, scaleX, scaleY ]
|
||||
|
||||
dragging = false;
|
||||
|
||||
clearMainView();
|
||||
resetPreview();
|
||||
resetVerticalShapes();
|
||||
}
|
||||
|
||||
function redrawDoodle() {
|
||||
console.log("f:redrawDoodle()");
|
||||
|
||||
clearMainView();
|
||||
|
||||
prevX = 0;
|
||||
prevY = 0;
|
||||
|
||||
for (var i = 0; i < _points.length; i++) {
|
||||
// console.log(" drawing points " + _points[i]);
|
||||
if (_points[i][2] == true) {
|
||||
draw(_points[i][0], _points[i][1], 0.5);
|
||||
} else {
|
||||
draw(_points[i][0], _points[i][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function adjustBounds(x, y) {
|
||||
var newPointsOutsideOfCurrentBounds = false;
|
||||
console.log("f:adjustBounds("+x+","+y+")");
|
||||
|
||||
if (doodleBounds[0] == -1) {
|
||||
// if doodleBounds[0] is -1 then it isn't initted yet, so x and y are both the min and max vals
|
||||
|
||||
doodleBounds[0] = x;
|
||||
doodleBounds[1] = y;
|
||||
doodleBounds[2] = x;
|
||||
doodleBounds[3] = y;
|
||||
return;
|
||||
}
|
||||
|
||||
if (x < doodleBounds[0]) {
|
||||
doodleBounds[0] = x;
|
||||
newPointsOutsideOfCurrentBounds = true;
|
||||
}
|
||||
if (x > doodleBounds[2]) {
|
||||
doodleBounds[2] = x;
|
||||
newPointsOutsideOfCurrentBounds = true;
|
||||
}
|
||||
if (y < doodleBounds[1]) {
|
||||
doodleBounds[1] = y;
|
||||
newPointsOutsideOfCurrentBounds = true;
|
||||
}
|
||||
if (y > doodleBounds[3]) {
|
||||
doodleBounds[3] = y;
|
||||
newPointsOutsideOfCurrentBounds = true;
|
||||
}
|
||||
// doodleBounds[0] = Math.min(doodleBounds[0], x); // left
|
||||
// doodleBounds[2] = Math.max(doodleBounds[2], x); // right
|
||||
//
|
||||
// doodleBounds[1] = Math.min(doodleBounds[1], y); // top
|
||||
// doodleBounds[3] = Math.max(doodleBounds[3], y); // bottom
|
||||
|
||||
// draw the bounding rect (DEBUG)
|
||||
/*
|
||||
ctx.beginPath();
|
||||
ctx.rect(doodleBounds[0],doodleBounds[1], doodleBounds[2] - doodleBounds[0], doodleBounds[3] - doodleBounds[1]);
|
||||
ctx.lineWidth = .2;
|
||||
ctx.strokeStyle = "#333"
|
||||
ctx.stroke();
|
||||
ctx.closePath();
|
||||
//*/
|
||||
|
||||
// console.log(" new bounds: " + doodleBounds);
|
||||
|
||||
return newPointsOutsideOfCurrentBounds;
|
||||
}
|
||||
|
||||
// does what exactly?
|
||||
function adjustPreviewTransformation() {
|
||||
// console.log("f:adjustPreviewTransformation()");
|
||||
|
||||
// doodleTransform[0] = doodleBounds[0] - (doodleBounds[2] - doodleBounds[0]) / 2;
|
||||
// doodleTransform[1] = doodleBounds[1] - (doodleBounds[3] - doodleBounds[1]) / 2;
|
||||
// doodleTransform[0] = doodleBounds[0] - ((doodleBounds[2] - doodleBounds[0]) / 2);
|
||||
// doodleTransform[1] = doodleBounds[1] - ((doodleBounds[3] - doodleBounds[1]) / 2);
|
||||
doodleTransform[0] = doodleBounds[0];
|
||||
doodleTransform[1] = doodleBounds[1];
|
||||
|
||||
var sclX, sclY, finalScl;
|
||||
if (_points.length < 2) {
|
||||
// console.log(_points);
|
||||
sclX = 1.0;
|
||||
sclY = 1.0;
|
||||
finalScl = Math.min(sclX, sclY);
|
||||
} else {
|
||||
sclX = canvasWidth / (doodleBounds[2] - doodleBounds[0]);
|
||||
sclY = canvasHeight / (doodleBounds[3] - doodleBounds[1]);
|
||||
|
||||
// TODO this shouldn't be a matter if choosing the smallest but should probably involve maintaining aspect ratio??
|
||||
finalScl = Math.min(sclX, sclY);
|
||||
}
|
||||
|
||||
doodleTransform[2] = finalScl;
|
||||
doodleTransform[3] = finalScl;
|
||||
}
|
||||
|
||||
|
||||
/* * * * * * * * * *
|
||||
*
|
||||
* MOUSE/TOUCH EVENTHANDLERS
|
||||
*
|
||||
* * * * * * * * * */
|
||||
function onCanvasMouseDown(e) {
|
||||
// console.log("onmousedown >> e.offsetX,e.offsetY = " + e.offsetX+","+e.offsetY);
|
||||
// console.log("onmousedown >> e.layerX,e.layerY= " + e.layerX+","+e.layerY);
|
||||
// console.log("onmousedown >> e: " + e);
|
||||
// console.log(e);
|
||||
// console.log("f:onCanvasMouseDown()");
|
||||
dragging = true;
|
||||
|
||||
prevCountingTime = new Date().getTime();
|
||||
movementCounter = 0
|
||||
|
||||
// _points.push([e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, true]);
|
||||
// adjustBounds(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
|
||||
// adjustPreviewTransformation();
|
||||
// draw(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop, 0.5);
|
||||
|
||||
var x, y;
|
||||
if (e.offsetX != undefined) {
|
||||
x = e.offsetX;
|
||||
y = e.offsetY;
|
||||
} else {
|
||||
x = e.layerX;
|
||||
y = e.layerY;
|
||||
}
|
||||
// console.log(" x: " + x + ", y: " + y);
|
||||
|
||||
_points.push([x, y, true]);
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y, 0.5);
|
||||
}
|
||||
|
||||
var prevPoint = {x:-1, y:-1};
|
||||
function onCanvasMouseMove(e) {
|
||||
// console.log("f:onCanvasMouseMove()");
|
||||
if (!dragging) return;
|
||||
// console.log("onmousemove");
|
||||
|
||||
var x, y;
|
||||
if (e.offsetX != undefined) {
|
||||
x = e.offsetX;
|
||||
y = e.offsetY;
|
||||
} else {
|
||||
x = e.layerX;
|
||||
y = e.layerY;
|
||||
}
|
||||
|
||||
if (prevPoint.x != -1 || prevPoint.y != -1) {
|
||||
var dist = Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2));
|
||||
if (dist > 5) { // replace by setting: doodle3d.simplify.minDistance
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
prevPoint.y = y;
|
||||
}
|
||||
} else {
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
prevPoint.y = y;
|
||||
}
|
||||
|
||||
// DEBUG
|
||||
// $("#textdump").text("");
|
||||
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
|
||||
// $("#textdump").append("doodletransform:" + doodleTransform + "\n");
|
||||
|
||||
if (new Date().getTime() - prevRedrawTime > redrawInterval) {
|
||||
// redrawing the whole preview the first X points ensures that the doodleBounds is set well
|
||||
prevRedrawTime = new Date().getTime();
|
||||
if (_points.length < 50) {
|
||||
redrawPreview();
|
||||
} else {
|
||||
updatePreview(x, y, true);
|
||||
/*
|
||||
if (_points.length - prevUpdateFullPreview > prevUpdateFullPreviewInterval) {
|
||||
console.log("f:onTouchMove >> passed prevUpdateFullPreviewInterval, updating full preview");
|
||||
redrawPreview();
|
||||
prevUpdateFullPreview = _points.length;
|
||||
} else {
|
||||
updatePreview(x, y, true);
|
||||
}
|
||||
//*/
|
||||
// redrawPreview();
|
||||
}
|
||||
}
|
||||
}
|
||||
prevUpdateFullPreview = 0; // 0 is not a timeframe but refers to the _points array
|
||||
prevUpdateFullPreviewInterval = 25; // refers to number of points, not a timeframe
|
||||
|
||||
function onCanvasMouseUp(e) {
|
||||
// console.log("f:onCanvasMouseUp()");
|
||||
// console.log("onmouseup");
|
||||
dragging = false;
|
||||
console.log("doodleBounds: " + doodleBounds);
|
||||
console.log("doodleTransform: " + doodleTransform);
|
||||
// ctx.stroke();
|
||||
|
||||
console.log("_points.length :" + _points.length);
|
||||
// console.log(_points);
|
||||
|
||||
// DEBUG
|
||||
// $("#textdump").text("");
|
||||
// $("#textdump").append("doodlebounds:" + doodleBounds + "\n");
|
||||
// $("#textdump").append("doodletransform:" + doodleTransform + "\n");
|
||||
|
||||
// redrawPreview();
|
||||
renderToImageDataPreview();
|
||||
}
|
||||
|
||||
function onCanvasTouchDown(e) {
|
||||
e.preventDefault();
|
||||
console.log("f:onCanvasTouchDown >> e: " , e);
|
||||
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
||||
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
|
||||
var x = e.touches[0].pageX - drawCanvasTopLeftCoords[0];
|
||||
var y = e.touches[0].pageY - drawCanvasTopLeftCoords[1];
|
||||
// var x = e.touches[0].pageX;
|
||||
// var y = e.touches[0].pageY;
|
||||
// var x = e.touches[0].layerX;
|
||||
// var y = e.touches[0].layerY;
|
||||
|
||||
_points.push([x, y, true]);
|
||||
adjustBounds(x, y);
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y, .5);
|
||||
|
||||
movementCounter = 0;
|
||||
|
||||
prevRedrawTime = new Date().getTime();
|
||||
}
|
||||
|
||||
function onCanvasTouchMove(e) {
|
||||
e.preventDefault();
|
||||
// var x = e.touches[0].pageX - e.touches[0].target.offsetLeft;
|
||||
// var y = e.touches[0].pageY - e.touches[0].target.offsetTop;
|
||||
var x = e.touches[0].pageX - drawCanvasTopLeftCoords[0];
|
||||
var y = e.touches[0].pageY - drawCanvasTopLeftCoords[1];
|
||||
// var x = e.touches[0].layerX;
|
||||
// var y = e.touches[0].layerY;
|
||||
// var x = e.touches[0].layerX;
|
||||
// var y = e.touches[0].layerY;
|
||||
|
||||
console.log("f:onCanvasTouchMove >> x,y = "+x+","+y+" , e: " , e);
|
||||
|
||||
if (prevPoint.x != -1 || prevPoint.y != -1) {
|
||||
var dist = Math.sqrt(Math.pow((prevPoint.x - x), 2) + Math.pow((prevPoint.y - y), 2));
|
||||
if (dist > 5) {
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
prevPoint.y = y;
|
||||
}
|
||||
} else {
|
||||
_points.push([x, y, false]);
|
||||
adjustBounds(x, y)
|
||||
adjustPreviewTransformation();
|
||||
draw(x, y);
|
||||
prevPoint.x = x;
|
||||
prevPoint.y = y;
|
||||
}
|
||||
|
||||
// update counter -> this was for getting a handle on how often the Canvas fires a move-event
|
||||
/*
|
||||
movementCounter++;
|
||||
if (new Date().getTime() - prevCountingTime > 1000) {
|
||||
// console.log("number of moves in 1sec: " + movementCounter)
|
||||
prevCountingTime= new Date().getTime();
|
||||
$("#numtimes").text(movementCounter + " times");
|
||||
movementCounter = 0;
|
||||
}
|
||||
//*/
|
||||
|
||||
if (new Date().getTime() - prevRedrawTime > redrawInterval) {
|
||||
// redrawing the whole preview the first X points ensures that the doodleBounds is set well
|
||||
if (_points.length < 50) {
|
||||
redrawPreview();
|
||||
} else {
|
||||
updatePreview(x, y, true);
|
||||
/*
|
||||
if (_points.length - prevUpdateFullPreview > prevUpdateFullPreviewInterval) {
|
||||
console.log("f:onTouchMove >> passed prevUpdateFullPreviewInterval, updating full preview");
|
||||
redrawPreview();
|
||||
prevUpdateFullPreview = _points.length;
|
||||
} else {
|
||||
updatePreview(x, y, true);
|
||||
}
|
||||
//*/
|
||||
}
|
||||
prevRedrawTime = new Date().getTime();
|
||||
}
|
||||
}
|
||||
|
||||
function onCanvasTouchEnd(e) {
|
||||
console.log("f:onCanvasTouchEnd()");
|
||||
console.log("doodleBounds: " + doodleBounds);
|
||||
console.log("doodleTransform: " + doodleTransform);
|
||||
// ctx.stroke();
|
||||
|
||||
console.log("_points.length :" + _points.length);
|
||||
|
||||
// redrawPreview();
|
||||
renderToImageDataPreview();
|
||||
}
|
||||
|
||||
function prevent(e) {
|
||||
e.preventDefault();
|
||||
}
|
10
www/js/d3dServerInterfacing.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
function setTemperature(callback) {
|
||||
|
||||
if (callback != undefined) callback();
|
||||
|
||||
}
|
||||
function setTemperature(callback) {
|
||||
|
||||
if (callback != undefined) callback();
|
||||
|
||||
}
|
335
www/js/gcodeGenerating.js
Normal file
@ -0,0 +1,335 @@
|
||||
/*var gcodeStart = [];
|
||||
gcodeStart.push(";Generated with Doodle3D");
|
||||
gcodeStart.push("G21"); // metric values
|
||||
gcodeStart.push("G91"); // relative positioning
|
||||
gcodeStart.push("M107"); // start with the fan off
|
||||
gcodeStart.push("G28 X0 Y0"); // move X/Y to min endstops
|
||||
gcodeStart.push("G28 Z0"); // move Z to min endstops
|
||||
gcodeStart.push("G1 Z15 F9000"); // move the platform down 15mm
|
||||
gcodeStart.push("G92 E0"); // zero the extruded length
|
||||
gcodeStart.push("G1 F200 E10"); // extrude 10mm of feed stock
|
||||
gcodeStart.push("G92 E0"); // zero the extruded length again
|
||||
//gcodeStart.push("G92 X-100 Y-100 E0"); // zero the extruded length again and make center the start position
|
||||
gcodeStart.push("G1 F9000");
|
||||
gcodeStart.push("G90"); // absolute positioning
|
||||
gcodeStart.push("M117 Printing Doodle... "); // display message (20 characters to clear whole screen)
|
||||
|
||||
var gcodeEnd= [];
|
||||
gcodeEnd.push("M107"); // fan off
|
||||
gcodeEnd.push("G91"); // relative positioning
|
||||
gcodeEnd.push("G1 E-1 F300"); // retract the filament a bit before lifting the nozzle, to release some of the pressure
|
||||
gcodeEnd.push("G1 Z+0.5 E-5 X-20 Y-20 F9000"); // move Z up a bit and retract filament even more
|
||||
gcodeEnd.push("G28 X0 Y0"); // move X/Y to min endstops, so the head is out of the way
|
||||
gcodeEnd.push("M84"); // disable axes / steppers
|
||||
gcodeEnd.push("G90"); // absolute positioning
|
||||
gcodeEnd.push("M117 Done "); // display message (20 characters to clear whole screen)*/
|
||||
|
||||
|
||||
var MAX_POINTS_TO_PRINT = 400000; //80000; //40000;
|
||||
var gcode = [];
|
||||
|
||||
function generate_gcode() {
|
||||
console.log("f:generategcode()");
|
||||
|
||||
// TODO 2013-09-18 evaluate if this should stay here
|
||||
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
|
||||
var gCodeOffsetX = 110; // mm
|
||||
var gCodeOffsetY = 110; // mm
|
||||
|
||||
gcode = [];
|
||||
|
||||
console.log("settings: ",settings);
|
||||
var speed = settings["printer.speed"]
|
||||
var normalSpeed = speed;
|
||||
var bottomSpeed = speed*0.5;
|
||||
var travelSpeed = settings["printer.travelSpeed"]
|
||||
var filamentThickness = settings["printer.filamentThickness"];
|
||||
var wallThickness = settings["printer.wallThickness"];
|
||||
var screenToMillimeterScale = settings["printer.screenToMillimeterScale"];
|
||||
var layerHeight = settings["printer.layerHeight"];
|
||||
var maxObjectHeight = settings["printer.maxObjectHeight"];
|
||||
var temperature = settings["printer.temperature"];
|
||||
var useSubLayers = settings["printer.useSubLayers"];
|
||||
var enableTraveling = settings["printer.enableTraveling"];
|
||||
var retractionEnabled = settings["printer.retraction.enabled"];
|
||||
var retractionspeed = settings["printer.retraction.speed"];
|
||||
var retractionminDistance = settings["printer.retraction.minDistance"];
|
||||
var retractionamount = settings["printer.retraction.amount"];
|
||||
var preheatTemperature = settings["printer.heatup.temperature"];
|
||||
|
||||
var startGcode = settings["printer.startgcode"];
|
||||
startGcode = startGcode.replace("{printingTemp}",temperature);
|
||||
startGcode = startGcode.replace("{preheatTemp}",preheatTemperature);
|
||||
startGcode = startGcode.split("\n");
|
||||
|
||||
var endGcode = settings["printer.endgcode"];
|
||||
endGcode = endGcode.replace("{printingTemp}",temperature);
|
||||
endGcode = endGcode.replace("{preheatTemp}",preheatTemperature);
|
||||
endGcode = endGcode.split("\n");
|
||||
|
||||
/*
|
||||
console.log("f:generate_gcode >> EFFE CHECKEN:");
|
||||
console.log(" speed: " + speed);
|
||||
console.log(" travelSpeed: " + travelSpeed);
|
||||
console.log(" filamentThickness: " + filamentThickness);
|
||||
console.log(" wallThickness: " + wallThickness);
|
||||
console.log(" screenToMillimeterScale: " + screenToMillimeterScale);
|
||||
console.log(" layerHeight: " + layerHeight);
|
||||
console.log(" objectHeight: " + objectHeight);
|
||||
console.log(" maxObjectHeight: " + maxObjectHeight);
|
||||
console.log(" temperature: " + temperature);
|
||||
console.log(" maxObjectHeight: " + maxObjectHeight);
|
||||
console.log(" useSubLayers: " + useSubLayers);
|
||||
console.log(" enableTraveling: " + enableTraveling);
|
||||
console.log(" retractionspeed: " + retractionspeed);
|
||||
console.log(" retractionminDistance: " + retractionminDistance);
|
||||
console.log(" retractionamount: " + retractionamount);
|
||||
console.log("");
|
||||
//*/
|
||||
|
||||
// max amount of real world layers
|
||||
var layers = maxObjectHeight / layerHeight; //maxObjectHeight instead of objectHeight
|
||||
|
||||
// translate numLayers in preview to objectHeight in real world
|
||||
//objectHeight = Math.ceil(numLayers / 5); // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
|
||||
//objectHeight = numLayers; // in settings objectHeight = 20, in previewRendering_v01.js numLayers is 100, hence the / 5
|
||||
objectHeight = Math.round(numLayers/maxNumLayers*maxObjectHeight);
|
||||
|
||||
// translate preview rotation (per layer) to real world rotation
|
||||
var rStepGCode = rStep * maxNumLayers/layers; ///maxNumLayers*maxObjectHeight;
|
||||
// correct direction
|
||||
rStepGCode = -rStepGCode;
|
||||
|
||||
// todo hier een array van PATHS maken wat de losse paths zijn
|
||||
|
||||
// copy array without reference -> http://stackoverflow.com/questions/9885821/copying-of-an-array-of-objects-to-another-array-without-object-reference-in-java
|
||||
var points = JSON.parse(JSON.stringify(_points));
|
||||
|
||||
// console.log("f:generategcode() >> paths: " + paths.toString());
|
||||
// console.log("paths.toString(): " + paths.toString());
|
||||
// return;
|
||||
|
||||
//gcode.push("M104 S" + temperature); // set target temperature and do not wait for the extruder to reach it
|
||||
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
||||
|
||||
// add gcode begin commands
|
||||
gcode = gcode.concat(startGcode);
|
||||
|
||||
//gcode.push("M109 S" + temperature); // set target temperature and wait for the extruder to reach it
|
||||
|
||||
var layers = maxObjectHeight / layerHeight; //maxObjectHeight instead of objectHeight
|
||||
var extruder = 0.0;
|
||||
var prev = new Point(); prev.set(0, 0);
|
||||
|
||||
// replacement (and improvement) for ofxGetCenterofMass
|
||||
var centerOfDoodle = {
|
||||
x: doodleBounds[0] + (doodleBounds[2]- doodleBounds[0])/2,
|
||||
y: doodleBounds[1] + (doodleBounds[3] - doodleBounds[1])/2
|
||||
// x: doodleBounds[0],
|
||||
// y: doodleBounds[1]
|
||||
}
|
||||
|
||||
console.log("f:generategcode() >> layers: " + layers);
|
||||
if (layers == Infinity) return;
|
||||
|
||||
// check feasibility of design
|
||||
var pointsToPrint = points.length * layers*(objectHeight/maxObjectHeight)
|
||||
//console.log(" points.length: ",points.length);
|
||||
//console.log(" numLayers: ",(layers*(objectHeight/maxObjectHeight)));
|
||||
//console.log(" pointsToPrint: ",pointsToPrint);
|
||||
//console.log(" MAX_POINTS_TO_PRINT: ",MAX_POINTS_TO_PRINT);
|
||||
|
||||
if(pointsToPrint > MAX_POINTS_TO_PRINT) {
|
||||
alert("Sorry, your doodle to to complex and / or to high");
|
||||
console.log("WARNING: to many points to convert to gcode");
|
||||
return [];
|
||||
}
|
||||
|
||||
for (var layer = 0; layer < layers; layer++) {
|
||||
|
||||
var p = JSON.parse(JSON.stringify(points)); // [].concat(points);
|
||||
|
||||
if (p.length < 2) return;
|
||||
var even = (layer % 2 == 0);
|
||||
var progress = layer / layers;
|
||||
|
||||
// float layerScale = scaleFunction(float(layer)/layers); // scaleFactor van de layer -> lookup naar vfunc[] voor die scaleVals
|
||||
// var layerScale = 1.0;
|
||||
var layerScale = scaleFunction(progress);
|
||||
|
||||
// if begin point this row and end point last row are close enough, isLoop is true
|
||||
var isLoop = lineLength(points[0][0], points[0][1], points[points.length-1][0], points[points.length-1][1]) < 3;
|
||||
|
||||
// set center of doodle as middle (ie subtract to that)
|
||||
pointsTranslate(p, -centerOfDoodle.x, -centerOfDoodle.y);
|
||||
pointsScale(p, screenToMillimeterScale,-screenToMillimeterScale);
|
||||
pointsScale(p, layerScale, layerScale);
|
||||
|
||||
// sort-of in de buurt van (360/2.5)
|
||||
// // -> aight.. er zijn 750 lines vs 1000 in de d3d app. 135 = .75 * 180... dit kan je nog rechttrekken als je NET wat slimmer nadenkt :)
|
||||
// update: NEE, het is niet .75 * 180 want 135 was niet de beste value.
|
||||
//pointsRotate(p, rStep * progress * 139);
|
||||
pointsRotate(p, rStepGCode * layer);
|
||||
|
||||
if (layer == 0) {
|
||||
//gcode.push("M107"); //fan off
|
||||
if (firstLayerSlow) {
|
||||
//gcode.push("M220 S20"); //slow speed
|
||||
speed = bottomSpeed;
|
||||
//console.log("> speed: ",speed);
|
||||
}
|
||||
} else if (layer == 2) { ////////LET OP, pas bij layer 2 weer op normale snelheid ipv layer 1
|
||||
gcode.push("M106"); //fan on
|
||||
//gcode.push("M220 S100"); //normal speed
|
||||
speed = normalSpeed;
|
||||
//console.log("> speed: ",speed);
|
||||
}
|
||||
|
||||
var curLayerCommand = 0;
|
||||
var totalLayerCommands = p.length;
|
||||
var layerProgress = 0;
|
||||
|
||||
var paths = [];
|
||||
var pathCounter = -1;
|
||||
// var points = [];
|
||||
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
if (p[i][2] == true) {
|
||||
pathCounter++;
|
||||
paths.push([]);
|
||||
paths[pathCounter].push([p[i][0], p[i][1]]);
|
||||
} else {
|
||||
paths[pathCounter].push([p[i][0], p[i][1]]);
|
||||
}
|
||||
}
|
||||
// console.log("f:generategcode() >> paths.length: " + paths.length);
|
||||
|
||||
// loop over the subpaths (the separately drawn lines)
|
||||
for (var j = 0; j < paths.length; j++) { // TODO paths > subpaths
|
||||
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
|
||||
// vector<ofSubPath::Command> &commands = subpaths[even ? j : subpaths.size()-1-j].getCommands();
|
||||
var commands = paths[j]; //commands zijn alle points uit subpath j // TODO commands > subpathPoints
|
||||
|
||||
// loop over the coordinates of the subpath
|
||||
for (var i = 0; i < commands.length; i++) {
|
||||
var last = commands.length - 1;
|
||||
|
||||
// this line is probably for drawing efficiency, alternating going from 0->end and end->0 (i.e. to and fro)
|
||||
// ofPoint to = commands[(even || isLoop || loopAlways) ? i : last-i].to;
|
||||
var to = new Point(); to.set(commands[i][0], commands[i][1]);
|
||||
|
||||
// TODO 2013-09-18 evaluate if this should stay..
|
||||
// this was added when Rick mailed us wrt the Ultimaker delivery of Doodle3D
|
||||
to.x += gCodeOffsetX;
|
||||
to.y += gCodeOffsetY;
|
||||
|
||||
var sublayer = (layer == 0) ? 0.0 : layer + (useSubLayers ? (curLayerCommand/totalLayerCommands) : 0);
|
||||
var z = (sublayer + 1) * layerHeight; // 2013-09-06 removed zOffset (seemed to be useless)
|
||||
|
||||
var isTraveling = !isLoop && i==0;
|
||||
var doRetract = retractionEnabled && prev.distance(to) > retractionminDistance;
|
||||
|
||||
if (enableTraveling && isTraveling) {
|
||||
// console.log("enableTraveling && isTraveling >> doRetract: " + doRetract + ", retractionspeed: " + retractionspeed);
|
||||
if (doRetract) gcode.push("G0 E" + (extruder - retractionamount).toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); //retract
|
||||
gcode.push("G0 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (travelSpeed * 60).toFixed(3));
|
||||
if (doRetract) gcode.push("G0 E" + extruder.toFixed(3) + " F" + (retractionspeed * 60).toFixed(3)); // return to normal
|
||||
} else {
|
||||
// console.log(" else");
|
||||
//extruder += prev.distance(to) * wallThickness * layerHeight / filamentThickness;
|
||||
extruder += prev.distance(to) * wallThickness * layerHeight / (Math.pow((filamentThickness/2), 2) * Math.PI);
|
||||
gcode.push("G1 X" + to.x.toFixed(3) + " Y" + to.y.toFixed(3) + " Z" + z.toFixed(3) + " F" + (speed * 60).toFixed(3) + " E" + extruder.toFixed(3));
|
||||
}
|
||||
|
||||
curLayerCommand++;
|
||||
layerProgress = curLayerCommand/totalLayerCommands;
|
||||
prev = to;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((layer/layers) > (objectHeight/maxObjectHeight)) {
|
||||
console.log("f:generategcode() >> (layer/layers) > (objectHeight/maxObjectHeight) is true -> breaking at layer " + (layer + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add gcode end commands
|
||||
gcode = gcode.concat(endGcode);
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
function scaleFunction(percent) {
|
||||
var r = 1.0;
|
||||
|
||||
switch (VERTICALSHAPE) {
|
||||
case verticalShapes.NONE:
|
||||
r = 1.0;
|
||||
break;
|
||||
case verticalShapes.DIVERGING:
|
||||
r = .5 + (percent * .5);
|
||||
break;
|
||||
case verticalShapes.CONVERGING:
|
||||
r = 1.0 - (percent * .8);
|
||||
break;
|
||||
case verticalShapes.SINUS:
|
||||
r = (Math.cos(percent * Math.PI * 4) * .25) + .75;
|
||||
break;
|
||||
}
|
||||
|
||||
// return 1.0 - (percent *.8);
|
||||
return r;
|
||||
}
|
||||
|
||||
pointsTranslate = function(p, x, y) {
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
p[i][0] += x;
|
||||
p[i][1] += y;
|
||||
}
|
||||
}
|
||||
|
||||
pointsScale = function(p, sx, sy) {
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
p[i][0] *= sx;
|
||||
p[i][1] *= sy;
|
||||
}
|
||||
}
|
||||
|
||||
// rotates around point 0,0 (origin).
|
||||
// Not the prettiest kind of rotation solution but in our case we're assuming that the points have just been translated to origin
|
||||
pointsRotate = function(p, ang) {
|
||||
var _ang, dist;
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
dist = Math.sqrt(p[i][0] * p[i][0] + p[i][1] * p[i][1]);
|
||||
_ang = Math.atan2(p[i][1], p[i][0]);
|
||||
p[i][0] = Math.cos(_ang + ang) * dist;
|
||||
p[i][1] = Math.sin(_ang + ang) * dist;
|
||||
}
|
||||
}
|
||||
|
||||
//+ Jonas Raoni Soares Silva
|
||||
//@ http://jsfromhell.com/math/line-length [rev. #1]
|
||||
lineLength = function(x, y, x0, y0){
|
||||
return Math.sqrt((x -= x0) * x + (y -= y0) * y);
|
||||
};
|
||||
|
||||
var Point = function() {};
|
||||
Point.prototype = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
set: function(_x, _y) {
|
||||
this.x = _x;
|
||||
this.y = _y;
|
||||
},
|
||||
distance: function(p) {
|
||||
var d = -1;
|
||||
if (p instanceof Point) {
|
||||
d = Math.sqrt((p.x - this.x) * (p.x - this.x) + (p.y - this.y) * (p.y - this.y));
|
||||
}
|
||||
return d;
|
||||
},
|
||||
toString: function() {
|
||||
console.log("x:" + this.x + ", y:" + this.y);
|
||||
}
|
||||
}
|
140
www/js/init_layout.js
Normal file
@ -0,0 +1,140 @@
|
||||
// TODO refactor this stuff, there's much to wipe
|
||||
var drawAreaContainerMinHeight = 300;
|
||||
var drawAreaContainerMaxHeight = 450;
|
||||
|
||||
function doOnResize() {
|
||||
// console.log("doOnResize() >> " + new Date().getTime());
|
||||
// $(".container").css("height", window.innerHeight);
|
||||
|
||||
/* 2013-10-09 commented out -> no more need with new layouting
|
||||
$drawAreaContainer.css("marginLeft", -$drawAreaContainer.width()/2);
|
||||
$drawAreaContainer.css("marginTop", -$drawAreaContainer.height() *.45);
|
||||
// $drawAreaContainer.css("marginTop", -parseInt($drawAreaContainer.css("height")) * 0.45);
|
||||
//*/
|
||||
|
||||
// canvas.width = $drawAreaContainer.width() - preview.width; // canvas.clientWidth;
|
||||
// canvas.width = $("#mycanvasContainer").width();
|
||||
canvas.width = $canvas.width();
|
||||
canvas.height = $canvas.height(); // canvas.clientHeight;
|
||||
// canvas.height = $drawAreaContainer.height(); // canvas.clientHeight;
|
||||
|
||||
preview.width = $preview.width();
|
||||
preview.height = $drawAreaContainer.height();
|
||||
|
||||
canvasWidth = canvas.width;
|
||||
canvasHeight = canvas.height;
|
||||
|
||||
console.log(" preview.width: " + preview.width + ", $preview.width(): " + $preview.width());
|
||||
|
||||
calcPreviewCanvasProperties();
|
||||
|
||||
// layerOffsetY = preview.height - 1.75 * layerCY;
|
||||
// yStep = preview.height / 150;
|
||||
// preview.width = parseInt($preview.css("width"), 10);
|
||||
// preview.height = parseInt($preview.css("height"), 10);
|
||||
|
||||
// canvasWidth = canvas.width;
|
||||
// canvasHeight = canvas.height;
|
||||
|
||||
drawCanvasTopLeftCoords[0] = drawCanvas.offset().left;
|
||||
drawCanvasTopLeftCoords[1] = drawCanvas.offset().top;
|
||||
// drawCanvasTopLeftCoords[0] = drawCanvas[0].offsetParent.offsetLeft;
|
||||
// drawCanvasTopLeftCoords[1] = drawCanvas[0].offsetParent.offsetTop;
|
||||
|
||||
// preview.height = $("#previewContainer").height();
|
||||
// console.log("f:doOnResize() >> preview.height: " + preview.height);
|
||||
|
||||
redrawDoodle();
|
||||
redrawPreview();
|
||||
|
||||
return;
|
||||
|
||||
// doClientAndOrientationStuff() // <-- is this necessary in this method?
|
||||
|
||||
// console.log("f:doOnResize() >> $('#canvascontainer').innerHeight: " + window.innerHeight);
|
||||
if (window.innerHeight < 768) {
|
||||
// $('#drawAreaContainer').innerHeight(window.innerHeight - $("#drawAreaContainer").offset().top - 70);
|
||||
var newVal = window.innerHeight - $("#drawAreaContainer").offset().top - 100; // what's the 70 ??
|
||||
newVal = Math.max(newVal, drawAreaContainerMinHeight);
|
||||
newVal = Math.min(newVal, drawAreaContainerMaxHeight);
|
||||
|
||||
$('#drawAreaContainer').innerHeight(newVal);
|
||||
|
||||
// canvas drawing area
|
||||
$canvas.css("height", newVal);
|
||||
canvas.height = newVal;
|
||||
canvasWidth = canvas.width;
|
||||
canvasHeight = canvas.height;
|
||||
|
||||
// preview area
|
||||
$preview.css("height", newVal);
|
||||
preview.height = newVal;
|
||||
layerOffsetY = preview.height - 1.75 * layerCY;
|
||||
yStep = preview.height / 150;
|
||||
|
||||
redrawDoodle();
|
||||
redrawPreview();
|
||||
}
|
||||
}
|
||||
|
||||
function initLayouting() {
|
||||
console.log("f:initLayouting()");
|
||||
|
||||
// first set the css width/height and actual width/height of the drawing area
|
||||
<!--div drawAreaContainer 650,450-->
|
||||
<!--canvas mycanvas 500, 450-->
|
||||
<!--canvas preview 150, 450-->
|
||||
|
||||
// $doodleCanvas = $("#mycanvas");
|
||||
// doodleCanvas = $("#mycanvas")[0];
|
||||
// doodleCanvasContext = doodleCanvas.getContext('2d');
|
||||
|
||||
$drawAreaContainer = $(".drawareacontainer");
|
||||
/* 2013-10-09 commented out -> no more need with new layouting
|
||||
$drawAreaContainer.css("margin", 0);
|
||||
$drawAreaContainer.css("marginLeft", -$drawAreaContainer.width()/2);
|
||||
$drawAreaContainer.css("marginTop", -$drawAreaContainer.height() *.45);
|
||||
//*/
|
||||
|
||||
// console.log(" preview.width: " + preview.width + ", $preview.width(): " + $preview.width());
|
||||
// canvas.width = $drawAreaContainer.width() - preview.width; // canvas.clientWidth;
|
||||
// canvas.width = $("#mycanvasContainer").width();
|
||||
canvas.width = $canvas.width();
|
||||
canvas.height = $canvas.height(); // canvas.clientHeight;
|
||||
// canvas.height = $drawAreaContainer.height(); // canvas.clientHeight;
|
||||
|
||||
preview.width = $preview.width();
|
||||
preview.height = $drawAreaContainer.height();
|
||||
|
||||
canvasWidth = canvas.width;
|
||||
canvasHeight = canvas.height;
|
||||
|
||||
$drawAreaContainer.show();
|
||||
|
||||
// window.innerHeight
|
||||
console.log("window.innerHeight: " + window.innerHeight);
|
||||
console.log("window.innerWidth: " + window.innerWidth);
|
||||
console.log("$drawAreaContainer.innerHeight(): " + $drawAreaContainer.innerHeight());
|
||||
console.log("$drawAreaContainer.offset().top: " + $drawAreaContainer.offset().top);
|
||||
|
||||
|
||||
/* 2013-07-26 not doing this resizing stuff now, it's not working well yet
|
||||
if (window.innerHeight < 768) {
|
||||
$('#drawAreaContainer').innerHeight(window.innerHeight - $("#drawAreaContainer").offset().top - 70);
|
||||
}
|
||||
//*/
|
||||
|
||||
// timeout because it SEEMS to be beneficial for initting the layout
|
||||
// 2013-09-18 seems beneficial since when?
|
||||
setTimeout(_startOrientationAndChangeEventListening, 1000);
|
||||
}
|
||||
|
||||
function _startOrientationAndChangeEventListening() {
|
||||
// Initial execution if needed
|
||||
|
||||
$(window).on('resize', doOnResize);
|
||||
|
||||
// is it necessary to call these? Aren't they called by the above eventhandlers?
|
||||
// doClientAndOrientationStuff();
|
||||
doOnResize();
|
||||
}
|
35
www/js/libs/excanvas.compiled.js
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2006 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
document.createElement("canvas").getContext||(function(){var s=Math,j=s.round,F=s.sin,G=s.cos,V=s.abs,W=s.sqrt,k=10,v=k/2;function X(){return this.context_||(this.context_=new H(this))}var L=Array.prototype.slice;function Y(b,a){var c=L.call(arguments,2);return function(){return b.apply(a,c.concat(L.call(arguments)))}}var M={init:function(b){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var a=b||document;a.createElement("canvas");a.attachEvent("onreadystatechange",Y(this.init_,this,a))}},init_:function(b){b.namespaces.g_vml_||
|
||||
b.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML");b.namespaces.g_o_||b.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML");if(!b.styleSheets.ex_canvas_){var a=b.createStyleSheet();a.owningElement.id="ex_canvas_";a.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}g_vml_\\:*{behavior:url(#default#VML)}g_o_\\:*{behavior:url(#default#VML)}"}var c=b.getElementsByTagName("canvas"),d=0;for(;d<c.length;d++)this.initElement(c[d])},
|
||||
initElement:function(b){if(!b.getContext){b.getContext=X;b.innerHTML="";b.attachEvent("onpropertychange",Z);b.attachEvent("onresize",$);var a=b.attributes;if(a.width&&a.width.specified)b.style.width=a.width.nodeValue+"px";else b.width=b.clientWidth;if(a.height&&a.height.specified)b.style.height=a.height.nodeValue+"px";else b.height=b.clientHeight}return b}};function Z(b){var a=b.srcElement;switch(b.propertyName){case "width":a.style.width=a.attributes.width.nodeValue+"px";a.getContext().clearRect();
|
||||
break;case "height":a.style.height=a.attributes.height.nodeValue+"px";a.getContext().clearRect();break}}function $(b){var a=b.srcElement;if(a.firstChild){a.firstChild.style.width=a.clientWidth+"px";a.firstChild.style.height=a.clientHeight+"px"}}M.init();var N=[],B=0;for(;B<16;B++){var C=0;for(;C<16;C++)N[B*16+C]=B.toString(16)+C.toString(16)}function I(){return[[1,0,0],[0,1,0],[0,0,1]]}function y(b,a){var c=I(),d=0;for(;d<3;d++){var f=0;for(;f<3;f++){var h=0,g=0;for(;g<3;g++)h+=b[d][g]*a[g][f];c[d][f]=
|
||||
h}}return c}function O(b,a){a.fillStyle=b.fillStyle;a.lineCap=b.lineCap;a.lineJoin=b.lineJoin;a.lineWidth=b.lineWidth;a.miterLimit=b.miterLimit;a.shadowBlur=b.shadowBlur;a.shadowColor=b.shadowColor;a.shadowOffsetX=b.shadowOffsetX;a.shadowOffsetY=b.shadowOffsetY;a.strokeStyle=b.strokeStyle;a.globalAlpha=b.globalAlpha;a.arcScaleX_=b.arcScaleX_;a.arcScaleY_=b.arcScaleY_;a.lineScale_=b.lineScale_}function P(b){var a,c=1;b=String(b);if(b.substring(0,3)=="rgb"){var d=b.indexOf("(",3),f=b.indexOf(")",d+
|
||||
1),h=b.substring(d+1,f).split(",");a="#";var g=0;for(;g<3;g++)a+=N[Number(h[g])];if(h.length==4&&b.substr(3,1)=="a")c=h[3]}else a=b;return{color:a,alpha:c}}function aa(b){switch(b){case "butt":return"flat";case "round":return"round";case "square":default:return"square"}}function H(b){this.m_=I();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.fillStyle=this.strokeStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=k*1;this.globalAlpha=1;this.canvas=b;
|
||||
var a=b.ownerDocument.createElement("div");a.style.width=b.clientWidth+"px";a.style.height=b.clientHeight+"px";a.style.overflow="hidden";a.style.position="absolute";b.appendChild(a);this.element_=a;this.lineScale_=this.arcScaleY_=this.arcScaleX_=1}var i=H.prototype;i.clearRect=function(){this.element_.innerHTML=""};i.beginPath=function(){this.currentPath_=[]};i.moveTo=function(b,a){var c=this.getCoords_(b,a);this.currentPath_.push({type:"moveTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};
|
||||
i.lineTo=function(b,a){var c=this.getCoords_(b,a);this.currentPath_.push({type:"lineTo",x:c.x,y:c.y});this.currentX_=c.x;this.currentY_=c.y};i.bezierCurveTo=function(b,a,c,d,f,h){var g=this.getCoords_(f,h),l=this.getCoords_(b,a),e=this.getCoords_(c,d);Q(this,l,e,g)};function Q(b,a,c,d){b.currentPath_.push({type:"bezierCurveTo",cp1x:a.x,cp1y:a.y,cp2x:c.x,cp2y:c.y,x:d.x,y:d.y});b.currentX_=d.x;b.currentY_=d.y}i.quadraticCurveTo=function(b,a,c,d){var f=this.getCoords_(b,a),h=this.getCoords_(c,d),g={x:this.currentX_+
|
||||
0.6666666666666666*(f.x-this.currentX_),y:this.currentY_+0.6666666666666666*(f.y-this.currentY_)};Q(this,g,{x:g.x+(h.x-this.currentX_)/3,y:g.y+(h.y-this.currentY_)/3},h)};i.arc=function(b,a,c,d,f,h){c*=k;var g=h?"at":"wa",l=b+G(d)*c-v,e=a+F(d)*c-v,m=b+G(f)*c-v,r=a+F(f)*c-v;if(l==m&&!h)l+=0.125;var n=this.getCoords_(b,a),o=this.getCoords_(l,e),q=this.getCoords_(m,r);this.currentPath_.push({type:g,x:n.x,y:n.y,radius:c,xStart:o.x,yStart:o.y,xEnd:q.x,yEnd:q.y})};i.rect=function(b,a,c,d){this.moveTo(b,
|
||||
a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath()};i.strokeRect=function(b,a,c,d){var f=this.currentPath_;this.beginPath();this.moveTo(b,a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath();this.stroke();this.currentPath_=f};i.fillRect=function(b,a,c,d){var f=this.currentPath_;this.beginPath();this.moveTo(b,a);this.lineTo(b+c,a);this.lineTo(b+c,a+d);this.lineTo(b,a+d);this.closePath();this.fill();this.currentPath_=f};i.createLinearGradient=function(b,
|
||||
a,c,d){var f=new D("gradient");f.x0_=b;f.y0_=a;f.x1_=c;f.y1_=d;return f};i.createRadialGradient=function(b,a,c,d,f,h){var g=new D("gradientradial");g.x0_=b;g.y0_=a;g.r0_=c;g.x1_=d;g.y1_=f;g.r1_=h;return g};i.drawImage=function(b){var a,c,d,f,h,g,l,e,m=b.runtimeStyle.width,r=b.runtimeStyle.height;b.runtimeStyle.width="auto";b.runtimeStyle.height="auto";var n=b.width,o=b.height;b.runtimeStyle.width=m;b.runtimeStyle.height=r;if(arguments.length==3){a=arguments[1];c=arguments[2];h=g=0;l=d=n;e=f=o}else if(arguments.length==
|
||||
5){a=arguments[1];c=arguments[2];d=arguments[3];f=arguments[4];h=g=0;l=n;e=o}else if(arguments.length==9){h=arguments[1];g=arguments[2];l=arguments[3];e=arguments[4];a=arguments[5];c=arguments[6];d=arguments[7];f=arguments[8]}else throw Error("Invalid number of arguments");var q=this.getCoords_(a,c),t=[];t.push(" <g_vml_:group",' coordsize="',k*10,",",k*10,'"',' coordorigin="0,0"',' style="width:',10,"px;height:",10,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]){var E=[];E.push("M11=",
|
||||
this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",j(q.x/k),",","Dy=",j(q.y/k),"");var p=q,z=this.getCoords_(a+d,c),w=this.getCoords_(a,c+f),x=this.getCoords_(a+d,c+f);p.x=s.max(p.x,z.x,w.x,x.x);p.y=s.max(p.y,z.y,w.y,x.y);t.push("padding:0 ",j(p.x/k),"px ",j(p.y/k),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",E.join(""),", sizingmethod='clip');")}else t.push("top:",j(q.y/k),"px;left:",j(q.x/k),"px;");t.push(' ">','<g_vml_:image src="',b.src,
|
||||
'"',' style="width:',k*d,"px;"," height:",k*f,'px;"',' cropleft="',h/n,'"',' croptop="',g/o,'"',' cropright="',(n-h-l)/n,'"',' cropbottom="',(o-g-e)/o,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",t.join(""))};i.stroke=function(b){var a=[],c=P(b?this.fillStyle:this.strokeStyle),d=c.color,f=c.alpha*this.globalAlpha;a.push("<g_vml_:shape",' filled="',!!b,'"',' style="position:absolute;width:',10,"px;height:",10,'px;"',' coordorigin="0 0" coordsize="',k*10," ",k*10,'"',' stroked="',
|
||||
!b,'"',' path="');var h={x:null,y:null},g={x:null,y:null},l=0;for(;l<this.currentPath_.length;l++){var e=this.currentPath_[l];switch(e.type){case "moveTo":a.push(" m ",j(e.x),",",j(e.y));break;case "lineTo":a.push(" l ",j(e.x),",",j(e.y));break;case "close":a.push(" x ");e=null;break;case "bezierCurveTo":a.push(" c ",j(e.cp1x),",",j(e.cp1y),",",j(e.cp2x),",",j(e.cp2y),",",j(e.x),",",j(e.y));break;case "at":case "wa":a.push(" ",e.type," ",j(e.x-this.arcScaleX_*e.radius),",",j(e.y-this.arcScaleY_*e.radius),
|
||||
" ",j(e.x+this.arcScaleX_*e.radius),",",j(e.y+this.arcScaleY_*e.radius)," ",j(e.xStart),",",j(e.yStart)," ",j(e.xEnd),",",j(e.yEnd));break}if(e){if(h.x==null||e.x<h.x)h.x=e.x;if(g.x==null||e.x>g.x)g.x=e.x;if(h.y==null||e.y<h.y)h.y=e.y;if(g.y==null||e.y>g.y)g.y=e.y}}a.push(' ">');if(b)if(typeof this.fillStyle=="object"){var m=this.fillStyle,r=0,n={x:0,y:0},o=0,q=1;if(m.type_=="gradient"){var t=m.x1_/this.arcScaleX_,E=m.y1_/this.arcScaleY_,p=this.getCoords_(m.x0_/this.arcScaleX_,m.y0_/this.arcScaleY_),
|
||||
z=this.getCoords_(t,E);r=Math.atan2(z.x-p.x,z.y-p.y)*180/Math.PI;if(r<0)r+=360;if(r<1.0E-6)r=0}else{var p=this.getCoords_(m.x0_,m.y0_),w=g.x-h.x,x=g.y-h.y;n={x:(p.x-h.x)/w,y:(p.y-h.y)/x};w/=this.arcScaleX_*k;x/=this.arcScaleY_*k;var R=s.max(w,x);o=2*m.r0_/R;q=2*m.r1_/R-o}var u=m.colors_;u.sort(function(ba,ca){return ba.offset-ca.offset});var J=u.length,da=u[0].color,ea=u[J-1].color,fa=u[0].alpha*this.globalAlpha,ga=u[J-1].alpha*this.globalAlpha,S=[],l=0;for(;l<J;l++){var T=u[l];S.push(T.offset*q+
|
||||
o+" "+T.color)}a.push('<g_vml_:fill type="',m.type_,'"',' method="none" focus="100%"',' color="',da,'"',' color2="',ea,'"',' colors="',S.join(","),'"',' opacity="',ga,'"',' g_o_:opacity2="',fa,'"',' angle="',r,'"',' focusposition="',n.x,",",n.y,'" />')}else a.push('<g_vml_:fill color="',d,'" opacity="',f,'" />');else{var K=this.lineScale_*this.lineWidth;if(K<1)f*=K;a.push("<g_vml_:stroke",' opacity="',f,'"',' joinstyle="',this.lineJoin,'"',' miterlimit="',this.miterLimit,'"',' endcap="',aa(this.lineCap),
|
||||
'"',' weight="',K,'px"',' color="',d,'" />')}a.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",a.join(""))};i.fill=function(){this.stroke(true)};i.closePath=function(){this.currentPath_.push({type:"close"})};i.getCoords_=function(b,a){var c=this.m_;return{x:k*(b*c[0][0]+a*c[1][0]+c[2][0])-v,y:k*(b*c[0][1]+a*c[1][1]+c[2][1])-v}};i.save=function(){var b={};O(this,b);this.aStack_.push(b);this.mStack_.push(this.m_);this.m_=y(I(),this.m_)};i.restore=function(){O(this.aStack_.pop(),
|
||||
this);this.m_=this.mStack_.pop()};function ha(b){var a=0;for(;a<3;a++){var c=0;for(;c<2;c++)if(!isFinite(b[a][c])||isNaN(b[a][c]))return false}return true}function A(b,a,c){if(!!ha(a)){b.m_=a;if(c)b.lineScale_=W(V(a[0][0]*a[1][1]-a[0][1]*a[1][0]))}}i.translate=function(b,a){A(this,y([[1,0,0],[0,1,0],[b,a,1]],this.m_),false)};i.rotate=function(b){var a=G(b),c=F(b);A(this,y([[a,c,0],[-c,a,0],[0,0,1]],this.m_),false)};i.scale=function(b,a){this.arcScaleX_*=b;this.arcScaleY_*=a;A(this,y([[b,0,0],[0,a,
|
||||
0],[0,0,1]],this.m_),true)};i.transform=function(b,a,c,d,f,h){A(this,y([[b,a,0],[c,d,0],[f,h,1]],this.m_),true)};i.setTransform=function(b,a,c,d,f,h){A(this,[[b,a,0],[c,d,0],[f,h,1]],true)};i.clip=function(){};i.arcTo=function(){};i.createPattern=function(){return new U};function D(b){this.type_=b;this.r1_=this.y1_=this.x1_=this.r0_=this.y0_=this.x0_=0;this.colors_=[]}D.prototype.addColorStop=function(b,a){a=P(a);this.colors_.push({offset:b,color:a.color,alpha:a.alpha})};function U(){}G_vmlCanvasManager=
|
||||
M;CanvasRenderingContext2D=H;CanvasGradient=D;CanvasPattern=U})();
|
924
www/js/libs/excanvas.js
Normal file
@ -0,0 +1,924 @@
|
||||
// Copyright 2006 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
// Known Issues:
|
||||
//
|
||||
// * Patterns are not implemented.
|
||||
// * Radial gradient are not implemented. The VML version of these look very
|
||||
// different from the canvas one.
|
||||
// * Clipping paths are not implemented.
|
||||
// * Coordsize. The width and height attribute have higher priority than the
|
||||
// width and height style values which isn't correct.
|
||||
// * Painting mode isn't implemented.
|
||||
// * Canvas width/height should is using content-box by default. IE in
|
||||
// Quirks mode will draw the canvas using border-box. Either change your
|
||||
// doctype to HTML5
|
||||
// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
|
||||
// or use Box Sizing Behavior from WebFX
|
||||
// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
|
||||
// * Non uniform scaling does not correctly scale strokes.
|
||||
// * Optimize. There is always room for speed improvements.
|
||||
|
||||
// Only add this code if we do not already have a canvas implementation
|
||||
if (!document.createElement('canvas').getContext) {
|
||||
|
||||
(function() {
|
||||
|
||||
// alias some functions to make (compiled) code shorter
|
||||
var m = Math;
|
||||
var mr = m.round;
|
||||
var ms = m.sin;
|
||||
var mc = m.cos;
|
||||
var abs = m.abs;
|
||||
var sqrt = m.sqrt;
|
||||
|
||||
// this is used for sub pixel precision
|
||||
var Z = 10;
|
||||
var Z2 = Z / 2;
|
||||
|
||||
/**
|
||||
* This funtion is assigned to the <canvas> elements as element.getContext().
|
||||
* @this {HTMLElement}
|
||||
* @return {CanvasRenderingContext2D_}
|
||||
*/
|
||||
function getContext() {
|
||||
return this.context_ ||
|
||||
(this.context_ = new CanvasRenderingContext2D_(this));
|
||||
}
|
||||
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
/**
|
||||
* Binds a function to an object. The returned function will always use the
|
||||
* passed in {@code obj} as {@code this}.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* g = bind(f, obj, a, b)
|
||||
* g(c, d) // will do f.call(obj, a, b, c, d)
|
||||
*
|
||||
* @param {Function} f The function to bind the object to
|
||||
* @param {Object} obj The object that should act as this when the function
|
||||
* is called
|
||||
* @param {*} var_args Rest arguments that will be used as the initial
|
||||
* arguments when the function is called
|
||||
* @return {Function} A new function that has bound this
|
||||
*/
|
||||
function bind(f, obj, var_args) {
|
||||
var a = slice.call(arguments, 2);
|
||||
return function() {
|
||||
return f.apply(obj, a.concat(slice.call(arguments)));
|
||||
};
|
||||
}
|
||||
|
||||
var G_vmlCanvasManager_ = {
|
||||
init: function(opt_doc) {
|
||||
if (/MSIE/.test(navigator.userAgent) && !window.opera) {
|
||||
var doc = opt_doc || document;
|
||||
// Create a dummy element so that IE will allow canvas elements to be
|
||||
// recognized.
|
||||
doc.createElement('canvas');
|
||||
doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));
|
||||
}
|
||||
},
|
||||
|
||||
init_: function(doc) {
|
||||
// create xmlns
|
||||
if (!doc.namespaces['g_vml_']) {
|
||||
doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',
|
||||
'#default#VML');
|
||||
|
||||
}
|
||||
if (!doc.namespaces['g_o_']) {
|
||||
doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',
|
||||
'#default#VML');
|
||||
}
|
||||
|
||||
// Setup default CSS. Only add one style sheet per document
|
||||
if (!doc.styleSheets['ex_canvas_']) {
|
||||
var ss = doc.createStyleSheet();
|
||||
ss.owningElement.id = 'ex_canvas_';
|
||||
ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +
|
||||
// default size is 300x150 in Gecko and Opera
|
||||
'text-align:left;width:300px;height:150px}' +
|
||||
'g_vml_\\:*{behavior:url(#default#VML)}' +
|
||||
'g_o_\\:*{behavior:url(#default#VML)}';
|
||||
|
||||
}
|
||||
|
||||
// find all canvas elements
|
||||
var els = doc.getElementsByTagName('canvas');
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
this.initElement(els[i]);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Public initializes a canvas element so that it can be used as canvas
|
||||
* element from now on. This is called automatically before the page is
|
||||
* loaded but if you are creating elements using createElement you need to
|
||||
* make sure this is called on the element.
|
||||
* @param {HTMLElement} el The canvas element to initialize.
|
||||
* @return {HTMLElement} the element that was created.
|
||||
*/
|
||||
initElement: function(el) {
|
||||
if (!el.getContext) {
|
||||
|
||||
el.getContext = getContext;
|
||||
|
||||
// Remove fallback content. There is no way to hide text nodes so we
|
||||
// just remove all childNodes. We could hide all elements and remove
|
||||
// text nodes but who really cares about the fallback content.
|
||||
el.innerHTML = '';
|
||||
|
||||
// do not use inline function because that will leak memory
|
||||
el.attachEvent('onpropertychange', onPropertyChange);
|
||||
el.attachEvent('onresize', onResize);
|
||||
|
||||
var attrs = el.attributes;
|
||||
if (attrs.width && attrs.width.specified) {
|
||||
// TODO: use runtimeStyle and coordsize
|
||||
// el.getContext().setWidth_(attrs.width.nodeValue);
|
||||
el.style.width = attrs.width.nodeValue + 'px';
|
||||
} else {
|
||||
el.width = el.clientWidth;
|
||||
}
|
||||
if (attrs.height && attrs.height.specified) {
|
||||
// TODO: use runtimeStyle and coordsize
|
||||
// el.getContext().setHeight_(attrs.height.nodeValue);
|
||||
el.style.height = attrs.height.nodeValue + 'px';
|
||||
} else {
|
||||
el.height = el.clientHeight;
|
||||
}
|
||||
//el.getContext().setCoordsize_()
|
||||
}
|
||||
return el;
|
||||
}
|
||||
};
|
||||
|
||||
function onPropertyChange(e) {
|
||||
var el = e.srcElement;
|
||||
|
||||
switch (e.propertyName) {
|
||||
case 'width':
|
||||
el.style.width = el.attributes.width.nodeValue + 'px';
|
||||
el.getContext().clearRect();
|
||||
break;
|
||||
case 'height':
|
||||
el.style.height = el.attributes.height.nodeValue + 'px';
|
||||
el.getContext().clearRect();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function onResize(e) {
|
||||
var el = e.srcElement;
|
||||
if (el.firstChild) {
|
||||
el.firstChild.style.width = el.clientWidth + 'px';
|
||||
el.firstChild.style.height = el.clientHeight + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
G_vmlCanvasManager_.init();
|
||||
|
||||
// precompute "00" to "FF"
|
||||
var dec2hex = [];
|
||||
for (var i = 0; i < 16; i++) {
|
||||
for (var j = 0; j < 16; j++) {
|
||||
dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
|
||||
}
|
||||
}
|
||||
|
||||
function createMatrixIdentity() {
|
||||
return [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
}
|
||||
|
||||
function matrixMultiply(m1, m2) {
|
||||
var result = createMatrixIdentity();
|
||||
|
||||
for (var x = 0; x < 3; x++) {
|
||||
for (var y = 0; y < 3; y++) {
|
||||
var sum = 0;
|
||||
|
||||
for (var z = 0; z < 3; z++) {
|
||||
sum += m1[x][z] * m2[z][y];
|
||||
}
|
||||
|
||||
result[x][y] = sum;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function copyState(o1, o2) {
|
||||
o2.fillStyle = o1.fillStyle;
|
||||
o2.lineCap = o1.lineCap;
|
||||
o2.lineJoin = o1.lineJoin;
|
||||
o2.lineWidth = o1.lineWidth;
|
||||
o2.miterLimit = o1.miterLimit;
|
||||
o2.shadowBlur = o1.shadowBlur;
|
||||
o2.shadowColor = o1.shadowColor;
|
||||
o2.shadowOffsetX = o1.shadowOffsetX;
|
||||
o2.shadowOffsetY = o1.shadowOffsetY;
|
||||
o2.strokeStyle = o1.strokeStyle;
|
||||
o2.globalAlpha = o1.globalAlpha;
|
||||
o2.arcScaleX_ = o1.arcScaleX_;
|
||||
o2.arcScaleY_ = o1.arcScaleY_;
|
||||
o2.lineScale_ = o1.lineScale_;
|
||||
}
|
||||
|
||||
function processStyle(styleString) {
|
||||
var str, alpha = 1;
|
||||
|
||||
styleString = String(styleString);
|
||||
if (styleString.substring(0, 3) == 'rgb') {
|
||||
var start = styleString.indexOf('(', 3);
|
||||
var end = styleString.indexOf(')', start + 1);
|
||||
var guts = styleString.substring(start + 1, end).split(',');
|
||||
|
||||
str = '#';
|
||||
for (var i = 0; i < 3; i++) {
|
||||
str += dec2hex[Number(guts[i])];
|
||||
}
|
||||
|
||||
if (guts.length == 4 && styleString.substr(3, 1) == 'a') {
|
||||
alpha = guts[3];
|
||||
}
|
||||
} else {
|
||||
str = styleString;
|
||||
}
|
||||
|
||||
return {color: str, alpha: alpha};
|
||||
}
|
||||
|
||||
function processLineCap(lineCap) {
|
||||
switch (lineCap) {
|
||||
case 'butt':
|
||||
return 'flat';
|
||||
case 'round':
|
||||
return 'round';
|
||||
case 'square':
|
||||
default:
|
||||
return 'square';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class implements CanvasRenderingContext2D interface as described by
|
||||
* the WHATWG.
|
||||
* @param {HTMLElement} surfaceElement The element that the 2D context should
|
||||
* be associated with
|
||||
*/
|
||||
function CanvasRenderingContext2D_(surfaceElement) {
|
||||
this.m_ = createMatrixIdentity();
|
||||
|
||||
this.mStack_ = [];
|
||||
this.aStack_ = [];
|
||||
this.currentPath_ = [];
|
||||
|
||||
// Canvas context properties
|
||||
this.strokeStyle = '#000';
|
||||
this.fillStyle = '#000';
|
||||
|
||||
this.lineWidth = 1;
|
||||
this.lineJoin = 'miter';
|
||||
this.lineCap = 'butt';
|
||||
this.miterLimit = Z * 1;
|
||||
this.globalAlpha = 1;
|
||||
this.canvas = surfaceElement;
|
||||
|
||||
var el = surfaceElement.ownerDocument.createElement('div');
|
||||
el.style.width = surfaceElement.clientWidth + 'px';
|
||||
el.style.height = surfaceElement.clientHeight + 'px';
|
||||
el.style.overflow = 'hidden';
|
||||
el.style.position = 'absolute';
|
||||
surfaceElement.appendChild(el);
|
||||
|
||||
this.element_ = el;
|
||||
this.arcScaleX_ = 1;
|
||||
this.arcScaleY_ = 1;
|
||||
this.lineScale_ = 1;
|
||||
}
|
||||
|
||||
var contextPrototype = CanvasRenderingContext2D_.prototype;
|
||||
contextPrototype.clearRect = function() {
|
||||
this.element_.innerHTML = '';
|
||||
};
|
||||
|
||||
contextPrototype.beginPath = function() {
|
||||
// TODO: Branch current matrix so that save/restore has no effect
|
||||
// as per safari docs.
|
||||
this.currentPath_ = [];
|
||||
};
|
||||
|
||||
contextPrototype.moveTo = function(aX, aY) {
|
||||
var p = this.getCoords_(aX, aY);
|
||||
this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});
|
||||
this.currentX_ = p.x;
|
||||
this.currentY_ = p.y;
|
||||
};
|
||||
|
||||
contextPrototype.lineTo = function(aX, aY) {
|
||||
var p = this.getCoords_(aX, aY);
|
||||
this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});
|
||||
|
||||
this.currentX_ = p.x;
|
||||
this.currentY_ = p.y;
|
||||
};
|
||||
|
||||
contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
|
||||
aCP2x, aCP2y,
|
||||
aX, aY) {
|
||||
var p = this.getCoords_(aX, aY);
|
||||
var cp1 = this.getCoords_(aCP1x, aCP1y);
|
||||
var cp2 = this.getCoords_(aCP2x, aCP2y);
|
||||
bezierCurveTo(this, cp1, cp2, p);
|
||||
};
|
||||
|
||||
// Helper function that takes the already fixed cordinates.
|
||||
function bezierCurveTo(self, cp1, cp2, p) {
|
||||
self.currentPath_.push({
|
||||
type: 'bezierCurveTo',
|
||||
cp1x: cp1.x,
|
||||
cp1y: cp1.y,
|
||||
cp2x: cp2.x,
|
||||
cp2y: cp2.y,
|
||||
x: p.x,
|
||||
y: p.y
|
||||
});
|
||||
self.currentX_ = p.x;
|
||||
self.currentY_ = p.y;
|
||||
}
|
||||
|
||||
contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
|
||||
// the following is lifted almost directly from
|
||||
// http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
|
||||
|
||||
var cp = this.getCoords_(aCPx, aCPy);
|
||||
var p = this.getCoords_(aX, aY);
|
||||
|
||||
var cp1 = {
|
||||
x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),
|
||||
y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)
|
||||
};
|
||||
var cp2 = {
|
||||
x: cp1.x + (p.x - this.currentX_) / 3.0,
|
||||
y: cp1.y + (p.y - this.currentY_) / 3.0
|
||||
};
|
||||
|
||||
bezierCurveTo(this, cp1, cp2, p);
|
||||
};
|
||||
|
||||
contextPrototype.arc = function(aX, aY, aRadius,
|
||||
aStartAngle, aEndAngle, aClockwise) {
|
||||
aRadius *= Z;
|
||||
var arcType = aClockwise ? 'at' : 'wa';
|
||||
|
||||
var xStart = aX + mc(aStartAngle) * aRadius - Z2;
|
||||
var yStart = aY + ms(aStartAngle) * aRadius - Z2;
|
||||
|
||||
var xEnd = aX + mc(aEndAngle) * aRadius - Z2;
|
||||
var yEnd = aY + ms(aEndAngle) * aRadius - Z2;
|
||||
|
||||
// IE won't render arches drawn counter clockwise if xStart == xEnd.
|
||||
if (xStart == xEnd && !aClockwise) {
|
||||
xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
|
||||
// that can be represented in binary
|
||||
}
|
||||
|
||||
var p = this.getCoords_(aX, aY);
|
||||
var pStart = this.getCoords_(xStart, yStart);
|
||||
var pEnd = this.getCoords_(xEnd, yEnd);
|
||||
|
||||
this.currentPath_.push({type: arcType,
|
||||
x: p.x,
|
||||
y: p.y,
|
||||
radius: aRadius,
|
||||
xStart: pStart.x,
|
||||
yStart: pStart.y,
|
||||
xEnd: pEnd.x,
|
||||
yEnd: pEnd.y});
|
||||
|
||||
};
|
||||
|
||||
contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
};
|
||||
|
||||
contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
|
||||
var oldPath = this.currentPath_;
|
||||
this.beginPath();
|
||||
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
this.stroke();
|
||||
|
||||
this.currentPath_ = oldPath;
|
||||
};
|
||||
|
||||
contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
|
||||
var oldPath = this.currentPath_;
|
||||
this.beginPath();
|
||||
|
||||
this.moveTo(aX, aY);
|
||||
this.lineTo(aX + aWidth, aY);
|
||||
this.lineTo(aX + aWidth, aY + aHeight);
|
||||
this.lineTo(aX, aY + aHeight);
|
||||
this.closePath();
|
||||
this.fill();
|
||||
|
||||
this.currentPath_ = oldPath;
|
||||
};
|
||||
|
||||
contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
|
||||
var gradient = new CanvasGradient_('gradient');
|
||||
gradient.x0_ = aX0;
|
||||
gradient.y0_ = aY0;
|
||||
gradient.x1_ = aX1;
|
||||
gradient.y1_ = aY1;
|
||||
return gradient;
|
||||
};
|
||||
|
||||
contextPrototype.createRadialGradient = function(aX0, aY0, aR0,
|
||||
aX1, aY1, aR1) {
|
||||
var gradient = new CanvasGradient_('gradientradial');
|
||||
gradient.x0_ = aX0;
|
||||
gradient.y0_ = aY0;
|
||||
gradient.r0_ = aR0;
|
||||
gradient.x1_ = aX1;
|
||||
gradient.y1_ = aY1;
|
||||
gradient.r1_ = aR1;
|
||||
return gradient;
|
||||
};
|
||||
|
||||
contextPrototype.drawImage = function(image, var_args) {
|
||||
var dx, dy, dw, dh, sx, sy, sw, sh;
|
||||
|
||||
// to find the original width we overide the width and height
|
||||
var oldRuntimeWidth = image.runtimeStyle.width;
|
||||
var oldRuntimeHeight = image.runtimeStyle.height;
|
||||
image.runtimeStyle.width = 'auto';
|
||||
image.runtimeStyle.height = 'auto';
|
||||
|
||||
// get the original size
|
||||
var w = image.width;
|
||||
var h = image.height;
|
||||
|
||||
// and remove overides
|
||||
image.runtimeStyle.width = oldRuntimeWidth;
|
||||
image.runtimeStyle.height = oldRuntimeHeight;
|
||||
|
||||
if (arguments.length == 3) {
|
||||
dx = arguments[1];
|
||||
dy = arguments[2];
|
||||
sx = sy = 0;
|
||||
sw = dw = w;
|
||||
sh = dh = h;
|
||||
} else if (arguments.length == 5) {
|
||||
dx = arguments[1];
|
||||
dy = arguments[2];
|
||||
dw = arguments[3];
|
||||
dh = arguments[4];
|
||||
sx = sy = 0;
|
||||
sw = w;
|
||||
sh = h;
|
||||
} else if (arguments.length == 9) {
|
||||
sx = arguments[1];
|
||||
sy = arguments[2];
|
||||
sw = arguments[3];
|
||||
sh = arguments[4];
|
||||
dx = arguments[5];
|
||||
dy = arguments[6];
|
||||
dw = arguments[7];
|
||||
dh = arguments[8];
|
||||
} else {
|
||||
throw Error('Invalid number of arguments');
|
||||
}
|
||||
|
||||
var d = this.getCoords_(dx, dy);
|
||||
|
||||
var w2 = sw / 2;
|
||||
var h2 = sh / 2;
|
||||
|
||||
var vmlStr = [];
|
||||
|
||||
var W = 10;
|
||||
var H = 10;
|
||||
|
||||
// For some reason that I've now forgotten, using divs didn't work
|
||||
vmlStr.push(' <g_vml_:group',
|
||||
' coordsize="', Z * W, ',', Z * H, '"',
|
||||
' coordorigin="0,0"' ,
|
||||
' style="width:', W, 'px;height:', H, 'px;position:absolute;');
|
||||
|
||||
// If filters are necessary (rotation exists), create them
|
||||
// filters are bog-slow, so only create them if abbsolutely necessary
|
||||
// The following check doesn't account for skews (which don't exist
|
||||
// in the canvas spec (yet) anyway.
|
||||
|
||||
if (this.m_[0][0] != 1 || this.m_[0][1]) {
|
||||
var filter = [];
|
||||
|
||||
// Note the 12/21 reversal
|
||||
filter.push('M11=', this.m_[0][0], ',',
|
||||
'M12=', this.m_[1][0], ',',
|
||||
'M21=', this.m_[0][1], ',',
|
||||
'M22=', this.m_[1][1], ',',
|
||||
'Dx=', mr(d.x / Z), ',',
|
||||
'Dy=', mr(d.y / Z), '');
|
||||
|
||||
// Bounding box calculation (need to minimize displayed area so that
|
||||
// filters don't waste time on unused pixels.
|
||||
var max = d;
|
||||
var c2 = this.getCoords_(dx + dw, dy);
|
||||
var c3 = this.getCoords_(dx, dy + dh);
|
||||
var c4 = this.getCoords_(dx + dw, dy + dh);
|
||||
|
||||
max.x = m.max(max.x, c2.x, c3.x, c4.x);
|
||||
max.y = m.max(max.y, c2.y, c3.y, c4.y);
|
||||
|
||||
vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),
|
||||
'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',
|
||||
filter.join(''), ", sizingmethod='clip');")
|
||||
} else {
|
||||
vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');
|
||||
}
|
||||
|
||||
vmlStr.push(' ">' ,
|
||||
'<g_vml_:image src="', image.src, '"',
|
||||
' style="width:', Z * dw, 'px;',
|
||||
' height:', Z * dh, 'px;"',
|
||||
' cropleft="', sx / w, '"',
|
||||
' croptop="', sy / h, '"',
|
||||
' cropright="', (w - sx - sw) / w, '"',
|
||||
' cropbottom="', (h - sy - sh) / h, '"',
|
||||
' />',
|
||||
'</g_vml_:group>');
|
||||
|
||||
this.element_.insertAdjacentHTML('BeforeEnd',
|
||||
vmlStr.join(''));
|
||||
};
|
||||
|
||||
contextPrototype.stroke = function(aFill) {
|
||||
var lineStr = [];
|
||||
var lineOpen = false;
|
||||
var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
|
||||
var color = a.color;
|
||||
var opacity = a.alpha * this.globalAlpha;
|
||||
|
||||
var W = 10;
|
||||
var H = 10;
|
||||
|
||||
lineStr.push('<g_vml_:shape',
|
||||
' filled="', !!aFill, '"',
|
||||
' style="position:absolute;width:', W, 'px;height:', H, 'px;"',
|
||||
' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
|
||||
' stroked="', !aFill, '"',
|
||||
' path="');
|
||||
|
||||
var newSeq = false;
|
||||
var min = {x: null, y: null};
|
||||
var max = {x: null, y: null};
|
||||
|
||||
for (var i = 0; i < this.currentPath_.length; i++) {
|
||||
var p = this.currentPath_[i];
|
||||
var c;
|
||||
|
||||
switch (p.type) {
|
||||
case 'moveTo':
|
||||
c = p;
|
||||
lineStr.push(' m ', mr(p.x), ',', mr(p.y));
|
||||
break;
|
||||
case 'lineTo':
|
||||
lineStr.push(' l ', mr(p.x), ',', mr(p.y));
|
||||
break;
|
||||
case 'close':
|
||||
lineStr.push(' x ');
|
||||
p = null;
|
||||
break;
|
||||
case 'bezierCurveTo':
|
||||
lineStr.push(' c ',
|
||||
mr(p.cp1x), ',', mr(p.cp1y), ',',
|
||||
mr(p.cp2x), ',', mr(p.cp2y), ',',
|
||||
mr(p.x), ',', mr(p.y));
|
||||
break;
|
||||
case 'at':
|
||||
case 'wa':
|
||||
lineStr.push(' ', p.type, ' ',
|
||||
mr(p.x - this.arcScaleX_ * p.radius), ',',
|
||||
mr(p.y - this.arcScaleY_ * p.radius), ' ',
|
||||
mr(p.x + this.arcScaleX_ * p.radius), ',',
|
||||
mr(p.y + this.arcScaleY_ * p.radius), ' ',
|
||||
mr(p.xStart), ',', mr(p.yStart), ' ',
|
||||
mr(p.xEnd), ',', mr(p.yEnd));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Following is broken for curves due to
|
||||
// move to proper paths.
|
||||
|
||||
// Figure out dimensions so we can do gradient fills
|
||||
// properly
|
||||
if (p) {
|
||||
if (min.x == null || p.x < min.x) {
|
||||
min.x = p.x;
|
||||
}
|
||||
if (max.x == null || p.x > max.x) {
|
||||
max.x = p.x;
|
||||
}
|
||||
if (min.y == null || p.y < min.y) {
|
||||
min.y = p.y;
|
||||
}
|
||||
if (max.y == null || p.y > max.y) {
|
||||
max.y = p.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
lineStr.push(' ">');
|
||||
|
||||
if (!aFill) {
|
||||
var lineWidth = this.lineScale_ * this.lineWidth;
|
||||
|
||||
// VML cannot correctly render a line if the width is less than 1px.
|
||||
// In that case, we dilute the color to make the line look thinner.
|
||||
if (lineWidth < 1) {
|
||||
opacity *= lineWidth;
|
||||
}
|
||||
|
||||
lineStr.push(
|
||||
'<g_vml_:stroke',
|
||||
' opacity="', opacity, '"',
|
||||
' joinstyle="', this.lineJoin, '"',
|
||||
' miterlimit="', this.miterLimit, '"',
|
||||
' endcap="', processLineCap(this.lineCap), '"',
|
||||
' weight="', lineWidth, 'px"',
|
||||
' color="', color, '" />'
|
||||
);
|
||||
} else if (typeof this.fillStyle == 'object') {
|
||||
var fillStyle = this.fillStyle;
|
||||
var angle = 0;
|
||||
var focus = {x: 0, y: 0};
|
||||
|
||||
// additional offset
|
||||
var shift = 0;
|
||||
// scale factor for offset
|
||||
var expansion = 1;
|
||||
|
||||
if (fillStyle.type_ == 'gradient') {
|
||||
var x0 = fillStyle.x0_ / this.arcScaleX_;
|
||||
var y0 = fillStyle.y0_ / this.arcScaleY_;
|
||||
var x1 = fillStyle.x1_ / this.arcScaleX_;
|
||||
var y1 = fillStyle.y1_ / this.arcScaleY_;
|
||||
var p0 = this.getCoords_(x0, y0);
|
||||
var p1 = this.getCoords_(x1, y1);
|
||||
var dx = p1.x - p0.x;
|
||||
var dy = p1.y - p0.y;
|
||||
angle = Math.atan2(dx, dy) * 180 / Math.PI;
|
||||
|
||||
// The angle should be a non-negative number.
|
||||
if (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
|
||||
// Very small angles produce an unexpected result because they are
|
||||
// converted to a scientific notation string.
|
||||
if (angle < 1e-6) {
|
||||
angle = 0;
|
||||
}
|
||||
} else {
|
||||
var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);
|
||||
var width = max.x - min.x;
|
||||
var height = max.y - min.y;
|
||||
focus = {
|
||||
x: (p0.x - min.x) / width,
|
||||
y: (p0.y - min.y) / height
|
||||
};
|
||||
|
||||
width /= this.arcScaleX_ * Z;
|
||||
height /= this.arcScaleY_ * Z;
|
||||
var dimension = m.max(width, height);
|
||||
shift = 2 * fillStyle.r0_ / dimension;
|
||||
expansion = 2 * fillStyle.r1_ / dimension - shift;
|
||||
}
|
||||
|
||||
// We need to sort the color stops in ascending order by offset,
|
||||
// otherwise IE won't interpret it correctly.
|
||||
var stops = fillStyle.colors_;
|
||||
stops.sort(function(cs1, cs2) {
|
||||
return cs1.offset - cs2.offset;
|
||||
});
|
||||
|
||||
var length = stops.length;
|
||||
var color1 = stops[0].color;
|
||||
var color2 = stops[length - 1].color;
|
||||
var opacity1 = stops[0].alpha * this.globalAlpha;
|
||||
var opacity2 = stops[length - 1].alpha * this.globalAlpha;
|
||||
|
||||
var colors = [];
|
||||
for (var i = 0; i < length; i++) {
|
||||
var stop = stops[i];
|
||||
colors.push(stop.offset * expansion + shift + ' ' + stop.color);
|
||||
}
|
||||
|
||||
// When colors attribute is used, the meanings of opacity and o:opacity2
|
||||
// are reversed.
|
||||
lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"',
|
||||
' method="none" focus="100%"',
|
||||
' color="', color1, '"',
|
||||
' color2="', color2, '"',
|
||||
' colors="', colors.join(','), '"',
|
||||
' opacity="', opacity2, '"',
|
||||
' g_o_:opacity2="', opacity1, '"',
|
||||
' angle="', angle, '"',
|
||||
' focusposition="', focus.x, ',', focus.y, '" />');
|
||||
} else {
|
||||
lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity,
|
||||
'" />');
|
||||
}
|
||||
|
||||
lineStr.push('</g_vml_:shape>');
|
||||
|
||||
this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));
|
||||
};
|
||||
|
||||
contextPrototype.fill = function() {
|
||||
this.stroke(true);
|
||||
}
|
||||
|
||||
contextPrototype.closePath = function() {
|
||||
this.currentPath_.push({type: 'close'});
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
contextPrototype.getCoords_ = function(aX, aY) {
|
||||
var m = this.m_;
|
||||
return {
|
||||
x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,
|
||||
y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2
|
||||
}
|
||||
};
|
||||
|
||||
contextPrototype.save = function() {
|
||||
var o = {};
|
||||
copyState(this, o);
|
||||
this.aStack_.push(o);
|
||||
this.mStack_.push(this.m_);
|
||||
this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
|
||||
};
|
||||
|
||||
contextPrototype.restore = function() {
|
||||
copyState(this.aStack_.pop(), this);
|
||||
this.m_ = this.mStack_.pop();
|
||||
};
|
||||
|
||||
function matrixIsFinite(m) {
|
||||
for (var j = 0; j < 3; j++) {
|
||||
for (var k = 0; k < 2; k++) {
|
||||
if (!isFinite(m[j][k]) || isNaN(m[j][k])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function setM(ctx, m, updateLineScale) {
|
||||
if (!matrixIsFinite(m)) {
|
||||
return;
|
||||
}
|
||||
ctx.m_ = m;
|
||||
|
||||
if (updateLineScale) {
|
||||
// Get the line scale.
|
||||
// Determinant of this.m_ means how much the area is enlarged by the
|
||||
// transformation. So its square root can be used as a scale factor
|
||||
// for width.
|
||||
var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];
|
||||
ctx.lineScale_ = sqrt(abs(det));
|
||||
}
|
||||
}
|
||||
|
||||
contextPrototype.translate = function(aX, aY) {
|
||||
var m1 = [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[aX, aY, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), false);
|
||||
};
|
||||
|
||||
contextPrototype.rotate = function(aRot) {
|
||||
var c = mc(aRot);
|
||||
var s = ms(aRot);
|
||||
|
||||
var m1 = [
|
||||
[c, s, 0],
|
||||
[-s, c, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), false);
|
||||
};
|
||||
|
||||
contextPrototype.scale = function(aX, aY) {
|
||||
this.arcScaleX_ *= aX;
|
||||
this.arcScaleY_ *= aY;
|
||||
var m1 = [
|
||||
[aX, 0, 0],
|
||||
[0, aY, 0],
|
||||
[0, 0, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), true);
|
||||
};
|
||||
|
||||
contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {
|
||||
var m1 = [
|
||||
[m11, m12, 0],
|
||||
[m21, m22, 0],
|
||||
[dx, dy, 1]
|
||||
];
|
||||
|
||||
setM(this, matrixMultiply(m1, this.m_), true);
|
||||
};
|
||||
|
||||
contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {
|
||||
var m = [
|
||||
[m11, m12, 0],
|
||||
[m21, m22, 0],
|
||||
[dx, dy, 1]
|
||||
];
|
||||
|
||||
setM(this, m, true);
|
||||
};
|
||||
|
||||
/******** STUBS ********/
|
||||
contextPrototype.clip = function() {
|
||||
// TODO: Implement
|
||||
};
|
||||
|
||||
contextPrototype.arcTo = function() {
|
||||
// TODO: Implement
|
||||
};
|
||||
|
||||
contextPrototype.createPattern = function() {
|
||||
return new CanvasPattern_;
|
||||
};
|
||||
|
||||
// Gradient / Pattern Stubs
|
||||
function CanvasGradient_(aType) {
|
||||
this.type_ = aType;
|
||||
this.x0_ = 0;
|
||||
this.y0_ = 0;
|
||||
this.r0_ = 0;
|
||||
this.x1_ = 0;
|
||||
this.y1_ = 0;
|
||||
this.r1_ = 0;
|
||||
this.colors_ = [];
|
||||
}
|
||||
|
||||
CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
|
||||
aColor = processStyle(aColor);
|
||||
this.colors_.push({offset: aOffset,
|
||||
color: aColor.color,
|
||||
alpha: aColor.alpha});
|
||||
};
|
||||
|
||||
function CanvasPattern_() {}
|
||||
|
||||
// set up externs
|
||||
G_vmlCanvasManager = G_vmlCanvasManager_;
|
||||
CanvasRenderingContext2D = CanvasRenderingContext2D_;
|
||||
CanvasGradient = CanvasGradient_;
|
||||
CanvasPattern = CanvasPattern_;
|
||||
|
||||
})();
|
||||
|
||||
} // if
|
499
www/js/libs/html5shiv-printshiv.js
Normal file
@ -0,0 +1,499 @@
|
||||
/**
|
||||
* @preserve HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
;(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.6.2';
|
||||
|
||||
/** Preset options */
|
||||
var options = window.html5 || {};
|
||||
|
||||
/** Used to skip problem elements */
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
|
||||
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||
var expando = '_html5shiv';
|
||||
|
||||
/** The id for the the documents expando */
|
||||
var expanID = 0;
|
||||
|
||||
/** Cached data for each document */
|
||||
var expandoData = {};
|
||||
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @param {String} cssText The CSS text.
|
||||
* @returns {StyleSheet} The style element.
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of `html5.elements` as an array.
|
||||
* @private
|
||||
* @returns {Array} An array of shived element node names.
|
||||
*/
|
||||
function getElements() {
|
||||
var elements = html5.elements;
|
||||
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Object} An object of data.
|
||||
*/
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived element for the given nodeName and document
|
||||
* @memberOf html5
|
||||
* @param {String} nodeName name of the element
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||
// is inserted into a document/fragment
|
||||
// * Link elements with `src` attributes that are inaccessible, as with
|
||||
// a 403 response, will cause the tab/window to crash
|
||||
// * Script elements appended to fragments will execute when their `src`
|
||||
// or `text` property is set
|
||||
return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived DocumentFragment for the given document
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||
* @private
|
||||
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||
* @param {Object} data of the document.
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/\w+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
shivMethods(ownerDocument, data);
|
||||
}
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `html5` object is exposed so that more elements can be shived and
|
||||
* existing shiving can be detected on iframes.
|
||||
* @type Object
|
||||
* @example
|
||||
*
|
||||
* // options can be changed before the script is included
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
*/
|
||||
'version': version,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
* @memberOf html5
|
||||
* @type boolean
|
||||
*/
|
||||
'supportsUnknownElements': supportsUnknownElements,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||
* methods should be overwritten.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
* @memberOf html5
|
||||
* @type String
|
||||
*/
|
||||
'type': 'default',
|
||||
|
||||
// shivs the document according to the specified `html5` object options
|
||||
'shivDocument': shivDocument,
|
||||
|
||||
//creates a shived element
|
||||
createElement: createElement,
|
||||
|
||||
//creates a shived documentFragment
|
||||
createDocumentFragment: createDocumentFragment
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose html5
|
||||
window.html5 = html5;
|
||||
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
/*------------------------------- Print Shiv -------------------------------*/
|
||||
|
||||
/** Used to filter media types */
|
||||
var reMedia = /^$|\b(?:all|print)\b/;
|
||||
|
||||
/** Used to namespace printable elements */
|
||||
var shivNamespace = 'html5shiv';
|
||||
|
||||
/** Detect whether the browser supports shivable style sheets */
|
||||
var supportsShivableSheets = !supportsUnknownElements && (function() {
|
||||
// assign a false negative if unable to shiv
|
||||
var docEl = document.documentElement;
|
||||
return !(
|
||||
typeof document.namespaces == 'undefined' ||
|
||||
typeof document.parentWindow == 'undefined' ||
|
||||
typeof docEl.applyElement == 'undefined' ||
|
||||
typeof docEl.removeNode == 'undefined' ||
|
||||
typeof window.attachEvent == 'undefined'
|
||||
);
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Wraps all HTML5 elements in the given document with printable elements.
|
||||
* (eg. the "header" element is wrapped with the "html5shiv:header" element)
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Array} An array wrappers added.
|
||||
*/
|
||||
function addWrappers(ownerDocument) {
|
||||
var node,
|
||||
nodes = ownerDocument.getElementsByTagName('*'),
|
||||
index = nodes.length,
|
||||
reElements = RegExp('^(?:' + getElements().join('|') + ')$', 'i'),
|
||||
result = [];
|
||||
|
||||
while (index--) {
|
||||
node = nodes[index];
|
||||
if (reElements.test(node.nodeName)) {
|
||||
result.push(node.applyElement(createWrapper(node)));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a printable wrapper for the given element.
|
||||
* @private
|
||||
* @param {Element} element The element.
|
||||
* @returns {Element} The wrapper.
|
||||
*/
|
||||
function createWrapper(element) {
|
||||
var node,
|
||||
nodes = element.attributes,
|
||||
index = nodes.length,
|
||||
wrapper = element.ownerDocument.createElement(shivNamespace + ':' + element.nodeName);
|
||||
|
||||
// copy element attributes to the wrapper
|
||||
while (index--) {
|
||||
node = nodes[index];
|
||||
node.specified && wrapper.setAttribute(node.nodeName, node.nodeValue);
|
||||
}
|
||||
// copy element styles to the wrapper
|
||||
wrapper.style.cssText = element.style.cssText;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the given CSS text.
|
||||
* (eg. header{} becomes html5shiv\:header{})
|
||||
* @private
|
||||
* @param {String} cssText The CSS text to shiv.
|
||||
* @returns {String} The shived CSS text.
|
||||
*/
|
||||
function shivCssText(cssText) {
|
||||
var pair,
|
||||
parts = cssText.split('{'),
|
||||
index = parts.length,
|
||||
reElements = RegExp('(^|[\\s,>+~])(' + getElements().join('|') + ')(?=[[\\s,>+~#.:]|$)', 'gi'),
|
||||
replacement = '$1' + shivNamespace + '\\:$2';
|
||||
|
||||
while (index--) {
|
||||
pair = parts[index] = parts[index].split('}');
|
||||
pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);
|
||||
parts[index] = pair.join('}');
|
||||
}
|
||||
return parts.join('{');
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the given wrappers, leaving the original elements.
|
||||
* @private
|
||||
* @params {Array} wrappers An array of printable wrappers.
|
||||
*/
|
||||
function removeWrappers(wrappers) {
|
||||
var index = wrappers.length;
|
||||
while (index--) {
|
||||
wrappers[index].removeNode();
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document for print.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivPrint(ownerDocument) {
|
||||
var shivedSheet,
|
||||
wrappers,
|
||||
data = getExpandoData(ownerDocument),
|
||||
namespaces = ownerDocument.namespaces,
|
||||
ownerWindow = ownerDocument.parentWindow;
|
||||
|
||||
if (!supportsShivableSheets || ownerDocument.printShived) {
|
||||
return ownerDocument;
|
||||
}
|
||||
if (typeof namespaces[shivNamespace] == 'undefined') {
|
||||
namespaces.add(shivNamespace);
|
||||
}
|
||||
|
||||
function removeSheet() {
|
||||
clearTimeout(data._removeSheetTimer);
|
||||
if (shivedSheet) {
|
||||
shivedSheet.removeNode(true);
|
||||
}
|
||||
shivedSheet= null;
|
||||
}
|
||||
|
||||
ownerWindow.attachEvent('onbeforeprint', function() {
|
||||
|
||||
removeSheet();
|
||||
|
||||
var imports,
|
||||
length,
|
||||
sheet,
|
||||
collection = ownerDocument.styleSheets,
|
||||
cssText = [],
|
||||
index = collection.length,
|
||||
sheets = Array(index);
|
||||
|
||||
// convert styleSheets collection to an array
|
||||
while (index--) {
|
||||
sheets[index] = collection[index];
|
||||
}
|
||||
// concat all style sheet CSS text
|
||||
while ((sheet = sheets.pop())) {
|
||||
// IE does not enforce a same origin policy for external style sheets...
|
||||
// but has trouble with some dynamically created stylesheets
|
||||
if (!sheet.disabled && reMedia.test(sheet.media)) {
|
||||
|
||||
try {
|
||||
imports = sheet.imports;
|
||||
length = imports.length;
|
||||
} catch(er){
|
||||
length = 0;
|
||||
}
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
sheets.push(imports[index]);
|
||||
}
|
||||
|
||||
try {
|
||||
cssText.push(sheet.cssText);
|
||||
} catch(er){}
|
||||
}
|
||||
}
|
||||
|
||||
// wrap all HTML5 elements with printable elements and add the shived style sheet
|
||||
cssText = shivCssText(cssText.reverse().join(''));
|
||||
wrappers = addWrappers(ownerDocument);
|
||||
shivedSheet = addStyleSheet(ownerDocument, cssText);
|
||||
|
||||
});
|
||||
|
||||
ownerWindow.attachEvent('onafterprint', function() {
|
||||
// remove wrappers, leaving the original elements, and remove the shived style sheet
|
||||
removeWrappers(wrappers);
|
||||
clearTimeout(data._removeSheetTimer);
|
||||
data._removeSheetTimer = setTimeout(removeSheet, 500);
|
||||
});
|
||||
|
||||
ownerDocument.printShived = true;
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose API
|
||||
html5.type += ' print';
|
||||
html5.shivPrint = shivPrint;
|
||||
|
||||
// shiv for print
|
||||
shivPrint(document);
|
||||
|
||||
}(this, document));
|
301
www/js/libs/html5shiv.js
vendored
Normal file
@ -0,0 +1,301 @@
|
||||
/**
|
||||
* @preserve HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
;(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.6.2';
|
||||
|
||||
/** Preset options */
|
||||
var options = window.html5 || {};
|
||||
|
||||
/** Used to skip problem elements */
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
|
||||
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||
var expando = '_html5shiv';
|
||||
|
||||
/** The id for the the documents expando */
|
||||
var expanID = 0;
|
||||
|
||||
/** Cached data for each document */
|
||||
var expandoData = {};
|
||||
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @param {String} cssText The CSS text.
|
||||
* @returns {StyleSheet} The style element.
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of `html5.elements` as an array.
|
||||
* @private
|
||||
* @returns {Array} An array of shived element node names.
|
||||
*/
|
||||
function getElements() {
|
||||
var elements = html5.elements;
|
||||
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Object} An object of data.
|
||||
*/
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived element for the given nodeName and document
|
||||
* @memberOf html5
|
||||
* @param {String} nodeName name of the element
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||
// is inserted into a document/fragment
|
||||
// * Link elements with `src` attributes that are inaccessible, as with
|
||||
// a 403 response, will cause the tab/window to crash
|
||||
// * Script elements appended to fragments will execute when their `src`
|
||||
// or `text` property is set
|
||||
return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived DocumentFragment for the given document
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||
* @private
|
||||
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||
* @param {Object} data of the document.
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/\w+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
shivMethods(ownerDocument, data);
|
||||
}
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `html5` object is exposed so that more elements can be shived and
|
||||
* existing shiving can be detected on iframes.
|
||||
* @type Object
|
||||
* @example
|
||||
*
|
||||
* // options can be changed before the script is included
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
*/
|
||||
'version': version,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
* @memberOf html5
|
||||
* @type boolean
|
||||
*/
|
||||
'supportsUnknownElements': supportsUnknownElements,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||
* methods should be overwritten.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
* @memberOf html5
|
||||
* @type String
|
||||
*/
|
||||
'type': 'default',
|
||||
|
||||
// shivs the document according to the specified `html5` object options
|
||||
'shivDocument': shivDocument,
|
||||
|
||||
//creates a shived element
|
||||
createElement: createElement,
|
||||
|
||||
//creates a shived documentFragment
|
||||
createDocumentFragment: createDocumentFragment
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose html5
|
||||
window.html5 = html5;
|
||||
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
}(this, document));
|
2
www/js/libs/jquery-1.8.3.min.js
vendored
Normal file
135
www/js/main.js
Normal file
@ -0,0 +1,135 @@
|
||||
var debugMode = false; // debug mode
|
||||
var sendPrintCommands = true; // if Doodle3d should send print commands to the 3d printer
|
||||
var communicateWithWifibox = true; // if Doodle3d should try interfacing with the wifibox (in case one is not connected)
|
||||
var wifiboxIsRemote = false; // when you want to run the client on a computer and have it remotely connect to the wifibox
|
||||
var autoUpdate = true; // auto retrieve updates about temperature and progress from printer
|
||||
|
||||
var printer = new Printer();
|
||||
var progressbar = new Progressbar();
|
||||
var thermometer = new Thermometer();
|
||||
var settingsWindow = new SettingsWindow();
|
||||
var message = new Message();
|
||||
|
||||
var firstTimeSettingsLoaded = true;
|
||||
|
||||
var wifiboxURL; // Using the uhttpd lua handler as default, because of better performance
|
||||
var wifiboxCGIBinURL; // CGI-bin, for some network stuff, where it needs to restart the webserver for example
|
||||
|
||||
var $drawAreaContainer, $doodleCanvas, doodleCanvas, doodleCanvasContext, $previewContainer;
|
||||
|
||||
$(function() {
|
||||
console.log("ready");
|
||||
|
||||
|
||||
//TODO give this a more logical place in code
|
||||
|
||||
if (getURLParameter("d") != "null") debugMode = (getURLParameter("d") == "1");
|
||||
if (getURLParameter("p") != "null") sendPrintCommands = (getURLParameter("p") == "1");
|
||||
if (getURLParameter("c") != "null") communicateWithWifibox = (getURLParameter("c") == "1");
|
||||
if (getURLParameter("r") != "null") wifiboxIsRemote = (getURLParameter("r") == "1");
|
||||
if (getURLParameter("u") != "null") autoUpdate = (getURLParameter("u") == "1");
|
||||
|
||||
if (wifiboxIsRemote) {
|
||||
wifiboxURL = "http://192.168.5.1/d3dapi";
|
||||
wifiboxCGIBinURL = "http://192.168.5.1/cgi-bin/d3dapi";
|
||||
} else {
|
||||
wifiboxURL = "http://" + window.location.host + "/d3dapi";
|
||||
wifiboxCGIBinURL = "http://" + window.location.host + "/cgi-bin/d3dapi";
|
||||
}
|
||||
|
||||
if (!communicateWithWifibox) {
|
||||
sendPrintCommands = false; // 'communicateWithWifibox = false' implies this
|
||||
}
|
||||
console.log("debugMode: " + debugMode);
|
||||
console.log("sendPrintCommands: " + sendPrintCommands);
|
||||
console.log("communicateWithWifibox: " + communicateWithWifibox);
|
||||
console.log("wifiboxIsRemote: " + wifiboxIsRemote);
|
||||
console.log("wifibox URL: " + wifiboxURL);
|
||||
|
||||
initDoodleDrawing();
|
||||
initPreviewRendering();
|
||||
initLayouting();
|
||||
initSidebars();
|
||||
initButtonBehavior();
|
||||
initVerticalShapes();
|
||||
|
||||
thermometer.init($("#thermometerCanvas"), $("#thermometerContainer"));
|
||||
progressbar.init($("#progressbarCanvas"), $("#progressbarCanvasContainer"));
|
||||
|
||||
message.init($("#message"));
|
||||
|
||||
printer.init();
|
||||
$(document).on(Printer.UPDATE,update);
|
||||
|
||||
settingsWindow.init(wifiboxURL,wifiboxCGIBinURL);
|
||||
$(document).on(SettingsWindow.SETTINGS_LOADED, settingsLoaded);
|
||||
|
||||
if(debugMode) {
|
||||
console.log("debug mode is true");
|
||||
$("body").css("overflow", "auto");
|
||||
$("#debug_textArea").css("display", "block");
|
||||
$("#preview_tmp").css("display", "block");
|
||||
|
||||
$("#debug_display").css("display", "block");
|
||||
|
||||
// show and hide the progressguage and thermometer
|
||||
showhideInterval = setInterval(showOrHideThermo, 2500);
|
||||
|
||||
// $("#debugContainer").css("display", "block");
|
||||
|
||||
/* TEMP CODE!! -> artificially populates the startgcode and endgcode textareas in the settings window */
|
||||
// todo remove this temporary code...
|
||||
/*
|
||||
setTimeout(function() {
|
||||
$("#startgcode").text("");
|
||||
$("#startgcode").append("G21 (mm) \n");
|
||||
$("#startgcode").append("G91 (relative) \n");
|
||||
$("#startgcode").append("G28 X0 Y0 Z0 (physical home) \n");
|
||||
$("#startgcode").append("M104 S230 (temperature) \n");
|
||||
$("#startgcode").append("G1 E10 F250 (flow) \n");
|
||||
$("#startgcode").append("G92 X-100 Y-100 Z0 E10 \n");
|
||||
$("#startgcode").append("G1 Z3 F5000 (prevent diagonal line) \n");
|
||||
$("#startgcode").append("G90 (absolute) \n");
|
||||
$("#startgcode").append("M106 (fan on)");
|
||||
console.log("$('#startgcode'): " + $("#startgcode").val());
|
||||
|
||||
$("#endgcode").text("");
|
||||
$("#endgcode").append("G1 X-100 Y-100 F15000 (fast homing) \n");
|
||||
$("#endgcode").append("M107 \n");
|
||||
$("#endgcode").append("M84 (disable axes) \n");
|
||||
console.log("$('#endgcode'): " + $("#endgcode").val());
|
||||
}, 1000);
|
||||
//*/
|
||||
}
|
||||
});
|
||||
|
||||
var showhideInterval;
|
||||
var showOrHide = false;
|
||||
|
||||
function showOrHideThermo() {
|
||||
console.log("f:showOrHideThermo()");
|
||||
if (showOrHide) {
|
||||
thermometer.hide();
|
||||
progressbar.hide();
|
||||
} else {
|
||||
thermometer.show();
|
||||
progressbar.show();
|
||||
|
||||
}
|
||||
showOrHide = !showOrHide;
|
||||
}
|
||||
|
||||
function settingsLoaded() {
|
||||
console.log("settingsLoaded");
|
||||
console.log("autoHeatup: ",settings["printer.heatup.enabled"]);
|
||||
if(settings["printer.heatup.enabled"]) {
|
||||
if(firstTimeSettingsLoaded) {
|
||||
printer.preheat();
|
||||
firstTimeSettingsLoaded = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setDebugText(text) {
|
||||
$("#debug_display").text(text);
|
||||
}
|
52
www/js/message.js
Normal file
@ -0,0 +1,52 @@
|
||||
function Message() {
|
||||
|
||||
Message.ERROR = "error";
|
||||
Message.WARNING = "warning";
|
||||
Message.NOTICE = "notice";
|
||||
Message.INFO = "info";
|
||||
|
||||
this.mode = "";
|
||||
|
||||
this.$element;
|
||||
|
||||
var self = this;
|
||||
var autoHideDelay = 2000;
|
||||
var autohideTimeout;
|
||||
|
||||
this.init = function($element) {
|
||||
console.log("Message:init");
|
||||
|
||||
this.$element = $element;
|
||||
console.log("$element: ",$element);
|
||||
}
|
||||
|
||||
this.set = function(text,mode,autoHide) {
|
||||
console.log("Message:set: ",text,mode,autoHide);
|
||||
self.hide(function() {
|
||||
self.show();
|
||||
self.clear();
|
||||
|
||||
self.$element.text(text);
|
||||
self.$element.addClass(mode);
|
||||
self.show();
|
||||
|
||||
self.mode = mode;
|
||||
|
||||
clearTimeout(autohideTimeout);
|
||||
if(autoHide) {
|
||||
autohideTimeout = setTimeout(function(){ self.hide()},autoHideDelay);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.clear = function($element) {
|
||||
this.$element.text("");
|
||||
this.$element.removeClass(this.mode);
|
||||
}
|
||||
|
||||
this.show = function() {
|
||||
this.$element.fadeIn(200);
|
||||
}
|
||||
this.hide = function(complete) {
|
||||
this.$element.fadeOut(200,complete);
|
||||
}
|
||||
}
|
343
www/js/previewRendering.js
Normal file
@ -0,0 +1,343 @@
|
||||
//*
|
||||
var $preview;
|
||||
var preview;
|
||||
var previewCtx;
|
||||
|
||||
var preview_tmp;
|
||||
var previewCtx_tmp;
|
||||
|
||||
var previewDefaults = {
|
||||
rotation: Math.PI/90,
|
||||
numLayers: 10
|
||||
}
|
||||
|
||||
var svgPathRegExp = /[LM]\d* \d*/ig;
|
||||
var svgPathParamsRegExp = /([LM])(\d*) (\d*)/;
|
||||
|
||||
var prevRedrawTime = new Date().getTime();
|
||||
var redrawInterval = 1000 / 30; // ms
|
||||
|
||||
function initPreviewRendering() {
|
||||
console.log("f:initPreviewRendering()");
|
||||
|
||||
$preview = $("#preview");
|
||||
preview = $preview[0];
|
||||
previewCtx = preview.getContext('2d');
|
||||
|
||||
// DEBUG --> mbt preview_tmp (voor de toImageData truc)
|
||||
var _ratio = preview.width / canvas.width;
|
||||
preview_tmp = document.getElementById('preview_tmp');
|
||||
preview_tmp.width = preview.width;
|
||||
preview_tmp.height = canvas.height * _ratio;
|
||||
$("#preview_tmp").css("top", -preview_tmp.height);
|
||||
|
||||
previewCtx_tmp = preview_tmp.getContext('2d');
|
||||
|
||||
calcPreviewCanvasProperties();
|
||||
redrawPreview();
|
||||
}
|
||||
|
||||
function calcPreviewCanvasProperties() {
|
||||
console.log("f:calcPreviewCanvasProperties()");
|
||||
|
||||
globalScale = preview.width / canvasWidth;
|
||||
layerCX = (canvasWidth / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
layerCY = (canvasHeight / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
// layerOffsetY = preview.height - 1.75 * layerCY;
|
||||
layerOffsetY = preview.height * (1 - previewVerticalPadding.bottom);
|
||||
yStep = (preview.height - (preview.height * (previewVerticalPadding.top + previewVerticalPadding.bottom))) / maxNumLayers;
|
||||
}
|
||||
|
||||
// TODO (perhaps) : make the twist limit dynamic, depending on what's printable (w.r.t. overlapping)
|
||||
var previewRotationLimit = Math.PI / 30; // rough estimate
|
||||
|
||||
var numLayers = previewDefaults.numLayers; // current number of preview layers
|
||||
var maxNumLayers= 100; // maximum number of preview layers
|
||||
var minNumLayers= 2; // minimum number of preview layers
|
||||
var globalScale = 0.3; // global scale of preview (width preview / width canvas)
|
||||
var globalAlpha = 0.20; // global alpha of preview
|
||||
var scaleY = 0.4; // additional vertical scale per path for 3d effect
|
||||
var viewerScale = 0.65; // additional scale to fit into preview nicely (otherwise is fills out totally)
|
||||
var previewVerticalPadding = { "top" : .15, "bottom" : 0.12 }; // %
|
||||
var strokeWidth = 2; //4;
|
||||
//var rStep = Math.PI/40; //Math.PI/40; //
|
||||
var rStep = previewDefaults.rotation; // Math.PI/180; //Math.PI/40; //
|
||||
var yStep;// = preview.height / 150; // 3; //6;
|
||||
//var svgWidth = 500; // 650 //parseInt($(svg).css("width"));
|
||||
//var svgHeight = 450; //450; //parseInt($(svg).css("height"));
|
||||
var layerCX, layerCY;
|
||||
//var layerCX = (canvasWidth / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
//var layerCY = (canvasHeight / 2) * globalScale; // defined in canvasDrawing_v01.js
|
||||
var layerOffsetY; //= preview.height - 1.75 * layerCY; // 330; // previewHeight - 120
|
||||
var prevX = 0;
|
||||
var prevY = 0;
|
||||
var highlight = true; //highlight bottom, middle and top layers
|
||||
|
||||
var linesRaw = "";
|
||||
var debug_redrawSimplification = 6;
|
||||
function redrawPreview(redrawLess) {
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
|
||||
if (_points.length < 2) return;
|
||||
|
||||
if (!redrawLess) {
|
||||
//debug_redrawSimplification = Math.round(_points.length / 65);
|
||||
//*
|
||||
if (_points.length < 100) {
|
||||
debug_redrawSimplification = 6;
|
||||
} else if (_points.length < 250) {
|
||||
debug_redrawSimplification = 7;
|
||||
} else if (_points.length < 400) {
|
||||
debug_redrawSimplification = 8;
|
||||
} else if (_points.length < 550) {
|
||||
debug_redrawSimplification = 9;
|
||||
} else if (_points.length < 700) {
|
||||
debug_redrawSimplification = 10;
|
||||
} else {
|
||||
debug_redrawSimplification = 11;
|
||||
}
|
||||
//*/
|
||||
// console.log("debug_redrawSimplification: " + debug_redrawSimplification);
|
||||
}
|
||||
|
||||
var y = 0;
|
||||
var r = 0;
|
||||
|
||||
//preview.width = preview.width;
|
||||
previewCtx.clearRect(0, 0, preview.width, preview.height);
|
||||
previewCtx.lineWidth = strokeWidth;
|
||||
previewCtx.strokeStyle = '#f00'; //"rgba(255,255,0,0)";
|
||||
|
||||
for(var i = 0; i < numLayers; i++) {
|
||||
|
||||
var verticalScaleFactor = scaleFunction(i / maxNumLayers);
|
||||
|
||||
if(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) {
|
||||
previewCtx.globalAlpha = 1;
|
||||
} else {
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
if (redrawLess && i%debug_redrawSimplification != 0 && !(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) ) {
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
continue;
|
||||
}
|
||||
|
||||
previewCtx.save();
|
||||
|
||||
// previewCtx.translate(layerCX, layerOffsetY + layerCY + y);
|
||||
previewCtx.translate(layerCX, layerOffsetY + y);
|
||||
// previewCtx.setTransform(1, 0, 0, scaleY, layerCX, layerOffsetY+layerCY+y);
|
||||
previewCtx.scale(viewerScale * verticalScaleFactor, scaleY * viewerScale * verticalScaleFactor);
|
||||
previewCtx.rotate(r);
|
||||
previewCtx.translate((-doodleTransform[0]) * (globalScale * doodleTransform[2]), (-doodleTransform[1]) * (globalScale * doodleTransform[3]));
|
||||
|
||||
var adjustedDoodlePoint = centeredAndScaledDoodlePoint(_points[0]);
|
||||
|
||||
previewCtx.beginPath();
|
||||
previewCtx.moveTo(adjustedDoodlePoint.x, adjustedDoodlePoint.y);
|
||||
for(var j = 1; j < _points.length; j++) {
|
||||
adjustedDoodlePoint = centeredAndScaledDoodlePoint(_points[j])
|
||||
if (redrawLess && j%debug_redrawSimplification != 0 ) continue;
|
||||
previewCtx.lineTo(adjustedDoodlePoint.x, adjustedDoodlePoint.y);
|
||||
}
|
||||
previewCtx.stroke();
|
||||
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
previewCtx.restore();
|
||||
}
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
function renderToImageDataPreview() {
|
||||
console.log("f:renderToImageDataPreview()");
|
||||
|
||||
if (_points.length < 2) return;
|
||||
|
||||
//*
|
||||
// the first step
|
||||
previewCtx_tmp.clearRect(0, 0, preview.width, preview.height);
|
||||
previewCtx_tmp.lineWidth = strokeWidth;
|
||||
previewCtx_tmp.strokeStyle = '#f00'; //"rgba(255,255,0,0)";
|
||||
|
||||
previewCtx_tmp.save();
|
||||
previewCtx_tmp.translate(layerCX, layerCY);
|
||||
previewCtx_tmp.scale(viewerScale, viewerScale);
|
||||
previewCtx_tmp.translate((-doodleTransform[0]) * (globalScale * doodleTransform[2]), (-doodleTransform[1]) * (globalScale * doodleTransform[3]));
|
||||
|
||||
var adjustedDoodlePt = centeredAndScaledDoodlePoint(_points[0]);
|
||||
|
||||
previewCtx_tmp.beginPath();
|
||||
previewCtx_tmp.moveTo(adjustedDoodlePt.x, adjustedDoodlePt.y);
|
||||
for(var j = 1; j < _points.length; j++) {
|
||||
adjustedDoodlePt = centeredAndScaledDoodlePoint(_points[j])
|
||||
previewCtx_tmp.lineTo(adjustedDoodlePt.x, adjustedDoodlePt.y);
|
||||
}
|
||||
previewCtx_tmp.stroke();
|
||||
previewCtx_tmp.closePath();
|
||||
previewCtx_tmp.restore();
|
||||
//*/
|
||||
|
||||
// var saved_rect = previewCtx_tmp.getImageData(0, 0, layerCX*2, layerCY*2);
|
||||
var saved_rect_todataurl = preview_tmp.toDataURL();
|
||||
doodleImageCapture = new Image();
|
||||
doodleImageCapture.onload = function() {
|
||||
|
||||
previewCtx.clearRect(0, 0, preview.width, preview.height);
|
||||
previewCtx.lineWidth = strokeWidth;
|
||||
previewCtx.strokeStyle = '#f00'; //"rgba(255,255,0,0)";
|
||||
|
||||
var y = 0;
|
||||
var r = 0;
|
||||
|
||||
for(var i=0;i<numLayers;i++) {
|
||||
|
||||
var verticalScaleFactor = scaleFunction(i / maxNumLayers);
|
||||
|
||||
if(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1){
|
||||
previewCtx.globalAlpha = 1;
|
||||
} else {
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
previewCtx.save();
|
||||
|
||||
previewCtx.translate(layerCX,layerOffsetY+y);
|
||||
// previewCtx.scale(1, scaleY)
|
||||
previewCtx.scale(verticalScaleFactor, scaleY * verticalScaleFactor)
|
||||
previewCtx.rotate(r);
|
||||
previewCtx.translate(-layerCX,-layerCY);
|
||||
|
||||
previewCtx.drawImage(doodleImageCapture, 0, 0);
|
||||
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
previewCtx.restore();
|
||||
}
|
||||
};
|
||||
doodleImageCapture.src = saved_rect_todataurl;
|
||||
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
// called by the move up/down or twist left/right buttons
|
||||
// it is assumed that the preview has been rendered to an Image object, which will be used to draw the preview with (much better performance)
|
||||
function redrawRenderedPreview(redrawLess) {
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
console.log("f:redrawRenderedPreview()");
|
||||
|
||||
previewCtx.clearRect(0, 0, preview.width, preview.height);
|
||||
previewCtx.lineWidth = strokeWidth;
|
||||
previewCtx.strokeStyle = '#f00'; //"rgba(255,255,0,0)";
|
||||
|
||||
var y = 0;
|
||||
var r = 0;
|
||||
|
||||
for(var i = 0; i < numLayers; i++) {
|
||||
|
||||
var verticalScaleFactor = scaleFunction(i / maxNumLayers);
|
||||
|
||||
if(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1){
|
||||
previewCtx.globalAlpha = 1;
|
||||
} else {
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
if (redrawLess && i%2 != 0 && !(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) ) {
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
continue;
|
||||
}
|
||||
previewCtx.save();
|
||||
|
||||
previewCtx.translate(layerCX,layerOffsetY+y);
|
||||
// previewCtx.scale(1, scaleY)
|
||||
previewCtx.scale(verticalScaleFactor, scaleY * verticalScaleFactor);
|
||||
previewCtx.rotate(r);
|
||||
previewCtx.translate(-layerCX,-layerCY);
|
||||
|
||||
previewCtx.drawImage(doodleImageCapture, 0, 0);
|
||||
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
previewCtx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
function centeredAndScaledDoodlePoint(p) {
|
||||
var obj = { x: 0, y: 0};
|
||||
|
||||
obj.x = (p[0] - ((doodleBounds[2] - doodleBounds[0])/2)) * (globalScale * doodleTransform[2]);
|
||||
obj.y = (p[1] - ((doodleBounds[3] - doodleBounds[1])/2)) * (globalScale * doodleTransform[3]);
|
||||
// obj.x = (p[0] - (doodleBounds[2] - doodleBounds[0])) * (globalScale * doodleTransform[2]);
|
||||
// obj.y = (p[1] - (doodleBounds[3] - doodleBounds[1])) * (globalScale * doodleTransform[3]);
|
||||
// obj.x = (p[0] - doodleTransform[0]) * (globalScale * doodleTransform[2]);
|
||||
// obj.y = (p[1] - doodleTransform[1]) * (globalScale * doodleTransform[3]);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
//*
|
||||
var updatePrevX = -1;
|
||||
var updatePrevY = -1;
|
||||
function updatePreview(_x, _y, redrawLess) {
|
||||
if (redrawLess == undefined) redrawLess = false;
|
||||
redrawLess = false;
|
||||
|
||||
if (_points.length < 2) return;
|
||||
if (updatePrevX == -1 || updatePrevY == -1) {
|
||||
updatePrevX = _x;
|
||||
updatePrevY = _y;
|
||||
return;
|
||||
}
|
||||
|
||||
// if (_points.length < 16 && Math.sqrt(Math.pow((updatePrevX - _x), 2) + Math.pow((updatePrevY - _y), 2)) < 8) return;
|
||||
|
||||
var y = 0;
|
||||
var r = 0;
|
||||
|
||||
previewCtx.lineWidth = strokeWidth;
|
||||
previewCtx.strokeStyle = '#f00'; //"rgba(255,255,0,0)";
|
||||
|
||||
for(var i = 0; i < numLayers; i++) {
|
||||
|
||||
if(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) {
|
||||
previewCtx.globalAlpha = 1;
|
||||
} else {
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
}
|
||||
|
||||
if (redrawLess && i%debug_redrawSimplification != 0 && !(i == 0 || i == Math.floor(numLayers/2) || i == numLayers-1) ) {
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
continue;
|
||||
}
|
||||
|
||||
previewCtx.save();
|
||||
|
||||
// previewCtx.translate(layerCX, layerOffsetY + layerCY + y);
|
||||
previewCtx.translate(layerCX, layerOffsetY + y);
|
||||
previewCtx.scale(viewerScale, scaleY * viewerScale);
|
||||
previewCtx.rotate(r);
|
||||
previewCtx.translate((-doodleTransform[0]) * (globalScale * doodleTransform[2]), (-doodleTransform[1]) * (globalScale * doodleTransform[3]));
|
||||
|
||||
|
||||
previewCtx.beginPath();
|
||||
var prevPoint = centeredAndScaledDoodlePoint([updatePrevX, updatePrevY]);
|
||||
previewCtx.moveTo(prevPoint.x, prevPoint.y);
|
||||
var adjustedDoodlePoint = centeredAndScaledDoodlePoint([_x, _y]);
|
||||
previewCtx.lineTo(adjustedDoodlePoint.x, adjustedDoodlePoint.y);
|
||||
previewCtx.stroke();
|
||||
|
||||
y -= yStep;
|
||||
r += rStep;
|
||||
previewCtx.restore();
|
||||
}
|
||||
previewCtx.globalAlpha = globalAlpha;
|
||||
updatePrevX = _x;
|
||||
updatePrevY = _y;
|
||||
|
||||
}
|
||||
//*/
|
62
www/js/sidebar.js
Normal file
@ -0,0 +1,62 @@
|
||||
var sidebarLeft;
|
||||
var sidebarRight;
|
||||
|
||||
function initSidebars() {
|
||||
console.log("f:initSidebars()");
|
||||
|
||||
sidebarLeft = new SideBar();
|
||||
sidebarLeft.init(".leftpanel", "hideleft", function() {
|
||||
$(".leftpanel").show();
|
||||
});
|
||||
|
||||
sidebarRight = new SideBar();
|
||||
sidebarRight.init(".rightpanel", "hideright", function() {
|
||||
$(".rightpanel").show();
|
||||
});
|
||||
}
|
||||
|
||||
function SideBar() {
|
||||
this.initted = false;
|
||||
this.$contentTarg = undefined;
|
||||
this.$sideBtn = undefined;
|
||||
this.contentHidden = false;
|
||||
this.hideClass = "";
|
||||
|
||||
this.init = function(targ, hideClass, callback) {
|
||||
console.log("SideBar >> f:init >> targ: " , $(targ) , ", hideClass: " + hideClass);
|
||||
this.$contentTarg = $(targ);
|
||||
this.hideClass = hideClass;
|
||||
|
||||
this.$contentTarg.addClass(this.hideClass);
|
||||
this.contentHidden = true;
|
||||
|
||||
this.$contentTarg.append("<div class='sidebutton'></div>");
|
||||
this.$sideBtn = $(targ +" .sidebutton");
|
||||
var self = this;
|
||||
|
||||
this.$sideBtn.on('click', function(e) {
|
||||
console.log("sidebutton");
|
||||
self.toggleShowHide();
|
||||
});
|
||||
|
||||
this.initted = true;
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
this.toggleShowHide = function() {
|
||||
if (this.contentHidden) {
|
||||
this.contentHidden = false;
|
||||
this.$contentTarg.removeClass(this.hideClass);
|
||||
// self.$sideBtn.addClass("sidebuttonin");
|
||||
this.$sideBtn.addClass("sidebuttonin");
|
||||
} else {
|
||||
this.contentHidden = true;
|
||||
this.$contentTarg.addClass(this.hideClass);
|
||||
// self.$sideBtn.removeClass("sidebuttonin");
|
||||
this.$sideBtn.removeClass("sidebuttonin");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
7
www/js/utils.js
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
// http://stackoverflow.com/questions/1403888/get-url-parameter-with-jquery
|
||||
function getURLParameter(name) {
|
||||
return decodeURI(
|
||||
(new RegExp('[&?]'+name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
|
||||
);
|
||||
}
|
41
www/js/verticalShapes.js
Normal file
@ -0,0 +1,41 @@
|
||||
var VERTICALSHAPE;
|
||||
var verticalShapes = {
|
||||
"NONE": 'none',
|
||||
"DIVERGING": 'diverging',
|
||||
"CONVERGING": 'converging',
|
||||
"SINUS": 'sinus'
|
||||
};
|
||||
|
||||
function initVerticalShapes() {
|
||||
// TODO give these vertical shapes a better spot
|
||||
VERTICALSHAPE = verticalShapes.NONE;
|
||||
$(".verticalShapes, .straight").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("diverging");
|
||||
VERTICALSHAPE = verticalShapes.NONE;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
$(".verticalShapes, .diverging").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("diverging");
|
||||
VERTICALSHAPE = verticalShapes.DIVERGING;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
$(".verticalShapes, .converging").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("converging");
|
||||
VERTICALSHAPE = verticalShapes.CONVERGING;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
$(".verticalShapes, .sinus").on('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
console.log("sinus");
|
||||
VERTICALSHAPE = verticalShapes.SINUS;
|
||||
redrawRenderedPreview();
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function resetVerticalShapes() {
|
||||
VERTICALSHAPE = verticalShapes.NONE;
|
||||
}
|
9
www/library/test/success.html
Normal file
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Success</TITLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
Success
|
||||
</BODY>
|
||||
</HTML>
|
147
www/settings.html
Executable file
@ -0,0 +1,147 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>settings</title>
|
||||
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta id="Viewport" name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
|
||||
|
||||
<link href="css/settings.css" rel="stylesheet" media="screen">
|
||||
</head>
|
||||
<body>
|
||||
<div class="settingsContainer">
|
||||
<form id="settingsForm">
|
||||
<!--<fieldset>
|
||||
<legend>3D printer</legend>
|
||||
<label for="printerType">Type:</label>
|
||||
<select id="printerType" name="printer.type">
|
||||
<option value="rigidbot">Rigidbot</option>
|
||||
<option value="ultimaker">Ultimaker</option>
|
||||
<option value="makerbot_replicator2">MakerBot Replicator2</option>
|
||||
<option value="makerbot_thingomatic">MakerBot Thing-o-matic</option>
|
||||
<option value="printrbot">Printrbot</option>
|
||||
<option value="bukobot">Bukobot</option>
|
||||
<option value="cartesio">Cartesio</option>
|
||||
<option value="cyrus">Cyrus</option>
|
||||
<option value="delta_rostockmax">Delta RostockMax</option>
|
||||
<option value="deltamaker">Deltamaker</option>
|
||||
<option value="eventorbot">EventorBot</option>
|
||||
<option value="felix">Felix</option>
|
||||
<option value="gigabot">Gigabot</option>
|
||||
<option value="kossel">Kossel</option>
|
||||
<option value="leapfrog_creatr">LeapFrog Creatr</option>
|
||||
<option value="lulzbot_aO_101">LulzBot AO-101</option>
|
||||
<option value="makergear_m2">MakerGear M2</option>
|
||||
<option value="makergear_prusa">MakerGear Prusa</option>
|
||||
<option value="makibox">Makibox</option>
|
||||
<option value="orca_0_3">Orca 0.3</option>
|
||||
<option value="ord_bot_hadron">ORD Bot Hadron</option>
|
||||
<option value="printxel_3d">Printxel 3D</option>
|
||||
<option value="prusa_i3">Prusa I3</option>
|
||||
<option value="prusa_iteration_2">Prusa Iteration 2</option>
|
||||
<option value="rapman">RapMan</option>
|
||||
<option value="reprappro_huxley">RepRapPro Huxley</option>
|
||||
<option value="reprappro_mendel">RepRapPro Mendel</option>
|
||||
<option value="robo_3d_printer">RoBo 3D Printer</option>
|
||||
<option value="shapercube">ShaperCube</option>
|
||||
<option value="tantillus">Tantillus</option>
|
||||
<option value="vision_3d_printer">Vision 3D Printer</option>
|
||||
</select>
|
||||
<br>
|
||||
<label for="printerBaudrate">Baud rate:</label>
|
||||
<select id="printerBaudrate" name="printer.baudrate">
|
||||
<option value="115200">115200 bps</option>
|
||||
<option value="2500000">2500000 bps</option>
|
||||
</select>
|
||||
</fieldset>-->
|
||||
|
||||
<fieldset id="printersettings">
|
||||
<legend>Print settings</legend>
|
||||
<label for="layerHeight">Layer height:</label><input id="layerHeight" type="number" step="0.01" class="small" name="printer.layerHeight">mm<br>
|
||||
<label for="wallThickness">Wall thickness:</label><input id="wallThickness" type="number" step="0.1" class="small" name="printer.wallThickness">mm<br>
|
||||
<label for="filamentThickness">Filament thickness:</label><input id="filamentThickness" step="0.01" type="number" class="small" name="printer.filamentThickness">mm<br>
|
||||
<label for="temperature">Temperature:</label><input id="temperature" type="number" class="small" name="printer.temperature">degrees C<br>
|
||||
<br>
|
||||
<label for="speed">Speed:</label><input id="speed" type="number" name="printer.speed" class="small">mm/s<br>
|
||||
<label for="travelSpeed">Travel speed:</label><input id="travelSpeed" type="number" name="printer.travelSpeed" class="small">mm/s<br>
|
||||
<label for="enableTraveling">Enable traveling:</label><input id="enableTraveling" type="checkbox" name="printer.enableTraveling" value="enableTraveling"><br>
|
||||
<label for="firstLayerSlow">First layer slow:</label><input id="firstLayerSlow" type="checkbox" name="printer.firstLayerSlow" value="firstLayerSlow"><br>
|
||||
<label for="useSubLayers">Use sub-layers*:</label><input id="useSubLayers" type="checkbox" name="printer.useSubLayers" value="firstLayerSlow"><br>
|
||||
<small>* Continuously move platform while printing instead of once per layer</small>
|
||||
<br>
|
||||
<label for="useRetraction">Use retraction:</label><input id="useRetraction" type="checkbox" name="printer.retraction.enabled" value="useRetraction"><br>
|
||||
<label for="retractionAmount">Retraction amount:</label><input id="retractionAmount" type="number" class="small" name="printer.retraction.amount">mm<br>
|
||||
<label for="retractionMinDistance">Retraction min distance:</label><input id="retractionMinDistance" type="number" class="small" name="printer.retraction.minDistance">mm<br>
|
||||
<label for="retractionSpeed">Retraction speed:</label><input id="retractionSpeed" type="number" class="small" name="printer.retraction.speed">mm/s<br>
|
||||
<br>
|
||||
<label for="heatupEnabled">Auto preheat:</label><input id="heatupEnabled" type="checkbox" name="printer.heatup.enabled" value="heatupEnabled"><br>
|
||||
<label for="heatupTemperature">Auto preaheat temperature:</label><input id="heatupTemperature" type="number" class="small" name="printer.heatup.temperature"><br>
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="doodlesettings">
|
||||
<legend>Doodle3D settings</legend>
|
||||
<label for="simplifyMinDistance">Minimal line distance:</label><input id="simplifyMinDistance" type="number" class="small" name="doodle3d.simplify.minDistance">px<br>
|
||||
<label for="maxObjectHeight">Max object height:</label><input id="maxObjectHeight" type="number" class="small" name="printer.maxObjectHeight">mm<br>
|
||||
<label for="screenToMillimeterScale">Pixels to mm scale:</label><input id="screenToMillimeterScale" type="number" step="0.1" class="small" name="printer.screenToMillimeterScale"><br>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Network settings</legend>
|
||||
<label>Connection type:</label>
|
||||
<div>
|
||||
<label for="ap"><input type="radio" name="connectiontype" value="ap" id="ap">Access point mode</label>
|
||||
<label for="client"><input type="radio" name="connectiontype" value="client" id="client">Client mode</label>
|
||||
</div>
|
||||
|
||||
<fieldset id="apSettings">
|
||||
<legend>Access point settings</legend>
|
||||
<label for="ssid">Wi-Fi box ssid*:</label><input type="text" class="large" name="network.ap.ssid" id="ssid"> <br>
|
||||
<small>* The text <em>%%MAC_ADDR_TAIL%%</em> will be replaced by the last 6 digits of your Doodle3D Wi-Fi box's MAC address.</small>
|
||||
<br>
|
||||
<label for="apKey">Password:</label><input type="text" class="large" name="network.ap.key" id="apKey"> <br>
|
||||
<label for="ipaddress">Wi-Fi box IP address:</label><input type="text" name="network.ap.address" id="ipaddress"><br>
|
||||
<label for="netmask">Wi-Fi box netmask:</label><input type="text" name="network.ap.netmask" id="netmask"><br>
|
||||
<input type="button" name="create" value="Create" class="button" id="createAP"/>
|
||||
<span id="apModeState"></span><br/>
|
||||
<br/>
|
||||
<small>When you can't connect to your device, you can always use an ethernet cable and go to <a href="http://connect.doodle3d.com">connect.doodle3d.com</a>.</small>
|
||||
</fieldset>
|
||||
|
||||
<fieldset id="clientSettings">
|
||||
<legend>Client mode settings</legend>
|
||||
|
||||
<label for="wifiboxid">Wi-Fi box id*:</label><input type="text" name="network.cl.wifiboxid" id="wifiboxid"><br>
|
||||
<small>* Is used on <a href="http://connect.doodle3d.com">connect.doodle3d.com</a>. <br/>
|
||||
The text <em>%%MAC_ADDR_TAIL%%</em> will be replaced by the last 6 digits of your Doodle3D Wi-Fi box's MAC address.</small>
|
||||
<br>
|
||||
<label for="network">Network:</label>
|
||||
<select id="network" name="network.client.network">
|
||||
</select>
|
||||
<input type="button" name="refresh" value="Refresh" class="button" id="refreshNetworks"/><br>
|
||||
<label for="password" id="passwordLabel">Password:</label><input type="password" name="network.client.password" id="password"><br>
|
||||
<input type="button" name="connect" value="Connect" class="button" id="connectToNetwork"/>
|
||||
<span id="clientModeState"></span><br/>
|
||||
<br/>
|
||||
<small>When you can't connect to your device, you can always use an ethernet cable and go to <a href="http://connect.doodle3d.com">connect.doodle3d.com</a>.</small>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>GCODE settings</legend>
|
||||
<div class="startgcode_left">
|
||||
<label for="startgcode">Start:</label><br/>
|
||||
<textarea id="startgcode" class="gcode" name="printer.startgcode">
|
||||
</textarea>
|
||||
|
||||
</div>
|
||||
<div>
|
||||
<label for="endgcode">End:</label><br/>
|
||||
<textarea id="endgcode" class="gcode" name="printer.endgcode">
|
||||
</textarea>
|
||||
</div>
|
||||
<small>The text <em>{printingTemp}</em> will be replaced by the printing temperature and <em>{preheatTemp}</em> will be replaced by the preaheat temperature.</small>
|
||||
</fieldset>
|
||||
</form><br/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|