From 135b2c838db157139402ac5eae4c2f831da704f9 Mon Sep 17 00:00:00 2001 From: NoobishSVK Date: Sat, 20 Jan 2024 23:21:37 +0100 Subject: [PATCH] maps.fmdx.pl integration, various bugfixes, UI changes --- datahandler.js | 10 ++++- index.js | 13 +++--- userconfig.js | 9 ++-- web/{ => css}/styles.css | 40 ++++++++++++++---- web/favicon.png | Bin 0 -> 17808 bytes web/favicon2.png | Bin 0 -> 7834 bytes web/index.html | 28 +++++++++---- web/main.js | 88 ++++++++++++++++++++++++++++++--------- 8 files changed, 143 insertions(+), 45 deletions(-) rename web/{ => css}/styles.css (95%) create mode 100644 web/favicon.png create mode 100644 web/favicon2.png diff --git a/datahandler.js b/datahandler.js index 88ca203..a5c84fa 100644 --- a/datahandler.js +++ b/datahandler.js @@ -139,6 +139,7 @@ var dataToSend = { af: [], rt0: '', rt1: '', + users: '' }; const initialData = { @@ -153,6 +154,7 @@ const initialData = { af: [], rt0: '', rt1: '', + users: '' }; const resetToDefault = dataToSend => Object.assign(dataToSend, initialData); @@ -244,6 +246,12 @@ function handleData(ws, receivedData) { } } +function showOnlineUsers(currentUsers) { + console.log(currentUsers); + dataToSend.users = currentUsers; + initialData.users = currentUsers; +} + module.exports = { - handleData + handleData, showOnlineUsers }; \ No newline at end of file diff --git a/index.js b/index.js index e8ecf43..1c7d575 100644 --- a/index.js +++ b/index.js @@ -20,11 +20,7 @@ const dataHandler = require('./datahandler'); const config = require('./userconfig'); /* Server settings */ -const webServerHost = config.webServerHost; // IP of the web server -const webServerPort = config.webServerPort; // web server port -const xdrdServerHost = config.xdrdServerHost; // xdrd server iP -const xdrdServerPort = config.xdrdServerPort; // xdrd server port -const xdrdPassword = config.xdrdPassword; +const { webServerHost, webServerPort, xdrdServerHost, xdrdServerPort, xdrdPassword, qthLatitude, qthLongitude } = config; const wss = new WebSocket.Server({ noServer: true }); @@ -37,6 +33,7 @@ const client = new net.Socket(); wss.on('connection', (ws, request) => { const clientIp = request.connection.remoteAddress; currentUsers++; + dataHandler.showOnlineUsers(currentUsers); console.log(infoMsg, `WebSocket client connected\nIP: ${clientIp}\nUsers online: ${currentUsers}`); ws.on('message', (message) => { @@ -49,6 +46,7 @@ wss.on('connection', (ws, request) => { ws.on('close', (code, reason) => { currentUsers--; + dataHandler.showOnlineUsers(currentUsers); console.log(infoMsg, `WebSocket client disconnected\nIP: ${clientIp}\nCode: ${code} ${reason}\nUsers online: ${currentUsers}`); }); @@ -121,6 +119,11 @@ httpServer.listen(webServerPort, webServerHost, () => { console.log(infoMsg, `Web server is running at \x1b[34mhttp://${webServerHost}:${webServerPort}\x1b[0m.`); }); + +app.get('/coordinates', (req, res) => { + // Sending the coordinates to the client + res.json({ qthLatitude, qthLongitude }); +}); /* Audio */ app.get('/audio-proxy', (req, res) => { diff --git a/userconfig.js b/userconfig.js index 75a1ba9..0fde9e0 100644 --- a/userconfig.js +++ b/userconfig.js @@ -3,10 +3,13 @@ const webServerPort = 8080; // web server port const xdrdServerHost = '192.168.1.15'; // xdrd server iP const xdrdServerPort = 7373; // xdrd server port -const xdrdPassword = ''; // xdrd password (optional) +const xdrdPassword = 'changeme'; // xdrd password (optional) + +const qthLatitude = '0.0'; // your latitude, useful for maps.fmdx.pl integration +const qthLongitude = '0.0'; // your longitude, useful for maps.fmdx.pl integration const verboseMode = false; // if true, console will display extra messages module.exports = { - webServerHost, webServerPort, xdrdServerHost, xdrdServerPort, xdrdPassword, verboseMode - }; \ No newline at end of file + webServerHost, webServerPort, xdrdServerHost, xdrdServerPort, xdrdPassword, qthLatitude, qthLongitude, verboseMode +}; \ No newline at end of file diff --git a/web/styles.css b/web/css/styles.css similarity index 95% rename from web/styles.css rename to web/css/styles.css index d38afa5..3ab02f0 100644 --- a/web/styles.css +++ b/web/css/styles.css @@ -12,6 +12,22 @@ --color-5: color-mix(in srgb, var(--color-main) 0%, var(--color-main-bright)); } +.color-1 { + color: var(--color-1); +} + +.color-2 { + color: var(--color-2); +} + +.color-3 { + color: var(--color-3); +} + +.color-4 { + color: var(--color-4); +} + ::selection { background: var(--color-main-bright); color: inherit; @@ -115,6 +131,7 @@ h2 { border-radius: 30px; text-align: center; margin-top: 30px; + transition: 0.3s ease-in-out background-color; } .panel-90 { @@ -158,12 +175,16 @@ h2 { /*font-family: "Monomaniac One", sans-serif;*/ } -.text-medium-big { +.text-medium { font-size: 24px; color: #aaa; font-weight: 300; } +.text-medium-big { + font-size: 46px; +} + .text-small { font-size: 13px; } @@ -519,11 +540,7 @@ input[type="range"]::-moz-range-thumb { display: block; } -.themes-list select { - display: none; -} - -#theme-selector { +select { height: 42px; width: 150px; padding: 10px; @@ -533,8 +550,17 @@ input[type="range"]::-moz-range-thumb { border-bottom: 4px solid var(--color-2); cursor: pointer; transition: 0.35s ease-in-out background; + font-family: inherit; + font-weight: bold; } -#theme-selector:hover { +select option { + font-family: 'Titillium Web', sans-serif; + font-weight: 300; + padding: 10px; + border: 0; +} + +select:hover { background: var(--color-5); } \ No newline at end of file diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..c86330d2cc8d521cb6d5f2d630ef668e3e57867a GIT binary patch literal 17808 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 Kb6Mw<&;$Una3!Ar literal 0 HcmV?d00001 diff --git a/web/favicon2.png b/web/favicon2.png new file mode 100644 index 0000000000000000000000000000000000000000..966184a6183d8a45565f7891c840198eca37679b GIT binary patch literal 7834 zcmeAS@N?(olHy`uVBq!ia0y~yU}OMc4mJh`hM1xiX$%YuoCO|{#S9GG!XV7ZFl&wk z0|SFXvPY0F14ET614BbI1H;e%3=9n~85l|p7#Ln9FfdrnU|pA>)8je$W+>aVRnhIC(I%2naDKwy-!17?-m_z==tr zWdZ|-q6&i(2Ti$3Vxp0`GYr-AzeZ&Hv*b z^WwjKhUJa9|9PkJ$9LcL-5GoO-`D(WZ-U&_pT1%Ldi&g~Pa5AJmOYKqi@R-~5uX0E zY}IS$xBnNsITCldJlp)*Ev^SX54sO5kNGckeSdL7bdO>G)05{^7$Ofv-R9mQYmpoN zmhl(!{PO+zk=g2!$^Rl;re9~b;E`bBVPe~z{fhYw_Z5cNhOF>?k~bJlm|ovq<g` z!#<5^J@f0X74`r53⁡O}78ee2(edrfYT#HAf{j$0;}LJ^u4M`@Ax~P3mq8=OeTI z4UU~T``~Fwq5t-e2O<(g0^V2lWqp7BuqCP7gyD1J^Si=dRMll7U*9)8Anb5mrfWXi znXT94@_QmR88vF3-xse?aerPvf8BxnHCyMiY)gG$)W)!!S)K9tF7+zA73HP#p8UJZ zV)OXj^S^mZ0$%)E%Um~k@#pt7_VOFA^%)<_xi$OG!W{kLe_81(l#^uk*?;I~&8e$@ zVDun0fwO@5!%Q2i`t&P1%hIWW-P7@|)Usez_V1)}-Plhd<(KScJ;`xp3UKoOf4M=D(QoRvS)RHDoEKmH z_HS6ITJXDlS9avPb!*L@{&M6G`&DC1xs&8i$tu zkIY*k*~QM>);o_)r{r+m;d|YT=Ze2S`l6uT^XtXIhTJ^|ZcbuZ&@rc;!9e?g=5;oq z$$Bo_N#7sKuMIzSMR>2_49^+cS;cqQaUa!54;E@rDyVZ7c`Tn5k=a<>Yskxa-dJXa z_ZKgpl5-}DK0I>i&R@6w+|$MPqf}?EyBpW_k#VU7lZCv6;e((1l6xvm9$MPDiySl$ zvfJnGwxjy%&K9K)8Xx91ytTS`a~g}nVgLXC4t!YdZ;*t?T^?E_kDAXfA6UN z*4y%Y=dG`a8tcl<)EG}_To-;f^?p^tqjNhMY&6-^gjFv*w)dpL^Dm!RXNSj_;lM z>3iNidt2E4x19NZxSjNz$#?hm{tmp7x-Q?@;Ly#Oi<2XcifyUQE`J}jN+-lkDfw2T zn~wa+9l2xh$XKCvv|~aNhbKJ%+y5Zf$O? zteL>2%NZV-oo{|D$ERpg^u4`*7n{kdCavi`a;}77tyq-RT=}c&v+pi3WU^qbxM+FV zEP;E&-M_z|tJEC7&3Rwp&Y}BLkIiT`?ElMGu&~CYR8QgAYuoGF!`ZUj%O~w$dSmLt zbMCX|p3fe5}p-O$Z^_U~`Tc-|}jo_8AEKJrk$ z;q=qlm5+-arKj&Y__dT{->V!07IEwQ7Po(%TGvy!uhiO5+~u-Z!+)jiSFdS3U_Y>* z)u=^a;o`Liejc0gZN}kCv!6_^eD0RS!oAbZ?*7-xpj|9N|LTkFCUz(L7w(&;$!H-w z74ui934%;3TPi`D;}5*n=E#n~5E@CZgsN!YSo`|@1f zV^1soT;HH(J^yqILkPq5qc-1Ov3!l&HGAPCeQn0~Q%^jXO25MNoh_zb;N!E0-|y_L zOPdq;VC%Z~lY?I7OtkrZpp+%z2)`mjx z=jUy^7AC02@%Xmkoc-#7UfO4WZ{8|b@LB)b`ByXfrEl=Y7jK*CZ)dyv;qtGn!VHV} zbtla`T>kWLcg>$~p*ug#FnsoMMzOx?=M!>Y4VN?dGb zjX@`4cap%#@|82+TmF&f>*2l-=r5HV_eJ_we6-t_bz#o`bNpHBetiC(R&{gh=2ms) zEB1PBS|5LMzP2eUJ1pDGWyr*_vG7p$yr<{6Q#9;*3eSW$C_hP_nO@>!{WEdFuk+qF z*_(bPP5R!U_-NAnPZhtyAIRrik@Ws}M(TIWEx9{m4JH7AMx>Do!v#z99Ek16@ zZ*^N@(uQ{@uieV8RGC!S^`!gOasgv0(`g{zEz&knOkAv6w?4tnd&bf2vwI9>=NKJO{}lePEm ziT*Cmx$DyRqRMFMGON={1vg_~r%hX$sl0n(`{tV_HHs_ztGEv|ZPR|`v2S{;w!!hm zf9|vHaFlLnx9PW(l$hpv`dzSL%i`TW3->*GaL9LycDwPy+m=_t`Od9k;3=(raoBlY z@MQrr>-Hz})#dGWKkVC8)5CB~$X@^UZyWwMCklVWi+M1-Gd=d>-V<)4%&VctjaEJ5 zzA__^HQzfoQZ{+lymN}C$(yy9;v#3w>AfTE#4zXWvqOB7)HOBB_s!hJAS3$V*$)M*ih^rrYR#{mU$C<5prr~y_@AM*uIYrlZMgG0KW$Int zOLN{XdnkOc#<-86<;JOBto@r5?aZ={)-Oy|V%)c#@8pM9oH7w#SDx|P(H`2Lmh$$; z8q?KG|Nkn@Q}8*qz<>D@h}Isz8y?gO5yX(zkdLu5}MIJNkM zmGf%;^N&gntk$2q_6%ph`u?})RDY%|TO2Ifz?vIg!aix;4;__LWwT!YsrPBM^Dn^kgU?&~yOzsqT5hb8(;8+6Z^Pco<|J1l!Q zSePLpq+#}>&tK&IX84-cns?ar_SAg2yt{_u@T&ghHzXph^|JHX{k(6cStZN=x%A*X zZ@}{vCaeh=4Q#*OoD+KVc(&N0vkEm9n!=OAgAX6PI)7<|WT>^GcOlch^~}#F{t1qa zm*(48eDQ(_>w^b2+y@jHU(HVM$^0hq@A@Q#=t2*^b-#G7N>*GIpMGnTm0Rh|2~(fR zlt14UY1z(ZJ$t73f_u)NbQsu|Ycd@Eq{E>2?f2)ucRpz(G_xx-_Lw z^R{1*blm$ImCZ~aI$L_HPjCLSfI;>{`uR_+_3c~zBkilE$VV74U0D8zp(-Th(c^_1 zHE;WINY`m6*3S2EWw@8Idy#a&1EAo2{(}LHv&d=YoOr6#5&&8!{ z#P^dwt`vjmzKOsP@Xxc(Q%fjUO1Z+-4J=P|yD zeq_DJNq-@0)FtZhf+5e05uYHPeP$i*w%FTxXa3@nw7c(G`uAkbd}^vta!p zE(hO}+zz3U2lw;7mHb}^f$JMSs?ucyA2p{n`}QJX@^6hF3mqXU)84V(3EEC?!{B~TSu}{#!@K%u)(}a@N zQ|0$JJr-DGVxgBB-}!cRYULizeUV|;MHVdHCU(i|R&MdhYNy$`nkB;9L>8Pg)%@+1 zbIK@3Tan4Y>;K+a9Ud?V&<;!RED+MvnHSfPKO zX@k~*UilZ<^INx^@qPRLO}6G+#{<8%UA67#O*U!0$Op4rJM7kbw2&2nBa(LHC@n`yhg-C4 z(hCxuYnJ!23N)l|eqhoaC3iDIi|NCyZ|a+ibkB=9Fo-RGqug0@)t$j9C*r~GyX76B zKLf8t&A+atKiNjnIZ4Xe>}y6w^o@u&=l=Vhe)RUXwb}PG4#85f_n)J`)K zEx5&QJ62!6KD+L>-$t$j-M8zv?`iJa)noE};gsBE#E{CGzU8<8|KA&-O&?oZG+QWvglab{&}+ z3)S}4_|4C>v~Jrx^&;b|TFun^9&Z-!V-ipbdY5tk9Cr%K^6F{-Q>V?zsyxkIJAJFo z{RySdB!x`3_J=>-8t)L` z5R^1O7-fARS!#n+g+aF8wmnaeI@ag?`+H~2*6e?M>TwmTe_maf(%-K3b>_5UC%$xL zVWum)&)&>i_eJ4nySs12G1&^v0}DlsZ!!5Y_nq9jz;Kytg^|Ntwi!<<&zy~{xwJ0p z@8cPkx6}9EO4%-Eld@xD^6O{r+wXikbz3+8kFOiM+W)7KbwY{TmR4W7nO89X$Bu{p zulzchyOOiv@l^(1+k2b;EN<+1czWJbc{Zb;seY6179H7qJAM29yT49-X3c7fy=9Ys zE;%}H`Nrhe6D3Rkss7l1>2J}3UGly+)ti2#$uRzKW@LFV(P6I9p(ty;bkB8rS26$S zUvqA!?zZ2v&-(Y)7X9w+zP?qrRyqEw*_MA#zqW5bQ}x-uxA<6ePWh(OrIUa8oVR3e z+}tbJ_^NIR1Ji@IvkT20@EFR-`)=|5+$OV}(R=OI(+vk1U;ShMlXU1k%R1FF<+oN| zNSn=Hwf1A2mhag^&8z)y+*|)?f-=Yc=gz-ZT|2sd&%GZhv8!_}d)|E3`>mUk~f&-SF-WAFO7yS}wFh zV#l4wGa?UMZ)7~0@KbgRf8<50`V(E(e#!=XbE$pmxc-}t{etrCo9;2M@{PS;6nu00 zoser&gD=W1n7i%l+ij)MvvVVFXKdfMdu{FCQ@pvW??vDJbxlyLy6NmUzM#1qPko)q zFaCJ?rab>`uU>O|Rw|uyEM$F9_+Y+}Sw&C!&z&y!!`eFxW~Z(FyUs8zxNmX8vgcCk z_s;6sC;DTD;Jl@ekC?9Q_KUf^OT)`N%U+`8?U$*3<=l4<@)UG)TmL;9&=T|Z=a>89 zGsITB6FnDp`Ah5FpG)>P9$E9oaMJ$S-@B^Kjz#=owkmV~E+JbdZNNXVG_JVz=~ssW zGr^{Ki)i1o;#P^XKcD==0ZQ7lJmpk`pG$w-%`A25`r5O#tiNa6(zd>1aPib}qi)uJ zFTMBf4g0ry_sdv~cjqSSzd6$!{94`oxi5oE`P1Fyy@sC~!b5)(O<(*|ZJWNDV1v8IG!2uyz8~`JdkUvVW!HYM+dYLR z|N9>C%MX63eShe5<@jl-eE+uc>*VOqdJKK9JNKt2 ztXX4yY=+t&@k+Zs?zLOnE4vOb|Ja`<^wRM4o4CvGzt{YdXN!^8z`Nb@_L_Y~beFrEqLv?}1XzRr@*%=D(W8Y~NLQ=ennyfa;{r>W_3E{XOxumgCkO-(yd$ z9;q(cn~?Q)%2rlkhU2z=p2f0lB@FS3j%A9;XSfdOImzX(wY{D%QgD=S(TR;`KOJn^ zDEZ^ik+{oyx5*UO*47*-yYn>1NY8t&|C3!}7hcu8o416QU-V%q_XqPgmdvND4|ukm z-1hl>i>JgdJM)O_yjkr=K(b zHihL|>htXFEg3bg2c$o0eb9Ws@gQZS4fyEk5&=d`2$)V=y&@^iWwQm&rwdaK;u-^0`}pT+L&+I_){$M-XBe|2z< z)%Km$Z_VR7ewmc~|D*EYay*m3ICIGsF5CKT(G2H9n@^rN=cIb<@Vk3e`hRxqvoZeCeEjA-76s-%Ee5|i z-ks@Rv$b$i{2PU+13Sa*qHblHMDCHwvfhzgsTa^Hu3lY`On3!Q`d&)0fxl|2e$#`w^S;U=N0_ zWRVL#Te#$lc7(Cck$4gFoq4`WSJv&>;vBkxK{Ne@^cr5dTn}G(gKf^!951E-7o`m* ztzR1&8P9K>m@zSnDREn@zFA!H^*XskWlMIpyyva+cK`8UFj8SE7dGQqV%wVbkI~{% z=hazz4}82Xu=kerB!k~R%Wk^c7n!xNEU4HyWyWl^l0%QC+`8fTrS`kP^?RkNH~3#S z)E8c_Fg_`i_-t{%oO;fo08WQSH^#Rvg%9ezDptuJ2-Y;;K2am`Xu^Z{CtqB9GEawb z-?Mcus~#=g_vxXgke-TFwB_ZSeJl%DToQ}}w@p=XblNVFyzTkQleaq;N%1R1$<`Yz zed!*xWw%-Vx!A+L?`D0vc>T8LG~IO8f=QbtRT!3nMy-WA%=*5hntpi8WU{+Cqx4V6 z1BXQ#TXgdM&H6RIR8GkL{8y9jt9@VoZoAK^q6JNxMO7GU7w-2qwL__ zi5KhY&PG|cX;goCVJq_AwqTuM+TDB4_^anKSUiqMUu%1FE%zLD8Rjd(stcky_jqhM z{`-N9e9|DS{WB7vJ(>M~c?)oix*SH8$+{ literal 0 HcmV?d00001 diff --git a/web/index.html b/web/index.html index f8ffcec..1b033b7 100644 --- a/web/index.html +++ b/web/index.html @@ -2,8 +2,10 @@ FM-DX Webserver [Noobish's Server] - + + + @@ -13,16 +15,18 @@
diff --git a/web/main.js b/web/main.js index e22ca7a..d04aa19 100644 --- a/web/main.js +++ b/web/main.js @@ -38,6 +38,19 @@ function zoomOut() { zoomMaxValue *= 1.1; } +function getInitialSettings() { + fetch('/coordinates') + .then(response => response.json()) + .then(data => { + // Use the received data (data.qthLatitude, data.qthLongitude) as needed + localStorage.setItem('qthLatitude', data.qthLatitude); + localStorage.setItem('qthLongitude', data.qthLongitude); + }) + .catch(error => console.error('Error:', error)); +} + +getInitialSettings(); + function updateCanvas() { // Remove old data when it exceeds the maximum data points @@ -179,7 +192,14 @@ function updatePanels(parsedData) { document.querySelector('#data-st').innerHTML = parsedData.st === false ? "ST" : "ST"; document.querySelector('#data-rt0').innerHTML = parsedData.rt0; document.querySelector('#data-rt1').innerHTML = parsedData.rt1; - document.querySelector('#data-signal').textContent = signalToggle.checked ? (parsedData.signal - 11.75).toFixed(1) : parsedData.signal; + + const signalValue = signalToggle.checked ? (parsedData.signal - 11.75) : parsedData.signal; + const integerPart = Math.floor(signalValue); + const decimalPart = (signalValue - integerPart).toFixed(1).slice(1); // Adjusted this line + + document.querySelector('#data-signal').textContent = integerPart; + document.querySelector('#data-signal-decimal').textContent = decimalPart; + document.querySelector('#users-online').textContent = parsedData.users; } signalToggle.addEventListener("change", function() { @@ -194,26 +214,43 @@ signalToggle.addEventListener("change", function() { const textInput = document.getElementById('commandinput'); +textInput.addEventListener('change', function (event) { + const inputValue = textInput.value; + // Check if the user agent contains 'iPhone' + if (/iPhone/i.test(navigator.userAgent) && socket.readyState === WebSocket.OPEN) { + socket.send(inputValue); + // Clear the input field if needed + textInput.value = ''; + } +}); + textInput.addEventListener('keyup', function (event) { - // Get the current input value - let inputValue = textInput.value; + // Check if the pressed key is 'Backspace' (key code 8) + if (event.key !== 'Backspace') { + // Get the current input value + let inputValue = textInput.value; - // Remove non-digit characters - inputValue = inputValue.replace(/[^0-9]/g, ''); + // Remove non-digit characters (excluding dot) + inputValue = inputValue.replace(/[^0-9.]/g, ''); - console.log("InputValue contains dot: ", inputValue.toLowerCase().includes(".")); - - // Determine where to add the dot based on the frequency range - if (inputValue.includes(".") === false) { - if (inputValue.startsWith('10') && inputValue.length > 2) { - // For frequencies starting with '10', add the dot after the third digit - inputValue = inputValue.slice(0, 3) + '.' + inputValue.slice(3); - textInput.value = inputValue; - } else if (inputValue.length > 2) { - // For other frequencies, add the dot after the second digit - inputValue = inputValue.slice(0, 2) + '.' + inputValue.slice(2); + // Remove the last dot if there are two consecutive dots + if (inputValue.includes("..")) { + inputValue = inputValue.slice(0, inputValue.lastIndexOf('.')) + inputValue.slice(inputValue.lastIndexOf('.') + 1); textInput.value = inputValue; } + + // Determine where to add the dot based on the frequency range + if (!inputValue.includes(".")) { + if (inputValue.startsWith('10') && inputValue.length > 2) { + // For frequencies starting with '10', add the dot after the third digit + inputValue = inputValue.slice(0, 3) + '.' + inputValue.slice(3); + textInput.value = inputValue; + } else if (inputValue.length > 2) { + // For other frequencies, add the dot after the second digit + inputValue = inputValue.slice(0, 2) + '.' + inputValue.slice(2); + textInput.value = inputValue; + } + } } // Update the input value @@ -266,12 +303,14 @@ function getCurrentFreq() { freqUpButton = document.getElementById('freq-up'); freqDownButton = document.getElementById('freq-down'); +psContainer = document.getElementById('ps-container'); piCodeContainer = document.getElementById('pi-code-container'); freqContainer = document.getElementById('freq-container'); freqUpButton.addEventListener("click", tuneUp); freqDownButton.addEventListener("click", tuneDown); -piCodeContainer.addEventListener("click", copyPi); +psContainer.addEventListener("click", copyPs); +piCodeContainer.addEventListener("click", findOnMaps); freqContainer.addEventListener("click", function() { textInput.focus(); }); @@ -290,20 +329,29 @@ function tuneDown() { } } -async function copyPi() { - console.log("clicked pi"); +async function copyPs() { let frequency = document.querySelector('#data-frequency').textContent; let pi = document.querySelector('#data-pi').textContent; let ps = document.querySelector('#data-ps').textContent; let signal = document.querySelector('#data-signal').textContent; + let signalDecimal = document.querySelector('#data-signal-decimal').textContent; let signalUnit = document.querySelector('#signal-units').textContent; try { - await copyToClipboard(frequency + " - " + pi + " | " + ps + " [" + signal + " " + signalUnit + "]"); + await copyToClipboard(frequency + " - " + pi + " | " + ps + " [" + signal + signalDecimal + " " + signalUnit + "]"); } catch(error) { console.error(error); } } +function findOnMaps() { + let frequency = document.querySelector('#data-frequency').textContent; + let pi = document.querySelector('#data-pi').textContent; + let latitude = localStorage.getItem('qthLongitude'); + let longitude = localStorage.getItem('qthLatitude'); + frequency = parseFloat(frequency).toFixed(1); + window.open("https://maps.fmdx.pl/#qth=" + longitude + "," + latitude + "&freq=" + frequency + "&pi=" + pi, "_blank"); +} + async function copyToClipboard(textToCopy) { // Navigator clipboard api needs a secure context (https) if (navigator.clipboard && window.isSecureContext) {