0

I am attempting to interface with the Google Maps API marking locations based on latitude and longitude data. I would also like to get time zone information based off of this latitude and longitude. To do this, I am using another external API that takes in the latitude and longitude and returns the time off-set. My issue, however, is that this time data returns after the page is loaded.

What is the best way to then add this information to the page after the page has loaded for the user? I started out thinking about using postback, but after doing some research, I don't think that's the right method for my problem.

Kruug
  • 449
  • 2
  • 9
  • 20

1 Answers1

1

In browsers, JavaScript allows you to contact a server after a page is loaded. This is known as an asynchronous request, the first 'A' in 'AJAX' (Asynchronous Java and XML).

The X can be a bit of a misnomer, as people will happily pass whole chunks of HTML, or JSON (AJAJ?) or other forms of data instead of XML through this mechanism.

I would always use a framework (my personal choice being JQuery) to perform the operation, as the framework writers will have done the job of making it all work cross-browser for you.

You could use this:

http://api.jquery.com/jQuery.get/ or if the return data is JSON, http://api.jquery.com/jQuery.getJSON/

This function, part of JQuery, will execute a callback function once the data is loaded. Your callback function can then use the JQuery selectors to find and update the elements in question.

If you update your question with specific code examples I can be more specific with my response.

Edit after seeing code example:

It looks like your problem is actually one of working out the order of code execution. Your code follows this pattern (somewhat simplified and a touch rearranged):

    var startTimeZone;

    jQuery(document).ready(function($) {
      $.ajax({
        url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + start_locale + "&format=json",
        dataType: "jsonp",
        success: function(parsed_json) {
          startTimeZone = parsed_json.data.time_zone[0].utcOffset;
          console.log("Callback: " + startTimeZone);
        },
        error: function(parsed_json) {

        }
      });
    });


    console.log("Main:" + startTimeZone);

Firstly, there isn't a need to wrap the ajax command in the document ready callback - that only needs to be done once for the whole of your code, around wherever the entry point is. (I assume that it was an attempt to delay the execution until after the following code.) (There is more to learn here as well - JQuery gives you more than one event to help initialise your code and work with the DOM, see window.onload vs $(document).ready() for a brief description)

If you ran the snippet above, you'd find that the console log would probably show:

Main: Undefined
Callback: [StartTimeZone]

where [StartTimezone] is the response from the server. The ajax command is asynchronous, meaning it goes off and does its thing, taking as long as it needs, leaving the code after it to run as if nothing had happened. When it's finished it calls the 'success' or 'error' callback appropriately. So the 'main' console log is called before the variable has been defined. After that, the callback is hit by the response to the ajax call - so the StartTimeZone is output.

If you're new to callbacks or used to a language that doesn't support them or use them very often (like PHP), you may expect or want the code to pause at the ajax call, then run the callback, then carry on with the rest of the code. Obviously this isn't the case.

In this simple situation I would simply move the code to process the timezone into the callback, but your code has a further wrinkle - you need two values, which you seem to need to retrieve with separate calls.

In this case, we need to make sure we have both values before we run the code that uses them. How can we do this?

A simple solution would be:

var startTimeZone;
var endTimeZone;

      $.ajax({
        url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + start_locale + "&format=json",
        dataType: "jsonp",
        success: function(parsed_json) {
          startTimeZone = parsed_json.data.time_zone[0].utcOffset;
          getEndTimeZone();
        },
        error: function(parsed_json) {
          //console.log("Error: " + parsed_json);
        }
      });



function getEndTimeZone() {
      $.ajax({
        url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + end_locale + "&format=json",
        dataType: "jsonp",
        success: function(parsed_json) {
          endTimeZone = parsed_json.data.time_zone[0].utcOffset;
          console.log(endTimeZone);
          processTimeZones();
        },
        error: function(parsed_json) {
          //console.log("Error: " + parsed_json);
        }
      });
}

function processTimeZones() {
    var timeZoneDifference = (endTimeZone * 3600000) - (startTimeZone * 3600000);
    // Do the rest of your processing here
}

Functions aren't run until they are called. Also, functions in JavaScript have access to the variables in their containing scope (this means that the functions have access to startTimeZone and endTimeZone, which are defined outside the functions themselves.)

The code above will call getEndTimeZone on success of the first ajax call. getEndTimeZone then uses an ajax call to get the end time zone, then calls the process function on success. This function definitely has access to the variables you need.

Of course, we're waiting in a queue now for two requests to be processed. We could speed things up a little by calling both at the same time, calling the process function with both, then figuring out if we have the data we need before doing the processing:

var startTimeZone;
var endTimeZone;

      $.ajax({
        url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + start_locale + "&format=json",
        dataType: "jsonp",
        success: function(parsed_json) {
          startTimeZone = parsed_json.data.time_zone[0].utcOffset;
          processTimeZones();
        },
        error: function(parsed_json) {
          //console.log("Error: " + parsed_json);
        }
      });



      $.ajax({
        url: "http://www.worldweatheronline.com/feed/tz.ashx?key=SecretKey&q=" + end_locale + "&format=json",
        dataType: "jsonp",
        success: function(parsed_json) {
          endTimeZone = parsed_json.data.time_zone[0].utcOffset;
          console.log(endTimeZone);
          processTimeZones();
        },
        error: function(parsed_json) {
          //console.log("Error: " + parsed_json);
        }
      });

function processTimeZones() {
  if (startTimeZone != undefined && endTimeZone != undefined)
  {
    var timeZoneDifference = (endTimeZone * 3600000) - (startTimeZone * 3600000);
    // Do the rest of your processing here
  }
}

Whichever ajax call returns first will call the process function. However, one of the variables will be undefined so the if condition will fail and the function will silently return. When the second result comes in, both variables will be set. Now the if condition will be met and the processing code will run.

There are 1001 ways to skin the proverbial cat, but these should hopefully get you started using the callbacks effectively.

Of course, all this is ignoring the fact that you've put the ajax calls in a for loop. Things could get funky if each iteration of the processing you need to do is dependent on the order it happens - the ajax calls could return in potentially any order. As you're plotting a route, this may well be the case.

If so, you could split your code into two phases - a loading phase and a processing phase. Run all the callbacks in the loading phase, then when you have all the data move to the processing phase and place the markers on the map. You could store the data in an array of objects.

There are a few ways to detect the end of the loading phase. One would be a counter that you increment every time you make an ajax call and decrement every time you get a success. You'd be able to create a loading progress bar using the same counter.

Also you could display a message to the user if any of the calls failed, with a link to restart the process. (Trivially this would reload the whole page, but you could restart the loading stage.)

HTH. By all means shout if you need further help.

Community
  • 1
  • 1
A Fader Darkly
  • 3,516
  • 1
  • 22
  • 28
  • I am already getting the information through jQuery/JSON...how would I go about adding this information at a later time? Also, I would post code, but my code is so horrendous at the moment, so it wouldn't be of any use to either of us. – Kruug Dec 18 '12 at 05:45
  • It would be useful to know a couple of things. Firstly, how must the information be added to the page? Is there an existing tag that needs its contents updating? Or do you need to add a new tag with the information? Both are pretty trivial operations in JQuery, using the selectors. However, to proceed I need to know more about the problem. What is the data you're getting back from the server and what do you want to do with it, exactly? Don't worry about horrible code. It would help to see it though, then I can offer a solution that you can plug straight in, rather than a vague recommendation – A Fader Darkly Dec 18 '12 at 09:33
  • http://pastebin.com/uqAAgdiH Here is the code that includes the timezone code. The information will actually be used in retrieving other data from a different source. The information will be displayed in Google Maps Markers as well as in a table below the map. The data I'm getting back is time offsets in milliseconds, and I want to add it to the current time to get the timezone's current time. – Kruug Dec 18 '12 at 18:28
  • @A Fader Darkly I was wondering if you had a chance to look at my situation again. If you don't have time, that's understandable. – Kruug Dec 19 '12 at 21:34
  • Apologies, things got busy. I'll have a look shortly. – A Fader Darkly Dec 20 '12 at 15:16
  • No worries. I realize that by coming for free help, I cannot expect people to drop what they are doing just to help me. – Kruug Dec 20 '12 at 15:22
  • Hi, I think I understand the underlying problem and the source of the confusion. I thought you were having a problem updating elements with JSON data, but it appears that the problem is with updating values and calling functions in the right order. Updating the answer. – A Fader Darkly Dec 21 '12 at 08:11
  • Very nice and thorough write-up. I am moving from desktop programming to web programming, so that's where my hang-up is (with timing and such). Thank you for the explanation on help. – Kruug Dec 21 '12 at 15:14