diff --git a/client/public/javascripts/svg-inject.js b/client/public/javascripts/svg-inject.js deleted file mode 100644 index 4e74af07..00000000 --- a/client/public/javascripts/svg-inject.js +++ /dev/null @@ -1,697 +0,0 @@ -/** - * SVGInject - Version 1.2.3 - * A tiny, intuitive, robust, caching solution for injecting SVG files inline into the DOM. - * - * https://github.com/iconfu/svg-inject - * - * Copyright (c) 2018 INCORS, the creators of iconfu.com - * @license MIT License - https://github.com/iconfu/svg-inject/blob/master/LICENSE - */ - -(function(window, document) { - // constants for better minification - var _CREATE_ELEMENT_ = 'createElement'; - var _GET_ELEMENTS_BY_TAG_NAME_ = 'getElementsByTagName'; - var _LENGTH_ = 'length'; - var _STYLE_ = 'style'; - var _TITLE_ = 'title'; - var _UNDEFINED_ = 'undefined'; - var _SET_ATTRIBUTE_ = 'setAttribute'; - var _GET_ATTRIBUTE_ = 'getAttribute'; - - var NULL = null; - - // constants - var __SVGINJECT = '__svgInject'; - var ID_SUFFIX = '--inject-'; - var ID_SUFFIX_REGEX = new RegExp(ID_SUFFIX + '\\d+', "g"); - var LOAD_FAIL = 'LOAD_FAIL'; - var SVG_NOT_SUPPORTED = 'SVG_NOT_SUPPORTED'; - var SVG_INVALID = 'SVG_INVALID'; - var ATTRIBUTE_EXCLUSION_NAMES = ['src', 'alt', 'onload', 'onerror']; - var A_ELEMENT = document[_CREATE_ELEMENT_]('a'); - var IS_SVG_SUPPORTED = typeof SVGRect != _UNDEFINED_; - var DEFAULT_OPTIONS = { - useCache: true, - copyAttributes: true, - makeIdsUnique: true - }; - // Map of IRI referenceable tag names to properties that can reference them. This is defined in - // https://www.w3.org/TR/SVG11/linking.html#processingIRI - var IRI_TAG_PROPERTIES_MAP = { - clipPath: ['clip-path'], - 'color-profile': NULL, - cursor: NULL, - filter: NULL, - linearGradient: ['fill', 'stroke'], - marker: ['marker', 'marker-end', 'marker-mid', 'marker-start'], - mask: NULL, - pattern: ['fill', 'stroke'], - radialGradient: ['fill', 'stroke'] - }; - var INJECTED = 1; - var FAIL = 2; - - var uniqueIdCounter = 1; - var xmlSerializer; - var domParser; - - - // creates an SVG document from an SVG string - function svgStringToSvgDoc(svgStr) { - domParser = domParser || new DOMParser(); - return domParser.parseFromString(svgStr, 'text/xml'); - } - - - // searializes an SVG element to an SVG string - function svgElemToSvgString(svgElement) { - xmlSerializer = xmlSerializer || new XMLSerializer(); - return xmlSerializer.serializeToString(svgElement); - } - - - // Returns the absolute url for the specified url - function getAbsoluteUrl(url) { - A_ELEMENT.href = url; - return A_ELEMENT.href; - } - - - // Load svg with an XHR request - function loadSvg(url, callback, errorCallback) { - if (url) { - var req = new XMLHttpRequest(); - req.onreadystatechange = function() { - if (req.readyState == 4) { - // readyState is DONE - var status = req.status; - if (status == 200) { - // request status is OK - callback(req.responseXML, req.responseText.trim()); - } else if (status >= 400) { - // request status is error (4xx or 5xx) - errorCallback(); - } else if (status == 0) { - // request status 0 can indicate a failed cross-domain call - errorCallback(); - } - } - }; - req.open('GET', url, true); - req.send(); - } - } - - - // Copy attributes from img element to svg element - function copyAttributes(imgElem, svgElem) { - var attribute; - var attributeName; - var attributeValue; - var attributes = imgElem.attributes; - for (var i = 0; i < attributes[_LENGTH_]; i++) { - attribute = attributes[i]; - attributeName = attribute.name; - // Only copy attributes not explicitly excluded from copying - if (ATTRIBUTE_EXCLUSION_NAMES.indexOf(attributeName) == -1) { - attributeValue = attribute.value; - // If img attribute is "title", insert a title element into SVG element - if (attributeName == _TITLE_) { - var titleElem; - var firstElementChild = svgElem.firstElementChild; - if (firstElementChild && firstElementChild.localName.toLowerCase() == _TITLE_) { - // If the SVG element's first child is a title element, keep it as the title element - titleElem = firstElementChild; - } else { - // If the SVG element's first child element is not a title element, create a new title - // ele,emt and set it as the first child - titleElem = document[_CREATE_ELEMENT_ + 'NS']('http://www.w3.org/2000/svg', _TITLE_); - svgElem.insertBefore(titleElem, firstElementChild); - } - // Set new title content - titleElem.textContent = attributeValue; - } else { - // Set img attribute to svg element - svgElem[_SET_ATTRIBUTE_](attributeName, attributeValue); - } - } - } - } - - - // This function appends a suffix to IDs of referenced elements in the in order to to avoid ID collision - // between multiple injected SVGs. The suffix has the form "--inject-X", where X is a running number which is - // incremented with each injection. References to the IDs are adjusted accordingly. - // We assume tha all IDs within the injected SVG are unique, therefore the same suffix can be used for all IDs of one - // injected SVG. - // If the onlyReferenced argument is set to true, only those IDs will be made unique that are referenced from within the SVG - function makeIdsUnique(svgElem, onlyReferenced) { - var idSuffix = ID_SUFFIX + uniqueIdCounter++; - // Regular expression for functional notations of an IRI references. This will find occurences in the form - // url(#anyId) or url("#anyId") (for Internet Explorer) and capture the referenced ID - var funcIriRegex = /url\("?#([a-zA-Z][\w:.-]*)"?\)/g; - // Get all elements with an ID. The SVG spec recommends to put referenced elements inside elements, but - // this is not a requirement, therefore we have to search for IDs in the whole SVG. - var idElements = svgElem.querySelectorAll('[id]'); - var idElem; - // An object containing referenced IDs as keys is used if only referenced IDs should be uniquified. - // If this object does not exist, all IDs will be uniquified. - var referencedIds = onlyReferenced ? [] : NULL; - var tagName; - var iriTagNames = {}; - var iriProperties = []; - var changed = false; - var i, j; - - if (idElements[_LENGTH_]) { - // Make all IDs unique by adding the ID suffix and collect all encountered tag names - // that are IRI referenceable from properities. - for (i = 0; i < idElements[_LENGTH_]; i++) { - tagName = idElements[i].localName; // Use non-namespaced tag name - // Make ID unique if tag name is IRI referenceable - if (tagName in IRI_TAG_PROPERTIES_MAP) { - iriTagNames[tagName] = 1; - } - } - // Get all properties that are mapped to the found IRI referenceable tags - for (tagName in iriTagNames) { - (IRI_TAG_PROPERTIES_MAP[tagName] || [tagName]).forEach(function (mappedProperty) { - // Add mapped properties to array of iri referencing properties. - // Use linear search here because the number of possible entries is very small (maximum 11) - if (iriProperties.indexOf(mappedProperty) < 0) { - iriProperties.push(mappedProperty); - } - }); - } - if (iriProperties[_LENGTH_]) { - // Add "style" to properties, because it may contain references in the form 'style="fill:url(#myFill)"' - iriProperties.push(_STYLE_); - } - // Run through all elements of the SVG and replace IDs in references. - // To get all descending elements, getElementsByTagName('*') seems to perform faster than querySelectorAll('*'). - // Since svgElem.getElementsByTagName('*') does not return the svg element itself, we have to handle it separately. - var descElements = svgElem[_GET_ELEMENTS_BY_TAG_NAME_]('*'); - var element = svgElem; - var propertyName; - var value; - var newValue; - for (i = -1; element != NULL;) { - if (element.localName == _STYLE_) { - // If element is a style element, replace IDs in all occurences of "url(#anyId)" in text content - value = element.textContent; - newValue = value && value.replace(funcIriRegex, function(match, id) { - if (referencedIds) { - referencedIds[id] = 1; - } - return 'url(#' + id + idSuffix + ')'; - }); - if (newValue !== value) { - element.textContent = newValue; - } - } else if (element.hasAttributes()) { - // Run through all property names for which IDs were found - for (j = 0; j < iriProperties[_LENGTH_]; j++) { - propertyName = iriProperties[j]; - value = element[_GET_ATTRIBUTE_](propertyName); - newValue = value && value.replace(funcIriRegex, function(match, id) { - if (referencedIds) { - referencedIds[id] = 1; - } - return 'url(#' + id + idSuffix + ')'; - }); - if (newValue !== value) { - element[_SET_ATTRIBUTE_](propertyName, newValue); - } - } - // Replace IDs in xlink:ref and href attributes - ['xlink:href', 'href'].forEach(function(refAttrName) { - var iri = element[_GET_ATTRIBUTE_](refAttrName); - if (/^\s*#/.test(iri)) { // Check if iri is non-null and internal reference - iri = iri.trim(); - element[_SET_ATTRIBUTE_](refAttrName, iri + idSuffix); - if (referencedIds) { - // Add ID to referenced IDs - referencedIds[iri.substring(1)] = 1; - } - } - }); - } - element = descElements[++i]; - } - for (i = 0; i < idElements[_LENGTH_]; i++) { - idElem = idElements[i]; - // If set of referenced IDs exists, make only referenced IDs unique, - // otherwise make all IDs unique. - if (!referencedIds || referencedIds[idElem.id]) { - // Add suffix to element's ID - idElem.id += idSuffix; - changed = true; - } - } - } - // return true if SVG element has changed - return changed; - } - - - // For cached SVGs the IDs are made unique by simply replacing the already inserted unique IDs with a - // higher ID counter. This is much more performant than a call to makeIdsUnique(). - function makeIdsUniqueCached(svgString) { - return svgString.replace(ID_SUFFIX_REGEX, ID_SUFFIX + uniqueIdCounter++); - } - - - // Inject SVG by replacing the img element with the SVG element in the DOM - function inject(imgElem, svgElem, absUrl, options) { - if (svgElem) { - svgElem[_SET_ATTRIBUTE_]('data-inject-url', absUrl); - var parentNode = imgElem.parentNode; - if (parentNode) { - if (options.copyAttributes) { - copyAttributes(imgElem, svgElem); - } - // Invoke beforeInject hook if set - var beforeInject = options.beforeInject; - var injectElem = (beforeInject && beforeInject(imgElem, svgElem)) || svgElem; - // Replace img element with new element. This is the actual injection. - parentNode.replaceChild(injectElem, imgElem); - // Mark img element as injected - imgElem[__SVGINJECT] = INJECTED; - removeOnLoadAttribute(imgElem); - // Invoke afterInject hook if set - var afterInject = options.afterInject; - if (afterInject) { - afterInject(imgElem, injectElem); - } - } - } else { - svgInvalid(imgElem, options); - } - } - - - // Merges any number of options objects into a new object - function mergeOptions() { - var mergedOptions = {}; - var args = arguments; - // Iterate over all specified options objects and add all properties to the new options object - for (var i = 0; i < args[_LENGTH_]; i++) { - var argument = args[i]; - for (var key in argument) { - if (argument.hasOwnProperty(key)) { - mergedOptions[key] = argument[key]; - } - } - } - return mergedOptions; - } - - - // Adds the specified CSS to the document's element - function addStyleToHead(css) { - var head = document[_GET_ELEMENTS_BY_TAG_NAME_]('head')[0]; - if (head) { - var style = document[_CREATE_ELEMENT_](_STYLE_); - style.type = 'text/css'; - style.appendChild(document.createTextNode(css)); - head.appendChild(style); - } - } - - - // Builds an SVG element from the specified SVG string - function buildSvgElement(svgStr, verify) { - if (verify) { - var svgDoc; - try { - // Parse the SVG string with DOMParser - svgDoc = svgStringToSvgDoc(svgStr); - } catch(e) { - return NULL; - } - if (svgDoc[_GET_ELEMENTS_BY_TAG_NAME_]('parsererror')[_LENGTH_]) { - // DOMParser does not throw an exception, but instead puts parsererror tags in the document - return NULL; - } - return svgDoc.documentElement; - } else { - var div = document.createElement('div'); - div.innerHTML = svgStr; - return div.firstElementChild; - } - } - - - function removeOnLoadAttribute(imgElem) { - // Remove the onload attribute. Should only be used to remove the unstyled image flash protection and - // make the element visible, not for removing the event listener. - imgElem.removeAttribute('onload'); - } - - - function errorMessage(msg) { - console.error('SVGInject: ' + msg); - } - - - function fail(imgElem, status, options) { - imgElem[__SVGINJECT] = FAIL; - if (options.onFail) { - options.onFail(imgElem, status); - } else { - errorMessage(status); - } - } - - - function svgInvalid(imgElem, options) { - removeOnLoadAttribute(imgElem); - fail(imgElem, SVG_INVALID, options); - } - - - function svgNotSupported(imgElem, options) { - removeOnLoadAttribute(imgElem); - fail(imgElem, SVG_NOT_SUPPORTED, options); - } - - - function loadFail(imgElem, options) { - fail(imgElem, LOAD_FAIL, options); - } - - - function removeEventListeners(imgElem) { - imgElem.onload = NULL; - imgElem.onerror = NULL; - } - - - function imgNotSet(msg) { - errorMessage('no img element'); - } - - - function createSVGInject(globalName, options) { - var defaultOptions = mergeOptions(DEFAULT_OPTIONS, options); - var svgLoadCache = {}; - - if (IS_SVG_SUPPORTED) { - // If the browser supports SVG, add a small stylesheet that hides the elements until - // injection is finished. This avoids showing the unstyled SVGs before style is applied. - addStyleToHead('img[onload^="' + globalName + '("]{visibility:hidden;}'); - } - - - /** - * SVGInject - * - * Injects the SVG specified in the `src` attribute of the specified `img` element or array of `img` - * elements. Returns a Promise object which resolves if all passed in `img` elements have either been - * injected or failed to inject (Only if a global Promise object is available like in all modern browsers - * or through a polyfill). - * - * Options: - * useCache: If set to `true` the SVG will be cached using the absolute URL. Default value is `true`. - * copyAttributes: If set to `true` the attributes will be copied from `img` to `svg`. Dfault value - * is `true`. - * makeIdsUnique: If set to `true` the ID of elements in the `` element that can be references by - * property values (for example 'clipPath') are made unique by appending "--inject-X", where X is a - * running number which increases with each injection. This is done to avoid duplicate IDs in the DOM. - * beforeLoad: Hook before SVG is loaded. The `img` element is passed as a parameter. If the hook returns - * a string it is used as the URL instead of the `img` element's `src` attribute. - * afterLoad: Hook after SVG is loaded. The loaded `svg` element and `svg` string are passed as a - * parameters. If caching is active this hook will only get called once for injected SVGs with the - * same absolute path. Changes to the `svg` element in this hook will be applied to all injected SVGs - * with the same absolute path. It's also possible to return an `svg` string or `svg` element which - * will then be used for the injection. - * beforeInject: Hook before SVG is injected. The `img` and `svg` elements are passed as parameters. If - * any html element is returned it gets injected instead of applying the default SVG injection. - * afterInject: Hook after SVG is injected. The `img` and `svg` elements are passed as parameters. - * onAllFinish: Hook after all `img` elements passed to an SVGInject() call have either been injected or - * failed to inject. - * onFail: Hook after injection fails. The `img` element and a `status` string are passed as an parameter. - * The `status` can be either `'SVG_NOT_SUPPORTED'` (the browser does not support SVG), - * `'SVG_INVALID'` (the SVG is not in a valid format) or `'LOAD_FAILED'` (loading of the SVG failed). - * - * @param {HTMLImageElement} img - an img element or an array of img elements - * @param {Object} [options] - optional parameter with [options](#options) for this injection. - */ - function SVGInject(img, options) { - options = mergeOptions(defaultOptions, options); - - var run = function(resolve) { - var allFinish = function() { - var onAllFinish = options.onAllFinish; - if (onAllFinish) { - onAllFinish(); - } - resolve && resolve(); - }; - - if (img && typeof img[_LENGTH_] != _UNDEFINED_) { - // an array like structure of img elements - var injectIndex = 0; - var injectCount = img[_LENGTH_]; - - if (injectCount == 0) { - allFinish(); - } else { - var finish = function() { - if (++injectIndex == injectCount) { - allFinish(); - } - }; - - for (var i = 0; i < injectCount; i++) { - SVGInjectElement(img[i], options, finish); - } - } - } else { - // only one img element - SVGInjectElement(img, options, allFinish); - } - }; - - // return a Promise object if globally available - return typeof Promise == _UNDEFINED_ ? run() : new Promise(run); - } - - - // Injects a single svg element. Options must be already merged with the default options. - function SVGInjectElement(imgElem, options, callback) { - if (imgElem) { - var svgInjectAttributeValue = imgElem[__SVGINJECT]; - if (!svgInjectAttributeValue) { - removeEventListeners(imgElem); - - if (!IS_SVG_SUPPORTED) { - svgNotSupported(imgElem, options); - callback(); - return; - } - // Invoke beforeLoad hook if set. If the beforeLoad returns a value use it as the src for the load - // URL path. Else use the imgElem's src attribute value. - var beforeLoad = options.beforeLoad; - var src = (beforeLoad && beforeLoad(imgElem)) || imgElem[_GET_ATTRIBUTE_]('src'); - - if (!src) { - // If no image src attribute is set do no injection. This can only be reached by using javascript - // because if no src attribute is set the onload and onerror events do not get called - if (src === '') { - loadFail(imgElem, options); - } - callback(); - return; - } - - // set array so later calls can register callbacks - var onFinishCallbacks = []; - imgElem[__SVGINJECT] = onFinishCallbacks; - - var onFinish = function() { - callback(); - onFinishCallbacks.forEach(function(onFinishCallback) { - onFinishCallback(); - }); - }; - - var absUrl = getAbsoluteUrl(src); - var useCacheOption = options.useCache; - var makeIdsUniqueOption = options.makeIdsUnique; - - var setSvgLoadCacheValue = function(val) { - if (useCacheOption) { - svgLoadCache[absUrl].forEach(function(svgLoad) { - svgLoad(val); - }); - svgLoadCache[absUrl] = val; - } - }; - - if (useCacheOption) { - var svgLoad = svgLoadCache[absUrl]; - - var handleLoadValue = function(loadValue) { - if (loadValue === LOAD_FAIL) { - loadFail(imgElem, options); - } else if (loadValue === SVG_INVALID) { - svgInvalid(imgElem, options); - } else { - var hasUniqueIds = loadValue[0]; - var svgString = loadValue[1]; - var uniqueIdsSvgString = loadValue[2]; - var svgElem; - - if (makeIdsUniqueOption) { - if (hasUniqueIds === NULL) { - // IDs for the SVG string have not been made unique before. This may happen if previous - // injection of a cached SVG have been run with the option makedIdsUnique set to false - svgElem = buildSvgElement(svgString, false); - hasUniqueIds = makeIdsUnique(svgElem, false); - - loadValue[0] = hasUniqueIds; - loadValue[2] = hasUniqueIds && svgElemToSvgString(svgElem); - } else if (hasUniqueIds) { - // Make IDs unique for already cached SVGs with better performance - svgString = makeIdsUniqueCached(uniqueIdsSvgString); - } - } - - svgElem = svgElem || buildSvgElement(svgString, false); - - inject(imgElem, svgElem, absUrl, options); - } - onFinish(); - }; - - if (typeof svgLoad != _UNDEFINED_) { - // Value for url exists in cache - if (svgLoad.isCallbackQueue) { - // Same url has been cached, but value has not been loaded yet, so add to callbacks - svgLoad.push(handleLoadValue); - } else { - handleLoadValue(svgLoad); - } - return; - } else { - var svgLoad = []; - // set property isCallbackQueue to Array to differentiate from array with cached loaded values - svgLoad.isCallbackQueue = true; - svgLoadCache[absUrl] = svgLoad; - } - } - - // Load the SVG because it is not cached or caching is disabled - loadSvg(absUrl, function(svgXml, svgString) { - // Use the XML from the XHR request if it is an instance of Document. Otherwise - // (for example of IE9), create the svg document from the svg string. - var svgElem = svgXml instanceof Document ? svgXml.documentElement : buildSvgElement(svgString, true); - - var afterLoad = options.afterLoad; - if (afterLoad) { - // Invoke afterLoad hook which may modify the SVG element. After load may also return a new - // svg element or svg string - var svgElemOrSvgString = afterLoad(svgElem, svgString) || svgElem; - if (svgElemOrSvgString) { - // Update svgElem and svgString because of modifications to the SVG element or SVG string in - // the afterLoad hook, so the modified SVG is also used for all later cached injections - var isString = typeof svgElemOrSvgString == 'string'; - svgString = isString ? svgElemOrSvgString : svgElemToSvgString(svgElem); - svgElem = isString ? buildSvgElement(svgElemOrSvgString, true) : svgElemOrSvgString; - } - } - - if (svgElem instanceof SVGElement) { - var hasUniqueIds = NULL; - if (makeIdsUniqueOption) { - hasUniqueIds = makeIdsUnique(svgElem, false); - } - - if (useCacheOption) { - var uniqueIdsSvgString = hasUniqueIds && svgElemToSvgString(svgElem); - // set an array with three entries to the load cache - setSvgLoadCacheValue([hasUniqueIds, svgString, uniqueIdsSvgString]); - } - - inject(imgElem, svgElem, absUrl, options); - } else { - svgInvalid(imgElem, options); - setSvgLoadCacheValue(SVG_INVALID); - } - onFinish(); - }, function() { - loadFail(imgElem, options); - setSvgLoadCacheValue(LOAD_FAIL); - onFinish(); - }); - } else { - if (Array.isArray(svgInjectAttributeValue)) { - // svgInjectAttributeValue is an array. Injection is not complete so register callback - svgInjectAttributeValue.push(callback); - } else { - callback(); - } - } - } else { - imgNotSet(); - } - } - - - /** - * Sets the default [options](#options) for SVGInject. - * - * @param {Object} [options] - default [options](#options) for an injection. - */ - SVGInject.setOptions = function(options) { - defaultOptions = mergeOptions(defaultOptions, options); - }; - - - // Create a new instance of SVGInject - SVGInject.create = createSVGInject; - - - /** - * Used in onerror Event of an `` element to handle cases when the loading the original src fails - * (for example if file is not found or if the browser does not support SVG). This triggers a call to the - * options onFail hook if available. The optional second parameter will be set as the new src attribute - * for the img element. - * - * @param {HTMLImageElement} img - an img element - * @param {String} [fallbackSrc] - optional parameter fallback src - */ - SVGInject.err = function(img, fallbackSrc) { - if (img) { - if (img[__SVGINJECT] != FAIL) { - removeEventListeners(img); - - if (!IS_SVG_SUPPORTED) { - svgNotSupported(img, defaultOptions); - } else { - removeOnLoadAttribute(img); - loadFail(img, defaultOptions); - } - if (fallbackSrc) { - removeOnLoadAttribute(img); - img.src = fallbackSrc; - } - } - } else { - imgNotSet(); - } - }; - - window[globalName] = SVGInject; - - return SVGInject; - } - - var SVGInjectInstance = createSVGInject('SVGInject'); - - if (typeof module == 'object' && typeof module.exports == 'object') { - module.exports = SVGInjectInstance; - } -})(window, document); \ No newline at end of file diff --git a/client/public/stylesheets/layout/layout.css b/client/public/stylesheets/layout/layout.css index cf209ea9..f6fa464c 100644 --- a/client/public/stylesheets/layout/layout.css +++ b/client/public/stylesheets/layout/layout.css @@ -38,7 +38,7 @@ font-size: 12px; position: absolute; right: 10px; - width: 160px; + width: 180px; z-index: 1000; } @@ -50,7 +50,7 @@ position: absolute; right: 10px; row-gap: 10px; - width: 160px; + width: 180px; z-index: 1000; } diff --git a/client/src/other/utils.ts b/client/src/other/utils.ts index 994ba120..d6ef4fd9 100644 --- a/client/src/other/utils.ts +++ b/client/src/other/utils.ts @@ -79,8 +79,8 @@ export function reciprocalHeading(heading: number): number { return heading > 180? heading - 180: heading + 180; } -export const zeroAppend = function (num: number, places: number) { - var string = String(num); +export const zeroAppend = function (num: number, places: number, decimal: boolean = false) { + var string = decimal? num.toFixed(2): String(num); while (string.length < places) { string = "0" + string; } @@ -176,4 +176,12 @@ export function ftToM(ft: number) { export function mToFt(m: number) { return m / 0.3048; +} + +export function mToNm(m: number) { + return m * 0.000539957; +} + +export function nmToFt(nm: number) { + return nm * 6076.12; } \ No newline at end of file diff --git a/client/src/panels/mouseinfopanel.ts b/client/src/panels/mouseinfopanel.ts index 7301e130..0aace7fb 100644 --- a/client/src/panels/mouseinfopanel.ts +++ b/client/src/panels/mouseinfopanel.ts @@ -1,6 +1,6 @@ import { Icon, LatLng, Marker, Polyline } from "leaflet"; import { getMap, getMissionData, getUnitsManager } from ".."; -import { distance, bearing, zeroPad, zeroAppend, reciprocalHeading } from "../other/utils"; +import { distance, bearing, zeroAppend, mToNm, nmToFt } from "../other/utils"; import { Unit } from "../units/unit"; import { Panel } from "./panel"; @@ -100,7 +100,9 @@ export class MouseInfoPanel extends Panel { if (bng === "000") bng = "360"; - let data = [`${bng}°`, `${Math.floor(dist * 0.000539957)} NM`]; + var [str, unit] = this.#computeDistanceString(dist) + + let data = [`${bng}°`, `${str} ${unit}`]; this.#measureBox.innerText = data.join(" / "); this.#measureBox.style.left = (getMap().getMousePosition().x + startXY.x) / 2 - this.#measureBox.offsetWidth / 2 + "px"; @@ -134,9 +136,11 @@ export class MouseInfoPanel extends Panel { if (bng === "000") bng = "360"; + var [str, unit] = this.#computeDistanceString(dist) + el.dataset.bearing = bng; - el.dataset.distance = zeroAppend(Math.floor(dist * 0.000539957), 3); - el.dataset.distanceUnits = "NM"; + el.dataset.distance = str; + el.dataset.distanceUnits = unit; } if (img != null) img.classList.remove("hide"); @@ -164,4 +168,23 @@ export class MouseInfoPanel extends Panel { img.dataset.label = (value < 0) ? prefixes[1] : prefixes[0]; } } + + #computeDistanceString(dist: number) { + var val = mToNm(dist); + var strVal = 0; + var decimal = false; + var unit = "NM"; + if (val > 10) + strVal = Math.floor(val); + else if (val > 1 && val <= 10) { + strVal = Math.floor(val * 100) / 100; + decimal = true; + } + else { + strVal = Math.floor(nmToFt(val)); + unit = "ft"; + } + + return [zeroAppend(strVal, 3, decimal), unit]; + } }