2013-01-02 15:33:37 +00:00
//~~ View models
2012-12-28 19:37:40 +00:00
function ConnectionViewModel ( ) {
var self = this ;
self . portOptions = ko . observableArray ( undefined ) ;
self . baudrateOptions = ko . observableArray ( undefined ) ;
self . selectedPort = ko . observable ( undefined ) ;
self . selectedBaudrate = ko . observable ( undefined ) ;
2013-01-01 20:04:00 +00:00
self . saveSettings = ko . observable ( undefined ) ;
2012-12-28 19:37:40 +00:00
self . isErrorOrClosed = ko . observable ( undefined ) ;
self . isOperational = ko . observable ( undefined ) ;
self . isPrinting = ko . observable ( undefined ) ;
self . isPaused = ko . observable ( undefined ) ;
self . isError = ko . observable ( undefined ) ;
self . isReady = ko . observable ( undefined ) ;
self . isLoading = ko . observable ( undefined ) ;
self . buttonText = ko . computed ( function ( ) {
if ( self . isErrorOrClosed ( ) )
return "Connect" ;
else
return "Disconnect" ;
} )
2012-12-29 18:34:55 +00:00
self . previousIsOperational = undefined ;
2013-01-01 20:04:00 +00:00
self . requestData = function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/connectionOptions" ,
method : "GET" ,
dataType : "json" ,
success : function ( response ) {
self . fromResponse ( response ) ;
}
} )
}
2012-12-28 19:37:40 +00:00
self . fromResponse = function ( response ) {
self . portOptions ( response . ports ) ;
self . baudrateOptions ( response . baudrates ) ;
if ( ! self . selectedPort ( ) && response . ports && response . ports . indexOf ( response . portPreference ) >= 0 )
self . selectedPort ( response . portPreference ) ;
if ( ! self . selectedBaudrate ( ) && response . baudrates && response . baudrates . indexOf ( response . baudratePreference ) >= 0 )
self . selectedBaudrate ( response . baudratePreference ) ;
2013-01-01 20:04:00 +00:00
self . saveSettings ( false ) ;
2012-12-28 19:37:40 +00:00
}
2013-01-11 23:00:58 +00:00
self . fromHistoryData = function ( data ) {
self . _processStateData ( data . state ) ;
}
2013-01-10 22:40:00 +00:00
self . fromCurrentData = function ( data ) {
self . _processStateData ( data . state ) ;
}
self . _processStateData = function ( data ) {
2012-12-29 18:34:55 +00:00
self . previousIsOperational = self . isOperational ( ) ;
2013-01-06 15:51:04 +00:00
self . isErrorOrClosed ( data . flags . closedOrError ) ;
self . isOperational ( data . flags . operational ) ;
self . isPaused ( data . flags . paused ) ;
self . isPrinting ( data . flags . printing ) ;
self . isError ( data . flags . error ) ;
self . isReady ( data . flags . ready ) ;
self . isLoading ( data . flags . loading ) ;
2012-12-29 18:34:55 +00:00
var connectionTab = $ ( "#connection" ) ;
if ( self . previousIsOperational != self . isOperational ( ) ) {
if ( self . isOperational ( ) && connectionTab . hasClass ( "in" ) ) {
// connection just got established, close connection tab for now
connectionTab . collapse ( "hide" ) ;
} else if ( ! connectionTab . hasClass ( "in" ) ) {
// connection just dropped, make sure connection tab is open
connectionTab . collapse ( "show" ) ;
}
}
2012-12-28 19:37:40 +00:00
}
self . connect = function ( ) {
if ( self . isErrorOrClosed ( ) ) {
2013-01-01 20:04:00 +00:00
var data = {
"port" : self . selectedPort ( ) ,
"baudrate" : self . selectedBaudrate ( )
} ;
if ( self . saveSettings ( ) )
data [ "save" ] = true ;
2012-12-28 19:37:40 +00:00
$ . ajax ( {
url : AJAX _BASEURL + "control/connect" ,
type : "POST" ,
dataType : "json" ,
2013-01-01 20:04:00 +00:00
data : data
2012-12-28 19:37:40 +00:00
} )
} else {
2013-01-01 20:04:00 +00:00
self . requestData ( ) ;
2012-12-28 19:37:40 +00:00
$ . ajax ( {
url : AJAX _BASEURL + "control/disconnect" ,
type : "POST" ,
dataType : "json"
} )
}
}
}
2012-12-25 19:49:10 +00:00
function PrinterStateViewModel ( ) {
var self = this ;
self . stateString = ko . observable ( undefined ) ;
self . isErrorOrClosed = ko . observable ( undefined ) ;
self . isOperational = ko . observable ( undefined ) ;
2012-12-26 14:03:34 +00:00
self . isPrinting = ko . observable ( undefined ) ;
self . isPaused = ko . observable ( undefined ) ;
self . isError = ko . observable ( undefined ) ;
self . isReady = ko . observable ( undefined ) ;
2012-12-28 19:37:40 +00:00
self . isLoading = ko . observable ( undefined ) ;
2012-12-25 19:49:10 +00:00
2012-12-28 19:37:40 +00:00
self . filename = ko . observable ( undefined ) ;
2012-12-25 19:49:10 +00:00
self . filament = ko . observable ( undefined ) ;
self . estimatedPrintTime = ko . observable ( undefined ) ;
self . printTime = ko . observable ( undefined ) ;
self . printTimeLeft = ko . observable ( undefined ) ;
self . currentLine = ko . observable ( undefined ) ;
self . totalLines = ko . observable ( undefined ) ;
self . currentHeight = ko . observable ( undefined ) ;
self . lineString = ko . computed ( function ( ) {
if ( ! self . totalLines ( ) )
return "-" ;
var currentLine = self . currentLine ( ) ? self . currentLine ( ) : "-" ;
return currentLine + " / " + self . totalLines ( ) ;
2012-12-26 14:03:34 +00:00
} ) ;
2012-12-25 19:49:10 +00:00
self . progress = ko . computed ( function ( ) {
if ( ! self . currentLine ( ) || ! self . totalLines ( ) )
return 0 ;
return Math . round ( self . currentLine ( ) * 100 / self . totalLines ( ) ) ;
} ) ;
2012-12-26 14:03:34 +00:00
self . pauseString = ko . computed ( function ( ) {
if ( self . isPaused ( ) )
return "Continue" ;
else
return "Pause" ;
} ) ;
2012-12-25 19:49:10 +00:00
2013-01-10 22:40:00 +00:00
self . fromCurrentData = function ( data ) {
2013-01-11 23:00:58 +00:00
self . _fromData ( data ) ;
2013-01-10 22:40:00 +00:00
}
self . fromHistoryData = function ( data ) {
2013-01-11 23:00:58 +00:00
self . _fromData ( data ) ;
}
self . _fromData = function ( data ) {
2013-01-10 22:40:00 +00:00
self . _processStateData ( data . state )
2013-01-11 23:00:58 +00:00
self . _processJobData ( data . job ) ;
self . _processGcodeData ( data . gcode ) ;
self . _processProgressData ( data . progress ) ;
self . _processZData ( data . currentZ ) ;
2013-01-10 22:40:00 +00:00
}
self . _processStateData = function ( data ) {
self . stateString ( data . stateString ) ;
2013-01-06 15:51:04 +00:00
self . isErrorOrClosed ( data . flags . closedOrError ) ;
self . isOperational ( data . flags . operational ) ;
self . isPaused ( data . flags . paused ) ;
self . isPrinting ( data . flags . printing ) ;
self . isError ( data . flags . error ) ;
self . isReady ( data . flags . ready ) ;
self . isLoading ( data . flags . loading ) ;
}
2013-01-10 22:40:00 +00:00
self . _processJobData = function ( data ) {
2013-01-06 15:51:04 +00:00
self . filename ( data . filename ) ;
2013-01-11 23:00:58 +00:00
self . totalLines ( data . lines ) ;
2013-01-06 15:51:04 +00:00
self . estimatedPrintTime ( data . estimatedPrintTime ) ;
self . filament ( data . filament ) ;
}
2013-01-10 22:40:00 +00:00
self . _processGcodeData = function ( data ) {
2013-01-10 20:02:47 +00:00
if ( self . isLoading ( ) ) {
2013-01-12 23:58:54 +00:00
var progress = Math . round ( data . progress * 100 ) ;
if ( data . mode == "loading" ) {
self . filename ( "Loading... (" + progress + "%)" ) ;
} else if ( data . mode == "parsing" ) {
self . filename ( "Parsing... (" + progress + "%)" ) ;
}
2013-01-10 20:02:47 +00:00
}
}
2013-01-10 22:40:00 +00:00
self . _processProgressData = function ( data ) {
2013-01-11 23:00:58 +00:00
self . currentLine ( data . progress ) ;
2013-01-06 15:51:04 +00:00
self . printTime ( data . printTime ) ;
self . printTimeLeft ( data . printTimeLeft ) ;
}
2013-01-10 22:40:00 +00:00
self . _processZData = function ( data ) {
2013-01-11 23:00:58 +00:00
self . currentHeight ( data ) ;
2013-01-06 15:51:04 +00:00
}
2012-12-25 19:49:10 +00:00
}
2013-02-23 17:47:01 +00:00
function TemperatureViewModel ( settingsViewModel ) {
2012-12-25 19:49:10 +00:00
var self = this ;
self . temp = ko . observable ( undefined ) ;
self . bedTemp = ko . observable ( undefined ) ;
2012-12-26 14:03:34 +00:00
self . targetTemp = ko . observable ( undefined ) ;
self . bedTargetTemp = ko . observable ( undefined ) ;
2012-12-28 19:37:40 +00:00
2012-12-26 14:03:34 +00:00
self . isErrorOrClosed = ko . observable ( undefined ) ;
self . isOperational = ko . observable ( undefined ) ;
self . isPrinting = ko . observable ( undefined ) ;
self . isPaused = ko . observable ( undefined ) ;
self . isError = ko . observable ( undefined ) ;
self . isReady = ko . observable ( undefined ) ;
2012-12-28 19:37:40 +00:00
self . isLoading = ko . observable ( undefined ) ;
2012-12-26 14:03:34 +00:00
2013-02-23 17:47:01 +00:00
self . temperature _profiles = settingsViewModel . temperature _profiles ;
2013-02-23 21:46:29 +00:00
self . setTempFromProfile = function ( profile ) {
if ( ! profile )
return ;
self . setTemp ( profile . extruder ) ;
}
self . setTemp = function ( temp ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/temperature" ,
type : "POST" ,
dataType : "json" ,
data : { temp : temp } ,
success : function ( ) { $ ( "#temp_newTemp" ) . val ( "" ) }
} )
} ;
self . setBedTempFromProfile = function ( profile ) {
if ( ! profile )
return ;
self . setBedTemp ( profile . bed ) ;
}
self . setBedTemp = function ( bedTemp ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/temperature" ,
type : "POST" ,
dataType : "json" ,
data : { bedTemp : bedTemp } ,
success : function ( ) { $ ( "#temp_newBedTemp" ) . val ( "" ) }
} )
} ;
2013-02-23 18:38:18 +00:00
2012-12-26 14:03:34 +00:00
self . tempString = ko . computed ( function ( ) {
if ( ! self . temp ( ) )
return "-" ;
2013-02-23 17:47:01 +00:00
return self . temp ( ) + " °C" ;
2012-12-26 14:03:34 +00:00
} ) ;
self . bedTempString = ko . computed ( function ( ) {
if ( ! self . bedTemp ( ) )
return "-" ;
2013-02-23 17:47:01 +00:00
return self . bedTemp ( ) + " °C" ;
2012-12-26 14:03:34 +00:00
} ) ;
self . targetTempString = ko . computed ( function ( ) {
if ( ! self . targetTemp ( ) )
return "-" ;
2013-02-23 17:47:01 +00:00
return self . targetTemp ( ) + " °C" ;
2012-12-26 14:03:34 +00:00
} ) ;
self . bedTargetTempString = ko . computed ( function ( ) {
if ( ! self . bedTargetTemp ( ) )
return "-" ;
2013-02-23 17:47:01 +00:00
return self . bedTargetTemp ( ) + " °C" ;
2012-12-26 14:03:34 +00:00
} ) ;
2012-12-25 19:49:10 +00:00
self . temperatures = [ ] ;
self . plotOptions = {
yaxis : {
min : 0 ,
max : 310 ,
ticks : 10
} ,
xaxis : {
2012-12-26 14:03:34 +00:00
mode : "time" ,
minTickSize : [ 2 , "minute" ] ,
tickFormatter : function ( val , axis ) {
2013-01-27 10:12:28 +00:00
if ( val == undefined || val == 0 )
return "" ; // we don't want to display the minutes since the epoch if not connected yet ;)
2013-01-22 16:44:20 +00:00
2013-03-03 15:57:35 +00:00
// current time in milliseconds in UTC
var timestampUtc = Date . now ( ) ;
2013-01-22 16:44:20 +00:00
2013-01-27 10:12:28 +00:00
// calculate difference in milliseconds
2013-01-22 16:44:20 +00:00
var diff = timestampUtc - val ;
2013-01-27 10:12:28 +00:00
// convert to minutes
2013-01-22 16:44:20 +00:00
var diffInMins = Math . round ( diff / ( 60 * 1000 ) ) ;
2012-12-26 14:03:34 +00:00
if ( diffInMins == 0 )
return "just now" ;
else
return "- " + diffInMins + " min" ;
}
2012-12-25 19:49:10 +00:00
} ,
legend : {
noColumns : 4
}
}
2013-01-10 22:40:00 +00:00
self . fromCurrentData = function ( data ) {
self . _processStateData ( data . state ) ;
self . _processTemperatureUpdateData ( data . temperatures ) ;
}
self . fromHistoryData = function ( data ) {
self . _processStateData ( data . state ) ;
self . _processTemperatureHistoryData ( data . temperatureHistory ) ;
}
self . _processStateData = function ( data ) {
2013-01-06 15:51:04 +00:00
self . isErrorOrClosed ( data . flags . closedOrError ) ;
self . isOperational ( data . flags . operational ) ;
self . isPaused ( data . flags . paused ) ;
self . isPrinting ( data . flags . printing ) ;
self . isError ( data . flags . error ) ;
self . isReady ( data . flags . ready ) ;
self . isLoading ( data . flags . loading ) ;
}
2013-01-10 22:40:00 +00:00
self . _processTemperatureUpdateData = function ( data ) {
2013-01-10 20:02:47 +00:00
if ( data . length == 0 )
return ;
self . temp ( data [ data . length - 1 ] . temp ) ;
self . bedTemp ( data [ data . length - 1 ] . bedTemp ) ;
self . targetTemp ( data [ data . length - 1 ] . targetTemp ) ;
2013-01-12 12:15:39 +00:00
self . bedTargetTemp ( data [ data . length - 1 ] . targetBedTemp ) ;
2013-01-06 20:19:39 +00:00
if ( ! self . temperatures )
self . temperatures = [ ] ;
if ( ! self . temperatures . actual )
self . temperatures . actual = [ ] ;
if ( ! self . temperatures . target )
self . temperatures . target = [ ] ;
if ( ! self . temperatures . actualBed )
self . temperatures . actualBed = [ ] ;
if ( ! self . temperatures . targetBed )
self . temperatures . targetBed = [ ] ;
2013-01-10 20:02:47 +00:00
for ( var i = 0 ; i < data . length ; i ++ ) {
self . temperatures . actual . push ( [ data [ i ] . currentTime , data [ i ] . temp ] )
self . temperatures . target . push ( [ data [ i ] . currentTime , data [ i ] . targetTemp ] )
self . temperatures . actualBed . push ( [ data [ i ] . currentTime , data [ i ] . bedTemp ] )
2013-01-12 12:15:39 +00:00
self . temperatures . targetBed . push ( [ data [ i ] . currentTime , data [ i ] . targetBedTemp ] )
2013-01-10 20:02:47 +00:00
}
2013-01-06 20:19:39 +00:00
self . temperatures . actual = self . temperatures . actual . slice ( - 300 ) ;
self . temperatures . target = self . temperatures . target . slice ( - 300 ) ;
self . temperatures . actualBed = self . temperatures . actualBed . slice ( - 300 ) ;
self . temperatures . targetBed = self . temperatures . targetBed . slice ( - 300 ) ;
2012-12-26 14:03:34 +00:00
2013-01-11 23:00:58 +00:00
self . updatePlot ( ) ;
2012-12-25 19:49:10 +00:00
}
2013-01-10 22:40:00 +00:00
self . _processTemperatureHistoryData = function ( data ) {
2013-01-06 20:19:39 +00:00
self . temperatures = data ;
2013-01-11 23:00:58 +00:00
self . updatePlot ( ) ;
2013-01-06 20:19:39 +00:00
}
2013-01-11 23:00:58 +00:00
self . updatePlot = function ( ) {
2012-12-25 19:49:10 +00:00
var data = [
{ label : "Actual" , color : "#FF4040" , data : self . temperatures . actual } ,
{ label : "Target" , color : "#FFA0A0" , data : self . temperatures . target } ,
{ label : "Bed Actual" , color : "#4040FF" , data : self . temperatures . actualBed } ,
{ label : "Bed Target" , color : "#A0A0FF" , data : self . temperatures . targetBed }
]
$ . plot ( $ ( "#temperature-graph" ) , data , self . plotOptions ) ;
}
}
2013-01-27 10:12:28 +00:00
function ControlsViewModel ( ) {
var self = this ;
self . isErrorOrClosed = ko . observable ( undefined ) ;
self . isOperational = ko . observable ( undefined ) ;
self . isPrinting = ko . observable ( undefined ) ;
self . isPaused = ko . observable ( undefined ) ;
self . isError = ko . observable ( undefined ) ;
self . isReady = ko . observable ( undefined ) ;
self . isLoading = ko . observable ( undefined ) ;
2013-02-09 23:40:06 +00:00
self . extrusionAmount = ko . observable ( undefined ) ;
2013-01-27 10:12:28 +00:00
self . controls = ko . observableArray ( [ ] ) ;
self . fromCurrentData = function ( data ) {
self . _processStateData ( data . state ) ;
}
self . fromHistoryData = function ( data ) {
self . _processStateData ( data . state ) ;
}
self . _processStateData = function ( data ) {
self . isErrorOrClosed ( data . flags . closedOrError ) ;
self . isOperational ( data . flags . operational ) ;
self . isPaused ( data . flags . paused ) ;
self . isPrinting ( data . flags . printing ) ;
self . isError ( data . flags . error ) ;
self . isReady ( data . flags . ready ) ;
self . isLoading ( data . flags . loading ) ;
}
self . requestData = function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/custom" ,
method : "GET" ,
dataType : "json" ,
success : function ( response ) {
self . _fromResponse ( response ) ;
}
} ) ;
}
self . _fromResponse = function ( response ) {
2013-01-27 17:28:11 +00:00
self . controls ( self . _enhanceControls ( response . controls ) ) ;
}
self . _enhanceControls = function ( controls ) {
for ( var i = 0 ; i < controls . length ; i ++ ) {
controls [ i ] = self . _enhanceControl ( controls [ i ] ) ;
}
return controls ;
}
self . _enhanceControl = function ( control ) {
2013-02-23 17:08:59 +00:00
if ( control . type == "parametric_command" || control . type == "parametric_commands" ) {
2013-01-27 17:28:11 +00:00
for ( var i = 0 ; i < control . input . length ; i ++ ) {
control . input [ i ] . value = control . input [ i ] . default ;
}
} else if ( control . type == "section" ) {
control . children = self . _enhanceControls ( control . children ) ;
}
return control ;
}
2013-02-10 16:00:47 +00:00
self . sendJogCommand = function ( axis , multiplier , distance ) {
if ( typeof distance === "undefined" )
distance = $ ( '#jog_distance button.active' ) . data ( 'distance' ) ;
2013-01-27 17:28:11 +00:00
$ . ajax ( {
url : AJAX _BASEURL + "control/jog" ,
type : "POST" ,
dataType : "json" ,
2013-02-10 16:00:47 +00:00
data : axis + "=" + ( distance * multiplier )
2013-01-27 17:28:11 +00:00
} )
}
self . sendHomeCommand = function ( axis ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/jog" ,
type : "POST" ,
dataType : "json" ,
data : "home" + axis
} )
2013-01-27 10:12:28 +00:00
}
2013-02-09 23:40:06 +00:00
self . sendExtrudeCommand = function ( ) {
self . _sendECommand ( 1 ) ;
}
self . sendRetractCommand = function ( ) {
self . _sendECommand ( - 1 ) ;
}
self . _sendECommand = function ( dir ) {
var length = self . extrusionAmount ( ) ;
if ( ! length )
length = 5 ;
$ . ajax ( {
url : AJAX _BASEURL + "control/jog" ,
type : "POST" ,
dataType : "json" ,
data : "extrude=" + ( dir * length )
} )
}
2013-01-27 10:12:28 +00:00
self . sendCustomCommand = function ( command ) {
2013-01-27 17:28:11 +00:00
if ( ! command )
return ;
2013-02-23 17:08:59 +00:00
var data = undefined ;
if ( command . type == "command" || command . type == "parametric_command" ) {
// single command
data = { "command" : command . command } ;
} else if ( command . type == "commands" || command . type == "parametric_commands" ) {
// multi command
data = { "commands" : command . commands } ;
}
if ( command . type == "parametric_command" || command . type == "parametric_commands" ) {
// parametric command(s)
data [ "parameters" ] = { } ;
2013-01-27 17:28:11 +00:00
for ( var i = 0 ; i < command . input . length ; i ++ ) {
2013-02-23 17:08:59 +00:00
data [ "parameters" ] [ command . input [ i ] . parameter ] = command . input [ i ] . value ;
2013-01-27 17:28:11 +00:00
}
2013-01-27 10:12:28 +00:00
}
2013-02-23 17:08:59 +00:00
if ( ! data )
return ;
$ . ajax ( {
url : AJAX _BASEURL + "control/command" ,
type : "POST" ,
dataType : "json" ,
contentType : "application/json; charset=UTF-8" ,
data : JSON . stringify ( data )
} )
2013-01-27 10:12:28 +00:00
}
self . displayMode = function ( customControl ) {
switch ( customControl . type ) {
case "section" :
return "customControls_sectionTemplate" ;
case "command" :
2013-02-23 17:08:59 +00:00
case "commands" :
2013-01-27 10:12:28 +00:00
return "customControls_commandTemplate" ;
2013-01-27 17:52:25 +00:00
case "parametric_command" :
2013-02-23 17:08:59 +00:00
case "parametric_commands" :
2013-01-27 17:52:25 +00:00
return "customControls_parametricCommandTemplate" ;
2013-01-27 10:12:28 +00:00
default :
return "customControls_emptyTemplate" ;
}
}
}
2012-12-29 14:41:23 +00:00
function SpeedViewModel ( ) {
var self = this ;
self . outerWall = ko . observable ( undefined ) ;
self . innerWall = ko . observable ( undefined ) ;
self . fill = ko . observable ( undefined ) ;
self . support = ko . observable ( undefined ) ;
self . isErrorOrClosed = ko . observable ( undefined ) ;
self . isOperational = ko . observable ( undefined ) ;
self . isPrinting = ko . observable ( undefined ) ;
self . isPaused = ko . observable ( undefined ) ;
self . isError = ko . observable ( undefined ) ;
self . isReady = ko . observable ( undefined ) ;
self . isLoading = ko . observable ( undefined ) ;
2013-01-11 23:00:58 +00:00
self . _fromCurrentData = function ( data ) {
self . _processStateData ( data . state ) ;
2012-12-29 14:41:23 +00:00
}
2013-01-11 23:00:58 +00:00
self . _fromHistoryData = function ( data ) {
self . _processStateData ( data . state ) ;
}
self . _processStateData = function ( data ) {
self . isErrorOrClosed ( data . flags . closedOrError ) ;
self . isOperational ( data . flags . operational ) ;
self . isPaused ( data . flags . paused ) ;
self . isPrinting ( data . flags . printing ) ;
self . isError ( data . flags . error ) ;
self . isReady ( data . flags . ready ) ;
self . isLoading ( data . flags . loading ) ;
}
2013-01-27 17:28:11 +00:00
self . requestData = function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/speed" ,
type : "GET" ,
dataType : "json" ,
success : self . _fromResponse
} ) ;
}
self . _fromResponse = function ( response ) {
if ( response . feedrate ) {
self . outerWall ( response . feedrate . outerWall ) ;
self . innerWall ( response . feedrate . innerWall ) ;
self . fill ( response . feedrate . fill ) ;
self . support ( response . feedrate . support ) ;
} else {
self . outerWall ( undefined ) ;
self . innerWall ( undefined ) ;
self . fill ( undefined ) ;
self . support ( undefined ) ;
}
2013-01-11 23:00:58 +00:00
}
2012-12-29 14:41:23 +00:00
}
2012-12-25 19:49:10 +00:00
function TerminalViewModel ( ) {
var self = this ;
2013-01-06 20:19:39 +00:00
self . log = [ ] ;
2012-12-25 19:49:10 +00:00
2013-01-06 15:51:04 +00:00
self . isErrorOrClosed = ko . observable ( undefined ) ;
self . isOperational = ko . observable ( undefined ) ;
self . isPrinting = ko . observable ( undefined ) ;
self . isPaused = ko . observable ( undefined ) ;
self . isError = ko . observable ( undefined ) ;
self . isReady = ko . observable ( undefined ) ;
self . isLoading = ko . observable ( undefined ) ;
2013-01-20 13:34:44 +00:00
self . autoscrollEnabled = ko . observable ( true ) ;
2013-01-11 23:00:58 +00:00
self . fromCurrentData = function ( data ) {
self . _processStateData ( data . state ) ;
self . _processCurrentLogData ( data . logs ) ;
}
self . fromHistoryData = function ( data ) {
self . _processStateData ( data . state ) ;
self . _processHistoryLogData ( data . logHistory ) ;
2013-01-06 15:51:04 +00:00
}
2012-12-25 19:49:10 +00:00
2013-01-11 23:00:58 +00:00
self . _processCurrentLogData = function ( data ) {
2013-01-06 20:19:39 +00:00
if ( ! self . log )
self . log = [ ]
2013-01-11 23:00:58 +00:00
self . log = self . log . concat ( data )
2013-01-06 20:19:39 +00:00
self . updateOutput ( ) ;
}
2013-01-11 23:00:58 +00:00
self . _processHistoryLogData = function ( data ) {
2013-01-06 20:19:39 +00:00
self . log = data ;
2012-12-25 19:49:10 +00:00
self . updateOutput ( ) ;
}
2013-01-11 23:00:58 +00:00
self . _processStateData = function ( data ) {
self . isErrorOrClosed ( data . flags . closedOrError ) ;
self . isOperational ( data . flags . operational ) ;
self . isPaused ( data . flags . paused ) ;
self . isPrinting ( data . flags . printing ) ;
self . isError ( data . flags . error ) ;
self . isReady ( data . flags . ready ) ;
self . isLoading ( data . flags . loading ) ;
}
2012-12-25 19:49:10 +00:00
self . updateOutput = function ( ) {
2013-01-06 20:19:39 +00:00
if ( ! self . log )
return ;
2012-12-28 19:37:40 +00:00
var output = "" ;
2012-12-25 19:49:10 +00:00
for ( var i = 0 ; i < self . log . length ; i ++ ) {
2012-12-28 19:37:40 +00:00
output += self . log [ i ] + "\n" ;
2012-12-25 19:49:10 +00:00
}
var container = $ ( "#terminal-output" ) ;
2012-12-26 14:03:34 +00:00
container . text ( output ) ;
2012-12-25 19:49:10 +00:00
2013-01-20 13:34:44 +00:00
if ( self . autoscrollEnabled ( ) ) {
2012-12-25 19:49:10 +00:00
container . scrollTop ( container [ 0 ] . scrollHeight - container . height ( ) )
}
}
}
function GcodeFilesViewModel ( ) {
var self = this ;
2013-03-06 22:27:16 +00:00
// initialize list helper
self . listHelper = new ItemListHelper (
"gcodeFiles" ,
{
"name" : function ( a , b ) {
// sorts ascending
if ( a [ "name" ] . toLocaleLowerCase ( ) < b [ "name" ] . toLocaleLowerCase ( ) ) return - 1 ;
if ( a [ "name" ] . toLocaleLowerCase ( ) > b [ "name" ] . toLocaleLowerCase ( ) ) return 1 ;
return 0 ;
} ,
"upload" : function ( a , b ) {
// sorts descending
if ( a [ "date" ] > b [ "date" ] ) return - 1 ;
if ( a [ "date" ] < b [ "date" ] ) return 1 ;
return 0 ;
} ,
"size" : function ( a , b ) {
// sorts descending
if ( a [ "bytes" ] > b [ "bytes" ] ) return - 1 ;
if ( a [ "bytes" ] < b [ "bytes" ] ) return 1 ;
return 0 ;
2013-01-20 12:43:29 +00:00
}
2013-03-06 22:27:16 +00:00
} ,
{
"printed" : function ( file ) {
return ! ( file [ "prints" ] && file [ "prints" ] [ "success" ] && file [ "prints" ] [ "success" ] > 0 ) ;
2013-01-20 12:43:29 +00:00
}
2013-03-06 22:27:16 +00:00
} ,
"name" ,
[ ] ,
CONFIG _GCODEFILESPERPAGE
)
2012-12-25 19:49:10 +00:00
2013-01-01 20:04:00 +00:00
self . requestData = function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "gcodefiles" ,
method : "GET" ,
dataType : "json" ,
success : function ( response ) {
self . fromResponse ( response ) ;
}
} ) ;
}
2012-12-25 19:49:10 +00:00
self . fromResponse = function ( response ) {
2013-03-06 22:27:16 +00:00
self . listHelper . updateItems ( response . files ) ;
2013-02-04 21:24:32 +00:00
if ( response . filename ) {
// got a file to scroll to
2013-03-06 22:27:16 +00:00
self . listHelper . switchToItem ( function ( item ) { return item . name == response . filename } ) ;
2013-02-04 21:24:32 +00:00
}
2012-12-25 19:49:10 +00:00
}
2013-01-20 12:43:29 +00:00
self . loadFile = function ( filename ) {
2012-12-25 19:49:10 +00:00
$ . ajax ( {
url : AJAX _BASEURL + "gcodefiles/load" ,
type : "POST" ,
dataType : "json" ,
data : { filename : filename }
} )
}
2013-02-04 20:41:02 +00:00
self . removeFile = function ( filename ) {
2012-12-25 19:49:10 +00:00
$ . ajax ( {
url : AJAX _BASEURL + "gcodefiles/delete" ,
type : "POST" ,
dataType : "json" ,
data : { filename : filename } ,
success : self . fromResponse
} )
}
2013-01-20 12:43:29 +00:00
2013-01-30 19:56:17 +00:00
self . getPopoverContent = function ( data ) {
var output = "<p><strong>Uploaded:</strong> " + data [ "date" ] + "</p>" ;
if ( data [ "gcodeAnalysis" ] ) {
output += "<p>" ;
output += "<strong>Filament:</strong> " + data [ "gcodeAnalysis" ] [ "filament" ] + "<br>" ;
output += "<strong>Estimated Print Time:</strong> " + data [ "gcodeAnalysis" ] [ "estimatedPrintTime" ] ;
output += "</p>" ;
}
if ( data [ "prints" ] && data [ "prints" ] [ "last" ] ) {
output += "<p>" ;
output += "<strong>Last Print:</strong> <span class=\"" + ( data [ "prints" ] [ "last" ] [ "success" ] ? "text-success" : "text-error" ) + "\">" + data [ "prints" ] [ "last" ] [ "date" ] + "</span>" ;
output += "</p>" ;
}
return output ;
}
self . getSuccessClass = function ( data ) {
if ( ! data [ "prints" ] || ! data [ "prints" ] [ "last" ] ) {
return "" ;
}
return data [ "prints" ] [ "last" ] [ "success" ] ? "text-success" : "text-error" ;
}
2012-12-25 19:49:10 +00:00
}
2013-01-03 14:25:20 +00:00
function WebcamViewModel ( ) {
var self = this ;
self . timelapseType = ko . observable ( undefined ) ;
self . timelapseTimedInterval = ko . observable ( undefined ) ;
self . isErrorOrClosed = ko . observable ( undefined ) ;
self . isOperational = ko . observable ( undefined ) ;
self . isPrinting = ko . observable ( undefined ) ;
self . isPaused = ko . observable ( undefined ) ;
self . isError = ko . observable ( undefined ) ;
self . isReady = ko . observable ( undefined ) ;
self . isLoading = ko . observable ( undefined ) ;
self . intervalInputEnabled = ko . computed ( function ( ) {
return ( "timed" == self . timelapseType ( ) ) ;
} )
self . isOperational . subscribe ( function ( newValue ) {
self . requestData ( ) ;
} )
2013-03-06 22:27:16 +00:00
// initialize list helper
self . listHelper = new ItemListHelper (
"timelapseFiles" ,
{
"name" : function ( a , b ) {
// sorts ascending
if ( a [ "name" ] . toLocaleLowerCase ( ) < b [ "name" ] . toLocaleLowerCase ( ) ) return - 1 ;
if ( a [ "name" ] . toLocaleLowerCase ( ) > b [ "name" ] . toLocaleLowerCase ( ) ) return 1 ;
return 0 ;
} ,
"creation" : function ( a , b ) {
// sorts descending
if ( a [ "date" ] > b [ "date" ] ) return - 1 ;
if ( a [ "date" ] < b [ "date" ] ) return 1 ;
return 0 ;
} ,
"size" : function ( a , b ) {
// sorts descending
if ( a [ "bytes" ] > b [ "bytes" ] ) return - 1 ;
if ( a [ "bytes" ] < b [ "bytes" ] ) return 1 ;
return 0 ;
}
} ,
{
} ,
"name" ,
[ ] ,
CONFIG _TIMELAPSEFILESPERPAGE
)
2013-01-03 14:25:20 +00:00
self . requestData = function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "timelapse" ,
type : "GET" ,
dataType : "json" ,
success : self . fromResponse
2013-01-06 15:51:04 +00:00
} ) ;
2013-01-27 17:28:11 +00:00
$ ( "#webcam_image" ) . attr ( "src" , CONFIG _WEBCAM _STREAM + "?" + new Date ( ) . getTime ( ) ) ;
2013-01-03 14:25:20 +00:00
}
self . fromResponse = function ( response ) {
2013-03-06 22:27:16 +00:00
self . timelapseType ( response . type ) ;
self . listHelper . updateItems ( response . files ) ;
2013-01-03 14:25:20 +00:00
if ( response . type == "timed" && response . config && response . config . interval ) {
self . timelapseTimedInterval ( response . config . interval )
} else {
self . timelapseTimedInterval ( undefined )
}
}
2013-01-11 23:00:58 +00:00
self . fromCurrentData = function ( data ) {
self . _processStateData ( data . state ) ;
}
self . fromHistoryData = function ( data ) {
self . _processStateData ( data . state ) ;
}
self . _processStateData = function ( data ) {
2013-01-06 15:51:04 +00:00
self . isErrorOrClosed ( data . flags . closedOrError ) ;
self . isOperational ( data . flags . operational ) ;
self . isPaused ( data . flags . paused ) ;
self . isPrinting ( data . flags . printing ) ;
self . isError ( data . flags . error ) ;
self . isReady ( data . flags . ready ) ;
self . isLoading ( data . flags . loading ) ;
2013-01-03 14:25:20 +00:00
}
2013-01-04 12:11:00 +00:00
self . removeFile = function ( ) {
var filename = this . name ;
$ . ajax ( {
url : AJAX _BASEURL + "timelapse/" + filename ,
type : "DELETE" ,
dataType : "json" ,
success : self . requestData
} )
}
2013-01-03 14:25:20 +00:00
self . save = function ( ) {
var data = {
"type" : self . timelapseType ( )
}
if ( self . timelapseType ( ) == "timed" ) {
data [ "interval" ] = self . timelapseTimedInterval ( ) ;
}
$ . ajax ( {
2013-01-04 12:11:00 +00:00
url : AJAX _BASEURL + "timelapse/config" ,
2013-01-03 14:25:20 +00:00
type : "POST" ,
dataType : "json" ,
data : data ,
success : self . fromResponse
} )
}
}
2013-02-02 11:36:43 +00:00
function GcodeViewModel ( ) {
var self = this ;
2013-02-02 13:24:11 +00:00
self . loadedFilename = undefined ;
self . status = 'idle' ;
2013-02-02 16:45:36 +00:00
self . enabled = false ;
self . initialize = function ( ) {
self . enabled = true ;
GCODE . ui . initHandlers ( ) ;
}
2013-02-02 13:24:11 +00:00
self . loadFile = function ( filename ) {
2013-02-03 21:01:11 +00:00
if ( self . status == 'idle' ) {
2013-02-02 13:24:11 +00:00
self . status = 'request' ;
$ . ajax ( {
2013-02-03 21:01:11 +00:00
url : AJAX _BASEURL + "gcodefiles/" + filename ,
2013-02-02 13:24:11 +00:00
type : "GET" ,
success : function ( response , rstatus ) {
if ( rstatus === 'success' ) {
self . showGCodeViewer ( response , rstatus ) ;
self . loadedFilename = filename ;
self . status = 'idle' ;
}
} ,
error : function ( ) {
self . status = 'idle' ;
}
} )
}
}
2013-02-03 21:01:11 +00:00
self . showGCodeViewer = function ( response , rstatus ) {
2013-02-02 13:24:11 +00:00
var par = { } ;
par . target = { } ;
par . target . result = response ;
GCODE . gCodeReader . loadFile ( par ) ;
}
2013-02-02 11:36:43 +00:00
self . fromHistoryData = function ( data ) {
2013-02-02 13:24:11 +00:00
self . _processData ( data ) ;
2013-02-02 11:36:43 +00:00
}
self . fromCurrentData = function ( data ) {
2013-02-02 13:24:11 +00:00
self . _processData ( data ) ;
2013-02-02 11:36:43 +00:00
}
2013-02-02 13:24:11 +00:00
self . _processData = function ( data ) {
2013-02-02 16:45:36 +00:00
if ( ! self . enabled ) return ;
2013-02-03 21:01:11 +00:00
if ( self . loadedFilename == data . job . filename ) {
2013-02-02 13:24:11 +00:00
var cmdIndex = GCODE . gCodeReader . getLinesCmdIndex ( data . progress . progress ) ;
if ( cmdIndex ) {
GCODE . renderer . render ( cmdIndex . layer , 0 , cmdIndex . cmd ) ;
GCODE . ui . updateLayerInfo ( cmdIndex . layer ) ;
}
2013-02-03 21:01:11 +00:00
} else if ( data . job . filename ) {
2013-02-02 13:24:11 +00:00
self . loadFile ( data . job . filename ) ;
2013-02-02 11:36:43 +00:00
}
}
}
2013-02-17 21:30:34 +00:00
function SettingsViewModel ( ) {
var self = this ;
2013-03-02 10:56:32 +00:00
self . appearance _name = ko . observable ( undefined ) ;
self . appearance _color = ko . observable ( undefined ) ;
/* I did attempt to allow arbitrary gradients but cross browser support via knockout or jquery was going to be horrible */
2013-03-06 22:27:16 +00:00
self . appearance _available _colors = ko . observable ( [ "default" , "red" , "orange" , "yellow" , "green" , "blue" , "violet" ] ) ;
2013-03-02 10:56:32 +00:00
2013-02-17 21:30:34 +00:00
self . printer _movementSpeedX = ko . observable ( undefined ) ;
self . printer _movementSpeedY = ko . observable ( undefined ) ;
self . printer _movementSpeedZ = ko . observable ( undefined ) ;
self . printer _movementSpeedE = ko . observable ( undefined ) ;
self . webcam _streamUrl = ko . observable ( undefined ) ;
self . webcam _snapshotUrl = ko . observable ( undefined ) ;
self . webcam _ffmpegPath = ko . observable ( undefined ) ;
self . webcam _bitrate = ko . observable ( undefined ) ;
2013-03-08 23:23:52 +00:00
self . webcam _watermark = ko . observable ( undefined ) ;
2013-02-17 21:30:34 +00:00
self . feature _gcodeViewer = ko . observable ( undefined ) ;
self . feature _waitForStart = ko . observable ( undefined ) ;
self . folder _uploads = ko . observable ( undefined ) ;
self . folder _timelapse = ko . observable ( undefined ) ;
self . folder _timelapseTmp = ko . observable ( undefined ) ;
self . folder _logs = ko . observable ( undefined ) ;
2013-02-23 17:59:27 +00:00
self . temperature _profiles = ko . observableArray ( undefined ) ;
2013-03-10 16:04:05 +00:00
self . system _actions = ko . observableArray ( [ ] ) ;
2013-02-23 17:59:27 +00:00
self . addTemperatureProfile = function ( ) {
self . temperature _profiles . push ( { name : "New" , extruder : 0 , bed : 0 } ) ;
} ;
self . removeTemperatureProfile = function ( profile ) {
self . temperature _profiles . remove ( profile ) ;
} ;
2013-02-23 01:09:30 +00:00
2013-02-17 21:30:34 +00:00
self . requestData = function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "settings" ,
type : "GET" ,
dataType : "json" ,
success : self . fromResponse
} )
}
self . fromResponse = function ( response ) {
2013-03-02 10:56:32 +00:00
self . appearance _name ( response . appearance . name ) ;
self . appearance _color ( response . appearance . color ) ;
2013-02-17 21:30:34 +00:00
self . printer _movementSpeedX ( response . printer . movementSpeedX ) ;
self . printer _movementSpeedY ( response . printer . movementSpeedY ) ;
self . printer _movementSpeedZ ( response . printer . movementSpeedZ ) ;
self . printer _movementSpeedE ( response . printer . movementSpeedE ) ;
self . webcam _streamUrl ( response . webcam . streamUrl ) ;
self . webcam _snapshotUrl ( response . webcam . snapshotUrl ) ;
self . webcam _ffmpegPath ( response . webcam . ffmpegPath ) ;
self . webcam _bitrate ( response . webcam . bitrate ) ;
2013-03-08 23:23:52 +00:00
self . webcam _watermark ( response . webcam . watermark ) ;
2013-02-17 21:30:34 +00:00
self . feature _gcodeViewer ( response . feature . gcodeViewer ) ;
self . feature _waitForStart ( response . feature . waitForStart ) ;
self . folder _uploads ( response . folder . uploads ) ;
self . folder _timelapse ( response . folder . timelapse ) ;
self . folder _timelapseTmp ( response . folder . timelapseTmp ) ;
self . folder _logs ( response . folder . logs ) ;
2013-02-23 01:09:30 +00:00
2013-02-23 17:47:01 +00:00
self . temperature _profiles ( response . temperature . profiles ) ;
2013-03-10 16:04:05 +00:00
self . system _actions ( response . system . actions ) ;
2013-02-17 21:30:34 +00:00
}
self . saveData = function ( ) {
var data = {
2013-03-02 10:56:32 +00:00
"appearance" : {
"name" : self . appearance _name ( ) ,
"color" : self . appearance _color ( )
} ,
2013-02-17 21:30:34 +00:00
"printer" : {
"movementSpeedX" : self . printer _movementSpeedX ( ) ,
"movementSpeedY" : self . printer _movementSpeedY ( ) ,
"movementSpeedZ" : self . printer _movementSpeedZ ( ) ,
"movementSpeedE" : self . printer _movementSpeedE ( )
} ,
"webcam" : {
"streamUrl" : self . webcam _streamUrl ( ) ,
"snapshotUrl" : self . webcam _snapshotUrl ( ) ,
"ffmpegPath" : self . webcam _ffmpegPath ( ) ,
2013-03-08 23:23:52 +00:00
"bitrate" : self . webcam _bitrate ( ) ,
"watermark" : self . webcam _watermark ( )
2013-02-17 21:30:34 +00:00
} ,
"feature" : {
"gcodeViewer" : self . feature _gcodeViewer ( ) ,
"waitForStart" : self . feature _waitForStart ( )
} ,
"folder" : {
"uploads" : self . folder _uploads ( ) ,
"timelapse" : self . folder _timelapse ( ) ,
"timelapseTmp" : self . folder _timelapseTmp ( ) ,
"logs" : self . folder _logs ( )
2013-02-23 01:09:30 +00:00
} ,
"temperature" : {
2013-02-23 21:46:29 +00:00
"profiles" : self . temperature _profiles ( )
2013-03-10 16:04:05 +00:00
} ,
"system" : {
"actions" : self . system _actions ( )
2013-02-23 21:46:29 +00:00
}
2013-02-17 21:30:34 +00:00
}
$ . ajax ( {
url : AJAX _BASEURL + "settings" ,
type : "POST" ,
dataType : "json" ,
contentType : "application/json; charset=UTF-8" ,
data : JSON . stringify ( data ) ,
success : function ( response ) {
self . fromResponse ( response ) ;
$ ( "#settings_dialog" ) . modal ( "hide" ) ;
}
} )
}
}
2013-03-10 16:04:05 +00:00
function NavigationViewModel ( appearanceViewModel , settingsViewModel ) {
var self = this ;
self . appearance = appearanceViewModel ;
self . systemActions = settingsViewModel . system _actions ;
self . triggerAction = function ( action ) {
var callback = function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "system" ,
type : "POST" ,
dataType : "json" ,
data : "action=" + action . action ,
success : function ( ) {
$ . pnotify ( { title : "Success" , text : "The command \"" + action . name + "\" executed successfully" , type : "success" } ) ;
} ,
error : function ( jqXHR , textStatus , errorThrown ) {
$ . pnotify ( { title : "Error" , text : "<p>The command \"" + action . name + "\" could not be executed.</p><p>Reason: <pre>" + jqXHR . responseText + "</pre></p>" , type : "error" } ) ;
}
} )
}
if ( action . confirm ) {
$ ( "#confirmation_dialog .confirmation_dialog_message" ) . text ( action . confirm ) ;
$ ( "#confirmation_dialog .confirmation_dialog_acknowledge" ) . click ( function ( e ) { e . preventDefault ( ) ; $ ( "#confirmation_dialog" ) . modal ( "hide" ) ; callback ( ) ; } ) ;
$ ( "#confirmation_dialog" ) . modal ( "show" ) ;
} else {
callback ( ) ;
}
}
}
2013-02-03 20:38:00 +00:00
function DataUpdater ( connectionViewModel , printerStateViewModel , temperatureViewModel , controlsViewModel , speedViewModel , terminalViewModel , gcodeFilesViewModel , webcamViewModel , gcodeViewModel ) {
2012-12-25 19:49:10 +00:00
var self = this ;
2012-12-28 19:37:40 +00:00
self . connectionViewModel = connectionViewModel ;
2012-12-25 19:49:10 +00:00
self . printerStateViewModel = printerStateViewModel ;
self . temperatureViewModel = temperatureViewModel ;
2013-01-27 10:12:28 +00:00
self . controlsViewModel = controlsViewModel ;
2012-12-25 19:49:10 +00:00
self . terminalViewModel = terminalViewModel ;
2012-12-29 14:41:23 +00:00
self . speedViewModel = speedViewModel ;
2013-02-03 20:14:22 +00:00
self . gcodeFilesViewModel = gcodeFilesViewModel ;
2013-01-03 14:25:20 +00:00
self . webcamViewModel = webcamViewModel ;
2013-02-02 11:36:43 +00:00
self . gcodeViewModel = gcodeViewModel ;
2012-12-25 19:49:10 +00:00
2013-01-11 23:00:58 +00:00
self . _socket = io . connect ( ) ;
self . _socket . on ( "connect" , function ( ) {
2013-01-06 21:10:59 +00:00
if ( $ ( "#offline_overlay" ) . is ( ":visible" ) ) {
$ ( "#offline_overlay" ) . hide ( ) ;
self . webcamViewModel . requestData ( ) ;
}
} )
2013-01-11 23:00:58 +00:00
self . _socket . on ( "disconnect" , function ( ) {
2013-01-13 17:28:55 +00:00
$ ( "#offline_overlay_message" ) . html (
"The server appears to be offline, at least I'm not getting any response from it. I'll try to reconnect " +
"automatically <strong>over the next couple of minutes</strong>, however you are welcome to try a manual reconnect " +
"anytime using the button below."
) ;
2013-01-06 21:10:59 +00:00
if ( ! $ ( "#offline_overlay" ) . is ( ":visible" ) )
$ ( "#offline_overlay" ) . show ( ) ;
} )
2013-01-13 17:28:55 +00:00
self . _socket . on ( "reconnect_failed" , function ( ) {
$ ( "#offline_overlay_message" ) . html (
"The server appears to be offline, at least I'm not getting any response from it. I <strong>could not reconnect automatically</strong>, " +
"but you may try a manual reconnect using the button below."
) ;
} )
2013-01-11 23:00:58 +00:00
self . _socket . on ( "history" , function ( data ) {
self . connectionViewModel . fromHistoryData ( data ) ;
2013-01-10 22:40:00 +00:00
self . printerStateViewModel . fromHistoryData ( data ) ;
self . temperatureViewModel . fromHistoryData ( data ) ;
2013-01-27 10:12:28 +00:00
self . controlsViewModel . fromHistoryData ( data ) ;
2013-01-11 23:00:58 +00:00
self . terminalViewModel . fromHistoryData ( data ) ;
self . webcamViewModel . fromHistoryData ( data ) ;
2013-02-02 11:36:43 +00:00
self . gcodeViewModel . fromHistoryData ( data ) ;
2013-01-10 22:40:00 +00:00
} )
2013-01-11 23:00:58 +00:00
self . _socket . on ( "current" , function ( data ) {
2013-01-10 22:40:00 +00:00
self . connectionViewModel . fromCurrentData ( data ) ;
self . printerStateViewModel . fromCurrentData ( data ) ;
self . temperatureViewModel . fromCurrentData ( data ) ;
2013-01-27 10:12:28 +00:00
self . controlsViewModel . fromCurrentData ( data ) ;
2013-01-11 23:00:58 +00:00
self . terminalViewModel . fromCurrentData ( data ) ;
self . webcamViewModel . fromCurrentData ( data ) ;
2013-02-02 11:36:43 +00:00
self . gcodeViewModel . fromCurrentData ( data ) ;
2013-01-06 20:19:39 +00:00
} )
2013-02-03 20:14:22 +00:00
self . _socket . on ( "updateTrigger" , function ( type ) {
if ( type == "gcodeFiles" ) {
gcodeFilesViewModel . requestData ( ) ;
}
} )
2013-01-11 23:00:58 +00:00
self . reconnect = function ( ) {
self . _socket . socket . connect ( ) ;
}
2012-12-25 19:49:10 +00:00
}
2013-03-06 22:27:16 +00:00
function ItemListHelper ( listType , supportedSorting , supportedFilters , defaultSorting , defaultFilters , filesPerPage ) {
var self = this ;
self . listType = listType ;
self . supportedSorting = supportedSorting ;
self . supportedFilters = supportedFilters ;
self . defaultSorting = defaultSorting ;
self . defaultFilters = defaultFilters ;
self . allItems = [ ] ;
self . items = ko . observableArray ( [ ] ) ;
self . pageSize = ko . observable ( filesPerPage ) ;
self . currentPage = ko . observable ( 0 ) ;
self . currentSorting = ko . observable ( self . defaultSorting ) ;
self . currentFilters = ko . observableArray ( self . defaultFilters ) ;
//~~ item handling
self . updateItems = function ( items ) {
self . allItems = items ;
self . _updateItems ( ) ;
}
//~~ pagination
self . paginatedItems = ko . dependentObservable ( function ( ) {
if ( self . items ( ) == undefined ) {
return [ ] ;
} else {
var from = Math . max ( self . currentPage ( ) * self . pageSize ( ) , 0 ) ;
var to = Math . min ( from + self . pageSize ( ) , self . items ( ) . length ) ;
return self . items ( ) . slice ( from , to ) ;
}
} )
self . lastPage = ko . dependentObservable ( function ( ) {
return Math . ceil ( self . items ( ) . length / self . pageSize ( ) ) - 1 ;
} )
self . pages = ko . dependentObservable ( function ( ) {
var pages = [ ] ;
if ( self . lastPage ( ) < 7 ) {
for ( var i = 0 ; i < self . lastPage ( ) + 1 ; i ++ ) {
pages . push ( { number : i , text : i + 1 } ) ;
}
} else {
pages . push ( { number : 0 , text : 1 } ) ;
if ( self . currentPage ( ) < 5 ) {
for ( var i = 1 ; i < 5 ; i ++ ) {
pages . push ( { number : i , text : i + 1 } ) ;
}
pages . push ( { number : - 1 , text : "…" } ) ;
} else if ( self . currentPage ( ) > self . lastPage ( ) - 5 ) {
pages . push ( { number : - 1 , text : "…" } ) ;
for ( var i = self . lastPage ( ) - 4 ; i < self . lastPage ( ) ; i ++ ) {
pages . push ( { number : i , text : i + 1 } ) ;
}
} else {
pages . push ( { number : - 1 , text : "…" } ) ;
for ( var i = self . currentPage ( ) - 1 ; i <= self . currentPage ( ) + 1 ; i ++ ) {
pages . push ( { number : i , text : i + 1 } ) ;
}
pages . push ( { number : - 1 , text : "…" } ) ;
}
pages . push ( { number : self . lastPage ( ) , text : self . lastPage ( ) + 1 } )
}
return pages ;
} )
self . switchToItem = function ( matcher ) {
var pos = - 1 ;
var itemList = self . items ( ) ;
for ( var i = 0 ; i < itemList . length ; i ++ ) {
if ( matcher ( itemList [ i ] ) ) {
pos = i ;
break ;
}
}
if ( pos > - 1 ) {
var page = Math . floor ( pos / self . pageSize ( ) ) ;
self . changePage ( page ) ;
}
}
self . changePage = function ( newPage ) {
if ( newPage < 0 || newPage > self . lastPage ( ) )
return ;
self . currentPage ( newPage ) ;
}
self . prevPage = function ( ) {
if ( self . currentPage ( ) > 0 ) {
self . currentPage ( self . currentPage ( ) - 1 ) ;
}
}
self . nextPage = function ( ) {
if ( self . currentPage ( ) < self . lastPage ( ) ) {
self . currentPage ( self . currentPage ( ) + 1 ) ;
}
}
//~~ sorting
self . changeSorting = function ( sorting ) {
if ( ! _ . contains ( _ . keys ( self . supportedSorting ) , sorting ) )
return ;
self . currentSorting ( sorting ) ;
self . _saveCurrentSortingToLocalStorage ( ) ;
self . changePage ( 0 ) ;
self . _updateItems ( ) ;
}
//~~ filtering
self . toggleFilter = function ( filter ) {
if ( ! _ . contains ( _ . keys ( self . supportedFilters ) , filter ) )
return ;
if ( _ . contains ( self . currentFilters ( ) , filter ) ) {
self . removeFilter ( filter ) ;
} else {
self . addFilter ( filter ) ;
}
}
self . addFilter = function ( filter ) {
if ( ! _ . contains ( _ . keys ( self . supportedFilters ) , filter ) )
return ;
var filters = self . currentFilters ( ) ;
filters . push ( filter ) ;
self . currentFilters ( filters ) ;
self . _saveCurrentFiltersToLocalStorage ( ) ;
self . _updateItems ( ) ;
}
self . removeFilter = function ( filter ) {
if ( filter != "printed" )
return ;
var filters = self . currentFilters ( ) ;
filters . pop ( filter ) ;
self . currentFilters ( filters ) ;
self . _saveCurrentFiltersToLocalStorage ( ) ;
self . _updateItems ( ) ;
}
//~~ update for sorted and filtered view
self . _updateItems = function ( ) {
// determine comparator
var comparator = undefined ;
var currentSorting = self . currentSorting ( ) ;
if ( typeof currentSorting !== undefined && typeof self . supportedSorting [ currentSorting ] !== undefined ) {
comparator = self . supportedSorting [ currentSorting ] ;
}
// work on all items
var result = self . allItems ;
// filter if necessary
var filters = self . currentFilters ( ) ;
_ . each ( filters , function ( filter ) {
if ( typeof filter !== undefined && typeof supportedFilters [ filter ] !== undefined )
result = _ . filter ( result , supportedFilters [ filter ] ) ;
} ) ;
// sort if necessary
if ( typeof comparator !== undefined )
result . sort ( comparator ) ;
// set result list
self . items ( result ) ;
}
//~~ local storage
self . _saveCurrentSortingToLocalStorage = function ( ) {
self . _initializeLocalStorage ( ) ;
var currentSorting = self . currentSorting ( ) ;
if ( currentSorting !== undefined )
localStorage [ self . listType ] [ "currentSorting" ] = currentSorting ;
else
localStorage [ self . listType ] [ "currentSorting" ] = undefined ;
}
self . _loadCurrentSortingFromLocalStorage = function ( ) {
self . _initializeLocalStorage ( ) ;
if ( _ . contains ( _ . keys ( supportedSorting ) , localStorage [ self . listType ] [ "currentSorting" ] ) )
self . currentSorting ( localStorage [ self . listType ] [ "currentSorting" ] ) ;
else
self . currentSorting ( defaultSorting ) ;
}
self . _saveCurrentFiltersToLocalStorage = function ( ) {
self . _initializeLocalStorage ( ) ;
var filters = _ . intersection ( _ . keys ( self . supportedFilters ) , self . currentFilters ( ) ) ;
localStorage [ self . listType ] [ "currentFilters" ] = filters ;
}
self . _loadCurrentFiltersFromLocalStorage = function ( ) {
self . _initializeLocalStorage ( ) ;
self . currentFilters ( _ . intersection ( _ . keys ( self . supportedFilters ) , localStorage [ self . listType , "currentFilters" ] ) ) ;
}
self . _initializeLocalStorage = function ( ) {
if ( localStorage [ self . listType ] !== undefined )
return ;
localStorage [ self . listType ] = {
"currentSorting" : self . defaultSorting ,
"currentFilters" : self . defaultFilters
}
}
self . _loadCurrentFiltersFromLocalStorage ( ) ;
self . _loadCurrentSortingFromLocalStorage ( ) ;
}
2013-03-10 16:04:05 +00:00
function AppearanceViewModel ( settingsViewModel ) {
var self = this ;
self . name = settingsViewModel . appearance _name ;
self . color = settingsViewModel . appearance _color ;
self . brand = ko . computed ( function ( ) {
if ( self . name ( ) )
return "OctoPrint: " + self . name ( ) ;
else
return "OctoPrint" ;
} )
self . title = ko . computed ( function ( ) {
if ( self . name ( ) )
return self . name ( ) + " [OctoPrint]" ;
else
return "OctoPrint" ;
} )
}
2012-12-25 19:49:10 +00:00
$ ( function ( ) {
2012-12-29 14:41:23 +00:00
2013-01-11 23:00:58 +00:00
//~~ View models
var connectionViewModel = new ConnectionViewModel ( ) ;
var printerStateViewModel = new PrinterStateViewModel ( ) ;
2013-02-23 17:47:01 +00:00
var settingsViewModel = new SettingsViewModel ( ) ;
2013-03-02 10:56:32 +00:00
var appearanceViewModel = new AppearanceViewModel ( settingsViewModel ) ;
2013-02-23 17:47:01 +00:00
var temperatureViewModel = new TemperatureViewModel ( settingsViewModel ) ;
2013-01-27 10:12:28 +00:00
var controlsViewModel = new ControlsViewModel ( ) ;
2013-01-11 23:00:58 +00:00
var speedViewModel = new SpeedViewModel ( ) ;
var terminalViewModel = new TerminalViewModel ( ) ;
var gcodeFilesViewModel = new GcodeFilesViewModel ( ) ;
var webcamViewModel = new WebcamViewModel ( ) ;
2013-02-02 11:36:43 +00:00
var gcodeViewModel = new GcodeViewModel ( ) ;
2013-03-10 16:04:05 +00:00
var navigationViewModel = new NavigationViewModel ( appearanceViewModel , settingsViewModel ) ;
2013-02-03 21:01:11 +00:00
2013-02-03 20:38:00 +00:00
var dataUpdater = new DataUpdater (
connectionViewModel ,
printerStateViewModel ,
temperatureViewModel ,
controlsViewModel ,
speedViewModel ,
terminalViewModel ,
gcodeFilesViewModel ,
webcamViewModel ,
gcodeViewModel
) ;
2013-02-03 20:14:22 +00:00
2013-03-02 10:56:32 +00:00
//~~ Show settings - to ensure centered
$ ( '#navbar_show_settings' ) . click ( function ( ) {
$ ( '#settings_dialog' ) . modal ( )
. css ( {
width : 'auto' ,
'margin-left' : function ( ) { return - ( $ ( this ) . width ( ) / 2 ) ; }
} ) ;
return false ;
} )
2012-12-29 14:41:23 +00:00
//~~ Print job control
2013-03-01 21:57:13 +00:00
$ ( "#job_print" ) . click ( function ( ) {
2012-12-25 19:49:10 +00:00
$ . ajax ( {
url : AJAX _BASEURL + "control/print" ,
2012-12-28 19:37:40 +00:00
type : "POST" ,
dataType : "json" ,
2012-12-25 19:49:10 +00:00
success : function ( ) { }
} )
} )
$ ( "#job_pause" ) . click ( function ( ) {
2012-12-28 19:37:40 +00:00
$ ( "#job_pause" ) . button ( "toggle" ) ;
2012-12-25 19:49:10 +00:00
$ . ajax ( {
url : AJAX _BASEURL + "control/pause" ,
2012-12-28 19:37:40 +00:00
type : "POST" ,
dataType : "json"
2012-12-25 19:49:10 +00:00
} )
} )
$ ( "#job_cancel" ) . click ( function ( ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/cancel" ,
2012-12-28 19:37:40 +00:00
type : "POST" ,
dataType : "json"
2012-12-25 19:49:10 +00:00
} )
} )
2013-02-23 18:38:18 +00:00
//~~ Temperature control (should really move to knockout click binding)
2012-12-29 14:41:23 +00:00
2013-02-23 18:38:18 +00:00
$ ( "#temp_newTemp_set" ) . click ( function ( ) {
2012-12-26 14:03:34 +00:00
var newTemp = $ ( "#temp_newTemp" ) . val ( ) ;
$ . ajax ( {
url : AJAX _BASEURL + "control/temperature" ,
type : "POST" ,
dataType : "json" ,
data : { temp : newTemp } ,
success : function ( ) { $ ( "#temp_newTemp" ) . val ( "" ) }
} )
} )
2013-02-23 18:38:18 +00:00
$ ( "#temp_newBedTemp_set" ) . click ( function ( ) {
2012-12-26 14:03:34 +00:00
var newBedTemp = $ ( "#temp_newBedTemp" ) . val ( ) ;
$ . ajax ( {
url : AJAX _BASEURL + "control/temperature" ,
type : "POST" ,
dataType : "json" ,
data : { bedTemp : newBedTemp } ,
success : function ( ) { $ ( "#temp_newBedTemp" ) . val ( "" ) }
} )
} )
2013-01-11 23:00:58 +00:00
$ ( '#tabs a[data-toggle="tab"]' ) . on ( 'shown' , function ( e ) {
temperatureViewModel . updatePlot ( ) ;
} ) ;
2012-12-26 14:03:34 +00:00
2012-12-29 14:41:23 +00:00
//~~ Speed controls
function speedCommand ( structure ) {
var speedSetting = $ ( "#speed_" + structure ) . val ( ) ;
if ( speedSetting ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/speed" ,
type : "POST" ,
dataType : "json" ,
data : structure + "=" + speedSetting ,
success : function ( response ) {
$ ( "#speed_" + structure ) . val ( "" )
speedViewModel . fromResponse ( response ) ;
}
} )
}
}
$ ( "#speed_outerWall_set" ) . click ( function ( ) { speedCommand ( "outerWall" ) } ) ;
$ ( "#speed_innerWall_set" ) . click ( function ( ) { speedCommand ( "innerWall" ) } ) ;
$ ( "#speed_support_set" ) . click ( function ( ) { speedCommand ( "support" ) } ) ;
$ ( "#speed_fill_set" ) . click ( function ( ) { speedCommand ( "fill" ) } ) ;
//~~ Terminal
2013-03-11 14:38:41 +00:00
$ ( "#terminal-send" ) . click ( function ( ) {
2012-12-25 19:49:10 +00:00
var command = $ ( "#terminal-command" ) . val ( ) ;
2012-12-29 14:41:23 +00:00
if ( command ) {
$ . ajax ( {
url : AJAX _BASEURL + "control/command" ,
type : "POST" ,
dataType : "json" ,
2013-02-23 17:08:59 +00:00
contentType : "application/json; charset=UTF-8" ,
data : JSON . stringify ( { "command" : command } )
2012-12-29 14:41:23 +00:00
} )
2013-03-11 14:38:41 +00:00
$ ( "#terminal-command" ) . val ( '' )
2012-12-29 14:41:23 +00:00
}
2013-03-11 14:38:41 +00:00
} )
$ ( "#terminal-command" ) . keyup ( function ( event ) {
if ( event . keyCode == 13 ) {
$ ( "#terminal-send" ) . click ( )
}
2012-12-25 19:49:10 +00:00
} )
2012-12-29 14:41:23 +00:00
//~~ Gcode upload
2012-12-28 19:37:40 +00:00
$ ( "#gcode_upload" ) . fileupload ( {
dataType : "json" ,
2012-12-25 19:49:10 +00:00
done : function ( e , data ) {
gcodeFilesViewModel . fromResponse ( data . result ) ;
2013-02-04 21:24:32 +00:00
$ ( "#gcode_upload_progress .bar" ) . css ( "width" , "0%" ) ;
2013-03-06 22:27:16 +00:00
$ ( "#gcode_upload_progress" ) . removeClass ( "progress-striped" ) . removeClass ( "active" ) ;
$ ( "#gcode_upload_progress .bar" ) . text ( "" ) ;
2012-12-25 19:49:10 +00:00
} ,
progressall : function ( e , data ) {
var progress = parseInt ( data . loaded / data . total * 100 , 10 ) ;
2012-12-28 19:37:40 +00:00
$ ( "#gcode_upload_progress .bar" ) . css ( "width" , progress + "%" ) ;
2013-03-06 22:27:16 +00:00
$ ( "#gcode_upload_progress .bar" ) . text ( "Uploading ..." ) ;
if ( progress >= 100 ) {
$ ( "#gcode_upload_progress" ) . addClass ( "progress-striped" ) . addClass ( "active" ) ;
$ ( "#gcode_upload_progress .bar" ) . text ( "Saving ..." ) ;
}
2012-12-25 19:49:10 +00:00
}
} ) ;
2012-12-30 19:30:31 +00:00
//~~ Offline overlay
2013-01-11 23:00:58 +00:00
$ ( "#offline_overlay_reconnect" ) . click ( function ( ) { dataUpdater . reconnect ( ) } ) ;
2012-12-30 19:30:31 +00:00
2013-02-03 20:14:22 +00:00
//~~ Alert
/ *
function displayAlert ( text , timeout , type ) {
var placeholder = $ ( "#alert_placeholder" ) ;
var alertType = "" ;
if ( type == "success" || type == "error" || type == "info" ) {
alertType = " alert-" + type ;
}
placeholder . append ( $ ( "<div id='activeAlert' class='alert " + alertType + " fade in' data-alert='alert'><p>" + text + "</p></div>" ) ) ;
placeholder . fadeIn ( ) ;
$ ( "#activeAlert" ) . delay ( timeout ) . fadeOut ( "slow" , function ( ) { $ ( this ) . remove ( ) ; $ ( "#alert_placeholder" ) . hide ( ) ; } ) ;
}
* /
2012-12-29 14:41:23 +00:00
//~~ knockout.js bindings
2013-01-30 19:56:17 +00:00
ko . bindingHandlers . popover = {
init : function ( element , valueAccessor , allBindingsAccessor , viewModel , bindingContext ) {
var val = ko . utils . unwrapObservable ( valueAccessor ( ) ) ;
var options = {
title : val . title ,
animation : val . animation ,
placement : val . placement ,
trigger : val . trigger ,
delay : val . delay ,
content : val . content ,
html : val . html
} ;
$ ( element ) . popover ( options ) ;
}
}
2012-12-28 19:37:40 +00:00
ko . applyBindings ( connectionViewModel , document . getElementById ( "connection" ) ) ;
2012-12-25 19:49:10 +00:00
ko . applyBindings ( printerStateViewModel , document . getElementById ( "state" ) ) ;
2012-12-26 14:03:34 +00:00
ko . applyBindings ( gcodeFilesViewModel , document . getElementById ( "files" ) ) ;
2013-02-10 20:48:24 +00:00
ko . applyBindings ( gcodeFilesViewModel , document . getElementById ( "files-heading" ) ) ;
2012-12-25 19:49:10 +00:00
ko . applyBindings ( temperatureViewModel , document . getElementById ( "temp" ) ) ;
2013-01-27 17:28:11 +00:00
ko . applyBindings ( controlsViewModel , document . getElementById ( "controls" ) ) ;
2012-12-25 19:49:10 +00:00
ko . applyBindings ( terminalViewModel , document . getElementById ( "term" ) ) ;
2012-12-29 14:41:23 +00:00
ko . applyBindings ( speedViewModel , document . getElementById ( "speed" ) ) ;
2013-02-03 21:01:11 +00:00
ko . applyBindings ( gcodeViewModel , document . getElementById ( "gcode" ) ) ;
2013-02-17 21:30:34 +00:00
ko . applyBindings ( settingsViewModel , document . getElementById ( "settings_dialog" ) ) ;
2013-03-10 16:04:05 +00:00
ko . applyBindings ( navigationViewModel , document . getElementById ( "navbar" ) ) ;
2013-03-02 10:56:32 +00:00
ko . applyBindings ( appearanceViewModel , document . getElementsByTagName ( "head" ) [ 0 ] ) ;
2012-12-29 14:41:23 +00:00
2013-01-03 14:25:20 +00:00
var webcamElement = document . getElementById ( "webcam" ) ;
if ( webcamElement ) {
ko . applyBindings ( webcamViewModel , document . getElementById ( "webcam" ) ) ;
}
2013-02-03 21:01:11 +00:00
var gCodeVisualizerElement = document . getElementById ( "gcode" ) ;
2013-02-02 16:45:36 +00:00
if ( gCodeVisualizerElement ) {
gcodeViewModel . initialize ( ) ;
}
2012-12-29 14:41:23 +00:00
//~~ startup commands
2012-12-25 19:49:10 +00:00
2013-01-01 20:04:00 +00:00
connectionViewModel . requestData ( ) ;
2013-01-27 10:12:28 +00:00
controlsViewModel . requestData ( ) ;
2013-01-01 20:04:00 +00:00
gcodeFilesViewModel . requestData ( ) ;
2013-01-03 14:25:20 +00:00
webcamViewModel . requestData ( ) ;
2013-02-17 21:30:34 +00:00
settingsViewModel . requestData ( ) ;
2013-01-01 20:04:00 +00:00
2013-01-30 19:56:17 +00:00
//~~ UI stuff
$ ( ".accordion-toggle[href='#files']" ) . click ( function ( ) {
if ( $ ( "#files" ) . hasClass ( "in" ) ) {
$ ( "#files" ) . removeClass ( "overflow_visible" ) ;
} else {
setTimeout ( function ( ) {
$ ( "#files" ) . addClass ( "overflow_visible" ) ;
} , 1000 ) ;
}
} )
2013-03-10 16:04:05 +00:00
$ . pnotify . defaults . history = false ;
2012-12-25 19:49:10 +00:00
}
) ;