Skip to main content
Known Participant
July 9, 2010
Question

CF>JS inside setTimeout() method

  • July 9, 2010
  • 3 replies
  • 2221 views

I'm trying to implement a javascript function that compares the session start time with the current time and notifies the user when their session has timed out. My Application.cfc is:

<cfcomponent output="no">

    <cfset this.name="MyApp">
    <cfset this.sessionManagement="yes">
    <cfset this.sessionTimeout=CreateTimeSpan(0,0,0,5)>
   
    <cffunction name="onApplicationStart" returntype="boolean" output="no">
        <cfset Application.appStarted=Now()>
        <cfreturn true>
    </cffunction>
       
    <cffunction name="onSessionStart" output="yes">
        <cfset Session.sessionStarted=Now()>
    </cffunction>
     
</cfcomponent>

and my index.cfm page is:

<!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" />
    <title>CF to JS</title>
</head>

<body onload="calltimeout();">
<h2> Testing CF to JS</h2>
<div>
  <p>Application started: <span id="test"></span></p>
  <p>Session started: <span id="test2"></span></p>
  <p>Difference between session start and now: <span id="test3"></span> seconds</p>
    <p id="test4"></p>
</div>

<script language="javascript" type="text/javascript">
           <cfoutput>
            var #toScript(Application.appStarted, "jsvar")#;
            var #toScript(Session.sessionStarted, "jsvar2")#;
        </cfoutput>
        document.getElementById("test").innerHTML = jsvar;
        document.getElementById("test2").innerHTML = jsvar2;
       
        var timer= null;
        function calltimeout(){
            <cfoutput>
                var #toScript(datediff("s", Session.sessionStarted, Now()), "jsvar3")#;
            </cfoutput>
           
            document.getElementById("test3").innerHTML = jsvar3;
            if (jsvar3 > 5) {
                document.getElementById("test4").innerHTML = "You have timed out.";
            }
            timer = setTimeout("calltimeout()", 1000);
        }
   </script>
</body>
</html>

Here's my problem: the "jsvar3" variable doesn't get updated unless the page is refreshed manually. I know the JS calltimeout() function is working, because I can implement a counter that increments each time, and which displays the updated value correctly each time the function is called. If I refresh the page manually, the jsvar3 variable shows that it's updated and eventually the conditional block runs and outputs "You have timed out".

Is there a different way I should be refreshing the "jsvar3" variable?

This topic has been closed for replies.

3 replies

Inspiring
July 13, 2010

I think you're pretty close to success in what you're trying to do.  You have the "jsvar2" set to the session start time.  Replace the code that is trying to set "jsvar3" with the value of the CF function NOW() with code to set it to the current date/time from javascript (since that is where the code is executing); You should be able to find info on doing that with a quick Google search.

A question about your overall logic - do you really want to base the javascript timeout of the CF session on a delta from when the session started?  I think that you really want to set "jsvar2" to the CF NOW() value, so that your javascript code starts its timeout counter based on when the user last touched the CF page (which is when CF is starting its session timeout counter).  The start time of the session really doesn't enter into the picture.

Everything everyone else said is 100% true about server side vs client side, and you should follow the links they provided to understand all of that, but there is no reason that the two cannot work together in instances such as this.

-reed

Inspiring
July 11, 2010

Regarding:

I'm trying to implement a javascript function that compares the session  start time with the current time and notifies the user when their  session has timed out

That's a very unusual approach.  Timeouts are normally associated with x minutes of inactivity, not x minutes of total session time.  The normal way is to incorporate the js in the onRequestStart or onRequestEnd functions of the application.cfc.

earacheflAuthor
Known Participant
July 11, 2010

Thanks, Dan, that makes perfect sense. Like I said earlier, I feel like I'm trying to re-invent the wheel... besides the Forta CFWack book, can you guys recommend any other good reading material?

ilssac
Inspiring
July 9, 2010

earachefl wrote:

Here's my problem: the "jsvar3" variable doesn't get updated unless the page is refreshed manually....

Is there a different way I should be refreshing the "jsvar3" variable?

That is the way web applications work.  ColdFusion runs on the server, JavaScript runs on the client and never can the two meet.  These are two different machines with separate memory and variables that can be thousands of miles apart.

There is absolutely no way for JavaScript and ColdFusion to share memory without a new request (i.e. refresh).

The common way to do what you want is just to set the JavaScript timeout variable to aproximately the session time out when ColdFusion builds the response to the request and then the JavaScript handle it on the client after it receives the response.

If you would like to, you could create an Java function that will make requests behind the scenes to the server that would get data.  But for a session timeout requirement, that would be worthless, because every time such a request is received and processed by the server, the session timeout would be reset to zero.

earacheflAuthor
Known Participant
July 9, 2010

Thanks, Ian. So let me get this straight; even though the CF session variable is only called from inside a JS script, the actual retrieval of the variable is being done via the request, not the script, and the script can't request the variable again; only a page refresh can retrieve it?

And for session persistence over multiple pages, I'm guessing I need to use a document.cookie?

Sigh... I feel like I'm re-inventing the wheel here. Google has not been my friend in finding a simple, secure solution to what must be the most common problem in application design.

ilssac
Inspiring
July 9, 2010

earachefl wrote:


I feel like I'm re-inventing the wheel here. Google has not been my friend in finding a simple, secure solution to what must be the most common problem in application design.

Not re-inventing the wheel, because this wheel does not exist and never can or will.  This is not a ColdFusion thing it is a HTTP thing.  By design, HTTP requests are always complete separate and distinct entities and share nothing with any request that comes before and after.

With web application design you need to keep, clearly in mind what the server does and what the client does.  The basic flow of a HTTP request for a ColdFusion resource goes like this.

  1. A client makes a request for a URI (A user clicks on a link, bookmark, types a url in to the browser etc)
  2. A web server receives the request.  It examins the URI and determines that it has been told be pass this request to the ColdFusion Application server.
  3. ColdFusion receives the request, it process the requested CFML file building a response that can consist of HTML, JavaScript, CSS, etc.
  4. ColdFusion returns the response to web server.  It is now done and complete forgets everything about this request and moves onto the next one in the cue, which is probably from a complete different client that could be on the other side of the world.
  5. The web server returns the response to the client, and then it forgets about it, moveing on to its next task.
  6. The client receives the response.  Depending on what is in the response, the client may render HTML, apply CSS rules and|or execute JavaScript code or whatever else it may know how to handle what was included in the response.

As you can see CFML and JS execute on completely separate systems and completely separate times and never do the share memory or variables.  THE ONLY way to get information from the client to the server is to make a request, and the only way to get data from the server to the client is in a response to a request.

earachefl wrote:

Thanks, Ian. So let me get this straight; even though the CF session variable is only called from inside a JS script, the actual retrieval of the variable is being done via the request, not the script, and the script can't request the variable again; only a page refresh can retrieve it?


A "page refresh" is not the only way to generate a new request through AJAX is a popular technology to make requests and process responses that do not require a 'refresh' by using the JavaScript XMLHttpRequest() function.  Inline frames are another way to make a separate request that does not affect the entire page as well.

Using technology beyond basic HTTP can change this dynamic as well.  Such as the FLASH|FLEX|AIR client that uses AMF to maintain a single request for an extended time where new data can be pulled from the client to the server and the server can push new data to the client.

earachefl wrote:

And for session persistence over multiple pages, I'm guessing I need to use a document.cookie?

Well yes, but ColdFusion does this for you automatically once you define an "Application" and probably "Session" management.  When you do this, ColdFusion will create cookies (CFID and CFTOKEN or JSESSIONID) that allows it to know what requests belong to what data it has stored in server memory.

The important note here for what you are trying to do, is that every time CF process a new request for an existing session, it is going to start the session timeout over.  So if you where to create some mechanism to send new requests to get the session timeout, the session will never timeout.  Each request to get the data will reset the timeout to zero.

As I said before the common solution (existing wheel) is just to set the JavaScript timeout to about the same value as the session timeout (i.e 20 minutes by default) in the response.  Then when the JavaScript function timeout, the server session should be timing out about the same time.