2014-08-09 17:38:46 +00:00
'use strict' ;
2014-07-16 10:59:12 +00:00
// Google Analytics
var googleAnalyticsService = analytics . getService ( 'ice_cream_app' ) ;
var googleAnalytics = googleAnalyticsService . getTracker ( 'UA-32728876-6' ) ;
var googleAnalyticsConfig = false ;
2014-08-09 17:38:46 +00:00
googleAnalyticsService . getConfig ( ) . addCallback ( function ( config ) {
2014-07-16 10:59:12 +00:00
googleAnalyticsConfig = config ;
2014-04-21 22:30:22 +00:00
} ) ;
2014-08-09 17:38:46 +00:00
$ ( document ) . ready ( function ( ) {
2014-03-28 23:59:39 +00:00
// translate to user-selected language
localize ( ) ;
2014-02-03 05:21:26 +00:00
// alternative - window.navigator.appVersion.match(/Chrome\/([0-9.]*)/)[1];
2014-03-08 05:25:15 +00:00
GUI . log ( 'Running - OS: <strong>' + GUI . operating _system + '</strong>, ' +
2014-08-09 17:38:46 +00:00
'Chrome: <strong>' + window . navigator . appVersion . replace ( /.*Chrome\/([0-9.]*).*/ , "$1" ) + '</strong>, ' +
2014-02-03 08:38:16 +00:00
'Configurator: <strong>' + chrome . runtime . getManifest ( ) . version + '</strong>' ) ;
2014-02-10 19:01:08 +00:00
// notification messages for various operating systems
switch ( GUI . operating _system ) {
case 'Windows' :
break ;
case 'MacOS' :
2014-02-26 05:49:38 +00:00
// var main_chromium_version = window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/,"$1").split('.')[0];
2014-02-10 19:01:08 +00:00
break ;
case 'ChromeOS' :
break ;
case 'Linux' :
break ;
case 'UNIX' :
break ;
}
2014-03-08 05:25:15 +00:00
2014-08-17 11:29:07 +00:00
// check release time to inform people in case they are running old release
2014-09-12 12:00:39 +00:00
if ( CONFIGURATOR . releaseDate > ( new Date ( ) . getTime ( ) - ( 86400000 * 60 ) ) ) { // 1 day = 86400000 miliseconds, * 60 = 2 month window
console . log ( 'Application version is valid for another: ' + Math . round ( ( CONFIGURATOR . releaseDate - ( new Date ( ) . getTime ( ) - ( 86400000 * 60 ) ) ) / 86400000 ) + ' days' ) ;
} else {
console . log ( 'Application version expired' ) ;
2014-08-17 12:20:28 +00:00
GUI . log ( 'You\'re using an old version of ' + chrome . runtime . getManifest ( ) . name + '. Please update so you can benefit from recently added features and bugfixes.' ) ;
2014-08-17 11:29:07 +00:00
}
2014-10-02 09:21:56 +00:00
// log webgl capability
// it would seem the webgl "enabling" through advanced settings will be ignored in the future
// and webgl will be supported if gpu supports it by default (canary 40.0.2175.0), keep an eye on this one
var canvas = document . createElement ( 'canvas' ) ;
if ( window . WebGLRenderingContext && ( canvas . getContext ( 'webgl' ) || canvas . getContext ( 'experimental-webgl' ) ) ) {
googleAnalytics . sendEvent ( 'Capability' , 'WebGL' , 'true' ) ;
} else {
googleAnalytics . sendEvent ( 'Capability' , 'WebGL' , 'false' ) ;
}
2014-09-25 10:18:47 +00:00
// log library versions in console to make version tracking easier
console . log ( 'Libraries: jQuery - ' + $ . fn . jquery + ', d3 - ' + d3 . version + ', three.js - ' + THREE . REVISION ) ;
2014-08-17 11:29:07 +00:00
2014-01-18 18:21:30 +00:00
// Tabs
2014-07-10 16:14:17 +00:00
var ui _tabs = $ ( '#tabs > ul' ) ;
2014-08-09 17:38:46 +00:00
$ ( 'a' , ui _tabs ) . click ( function ( ) {
2014-07-09 14:10:02 +00:00
if ( $ ( this ) . parent ( ) . hasClass ( 'active' ) == false && ! GUI . tab _switch _in _progress ) { // only initialize when the tab isn't already active
2014-08-09 17:38:46 +00:00
var self = this ,
tab = $ ( self ) . parent ( ) . prop ( 'class' ) ;
2014-04-21 22:30:22 +00:00
// if there is no active connection, return
2014-09-08 15:52:07 +00:00
if ( ! CONFIGURATOR . connectionValid ) {
2014-06-20 09:07:43 +00:00
GUI . log ( 'You need to <strong>connect</strong> before you can view any of the tabs' ) ;
2013-04-08 19:10:47 +00:00
return ;
}
2014-03-08 05:25:15 +00:00
2014-07-09 14:10:02 +00:00
GUI . tab _switch _in _progress = true ;
2014-08-09 17:38:46 +00:00
GUI . tab _switch _cleanup ( function ( ) {
2013-12-09 18:34:34 +00:00
// disable previously active tab highlight
2014-07-10 16:14:17 +00:00
$ ( 'li' , ui _tabs ) . removeClass ( 'active' ) ;
2014-03-08 05:25:15 +00:00
2013-12-09 18:34:34 +00:00
// Highlight selected tab
2013-11-09 05:14:21 +00:00
$ ( self ) . parent ( ) . addClass ( 'active' ) ;
2014-03-08 05:25:15 +00:00
2014-03-15 14:43:08 +00:00
// detach listeners and remove element data
2014-07-12 10:03:13 +00:00
var content = $ ( '#content' ) ;
content . empty ( ) ;
// display loading screen
$ ( '#cache .data-loading' ) . clone ( ) . appendTo ( content ) ;
2014-08-09 17:38:46 +00:00
function content _ready ( ) {
GUI . tab _switch _in _progress = false ;
}
2014-07-12 10:03:13 +00:00
switch ( tab ) {
2014-09-20 11:51:23 +00:00
case 'tab_setup' :
TABS . setup . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
2014-09-17 08:31:36 +00:00
case 'tab_configuration' :
TABS . configuration . initialize ( content _ready ) ;
break ;
2014-07-12 10:03:13 +00:00
case 'tab_pid_tuning' :
2014-08-12 13:51:31 +00:00
TABS . pid _tuning . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
case 'tab_receiver' :
2014-08-12 13:51:31 +00:00
TABS . receiver . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
case 'tab_auxiliary_configuration' :
2014-08-12 13:51:31 +00:00
TABS . auxiliary _configuration . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
case 'tab_servos' :
2014-08-12 13:51:31 +00:00
TABS . servos . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
case 'tab_gps' :
2014-08-12 13:51:31 +00:00
TABS . gps . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
case 'tab_motor_outputs' :
2014-08-12 13:51:31 +00:00
TABS . motor _outputs . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
case 'tab_sensors' :
2014-08-12 13:51:31 +00:00
TABS . sensors . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
case 'tab_logging' :
2014-08-12 13:51:31 +00:00
TABS . logging . initialize ( content _ready ) ;
2014-07-12 10:03:13 +00:00
break ;
2014-09-20 11:51:23 +00:00
case 'tab_cli' :
TABS . cli . initialize ( content _ready ) ;
break ;
default :
console . log ( 'Tab not found' ) ;
2014-07-12 10:03:13 +00:00
}
2013-11-09 05:14:21 +00:00
} ) ;
2013-04-08 19:10:47 +00:00
}
} ) ;
2014-03-08 05:25:15 +00:00
2014-09-20 11:51:23 +00:00
TABS . landing . initialize ( ) ;
2014-03-08 05:25:15 +00:00
2014-04-22 14:16:22 +00:00
// options
2014-08-09 17:38:46 +00:00
$ ( 'a#options' ) . click ( function ( ) {
2014-04-22 14:16:22 +00:00
var el = $ ( this ) ;
if ( ! el . hasClass ( 'active' ) ) {
el . addClass ( 'active' ) ;
el . after ( '<div id="options-window"></div>' ) ;
2014-07-16 11:38:11 +00:00
2014-08-09 17:38:46 +00:00
$ ( 'div#options-window' ) . load ( './tabs/options.html' , function ( ) {
2014-07-16 10:59:12 +00:00
googleAnalytics . sendAppView ( 'Options' ) ;
2014-04-22 14:16:22 +00:00
// translate to user-selected language
localize ( ) ;
// if notifications are enabled, or wasn't set, check the notifications checkbox
2014-08-09 17:38:46 +00:00
chrome . storage . local . get ( 'update_notify' , function ( result ) {
2014-08-14 15:03:47 +00:00
if ( result . update _notify === 'undefined' || result . update _notify ) {
2014-04-22 14:16:22 +00:00
$ ( 'div.notifications input' ) . prop ( 'checked' , true ) ;
}
} ) ;
2014-08-09 17:38:46 +00:00
$ ( 'div.notifications input' ) . change ( function ( ) {
2014-04-22 14:16:22 +00:00
var check = $ ( this ) . is ( ':checked' ) ;
chrome . storage . local . set ( { 'update_notify' : check } ) ;
} ) ;
// if tracking is enabled, check the statistics checkbox
2014-07-16 10:59:12 +00:00
if ( googleAnalyticsConfig . isTrackingPermitted ( ) ) {
2014-04-22 14:16:22 +00:00
$ ( 'div.statistics input' ) . prop ( 'checked' , true ) ;
}
2014-08-09 17:38:46 +00:00
$ ( 'div.statistics input' ) . change ( function ( ) {
2014-07-16 10:59:12 +00:00
var result = $ ( this ) . is ( ':checked' ) ;
googleAnalyticsConfig . setTrackingPermitted ( result ) ;
2014-04-22 14:16:22 +00:00
} ) ;
2014-07-16 11:38:11 +00:00
function close _and _cleanup ( e ) {
2014-07-16 13:56:24 +00:00
if ( e . type == 'click' && ! $ . contains ( $ ( 'div#options-window' ) [ 0 ] , e . target ) || e . type == 'keyup' && e . keyCode == 27 ) {
$ ( document ) . unbind ( 'click keyup' , close _and _cleanup ) ;
2014-07-16 11:38:11 +00:00
2014-09-04 07:33:13 +00:00
$ ( 'div#options-window' ) . slideUp ( 250 , function ( ) {
2014-07-16 11:38:11 +00:00
el . removeClass ( 'active' ) ;
$ ( this ) . empty ( ) . remove ( ) ;
} ) ;
}
}
2014-07-16 13:56:24 +00:00
$ ( document ) . bind ( 'click keyup' , close _and _cleanup ) ;
2014-07-16 11:38:11 +00:00
2014-09-04 07:33:13 +00:00
$ ( this ) . slideDown ( 250 ) ;
2014-04-22 14:16:22 +00:00
} ) ;
}
} ) ;
2014-01-15 23:55:45 +00:00
// listen to all input change events and adjust the value within limits if necessary
2014-08-09 17:38:46 +00:00
$ ( "#content" ) . on ( 'focus' , 'input[type="number"]' , function ( ) {
var element = $ ( this ) ,
val = element . val ( ) ;
2014-03-08 05:25:15 +00:00
2014-01-16 00:58:07 +00:00
if ( ! isNaN ( val ) ) {
element . data ( 'previousValue' , parseFloat ( val ) ) ;
}
} ) ;
2014-03-08 05:25:15 +00:00
2014-08-09 17:38:46 +00:00
$ ( "#content" ) . on ( 'keydown' , 'input[type="number"]' , function ( e ) {
2014-01-24 15:44:08 +00:00
// whitelist all that we need for numeric control
2014-07-16 22:28:01 +00:00
var whitelist = [
96 , 97 , 98 , 99 , 100 , 101 , 102 , 103 , 104 , 105 , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , // numpad and standard number keypad
109 , 189 , // minus on numpad and in standard keyboard
8 , 46 , 9 , // backspace, delete, tab
190 , 110 , // decimal point
37 , 38 , 39 , 40 , 13 // arrows and enter
] ;
2014-08-09 17:38:46 +00:00
if ( whitelist . indexOf ( e . keyCode ) == - 1 ) {
e . preventDefault ( ) ;
}
2014-01-24 15:44:08 +00:00
} ) ;
2014-03-08 05:25:15 +00:00
2014-08-09 17:38:46 +00:00
$ ( "#content" ) . on ( 'change' , 'input[type="number"]' , function ( ) {
var element = $ ( this ) ,
min = parseFloat ( element . prop ( 'min' ) ) ,
max = parseFloat ( element . prop ( 'max' ) ) ,
step = parseFloat ( element . prop ( 'step' ) ) ,
val = parseFloat ( element . val ( ) ) ,
decimal _places ;
2014-03-08 05:25:15 +00:00
2014-01-15 23:55:45 +00:00
// only adjust minimal end if bound is set
2014-01-16 00:58:07 +00:00
if ( element . prop ( 'min' ) ) {
2014-08-09 17:38:46 +00:00
if ( val < min ) {
element . val ( min ) ;
2014-09-22 08:16:27 +00:00
val = min ;
2014-08-09 17:38:46 +00:00
}
2014-01-15 19:25:51 +00:00
}
2014-03-08 05:25:15 +00:00
2014-01-15 23:55:45 +00:00
// only adjust maximal end if bound is set
2014-01-16 00:58:07 +00:00
if ( element . prop ( 'max' ) ) {
2014-08-09 17:38:46 +00:00
if ( val > max ) {
element . val ( max ) ;
2014-09-22 08:16:27 +00:00
val = max ;
2014-08-09 17:38:46 +00:00
}
2014-01-16 00:58:07 +00:00
}
2014-03-08 05:25:15 +00:00
2014-01-16 00:58:07 +00:00
// if entered value is illegal use previous value instead
if ( isNaN ( val ) ) {
element . val ( element . data ( 'previousValue' ) ) ;
2014-09-22 08:16:27 +00:00
val = element . data ( 'previousValue' ) ;
2014-01-16 00:58:07 +00:00
}
2014-03-08 05:25:15 +00:00
2014-01-16 00:58:07 +00:00
// if step is not set or step is int and value is float use previous value instead
if ( isNaN ( step ) || step % 1 === 0 ) {
if ( val % 1 !== 0 ) {
element . val ( element . data ( 'previousValue' ) ) ;
2014-09-22 08:16:27 +00:00
val = element . data ( 'previousValue' ) ;
2014-01-16 00:58:07 +00:00
}
2014-01-15 19:25:51 +00:00
}
2014-03-08 05:25:15 +00:00
2014-01-29 19:22:14 +00:00
// if step is set and is float and value is int, convert to float, keep decimal places in float according to step *experimental*
if ( ! isNaN ( step ) && step % 1 !== 0 ) {
2014-08-09 17:38:46 +00:00
decimal _places = String ( step ) . split ( '.' ) [ 1 ] . length ;
2014-03-08 05:25:15 +00:00
2014-01-29 19:22:14 +00:00
if ( val % 1 === 0 ) {
element . val ( val . toFixed ( decimal _places ) ) ;
} else if ( String ( val ) . split ( '.' ) [ 1 ] . length != decimal _places ) {
element . val ( val . toFixed ( decimal _places ) ) ;
}
}
2014-01-15 19:25:51 +00:00
} ) ;
2013-11-08 17:31:19 +00:00
} ) ;
2014-10-01 12:08:15 +00:00
function catch _startup _time ( startTime ) {
var endTime = new Date ( ) . getTime ( ) ,
timeSpent = endTime - startTime ;
googleAnalytics . sendTiming ( 'Load Times' , 'Application Startup' , timeSpent ) ;
}
2013-11-13 08:49:03 +00:00
function microtime ( ) {
var now = new Date ( ) . getTime ( ) / 1000 ;
return now ;
2013-11-20 11:24:37 +00:00
}
2014-04-12 12:55:20 +00:00
function millitime ( ) {
var now = new Date ( ) . getTime ( ) ;
return now ;
}
2014-06-25 07:18:01 +00:00
function bytesToSize ( bytes ) {
2014-08-09 17:38:46 +00:00
if ( bytes < 1024 ) {
bytes = bytes + ' Bytes' ;
} else if ( bytes < 1048576 ) {
bytes = ( bytes / 1024 ) . toFixed ( 3 ) + ' KB' ;
} else if ( bytes < 1073741824 ) {
bytes = ( bytes / 1048576 ) . toFixed ( 3 ) + ' MB' ;
} else {
bytes = ( bytes / 1073741824 ) . toFixed ( 3 ) + ' GB' ;
}
return bytes ;
2014-10-05 17:46:27 +00:00
}
Number . prototype . clamp = function ( min , max ) {
return Math . min ( Math . max ( this , min ) , max ) ;
} ;