diff --git a/src/js/main.js b/src/js/main.js index 58b9b710..b41bb26c 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -1,7 +1,7 @@ 'use strict'; -var googleAnalytics = analytics; -var analytics = undefined; +window.googleAnalytics = analytics; +window.analytics = null; $(document).ready(function () { $.getJSON('version.json', function(data) { @@ -10,7 +10,7 @@ $(document).ready(function () { // Version in the ChromeApp's manifest takes precedence. if(chrome.runtime && chrome.runtime.getManifest) { - var manifest = chrome.runtime.getManifest(); + const manifest = chrome.runtime.getManifest(); CONFIGURATOR.version = manifest.version; // manifest.json for ChromeApp can't have a version // with a prerelease tag eg 10.0.0-RC4 @@ -22,8 +22,8 @@ $(document).ready(function () { i18n.init(function() { startProcess(); - checkSetupAnalytics(function (analytics) { - analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'SelectedLanguage', i18n.selectedLanguage); + checkSetupAnalytics(function (analyticsService) { + analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'SelectedLanguage', i18n.selectedLanguage); }); initializeSerialBackend(); @@ -45,29 +45,30 @@ function checkSetupAnalytics(callback) { } else if (callback) { callback(analytics); } -}; +} function getBuildType() { return GUI.Mode; } function setupAnalytics(result) { - var userId; + let userId; if (result.userId) { userId = result.userId; } else { - var uid = new ShortUniqueId(); + const uid = new ShortUniqueId(); userId = uid.randomUUID(13); ConfigStorage.set({ 'userId': userId }); } - var optOut = !!result.analyticsOptOut; - var checkForDebugVersions = !!result.checkForConfiguratorUnstableVersions; + const optOut = !!result.analyticsOptOut; + const checkForDebugVersions = !!result.checkForConfiguratorUnstableVersions; - var debugMode = typeof process === "object" && process.versions['nw-flavor'] === 'sdk'; + const debugMode = typeof process === "object" && process.versions['nw-flavor'] === 'sdk'; - analytics = new Analytics('UA-123002063-1', userId, 'Betaflight Configurator', CONFIGURATOR.version, CONFIGURATOR.gitChangesetId, GUI.operating_system, checkForDebugVersions, optOut, debugMode, getBuildType()); + window.analytics = new Analytics('UA-123002063-1', userId, 'Betaflight Configurator', CONFIGURATOR.version, CONFIGURATOR.gitChangesetId, GUI.operating_system, + checkForDebugVersions, optOut, debugMode, getBuildType()); function logException(exception) { analytics.sendException(exception.stack); @@ -80,11 +81,11 @@ function setupAnalytics(result) { analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppStart', { sessionControl: 'start' }); function sendCloseEvent() { - analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' }) + analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' }); } if (GUI.isNWJS()) { - var win = GUI.nwGui.Window.get(); + const win = GUI.nwGui.Window.get(); win.on('close', function () { sendCloseEvent(); @@ -110,30 +111,15 @@ function startProcess() { // translate to user-selected language i18n.localizePage(); - // alternative - window.navigator.appVersion.match(/Chrome\/([0-9.]*)/)[1]; - GUI.log(i18n.getMessage('infoVersions', { operatingSystem: GUI.operating_system, - chromeVersion: window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/, "$1"), - configuratorVersion: CONFIGURATOR.version })); + GUI.log(i18n.getMessage('infoVersions', { + operatingSystem: GUI.operating_system, + chromeVersion: window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/, "$1"), + configuratorVersion: CONFIGURATOR.version })); $('#logo .version').text(CONFIGURATOR.version); updateStatusBarVersion(); updateTopBarVersion(); - // notification messages for various operating systems - switch (GUI.operating_system) { - case 'Windows': - break; - case 'MacOS': - // var main_chromium_version = window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/,"$1").split('.')[0]; - break; - case 'ChromeOS': - break; - case 'Linux': - break; - case 'UNIX': - break; - } - if (!GUI.isOther() && GUI.operating_system !== 'ChromeOS') { checkForConfiguratorUpdates(); } @@ -141,29 +127,29 @@ function startProcess() { // 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'); + document.createElement('canvas'); // log library versions in console to make version tracking easier - console.log('Libraries: jQuery - ' + $.fn.jquery + ', d3 - ' + d3.version + ', three.js - ' + THREE.REVISION); + console.log(`Libraries: jQuery - ${$.fn.jquery}, d3 - ${d3.version}, three.js - ${THREE.REVISION}`); // Tabs $("#tabs ul.mode-connected li").click(function() { // store the first class of the current tab (omit things like ".active") - ConfigStorage.set({ - lastTab: $(this).attr("class").split(' ')[0] - }); + ConfigStorage.set( + {lastTab: $(this).attr("class").split(' ')[0]} + ); }); - var ui_tabs = $('#tabs > ul'); + const ui_tabs = $('#tabs > ul'); $('a', ui_tabs).click(function () { - if ($(this).parent().hasClass('active') == false && !GUI.tab_switch_in_progress) { // only initialize when the tab isn't already active - var self = this, - tabClass = $(self).parent().prop('class'); + if ($(this).parent().hasClass('active') === false && !GUI.tab_switch_in_progress) { // only initialize when the tab isn't already active + const self = this; + const tabClass = $(self).parent().prop('class'); - var tabRequiresConnection = $(self).parent().hasClass('mode-connected'); + const tabRequiresConnection = $(self).parent().hasClass('mode-connected'); - var tab = tabClass.substring(4); - var tabName = $(self).text(); + const tab = tabClass.substring(4); + const tabName = $(self).text(); if (tabRequiresConnection && !CONFIGURATOR.connectionValid) { GUI.log(i18n.getMessage('tabSwitchConnectionRequired')); @@ -175,7 +161,7 @@ function startProcess() { return; } - if (GUI.allowedTabs.indexOf(tab) < 0 && tabName == "Firmware Flasher") { + if (GUI.allowedTabs.indexOf(tab) < 0 && tabName === "Firmware Flasher") { if (GUI.connected_to || GUI.connecting_to) { $('a.connect').click(); } else { @@ -202,7 +188,7 @@ function startProcess() { $(self).parent().addClass('active'); // detach listeners and remove element data - var content = $('#content'); + const content = $('#content'); content.empty(); // display loading screen @@ -212,8 +198,8 @@ function startProcess() { GUI.tab_switch_in_progress = false; } - checkSetupAnalytics(function (analytics) { - analytics.sendAppView(tab); + checkSetupAnalytics(function (analyticsService) { + analyticsService.sendAppView(tab); }); switch (tab) { @@ -298,7 +284,7 @@ function startProcess() { break; default: - console.log('Tab not found:' + tab); + console.log(`Tab not found: ${tab}`); } }); } @@ -308,7 +294,7 @@ function startProcess() { // options $('a#options').click(function () { - var el = $(this); + const el = $(this); if (!el.hasClass('active')) { el.addClass('active'); @@ -324,7 +310,7 @@ function startProcess() { } $('div.permanentExpertMode input').change(function () { - var checked = $(this).is(':checked'); + const checked = $(this).is(':checked'); ConfigStorage.set({'permanentExpertMode': checked}); @@ -335,7 +321,7 @@ function startProcess() { ConfigStorage.get('rememberLastTab', function (result) { $('div.rememberLastTab input') .prop('checked', !!result.rememberLastTab) - .change(function() { ConfigStorage.set({rememberLastTab: $(this).is(':checked')}) }) + .change(function() { ConfigStorage.set({rememberLastTab: $(this).is(':checked')}); }) .change(); }); @@ -346,7 +332,7 @@ function startProcess() { } $('div.checkForConfiguratorUnstableVersions input').change(function () { - var checked = $(this).is(':checked'); + const checked = $(this).is(':checked'); ConfigStorage.set({'checkForConfiguratorUnstableVersions': checked}); @@ -363,19 +349,19 @@ function startProcess() { } $('div.analyticsOptOut input').change(function () { - var checked = $(this).is(':checked'); + const checked = $(this).is(':checked'); ConfigStorage.set({'analyticsOptOut': checked}); - checkSetupAnalytics(function (analytics) { + checkSetupAnalytics(function (analyticsService) { if (checked) { - analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'OptOut'); + analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'OptOut'); } - analytics.setOptOut(checked); + analyticsService.setOptOut(checked); if (!checked) { - analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'OptIn'); + analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'OptIn'); } }); }).change(); @@ -384,7 +370,7 @@ function startProcess() { $('div.cliAutoComplete input') .prop('checked', CliAutoComplete.configEnabled) .change(function () { - var checked = $(this).is(':checked'); + const checked = $(this).is(':checked'); ConfigStorage.set({'cliAutoComplete': checked}); CliAutoComplete.setEnabled(checked); @@ -393,14 +379,14 @@ function startProcess() { $('#darkThemeSelect') .val(DarkTheme.configEnabled) .change(function () { - var value = parseInt($(this).val()); + const value = parseInt($(this).val()); ConfigStorage.set({'darkTheme': value}); setDarkTheme(value); }).change(); function close_and_cleanup(e) { - if (e.type == 'click' && !$.contains($('div#options-window')[0], e.target) || e.type == 'keyup' && e.keyCode == 27) { + if (e.type === 'click' && !$.contains($('div#options-window')[0], e.target) || e.type === 'keyup' && e.keyCode === 27) { $(document).unbind('click keyup', close_and_cleanup); $('div#options-window').slideUp(250, function () { @@ -419,8 +405,8 @@ function startProcess() { // listen to all input change events and adjust the value within limits if necessary $("#content").on('focus', 'input[type="number"]', function () { - var element = $(this), - val = element.val(); + const element = $(this); + const val = element.val(); if (!isNaN(val)) { element.data('previousValue', parseFloat(val)); @@ -429,41 +415,37 @@ function startProcess() { $("#content").on('keydown', 'input[type="number"]', function (e) { // whitelist all that we need for numeric control - var whitelist = [ + const 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 + 37, 38, 39, 40, 13, // arrows and enter ]; - if (whitelist.indexOf(e.keyCode) == -1) { + if (whitelist.indexOf(e.keyCode) === -1) { e.preventDefault(); } }); $("#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; + const element = $(this); + const min = parseFloat(element.prop('min')); + const max = parseFloat(element.prop('max')); + const step = parseFloat(element.prop('step')); + + let val = parseFloat(element.val()); // only adjust minimal end if bound is set - if (element.prop('min')) { - if (val < min) { - element.val(min); - val = min; - } + if (element.prop('min') && val < min) { + element.val(min); + val = min; } // only adjust maximal end if bound is set - if (element.prop('max')) { - if (val > max) { - element.val(max); - val = max; - } + if (element.prop('max') && val > max) { + element.val(max); + val = max; } // if entered value is illegal use previous value instead @@ -473,30 +455,26 @@ function startProcess() { } // 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')); - val = element.data('previousValue'); - } + if ((isNaN(step) || step % 1 === 0) && val % 1 !== 0) { + element.val(element.data('previousValue')); + val = element.data('previousValue'); } // 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) { - decimal_places = String(step).split('.')[1].length; + const decimal_places = String(step).split('.')[1].length; - if (val % 1 === 0) { - element.val(val.toFixed(decimal_places)); - } else if (String(val).split('.')[1].length != decimal_places) { + if (val % 1 === 0 || String(val).split('.')[1].length !== decimal_places) { element.val(val.toFixed(decimal_places)); } } }); $("#showlog").on('click', function () { - var state = $(this).data('state'); + let state = $(this).data('state'); if (state) { $("#log").animate({height: 27}, 200, function () { - var command_log = $('div#log'); + const command_log = $('div#log'); command_log.scrollTop($('div.wrapper', command_log).height()); }); $("#log").removeClass('active'); @@ -532,9 +510,9 @@ function startProcess() { } $('input[name="expertModeCheckbox"]').change(function () { - var checked = $(this).is(':checked'); - checkSetupAnalytics(function (analytics) { - analytics.setDimension(analytics.DIMENSIONS.CONFIGURATOR_EXPERT_MODE, checked ? 'On' : 'Off'); + const checked = $(this).is(':checked'); + checkSetupAnalytics(function (analyticsService) { + analyticsService.setDimension(analyticsService.DIMENSIONS.CONFIGURATOR_EXPERT_MODE, checked ? 'On' : 'Off'); }); if (FEATURE_CONFIG && FEATURE_CONFIG.features !== 0) { @@ -555,33 +533,35 @@ function startProcess() { setDarkTheme(result.darkTheme); } }); -}; +} function setDarkTheme(enabled) { DarkTheme.setConfig(enabled); - checkSetupAnalytics(function (analytics) { - analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'DarkTheme', enabled); + checkSetupAnalytics(function (analyticsService) { + analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'DarkTheme', enabled); }); } function checkForConfiguratorUpdates() { - var releaseChecker = new ReleaseChecker('configurator', 'https://api.github.com/repos/betaflight/betaflight-configurator/releases'); + const releaseChecker = new ReleaseChecker('configurator', 'https://api.github.com/repos/betaflight/betaflight-configurator/releases'); releaseChecker.loadReleaseData(notifyOutdatedVersion); } function notifyOutdatedVersion(releaseData) { ConfigStorage.get('checkForConfiguratorUnstableVersions', function (result) { - var showUnstableReleases = false; + let showUnstableReleases = false; if (result.checkForConfiguratorUnstableVersions) { showUnstableReleases = true; } - var versions = releaseData.filter(function (version) { - var semVerVersion = semver.parse(version.tag_name); - if (semVerVersion && (showUnstableReleases || semVerVersion.prerelease.length === 0)) { - return version; - } + const versions = releaseData.filter(function (version) { + const semVerVersion = semver.parse(version.tag_name); + if (semVerVersion && (showUnstableReleases || semVerVersion.prerelease.length === 0)) { + return version; + } else { + return null; + } }).sort(function (v1, v2) { try { return semver.compare(v2.tag_name, v1.tag_name); @@ -593,7 +573,7 @@ function notifyOutdatedVersion(releaseData) { if (versions.length > 0 && semver.lt(CONFIGURATOR.version, versions[0].tag_name)) { GUI.log(i18n.getMessage('configuratorUpdateNotice', [versions[0].tag_name, versions[0].html_url])); - var dialog = $('.dialogConfiguratorUpdate')[0]; + const dialog = $('.dialogConfiguratorUpdate')[0]; $('.dialogConfiguratorUpdate-content').html(i18n.getMessage('configuratorUpdateNotice', [versions[0].tag_name, versions[0].html_url])); @@ -617,35 +597,34 @@ function update_packet_error(caller) { } function microtime() { - var now = new Date().getTime() / 1000; - - return now; + return new Date().getTime() / 1000; } function millitime() { - var now = new Date().getTime(); - - return now; + return new Date().getTime(); } -var DEGREE_TO_RADIAN_RATIO = Math.PI / 180; +const DEGREE_TO_RADIAN_RATIO = Math.PI / 180; function degToRad(degrees) { return degrees * DEGREE_TO_RADIAN_RATIO; } function bytesToSize(bytes) { + + let outputBytes; + if (bytes < 1024) { - bytes = bytes + ' Bytes'; + outputBytes = `${bytes} Bytes`; } else if (bytes < 1048576) { - bytes = (bytes / 1024).toFixed(3) + ' KB'; + outputBytes = `${(bytes / 1024).toFixed(3)} KB`; } else if (bytes < 1073741824) { - bytes = (bytes / 1048576).toFixed(3) + ' MB'; + outputBytes = `${(bytes / 1048576).toFixed(3)} MB`; } else { - bytes = (bytes / 1073741824).toFixed(3) + ' GB'; + outputBytes = `${(bytes / 1073741824).toFixed(3)} GB`; } - return bytes; + return outputBytes; } function isExpertModeEnabled() { @@ -707,95 +686,94 @@ function updateTabList(features) { } function zeroPad(value, width) { - value = "" + value; - while (value.length < width) { - value = "0" + value; + let valuePadded = String(value); + + while (valuePadded.length < width) { + valuePadded = `0${value}`; } - return value; + return valuePadded; } function generateFilename(prefix, suffix) { - var date = new Date(); - var filename = prefix; + const date = new Date(); + let filename = prefix; if (CONFIG) { if (CONFIG.flightControllerIdentifier) { - filename = CONFIG.flightControllerIdentifier + '_' + filename; + filename = `${CONFIG.flightControllerIdentifier}_${filename}`; } if(CONFIG.name && CONFIG.name.trim() !== '') { - filename = filename + '_' + CONFIG.name.trim().replace(' ', '_'); + filename = `${filename}_${CONFIG.name.trim().replace(' ', '_')}`; } } - filename = filename + '_' + date.getFullYear() - + zeroPad(date.getMonth() + 1, 2) - + zeroPad(date.getDate(), 2) - + '_' + zeroPad(date.getHours(), 2) - + zeroPad(date.getMinutes(), 2) - + zeroPad(date.getSeconds(), 2); + const yyyymmdd = `${date.getFullYear()}${zeroPad(date.getMonth() + 1, 2)}${zeroPad(date.getDate(), 2)}`; + const hhmmss = `${zeroPad(date.getHours(), 2)}${zeroPad(date.getMinutes(), 2)}${zeroPad(date.getSeconds(), 2)}`; + filename = `${filename}_${yyyymmdd}_${hhmmss}`; - return filename + '.' + suffix; + return `${filename}.${suffix}`; } function getTargetVersion(hardwareId) { - var versionText = ''; + let versionText = ''; if (hardwareId) { - versionText += i18n.getMessage('versionLabelTarget') + ': ' + hardwareId; + versionText = `${i18n.getMessage('versionLabelTarget')}: ${hardwareId}`; } return versionText; } function getFirmwareVersion(firmwareVersion, firmwareId) { - var versionText = ''; + let versionText = ''; if (firmwareVersion) { - versionText += i18n.getMessage('versionLabelFirmware') + ': ' + firmwareId + ' ' + firmwareVersion; + versionText = `${i18n.getMessage('versionLabelFirmware')}: ${firmwareId} ${firmwareVersion}`; } return versionText; } function getConfiguratorVersion() { - return i18n.getMessage('versionLabelConfigurator') + ': ' + CONFIGURATOR.version; + return `${i18n.getMessage('versionLabelConfigurator')}: ${CONFIGURATOR.version}`; } function updateTopBarVersion(firmwareVersion, firmwareId, hardwareId) { - var versionText = getConfiguratorVersion() + '
'; - versionText = versionText + getFirmwareVersion(firmwareVersion, firmwareId) + '
'; + const configuratorVersion = getConfiguratorVersion(); + const firmwareVersionAndId = getFirmwareVersion(firmwareVersion, firmwareId); + const targetVersion = getTargetVersion(hardwareId); - versionText = versionText + getTargetVersion(hardwareId); + const versionText = `${configuratorVersion}
${firmwareVersionAndId}
${targetVersion}`; $('#logo .logo_text').html(versionText); } function updateStatusBarVersion(firmwareVersion, firmwareId, hardwareId) { - var versionText = ''; + let versionText = ''; versionText = versionText + getFirmwareVersion(firmwareVersion, firmwareId); if (versionText !== '') { - versionText = versionText + ', '; + versionText = `${versionText}, `; } - let targetVersion = getTargetVersion(hardwareId); + const targetVersion = getTargetVersion(hardwareId); versionText = versionText + targetVersion; if (targetVersion !== '') { - versionText = versionText + ', '; + versionText = `${versionText}, `; } - versionText = versionText + getConfiguratorVersion() + ' (' + CONFIGURATOR.gitChangesetId + ')'; + versionText = `${versionText}${getConfiguratorVersion()} (${CONFIGURATOR.gitChangesetId})`; $('#status-bar .version').text(versionText); } function showErrorDialog(message) { - var dialog = $('.dialogError')[0]; + const dialog = $('.dialogError')[0]; $('.dialogError-content').html(message);