gregs

JavaScript

AJAX calls and expired sessions

by gregs on Jun.19, 2008, under ColdFusion, JavaScript

I have been updating a bunch of code recently to make use of the new features in Prototype 1.6 and one of the great additions in this release was the introduction of Automatic JavaScript response evaluation. This allowed me to improve on my session checking code without having to fuff around with the response information sent back to the client. The problem was with XHR requests: i.e. if the user initiated such a request when his session had expired, then usually the response would fail or worse just hang.

The snippet below shows my new session checking code.

JAVASCRIPT:
  1. <script type="text/javascript"><!--
  2. function myAjaxCall() {
  3.     url = "index.cfm";
  4.     pars="?fuseaction.someFuseaction&par1=1&par2=2";
  5.     new Ajax.Updater(\\'div_to_populate\\',
  6.        url, {
  7.        method: \\'post\\',
  8.        postBody: pars,
  9.        onLoading: function()
  10.        {
  11.           //code to run while making the request
  12.        },
  13.        onComplete : function(transport,json)
  14.        {
  15.           if(json && json[\\'session\\'])
  16.           {
  17.              setSessionExpired();
  18.           } else {
  19.                         //Code to run when the request has completed
  20.          }
  21.        },
  22.        onFailure: function ()
  23.        {
  24.          alert(\\'something went wrong\\');
  25.        },
  26.        evalScripts:true
  27.     });
  28.  }
  29.  
  30. function setSessionExpired()
  31. {
  32.     alert(\\'Your session has timed out\\');
  33.     window.location=\\'http://<cfoutput>#cgi.HTTP_HOST#</cfoutput>/?fuseaction=home.home\\';
  34. }
  35. // --></script>

The trick is to intercept the call when you do your session checking at the back end. Let's say you have a fuseaction called login.login (see below and yes this is fusebox 3 :S) where you display the login form when a user is not logged in, this is where I inserted the check for an XHR request, by looking at the http headers sent along with the request. The key here is a new header attribute passed in with Prototype "X-Requested-With". If this attribute exists then I know it's an XHR request and I can create a custom JSON header with an error struct that holds a key called session with a value of timeout. All I then need to do is encode the struct as JSON and pass that encoded struct back to the browser.

CODE:
  1. <cfcase value="login">
  2.         <!--- gvs 1Feb08 - handles XHR requests that session timeout --->
  3.         <cfset attributes.request = GetHttpRequestData()/>
  4.         <cfif StructKeyExists(attributes.request.headers,"X-Requested-With")>
  5.             <cfsetting showdebugoutput="false">
  6.             <cfparam name="attributes.jsonObj" default="#CreateObject('component','com.jehiah.json')#"/>
  7.             <cfparam name="error" default="#StructNew()#"/>
  8.             <cfset error['session']='timeout'/>
  9.             <cfif StructKeyExists(attributes,"jsonObj")>
  10.                 <cfheader name="X-JSON" value="#trim(attributes.jsonObj.encode(error))#" /><cfabort>
  11.             </cfif>
  12.         </cfif>
  13.  
  14.         <cfif StructKeyExists(session,'login')>
  15.             <cfset attributes.login = session.login/>
  16.         <cfelse>
  17.             <cfparam name="attributes.login" default=""/>
  18.         </cfif>
  19.  
  20.         <cfscript>
  21.             xfa.submitform='index.cfm?fuseaction=login.processlogin';
  22.         </cfscript>
  23.         <cfinclude template="#affiliate('dsp_login.cfm')#"/>
  24. </cfcase>

Now let's jump back to the JavaScript code and take a look at the onComplete function again:

JAVASCRIPT:
  1. onComplete : function(transport,json)
  2. {
  3.         if(json &amp;&amp; json['session'])
  4.         {
  5.                 setSessionExpired();
  6.         } else {
  7.                 //Code to run when the request has completed
  8.         }
  9. }

If there's a JSON object and it has a key of session then I call my setSessionExpired function which redirects the users. Now the json session key only exists in these situations since the call normally just passes back the result of the call.

Leave a Comment more...

Reflow

by gregs on May.30, 2008, under CSS, JavaScript, browser, rendering

Or more appropriately what is it? Fascinating...

Leave a Comment more...

Embedded images an IE work around

by gregs on May.18, 2008, under JavaScript

A while back I posted about using the data:image/jpeg;base64 to directly embed the image in to the source attribute of an image tag, however this did not work with IE. Today I stumbled across this JavasScript solution. Certainly an option, though in my case it was overkill, however I thought others might find it useful.

Leave a Comment more...

IE , the dom and long numbers

by gregs on Apr.27, 2007, under JavaScript

I just spent the best part of 45 minutes trying to figure out a weird issue with a value I was pulling out of a select box (using $F(element)). The value in question was a long number: 1000002229651626, which IE converted at the time of writing the value to the page (this was an AJAX call) to: 1.00000222965163e+15.

IE decided to convert my number when I was using the new Option() method to populate the drop down, making the debug process even harder. I personally can't wait until we get a firebug like extension for IE, right now I'd just settle for an option to view the rendered source.

Rant over, the solution is to convert the number to a string:

JavaScript:
  1. selectBox[x] = new Option('Some text',new String(1000002229651626),false);

On the plus side I came across a neat way to debug values in a form field using the address the browser address bar:

CODE:
  1. javascript:alert(document.all.myfield.value); void(0)

And to see what IE had actually written to the page:

CODE:
  1. javascript:alert(document.all.myfield.innerHTML ); void(0)

2 Comments more...

encodeURIComponent()

by gregs on Jun.30, 2006, under JavaScript

I just stumbled across this post from the Red Balloon guys, which reminded me that I wanted to blog about this great little resource about the subtle differences of URL encoding and JavaScript.

The bottom line of this article is that 9 times out of 10 you'll want to be using encodeURIComponent() to encode vars that are to be passed as part of a URL instead of the escape() method.

Leave a Comment more...

FireBug

by gregs on Feb.23, 2006, under JavaScript

Now I can't remember where I stumbled across this little gem of a plug in for FireFox: FireBug, but yesterday it completely surprised me.

I originally had installed it because it was meant to be far better at debugging JS, than the new version of the JavaScript Console that was shipped with FireFox 1.5 and that it was. So I have been using it for a while now, but yesterday I stumbled across a feature that makes it utterly invaluable now. I do a lot of Ajax based development these days and sometimes trying to figure out what is going on under the hood is a little problematic. However if you open it up and look at the options, you'll see an option to show XmlHttpRequests disabled. Enable it and make a remoting call.

Along with the usual JS/CSS debug you should now see something like this:

Firebug screenshot 1

If you click on the Response Tab you can see what has been returned to the browser.

Firebug screenshot 2

And if you click on the JS tab you can inspect the whole response object.

Firebug screenshot 3

Awesome!

And since it's been so long between posts here a couple of other useful Ajax/prototype links:

Leave a Comment more...

Generic Form validation part ii

by gregs on Oct.31, 2005, under JavaScript

A few weeks back someone on the CFDJ list enquired about JavaScript form validation and pointed them in the direction of my script, however I only just realised that the script itself was no longer working. Oops... so apologies, but I have fixed up the problems and done made it sure it works for the following browsers.

  • Win XP / Netscape 4.7x
  • Win XP / IE 6
  • Win XP / Mozilla 1.4
  • Win 2K / IE 6
  • Win 2K / Mozilla 1.5
  • Win XP / Firefox 0.8

If you have access to ones not on the list, I'd be grateful for any feedback. The revised version with sample file can be found here.

Leave a Comment more...

stopping a page refresh

by gregs on Oct.21, 2005, under JavaScript, browser

I found myself having to trap a user attempting to refresh a page for one of our web apps. After a little bit of digging I stumbled across this solution:

CODE:
  1. <script type="text/javascript">
  2. <!--
  3. window.onbeforeunload = unloadMess;
  4. function unloadMess()
  5. {
  6.     mess = "You are about to refresh the screen and will loose all of your changes.nAre you sure you want to do so?"   return mess;
  7. }
  8. //-->
  9. </script>

To use it simply embed or include it into your template

Eventhough the article says this is a IE specific event/feature it also works in FireFox. You should be aware that whenever the user leaves the page, they will be prompted about their impeding data loss, which can get a little tedious while developing.

Again this became a handy feature for our AJAX apps as most of the processing is done in the background without the page reload, a user could accidentally hit the back button and loose where they were at.

Leave a Comment more...

Conditional compilation

by gregs on Aug.23, 2005, under JavaScript, browser

What with the buzz going on around xmlHttpRequest, I decided to have a little play with the technology (yes I know very me too of me). One tutorial/example site I stumbled across "Guide to Using XMLHttpRequest (with Baby Steps)" used some interesting JavaScript: Conditional Compilation. Here is an example:

JavaScript:
  1. /*@cc_on @*/
  2. /*@if (@_jscript_version&gt;= 4)
  3. alert("JScript version 4 or better");
  4. @else @*/
  5. alert("You need a more recent script engine.");
  6. /*@end @*/

From the looks of it, it's an IE only thing, but I wonder what the advantages are of using this code over a regular browser check? Is this a more reliable way than using window.ActiveXObject and, if you are specifically playing around with xmlHttpRequest, based on that condition making the correct create object call?

Leave a Comment more...

Checking for a valid e-mail address

by gregs on Oct.18, 2000, under JavaScript

I made my first venture in regular expressions, when I had to create a JavaScript that checked the validity of an e-mail address. By checking it's validity, I mean that I wanted to make sure that users submitted an address that followed your_name@domain.com and not simply entered a whole bunch of garbage. The best way to do this is to match a pattern or as it is known use regular expressions. Before we set off here is the script that we are going to work through:

<script language="JavaScript" type="text/javascript">
<!--
function validate() {
   var pat_email = /^[-._&0-9a-zA-Z]+[@][-._&0-9a-zA-Z]+[.][._0-9a-zA-Z]+[a-zA-Z]$/;
   with (document.form1) {
      //validate email
      if ( pat_email.exec(txt_email.value) == null ) {
         alert("You have not entered a valid email address.");
         txt_email.focus();
         return false;
      }
   }
}
//-->
</script>

OK let's see what is going on here. First we define the pattern that we are trying to match. There we specify the characters that are accepted and the characters that need to appear in it to determine it's validity. JavaScript knows you are defining a regular expression when you use the statement var <pattern_name> = /<pattern_goes_here>$/;. If you take a look at the pattern you will notice [] (I will get to the caret in a second). These are used to group patterns together and in some cases create sub-patterns. Taking a step back you can see that we are trying to match pattern that follows these guidelines []@[].[], which is how most e-mail addresses are composed. In between the square brackets I have specified the characters that are permitted for each sub-pattern. So looking at the first set of square brackets, only values between 0-9, a-z, A-Z, "-", "_", "&" and "." are accepted. How does the script know that these are to be accepted? This is where we get back to the caret (^). This symbol inside the forward slashes indicates that it should accept only those characters specified. Move the caret outside of the slashes and you get achieve the opposite, accept any characters other than the one listed above. You may also wonder what the +[a-zA-Z] is about. We included this in order to accept domains names such as .co.uk or .com.au, hence the reason for only including letters and not numbers.

As an aside should you wish to learn more about regular expressions or pattern matching I can recommend two books. The first is what I used and it gave me an introduction to regular expressions and is the JavaScript developers bible: JavaScript from O'Reilly & Associates, Inc. The other is Perl Programming also from O'Reilly & Associates, Inc. You may be wondering why recommend a Perl book for JavaScript regular expressions. As it happens Perl forms the basis for the way in which JavaScript handles regular expressions.

Right on with the script. Once we have defined our pattern we have to match it up with something. This happens in the following line, where we inform the script to match it to form1 in our current page. Next we set the condition, where if pat_email is matched up against text_email (this is the form field we are validating) and if this returns null, then we have no match and hence the user has entered an e-mail address that does not satisfy our criteria. If this is the case an alert should be made, the focus set back to aforementioned form field and the form submission aborted.

And there you go that's the script. You invoke the script by including onsubmit="return validate();" in your <FORM> tag. As ever I hope this proved to be useful and informative. Comments and feedback always welcome!!!

Leave a Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!