Display local weather and time on a website - javascript

I am a bit of a novice to programming and have started to dive into JavaScript lately. I am trying to create a small widget on a website I am helping a friend build. I want to build a widget on the website that displays the current local time for the user browsing, but also his location and the weather at his or her location.
So far, I have managed to create the script to display the local time for the user, but what I cannot figure out is the weather app.
My idea is to request the IP address from the client and link that to a geo location and lastly a weather API. Again, I am quite a novice in this field so any help would be appreciated. Feels like I have been Googling without any success for the last two days.
So far, I have the following code for the local time.
<!DOCTYPE html>
<html>
<head>
<style>
table {
font-family:Arial, Helvetica, sans-serif;
font-size:24px;
}
</style>
<script>
function startTime() {
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
m = checkTime(m);
s = checkTime(s);
document.getElementById('txt').innerHTML =
h + ":" + m + ":" + s;
var t = setTimeout(startTime, 500);
}
function checkTime(i) {
if (i < 10) {i = "0" + i}; // add zero in front of numbers < 10
return i;
}
</script>
</head>
<body onload="startTime()">
<table>
<tr><td>Current Local Time:</td><td><div id="txt"</div></tr><td></td>
</div>
</table>
</body>
</html>

thats a great project for learning javascript. The more experienced you get with javascript the more you will learn about the different api features of the browser. One of these features is the navigator to ask the user for permission for geolocation and to retrieve the data:
navigator.geolocation.getCurrentPosition( (data) => console.log(data) )
The following link gives you a great and more detailed Overview about Geolocation possibilities of the browser -> html geolocation
You can now send these values to a backend which maps from geolocation to weahterinformation.

first try to get user's location
now you need to use an api and filter by that location
to do that there is many ways that can help depending on the Api here is some suggestion you will find
some apis uses longitude and latitude and others uses location name.
so in this example you will get the latitude and longitude of user location and then use them like the following in a fetch method that is GET Method by default .
<script>
const getlocation = () => {
navigator.geolocation.watchPosition(async(pos) => {
var lat = pos.coords.latitude;
var long = pos.coords.longitude;
const url = "https://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + long;
const response = await fetch(url);
const data = await response.json();
console.log(data);
});
}
</script>
the data will be in json
so you can jump into any necessary variables in json object and get it for example
if you get
{
"coord": { "lon": 139,"lat": 35},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01n"
}
],......
you can create a variable and get weather by doing this
const result = data.weather[0];
var id = result.id
Note the URL not working and you need to have a valid API key or use another one if you have.

Related

How to split JSON data from app script on a spreadsheet getting info from Wialon platform

I've collected some code to get this work, this GPS platform (Wialon) is for tracking vehicles and it has some functions to get notifications, one of them is to send them via server GET / POST method, so I have the following result in one cell:
{"|2020/08/13 18:57|CR-03 FR|0 km|🦂|JESUS SALVADOR GARCIA SCOTT|":""} //example
I separated some values by "||||" characters just to split them easily by SPLIT() formula in Google Sheets, but I want a cleaner result from the script, this is what I got from this code:
Please if you can help me to get this FINAL result, it didn't have to be necessarily formatted (date), this already splitted and separated by "|":
In this code are other functions that send the same data to a Telegram Group, ignore it, just put it here in case helps to anyone.
var token = "FILL IN YOUR OWN TOKEN"; // 1. FILL IN YOUR OWN TOKEN
var telegramUrl = "https://api.telegram.org/bot" + token;
var webAppUrl = "FILL IN YOUR GOOGLE WEB APP ADDRESS"; // 2. FILL IN YOUR GOOGLE WEB APP ADDRESS
var ssId = "FILL IN THE ID OF YOUR SPREADSHEET"; // 3. FILL IN THE ID OF YOUR SPREADSHEET
var adminID = "-XXXXXXXXX"; // 4. Fill in your own Telegram ID for debugging
function getMe() {
var url = telegramUrl + "/getMe";
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function setWebhook() {
var url = telegramUrl + "/setWebhook?url=" + webAppUrl;
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function sendText(id,text) {
var url = telegramUrl + "/sendMessage?chat_id=" + id + "&text=" + encodeURIComponent(text);
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
function doGet(e) {
return HtmlService.createHtmlOutput("Hi there");
}
function doPost(e) {
try {
// this is where telegram works
var data = JSON.parse(e.postData.contents);
var text = data.message.text;
var id = data.message.chat.id;
var name = data.message.chat.first_name + " " + data.message.chat.last_name;
var answer = "Hi " + name;
sendText(id,answer);
SpreadsheetApp.openById(ssId).getSheets()[0].appendRow([new Date(),id,name,text,answer]);
if(/^#/.test(text)) {
var sheetName = text.slice(1).split(" ")[0];
var sheet = SpreadsheetApp.openById(ssId).getSheetByName(sheetName) ? SpreadsheetApp.openById(ssId).getSheetByName(sheetName) : SpreadsheetApp.openById(ssId).insertSheet(sheetName);
var newText = text.split(" ").slice(1).join(" ");
sheet.appendRow([new Date(),id,name,newText,answer]);
sendText(id,"your text '" + newText + "' is now added to the sheet '" + sheetName + "'");
}
} catch(e) {
sendText(adminID, JSON.stringify(e,null,4));
}
}
This is the notification panel in the GPS platform and how it should be configured with the App Script:
I believe your goal as follows.
You want to split the following value in a cell of Google Spreadsheet.
{"|2020/08/13 18:57|CR-03 FR|0 km|🦂|JESUS SALVADOR GARCIA SCOTT|":""}
Sample formula:
=QUERY(ARRAYFORMULA(SPLIT(REGEXEXTRACT(SUBSTITUTE(A1:A5," km","|km"),"\|(\w.+)\|"),"|",TRUE,FALSE)),"select Col2,Col1,Col6,Col3,Col4")
The flow of this formula is as follows.
Put | to 0 km using SUBSTITUTE.
Retrieve |2020/08/13 18:57|CR-03 FR|0 km|🦂|JESUS SALVADOR GARCIA SCOTT| from {"|2020/08/13 18:57|CR-03 FR|0 km|🦂|JESUS SALVADOR GARCIA SCOTT|":""} using REGEXEXTRACT.
Split it with | using SPLIT.
Rearrange the columns using QUERY.
Result:
When your sample value is used with above formula, it becomes as follows.
Note:
Above proposed answer uses the built-in functions of Google Spreadsheet. If you want to convert above using Google Apps Script, please tell me. At that time, can you provide the sample values including {"|2020/08/13 18:57|CR-03 FR|0 km|🦂|JESUS SALVADOR GARCIA SCOTT|":""} from the response of the API? By this, I would like to think of the solution.
References:
SUBSTITUTE
REGEXEXTRACT
SPLIT
QUERY

Google Scripts: Pull Google Document Based on User ID / Email

Good Morning Stack!
I was looking for some advice for some expanded functionality on a Google Script that helps me track and process absence requests. The process is as follows:
A user submits their form responses
The form responses are stored on a spreadsheet
A google doc, pre-created, is pulled and the values from the spreadsheet are implanted in the document.
The document is converted to a PDF
That PDF is automatically emailed to me.
However, some work policies have changed and I now need this form to have a signature that is unique to the person filling the form. In the past we simply printed the resulting PDF and had the person sign off on it.
I know I do not have the technicality to add on any sort of Electronic Signature functionality, nor is emailing that PDF to them an option as it doesn't create a fillable PDF (and my users don't really know how to digitally sign items anyways)
So what I was thinking is to create a form unique to each of the 15-20 users of this process and instead of a getFileByID, have the script check the Google Users account / email and pull the file created for them and stored in my drive instead.
As follows is my current, functional, script. How could I make this work?
function onFormSubmit(e) {
var Last_Name = e.values[2];
var First_Name = e.values[3];
var Middle_Initial = e.values[4];
var Work_Location = e.values[5];
var Job_Title = e.values[6];
var Contact_Number = e.values[7];
var Start = e.values[8];
var End = e.values[9];
var Time = e.values[10];
var Reason = e.values[11];
var D = new Date();
var copyId = DriveApp
.getFileById("1sdfjlsdf55asdfnk565enasdfnsnsd2")
.makeCopy("AbsenceRequest" + Last_Name + Start).getId();
var copyDoc = DocumentApp.openById(copyId)
var copyBody = copyDoc.getActiveSection();
copyBody.replaceText('keyLastName', Last_Name);
copyBody.replaceText('keyFirstName', First_Name);
copyBody.replaceText('keyMiddleInitial', Middle_Initial);
copyBody.replaceText('keyWorkLocation', Work_Location);
copyBody.replaceText('keyJobTitle', Job_Title);
copyBody.replaceText('keyContactNumber',Contact_Number);
copyBody.replaceText('keyStart', Start);
copyBody.replaceText('keyEnd', End);
copyBody.replaceText('keyTime', Time);
copyBody.replaceText('keyDate', D);
copyDoc.saveAndClose();
var pdf = DriveApp.getFileById(copyId).getAs("application/pdf");
var Email = "email#email.org" + "," + "email#email.org";
var Subject = "Absence Request"
var Body = "This is an absence request"
MailApp.sendEmail(Email, Subject, Body, {attachments: pdf});
DriveApp.getFileById(copyId).setTrashed(true);
}

Bitcoin - JavaScript function to return the current BTC exchange rate

I'm looking to write a JavaScript function that will return the current BTC/USD exchange rate. I've done some research, but I just want something simple. It won't be used server-side for calculating values (obvious security implications), but just as a convenience for my users. I have 2 text fields, and when the user changes one of the values, it will update the other field.
Here is my code so far:
var getBTCRate = function(){ /* code here */ };
var btcprice = getBTCRate();
// update the BTC value as the USD value is updated
$("#usdvalue").keyup(function(ev){
var usdvalue = $("#usdvalue").val();
$("#btcvalue").val(usdvalue / btcprice);
});
// update the USD value as the BTC value is updated
$("#btcvalue").keyup(function(ev){
var btcvalue = $("#btcvalue").val();
$("#usdvalue").val(btcvalue * btcprice);
});
Plain and simple. In my research I haven't been able to find something that will do this, only a bunch of confusing APIs. Any help is much appreciated.
EDITED to fix a mistake in the code.
EDITED AGAIN to fix the position of the function declaration. Thanks to #RobG for pointing this out.
My first idea was to use JQuery load like this
$.get('https://www.google.com/search?q=btc+value', function(p) {
console.log(p);
});
but cross-origin rules stopped me.
Now, you can pay for a service that has an API, but I wanted to do it without having to pay. What I ended up doing is a server based solution. I use PowerBasic for my back end, with the SocketTools Library.
#COMPILE EXE
#DIM ALL
#Include "pbcgi.inc"
#Include "C:\bas_src\socketTools\v9.5\inc\cstools9.inc"
Function PBMain () As Long
Local btc As String
Local html As String
html= httpGet("https://www.google.com/search?q=btc+value")
' filter out just the current BTC value
' by looking for what is between the words "Bitcoin =" and "United States Dollar"
btc=Remain$(html,"Bitcoin =")
btc=Extract$(btc,"United States Dollar")
btc=Trim$(btc)
writeCGI "{"+jsonPad("btc")+":"+jsonPad(btc)+","+jsonPad("error")+":"+jsonPad("0")+"}"
END FUNCTION
'================================================================
' retrieve the page and return it as a string
Function httpGet(ByVal URL As String) As String
If IsFalse( HttpInitialize($CSTOOLS9_LICENSE_KEY) ) Then
Function="unable to init socket library"
Exit Function
End If
Local hClient As Dword
Local lpszURL As STRINGZ * 4096
Local lpszBuffer As STRINGZ * 100000
Local httpContents As String
Local httpPort As Long
Local httpOptions As Dword
Local nResult As Long
If LCase$(Trim$(Left$(URL, 8))) = "https://" Then
httpPort = 443
httpOptions = %HTTP_OPTION_SECURE Or %HTTP_OPTION_REDIRECT
Else
httpPort = 80
httpOptions = %HTTP_OPTION_REDIRECT
End If
lpszURL = URL & Chr$(0)
hClient = HttpConnect(lpszURL, _
httpPort, _
%HTTP_TIMEOUT, _
httpOptions, _
%HTTP_VERSION_10)
If hClient = %INVALID_CLIENT Then
Function = "Could not connect to: " & URL
Exit Function
End If
HttpSetEncodingType(hClient, %HTTP_ENCODING_NONE)
nResult = HttpGetText(hClient, lpszURL, lpszBuffer, 100000)
If nResult = %HTTP_ERROR Then
Function = "Error retrieving file."+Str$(nResult)
Else
' success
httpContents = lpszBuffer
Function =httpContents
End If
Call HttpDisconnect(hClient)
HttpUninitialize()
End Function
'================================================================
' pad string for json return
Function jsonPad(jstr As String) As String
Local i As Long
Replace Chr$(10) With " " In jstr
Replace Chr$(13) With " " In jstr
Replace "\" With "\\" In jstr
Replace $Dq With "\"+$Dq In jstr
For i = 0 To 9
Replace Chr$(i) With " " In jstr
Next
Function=$Dq+Trim$(jstr)+$Dq
End Function
On my web page, I call it using AJAX
function showBTC(){
$.ajax({
type: "POST",
url: "../cgi/btcGet.exe",
dataType: "json",
success: function(json){
if(json.error !== "0" ){
console.log( json.error );
return;
}
$("#btcValue").html( "current BTC value $"+json.btc+"<br><br>" );
}
});
}
I know that seems like a "too specific" answer, but it's how I do it.
EDIT 5/11/2020:
there is a Bitcoin API found at coindesk.com which greatly simplifies this process.
const api = 'https://apiv2.bitcoinaverage.com/indices/local/ticker/short?crypto=BTC&fiat=USD'
$.get(api, p => {
document.querySelector('pre').textContent = JSON.stringify(p, null, 2)
});
Result
{
"BTCUSD": {
"ask": 3594.5649555077953,
"timestamp": 1550284932,
"bid": 3591.715961836563,
"last": 3592.745617344171,
"averages": {
"day": 3583.13243402
}
}
}
So take your pick p.BTCUSD.ask // or bid or last
demo

Cannot select JSON elements

I'm brand new to web dev but I'm trying to create a Weather app using the openweatherapp API: https://openweathermap.org/current#geo . The JSON object is below:
{"coord":{"lon":5.38,"lat":34.72},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"stations","main":{"temp":280.903,"pressure":1000.23,"humidity":65,"temp_min":280.903,"temp_max":280.903,"sea_level":1031.37,"grnd_level":1000.23},"wind":{"speed":8.5,"deg":317},"clouds":{"all":0},"dt":1486603649,"sys":{"message":0.3449,"country":"DZ","sunrise":1486621797,"sunset":1486660553},"id":2475612,"name":"Tolga","cod":200}
Here's my javascript:
$(document).ready(function() {
// findind my latitude and longitude
if(navigator.geolocation){
function success(position){
var lat = position.coords.latitude.toString();
var long = position.coords.longitude.toString();
$("p").html("latitude: " + lat + "<br>longitude: " + long);
// using the API to get the weather from those lat and long values
$.getJSON("http://api.openweathermap.org/data/2.5/weather?lat=" + lat + "&lon=" + long+"&appid=6a5aa3b59ebd571086cbd82be484ec8b", function(a){
temp = a[0].main.temp.toString();
hum = a[0].main.humidity.toString();
press= a[0].main.pressure.toString();
name = a[0].name;
$("h1").html(temp);
});
};
};
function failure(){
$("p").html("Not working");
};
navigator.geolocation.getCurrentPosition(success,failure);
});
The lat and long part is running fine but not the API for the weather.
Any help would be appreciated.
EDIT: Here's my codepen to make it simpler : https://codepen.io/tadm123/pen/OWojPx
Worked fine for me. Make sure that your browser has permission to know your location and that the computer has GPS. This probably will not work on a desktop.
Try manually setting the lat and long values and it should work.

Twitter OAuth Request_Token with Javascript, possibly wrong time?

So I'm trying and failing to get a token from twitter.
I get the following error: "Failed to validate oauth signature and token".
I have read it can be due to your system clock being wrong.
In javascript I tested my date with the following code
var minutes=1000*60;
var hours=minutes*60;
var days=hours*24;
var years=days*365;
var d=new Date();
var t=d.getTime();
var y=t/years;
console.log((y+1970) + " year and " + (t%years)/days)
This gave me the year as 2012 and 17 days..
1972
1976
1980
1984
1988
1992
1996
2000
2004
2008
__=10 leap days. Today is the 8th, so taking away leap days it appears my system clock is on the 7th? Or have I made a mistake here? If this is the problem how do I fix correct my clock?
In cmd when I do the date cmd it gives me todays date, i.e the 8th.
Here is my post request and code in case the problem lies within the code and not the clock.
My Post request is:
POST http://api.twitter.com/oauth/request_token?oauth_callback=127.0.0.1&oauth_consumer_key=FFZJrBaPLsiwTDg5159tTQ&oauth_nonce=tWHEEIW8vLS6tMggo3IXe6e449qv1GpE8LunKRsbRF&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1326039495&oauth_version=1.0&oauth_signature=d%2BQqgTzJCjYIp9vKwm%2BCWzVLPvA
which gets 401 (Unauthorized)
Here is my javascript code.
var url = "http://api.twitter.com/oauth/request_token";
var params={
oauth_callback : "127.0.0.1"
,oauth_consumer_key : "FFZJrBaPLsiwTDg5159tTQ"
,oauth_nonce : OAuth.nonce(42)
,oauth_signature_method : "HMAC-SHA1"
,oauth_timestamp : OAuth.timestamp()
,oauth_version: "1.0"}
//temp is to be the signature base string
var temp = toSignParams("POST",url,params);
console.log(temp);
//This logs the signature base string as "POST&http%3A%2F%2Fapi.twitter.com%2Foauth%2Frequest_token&oauth_callback%3D127.0.0.1%26oauth_consumer_key%3DFFZJrBaPLsiwTDg5159tTQ%26oauth_nonce%3D5gQVIa3WmwD6ARGGQTITl1Ozgxe2t8em5HC7g8wvMi%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1326038871%26oauth_version%3D1.0"
//which is correct I think.
//When I use this with the base signature from twitters oauth example page I get the result they got.
//it hashes the twitter signing key with base signature.
params.oauth_signature = b64_hmac_sha1("MCD8BKwGdgPHvAuvgvz4EQpqDAtx89grbuNMRd7Eh98&",temp);
var req = new XMLHttpRequest();
req.open("POST",toURIParams(url,params),true);
req.send();
console.log(params)
req.onreadystatechange=function(){
if (req.readyState==4)
{
console.log(req.responseText); //this is saying "Failed to validate oauth signature and token"
}
}
//function to convert to Signature paramaters, as indicated on twitter page.
function toSignParams(method,base,params){
tail=[];
for (var p in params) {
if (params.hasOwnProperty(p)) {
tail.push(p + "%3D" + encodeURIComponent(params[p]));
}
}
return method + "&" + encodeURIComponent(base) + "&" + tail.join("%26")
}
//function to convert to uri encoded parameters.
function toURIParams(base, params) {
tail = [];
for (var p in params) {
if (params.hasOwnProperty(p)) {
tail.push(p + "=" + encodeURIComponent(params[p]));
}
}
return base + "?" + tail.join("&")
}
Any ideas?
I used a library called "jsOAuth-1.3.3" as was found on the twitter list of libraries compatible with JavaScript but is no longer there.
The 2 javascript options they list now are:
user-stream by #AivisSilins — a simple Node.js User streams client
and
codebird-js by #mynetx — a Twitter Library in JScript.
as found on https://dev.twitter.com/docs/twitter-libraries
If anybody has a problem where they can't get either of those solutions to work, I can try find online or upload the library I used somewhere.

Categories

Resources