Most read posts this month



Jan 20th 2009 × getting fancy with AJAX: your first form submission and verification

Having frequented the Digital Point Forums as of recent, I have come to the conclusion that most people are barely coping with the concepts of javascript and AJAX. So much so that they are struggling to interpret anything that is more advanced than changing a few field names and including some javascript files in the page header.

Naturally – people wanting it to ‘just work’ are right, of course. There will be plenty of solutions out there for most things that can do this and achieve it in such a way that does not warrant an understanding of any javascript concept. But there comes a day when you go ‘hold on, what if I need to do this?’ and find you are stuck with a solution that you cannot comprehend…

I guess all my posts thus far have been aimed at a different type of person – one that is more ‘at home’ with javascript and mootools. Time to go back to basics…

*edit* if you’ve come here for the magical email regex that will cover _any_ RFC compliant email, here it is:
var validEmailRegex = /^(([^<>()[\]\\.,;:\s@\”]+(\.[^<>()[\]\\.,;:\s@\”]+)*)|(\”.+\”))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

click here to view sample tests and code

The most common use for AJAX that seems to draw the crowds is still a form submission. It can be via GET or via POST, it may do some form processing for required fields and so forth. But it needs to submit without a page reload and it needs to output something back. So, how do you set about creating an AJAX form?

1. First of all, grab a copy of a javascript framework. A framework is simply a library of pre-set functions and methods you can use in your own pages. I tend to use mootools but anything will do – read my post on selecting a framework. In this example, we WILL use mootools, however.

2. Create your form page. As basic as this example is, we need to assume at you have at the very least the rudimentary skill of being able to compose a form in HTML. What you should try to do is to get your form working and submitting data to your PHP or ASP or CGI processor page on its own – and we will then convert your page into an AJAX submission instead. Here is an example form page:


<div id="feedback" style="background: #eee; padding: 2px; border: 1px solid #333; float: left">
    <form action="mooForm.php?a=send" method="POST" id="myform">
    <label for="customer_name">Your name:</label><p>
    <input type="text" class="required bordered" value="" name="customer_name" id="customer_name"/><p>
    <label for="customer_email">Your email:</label><p>
    <input type="text" class="required bordered" value="" name="customer_email" id="customer_email"/><p>
    <label for="customer_comment">Your message:</label><br />
    <textarea class="required" style="width: 360px" name="customer_comment" id="customer_email"/></textarea><br /><br />
    <input type="submit" value="Send data" /></form>
</div>

3. Create a wrapper element for the form where we will output the reply: when contact_us.php is ‘reached’ and the data is saved, it can send us feedback to this effect – something along the lines of: “Thank you for your submission”. To do so, just add <div id=”feedback”></div> around your form – or you can keep it to the side, up to you and your styling preferences. We are going to be ‘replacing’ the form with the reply, however. Here it is how it all looks and works ‘on-screen’:


4. Attach javascript to intercept the form submission: you need to take control of what happens once the user presses “Send data”. Do this by fetching a copy of mootools and uploading it to your server. Within the head section of your site, you’d add the following:

<script type="text/javascript" src="mootools-1.2.1core.js"></script>
<script type="text/javascript">
// in mootools, the 'onload' event is called 'domready' and it ensures
// the DOM has completed loading and elements can be modified safely.
window.addEvent("domready", function() {
    // now, add events for the form
    $("myform").addEvents({
        "submit": function(e) {
            // stop the event from propagation...
            e.preventDefault();

            new Request({
                url: this.get("action"),
                data: this,
                onComplete: function() {
                    $("feedback").set("html", this.response.text);
                }
            }).send();
        }
    });
}); // end domready
</script>

Although, you can leave it at that, to get a working AJAX form

5. Expand on your code to add some error checking. Of course, you can use PHP or ASP or whatever serverside language you like to inspect the data being submitted – and probably should do so anyway. But it helps if you can add some trapping clientside as well – on the off-chance it reduces errors and keeps your server load lower.


// extend elements to support warnings within values
Element.implement({
    fieldWarning: function(warningText, warningDelay) {
        // very basic - changes the value of the input to warningText
        // restores to "" within warningDelay in ms

        this.set({
            value: warningText,
            styles: {
                backgroundColor: "#fcc"
            },
            events: {
                focus: function() {
                    this.set({
                        value:  "",
                        styles: {
                            backgroundColor: "#fff"
                        }
                    }).removeEvents();
                }
            }
        });

        (function() {
            this.fireEvent("focus").removeEvents();
        }).delay(warningDelay, this);
    }
});

var validEmailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;

// define common functions and variables
var isValid = function(email) {
    // boolean function that checks email string against allowed strings in accordance to RFCs
    return email.test(validEmailRegex);
},  // end isValid
cleanData = function(elementsArray) {
    // cleans passed elements with property 'value' from spaces and XSS
    elementsArray.each(function(el) {
        el.set("value", el.get("value").clean().stripScripts());
    }); // end each
} // end cleanData

window.addEvent("domready", function() {
    // now, add events for the form
    $("myform").addEvents({
        "submit": function(e) {
            // stop the event's default action from propagation...
            e.preventDefault(); // can also do new Event(e).stop();

            // clean all form fields from excess spaces and cross side scripting attacks
            cleanData($("myform").getElements("input,textarea"));

            var noErrors = true;

            // first, loop required elements
            $$("input.required,textarea.required").each(function(el) {
                var testedValue = el.get("value");
                if (testedValue.length == 0 || testedValue == "Required field") {
                    noErrors = false;
                    el.fieldWarning("Required field", 2000);
                }
            });

            if (noErrors) { // test email
                var testedEmail = $("customer_email").get("value");
                if (!isValid(testedEmail)) {
                    $("customer_email").fieldWarning("INVALID: " + testedEmail, 2000);
                    noErrors = false;
                }
            }

            // if no errors in the form, compose the XHTTP request manually.
            if (noErrors)
            new Request({
                url: this.get("action"),
                data: this,
                onComplete: function() {
                    $("feedback").set("html", this.response.text);
                    // since the form itself is contained within this layer
                    // it will 'self destroy' with whatever HTML we print
                    // from the PHP/ASP.
                }
            }).send();
        }
    });

});

What is taking place here? For the purposes of this small form, we are going to perform 2 types of javascript validations: a required field (which they all are) – a check to see if the length of the strings entered is greater than zero; and an email verification test – a check to see if the email string is compliant with RFCs, done via a regex test.

You can download the javascript above by clicking here and look at it at your own leisure.


Sep 29th 2008 × What is a javascript framework and why do I need one, part I

This ‘article’ is aimed at helping webmasters, programmers and designers who already have a rudimentary understanding of javascript and DOM programming in cementing their knowledge and getting a solid base for building browser apps in the future. For illustration purposes, I shall be using the MooTools framework but this does not mean it’s the only sensible choice.

I have been posting a fair bit on DigitalPoint’s javascript forums recently and was amazed to discover (well, not really) the huge amounts of people that struggle to get basic javascript bits and bobs working. Adding a javascript framework won’t necessarily fix that all of these problems but a good half of them (at least) will get ‘nearly there’. It also proven to improve manhood tenfold…

So, what is a javascript framework anyway?
In a nutshell: a library of pre-written javascript controls, functions and methods that make it easier for the developer to quickly and accurately produce cross browser compliant code. Example popular frameworks are: YUI, ExtJS, Prototype, MooTools and of course, jQuery. There are also several smaller frameworks around – have a look on ajaxian for a recent rundown of the relative unknowns (like Capuccino)

Yeah, and? What do I need all these libraries for?

Selectors

making sure you can access any and all of your DOM elements at your fingertips

Typically, frameworks provide all sorts of shortcuts for accessing elements within the DOM. These are called selectors and are similar to CSS selectors. Example:

<div id="mydiv" class="myclass" rel="89">click me</div>
<div id="mydiv2" class="myclass" rel="90"><a href="#">null link #0</a></div>
<span id="myspan" class="myclass" rel="89">hello world 3</span>

<a href="#">null link #1</a>
<a href="#">null link #2</a>
<a href="/index.php">normal link</a>
<input id="name" type="text" class="textfield" />
<input id="surname" type="text" class="textfield required" />*
<textarea id="message" class="required"></textarea>*

… and mootools selectors on the above

var div = $("mydiv"); // just reference by id, same as document.getElementById("mydiv"); 

// get an array of all elements that are 'myclass' (mydiv, mydiv2, myspan)
var elsArray = document.getElements(".myclass"); 

// get an array of div elements that are 'myclass' (mydiv, mydiv2)
var elsArray = document.getElements("div.myclass"); 

// get an array of elements that are myclass and rel == 89 (mydiv, myspan)
var elsArray = document.getElements(".myclass[rel=89]");

// get an array of elements that are myclass and rel is not 89 (mydiv2)
var elsArray = document.getElements(".myclass[rel!=89]"); 

// get the first element that has class myclass and rel=89 (mydiv)
var elObject = document.getElement("myclass[rel=89]");

// get an array of null links (to anchors) - (null links #0,1,2)
var links = document.getElements("a[href=#]");

// all links within the mydiv2 layer only
var localLinksArray = $("mydiv2").getElements("a"); 

// get all required fields (surname, message)
var requiredFields = document.getElements("input.required textarea.required");

The examples for selectors are potentially endless as are the possiblities for use. There is nothing to prevent you from using the old document.getElementById() function, or even document.getElementsByTagName(). There is even a new function coming out now to a browser near you (perhaps) – getElementsByClassName(). But that’s just the point – by using a framework, you are guaranteed compatibility NOW and with future releases. If a new browser ‘Steel’ comes on the market that provides access to its DOM elements by way of a function document.ById(), you would not have to go and update every single bit of javascript that on your sites to provide support for it – all you’d do is update your framework and grab a coffee – the major frameworks will always pickup on browser changes and new versions. In fact, I expect most are readying updates to cover the new Google Chrome browser and webkit changes.

Compatibility and performance

Different browsers and different versions have always had their old ideas about what’s the best way to ‘do things’. One can’t help but apploud the peioneering spirit of the Internet Explorer engineers, who pretty much just made stuff up as they went along and ignored many a WC3 standard in the process… The thing that frameworks give you that you will learn to appreciate the most is a bridge between all the browsers. You no longer need to worry if IE6 will fire an onload event when other browsers fire oncomplete. You also won’t have to worry about mistakes in misfiring of onmouseout events when hovering over child elements (IE bug, of course). Frameworks do the worrying for you and fix those common errors that are deemed fixable.

As for performance, it really, really can’t get much better than relying on a bunch of crazed javascript coders and programmers, many of whom are involved in the development of Mozilla, to write, refactor and improve all your functions for you! You get what you want from the DOM, in the fastest possible way. Yes, I am talking ‘selectors’ again and there are lots of test suites / javascript framework benchmarking results of all the major frameworks. More or that will come in part 2 – for now, suffice to say: doing a for() loop through your elements just won’t cut it.

AJAX out of the box

Enough selecting, it’s time to use some keywords that spell ‘magic’ to any marketing pro out there: ajax. web 2.0. ooooh….

Most of today’s modern frameworks will have a way of dealing with XHR requests, more commonly referred to as AJAX. Whereas it does not take much to get going with a simple AJAX request, frameworks have it polished into perfection. You can easily set things like:

  • method (GET / POST)
  • target url
  • setting up events (start, sucess, failure)
  • parameters to url as GET or POST data
  • displaying desponse into a layer/table element
  • evaluating response as javascript in a safe way
  • processing response AND evaluating <script> tags

    Say, you have an element with some summary text and you’d like to attach a click event to it to show the full article text. Here is how that AJAX request can look in mootools:

    $("mydiv").addEvent("click", function() {
        // make a click on mydiv2 to callup an ajax function that gets
        // the full contents of the layer replaced and runs through some scripts
        new Request({
            url: "/index.php",
            method: "get",
            evalResponse: false,
            evalScripts: true,
            update: $("mydiv"), // replaces the text there at the moment
            onComplete: function() {
                // already updated to full text, no need for the event to remain
                $("mydiv").removeEvents();
            }
        }).send("action=getFullText&id="+this.get("rel"));
    });

    Same functionality (just the AJAX call) in jQuery would go like so:

    $.ajax({
      url: "index.php",
      cache: false,
      success: function(response){
        $("#mydiv").append(response);
      }
    });

    In part 2, we will review how to code a few practical snippets that can build you a core library for your site – things like, tooltips, bubbles, form checkers, expanding and collapsing menus and more. And of course, my advice on choosing the right framework for you (always a subject of debate and controversy)