@ -79,7 +79,7 @@ var configuratorApp = (function(){
self = this ; // a 'this' for use when 'this' is something else
self = this ; // a 'this' for use when 'this' is something else
// Set up the form
// Set up the form
this . setup ConfigForm( ) ;
this . init ConfigForm( ) ;
// Make tabs for the fieldsets
// Make tabs for the fieldsets
var $fset = $ ( '#config_form fieldset' ) ;
var $fset = $ ( '#config_form fieldset' ) ;
@ -105,78 +105,87 @@ var configuratorApp = (function(){
$ ( '<br>' , { class : 'clear' } ) . appendTo ( '#tabs' ) ;
$ ( '<br>' , { class : 'clear' } ) . appendTo ( '#tabs' ) ;
$tabs . find ( 'a:first' ) . trigger ( 'click' ) ;
$tabs . find ( 'a:first' ) . trigger ( 'click' ) ;
// Make a droppable file uploader
// Make a droppable file uploader , if possible
var $uploader = $ ( '#file-upload' ) ;
var $uploader = $ ( '#file-upload' ) ;
var fileUploader = new BinaryFileUploader ( {
var fileUploader = new BinaryFileUploader ( {
element : $uploader [ 0 ] ,
element : $uploader [ 0 ] ,
onFileLoad : function ( file ) { self . handleFileLoad ( file , $uploader ) ; }
onFileLoad : function ( file ) { self . handleFileLoad ( file , $uploader ) ; }
} ) ;
} ) ;
if ( ! fileUploader . hasFileUploaderSupport ( ) )
if ( ! fileUploader . hasFileUploaderSupport ( ) ) alert ( 'Your browser doesn\'t support the file reading API' ) ;
this . setMessage ( "Your browser doesn't support the file reading API." , 'error' ) ;
// Read boards.h
// Read boards.h, Configuration.h, Configuration_adv.h
boards _list = { } ;
var ajax _count = 0 , success _count = 0 ;
var loaded _items = { } ;
var errFunc = function ( jqXHR , textStatus , errorThrown ) {
var config _files = [ boards _file , config _file , config _adv _file ] ;
alert ( 'Failed to load ' + this . url + '. Try the file field.' ) ;
$ . each ( config _files , function ( i , fname ) {
} ;
self . log ( "Loading " + fname + "..." , 3 ) ;
$ . ajax ( {
$ . ajax ( {
url : marlin _config + '/' + boards_fil e,
url : marlin _config + '/' + fnam e,
type : 'GET' ,
type : 'GET' ,
async : fals e,
async : tru e,
cache : false ,
cache : false ,
success : function ( txt ) {
success : function ( txt ) {
// Get all the boards and save them into an object
self . log ( "Loaded " + fname + "..." , 3 ) ;
self . initBoardsFromText ( txt ) ;
loaded _items [ fname ] = function ( ) { self . fileLoaded ( fname , txt ) ; } ;
has _boards = true ;
success _count ++ ;
} ,
} ,
error : errFunc
complete : function ( ) {
ajax _count ++ ;
if ( ajax _count >= 3 ) {
$ . each ( config _files , function ( i , fname ) { if ( typeof loaded _items [ fname ] != 'undefined' ) loaded _items [ fname ] ( ) ; } ) ;
self . refreshConfigForm ( ) ;
if ( success _count < ajax _count )
self . setMessage ( 'Unable to load configurations. Use the upload field instead.' , 'error' ) ;
}
}
} ) ;
} ) ;
// Read Configuration.h
$ . ajax ( {
url : marlin _config + '/' + config _file ,
type : 'GET' ,
async : false ,
cache : false ,
success : function ( txt ) {
// File contents into the textarea
$config . text ( txt ) ;
// Get thermistor info too
self . initThermistorsFromText ( txt ) ;
has _config = true ;
} ,
error : errFunc
} ) ;
} ) ;
// Read Configuration.h
$ . ajax ( {
url : marlin _config + '/' + config _adv _file ,
type : 'GET' ,
async : false ,
cache : false ,
success : function ( txt ) {
// File contents into the textarea
$config _adv . text ( txt ) ;
has _config _adv = true ;
self . refreshConfigForm ( ) ;
} ,
} ,
error : errFunc
} ) ;
setMessage : function ( msg , type ) {
if ( msg ) {
if ( typeof type == 'undefined' ) type = 'message' ;
var $err = $ ( '<p class="' + type + '">' + msg + '</p>' ) , err = $err [ 0 ] ;
$ ( '#message' ) . prepend ( $err ) ;
var baseColor = $err . css ( 'color' ) . replace ( /rgba?\(([^),]+,[^),]+,[^),]+).*/ , 'rgba($1,' ) ;
var d = new Date ( ) ;
err . startTime = d . getTime ( ) ;
err . pulser = setInterval ( function ( ) {
d = new Date ( ) ;
var pulse _time = ( d . getTime ( ) - err . startTime ) ;
$err . css ( { color : baseColor + ( 0.5 + Math . sin ( pulse _time / 200 ) * 0.4 ) + ')' } ) ;
if ( pulse _time > 5000 ) {
clearInterval ( err . pulser ) ;
$err . remove ( ) ;
}
} , 50 ) ;
}
else {
$ ( '#message p.error, #message p.warning' ) . each ( function ( ) {
if ( typeof this . pulser != 'undefined' && this . pulser )
clearInterval ( this . pulser ) ;
$ ( this ) . remove ( ) ;
} ) ;
}
} ,
} ,
/ * *
* Init the boards array from a boards . h file
* /
initBoardsFromText : function ( txt ) {
initBoardsFromText : function ( txt ) {
boards _list = { } ;
boards _list = { } ;
var r , findDef = new RegExp ( '[ \\t]*#define[ \\t]+(BOARD_[\\w_]+)[ \\t]+(\\d+)[ \\t]*(//[ \\t]*)?(.+)?' , 'gm' ) ;
var r , findDef = new RegExp ( '[ \\t]*#define[ \\t]+(BOARD_[\\w_]+)[ \\t]+(\\d+)[ \\t]*(//[ \\t]*)?(.+)?' , 'gm' ) ;
while ( ( r = findDef . exec ( txt ) ) !== null ) {
while ( ( r = findDef . exec ( txt ) ) !== null ) {
boards _list [ r [ 1 ] ] = r [ 2 ] . prePad ( 3 , ' ' ) + " — " + r [ 4 ] . replace ( /\).*/ , ')' ) ;
boards _list [ r [ 1 ] ] = r [ 2 ] . prePad ( 3 , ' ' ) + " — " + r [ 4 ] . replace ( /\).*/ , ')' ) ;
}
}
this . log ( "Loaded boards" , 0 ) ;
this . log ( "Loaded boards" , 3) ; this . log ( boards _list , 3 ) ;
this . log ( boards _list , 0 ) ;
has _boards = true ;
} ,
} ,
/ * *
* Init the thermistors array from the Configuration . h file
* /
initThermistorsFromText : function ( txt ) {
initThermistorsFromText : function ( txt ) {
// Get all the thermistors and save them into an object
// Get all the thermistors and save them into an object
var r , s , findDef = new RegExp ( '(//.*\n)+\\s+(#define[ \\t]+TEMP_SENSOR_0)' , 'g' ) ;
var r , s , findDef = new RegExp ( '(//.*\n)+\\s+(#define[ \\t]+TEMP_SENSOR_0)' , 'g' ) ;
@ -187,48 +196,67 @@ var configuratorApp = (function(){
}
}
} ,
} ,
handleFileLoad : function ( file , $uploader ) {
/ * *
file += '' ;
* Handle a file being dropped on the file field
* /
handleFileLoad : function ( txt , $uploader ) {
txt += '' ;
var filename = $uploader . val ( ) . replace ( /.*[\/\\](.*)$/ , '$1' ) ;
var filename = $uploader . val ( ) . replace ( /.*[\/\\](.*)$/ , '$1' ) ;
switch ( filename ) {
switch ( filename ) {
case boards _file :
case boards _file :
this . initBoardsFromText ( file ) ;
case config _file :
has _boards = true ;
case config _adv _file :
this . fileLoaded ( filename , txt ) ;
break ;
default :
this . log ( "Can't parse " + filename , 1 ) ;
break ;
}
} ,
fileLoaded : function ( filename , txt ) {
this . log ( "fileLoaded:" + filename , 4 ) ;
switch ( filename ) {
case boards _file :
this . initBoardsFromText ( txt ) ;
$ ( '#MOTHERBOARD' ) . html ( '' ) . addOptions ( boards _list ) ;
$ ( '#MOTHERBOARD' ) . html ( '' ) . addOptions ( boards _list ) ;
if ( has _config ) this . initField ( 'MOTHERBOARD' ) ;
if ( has _config ) this . initField ( 'MOTHERBOARD' ) ;
this . setMessage ( boards _file + ' loaded successfully.' ) ;
break ;
break ;
case config _file :
case config _file :
if ( has _boards ) {
if ( has _boards ) {
$config . text ( file ) ;
$config . text ( txt ) ;
has _config = true ;
total _config _lines = txt . split ( /\r?\n|\r/ ) . length ;
total _config _lines = file . replace ( /[^\n]+/g , '' ) . length ;
this . initThermistorsFromText ( txt ) ;
this . initThermistorsFromText ( file ) ;
this . purgeDefineInfo ( false ) ;
this . purgeDefineInfo ( false ) ;
this . refreshConfigForm ( ) ;
this . refreshConfigForm ( ) ;
this . setMessage ( config _file + ' loaded successfully.' ) ;
has _config = true ;
}
}
else {
else {
alert ( "Upload a " + boards _file + " file first!" ) ;
this . setMessage ( "Upload a " + boards _file + " file first!" , 'error' ) ;
}
}
break ;
break ;
case config _adv _file :
case config _adv _file :
if ( has _config ) {
if ( has _config ) {
$config _adv . text ( file ) ;
$config _adv . text ( txt ) ;
has _config _adv = true ;
total _config _adv _lines = txt . split ( /\r?\n|\r/ ) . length ;
total _config _adv _lines = file . replace ( /[^\n]+/g , '' ) . length ;
this . purgeDefineInfo ( true ) ;
this . purgeDefineInfo ( true ) ;
this . refreshConfigForm ( ) ;
this . refreshConfigForm ( ) ;
this . setMessage ( config _adv _file + ' loaded successfully.' ) ;
has _config _adv = true ;
}
}
else {
else {
alert ( "Upload a " + config _file + " file first!" ) ;
this . setMessage ( "Upload a " + config _file + " file first!" , 'error' ) ;
}
}
break ;
break ;
default :
this . log ( "Can't parse " + filename , 1 ) ;
break ;
}
}
} ,
} ,
setupConfigForm : function ( ) {
/ * *
* Add enhancements to the form
* /
initConfigForm : function ( ) {
// Modify form fields and make the form responsive.
// Modify form fields and make the form responsive.
// As values change on the form, we could update the
// As values change on the form, we could update the
// contents of text areas containing the configs, for
// contents of text areas containing the configs, for
@ -258,14 +286,16 @@ var configuratorApp = (function(){
) ;
) ;
} ) ;
} ) ;
// Add options to the popup menus
$ ( '#SERIAL_PORT' ) . addOptions ( [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ) ;
$ ( '#SERIAL_PORT' ) . addOptions ( [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 ] ) ;
$ ( '#BAUDRATE' ) . addOptions ( [ 2400 , 9600 , 19200 , 38400 , 57600 , 115200 , 250000 ] ) ;
$ ( '#BAUDRATE' ) . addOptions ( [ 2400 , 9600 , 19200 , 38400 , 57600 , 115200 , 250000 ] ) ;
$ ( '#EXTRUDERS' ) . addOptions ( [ 1 , 2 , 3 , 4 ] ) ;
$ ( '#EXTRUDERS' ) . addOptions ( [ 1 , 2 , 3 , 4 ] ) ;
$ ( '#POWER_SUPPLY' ) . addOptions ( { '1' : 'ATX' , '2' : 'Xbox 360' } ) ;
$ ( '#POWER_SUPPLY' ) . addOptions ( { '1' : 'ATX' , '2' : 'Xbox 360' } ) ;
// Replace the Serial popup menu with a stepper control
$ ( '#serial_stepper' ) . jstepper ( {
$ ( '#serial_stepper' ) . jstepper ( {
min : 0 ,
min : 0 ,
max : 7 ,
max : 3 ,
val : $ ( '#SERIAL_PORT' ) . val ( ) ,
val : $ ( '#SERIAL_PORT' ) . val ( ) ,
arrowWidth : '18px' ,
arrowWidth : '18px' ,
arrowHeight : '15px' ,
arrowHeight : '15px' ,
@ -276,7 +306,6 @@ var configuratorApp = (function(){
textStyle : { width : '1.5em' , fontSize : '120%' , textAlign : 'center' } ,
textStyle : { width : '1.5em' , fontSize : '120%' , textAlign : 'center' } ,
onChange : function ( v ) { $ ( '#SERIAL_PORT' ) . val ( v ) . trigger ( 'change' ) ; }
onChange : function ( v ) { $ ( '#SERIAL_PORT' ) . val ( v ) . trigger ( 'change' ) ; }
} ) ;
} ) ;
} ,
} ,
refreshConfigForm : function ( ) {
refreshConfigForm : function ( ) {
@ -322,30 +351,36 @@ var configuratorApp = (function(){
this . initField ( 'MAX_REDUNDANT_TEMP_SENSOR_DIFF' ) ;
this . initField ( 'MAX_REDUNDANT_TEMP_SENSOR_DIFF' ) ;
this . initField ( 'TEMP_RESIDENCY_TIME' ) ;
this . initField ( 'TEMP_RESIDENCY_TIME' ) ;
} ,
// prettyPrint();
setTextAndHighlight : function ( $field , txt , name ) {
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
if ( inf == null ) return ;
} ,
} ,
/ * *
/ * *
* initField - make a field responsive and get info
* Make a field responsive and initialize its defineInfo
* about its configuration file define
* /
* /
initField : function ( name , adv ) {
initField : function ( name , adv ) {
this . log ( "initField:" + name , 3 ) ;
this . log ( "initField:" + name , 4 ) ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] ;
if ( elm . defineInfo == = undefined ) {
if ( elm . defineInfo == null ) {
elm . defineInfo = this . getDefineInfo ( name , adv ) ;
elm . defineInfo = this . getDefineInfo ( name , adv ) ;
$elm . on ( $elm . attr ( 'type' ) == 'text' ? 'input' : 'change' , this . handleChange ) ;
$elm . on ( $elm . attr ( 'type' ) == 'text' ? 'input' : 'change' , this . handleChange ) ;
}
}
this . setFieldFromDefine ( name ) ;
this . setFieldFromDefine ( name ) ;
} ,
} ,
handleChange : function ( e ) {
/ * *
self . updateDefineFromField ( e . target . id ) ;
* Handle any value field being changed
} ,
* /
handleChange : function ( ) { self . updateDefineFromField ( this . id ) ; } ,
handleSwitch : function ( e ) {
/ * *
var $elm = $ ( e . target ) , $prev = $elm . prev ( ) ;
* Handle a switch checkbox being changed
* /
handleSwitch : function ( ) {
var $elm = $ ( this ) , $prev = $elm . prev ( ) ;
var on = $elm . prop ( 'checked' ) || false ;
var on = $elm . prop ( 'checked' ) || false ;
$prev . attr ( 'disabled' , ! on ) ;
$prev . attr ( 'disabled' , ! on ) ;
self . setDefineEnabled ( $prev [ 0 ] . id , on ) ;
self . setDefineEnabled ( $prev [ 0 ] . id , on ) ;
@ -357,6 +392,7 @@ var configuratorApp = (function(){
defineValue : function ( name ) {
defineValue : function ( name ) {
this . log ( 'defineValue:' + name , 4 ) ;
this . log ( 'defineValue:' + name , 4 ) ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
if ( inf == null ) return 'n/a' ;
var result = inf . regex . exec ( $ ( inf . field ) . text ( ) ) ;
var result = inf . regex . exec ( $ ( inf . field ) . text ( ) ) ;
this . log ( result , 2 ) ;
this . log ( result , 2 ) ;
@ -370,12 +406,13 @@ var configuratorApp = (function(){
defineIsEnabled : function ( name ) {
defineIsEnabled : function ( name ) {
this . log ( 'defineIsEnabled:' + name , 4 ) ;
this . log ( 'defineIsEnabled:' + name , 4 ) ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
if ( inf == null ) return false ;
var result = inf . regex . exec ( $ ( inf . field ) . text ( ) ) ;
var result = inf . regex . exec ( $ ( inf . field ) . text ( ) ) ;
this . log ( result , 2 ) ;
this . log ( result , 2 ) ;
var on = result !== null ? result [ 1 ] . trim ( ) != '//' : true ;
var on = result !== null ? result [ 1 ] . trim ( ) != '//' : true ;
this . log ( name + ' = ' + on , 4 ) ;
this . log ( name + ' = ' + on , 2 ) ;
return on ;
return on ;
} ,
} ,
@ -385,23 +422,15 @@ var configuratorApp = (function(){
* /
* /
setDefineEnabled : function ( name , val ) {
setDefineEnabled : function ( name , val ) {
this . log ( 'setDefineEnabled:' + name , 4 ) ;
this . log ( 'setDefineEnabled:' + name , 4 ) ;
var $elm = $ ( '#' + name ) , inf = $elm [ 0 ] . defineInfo ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
if ( inf == null ) return ;
var $c = $ ( inf . field ) , txt = $c . text ( ) ;
var slash = val ? '' : '//' ;
var slash = val ? '' : '//' ;
var newline = inf . line
var newline = inf . line
. replace ( /^([ \t]*)(\/\/)([ \t]*)/ , '$1$3' ) // remove slashes
. replace ( /^([ \t]*)(\/\/)([ \t]*)/ , '$1$3' ) // remove slashes
. replace ( inf . pre + inf . define , inf . pre + slash + inf . define ) ; // add them back
. replace ( inf . pre + inf . define , inf . pre + slash + inf . define ) ; // add them back
txt = txt . replace ( inf . line , newline ) ;
this . setDefineLine ( name , newline ) ;
inf . line = newline ;
this . log ( newline , 2 ) ;
$c . text ( txt ) ;
// Scroll to reveal the define
this . scrollToDefine ( name ) ;
} ,
} ,
/ * *
/ * *
@ -409,11 +438,8 @@ var configuratorApp = (function(){
* /
* /
updateDefineFromField : function ( name ) {
updateDefineFromField : function ( name ) {
this . log ( 'updateDefineFromField:' + name , 4 ) ;
this . log ( 'updateDefineFromField:' + name , 4 ) ;
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
var $elm = $ ( '#' + name ) , inf = $elm [ 0 ] . defineInfo ;
var $c = $ ( inf . field ) , txt = $c . text ( ) ;
if ( inf == null ) return ;
// var result = inf.repl.exec(txt);
// this.log(result, 2);
var isCheck = $elm . attr ( 'type' ) == 'checkbox' ,
var isCheck = $elm . attr ( 'type' ) == 'checkbox' ,
val = isCheck ? $elm . prop ( 'checked' ) : $elm . val ( ) ;
val = isCheck ? $elm . prop ( 'checked' ) : $elm . val ( ) ;
@ -446,18 +472,36 @@ var configuratorApp = (function(){
break ;
break ;
}
}
txt = txt . replace ( inf . line , newline ) ;
this . setDefineLine ( name , newline ) ;
} ,
/ * *
* Set the define ' s line in the text to a new line ,
* then update , highlight , and scroll to the line
* /
setDefineLine : function ( name , newline ) {
var $elm = $ ( '#' + name ) , elm = $elm [ 0 ] , inf = elm . defineInfo ;
var $c = $ ( inf . field ) , txt = $c . text ( ) ;
var hilite _token = '[HIGHLIGHTER-TOKEN]' ;
txt = txt . replace ( inf . line , hilite _token + newline ) ;
inf . line = newline ;
inf . line = newline ;
this . log ( newline , 2 ) ;
this . log ( newline , 2 ) ;
$c . text ( txt ) ;
// Convert txt into HTML before storing
var html = $ ( '<div/>' ) . text ( txt ) . html ( ) . replace ( hilite _token , '<span></span>' ) ;
// Set the final text including the highlighter
$c . html ( html ) ;
// Scroll to reveal the define
// Scroll to reveal the define
this . scrollToDefine ( name ) ;
this . scrollToDefine ( name ) ;
} ,
} ,
/ * *
/ * *
* Scroll the field to show a define
* Scroll a pre box to reveal a # define
* /
* /
scrollToDefine : function ( name , always ) {
scrollToDefine : function ( name , always ) {
this . log ( 'scrollToDefine:' + name , 4 ) ;
this . log ( 'scrollToDefine:' + name , 4 ) ;
@ -474,7 +518,6 @@ var configuratorApp = (function(){
if ( always == true || Math . abs ( $c . prop ( 'scrollTop' ) - textScrollY ) > halfHeight )
if ( always == true || Math . abs ( $c . prop ( 'scrollTop' ) - textScrollY ) > halfHeight )
$c . animate ( { scrollTop : textScrollY < 0 ? 0 : textScrollY } ) ;
$c . animate ( { scrollTop : textScrollY < 0 ? 0 : textScrollY } ) ;
} ,
} ,
/ * *
/ * *
@ -587,6 +630,9 @@ var configuratorApp = (function(){
return null ;
return null ;
} ,
} ,
/ * *
* Count the number of lines before a match , return - 1 on fail
* /
getLineInText : function ( line , txt ) {
getLineInText : function ( line , txt ) {
var pos = txt . indexOf ( line ) ;
var pos = txt . indexOf ( line ) ;
return ( pos < 0 ) ? pos : txt . substr ( 0 , pos ) . replace ( /[^\n]+/g , '' ) . length ;
return ( pos < 0 ) ? pos : txt . substr ( 0 , pos ) . replace ( /[^\n]+/g , '' ) . length ;