org.symbian.wrttools.doc.WRTKit/html/WRTKit_Travel_Companion_functionality-GUID-384f2430-3de9-4006-ac8e-86c5774c3a79.html
--- a/org.symbian.wrttools.doc.WRTKit/html/WRTKit_Travel_Companion_functionality-GUID-384f2430-3de9-4006-ac8e-86c5774c3a79.html Fri Mar 05 19:11:15 2010 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,854 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html lang="en" xml:lang="en">
-<head>
-<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
-<meta name="copyright" content="(C) Copyright 2005" />
-<meta name="DC.rights.owner" content="(C) Copyright 2005" />
-<meta content="concept" name="DC.Type" />
-<meta name="DC.Title" content="Functionality" />
-<meta scheme="URI" name="DC.Relation" content="WRTKit_Travel_Companion_Tutorial-GUID-be79ba64-fa03-4968-964e-d7dcc42d7053.html" />
-<meta content="XHTML" name="DC.Format" />
-<meta content="GUID-384F2430-3DE9-4006-AC8E-86C5774C3A79" name="DC.Identifier" />
-<meta content="en" name="DC.Language" />
-<link href="commonltr.css" type="text/css" rel="stylesheet" />
-<title>
-Functionality</title>
-</head>
-<body id="GUID-384F2430-3DE9-4006-AC8E-86C5774C3A79"><a name="GUID-384F2430-3DE9-4006-AC8E-86C5774C3A79"><!-- --></a>
-
-
-
- <h1 class="topictitle1">
-Functionality</h1>
-
- <div>
-
- <div class="section"><h2 class="sectiontitle">
-Weather forecast</h2>
-
-
- <p>
-
- Let's continue by implementing the weather forecast view. This view will
- be entirely composed of non-foldable ContentPanel controls. We'll have one
- panel that displays the city for which the forecast is for and one panel
- for each day of the five-day forecast. In order to make it easy to change
- the number of days the forecast is for we'll store references to the forecast
- panels in an array. Thus, we need to add two global variables to the widget:
- </p>
-
-<pre>
-
-// Weather view controls.
-var weatherCityPanel;
-var weatherContentPanels;
-</pre>
-
- <p>
-
- The next step is to create the actual view in the createWeatherView() function.
- Of course the actual content for the content panels won't be known until at
- runtime when we know what city the forecast is for and what the actual weather
- forecast is. Still, we can create the actual content panels and just set their
- content later so this is not a problem.
- </p>
-
-<pre>
-
-// Creates the weather view.
-function createWeatherView() {
- // empty caption text to display the caption bar - custom background using CSS
- weatherView = new ListView(null, "");
-
- // heading panel for city
- weatherCityPanel = new ContentPanel();
- weatherView.addControl(weatherCityPanel);
-
- // create five content panels - one for each day in the 5-day forecast
- weatherContentPanels = [];
- for (var i = 0; i < 5; i++) {
- var weatherContentPanel = new ContentPanel();
- weatherView.addControl(weatherContentPanel)
- weatherContentPanels.push(weatherContentPanel);
- }
-}
-</pre>
-
- <p>
-
- When we show the weather view we have to check what the current local city
- is and set the weatherCityPanel's content to a suitable HTML fragment that
- will work as a heading for the weather forecast. In addition to that we'll
- have to retrieve the weather forecast from the business logic engine and then
- create HTML from that for each day in the forecast and set it to the five
- content panels that we are storing references to in the weatherContentPanels
- array. The caption for the weather forecast panels will be a string that
- indicates the day that the forecast is for.
- </p>
-
- <p>
-
- Creating the HTML fragment for the forecast heading doesn't sound so hard
- but generating HTML for a weather forecast for five days sounds a bit tricky.
- Let's create a separate function to do that. Remember that the weather object
- that the engine is returning to us has two properties: temperature and type.
- The temperature is in the preferred temperature unit and the type is one of
- the type codes, e.g. "Sunny". We'll use it to match it up with a weather icon.
- </p>
-
-<pre>
-
-// Returns HTML for one day of weather forecast.
-function getHTMLForWeather(weather) {
- // build weather icon file name string
- var weatherIcon = "Weather" + weather.type + ".png";
-
- // build temperature string
- var temperatureStr = weather.temperature + "&deg;" + engine.getTemperatureUnit().toUpperCase();
-
- // build weather HTML
- var weatherBuf = "";
- weatherBuf += "<table class=\"WeatherForecastDayTable\"><tr>";
- weatherBuf += "<td class=\"WeatherForecastIconCell\">";
- weatherBuf += "<img src=\"" + weatherIcon + "\"/>";
- weatherBuf += "</td>";
- weatherBuf += "<td class=\"WeatherForecastTemperatureCell\">";
- weatherBuf += temperatureStr;
- weatherBuf += "</td>";
- weatherBuf += "</tr></table>";
-
- return weatherBuf;
-}
-</pre>
-
- <p>
-
- The HTML that we are generating is a table with a single row with two cells.
- The left cell has the weather icon image and the right cell has the temperature.
- We are using three CSS style rules for the table and we naturally need to create
- those too in the TravelCompanion.css file:
- </p>
-
-<pre>
-
-/* Table for one day of weather forecast information */
-.WeatherForecastDayTable {
- margin: auto;
- border-spacing: 0px;
-}
-
-/* Table cell for weather icon */
-.WeatherForecastIconCell {
- line-height: 1px;
- font-size: 1px;
- vertical-align: middle;
-}
-
-/* Table cell for temperature information */
-.WeatherForecastTemperatureCell {
- padding: 0px 0px 0px 10px;
- vertical-align: middle;
-}
-</pre>
-
- <p>
-
- Now we have a way to turn a weather forecast into HTML that we can use in a
- ContentPanel control. We'll do that in a function we call updateWeatherForecast().
- The caption for each weather forecast panel will indicate the day that the
- forecast is for. The first weather object in the array that the engine returns
- is for today and the subsequent ones are for coming days.
- </p>
-
-<pre>
-
-// Updates the weather forecast.
-function updateWeatherForecast() {
- // get local time and weather
- var localTime = engine.getLocalTime();
- var localWeather = engine.getLocalWeather();
-
- // set the weather for each day in the forecast
- for (var i = 0; i < 5; i++) {
- // figure out day name
- var day = (localTime.day + i) % 7;
- var dayName = localTime.dayNames[day];
-
- // set weather to content panel
- weatherContentPanels[i].setCaption((i == 0 ? "Today, " : "") + dayName);
- weatherContentPanels[i].setContent(getHTMLForWeather(localWeather[i]));
- }
-}
-</pre>
-
- <p>
-
- We are now ready to implement the showWeatherView() function:
- </p>
-
-<pre>
-
-// Displays the weather view.
-function showWeatherView() {
- // set heading city panel
- weatherCityPanel.setContent("<div class=\"WeatherCityPanel\">" + engine.getLocalCity().name + " 5-day Forecast("</div>");
-
- // update the weather forecast before showing the view
- updateWeatherForecast();
-
- setSubViewSoftkeys();
- uiManager.setView(weatherView);
-}
-</pre>
-
- <p>
-
- The weatherCityPanel gets a heading that matches the currently configured local city.
- We're using another CSS rule for that so we'll have to add it to our stylesheet:
- </p>
-
-<pre>
-
-/* City heading panel for weather forecast view */
-.WeatherCityPanel {
- font-size: 14px;
- font-weight: bold;
- padding: 0px 0px 10px 0px;
-}
-</pre>
-
- <p>
-
- The weather forecast view and functionality is now ready to be tested.
- </p>
-
- </div>
-
- <div class="section"><h2 class="sectiontitle">
-Currency converter</h2>
-
-
- <p>
-
- It's time to move on to the currency converter. This view is going to have two
- TextField controls. One for home currency and one for local currency. In addition
- there will be two FormButton controls to convert from the home currency to the
- local currency, and vice versa. We'll need references to the textfields so that
- we can retrieve their values when the form buttons are pressed:
- </p>
-
-<pre>
-
-// Converter view controls.
-var homeMoneyField;
-var localMoneyField;
-</pre>
-
- <p>
-
- Creating the view is quite straight forward:
- </p>
-
-<pre>
-
-// Creates the converter view.
-function createConverterView() {
- // empty caption text to display the caption bar - custom background using CSS
- converterView = new ListView(null, "");
-
- // home money
- homeMoneyField = new TextField();
- converterView.addControl(homeMoneyField);
-
- // local money
- localMoneyField = new TextField();
- converterView.addControl(localMoneyField);
-
- // home to local
- var homeToLocalButton = new FormButton(null, "Convert Home to Local");
- converterView.addControl(homeToLocalButton);
-
- // local to home
- var localToHomeButton = new FormButton(null, "Convert Local to Home");
- converterView.addControl(localToHomeButton);
-}
-</pre>
-
- <p>
-
- Notice that the textfields don't have any caption or text at this point. We will
- set that just before the view is displayed because the caption will depend on
- what the home and local cities are configured to.
- </p>
-
- <p>
-
- Also notice that we don't have any event listeners for the buttons at this point.
- That's because we haven't actually written any functions that will implement
- the currency conversion yet. But before we do that we'll implement the
- function to show the view:
- </p>
-
-<pre>
-
-// Displays the converter view.
-function showConverterView() {
- // set captions and reset fields
- homeMoneyField.setCaption("Home Currency (" + engine.getHomeCity().currency + ")");
- homeMoneyField.setText("");
- localMoneyField.setCaption("Local Currency (" + engine.getLocalCity().currency + ")");
- localMoneyField.setText("");
-
- setSubViewSoftkeys();
- uiManager.setView(converterView);
-}
-</pre>
-
- <p>
-
- You can now test the view but it won't actually convert any currency until
- we give our form buttons event listeners and write the code that will be
- called when the buttons are pressed.
- </p>
-
- <p>
-
- We'll implement that in two functions. One to convert from home to local and
- another to convert in the other direction. The functions take the current
- text value from the corresponding field and then pass it to the engine to do
- the conversion. The result is then placed in the other of the two fields,
- formatted so that the result has exactly two digits.
- </p>
-
-<pre>
-
-// Called when the user clicks on the "convert home to local" button
-// in the converter view. (rounds to two decimals)
-function convertHomeToLocalMoney() {
- var homeMoney = parseFloat(homeMoneyField.getText());
- var localMoney = engine.convertHomeToLocalMoney(homeMoney).toFixed(2);
- localMoneyField.setText(localMoney);
-}
-
-// Called when the user clicks on the "convert local to home" button
-// in the converter view. (rounds to two decimals)
-function convertLocalToHomeMoney() {
- var localMoney = parseFloat(localMoneyField.getText());
- var homeMoney = engine.convertLocalToHomeMoney(localMoney).toFixed(2);
- homeMoneyField.setText(homeMoney);
-}
-</pre>
-
- <p>
-
- Now that the functions are implemented we can add the event listeners to our
- form buttons. We'll add this code right after where the buttons are created in
- the createConverterView() function:
- </p>
-
-<pre>
-
-homeToLocalButton.addEventListener("ActionPerformed", convertHomeToLocalMoney);
-localToHomeButton.addEventListener("ActionPerformed", convertLocalToHomeMoney);
-</pre>
-
- <p>
-
- The currency converter is now working and it's time to test it. Try it with
- different currencies by changing the home and local cities in the settings view.
- </p>
-
- <div class="fignone" id="GUID-384F2430-3DE9-4006-AC8E-86C5774C3A79__GUID-D5A1648B-B81D-46B0-A15F-C3C8FF2185D7"><a name="GUID-384F2430-3DE9-4006-AC8E-86C5774C3A79__GUID-D5A1648B-B81D-46B0-A15F-C3C8FF2185D7"><!-- --></a><span class="figcap">Figure 1.
-Travel Companion converter view</span>
-
-
- <br /><img src="Travel_Companion_Converter_Screenshot_1.png" /><br />
- </div>
-
- </div>
-
- <div class="section"><h2 class="sectiontitle">
-Information view</h2>
-
-
- <p>
-
- The information view is a summary of relevant information that the user is
- will often need. Here we'll have a world clock that shows the home and local
- time, the current weather at home and in the local city, as well as the
- latest news headlines. We will use ContentPanel controls for all of these.
- One for the home time, one for the local time, one for the home weather, one
- for the local weather, and one for all the news headlines.
- </p>
-
- <p>
-
- We'll need to access all of these content panels from outside the view creation
- function so we'll need global variables to hold references to them:
- </p>
-
-<pre>
-
-// Info view controls.
-var homeCityTimePanel;
-var localCityTimePanel;
-var homeCityWeatherPanel;
-var localCityWeatherPanel;
-var newsHeadlinesPanel;
-</pre>
-
- <p>
-
- We can now proceed and actually implement the creation of the information view:
- </p>
-
-<pre>
-
-// Creates the info view.
-function createInfoView() {
- // empty caption text to display the caption bar - custom background using CSS
- infoView = new ListView(null, "");
-
- // home city time
- homeCityTimePanel = new ContentPanel();
- infoView.addControl(homeCityTimePanel);
-
- // local city time
- localCityTimePanel = new ContentPanel();
- infoView.addControl(localCityTimePanel);
-
- // separator
- infoView.addControl(new Separator());
-
- // home city weather
- homeCityWeatherPanel = new ContentPanel();
- infoView.addControl(homeCityWeatherPanel);
-
- // local city weather
- localCityWeatherPanel = new ContentPanel();
- infoView.addControl(localCityWeatherPanel);
-
- // separator
- infoView.addControl(new Separator());
-
- // news headlines
- newsHeadlinesPanel = new ContentPanel();
- infoView.addControl(newsHeadlinesPanel);
-}
-</pre>
-
- <p>
-
- We already have a function that turns a weather forecast into HTML but we
- don't have similar functions for time or for news headlines. We'll need
- that when we want to put content into the time and headline content panels
- so let's write those functions next.
- </p>
-
- <p>
-
- For time we'll need a function that takes a DateTime object and returns
- HTML that we can use in the content panel in the information view.
- </p>
-
-<pre>
-
-// Returns HTML for time.
-function getHTMLForTime(time) {
- // build HTML buffer
- var timeBuf = "";
- timeBuf += "<div class=\"Clock\">";
- timeBuf += time.hours + ":" + (time.minutes < 10 ? "0" : "") + time.minutes;
- timeBuf += "</div>";
- return timeBuf;
-}
-</pre>
-
- <p>
-
- The HTML uses a CSS rule that we'll have to define in our stylesheet:
- </p>
-
-<pre>
-
-/* Clock div */
-.Clock {
- text-align: center;
- font-size: 16px;
- font-weight: bold;
-}
-</pre>
-
- <p>
-
- Next up is the function for turning the latest news headlines into HTML.
- For each news headline we'll generate a div that contains the actual
- news headline plus a link to the website where the full news article is.
- Opening URLs should be done using the widget.openURL() method in the
- S60 Web Runtime but since we don't have that functionality in a PC browser
- we'll write a wrapper for the function just like we did for the RSS Reader:
- </p>
-
-<pre>
-
-// Opens a URL.
-function openURL(url) {
- if (window.widget) {
- // in WRT
- widget.openURL(url);
- } else {
- // outside WRT
- window.open(url, "NewWindow");
- }
-}
-</pre>
-
- <p>
-
- Now we can implement the function that turns news headlines into HTML:
- </p>
-
-<pre>
-
-// Returns HTML for news headlines.
-function getHTMLForNewsHeadlines(newsHeadlines) {
- var newsBuf = "";
- for (var i = 0; i < newsHeadlines.length; i++) {
- newsBuf += "<div class=\"NewsHeadline\">";
- newsBuf += newsHeadlines[i].headline + "<br/>";
- newsBuf += "<a href=\"JavaScript:openURL('" + newsHeadlines[i].url + "');\">";
- newsBuf += "Read more...";
- newsBuf += "</a>";
- newsBuf += "</div>";
- }
- return newsBuf;
-}
-</pre>
-
- <p>
-
- The div that encloses each news headline uses a CSS rule called NewsHeadline.
- As with all other CSS rules that we use we'll define this one too in
- the TravelCompanion.css stylesheet file. We also need to add rules for what
- links should look like in the context of a news headline. We define the link
- as bold underlined blue text in its normal state and inverse with blue background
- and white text when focused.
- </p>
-
-<pre>
-
-/* News headline */
-.NewsHeadline {
- padding: 0px 0px 10px 0px;
-}
-
-/* Anchor tags in the context of a news headline link */
-.NewsHeadline a {
- text-decoration: underline;
- font-weight: bold;
- color: rgb(0,0,255);
-}
-
-/* Focused anchor tags */
-.NewsHeadline a:focus {
- background: rgb(0,0,255);
- color: rgb(255,255,255);
-}
-</pre>
-
- <p>
-
- Now we should have everything we need to be able to update the information
- view content panels when the view is shown. It's time to implement the
- showInfoView() function:
- </p>
-
-<pre>
-
-// Displays the info view.
-function showInfoView() {
- // set current information to controls
- var homeCity = engine.getHomeCity();
- var localCity = engine.getLocalCity();
-
- // set time
- var homeTime = engine.getHomeTime();
- var localTime = engine.getLocalTime();
- homeCityTimePanel.setCaption(homeCity.name + " Time");
- homeCityTimePanel.setContent(getHTMLForTime(homeTime));
- localCityTimePanel.setCaption(localCity.name + " Time");
- localCityTimePanel.setContent(getHTMLForTime(localTime));
-
- // set weather
- var homeWeather = engine.getHomeWeather();
- var localWeather = engine.getLocalWeather();
- homeCityWeatherPanel.setCaption(homeCity.name + " Weather");
- homeCityWeatherPanel.setContent(getHTMLForWeather(homeWeather[0]));
- localCityWeatherPanel.setCaption(localCity.name + " Weather");
- localCityWeatherPanel.setContent(getHTMLForWeather(localWeather[0]));
-
- // set headline
- var newsHeadlines = engine.getNewsHeadlines();
- newsHeadlinesPanel.setCaption("News Headlines");
- newsHeadlinesPanel.setContent(getHTMLForNewsHeadlines(newsHeadlines));
-
- setSubViewSoftkeys();
- uiManager.setView(infoView);
-}
-</pre>
-
- <p>
-
- If you try the view now, everything will seem to work fine. But there
- is a big problem! We set the content in the content panels when the
- view is shown but if we stay in the view for an hour the clocks will
- still show the same time as when we showed the view. What's worse, it's
- not just the information view that has this problem. The weather forecast
- view is equally broken.
- </p>
-
- </div>
-
- <div class="section"><h2 class="sectiontitle">
-Updating views with a timer</h2>
-
-
- <p>
-
- In order to keep the views up to date we'll need to start a timer that
- periodically calls a function where we examine whether it's been long
- enough since the last update of a view that it's time to update the
- content in that view. Note that we only need to update a view using the
- timer if the view is actually visible.
- </p>
-
- <p>
-
- That sounds good at first but some things have to be updated more
- frequently than others. The clocks in our information view have to not
- only be updated once a minute but immediately when the minute changes.
- Such accuracy is not needed for the weather forecasts or news headlines.
- For them it's fine if they are updated once per hour. Except that weather
- forecasts also have to be updated when the day rolls over to the next as
- otherwise the forecast will show the wrong day. Because the home and local
- cities can be in different timezones their days will roll over at
- different times and thus we have to track these separately.
- </p>
-
- <p>
-
- It turns out that we need no less than five variables to track this.
- We need one to track the last minute that has been updated to the clocks,
- one variable is needed to track when the weather was last updated, one
- to track the day in the home city when the home city weather forecast
- was updated, one to track the same but for the local city, and one to
- track when the news headlines were updated. Let's declare those variables
- and initialize them:
- </p>
-
-<pre>
-
-// Tracks last updated minute on the clocks.
-var lastUpdatedClockMinute = -1;
-
-// Tracks last update time for weather.
-var weatherLastUpdated = -1;
-
-// Tracks the days when the weather was last updated.
-var lastUpdatedHomeWeatherDay = -1;
-var lastUpdatedLocalWeatherDay = -1;
-
-// Tracks last update time for news headlines.
-var newsHeadlinesLastUpdated = -1;
-</pre>
-
- <p>
-
- We'll use the time in millieconds to remember update times and compare
- how long it's been since an update happened. Since we'll use this quite
- a lot, let's create a small helper function for it:
- </p>
-
-<pre>
-
-// Returns the current time in milliseconds.
-function getTimeMillis() {
- return new Date().getTime();
-}
-</pre>
-
- <p>
-
- When we show a view we have to update the appropriate tracking variables
- so the widget will properly keep track of when a view was updated. That
- means that we have to add the following to just before we show the
- information view in showInfoView():
- </p>
-
-<pre>
-
-// update the tracking variables
-lastUpdatedClockMinute = homeTime.minutes;
-weatherLastUpdated = getTimeMillis();
-lastUpdatedHomeWeatherDay = homeTime.day;
-lastUpdatedLocalWeatherDay = localTime.day;
-newsHeadlinesLastUpdated = getTimeMillis();
-</pre>
-
- <p>
-
- In the same way the showWeatherView() function needs the following addition:
- </p>
-
-<pre>
-
-// update the tracking variables
-weatherLastUpdated = getTimeMillis();
-lastUpdatedLocalWeatherDay = engine.getLocalTime().day;
-</pre>
-
- <p>
-
- Now our tracking variables should be updated to the right times whenever views
- are shown but we still don't have a timer to handle the automatic updating
- of the views.
- </p>
-
- <p>
-
- We'll set this timer up so that the timer callback function is called once
- every second so that we can make sure that the clocks don't fall behind. We'll
- track the timer identifier in a variable:
- </p>
-
-<pre>
-
-// View updating timer identifier.
-var timerId;
-</pre>
-
- <p>
-
- We'll make the timer call a function called updateViews() that we will
- create shortly but first let's start the timer as the last thing in the
- init() function:
- </p>
-
-<pre>
-
-// start timer that keeps views up to date
-timerId = setInterval(updateViews, 1000);
-</pre>
-
- <p>
-
- The updateViews() function needs to check what view we are currently in and do
- the appropriate checks depending on the view. If we're in the information view
- then we have three things to check. The first thing is to check if the minute
- has changed on the clock. The second is to check if it's been over 60 minutes
- since the weather was updated or if either the home or local city has rolled
- over to the next day. And finally the third to thing to check is if it's been
- over 60 minutes since the news headlines were updated.
- </p>
-
- <p>
-
- If we are in the weather view then we check if it's been over 60 minutes since
- the weather was updated or if the local city has rolled over to the next day.
- Note that the weather forecast view only displays the local weather forecast
- so we don't have to check for if the home city has rolled over to the next day.
- </p>
-
- <p>
-
- The implementation of the function is therefore as follows:
- </p>
-
-<pre>
-
-// Timer callback function that gets called once every second to keep views up to date.
-function updateViews() {
-
- // get the current view
- var currentView = uiManager.getView();
-
- // get home and local time as well as time in milliseconds
- var homeTime = engine.getHomeTime();
- var localTime = engine.getLocalTime();
- var now = getTimeMillis();
-
- if (currentView == infoView) {
- // only update the clocks if the minute has changed
- if (homeTime.minutes != lastUpdatedClockMinute) {
- lastUpdatedClockMinute = homeTime.minute;
- homeCityTimePanel.setContent(getHTMLForTime(homeTime));
- localCityTimePanel.setContent(getHTMLForTime(localTime));
- }
-
- // update weather if it hasn't been updated in the last hour or if the day has changed
- if ((now > weatherLastUpdated + (1000 * 60 * 60)) ||
- (homeTime.day != lastUpdatedHomeWeatherDay) ||
- (localTime.day != lastUpdatedLocalWeatherDay)) {
- weatherLastUpdated = now;
- lastUpdatedHomeWeatherDay = homeTime.day;
- lastUpdatedLocalWeatherDay = localTime.day;
- var homeWeather = engine.getHomeWeather();
- var localWeather = engine.getLocalWeather();
- homeCityWeatherPanel.setContent(getHTMLForWeather(homeWeather[0]));
- localCityWeatherPanel.setContent(getHTMLForWeather(localWeather[0]));
- }
-
- // update news headlines if they haven't been updated in the last hour
- if (now > newsHeadlinesLastUpdated + (1000 * 60 * 60)) {
- newsHeadlinesLastUpdated = now;
- var newsHeadlines = engine.getNewsHeadlines();
- newsHeadlinesPanel.setContent(getHTMLForNewsHeadlines(newsHeadlines));
- }
- } else if (currentView == weatherView) {
- // update weather if it hasn't been updated in the last hour or if the day has changed
- if ((now > weatherLastUpdated + (1000 * 60 * 60)) ||
- (localTime.day != lastUpdatedLocalWeatherDay)) {
- weatherLastUpdated = now;
- lastUpdatedLocalWeatherDay = localTime.day;
- updateWeatherForecast();
- }
- }
-}
-</pre>
-
- <div class="fignone" id="GUID-384F2430-3DE9-4006-AC8E-86C5774C3A79__GUID-CBE870F8-DE6F-47D9-BE2B-F7D756DC8A40"><a name="GUID-384F2430-3DE9-4006-AC8E-86C5774C3A79__GUID-CBE870F8-DE6F-47D9-BE2B-F7D756DC8A40"><!-- --></a><span class="figcap">Figure 2.
-Travel Companion information view</span>
-
-
- <br /><img src="Travel_Companion_Info_Screenshot_1.png" /><br />
- </div>
-
- </div>
-
- <div class="section"><h2 class="sectiontitle">
-What we have learned</h2>
-
-
- <p>
-
- The Travel Companion widget is now completed! We have learned to implement
- complex widgets with multiple views using the WRTKit. We have also learned
- how to keep information in views up to date using a timer. And we implemented
- the widget without any dependencies to how the business logic engine was
- implemented. That will come in handy if you want to continue developing this
- widget by substituting the mock engine with one that actually uses real
- world data. You are now ready to tackle any challenge using the WRTKit!
- </p>
-
- </div>
-
- </div>
-
-<div>
-<div class="familylinks">
-<div class="parentlink"><strong>Parent topic:</strong> <a href="WRTKit_Travel_Companion_Tutorial-GUID-be79ba64-fa03-4968-964e-d7dcc42d7053.html">Travel Companion</a></div>
-</div>
-</div>
-
-</body>
-</html>
\ No newline at end of file