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');
|
2014-07-20 00:01:25 +00:00
|
|
|
var googleAnalytics = googleAnalyticsService.getTracker(atob("VUEtNTI4MjA5MjAtMQ=="));
|
2014-07-16 10:59:12 +00:00
|
|
|
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
|
|
|
|
2014-10-12 14:05:35 +00:00
|
|
|
$('#status-bar .version').text(chrome.runtime.getManifest().version);
|
|
|
|
|
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');
|
2015-01-03 22:30:40 +00:00
|
|
|
GUI.log('You are using an old version of ' + chrome.runtime.getManifest().name + '. There may be a more recent version with improvements and fixes.');
|
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
|
|
|
|
2014-09-08 15:52:07 +00:00
|
|
|
if (!CONFIGURATOR.connectionValid) {
|
2015-01-08 11:38:10 +00:00
|
|
|
GUI.log(chrome.i18n.getMessage('tabSwitchConnectionRequired'));
|
2013-04-08 19:10:47 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-03-08 05:25:15 +00:00
|
|
|
|
2015-01-06 19:35:58 +00:00
|
|
|
if (CONFIGURATOR.connectionValidCliOnly) {
|
2015-01-08 01:50:35 +00:00
|
|
|
GUI.log(chrome.i18n.getMessage('tabSwitchUpgradeRequired'));
|
2015-01-06 19:35:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
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-03-15 14:43:08 +00:00
|
|
|
|
2014-08-09 17:38:46 +00:00
|
|
|
function content_ready() {
|
|
|
|
GUI.tab_switch_in_progress = false;
|
|
|
|
}
|
|
|
|
|
2013-12-09 18:34:34 +00:00
|
|
|
switch (tab) {
|
2014-12-18 22:38:55 +00:00
|
|
|
case 'tab_auxiliary':
|
|
|
|
TABS.auxiliary.initialize(content_ready);
|
|
|
|
break;
|
|
|
|
case 'tab_adjustments':
|
|
|
|
TABS.adjustments.initialize(content_ready);
|
|
|
|
break;
|
2015-01-02 00:05:09 +00:00
|
|
|
case 'tab_ports':
|
|
|
|
TABS.ports.initialize(content_ready);
|
|
|
|
break;
|
2014-12-18 22:38:55 +00:00
|
|
|
|
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);
|
2013-12-09 18:34:34 +00:00
|
|
|
break;
|
|
|
|
case 'tab_pid_tuning':
|
2014-08-12 13:51:31 +00:00
|
|
|
TABS.pid_tuning.initialize(content_ready);
|
2013-12-09 18:34:34 +00:00
|
|
|
break;
|
|
|
|
case 'tab_receiver':
|
2014-08-12 13:51:31 +00:00
|
|
|
TABS.receiver.initialize(content_ready);
|
2013-12-09 18:34:34 +00:00
|
|
|
break;
|
2014-10-30 11:43:35 +00:00
|
|
|
case 'tab_modes':
|
|
|
|
TABS.modes.initialize(content_ready);
|
2014-11-09 00:46:12 +00:00
|
|
|
break;
|
2013-12-09 18:34:34 +00:00
|
|
|
case 'tab_servos':
|
2014-08-12 13:51:31 +00:00
|
|
|
TABS.servos.initialize(content_ready);
|
2013-12-09 18:34:34 +00:00
|
|
|
break;
|
|
|
|
case 'tab_gps':
|
2014-08-12 13:51:31 +00:00
|
|
|
TABS.gps.initialize(content_ready);
|
2013-12-09 18:34:34 +00:00
|
|
|
break;
|
2014-10-30 11:43:35 +00:00
|
|
|
case 'tab_motors':
|
|
|
|
TABS.motors.initialize(content_ready);
|
2013-12-09 18:34:34 +00:00
|
|
|
break;
|
|
|
|
case 'tab_sensors':
|
2014-08-12 13:51:31 +00:00
|
|
|
TABS.sensors.initialize(content_ready);
|
2014-03-08 05:25:15 +00:00
|
|
|
break;
|
2014-05-22 10:13:16 +00:00
|
|
|
case 'tab_logging':
|
2014-08-12 13:51:31 +00:00
|
|
|
TABS.logging.initialize(content_ready);
|
2014-05-22 10:13:16 +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');
|
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-11-20 18:29:43 +00:00
|
|
|
if (typeof 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');
|
2014-11-20 18:29:43 +00:00
|
|
|
googleAnalytics.sendEvent('Settings', 'Notifications', check);
|
2014-04-22 14:16:22 +00:00
|
|
|
|
|
|
|
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-11-20 18:29:43 +00:00
|
|
|
var check = $(this).is(':checked');
|
|
|
|
googleAnalytics.sendEvent('Settings', 'GoogleAnalytics', check);
|
|
|
|
googleAnalyticsConfig.setTrackingPermitted(check);
|
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-04-22 14:16:22 +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-04-22 14:16:22 +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-11-09 00:46:12 +00:00
|
|
|
}
|
2014-10-05 17:46:27 +00:00
|
|
|
|
|
|
|
Number.prototype.clamp = function(min, max) {
|
|
|
|
return Math.min(Math.max(this, min), max);
|
2014-12-19 02:58:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* String formatting now supports currying (partial application).
|
|
|
|
* For a format string with N replacement indices, you can call .format
|
|
|
|
* with M <= N arguments. The result is going to be a format string
|
|
|
|
* with N-M replacement indices, properly counting from 0 .. N-M.
|
2014-12-19 03:05:25 +00:00
|
|
|
* The following Example should explain the usage of partial applied format:
|
2014-12-19 02:58:42 +00:00
|
|
|
* "{0}:{1}:{2}".format("a","b","c") === "{0}:{1}:{2}".format("a","b").format("c")
|
|
|
|
* "{0}:{1}:{2}".format("a").format("b").format("c") === "{0}:{1}:{2}".format("a").format("b", "c")
|
|
|
|
**/
|
|
|
|
String.prototype.format = function () {
|
|
|
|
var args = arguments;
|
|
|
|
return this.replace(/\{(\d+)\}/g, function (t, i) {
|
|
|
|
return args[i] !== void 0 ? args[i] : "{"+(i-args.length)+"}";
|
|
|
|
});
|
2015-01-07 08:21:42 +00:00
|
|
|
};
|