|
|
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 |
|
Subject:
Re: Automatically refreshed textual contents of HTML pages
Answered By: robertskelton-ga on 16 May 2003 23:34 PDT Rated: |
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 | |
| |
|
petar-ga rated this answer: |
|
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 |
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 Home - Answers FAQ - Terms of Service - Privacy Policy |