I have a map that I have ported from V2 to V3 and I am trying to update the code to refresh the KML data at a set time. In this case every 30 secs. It is just suppose to update the data on the map and show the countdown for when the next update happens.
Here is a working version of how it is suppose to work in V2.
V2 EXAMPLE
Here is the relevant code in the V3 script I have updated but it is not working. I am not getting any errors so I am not sure what I am doing wrong. This is working on V2 but I can't get it to work with V3. What am I missing and overlooking?
//This calls genkml.php on every refresh cycle to generate a new kml file
function UpdateKML() {
//document.getElementById('TheDiv').innerHTML = '0';
var xmlhttp=false;
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
xmlhttp=false;
}
}
if (!xmlhttp && window.createRequest) {
try {
xmlhttp = window.createRequest();
} catch (e) {
xmlhttp=false;
}
}
xmlhttp.open("GET", "genkml.php?force=" + force + "&ofd=" + KMLdate + "&nsd=" + NSdate + "&dbg=" + dbg + "&rand="+(new Date()).valueOf(),true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
var resp = xmlhttp.responseText;
//if (resp === undefined) resp = ''; // If we get a bad response, just set resp to nothing
if (dbg == 'y') { // Check if we want debug info
var tmpresp = resp;
if (tmpresp === undefined) tmpresp = ' ';
if (document.getElementById('div1') == null) { // Check if debug div exists, if not add it to end of body
var divTag = document.createElement("div");
divTag.id = "div1";
divTag.innerHTML = 'Response Status: ' + xmlhttp.status + '<br />' + tmpresp;
document.body.appendChild(divTag);
} else { // Otherwise just update the info
document.getElementById('div1').innerHTML = 'Response Status: ' + xmlhttp.status + '<br />' + tmpresp;
}
} else { // Else check if debug div exists and remove it (will take an update to remove
if (document.getElementById('div1') != null) document.body.removeChild(document.getElementById("div1"));
}
if (resp !== undefined) { // Make sure we got data
KMLdate = resp.split("|")[0].split("~")[0];
NSdate = resp.split("|")[0].split("~")[1];
updateHTML(resp); // This calls the updateHTML function if there is info returned
}
}
}
xmlhttp.send(null);
// add back overlays
nyLayer = new google.maps.KmlLayer(null);
nyLayer.setMap(null); // Remove overlays
var nyLayer = new google.maps.KmlLayer(URLToKML + "?rand="+(new Date()).valueOf(),
{
suppressInfoWindows: false,
map: map,
preserveViewport: true,
zIndex: 999
});
// Time overlayed on map - could be in updateHTML() to just show when .kml read last
var time = CurrentTime ("B", "12a", true, TZOffset)
document.getElementById('currenttime').innerHTML = time;
}
function CurrentTime (type, hours, secs, ofs) {
/*
type (char) hours (char) secs (bool) ofs (num)
"U"-UTC "24"=24 hr time true=hh:mm:ss 0=hours from UTC
"B"-User's Browser "12"=12 hr time false=hh:mm
"S"-Web Site "12a"=am/pm
*/
if (type == null){ type = "B"; } // These are the defaults
if (hours == null){ hours = "12a"; }
if (secs == null){ secs = true; }
if (ofs == null){ ofs = 0; }
var currentHour = 0;
var currentMinute = 0;
var currentSecond = 0;
var time = 0;
var currentDate = new Date();
if (type == "U") {
currentHour = currentDate.getUTCHours(); // UTC
} else if (type == "B") {
currentHour = currentDate.getHours(); // Viewer's time
} else {
currentHour = currentDate.getUTCHours() + ofs; // your local time
if(currentHour < 0) { currentHour = currentHour + 24;}
}
currentMinute = currentDate.getMinutes();
currentMinute = (currentMinute < 10 ? "0" : "") + currentMinute;
if (hours == "24") {
if(currentHour == 24) { currentHour = 0 }; // use if wanting 24 hour time
currentHour = (currentHour < 10 ? "0" : "") + currentHour;
} else if (hours == "12") {
if(currentHour == 0) currentHour = 12;
currentHour = (currentHour < 10 ? "0" : "") + currentHour;
} else {
if(currentHour == 0) currentHour = 12; // else no leading zero for am/pm
}
time = currentHour + ":" + currentMinute;
if (secs) {
currentSecond = currentDate.getSeconds();
currentSecond = (currentSecond < 10 ? "0" : "") + currentSecond;
time = time + ":" + currentSecond;
}
if (hours == "12a") {
time = time + " " + (currentHour > 12 ? "PM" : "AM");
}
return time;
}
//This function is only used if you leave the debug checkbox below
// You can remove this function and the checkbox and set the debug
// mode using the dbg=y query parameter
function debug(obj){
if (obj.checked) {
dbg='y';
} else {
dbg='n';
if (document.getElementById('div1') != null) document.body.removeChild(document.getElementById("div1"));
//document.getElementById('TheDiv').innerHTML = '';
}
}
//This function is only used if you leave the Force Update checkbox below
// You can remove this function and the checkbox and set the force
// mode using the force=y query parameter
function forceupdate(obj){
if (obj.checked) {
force='y';
} else {
force='n';
}
}
//This function parses out the query parameter value
function gup( name ){
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
Here is a link to the full .js map code for V3 if anyone needs to see it.
V3 NSGAMP CODE
V3 FULL PAGE
EDIT: I think it has to do with this snippet of code that is suppose to remove then add the updated KML data to the map.
This was in V2 which is depreciated now.
// add back overlays
map.removeOverlay(geoXml); //Remove overlays
geoXml = new GGeoXml(URLToKML + "?rand="+(new Date()).valueOf() ); //rand is used to trick google maps into thinking this is a new KML (don't use cache version)
map.addOverlay(geoXml); //Add the new data from the newly generated KML
Code I updated for V3 replacing the above depreciated V2 snippet which was found by searching. Not sure if this is correct but it was all I could find.
// add back overlays
nyLayer = new google.maps.KmlLayer(null);
nyLayer.setMap(null); // Remove overlays
function refresh(layer) {
var nyLayer = new google.maps.KmlLayer(URLToKML + "?rand="+(new Date()).valueOf(),
{
suppressInfoWindows: false,
map: map,
preserveViewport: true,
zIndex: 999
});
}
I got it sorted and working and I knew it was a simple edit but I was having a really difficult time finding a solution. If anyone else this could help this is what I did.
Changed this in the V2 version.
updateHTML(resp); //This calls the updateHTML function if there is info returned
}
}
}
xmlhttp.send(null);
// add back overlays
map.removeOverlay(geoXml); //Remove overlays
geoXml = new GGeoXml(URLToKML + "?rand="+(new Date()).valueOf() ); //rand is used to trick google maps into thinking this is a new KML (don't use cache version)
map.addOverlay(geoXml); //Add the new data from the newly generated KML
To this in the V3 version.
updateHTML(resp); // This calls the updateHTML function if there is info returned
}
//remove layer
window.nyLayer.setMap(null);
//change its url so that we would force the google to refetch data
window.nyLayer.url = URLToKML + "?rand="+(new Date()).valueOf();
//and re-add layer
window.nyLayer.setMap(window.map);
}
}
xmlhttp.send(null);
The map.removeOverlay and map.addOverlay is depreciated in V3 so it took me while to find the replacement.
Or you can simplify it even further and use:
window.nyLayer.url = URLToKML + '&ver=' + Date.now();
Related
I am wanting to drive a web page using data from a few google sheets.
I’ve figure out how to query my sheet, but the data displays as a datatable and that’s not what I’m looking for. I’d like to be able to take the query cell value and insert it into HTML code. I will also use the value in another query in order to retrieve other information from a different google sheet.
I have two live pages:
http://www.bandstand.ca/widget
This page is a starter skeleton version of my project. I have “Day 5” statically coded and formatted for now but want to replace it with query data as per:
http://www.bandstand.ca/widget/sas.html
I had tried using getValue(0,0) but must not have had something set right. I am totally new to using queries and have not been able to figure out if JavaScript can do anything with the content of the response. I tried hiding the div element that the query fills and just parsing content of the data table, but again, couldn’t figure out a workable solution. I’ve tried searching through the api documentation but I’m not finding anything that looks right either. Surely there’s a way to extract the data and use it within other html. I don’t particularly care if the code is clean (as I’m sure you can tell, I’ve hacked apart other peoples’ code to get the sas.html file down to where it’s at.) I just want something that works.
I’m a teacher and thought this would be an easy little project to build an in-class announcement page that I could have displayed all the time in my room and have it cycle through my schedule of classes via my easily updated google sheets. So far, not so easy! If anyone can help tweak my code to get what I’m asking, I’d sure be grateful!
You can try something like this:
function GetCurrentDate() {
var currentTime = new Date();
var month = currentTime.getMonth() + 2;
var day = currentTime.getDate();
var year = currentTime.getFullYear();
var currentDate = "'" + year + "-" + month + "-" + day + "'";
return currentDate;
}
function CreateUrl(key, gql) {
var gq = 'SELECT '+ gql;
var encodedgg = encodeURIComponent(gq);
var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg;
return url;
}
function Request(url, responseFunction) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = this.responseText.substring(this.responseText.IndexOf("(")+1, this.responseText.lastIndexOf(")"));
var responseJSON = JSON.parse(response);
responseFunction(responseJSON);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
function preview(elm, url) {
fetch(url)
.then(data => data.text())
.then(function(response) {
var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")"));
var response = JSON.parse(responseText);
var value = response['table']['rows'][0]['c'][0]['v'];
elm.innerHTML = value;
})
}
var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ';
var currentDate = GetCurrentDate();
var gql = "C WHERE A = DATE " + currentDate;
var url = CreateUrl(gsKey, gql);
var previewElement = document.getElementById('preview');
preview(previewElement, url);
<html>
<head>
<title>Student Announcement System</title>
</head>
<body>
<div id="preview">initial value</div>
</body>
</html>
Here is link to jsbin snippet. (Inline stackoverflow snippet might not work because of CORS and Access-Control-Allow-Origin.)
EDIT after Greg Duguid's comment:
There are three problems with your code:
Your scripts are not working at all. Try to run following snippet:
<script>
document.write("Text 1")
</script>
<script language = "text/javascript">
document.write("Text 2")
</script>
<script type = "text/javascript">
document.write("Text 3")
</script>
When you run it you should get something like Text 1 Text 3 and that is because <script language = "text/javascript"> is wrong and won't work, language parameter is deprecated and you should use type instead. Also in HTML5 you can omit type parameter so it is best to use syntax like this <script>document.write("Text")</script>.
There is syntax error in function preview: last bracket ( should be ).
// OLD CODE
/*
function preview(elm, url) {
fetch(url)
.then(data => data.text())
.then(function(response) {
var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")"));
var response = JSON.parse(responseText);
var value = response['table']['rows'][0]['c'][0]['v'];
//elm.innerHTML = value;
DayNumber = value;
}
( // ERROR IS IN THIS LINE
}
*/
// NEW CODE
function preview(elm, url) {
fetch(url)
.then(data => data.text())
.then(function(response) {
var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")"));
var response = JSON.parse(responseText);
var value = response['table']['rows'][0]['c'][0]['v'];
//elm.innerHTML = value;
DayNumber = value;
}
) // error WAS in this line
}
Code in line:
<font size="+6" color="#FFFF00">Day <script>document.write(DayNumber);</script></font>
When you call function document.write(DayNumber) variable DayNumber is equal to "" because function preview is still not executed at that moment. Reason for this is that execution of function preview takes time. (Because you are retrieving data from sheet document, usually when you retrieve data from server or something similar that takes time.) Execution of code in javascript is asynchronous which means that javscript doesn't wait for function to finish with execution and goes on. Look at this example:
function getData() {
// some function that takes time to get data from server, ducument, or something else
return data;
}
var data = getData();
document.write(data);
In first line function getData() is called, but data will be set to undefined because program will not wait for function getData() to return its value. So function document.write(data) will not preview anything.
(Also it is not good practice to use script tag inside another tag. So you should avoid putting script tag inside font tag like this: <font size="+6" color="#FFFF00">Day <script>document.write(DayNumber);</script></font>.)
Solution for this problem is that you add id to you font tag and than change text in font tag in javascript inside function preview:
function GetCurrentDate() {
var currentTime = new Date();
var month = currentTime.getMonth();
var day = currentTime.getDate() + 1;
var year = currentTime.getFullYear();
var currentDate = "'" + year + "-" + month + "-" + day + "'";
return currentDate;
}
function CreateUrl(key, gql) {
var gq = 'SELECT '+ gql;
var encodedgg = encodeURIComponent(gq);
var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg;
return url;
}
function Request(url, responseFunction) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = this.responseText.substring(this.responseText.IndexOf("(")+1, this.responseText.lastIndexOf(")"));
var responseJSON = JSON.parse(response);
responseFunction(responseJSON);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
function preview(elm, url) {
fetch(url)
.then(data => data.text())
.then(function(response) {
var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")"));
var response = JSON.parse(responseText);
var value = response['table']['rows'][0]['c'][0]['v'];
elm.innerHTML += " " + value;
}
)
}
var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ';
var currentDate = GetCurrentDate();
var gql = "C WHERE A = DATE " + currentDate;
var url = CreateUrl(gsKey, gql);
var previewElement = document.getElementById('preview');
preview(previewElement, url);
<html>
<title>Student Announcement System</title>
<body>
<font size="+6" color="#FFFF00" id="preview">Day</font>
</body>
</html>
This last code should be solution to your problem. Also here is link to jsbin snippet (because stackoverflow snippet might not work when you run it).
EDIT after second Greg Duguid's comment:
Sorry it took little longer to answer. Problem is in line:
var previewElement = document.getElementById('preview');
When this line is executed previewElement is not found and it is set to undefined. This is because javascript code in script tag (<script>...</script>) is before body tag (<body>...</body>) so code is executed before elements in body are defined. So when your page is run, first javascript code is executed and then element <font id="preview">Day</font> is defined. There is simple solution for this: You need to put your script tag at the end of body like this:
<html>
<head>
<style type="text/css">
<!--
body {
background-color: #003c66;
}
-->
</style>
<title>Student Announcement System</title>
</head>
<body>
<font size="+6" color="#FFFF00" id="preview">Day</font>
<script>
function GetCurrentDate() {
var currentTime = new Date();
var month = currentTime.getMonth()+1;
var day = currentTime.getDate();
var year = currentTime.getFullYear();
var currentDate = "'" + year + "-" + month + "-" + day + "'";
return currentDate;
}
function CreateUrl(key, gql, sheet) {
var gq = 'SELECT '+ gql;
var encodedgg = encodeURIComponent(gq);
var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg + '&gid=' + sheet;
return url;
}
function Request(url, responseFunction) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = this.responseText.substring(this.responseText.IndexOf("(")+1, this.responseText.lastIndexOf(")"));
var responseJSON = JSON.parse(response);
responseFunction(responseJSON);
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
function preview(elm, url) {
fetch(url)
.then(data => data.text())
.then(function(response) {
var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")"));
var response = JSON.parse(responseText);
var value = response['table']['rows'][0]['c'][0]['v'];
elm.innerHTML += " " + value;
}
)
}
var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ';
var gsSheet='349215948';
var currentDate = GetCurrentDate();
var gql = "C WHERE A = DATE " + currentDate;
var url = CreateUrl(gsKey, gql, gsSheet);
var previewElement = document.getElementById('preview');
preview(previewElement, url);
</script>
</body>
</html>
And again here is jsbin snippet which should work.
EDIT after this Greg Duguid's comment:
The problem is in your query:
var PERIODgql = "C WHERE A = " + value + " AND B = " + CurrentPeriod;
CurrentPeriod is string so you need to add single quotes around it like this:
var PERIODgql = "C WHERE A = " + value + " AND B = '" + CurrentPeriod + "'";
When it is created, PERIODgql will be something like:
"C WHERE A = 1 AND B = 'P5'"
These queries are similar to SQL queries (which are used to get data form SQL database), you can read more about this here.
Also i noticed your function FindCurrentPeriod:
function FindCurrentPeriod() {
var CurrentPeriod;
var CurrentDate = new Date();
//////////////////////////////
//FOR TESTING VARIOUS TIMES
CurrentDate.setHours(14);
CurrentDate.setMinutes(0);
//////////////////////////////
var CurrentHour = CurrentDate.getHours();
var CurrentMinute = CurrentDate.getMinutes();
if (CurrentHour < 8) {
CurrentPeriod = "Before School";
}
if (CurrentHour == 8) {
if (CurrentMinute < 40) {
CurrentPeriod = "Before School";
} else {
CurrentPeriod = "P1";
}
}
if (CurrentHour == 9) {
if (CurrentMinute < 40) {
CurrentPeriod = "P1";
} else {
if (CurrentMinute < 45) {
CurrentPeriod = "B12";
} else {
CurrentPeriod = "P2";
}
}
}
if (CurrentHour == 10) {
if (CurrentMinute < 37) {
CurrentPeriod = "P2";
} else {
if (CurrentMinute < 47) {
CurrentPeriod = "B23";
} else {
CurrentPeriod = "P3";
}
}
}
if (CurrentHour == 11) {
if (CurrentMinute < 39) {
CurrentPeriod = "P3";
} else {
if (CurrentMinute < 44) {
CurrentPeriod = "B34";
} else {
CurrentPeriod = "P4";
}
}
}
if (CurrentHour == 12) {
if (CurrentMinute < 36) {
CurrentPeriod = "P4";
} else {
CurrentPeriod = "Lunch";
}
}
if (CurrentHour == 13) {
if (CurrentMinute < 13) {
CurrentPeriod = "Lunch";
} else {
CurrentPeriod = "P5";
}
}
if (CurrentHour == 14) {
if (CurrentMinute < 5) {
CurrentPeriod = "P5";
} else {
if (CurrentMinute < 10) {
CurrentPeriod = "B56";
} else {
CurrentPeriod = "P6";
}
}
}
if (CurrentHour == 15) {
if (CurrentMinute < 2) {
CurrentPeriod = "P6";
} else {
CurrentPeriod = "After School";
}
} else {
CurrentPeriod = "After School";
}
return CurrentPeriod;
}
While this is working, it is not really easy to read and there is some repeating conditions so if need to change your code later, that will be harder to do. So I would suggest using a function to help you compare time (in hours and minutes). You can add just short function like this:
function time(hours, minutes) {
return hours*60 + minutes;
}
Now you can compare times 10:50 and 11:25 like this:
if (time(10,50) < time(11,25)) {
//part when you do what you want if condition is ture
}
So you can write your function FindCurrentPeriod like this:
function FindCurrentPeriod() {
var CurrentPeriod;
var CurrentDate = new Date();
//////////////////////////////
//FOR TESTING VARIOUS TIMES
CurrentDate.setHours(14);
CurrentDate.setMinutes(0);
//////////////////////////////
var CurrentHour = CurrentDate.getHours();
var CurrentMinute = CurrentDate.getMinutes();
var cirrentTime = time(CurrentHour, CurrentMinute);
if (cirrentTime < time(8, 40)) {
CurrentPeriod = "Before School";
}
else if (cirrentTime < time(9, 40)) {
CurrentPeriod = "P1";
}
else if (cirrentTime < time(9, 45)) {
CurrentPeriod = "B12";
}
else if (cirrentTime < time(10, 37)) {
CurrentPeriod = "P2";
}
else if (cirrentTime < time(10, 47)) {
CurrentPeriod = "B23";
}
else if (cirrentTime < time(11, 39)) {
CurrentPeriod = "P3";
}
else if (cirrentTime < time(11, 44)) {
CurrentPeriod = "P3";
}
else if (cirrentTime < time(12, 36)) {
CurrentPeriod = "P4";
}
else if (cirrentTime < time(13, 13)) {
CurrentPeriod = "Lunch";
}
else if (cirrentTime < time(14, 5)) {
CurrentPeriod = "P5";
}
else if (cirrentTime < time(14, 10)) {
CurrentPeriod = "B56";
}
else if (cirrentTime < time(15, 2)) {
CurrentPeriod = "P6";
}
else {
CurrentPeriod = "After School";
}
return CurrentPeriod;
}
This is shorter and also easier to read and change if needed.
Here is whole code in stackoverflow snippet (again I'll add jsbin snippet below, because inline stackoverflow snippet might not work because of CORS rules):
function preview2(elm, url) {
fetch(url)
.then(data => data.text())
.then(function(response) {
var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")"));
var response = JSON.parse(responseText);
var value = response['table']['rows'][0]['c'][0]['v'];
elm.innerHTML = value;
})
}
function GetCurrentDate() {
var currentTime = new Date();
var month = currentTime.getMonth() + 1;
var day = currentTime.getDate();
var year = currentTime.getFullYear();
var currentDate = "'" + year + "-" + month + "-" + day + "'";
return currentDate;
}
function CreateUrl(key, gql, sheet) {
var gq = 'SELECT ' + gql;
var encodedgg = encodeURIComponent(gq);
var url = 'https://docs.google.com/spreadsheets/d/' + key + '/gviz/tq?tq=' + encodedgg + '&gid=' + sheet;
return url;
}
function time(hours, minutes) {
return hours*60 + minutes;
}
function FindCurrentPeriod() {
var CurrentPeriod;
var CurrentDate = new Date();
//////////////////////////////
//FOR TESTING VARIOUS TIMES
CurrentDate.setHours(14);
CurrentDate.setMinutes(0);
//////////////////////////////
var CurrentHour = CurrentDate.getHours();
var CurrentMinute = CurrentDate.getMinutes();
var cirrentTime = time(CurrentHour, CurrentMinute);
if (cirrentTime < time(8, 40)) {
CurrentPeriod = "Before School";
}
else if (cirrentTime < time(9, 40)) {
CurrentPeriod = "P1";
}
else if (cirrentTime < time(9, 45)) {
CurrentPeriod = "B12";
}
else if (cirrentTime < time(10, 37)) {
CurrentPeriod = "P2";
}
else if (cirrentTime < time(10, 47)) {
CurrentPeriod = "B23";
}
else if (cirrentTime < time(11, 39)) {
CurrentPeriod = "P3";
}
else if (cirrentTime < time(11, 44)) {
CurrentPeriod = "P3";
}
else if (cirrentTime < time(12, 36)) {
CurrentPeriod = "P4";
}
else if (cirrentTime < time(13, 13)) {
CurrentPeriod = "Lunch";
}
else if (cirrentTime < time(14, 5)) {
CurrentPeriod = "P5";
}
else if (cirrentTime < time(14, 10)) {
CurrentPeriod = "B56";
}
else if (cirrentTime < time(15, 2)) {
CurrentPeriod = "P6";
}
else {
CurrentPeriod = "After School";
}
return CurrentPeriod;
}
function preview1(elm, url) {
fetch(url)
.then(data => data.text())
.then(function(response) {
var responseText = response.substring(response.indexOf("(") + 1, response.lastIndexOf(")"));
var response = JSON.parse(responseText);
var value = response['table']['rows'][0]['c'][0]['v'];
elm.innerHTML += " " + value;
var CurrentPeriod = FindCurrentPeriod();
var PERIODgsSheet = '618896702';
var PERIODgql = "C WHERE A = " + value + " AND B = '" + CurrentPeriod + "'";
var PeriodURL = CreateUrl(gsKey, PERIODgql, PERIODgsSheet);
var periodElement = document.getElementById('period1');
preview2(periodElement, PeriodURL);
})
}
var gsKey = '1-dNm_AKv3Iiy-ggLjGJKHPwUqs379QJh0e4SzbEPcJQ';
var DAYgsSheet = '349215948';
var currentDate = GetCurrentDate();
var DAYgql = "C WHERE A = DATE " + currentDate;
var DayURL = CreateUrl(gsKey, DAYgql, DAYgsSheet);
var previewElement = document.getElementById('preview');
preview1(previewElement, DayURL);
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="refresh" content="600" />
<title>Student Announcement System</title>
<style type="text/css">
<!--
body {
background-color: #003c66;
}
-->
</style>
<!-- CSS Code -->
<style type="text/css" scoped>
.GeneratedMarquee {
font-family:'Arial Black', sans-serif;
font-size:8em;
font-weight:bold;
line-height:2em;
text-align:left;
color:#ffff00;
background-color:#003c66;
padding:40pt;
}
</style>
</head>
<body>
<table width=100%>
<tr>
<td width=240px>
<iframe scrolling="no" frameborder="no" clocktype="html5" style="overflow:hidden;border:0;margin:0;padding:0;width:240px;height:80px;"src="https://www.clocklink.com/html5embed.php?clock=004&timezone=MST&color=white&size=240&Title=&Message=&Target=&From=2018,1,1,0,0,0&Color=white"></iframe>
</td>
<td nowrap>
<center>
<font size="80px" color="#FFFF00" id="preview">DAY </font>
</center>
</td>
<td width=100%>
<a class="weatherwidget-io" href="https://forecast7.com/en/53d54n113d49/edmonton/" data-label_1="EDMONTON" data-font="Helvetica" data-icons="Climacons Animated" data-days="7" data-theme="original" data-basecolor="#003c66" ></a>
<script>
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src='https://weatherwidget.io/js/widget.min.js';fjs.parentNode.insertBefore(js,fjs);}}(document,'script','weatherwidget-io-js');
</script>
</td>
</tr>
</table>
<font color="FFFFFF", size="+6">
<script language=javascript>
var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
var today = new Date();
document.write(today.toLocaleDateString("en-US", options)); // Saturday, September 17, 2016
formattedDate = today.toLocaleDateString("en-US", options);
</script>
</font>
<br><font size="80px" color="#FFFF00" id="period1">Class:</font>
<script src="sas.js"></script>
</body>
</html>
Here is jsbin snippet.
I am trying to make a counter with JS. So far I've managed to pull that off, however I now encounter a problem. While using AJAX to retreive the time to count down I can't make it work. It's weird because it works on my original file but not with a php file called by AJAX.
This works fine :
https://jsfiddle.net/6kvp25vv/
I have no idea what the problem is. This is the HTML page :
<button onclick="upgrade('meat_max')" id="up_meat_max">+</button>
When I click on the button, it runs the function inside this js file which creates a GET request on upgrade.php :
function upgrade(building) {
var file = 'upgrade.php?building=' + building;
ajax(file, function(response) {
document.getElementById('construction').innerHTML += response;
})
}
function ajax(file, fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
fn(xmlhttp.responseText);
}
};
xmlhttp.open('GET', file, true);
xmlhttp.send();
}
And this is the code from upgrade.php (variables sent to this file with AJAX are not used for the purpose of testing the code) :
<div class="time">Time: <span id="timer">?</span></div>
var hour = 2;
var minute = 46;
var second = 45;
// function to make a counter
function clockIt() {
function clockO(digit) {
if(digit<10) {
return '0';
} else {
return '';
}
}
document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
if(second>0) {
second -= 1;
} else if(minute>0) {
minute -= 1;
second += 59;
} else if(hour>0) {
hour -= 1;
minute += 59;
}
}
// runs the function every seconds
clockIt();
setInterval(function (){clockIt()}, 1000);
innerHTML does not execute ajax loaded scripts, what I would do in your case is to return a JSON encoded string with the variables that you need and have a function on your main script (the one thats already loaded) with this provided script, that way you already have the function ready and only pass parameters with the ajax response.
You can decode a json string with:
obj = JSON.parse(jsonString);
For example:
Ajax JSON response string:
{"time": {"hour":2, "minute":46, "second": 45}, "html": "<div class=\"time\">Time: <span id=\"timer\"></span></div>"}
Modified upgrade function:
function upgrade(building) {
var file = 'upgrade.php?building=' + building;
ajax(file, function(response) {
obj = JSON.parse(response);
time = obj.time;
document.getElementById('construction').innerHTML += obj.html;
startCountdown(time.hour, time.minute, time.second);
})
}
New function
function startCountdown(hour, minute, second) {
// function to make a counter
function clockIt() {
function clockO(digit) {
if(digit<10) {
return '0';
} else {
return '';
}
}
document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
if(second>0) {
second -= 1;
} else if(minute>0) {
minute -= 1;
second += 59;
} else if(hour>0) {
hour -= 1;
minute += 59;
}
}
// runs the function every seconds
clockIt();
setInterval(function (){clockIt()}, 1000);
}
My problem was with the method for the countdown timer. When you specify an interval of 1000 milliseconds, you can't count on it being 1000 milliseconds. It's actually as soon as the timer loop gets to it after 1000 milliseconds have passed. Over a period of time, there are going to be some delays. What you want to do, if you want accurate timing, is to store the initial settings and then measure the time from when the countdown was started to the current time. See the code below which bases the timer on the internal clock rather than the interval counter. Once you have the number of seconds, you can easily it convert it to hours, minutes, and seconds by dividing by 3600 for the hours and using division and modulo arithmetic for the minute and second.
See https://www.sitepoint.com/creating-accurate-timers-in-javascript/
How to create an accurate timer in javascript?
<!DOCTYPE html />
<html>
<head>
<meta encoding="UTF-8" />
<title>Testing XMLHttpRequest</title>
<script>
var request;
var button1;
var display1;
var display2;
var display3;
var start;
var counter;
function second() {
display2.value = display2.value + "\r\nreadyState=" + request.readyState + " status=" + request.status + "\r\n";;
if (request.readyState == 4 && request.status == 200) {
display1.value = display1.value + request.responseText + "\r\n";
}
}
function first() {
display2.value = display2.value + "\r\n" +
"Starting page \r\n";
request = new XMLHttpRequest();
request.onreadystatechange = second;
var file = "http://localhost:80/";
request.open('GET', file, true);
request.send();
setInterval(timed, 1000);
}
function starter() {
display1 = document.getElementById("display1");
display2 = document.getElementById("display2");
display3 = document.getElementById("display3");
button1 = document.getElementById("button1");
button1.onclick = first;
start = new Date();
counter = 60;
}
function timed() {
var duration = (start.getTime() - new Date().getTime()) / 1000.0;
display3.value = (duration + counter).toFixed(0);
}
window.onload = starter;
</script>
</head>
<body>
<form>
<p>
<input type="button" id="button1" value="Start" />Timer:
<input type="text" readonly="readonly" id="display3" />
</p>
<p>Status:
<textarea rows="5" cols="30" id="display2"></textarea>
</p>
<p>Response:
<textarea rows="60" cols="80" id="display1"></textarea>
</p>
</form>
</body>
</html>
Found a way to compensate the delays, using the original version :
function upgrade(building) {
var file = 'upgrade.php?building=' + building;
ajax(file, function(response) {
var obj = JSON.parse(response);
var time = obj.time;
document.getElementById('construction').innerHTML += obj.html;
run_clockIt(time.hour, time.minute, time.second);
})
}
// general AJAX launcher
function ajax(file, fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
fn(xmlhttp.responseText);
}
};
xmlhttp.open('GET', file, true);
xmlhttp.send();
}
// count down timer with adjustments to compensate delay
function clockIt(hour, minute, second, finished, nbOfLoop) {
// every 5 seconds, run a delay correction
if(nbOfLoop%5 == 0) {
var actualTimeLeft = adjustClock(finished);
minute = actualTimeLeft[0];
second = actualTimeLeft[1];
}
nbOfLoop += 1;
// add a string "0" if necessary
function clockO(digit) {
if(digit<10) {
return '0';
} else {
return '';
}
}
document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
// update displayed timer
if(second>0) {
second -= 1;
} else if(minute>0) {
minute -= 1;
second += 59;
} else if(hour>0) {
hour -= 1;
minute += 59;
}
// waits 1 sec before launching the next one
setTimeout(function() {
clockIt(hour, minute, second, finished, nbOfLoop);
}, 1000);
}
// runs the function for the first time
function run_clockIt(hour, minute, second) {
var finished = new Date();
finished.setUTCHours(finished.getUTCHours() + hour);
finished.setUTCMinutes(finished.getUTCMinutes() + minute);
finished.setUTCSeconds(finished.getUTCSeconds() + second);
clockIt(hour, minute, second, finished, 1);
}
function adjustClock(finished) {
var now = new Date();
var diff = new Date(Math.abs(now - finished));
return [diff.getUTCMinutes(), diff.getUTCSeconds()];
}
This way, the count down timer is smooth, no lagging and most of all you can define the interval on which the adjust function will run and correct the timer.
This is the php file, preparing the JSON object (thanks #Miguel) :
<?php
header('Content-Type: application/json');
// retreive variables from AJAX call
$building = $_REQUEST['building'];
// processing variable with database...
// prepare JSON object
$jsonData = '
{
"time":{"hour":2, "minute":46, "second": 45},
"html": "<div class=\"time\">Time: <span id=\"timer\"></span></div>"
}
';
echo $jsonData;
last year I was using the code found here http://gdata-javascript-client.googlecode.com/svn/trunk/samples/calendar/simple_sample/simple_sample.html to retrieve all events from "now" of a public Google Calendar and then display the results in a webpage.
I modified that code to match my needs (see the code below).
Now, with API v3, the code doesn't work anymore and I'm not able to understand which lines of the code are deprecated and how to update them.
Could please someone help me with this code?
Thank you so much :-)
<body>
<script type="text/javascript" src="http://www.google.com/jsapi?key=YOUR_KEY_HERE"></script>
<script type="text/javascript">
/* Loads the Google data JavaScript client library */
google.load("gdata", "2.x");
function init() {
// init the Google data JS client library with an error handler
google.gdata.client.init(handleGDError);
// load the code.google.com calendar
loadMyCalendar();
}
/**
* Loads the Google Event Calendar
*/
function loadMyCalendar() {
loadCalendarByAddress('MY_ADDRESS#gmail.com'); /* address here
}
/**
* Adds a leading zero to a single-digit number. Used for displaying dates.
*/
function padNumber(num) {
if (num <= 9) {
return "0" + num;
}
return num;
}
/**
* Determines the full calendarUrl based upon the calendarAddress
* argument and calls loadCalendar with the calendarUrl value.
*
* #param {string} calendarAddress is the email-style address for the calendar
*/
function loadCalendarByAddress(calendarAddress) {
var calendarUrl = 'https://www.google.com/calendar/feeds/' +
calendarAddress +
'/public/full';
loadCalendar(calendarUrl);
}
function loadCalendar(calendarUrl) {
var service = new
google.gdata.calendar.CalendarService('gdata-js-client-samples-simple');
var query = new google.gdata.calendar.CalendarEventQuery(calendarUrl);
query.setOrderBy('starttime');
query.setSortOrder('ascending');
query.setFutureEvents(true);
query.setSingleEvents(true);
query.setMaxResults(100);
service.getEventsFeed(query, listEvents, handleGDError);
}
/**
* Callback function for the Google data JS client library to call when an error
* occurs during the retrieval of the feed. Details available depend partly
* on the web browser, but this shows a few basic examples. In the case of
* a privileged environment using ClientLogin authentication, there may also
* be an e.type attribute in some cases.
*
* #param {Error} e is an instance of an Error
*/
function handleGDError(e) {
document.getElementById('jsSourceFinal').setAttribute('style',
'display:none');
if (e instanceof Error) {
/* alert with the error line number, file and message */
alert('Error at line ' + e.lineNumber +
' in ' + e.fileName + '\n' +
'Message: ' + e.message);
/* if available, output HTTP error code and status text */
if (e.cause) {
var status = e.cause.status;
var statusText = e.cause.statusText;
alert('Root cause: HTTP error ' + status + ' with status text of: ' +
statusText);
}
} else {
alert(e.toString());
}
}
/**
* Callback function for the Google data JS client library to call with a feed
* of events retrieved.
*
* Creates an unordered list of events in a human-readable form. This list of
* events is added into a div called 'events'. The title for the calendar is
* placed in a div called 'calendarTitle'
*
* #param {json} feedRoot is the root of the feed, containing all entries
*/
function listEvents(feedRoot) {
var entries = feedRoot.feed.getEntries();
var eventDiv = document.getElementById('events');
if (eventDiv.childNodes.length > 0) {
eventDiv.removeChild(eventDiv.childNodes[0]);
}
var ul = document.createElement('ul');
/* set the calendarTitle div with the name of the calendar */
/*document.getElementById('calendarTitle').innerHTML =
"Calendar: " + feedRoot.feed.title.$t + "<br/><br/>";*/
/* loop through each event in the feed */
var len = entries.length;
for (var i = 0; i < len; i++) {
var entry = entries[i];
/* contenuto e titolo sono invertiti */
var cont = entry.getTitle().getText();
var title = entry.getContent().getText(); /* get description notes */
/* only events containing WORD_1 &/or WORD_2 & not containing '?' */
if(cont.indexOf('?') == -1 && (cont.indexOf('WORD_1') > -1 || cont.indexOf('WORD_2') > -1)){
var whereIs = entry.getLocations()[0].getValueString();
var startDateTime = null;
var startJSDate = null;
var times = entry.getTimes();
if (times.length > 0) {
startDateTime = times[0].getStartTime();
startJSDate = startDateTime.getDate();
}
var entryLinkHref = null;
if (entry.getHtmlLink() != null) {
entryLinkHref = entry.getHtmlLink().getHref();
}
var day = padNumber(startJSDate.getDate());
var month = padNumber(startJSDate.getMonth() + 1);
var dateString = day + "/" + month + "/" + startJSDate.getFullYear();
if (title.indexOf(' - ') > -1) {
cont = title.substring(0, title.indexOf(' - ')+3) + cont + " # " + whereIs;
title = title.substring(title.indexOf(' - ')+3);
} else cont = "h_:_ - " + cont + " # " + whereIs;
var li = document.createElement('li');
/* if we have a link to the event, create an 'a' element */
if (entryLinkHref != null) {
entryLink = document.createElement('a');
entryLink.setAttribute('href', entryLinkHref);
li.appendChild(document.createTextNode(dateString + ' - '));
entryLink.appendChild(document.createTextNode(title));
li.appendChild(entryLink);
} else {
li.appendChild(document.createTextNode(dateString + ' - ' + title));
}
var p = document.createElement("p");
var lo = document.createElement('lo');
lo.appendChild(document.createTextNode(cont));
li.style.fontSize = "25px";
lo.style.fontSize = "15px";
/* append the list item onto the unordered list */
ul.appendChild(li);
ul.appendChild(lo);
ul.appendChild(p);
}
eventDiv.appendChild(ul);
}
}
google.setOnLoadCallback(init);
</script>
<p id="events">LOADING CALENDAR . . . . . . . . . .</p>
</body>
SOLVED :-) here's the javascript code to access and show upcoming events of PUBLIC google Calendars, with Google Calendar API v3.
<html>
<head>
</head>
<body bgcolor="black" text="white" link="#00ffff" vlink="green" alink="yellow">
<script>
var clientId = 'YOUR_CLIENT_ID HERE'; //choose web app client Id, redirect URI and Javascript origin set to http://localhost
var apiKey = 'YOUR_APIKEY_HERE'; //choose public apiKey, any IP allowed (leave blank the allowed IP boxes in Google Dev Console)
var userEmail = "YOUR_ADDRESS#gmail.com"; //your calendar Id
var userTimeZone = "YOUR_TIME_ZONE_HERE"; //example "Rome" "Los_Angeles" ecc...
var maxRows = 10; //events to shown
var calName = "YOUR CALENDAR NAME"; //name of calendar (write what you want, doesn't matter)
var scopes = 'https://www.googleapis.com/auth/calendar';
//--------------------- Add a 0 to numbers
function padNum(num) {
if (num <= 9) {
return "0" + num;
}
return num;
}
//--------------------- end
//--------------------- From 24h to Am/Pm
function AmPm(num) {
if (num <= 12) { return "am " + num; }
return "pm " + padNum(num - 12);
}
//--------------------- end
//--------------------- num Month to String
function monthString(num) {
if (num === "01") { return "JAN"; }
else if (num === "02") { return "FEB"; }
else if (num === "03") { return "MAR"; }
else if (num === "04") { return "APR"; }
else if (num === "05") { return "MAJ"; }
else if (num === "06") { return "JUN"; }
else if (num === "07") { return "JUL"; }
else if (num === "08") { return "AUG"; }
else if (num === "09") { return "SEP"; }
else if (num === "10") { return "OCT"; }
else if (num === "11") { return "NOV"; }
else if (num === "12") { return "DEC"; }
}
//--------------------- end
//--------------------- from num to day of week
function dayString(num){
if (num == "1") { return "mon" }
else if (num == "2") { return "tue" }
else if (num == "3") { return "wed" }
else if (num == "4") { return "thu" }
else if (num == "5") { return "fri" }
else if (num == "6") { return "sat" }
else if (num == "0") { return "sun" }
}
//--------------------- end
//--------------------- client CALL
function handleClientLoad() {
gapi.client.setApiKey(apiKey);
checkAuth();
}
//--------------------- end
//--------------------- check Auth
function checkAuth() {
gapi.auth.authorize({client_id: clientId, scope: scopes, immediate: true}, handleAuthResult);
}
//--------------------- end
//--------------------- handle result and make CALL
function handleAuthResult(authResult) {
if (authResult) {
makeApiCall();
}
}
//--------------------- end
//--------------------- API CALL itself
function makeApiCall() {
var today = new Date(); //today date
gapi.client.load('calendar', 'v3', function () {
var request = gapi.client.calendar.events.list({
'calendarId' : userEmail,
'timeZone' : userTimeZone,
'singleEvents': true,
'timeMin': today.toISOString(), //gathers only events not happened yet
'maxResults': maxRows,
'orderBy': 'startTime'});
request.execute(function (resp) {
for (var i = 0; i < resp.items.length; i++) {
var li = document.createElement('li');
var item = resp.items[i];
var classes = [];
var allDay = item.start.date? true : false;
var startDT = allDay ? item.start.date : item.start.dateTime;
var dateTime = startDT.split("T"); //split date from time
var date = dateTime[0].split("-"); //split yyyy mm dd
var startYear = date[0];
var startMonth = monthString(date[1]);
var startDay = date[2];
var startDateISO = new Date(startMonth + " " + startDay + ", " + startYear + " 00:00:00");
var startDayWeek = dayString(startDateISO.getDay());
if( allDay == true){ //change this to match your needs
var str = [
'<font size="4" face="courier">',
startDayWeek, ' ',
startMonth, ' ',
startDay, ' ',
startYear, '</font><font size="5" face="courier"> # ', item.summary , '</font><br><br>'
];
}
else{
var time = dateTime[1].split(":"); //split hh ss etc...
var startHour = AmPm(time[0]);
var startMin = time[1];
var str = [ //change this to match your needs
'<font size="4" face="courier">',
startDayWeek, ' ',
startMonth, ' ',
startDay, ' ',
startYear, ' - ',
startHour, ':', startMin, '</font><font size="5" face="courier"> # ', item.summary , '</font><br><br>'
];
}
li.innerHTML = str.join('');
li.setAttribute('class', classes.join(' '));
document.getElementById('events').appendChild(li);
}
document.getElementById('updated').innerHTML = "updated " + today;
document.getElementById('calendar').innerHTML = calName;
});
});
}
//--------------------- end
</script>
<script src='https://apis.google.com/js/client.js?onload=handleClientLoad'></script>
<div id='content'>
<h1 id='calendar' style="color:grey">LOADING . . . .</h1>
<ul id='events'></ul>
</div>
<p id='updated' style="font-size:12; color:grey">updating . . . . .</p>
</body>
</html>
Here's a simplified, annotated, and updated script based on Max's original that makes use of Moment.js and JQuery. Read the full blog post here for details (including how to get your API key), or just replace YOUR_CALENDAR_ID and YOUR_API_KEY in the script below:
<script>
/* This solution makes use of "simple access" to google, providing only an API Key.
* This way we can only get access to public calendars. To access a private calendar,
* we would need to use OAuth 2.0 access.
*
* "Simple" vs. "Authorized" access: https://developers.google.com/api-client-library/javascript/features/authentication
* Examples of "simple" vs OAuth 2.0 access: https://developers.google.com/api-client-library/javascript/samples/samples#authorizing-and-making-authorized-requests
*
* We will make use of "Option 1: Load the API discovery document, then assemble the request."
* as described in https://developers.google.com/api-client-library/javascript/start/start-js
*/
function printCalendar() {
// The "Calendar ID" from your calendar settings page, "Calendar Integration" secion:
var calendarId = 'YOUR_CALENDAR_ID#group.calendar.google.com';
// 1. Create a project using google's wizzard: https://console.developers.google.com/start/api?id=calendar
// 2. Create credentials:
// a) Go to https://console.cloud.google.com/apis/credentials
// b) Create Credentials / API key
// c) Since your key will be called from any of your users' browsers, set "Application restrictions" to "None",
// leave "Website restrictions" blank; you may optionally set "API restrictions" to "Google Calendar API"
var apiKey = 'YOUR_API_KEY';
// You can get a list of time zones from here: http://www.timezoneconverter.com/cgi-bin/zonehelp
var userTimeZone = "Europe/Budapest";
// Initializes the client with the API key and the Translate API.
gapi.client.init({
'apiKey': apiKey,
// Discovery docs docs: https://developers.google.com/api-client-library/javascript/features/discovery
'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'],
}).then(function () {
// Use Google's "apis-explorer" for research: https://developers.google.com/apis-explorer/#s/calendar/v3/
// Events: list API docs: https://developers.google.com/calendar/v3/reference/events/list
return gapi.client.calendar.events.list({
'calendarId': calendarId,
'timeZone': userTimeZone,
'singleEvents': true,
'timeMin': (new Date()).toISOString(), //gathers only events not happened yet
'maxResults': 20,
'orderBy': 'startTime'
});
}).then(function (response) {
if (response.result.items) {
var calendarRows = ['<table class="wellness-calendar"><tbody>'];
response.result.items.forEach(function(entry) {
var startsAt = moment(entry.start.dateTime).format("L") + ' ' + moment(entry.start.dateTime).format("LT");
var endsAt = moment(entry.end.dateTime).format("LT");
calendarRows.push(`<tr><td>${startsAt} - ${endsAt}</td><td>${entry.summary}</td></tr>`);
});
calendarRows.push('</tbody></table>');
$('#wellness-calendar').html(calendarRows.join(""));
}
}, function (reason) {
console.log('Error: ' + reason.result.error.message);
});
};
// Loads the JavaScript client library and invokes `start` afterwards.
gapi.load('client', printCalendar);
</script>
You will also need to include Moment.JS and the Google JS API somewhere in your page:
<script src="https://cdn.jsdelivr.net/npm/moment#2/moment.min.js"></script>
<script src="https://apis.google.com/js/api.js"></script>
I'm working on a script to get the Geolocations (Lat, lon) that I can use to center my instance of google maps. For now i work with 2 possible technologies. One is the google.loader.ClientLocation object. I haven't tested this one yet because it returns null for me. I think because I'm not living on a regular location (Willemstad, Curacao using a wireless internet connection. So my modem is wireless.).
Therefore I made a backup plan using navigator.geolocation. This works great in Chrome, but firefox gives a timeout and it doesn't work at all in IE.
Does anyone know a good alternative method to get the users geolocation, or does anyone have recommendation on my code how it can become more stable.
I set a timeout for navigator.geolocation because I don't want my users to wait for more as 5 seconds. Increasing the timeout does not improve the reliability of firefox.
function init_tracker_map() {
var latitude;
var longitude;
if(google.loader.ClientLocation) {
latitude = (google.loader.ClientLocation.latitude);
longitude = (google.loader.ClientLocation.longitude);
buildMap(latitude, longitude);
}
else if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function(position) {
latitude = (position.coords.latitude);
longitude = (position.coords.longitude);
buildMap(latitude, longitude);
},
function errorCallback(error) {
useDefaultLatLon();
},
{
enableHighAccuracy:false,
maximumAge:Infinity,
timeout:5000
}
);
}
else {
useDefaultLatLon();
}
}
function useDefaultLatLon() {
latitude = (51.81540697949437);
longitude = (5.72113037109375);
buildMap(latitude, longitude);
}
ps. I'm aware there are more questions like this on SO but couldn't find a clear answer. I'm hoping that people made some new discovery's.
Update:
Tried google gears aswell. Succesfull in chrome again. Fails in FF and IE.
var geo = google.gears.factory.create('beta.geolocation');
if(geo) {
function updatePosition(position) {
alert('Current lat/lon is: ' + position.latitude + ',' + position.longitude);
}
function handleError(positionError) {
alert('Attempt to get location failed: ' + positionError.message);
}
geo.getCurrentPosition(updatePosition, handleError);
}
Update 2: navigator.geolocation works fine in FF from my work location.
Final Result
This works great. Get an api key from ipinfodb.org
var Geolocation = new geolocate(false, true);
Geolocation.checkcookie(function() {
alert('Visitor latitude code : ' + Geolocation.getField('Latitude'));
alert('Visitor Longitude code : ' + Geolocation.getField('Longitude'));
});
function geolocate(timezone, cityPrecision) {
alert("Using IPInfoDB");
var key = 'your api code';
var api = (cityPrecision) ? "ip_query.php" : "ip_query_country.php";
var domain = 'api.ipinfodb.com';
var version = 'v2';
var url = "http://" + domain + "/" + version + "/" + api + "?key=" + key + "&output=json" + ((timezone) ? "&timezone=true" : "&timezone=false" ) + "&callback=?";
var geodata;
var JSON = JSON || {};
var callback = function() {
alert("lol");
}
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
var t = typeof (obj);
if (t != "object" || obj === null) {
// simple data type
if (t == "string") obj = '"'+obj+'"';
return String(obj);
}
else {
// recurse array or object
var n, v, json = [], arr = (obj && obj.constructor == Array);
for (n in obj) {
v = obj[n]; t = typeof(v);
if (t == "string") v = '"'+v+'"';
else if (t == "object" && v !== null) v = JSON.stringify(v);
json.push((arr ? "" : '"' + n + '":') + String(v));
}
return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
}
};
// implement JSON.parse de-serialization
JSON.parse = JSON.parse || function (str) {
if (str === "") str = '""';
eval("var p=" + str + ";");
return p;
};
// Check if cookie already exist. If not, query IPInfoDB
this.checkcookie = function(callback) {
geolocationCookie = getCookie('geolocation');
if (!geolocationCookie) {
getGeolocation(callback);
}
else {
geodata = JSON.parse(geolocationCookie);
callback();
}
}
// Return a geolocation field
this.getField = function(field) {
try {
return geodata[field];
} catch(err) {}
}
// Request to IPInfoDB
function getGeolocation(callback) {
try {
$.getJSON(url,
function(data){
if (data['Status'] == 'OK') {
geodata = data;
JSONString = JSON.stringify(geodata);
setCookie('geolocation', JSONString, 365);
callback();
}
});
} catch(err) {}
}
// Set the cookie
function setCookie(c_name, value, expire) {
var exdate=new Date();
exdate.setDate(exdate.getDate()+expire);
document.cookie = c_name+ "=" +escape(value) + ((expire==null) ? "" : ";expires="+exdate.toGMTString());
}
// Get the cookie content
function getCookie(c_name) {
if (document.cookie.length > 0 ) {
c_start=document.cookie.indexOf(c_name + "=");
if (c_start != -1){
c_start=c_start + c_name.length+1;
c_end=document.cookie.indexOf(";",c_start);
if (c_end == -1) {
c_end=document.cookie.length;
}
return unescape(document.cookie.substring(c_start,c_end));
}
}
return '';
}
}
geolocation using javascript will work with HTML 5 compliant browsers, so that leaves out IE completely.
Your alternative is to use the IP address to ascertain the approximate lat/long.
Using this alternative method and assuming you find a provider with an accurate and complete lat/long-to-IP mapping, you will only get the lat/long of the ISP (or the nearest point where the ISP connects to the internet).
Hope this resets your expectation (about location-accuracy)
you should read this Which Devices Support Javascript Geolocation via navigator.geolocation?
I had a similar problem and, for browsers without geolocation, went with server-side location based on the user's IP.
Two free geolocation services are:
http://www.maxmind.com/app/geolitecity
http://www.hostip.info/
I found maxmind to me much more accurate.
If it's possible within your project you could query the location before rendering the page, or perform an ajax call to query the location.
Hi, everyone!
I'm writing Asp.Net MVC 2 site.
I have TimeController and TimeView, CountDownHelper for render time on TimeView page.
Also I have JavaScript that updates current time, that is used in CountDownHelper.
I need to call AJAX from this JavaScript to get current Time on server.
How I can to do it? Please help me! I must it done about several hours!
Below you may see this javaScript and in its end my try to call AJAX. I have tried to write GetServerTime.html in several ways, but anyone from which don't work. (((
//countDown.js
function calcage(secs, num1, num2)
{
s = ((Math.floor(secs / num1)) % num2).toString();
if (LeadingZero && s.length < 2)
s = "0" + s;
return "<b>" + s + "</b>";
}
function CountBack(secs)
{
if (secs < 0)
{
location.reload(true);
document.getElementById("cntdwn").innerHTML = FinishMessage;
return;
}
//difference between recieve time and current client time
diff = new Date(new Date() - clientTime);
targetD = new Date(TargetDate);
serverD = new Date(serverDate);
currentServerDate = new Date(serverD.getTime() + diff.getTime());
//targetD
leftD = new Date(targetD.getTime() - currentServerDate.getTime());
secs = leftD.getTime() / 1000;
DisplayStr = DisplayFormat.replace(/%%D%%/g, calcage(secs, 86400, 100000));
DisplayStr = DisplayStr.replace(/%%H%%/g, calcage(secs, 3600, 24));
DisplayStr = DisplayStr.replace(/%%M%%/g, calcage(secs, 60, 60));
DisplayStr = DisplayStr.replace(/%%S%%/g, calcage(secs, 1, 60));
document.getElementById("cntdwn").innerHTML = DisplayStr;
if (CountActive)
setTimeout("CountBack(" + (secs + CountStepper) + ")", SetTimeOutPeriod);
}
function putspan(backcolor, forecolor)
{
document.write("<span id='cntdwn' style='background-color:" + backcolor +
"; color:" + forecolor + "'></span>");
}
if (typeof (BackColor) == "undefined")
BackColor = "white";
if (typeof (ForeColor) == "undefined")
ForeColor = "black";
if (typeof (TargetDate) == "undefined")
TargetDate = "12/31/2020 5:00 AM";
if (typeof (serverDate) == "undefined")
serverDate = "12/31/2020 5:00 AM";
if (typeof (DisplayFormat) == "undefined")
DisplayFormat = "%%D%% Days, %%H%% Hours, %%M%% Minutes, %%S%% Seconds.";
if (typeof (CountActive) == "undefined")
CountActive = true;
if (typeof (FinishMessage) == "undefined")
FinishMessage = "";
if (typeof (CountStepper) != "number")
CountStepper = -1;
if (typeof (LeadingZero) == "undefined")
LeadingZero = true;
CountStepper = Math.ceil(CountStepper);
if (CountStepper == 0)
CountActive = false;
var SetTimeOutPeriod = (Math.abs(CountStepper) - 1) * 1000 + 990;
putspan(BackColor, ForeColor);
var dthen = new Date(TargetDate);
var dtServ = new Date(serverDate);
var dnow = new Date();
if (CountStepper > 0)
ddiff = new Date(dnow - dthen);
else
ddiff = new Date(dthen - dtServ);
//ddiff = new Date(TargetDate - serverDate);
//ddiff = new Date(dthen - dnow);
gsecs = Math.floor(ddiff.valueOf() / 1000);
CountBack(gsecs);
alert("Start");
alert(serverDate);
//AJAX CALL ????
//How to call async JavaScript?
//Which must be GetServerTime.html
$.get('Views/GetServerTime.html', function(data) {
serverDate = data;
clientTime = new Date();
});
alert(serverDate);**
Normally you don't access your views directly. And the view is usually an .ASPX file.
So
$.get('Views/GetServerTime.html',...
Becomes
$.get('/GetServerTime/',...
For the Views/GetServerTime/Index.aspx view and the getserverTimeController.cs controller with a default Action of Index.
But I'm guessing that's not the only issue you have?...
Edit
Also you should probably use JSON for this. You can use the System.Web.Mvc.JsonResult to automatically send your result as JSON and jQuery will process and convert this JSON to javascript objects.
$.get('/GetServerTime/',
function (data)
{
if (data.HasError == false)
{
$("#resultDiv").html(data.ServerTime);
}
}, "json");
Your MVC Action can look like this...
public JsonResult Index(string id)
{
JsonResult res = new JsonResult();
res.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
res.Data = new { ServerTime = DateTime.Now(), HasError = false };
return res;
}
The above is approximate since I don't have a compiler.
First of all, I'm not sure "GetServerTime.html" will successfully give you the current time. Are you sure its the name of the page that you want? Unless you have your Routing set to handle that URL pattern. As Kervin says below.
Also, the body of the "function(data)" method is the callback that gets called when the ajax function returns.
As for your page that returns the server date/time, you'll need to decide what format it will return: XML or JSon. Then your controller would return that.
public class DateController : Controller {
public ActionResult CurrentDate()
{
var returnJson = new
{
currentDate = DateTime.Now.ToString()
}
return Json(returnJson, JsonRequestBehavior.AllowGet);
}
}
then your .get function would look like:
$.get('/Date' function(data) {
theDate = data.currentDate;
});