Weird Thoughts From Eric's Head

Categories : All | AJAX | BUSINESS | PERSONAL | PROGRAMMING | BOOK REVIEW

AJAX : A Basic Example and a Bookmarklet
Okay now what you all been waiting for: my example on AJAX. Waring: I am not going to go into extreme detail; you can get Dave Crane’s and my book (AJAX in Action) for that when it comes out later this year. First lets see an example of AJAX working right here under our noses.

Now everyone in a JavaScript world says. How can I protect my pages with a username and password without a server side language? Well it can not be done, but you can make it hard to find your content. In this example below you can see a textbox, a password box and the wonderful submit button. Try entering in a username and password.

User Name:
Password:  

Look at the source and you will see there is no username and password. Instead we are using the username and password field to see if the file exists. With AJAX, we look to see if this file is there. If it is, we go there, if not we get the error. Well I am sure you want to see the location so the username is Eric and the password is pass. Now you are able to go there and see my message.

So what is the code to do this? Well now we all know the fun we have coding JavaScript, nothing works the same for different browsers. With IE we need to use ActiveX to do it. Mozilla has there own method to do it.

First we have two things. We have the code that does the request, and then we have a function that handles the returned data. If you are using one of those libraries, you may not have seen this, so open up your eyes wide. Now I am just going to explain the code with comments. (Yeah that is cheating compared to my normal discussion style here on my blog, but I am trying to write a book you know!)

<html>
  <head>
    <script type="text/javascript">

      //We need a wonderful global variables to hold our request object!
      //So we can pass it around.
      var reqXML;
      //We need to have a global variable to hold the url.
      //It keeps us from having to repeat code!
      var url;

      //Create our function to start the request
      function VerifyLogin(){

        //inform there is an action!
        document.getElementById("spanLog").innerHTML = "<span style='color:green'> Checking Information</span>";

        //Grab our form field values
        var strName = document.Form1.username.value;
        var strPass = document.Form1.password.value;
        
        //Make the URL for the request
        url = "http://radio.javaranch.com/pascarello/files/" + strName + strPass + ".html";

        //determine if the browser is Moz, FF, NN, Op
        if (window.XMLHttpRequest){ 
          reqXML = new XMLHttpRequest();            //set the request
          reqXML.onreadystatechange = LoginUser;    //function to call on each set
          reqXML.open("GET", url, true);            //set the page to request
          reqXML.send(null);                        //initialize the request 
        }
        //ActiveX - can we say IE?
        else if(window.ActiveXObject){ 
          //Create our RequestObject
          reqXML = new ActiveXObject("Microsoft.XMLHTTP"); 
          if(reqXML){ 
            reqXML.onreadystatechange = LoginUser  //function to call on each step
            reqXML.open("GET", url, true);         //set the page to request
            reqXML.send(null);                     //initialize the request
          }
        }
        else{  //I do not support this so I need to do something!
           window.location.href = url;
        }       
      }
          
      function LoginUser(){

        //Look to see if the request is in the 4th stage (complete)         
        if(reqXML.readyState == 4){
          //Make sure that we get a sucess page status   
          if(reqXML.status == 200){
            //change our location
            window.location.href = url;
          }
          //For all of the wrong error pages here
          else{
            document.getElementById("spanLog").innerHTML = "<span style='color:red'> Error: username and password is not correct!</span>";
          }
        }
      }
    </script>
  </head>
  <body>
    <form name="Form1" onsubmit="VerifyLogin();return false;">
      <span style="font-family:courier">User Name: </span><input type="text" name="username"><br/>
      <span style="font-family:courier">Password:  </span><input type="password" name="password"><br/>
      <input type="submit" name="btnSub" value="Login" style="font-family:courier">
    </form>
  </body>
</html>

Now I added the event handler to the form to allow us to submit it, I did not think that needed a comment! Now you may be wondering what some things actually mean.

Now the XMLHttpRequest Object has an event handler onreadystatechange that we set to call LoginUser. Now when the XMLHttpRequest is executed we go through 5 stages:

  • 0 - un-initialized
  • 1 - loading
  • 2 - loaded
  • 3 - interactive
  • 4 - complete

We also need to check the status of the document that has been returned. We are looking for a status code of 200 since that means success! We do not want to see that 404 error!

I know I just went over this fast, but you can get more details in AJAX in Action when it comes out. But you may be saying why would I ever want to use this? Well with some minor changes, creating a JS file, and creating a bookmarklet, we can make a very very very very (did I say very) useful tool for a web master that has to check pages to see if all of the links are correct.

Let’s try this out then I will give you the source code. The first step is create a bookmarklet. Take the link below, right click on it, and save it as a bookmark. Agree to the security warning because the link is a JavaScript statement that executes some code. You will be shown the code for the bookmark on the example page.

Verify Links!

After you bookmarked that link above, you need to do open up this link below, go to your bookmarks/favorites and select the one that you just saved. It will then got through all of the links and verify them if they are good or bad. Good is marked in green and bad are marked in red! Give this code to your webmaster!

The test page for you.

There are good and bad links for you!

Now have you seen anyone else use AJAX like this? I do not think so. Hopefully you can see why AJAX is not hype. You can make it do things that you can run from a command in your bookmarks! Now below is the source code so you can save it to your server. Change the bookmark to point to where you saved this document.


      //Set those global variables!
      var reqXML;
      var url;
      var arrLinks;
      var intErrors = 0;
      var currentLink = 0; //We need a counter!
      var timeOutTimer;
      var maxWaitTime = 10000; //Milliseconds!
      var strErrColor = "red";
      var strValidColor = "green";

      function TestThatLink(){
        window.status = "testing: " + url.href;
        timeOutTimer = setTimeout("reqXML='';intErrors++;FinishRequest('" + strErrColor + "');",maxWaitTime);
        try {
	  if (netscape.security.PrivilegeManager.enablePrivilege) {
		netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
	  }
        }
        catch (ex) { // eat it
        }
        if (window.XMLHttpRequest){ 
          reqXML = new XMLHttpRequest(); 
          reqXML.onreadystatechange = TestLink;
          reqXML.open("GET", url.href, true); 
          reqXML.send(null);
        }
        else if(window.ActiveXObject){ 
          reqXML = new ActiveXObject("Microsoft.XMLHTTP"); 
          if(reqXML){ 
            reqXML.onreadystatechange = TestLink;
            reqXML.open("GET", url.href, true); 
            reqXML.send(); 
          } 
        }
        else{
          alert("Test browser does not support this!");
        }       
      }
          
      function TestLink(){         
        try {
	  if (netscape.security.PrivilegeManager.enablePrivilege) {
		netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
	  }
        } 
        catch (ex) { // eat it
        }
        if(reqXML.readyState == 4){
          window.clearTimeout(timeOutTimer);
          try {
          if(reqXML.status == 200){
            strColor = strValidColor; 
          }
          else{
            strColor = strErrColor;
            intErrors++;
          }
          }
          catch(ex){
            strColor = strErrColor;
            intErrors++;
          }

          FinishRequest(strColor);
        }
      }

      function FinishRequest(xColor){
        window.clearTimeout(timeOutTimer);
        url.style.backgroundColor = xColor;
        currentLink++;
        if(arrLinks.length > currentLink){
          url = arrLinks[currentLink];
          TestThatLink();
        }
        else{
          alert(intErrors + " broken link(s) were found!");
          window.status = "done";
        }
      }

      arrLinks = document.links;  //Grab those Links
      url = arrLinks[currentLink];  //Get the link

      TestThatLink()

Hopefully you can understand what is going on in the code. We are grabbing all of the links, checking to see if they exist, and showing the result on the page. See AJAX does not need to use server side code like everyone says! If you want to understand more about this code, ask away in the comments in this page. (If I do not answer, it is because I am sitting on the beach!)

Now it is Friday, so I think we need to put your brain to rest until Monday where we will talk about AJAX with server side code! But if you want to see a Moderator’s game that uses AJAX, take a look at Bear’s Blackbox here: Blackbox. Or you can sit back and play my JavaScript game (no AJAX) until my bandwidth is used up: Reversi.



Eric Pascarello
Moderator of HTML/JavaScript at www.JavaRanch.com
Author of: JavaScript: Your Visual Blueprint for Dynamic Web Pages


Great stuff Eric! Got you bloglined, so I dont miss out on any of your posts :)
This is not a new idea. What makes it worthy of a book?
(Note: this isn't really meant to be posted, just feedback for the author.) "How can I protect my pages with a username and password without a server side language? Well it can not be done..." This is actually not true. I'd suggest you review this thread (http://www.webdeveloper.com/forum/showthread.php?t=45175) over at the Web developer forums.
I've tried the link checker on my site (Apache 1.3.27) using Internet Explorer 6.0.2900xxx on an XP SP2 client (MSXML version 6 I think). I ran it on a sitemap page that has some internal links and some external links that I know will be broken. About 100 links in total. I been getting a few stack overflow error on the reqXML.send() statement. Have you heard of this before?
Try this and see if you still develop the error. Change this
timeOutTimer = setTimeout("reqXML='';intErrors++;FinishRequest('" + strErrColor + "');",maxWaitTime);
to
timeOutTimer = setTimeout("try{reqXML.abort();}catch(e){reqXML='';}intErrors++;FinishRequest('" + strErrColor + "');",maxWaitTime);
Not sure if that will make a big difference, but we will see.
Eric
Thanks for the response. I'm not sure why, but I no longer had the stack over flow errors even before I implemented your suggested change. Maybe something was wrong with IE and it cleared up when I restarted my pc. Thanks again.
Stack over flow errors are common when memory starts to get short. Could be cache was full, had multiple instances of IE open, something running in the background. Basically it filled up the browser's memory and the operating system has not able to keep track of the recursive function calls. Eric
Please send some basic sample examples and how to go about it. I am verymuch interested in looking at that as early as possible
On a lot of forums I post on people have been getting the stack overflow error a lot.
With some research if you use "POST" instead of "GET" it seems to eliminate the memory errors in IE.
Eric
Please send some basic sample examples that can use with jsp /javabean and how to go about it. I am very much interested & I'm using jsp/javabean to retrieve values from database (& display on the same page) once user make entry/changes to one of the field without submit
That was great stuff! But Is it possible to return custom values instead of just status codes? Thanks
Good! But where is the server side code. I'd like to see that too.
Raman, There is no serverside code involved in this. Eric
Eric, you might want to be specific with your response to 'Raman' by saying, "Raman, There is no serverside code involved in this EXAMPLE." Otherwise, your response could be misleading to suggest that "there is no serverside code involved in this [Re:AJAX].
thumbs up!!
A nice example ! What i 've seen! try to Send me a lot!!!
WOW GOOD
very nice example, fun and clear
In the first example, it should be included "<span id="spanLog"></span>" just before the end of the form tag.
The linksGalore example doesn't work in Firefox 1.5 for me.
I knew someone would have made a link checker like this. Glad I didn't have to go and make my own. BUT due to cross-site scripting protection, the link checker will not work for external domains unless you allow it extra privileges in Firefox. This is turned off by default in FF, but once enabled, is global... There are some security issues with it. In FF, enter "about:config" in the location bar. Scroll down to find "signed.applets.codebase_principal_support" and set it to TRUE The web page you look at is now allowed to make requests to other sites on your behalf. Kewl. I'm unhappy that all the checks are done SYNCHRONOUSLY (not AJAX at all ;-) so I'll see if I can get a version hacked together that loads them all ASYNCHRONOUSLY, and will take 20 seconds rather than the current 2+ minutes per page.
jhkjhk


Add a comment

Title
Body
HTML : b, i, blockquote, br, p, pre, a href="", ul, ol, li
Math Quiz 1 + 10 = (Helps stop blog spam)
Name
E-mail address
Website
Remember me Yes  No 

E-mail addresses are not publicly displayed, so please only leave your e-mail address if you would like to be notified when new comments are added to this blog entry (you can opt-out later).

TrackBack to http://radio.javaranch.com/pascarello/addTrackBack.action?entry=1119626686861