No-Refresh Links

    Kevin Yank
    Kevin Yank

    It has become relatively commonplace to see links on Web sites that do not actually cause the browser to load a new Web page. Many such links are used to trigger client-side JavaScript scripts that alter the existing page in some way. Other examples of this effect include the various currency calculators that are available online, where you type the amount in one currency into one form field, then press a button, and then the equivalent amount in another currency appears in a second form field – all without loading a new page.

    The common thread linking these examples is the use of an HTML element that was designed for fetching new Web pages but has been used in a way that prevents this from happening. Links, when clicked on, usually load a new Web page. Forms, when submitted, usually send their contents to the Web server along with a request for a new Web page. By using client-side scripts, one can easily prevent this from happening to achieve some other effect.

    But what if client-side scripting isn’t enough? What if the action to be taken upon clicking a link or submitting a form must be performed by a server-side script (updating a database, for example)? Can this still be done without having to load a new page in the browser window?

    This was the question put to me by Claude Needham in an early issue of the Tech Times. Both he and I had seen this effect in action. He had seen seamlessly add a song to his personal track list when he clicked on a link on their site. I had seen add an item to my shopping cart when I filled in and submitted a small form. Both of these tasks had been completed without any change in the page display whatsoever (as Claude said, “not even a flicker.”)

    At first, I found this effect rather distracting. After all, when the user of an online shopping site does something as important as adding an item to his or her shopping cart, that user is right to expect some form of feedback in response to that action. I realised then that this ‘no-refresh’ type of link didn’t have to exclude appropriate feedback. A simple JavaScript pop-up message stating, “this item has been added to your shopping cart” could easily be displayed at the same time, for example.

    The question then became how to create a link that submits a request to the Web server without changing the current page view. Unfortunately, my enquiries of the Web design firms that had accomplished this effect went unanswered. It seemed that the method for creating no-refresh links was something of a well-kept secret. Some ideas advanced by readers of the Tech Times included loading the resulting page into an invisible frame, and having the server-side script called by the request sleep for a very long time. The former is a relatively good solution, except that Netscape is not cooperative when it comes to creating frames of width or height zero. The latter solution, while creative and closer to what I had in mind, would result in a large number of zombie processes left running on the server.

    So How’s It Done?

    Then Fabio Dias wrote to me on Christmas Day (how appropriate!) with a promising tidbit he found hiding in the Hypertext Transfer Protocol (HTTP) Specification. For those who don’t know, HTTP is the protocol used for communication between Web browsers and Web servers. Basically, HTTP communication is initiated by a browser making a page request. The Web server then answers that request, first with a code that indicates the type of response, then with the HTML content for the new page if appropriate. The most common response code is 200, meaning a successful request with the requested Web page to follow. Another familiar response code is 404, meaning the requested document does not exist.

    What Fabio spotted was response code 204 – the “No Content” response. This response says to the browser, “I’ve done what you asked, but don’t have a new page for you to display.” As it turns out, this is precisely how the no-refresh links on and work!

    Although any server-side scripting language may be used to generate a 204 No Content response, let’s begin with a PHP example. The following will be our link that literally does nothing:

    <a href="204.php">Click me!</a>

    Similarly, the following will be a form that, when submitted, causes no visible change to the page:

    <form action="204.php" method="POST">

    This is just a normal HTML link and an ordinary HTML form; the magic is in 204.php, the script that these two HTML elements call:

    <? header("HTTP/1.0 204 No Content"); ?>

    This single line of PHP returns the 204 No Content response discussed above. If your Web server is equipped with PHP, try it yourself! If your server spits out a 500 error (internal server error), chances are good that you are running an Apache server with the CGI version of PHP, rather than the (quicker and more powerful) Apache module. In such configurations, you must instead use the following alternate syntax:

    <? header("Status: 204 No Content"); ?>

    Whichever code you end up using, when you click on the link your browser should do absolutely nothing. Depending on the specific browser and Web server you use, however, the little animation that indicates your browser is loading a page may start up. This is an unfortunate side effect of this method, which makes the inclusion of appropriate feedback all the more important. The following variations of the link and form, for example, will notify the user that the action has been taken:

    <a href="204.php" onClick="alert('Done!');">Click me!</a>
    <form action="204.php" method="POST" onSubmit="alert('Done!');">

    In this case, the feedback isn’t all that important; however, if we were to expand 204.php to do something interesting, like updating a counter in a MySQL database, we would then definitely want to let the user know that something had happened.

     $ok = mysql_query("UPDATE Counters SET Hits = Hits + 1 WHERE ID=42")  
             or die("A database error has occurred. Please try again.");  
     header("HTTP/1.0 204 No Content");  

    Note that the above script may or may not generate a page in response to the user’s action. If the query occurs normally, then the 204 No Content response will be sent and no HTML document will be returned to the browser (again, use the alternate form given above if you are using the CGI version of PHP on Apache server). If the query fails for some reason, the call to die() returns a page with an error message to the browser, and the call to header() never happens (since die() terminates the script when it is finished).

    More complex schemes can be used to determine whether or not to send a new page to the browser (depending on the value of a variable or the coordinates of a mouse click, for example), and applications for this ability can be imagined in areas such as simple online games.

    For the ASP aficionados in the audience, the following script (written in VBScript) is the equivalent of the PHP example above. It will return nothing to the browser, and you are free to make the script do whatever you please by adding to it the required commands.

    <% Response.Status = "204 No Content" %>

    And here’s how to do it in Perl using

    print header(-status=>'204 No Response');

    I should mention one note of caution. In all of the above versions of this little trick, and likely in other scripting languages as well, the command that sends the 204 No Content response must not be preceded by any output to the page. In PHP, for instance, if your script were structured as follows, it would fail with an error:

     if (some condition) {  
       header("HTTP/1.0 204 No Content");  

    The problem here is the HTML tags that appear before the PHP code. Your script can’t decide not to send the browser a Web page when it has already begun transmitting that page to the browser.

    Other than that, this technique is fairly straightforward. It just goes to show how we can take a technology for granted. Many of the readers of the Tech Times and I have built our careers working with the Web, and yet the very protocol upon which the Web is based is largely ignored — or maybe HTTP just isn’t as sexy as CSS and JavaScript.

    If you’re interested in reading more about the HTTP standard, your best bet is to go straight to the source: RFC 2616: The HTTP 1.1 Standard.