Added minimap and scale

This commit is contained in:
Pax1601 2023-04-26 16:49:01 +02:00
parent f4fd516d92
commit 40bcd46677
21 changed files with 4393 additions and 67 deletions

View File

@ -643,6 +643,7 @@ class DemoDataGenerator {
logs(req, res){
var ret = {logs: {}};
ret.time = Date.now();
res.send(JSON.stringify(ret));
};
@ -667,6 +668,7 @@ class DemoDataGenerator {
coalition: "blue"
}
}};
ret.time = Date.now();
res.send(JSON.stringify(ret));
};
@ -685,11 +687,13 @@ class DemoDataGenerator {
longitude: -115.7
}
}};
ret.time = Date.now();
res.send(JSON.stringify(ret));
};
mission(req, res){
var ret = {mission: {theatre: "Nevada"}};
ret.time = Date.now();
res.send(JSON.stringify(ret));
}

4170
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,12 +2,12 @@
"name": "DCSOlympus",
"node-main": "./bin/www",
"main": "http://localhost:3000",
"version": "0.1.1-alpha",
"version": "v0.2.0-alpha",
"private": true,
"scripts": {
"copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css",
"start": "npm run copy & concurrently --kill-others \"npm run watch\" \"nodemon ./bin/www\"",
"watch": "watchify .\\src\\index.ts --debug -p [ tsify --noImplicitAny ] -o .\\public\\javascripts\\bundle.js"
"watch": "watchify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]"
},
"dependencies": {
"@types/geojson": "^7946.0.10",
@ -17,15 +17,21 @@
"ejs": "^3.1.8",
"express": "~4.16.1",
"leaflet": "^1.9.3",
"leaflet-control-mini-map": "^0.4.0",
"leaflet.nauticscale": "^1.1.0",
"milsymbol": "^2.0.0",
"morgan": "~1.9.1",
"save": "^2.9.0"
},
"devDependencies": {
"@babel/preset-env": "^7.21.4",
"@types/gtag.js": "^0.0.12",
"@types/node": "^18.16.1",
"@types/sortablejs": "^1.15.0",
"babelify": "^10.0.0",
"browserify": "^17.0.0",
"concurrently": "^7.6.0",
"esmify": "^2.1.1",
"nodemon": "^2.0.20",
"sortablejs": "^1.15.0",
"tsify": "^5.0.4",

View File

@ -10,7 +10,6 @@
@import url("unitinfopanel.css");
@import url("popup.css");
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;

View File

@ -8,7 +8,7 @@ export class AICFormation_Single extends AICFormation implements AICFormationInt
"name" = "single";
"numGroups" = 1;
"summary" = "One contact on its own";
"unitBreakdown" = [];
"unitBreakdown": string[] = [];
constructor() {

View File

@ -46,7 +46,7 @@ class ATCDataHandler {
startUpdates() {
this.#updateInterval = setInterval( () => {
this.#updateInterval = window.setInterval( () => {
const aBoardIsVisible = this.#atc.getBoards().some( board => board.boardIsVisible() );

View File

@ -83,7 +83,7 @@ export abstract class ATCBoard {
});
setInterval( () => {
window.setInterval( () => {
this.updateClock();
}, 1000 );
@ -206,7 +206,7 @@ export abstract class ATCBoard {
this.#strips[ flightId ].element.remove();
this.#strips[ flightId ].isDeleted = true;
setTimeout( () => {
window.setTimeout( () => {
delete this.#strips[ flightId ];
}, 10000 );
@ -326,7 +326,7 @@ export abstract class ATCBoard {
resetSuggestions();
searchTimeout = setTimeout( () => {
searchTimeout = window.setTimeout( () => {
const searchString = unitName.value.toLowerCase();
@ -408,7 +408,7 @@ export abstract class ATCBoard {
return;
}
this.#updateInterval = setInterval( () => {
this.#updateInterval = window.setInterval( () => {
this.update();

View File

@ -90,10 +90,8 @@ function readConfig(config: any)
{
const address = config["server"]["address"];
const port = config["server"]["port"];
if ((typeof address === 'string' || address instanceof String) && typeof port == 'number')
{
setAddress(window.location.hostname, <number>port);
}
if (typeof address === 'string' && typeof port == 'number')
setAddress(address == "*"? window.location.hostname: address, <number>port);
/* On the first connection, force request of full data */
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
@ -122,7 +120,7 @@ function requestUpdate() {
checkSessionHash(data.sessionHash);
}
}, false);
setTimeout(() => requestUpdate(), getConnected() ? 250 : 1000);
window.setTimeout(() => requestUpdate(), getConnected() ? 250 : 1000);
getConnectionStatusPanel()?.update(getConnected());
}
@ -134,7 +132,9 @@ function requestRefresh() {
getUnitsManager()?.update(data);
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
getBullseyes((data: BullseyesData) => getMissionData()?.update(data));
getMission((data: any) => {getMissionData()?.update(data)});
getMission((data: any) => {
getMissionData()?.update(data)
});
// Update the list of existing units
getUnitDataTable()?.update();
@ -142,7 +142,7 @@ function requestRefresh() {
checkSessionHash(data.sessionHash);
}
}, true);
setTimeout(() => requestRefresh(), 5000);
window.setTimeout(() => requestRefresh(), 5000);
}
function checkSessionHash(newSessionHash: string) {

View File

@ -114,7 +114,7 @@ export var BoxSelect = Handler.extend({
if (!this._moved) { return; }
// Postpone to next JS tick so internal click event handling
// still see it as "moved".
setTimeout(Util.bind(this._resetState, this), 0);
window.setTimeout(Util.bind(this._resetState, this), 0);
var bounds = new LatLngBounds(
this._map.containerPointToLatLng(this._startPoint),
this._map.containerPointToLatLng(this._point));

View File

@ -1,4 +1,6 @@
import * as L from "leaflet"
import { MiniMap, MiniMapOptions } from "leaflet-control-mini-map";
import { getUnitsManager } from "..";
import { BoxSelect } from "./boxselect";
import { MapContextMenu } from "../controls/mapcontextmenu";
@ -8,18 +10,35 @@ import { Dropdown } from "../controls/dropdown";
import { Airbase } from "../missionhandler/airbase";
import { Unit } from "../units/unit";
// TODO a bit of a hack, this module is provided as pure javascript only
require("../../node_modules/leaflet.nauticscale/dist/leaflet.nauticscale.js")
export const IDLE = "IDLE";
export const MOVE_UNIT = "MOVE_UNIT";
L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
export class ClickableMiniMap extends MiniMap {
constructor(layer: L.TileLayer | L.LayerGroup, options?: MiniMapOptions)
{
super(layer, options);
}
getMap() {
//@ts-ignore needed to access not exported member. A bit of a hack, required to access click events
return this._miniMap;
}
}
export class Map extends L.Map {
#state: string;
#layer: L.TileLayer | null = null;
#preventLeftClick: boolean = false;
#leftClickTimer: number = 0;
#leftClickTimer: any = 0;
#lastMousePosition: L.Point = new L.Point(0, 0);
#centerUnit: Unit | null = null;
#miniMap: ClickableMiniMap | null = null;
#miniMapLayerGroup: L.LayerGroup;
#mapContextMenu: MapContextMenu = new MapContextMenu("map-contextmenu");
#unitContextMenu: UnitContextMenu = new UnitContextMenu("unit-contextmenu");
@ -30,11 +49,59 @@ export class Map extends L.Map {
constructor(ID: string) {
/* Init the leaflet map */
//@ts-ignore
super(ID, { doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true, zoomAnimation: false });
this.setView([37.23, -115.8], 12);
super(ID, { doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true, zoomAnimation: true, maxBoundsViscosity: 1.0, minZoom: 7 });
this.setView([37.23, -115.8], 10);
this.setLayer("ArcGIS Satellite");
/* Minimap */
/* Draw the limits of the maps in the minimap*/
var latlngs = [[ // NTTR
new L.LatLng(39.7982463, -119.985425 ),
new L.LatLng(34.4037128, -119.7806729),
new L.LatLng(34.3483316, -112.4529351),
new L.LatLng(39.7372411, -112.1130805),
new L.LatLng(39.7982463, -119.985425 )
],
[ // Syria
new L.LatLng(37.3630556, 29.2686111),
new L.LatLng(31.8472222, 29.8975),
new L.LatLng(32.1358333, 42.1502778),
new L.LatLng(37.7177778, 42.3716667),
new L.LatLng(37.3630556, 29.2686111)
],
[ // Caucasus
new L.LatLng(39.6170191, 27.634935),
new L.LatLng(38.8735863, 47.1423108),
new L.LatLng(47.3907982, 49.3101946),
new L.LatLng(48.3955879, 26.7753625),
new L.LatLng(39.6170191, 27.634935)
],
[ // Persian Gulf
new L.LatLng(32.9355285, 46.5623682),
new L.LatLng(21.729393, 47.572675),
new L.LatLng(21.8501348, 63.9734737),
new L.LatLng(33.131584, 64.7313594),
new L.LatLng(32.9355285, 46.5623682)
],
[ // Marianas
new L.LatLng(22.09, 135.0572222),
new L.LatLng(10.5777778, 135.7477778),
new L.LatLng(10.7725, 149.3918333),
new L.LatLng(22.5127778, 149.5427778),
new L.LatLng(22.09, 135.0572222)
]
];
var minimapLayer = new L.TileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { minZoom: 0, maxZoom: 13 });
this.#miniMapLayerGroup = new L.LayerGroup([minimapLayer]);
var miniMapPolyline = new L.Polyline(latlngs, {color: '#202831'});
miniMapPolyline.addTo(this.#miniMapLayerGroup);
/* Scale */
//@ts-ignore TODO more hacking because the module is provided as a pure javascript module only
L.control.scalenautic({position: "topright", maxWidth: 300, nautic: true, metric: true, imperial: false}).addTo(this);
/* Init the state machine */
this.#state = IDLE;
@ -198,12 +265,11 @@ export class Map extends L.Map {
}
/* Spawn from air base */
spawnFromAirbase(e: any)
{
spawnFromAirbase(e: any) {
//this.#aircraftSpawnMenu(e);
}
centerOnUnit(ID: number | null){
centerOnUnit(ID: number | null) {
if (ID != null)
{
this.options.scrollWheelZoom = 'center';
@ -215,6 +281,47 @@ export class Map extends L.Map {
}
}
setTheatre(theatre: string) {
var bounds = new L.LatLngBounds([-90, -180], [90, 180]);
var miniMapZoom = 5;
if (theatre == "Syria")
bounds = new L.LatLngBounds([31.8472222, 29.8975], [37.7177778, 42.3716667]);
else if (theatre == "MarianaIslands")
bounds = new L.LatLngBounds([10.5777778, 135.7477778], [22.5127778, 149.5427778]);
else if (theatre == "Nevada")
bounds = new L.LatLngBounds([34.4037128, -119.7806729], [39.7372411, -112.1130805])
else if (theatre == "PersianGulf")
bounds = new L.LatLngBounds([21.729393, 47.572675], [33.131584, 64.7313594])
else if (theatre == "Falklands")
{
// TODO
}
else if (theatre == "Caucasus")
{
bounds = new L.LatLngBounds([39.6170191, 27.634935], [47.3907982, 49.3101946])
miniMapZoom = 4;
}
this.setView(bounds.getCenter(), 8);
this.setMaxBounds(bounds);
if (this.#miniMap)
this.#miniMap.remove();
//@ts-ignore // Needed because some of the inputs are wrong in the original module interface
this.#miniMap = new ClickableMiniMap(this.#miniMapLayerGroup, {position: "topright", width: 192*1.5, height: 108*1.5, zoomLevelFixed: miniMapZoom, centerFixed: bounds.getCenter()}).addTo(this);
this.#miniMap.disableInteractivity();
this.#miniMap.getMap().on("click", (e: any) => {
if (this.#miniMap)
this.setView(e.latlng);
})
}
getMiniMapLayerGroup() {
return this.#miniMapLayerGroup;
}
/* Event handlers */
#onClick(e: any) {
if (!this.#preventLeftClick) {
@ -252,7 +359,7 @@ export class Map extends L.Map {
{
clearTimeout(this.#leftClickTimer);
this.#preventLeftClick = true;
this.#leftClickTimer = setTimeout(() => {
this.#leftClickTimer = window.setTimeout(() => {
this.#preventLeftClick = false;
}, 200);
getUnitsManager().selectFromBounds(e.selectionBounds);

View File

@ -43,21 +43,10 @@ export class MissionHandler
if ("mission" in data)
{
if (data.mission.theatre != this.#theatre)
if (data.mission != null && data.mission.theatre != this.#theatre)
{
this.#theatre = data.mission.theatre
if (this.#theatre == "Syria")
getMap().setView(new LatLng(34.5, 36.0), 8);
else if (this.#theatre == "MarianaIslands")
getMap().setView(new LatLng(16.7, 145.7), 7);
else if (this.#theatre == "Nevada")
getMap().setView(new LatLng(37.1, -115.2), 8);
else if (this.#theatre == "PersianGulf")
getMap().setView(new LatLng(26.5, 55.3), 8);
else if (this.#theatre == "Falklands")
getMap().setView(new LatLng(-50.6, -42.7), 7);
else if (this.#theatre == "Caucasus")
getMap().setView(new LatLng(42.1, 42.3), 8);
this.#theatre = data.mission.theatre;
getMap().setTheatre(this.#theatre);
getInfoPopup().setText("Map set to " + this.#theatre);
}

View File

@ -82,7 +82,7 @@ export class MouseInfoPanel extends Panel {
el.dataset.bearing = zeroAppend(Math.floor(bear), 3);
el.dataset.distance = zeroAppend(Math.floor(dist*0.000539957), 3);
el.dataset.distanceUnits = "nm";
el.dataset.distanceUnits = "NM";
}
}
@ -176,7 +176,7 @@ export class MouseInfoPanel extends Panel {
bng = "360";
}
let data = [ `${bng}°`, `${Math.floor(dist*0.000539957)}nm`, `${reciprocal}°` ];
let data = [ `${bng}°`, `${Math.floor(dist*0.000539957)}NM`, `${reciprocal}°` ];
if ( bear < 180 ) {
data = data.reverse();
@ -229,7 +229,7 @@ export class MouseInfoPanel extends Panel {
pos.dataset.bearing = "---";
pos.dataset.distance = "---";
pos.dataset.distanceUnits = "nm";
pos.dataset.distanceUnits = "NM";
}
}

View File

@ -42,7 +42,7 @@ export class UnitInfoPanel extends Panel {
document.addEventListener("unitsSelection", (e: CustomEvent<Unit[]>) => this.#onUnitsSelection(e.detail));
document.addEventListener("unitsDeselection", (e: CustomEvent<Unit[]>) => this.#onUnitsDeselection(e.detail));
document.addEventListener("clearSelection", () => this.#onUnitsDeselection([]));
document.addEventListener("clearSelection", (e: CustomEvent<Unit[]>) => this.#onUnitsDeselection([]));
document.addEventListener("unitUpdated", (e: CustomEvent<Unit>) => this.#onUnitUpdate(e.detail));
this.hide();

View File

@ -17,10 +17,10 @@ export class Popup extends Panel {
clearTimeout(this.#visibilityTimer);
clearTimeout(this.#hideTimer);
this.#visibilityTimer = setTimeout(() => {
this.#visibilityTimer = window.setTimeout(() => {
this.getElement().classList.remove("visible");
this.getElement().classList.add("invisible");
this.#hideTimer = setTimeout(() => this.hide(), 2000);
this.#hideTimer = window.setTimeout(() => this.hide(), 2000);
}, this.#fadeTime);
}
}

View File

@ -23,7 +23,7 @@ export function GET(callback: CallableFunction, uri: string){
xmlHttp.open("GET", `${demoEnabled? DEMO_ADDRESS: REST_ADDRESS}/${uri}`, true);
xmlHttp.onload = function (e) {
var data = JSON.parse(xmlHttp.responseText);
if (parseInt(data.time) > lastUpdateTime)
if (uri != UNITS_URI || parseInt(data.time) > lastUpdateTime)
{
callback(data);
lastUpdateTime = parseInt(data.time);

View File

@ -2064,8 +2064,8 @@ export class AircraftDatabase extends UnitDatabase {
],
"filename": "kc-135.png"
},
"KC-135MPRS": {
"name": "KC-135MPRS",
"KC135MPRS": {
"name": "KC135MPRS",
"label": "KC-135 MPRS Stratotanker",
"shortLabel": "135M",
"loadouts": [
@ -2083,6 +2083,44 @@ export class AircraftDatabase extends UnitDatabase {
],
"filename": "kc-135.png"
},
"KC_10_Extender": {
"name": "KC_10_Extender",
"label": "KC-10 Extender",
"shortLabel": "KC10",
"loadouts": [
{
"fuel": 1,
"items": [
],
"roles": [
"Tanker"
],
"code": "",
"name": "Default Tanker"
}
],
"filename": "kc-10.png"
},
"KC_10_Extender_D": {
"name": "KC_10_Extender_D",
"label": "KC-10 Extender (Drogue)",
"shortLabel": "KC10",
"loadouts": [
{
"fuel": 1,
"items": [
],
"roles": [
"Tanker"
],
"code": "",
"name": "Default Tanker"
}
],
"filename": "kc-10.png"
},
"MiG-15bis": {
"name": "MiG-15bis",
"label": "MiG-15 Fagot",

View File

@ -1,4 +1,4 @@
import { Marker, LatLng, Polyline, Icon, DivIcon } from 'leaflet';
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker } from 'leaflet';
import { getMap, getUnitsManager } from '..';
import { rad2deg } from '../other/utils';
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit } from '../server/server';
@ -77,6 +77,7 @@ export class Unit extends Marker {
#pathMarkers: Marker[] = [];
#pathPolyline: Polyline;
#targetsPolylines: Polyline[];
#miniMapMarker: CircleMarker | null = null;
#timer: number = 0;
#forceUpdate: boolean = false;
@ -107,11 +108,11 @@ export class Unit extends Marker {
/* Deselect units if they are hidden */
document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => {
setTimeout(() => {this.setSelected(this.getSelected() && !this.getHidden())}, 300);
window.setTimeout(() => {this.setSelected(this.getSelected() && !this.getHidden())}, 300);
});
document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => {
setTimeout(() => {this.setSelected(this.getSelected() && !this.getHidden())}, 300);
window.setTimeout(() => {this.setSelected(this.getSelected() && !this.getHidden())}, 300);
});
/* Set the unit data */
@ -124,7 +125,6 @@ export class Unit extends Marker {
iconAnchor: [0, 0]
});
this.setIcon(icon);
}
getMarkerHTML() {
@ -392,7 +392,7 @@ export class Unit extends Marker {
}
#onClick(e: any) {
this.#timer = setTimeout(() => {
this.#timer = window.setTimeout(() => {
if (!this.#preventClick) {
if (getMap().getState() === 'IDLE' || getMap().getState() === 'MOVE_UNIT' || e.originalEvent.ctrlKey) {
if (!e.originalEvent.ctrlKey) {
@ -517,8 +517,24 @@ export class Unit extends Marker {
#updateMarker() {
this.updateVisibility();
if (!this.getHidden()) {
if (this.#miniMapMarker == null)
{
this.#miniMapMarker = new CircleMarker(new LatLng(this.getFlightData().latitude, this.getFlightData().longitude), {radius: 0.5});
if (this.getMissionData().coalition == "neutral")
this.#miniMapMarker.setStyle({color: "#CFD9E8"});
else if (this.getMissionData().coalition == "red")
this.#miniMapMarker.setStyle({color: "#ff5858"});
else
this.#miniMapMarker.setStyle({color: "#247be2"});
this.#miniMapMarker.addTo(getMap().getMiniMapLayerGroup());
this.#miniMapMarker.bringToBack();
}
else {
this.#miniMapMarker.setLatLng(new LatLng(this.getFlightData().latitude, this.getFlightData().longitude));
this.#miniMapMarker.bringToBack();
}
if (!this.getHidden()) {
this.setLatLng(new LatLng(this.getFlightData().latitude, this.getFlightData().longitude));
var element = this.getElement();
if (element != null) {
@ -538,8 +554,7 @@ export class Unit extends Marker {
var unitAltitudeDiv = element.querySelector(".unit-altitude");
if (unitAltitudeDiv != null) {
unitAltitudeDiv.innerHTML = String(Math.floor(this.getFlightData().altitude / 0.3048 / 1000));
unitAltitudeDiv.innerHTML = "FL" + String(Math.floor(this.getFlightData().altitude / 0.3048 / 1000));
}
element.querySelectorAll( "[data-rotate-to-heading]" ).forEach( el => {

View File

@ -68,7 +68,7 @@ export class UnitsManager {
Object.keys(data.units)
.filter((ID: string) => !(ID in this.#units))
.reduce((timeout: number, ID: string) => {
setTimeout(() => {
window.setTimeout(() => {
if (!(ID in this.#units))
this.addUnit(parseInt(ID), data.units[ID]);
this.#units[parseInt(ID)]?.setData(data.units[ID]);
@ -330,7 +330,7 @@ export class UnitsManager {
this.#showActionMessage(this.#copiedUnits, `pasted`);
}
this.#pasteDisabled = true;
setTimeout(() => this.#pasteDisabled = false, 250);
window.setTimeout(() => this.#pasteDisabled = false, 250);
}
}
@ -348,7 +348,7 @@ export class UnitsManager {
/* Disable the firing of the selection event for a certain amount of time. This avoids firing many events if many units are selected */
if (!this.#selectionEventDisabled)
{
setTimeout(() => {
window.setTimeout(() => {
document.dispatchEvent(new CustomEvent("unitsSelection", {detail: this.getSelectedUnits()}));
this.#selectionEventDisabled = false;
}, 100);

View File

@ -9,7 +9,7 @@
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "ES2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
@ -33,14 +33,15 @@
], /* Specify multiple folders that act like './node_modules/@types'. */
"types": [
"leaflet",
"geojson"
"geojson",
"node"
], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
"allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */

View File

@ -38,6 +38,7 @@
<% /* %>
<%- include('log.ejs') %>
<% */ %>
<script src="javascripts/bundle.js"></script>
</body>

View File

@ -3,18 +3,18 @@
<div>
<dl class="ol-data-grid">
<dt id="ref-measure-position" data-tooltip="CTRL-click on the map to activate the measuring tool."></dt>
<dd id="measure-position" class="br-info" data-bearing="---" data-distance="---" data-distance-units="nm"></dd>
<dd id="measure-position" class="br-info" data-bearing="---" data-distance="---" data-distance-units="NM"></dd>
<dt id="ref-unit-position" data-tooltip="Bearing/range from selected unit."></dt>
<dd id="unit-position" class="br-info" data-bearing="---" data-distance="---" data-distance-units="nm"></dd>
<dd id="unit-position" class="br-info" data-bearing="---" data-distance="---" data-distance-units="NM"></dd>
</dl>
</div>
<div>
<dl class="ol-data-grid">
<dt id="ref-bullseye-2" data-tooltip="Bearing/range from this bullseye." data-label="BE" data-coalition="blue"></dt>
<dd id="bullseye-2" class="br-info" data-bearing="---" data-distance="---" data-distance-units="nm"></dd>
<dd id="bullseye-2" class="br-info" data-bearing="---" data-distance="---" data-distance-units="NM"></dd>
<dt id="ref-bullseye-1" data-tooltip="Bearing/range from this bullseye." data-label="BE" data-coalition="red"></dt>
<dd id="bullseye-1" class="br-info" data-bearing="---" data-distance="---" data-distance-units="nm"></dd>
<dd id="bullseye-1" class="br-info" data-bearing="---" data-distance="---" data-distance-units="NM"></dd>
</dl>
</div>