Google Answers Logo
View Question
 
Q: Automatically refreshed textual contents of HTML pages ( Answered 1 out of 5 stars,   5 Comments )
Question  
Subject: Automatically refreshed textual contents of HTML pages
Category: Computers > Internet
Asked by: petar-ga
List Price: $15.00
Posted: 16 May 2003 19:27 PDT
Expires: 15 Jun 2003 19:27 PDT
Question ID: 204911
I need to figure out how to write a web page, using HTML and
JavaScript, such
that certain parts of the HTML of the page will have to be refreshed
in intervals of time from the server.

So for example, I want to write a simple page which shows the text:

Current time in America: 4:34 pm
Current time in Europe: 11:34 pm

---

I want the text that represents the time (not the whole page) to be
automatically refreshed every 1 second. Notice that the two timers
need
to be treated as independent objects.

Furthermore, I don't want to use Java or any other such heavy-wight
tool.Ideally, this should be possible based on common
JavaScript/HTML/style sheets.

Many thanks,
Petar
Answer  
Subject: Re: Automatically refreshed textual contents of HTML pages
Answered By: robertskelton-ga on 16 May 2003 23:34 PDT
Rated:1 out of 5 stars
 
Hi there,

I have placed the working result on this page:
http://skelton.id.au/time_example.html

Here is the code:


Head Section Code
-----------------

<SCRIPT LANGUAGE="JavaScript">


<!-- This script is a merge of two -->
<!-- one by Craig Lumley -->
<!-- at http://www.ws4all.co.uk -->
<!-- and The 24 Hour World -->
<!-- at http://tech.irt.org/articles/js076/ -->

<!-- Begin
function MakeArrayday(size) {
this.length = size;
for(var i = 1; i <= size; i++) {
this[i] = "";
}
return this;
}
function MakeArraymonth(size) {
this.length = size;
for(var i = 1; i <= size; i++) {
this[i] = "";
}
return this;
}
function funClock() {
if (!document.layers && !document.all)
return;
var GMT_DIFFERENCE = -4
var runTime = new Date();
timezoneoffset = runTime.getTimezoneOffset();
if ((navigator.appVersion.indexOf('MSIE 3') != -1)) timezoneoffset =
timezoneoffset * (-1);
runTime.setTime(runTime.getTime() + timezoneoffset*60*1000);
runTime.setTime(runTime.getTime() + GMT_DIFFERENCE*60*60*1000);
var hours = runTime.getHours();
var minutes = runTime.getMinutes();
var seconds = runTime.getSeconds();
var dn = "AM";
if (hours >= 12) {
dn = "PM";
hours = hours - 12;
}
if (hours == 0) {
hours = 12;
}
if (minutes <= 9) {
minutes = "0" + minutes;
}
if (seconds <= 9) {
seconds = "0" + seconds;
}
movingtime = "<b>"+ hours + ":" + minutes + ":" + seconds + " " + dn +
"</b>";
if (document.layers) {
document.layers.clock.document.write(movingtime);
document.layers.clock.document.close();
}
else if (document.all) {
clock.innerHTML = movingtime;
}
setTimeout("funClock()", 1000)
}
window.onload = funClock;
//  End -->
</script>


<SCRIPT LANGUAGE="JavaScript">
<!-- Original:  Craig Lumley -->
<!-- Web Site:  http://www.ws4all.co.uk -->

<!-- This script and many more are available free online at -->
<!-- The JavaScript Source!! http://javascript.internet.com -->

<!-- Begin
function MakeArraydays(sizes) {
this.lengths = sizes;
for(var x = 1; x <= sizes; x++) {
this[x] = "";
}
return this;
}
function MakeArraymonths(sizes) {
this.lengths = sizes;
for(var x = 1; x <= sizes; x++) {
this[x] = "";
}
return this;
}
function funClocks() {
if (!document.layers && !document.all)
return;
var GMT_DIFFERENCES = 1
var runTimes = new Date();
timezoneoffset = runTimes.getTimezoneOffset();
if ((navigator.appVersion.indexOf('MSIE 3') != -1)) timezoneoffset =
timezoneoffset * (-1);
runTimes.setTime(runTimes.getTime() + timezoneoffset*60*1000);
runTimes.setTime(runTimes.getTime() + GMT_DIFFERENCES*60*60*1000);
var hourss = runTimes.getHours();
var minutess = runTimes.getMinutes();
var secondss = runTimes.getSeconds();
var dns = "AM";
if (hourss >= 12) {
dns = "PM";
hourss = hourss - 12;
}
if (hourss == 0) {
hourss = 12;
}
if (minutess <= 9) {
minutess = "0" + minutess;
}
if (secondss <= 9) {
secondss = "0" + secondss;
}
movingtimes = "<b>"+ hourss + ":" + minutess + ":" + secondss + " " +
dns + "</b>";
if (document.layers) {
document.layers.clocks.document.write(movingtimes);
document.layers.clocks.document.close();
}
else if (document.all) {
clocks.innerHTML = movingtimes;
}
setTimeout("funClocks()", 1000)
}
window.onload = funClocks;
//  End -->
</script>





Body section code
-----------------

<body onload="funClock();funClocks()">

Current time in America <span id=clock
style="position:relative;"></span><br><br>

Current time in Europe <span id=clocks
style="position:relative;"></span>

</body>




Notes
-----
To change the times, just change these two variables in the code: 

GMT_DIFFERENCE (currently set to -4 for New York) 
GMT_DIFFERENCES (currently set to 1 for London)

To find the GMT +/- amount for different locations, go to this site:
http://greenwichmeantime.com/local/

Make sure that the the body tag of your page is the same as I have
used:
<body onload="funClock();funClocks()">


Search Strategy
---------------
To make it I found two pieces of code and merged them to get the
desired result. One is for calculating timezones and one is a dynamic
clock.

The 24 Hour World
http://tech.irt.org/articles/js076/

Dynamic Clock 
http://javascript.internet.com/clocks/dynamic-clock.html


Best wishes,
robertskelton-ga

Request for Answer Clarification by petar-ga on 17 May 2003 07:45 PDT
This answer solves my example scenario, but as I have clarified in my
question,
I am actually looking for a *GENERAL* solution that *fetches* the
updated text
from a server, rather than computing them locally. I don't think this
code will work in that case.

Petar

Clarification of Answer by robertskelton-ga on 17 May 2003 15:47 PDT
Apologies for misinterpreting your query.
petar-ga rated this answer:1 out of 5 stars

Comments  
Subject: Re: Automatically refreshed textual contents of HTML pages
From: eadfrith-ga on 17 May 2003 12:49 PDT
 
Hi Petar,

The trick to achieving the dynamic updating of web page content from a
server is to use 2 frames; an invisible frame that just holds
javascript and a display frame that shows the dynamic content. The
content of the javascript frame gets loaded from the server
periodically and updates the content of object(s) in the display
frame. You can use 2 different techniques to update the javascript
frame; pull or push. In the pull model the javascript frame is told to
refresh itself every <n> seconds by going back to the server for new
content. The drawback of this is that you'll see the browser making
new requests each time. In the push model the server keeps a connetion
open to the client browser and just pusher new content every <n>
seconds. This looks much better from the client point of view, since
there are no new browser requests, but the drawback is that you have
to keep the connection open, which may be a problem if you need to
handle thousands of client requests.

Let's consider the pull model first. Your main page would look like
this.

clockPull.html:

<script LANGUAGE="JavaScript">
  function updateAmericanTime(time)
  {
    window.displayFrame.americanTime.innerHTML = time;
  }

  function updateEuropeanTime(time)
  {
    window.displayFrame.europeanTime.innerHTML = time;
  }
</script>

</head>
<frameset BORDER=0 Rows="0,*">
     <frame SRC="googleTimer?mode=pull" BORDER=0  SCROLLING=no>
     <frame SRC="display.html" NAME="displayFrame"  BORDER=0 
SCROLLING=no>
</frameset>

Notice that we use 2 frames. The first frame is invisible (since it's
allocated 0% of the frameset) and its content comes from a dynamic
server source. The second frame, the displayFrame, shows the content
(see below). We also have a couple of javascript functions that can be
called to update objects in the displayFrame.

display.html:

<body>
Current time in America:
<span id=americanTime style="position:relative;"/></span><br><br>
Current time in Europe:
<span id=europeanTime style="position:relative;"></span>
</body>

Now we need to look at how the dynamic content of the javascript frame
is served up. I've used a Java servlet, but you should be able to use
any server side technology you're comfortable with. (I know you said
you didn't want to use Java, but this is running on the server, not in
the browser). Here's the servlet, which gets called by the browser in
order to fetch the content of the 1st frame (I mapped the servlet to
googleTimer).

import java.io.*;
import java.util.*;
import java.text.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class TimerServlet extends HttpServlet
{

  private DateFormat m_pacificDateFormatter;
  private DateFormat m_britishDateFormatter;

  public TimerServlet()
  {
    m_pacificDateFormatter = new SimpleDateFormat("h:mm:ss a");
    m_pacificDateFormatter.setTimeZone(TimeZone.getTimeZone("PST"));

    m_britishDateFormatter = new SimpleDateFormat("h:mm:ss a");
    m_britishDateFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
  }

  public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException
  {
    ServletOutputStream out = resp.getOutputStream();

    String mode = req.getParameter("mode");
    if("pull".equals(mode))
    {
      out.print("<meta HTTP-EQUIV=\"refresh\" CONTENT=\"1\">");
      out.print("<script language=JavaScript >");
      Date now = new Date();
      out.print("parent.updateAmericanTime('" +
m_pacificDateFormatter.format(now) + "');");
      out.print("parent.updateEuropeanTime('" +
m_britishDateFormatter.format(now) + "');");
      out.print("</script>");
    }
    else if("push".equals(mode))
    {
      while(true)
      {
        out.print("<script language=JavaScript >");
        Date now = new Date();
        out.print("parent.updateAmericanTime('" +
m_pacificDateFormatter.format(now) + "');");
        out.print("parent.updateEuropeanTime('" +
m_britishDateFormatter.format(now) + "');");
        out.print("</script>");
        out.flush();
        try
        {
          Thread.sleep(1000);
        }
        catch (InterruptedException e) {}
      }
    }
  }
}

Notice that if the request mode is "pull" then the following content
is sent to the javascript frame:

meta HTTP-EQUIV=\"refresh\" CONTENT=\"1\">
<script language=JavaScript >
parent.updateAmericanTime('12:16:36 PM');
parent.updateEuropeanTime('7:16:36 PM');
</script>

This gets run by the browser and the result is that the values in the
displayFrame get updated. The browser is also told to refresh the
frame in 1 second.

I don't have access to a public servlet container on which to deploy
this servlet so you'll need to deploy it yourself, or adapt it to your
own server side technology, but if you run it you'll see that the time
does get updated but that you can see the browser making new requests
every second (eg. the progress bar on IE is activated).

So, let's look at the push model. The main page is almost identical
except that we specify a push mode in our request to the server:

clockPush.html

<script LANGUAGE="JavaScript">

  function updateAmericanTime(time)
  {
    window.displayFrame.americanTime.innerHTML = time;
  }

  function updateEuropeanTime(time)
  {
    window.displayFrame.europeanTime.innerHTML = time;
  }

</script>

</head>
<frameset BORDER=0 Rows="0,*">
     <frame SRC="googleTimer?mode=push" BORDER=0  SCROLLING=no>
     <frame SRC="display.html" NAME="displayFrame"  BORDER=0 
SCROLLING=no>
</frameset>

the display.html page is the same.

If you look at the servlet you'll notice that if the request mode is
"push" then the servlet enters a loop in which it writes out the
following javascript:

<script language=JavaScript >
parent.updateAmericanTime('12:16:36 PM');
parent.updateEuropeanTime('7:16:36 PM');
</script>

(notice there's no refresh command), then it sleeps for 1 second
before going back around to resend a new javascript command.

If you ran the push version you'd see the time being smoothly updated
with no new browser requests being made. However, as I said above, the
connection has to be kept open by the server in order for this
approach to work.

Hope this helps. Let me know if you have any questions.

Cheers,

Eadfrith
Subject: Re: Automatically refreshed textual contents of HTML pages
From: petar-ga on 17 May 2003 16:40 PDT
 
Well, this is sort of better. Although, I should have mentioned that
frames
are not a desired solution by most developers for various reasons. I
am wondering
is it possible to use a push technique and something different than
frames, maybe layers?

Thank you,
Petar
Subject: Re: Automatically refreshed textual contents of HTML pages
From: eadfrith-ga on 17 May 2003 18:04 PDT
 
Hi Petar,

As far as I'm aware there's no alternative to using an invisible
frame. What are your reservations about frames? They can certainly be
abused, but in this case the browser window is occupied by a single
frame, the content frame, so there shouldn't be an issue.

The issue is that without the hidden frame there's no way for the
server to safely push the javascript update script. If your clients
use IE then you can serve up all of the content from your servlet (or
whatever server-side technology your using), keep the connection open
and just keep sending the javascript updates. IE executes these
scripts and the content gets updated. The trouble with this solution
is that the page never finishes loading (as it does if you use frames)
so the user will continue to see the hourglass and progress bar
active. However, the bigger problem is that this approach doesn't work
at all in Netscape - once the page has initially loaded it ignores any
javascript that's subsequently sent.

So frames are the only way I know of doing what you want. 

Cheers,

Eadfrith

PS. I'm not a researcher and so there's no danger of you having to pay
for my advice :-).
Subject: Re: Automatically refreshed textual contents of HTML pages
From: petar-ga on 18 May 2003 14:00 PDT
 
But doesnt this continuous feeding of information (when we use the
push technique) eat up more and more memory over time. Can I leave an
open page like this forever without running out of memory?

Thanks,
Petar
Subject: Re: Automatically refreshed textual contents of HTML pages
From: eadfrith-ga on 18 May 2003 17:26 PDT
 
Petar,

You're correct, there could be a problem with memory on the client.
You're continually sending new content to the browser and this has to
be stored somewhere. I've never used the push technique in production
so I haven't stress tested it. One idea would be periodically send a
meta refresh command instead of a javascript update script - this
would cause the browser to reload the frame, thereby freeing the
previous content. I haven't tested whether all browsers recognize
refresh commands in the middle of the content though.

I think the biggest resource problem with the push solution is that
you're tying up a thread per client on the server. A java servlet
container typically works by using a thread pool to service client
requests. Each time a request comes in a thread is recovered from the
pool and used to handle the request. When the servlet finishes the
thread is returned to the pool. However, with the push technique the
servlet never finishes, at least not while it's updating the client,
and so the thread is tied up. If you need to update thousands of
clients at the same time then this is going to be a problem. I suspect
most server side technologies would have similar issues.

The difficulty with what you're trying to achieve here is that HTTP is
intended to be a stateless protocol with short-lived connections: the
client makes a request, gets its information and you're done.
Dynamically updating a client view really requires a statefull,
long-lived connection protocol, but web standard web browsers don't
support such a protocol without plug-in technology such as applets.
You could achieve what you want here with a very simple applet that
was just big enough to display the time - the user wouldn't even know
there was an applet on the page.

Anyway, good luck with your project.

Cheers,

Eadfrith

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy