MochiKit by Example

An overview of MochiKit with three real-life examples.
Example 3: Simple User Name/Password UI with Ajax

Our final example creates a dynamic login screen. The idea is to provide feedback for an incorrect password without refreshing the entire Web page. On success, the main menu screen loads without requiring a full page reload.

MochiKit's logging functionality isn't only for debugging. Instead, it can be co-opted to be an easy error-reporting mechanism. We use this mechanism to report both incorrect user name/password errors and errors with the login script on the server (server down and so on):

function fatalLog(sendLogTo, logInst)
    /*handles our logError calls, displays in
        element param #1, displaying the error in
        yellow then fading it out after 5 seconds*/
{
    var errStr = logInst.info.join(" ");

    if (errStr.length == 0)
        errStr = "Unknown error";
    sendLogTo.innerHTML =
        "<pre> We're sorry an error occurred: " +
        errStr + ". Please try again. </pre>";

    Highlight( sendLogTo, {delay: 1, duration: 5} );
    //Yellow Fade Technique
    //see Visual.DefaultOptions documentation for
    //associative array options that affect
    //MochiKit.Visual

} //end fatalLog

Co-opting MochiKit's log functionality means that all errors can be reported using MochiKit.Logging calls. During debugging of this site, something else could be set up to handle the errors—perhaps logging more information or breaking into a source-level debugger.

We have an issue here: when parts of the page redraw, it's sometimes not obvious that part of the page contains new information. The user could be waiting for something to happen when, in fact, it already has. The Ajax community has solved this by highlighting changed elements in yellow (traditionally) and fading back to the normal background after an amount of time. This technique (the yellow fade technique) is used, in particular, by 37 Signals (the minds behind Ruby on Rails). The technique is used here to prompt users to react to the error (for example, try the password again). MochiKit makes this technique very easy with MochiKit.Visual.Highlight(). We can specify how long to delay before starting the effect, how long it should last and other options, all specified via an associative array (see the keys outlined in MochiKit.Visuals.DefaultOptions). Many of MochiKit's visual effects were ported from Scriptaculous for MochiKit 1.4.

As shown in the next code sample, our load function plugs our fatalLog function into the MochiKit.Logging framework, then sets up the environment to call our subClicked handler when the submit button is pressed:

function subClicked(eventObj)
    /*checks the username/pw*/
{
    d = MochiKit.Async.doSimpleXMLHttpRequest(
        cgiLoginLocation,
        { 'username': getElement('uname').value,
          'passw': getElement('pword').value } );

    d.addCallback(handleServerResult_Login);
    d.addErrback(handleServerError);

    getElement('waitMsg').innerHTML =
        "Please wait...";

    clearError();
    //clear the old error message, it doesn't apply

}   //end subClicked

function myLoadFunction()
{
    /*first create our Logging listener, and direct
    our generic function the errMsg span we have*/
    fatalLogTo = partial(fatalLog,
        MochiKit.DOM.getElement('errorMsg'));

    MochiKit.Logging.logger.addListener('ERRORONLY',
        null, fatalLogTo);

    MochiKit.Signal.connect( 'submit', 'onclick',
        subClicked );

    //now hide the place where our main menu will be
    MochiKit.Style.hideElement("Result");
}

/*connect our event handlers right off*/
MochiKit.Signal.connect(window, "onload",
    myLoadFunction);
//end script

MochiKit.Async.doSimpleXMLHttpRequest is the simplest way in MochiKit to do an Ajax request. It accepts the URI to which to send the request, the GET parameters for that URI, and it returns a MochiKit.Async.Deferred object. For advanced requirements, MochiKit.Async also provides functionality for sending POSTs instead of GETs, obtaining JSON documents and more. All MochiKit.Async Ajax functions return a Deferred object, so (beyond the construction) these functions behave exactly as in our example doSimpleXMLHttpRequest().

By the time we have our Deferred object, the Ajax event already is sent off. Because the call is asynchronous, it may be several seconds until an answer is received—plenty of time to set up functions (callbacks) that will handle error or success. The MochiKit.Async.Deferred object is merely a guarantee that something will happen—what happens is up to us. When a Deferred object comes back from a MochiKit Ajax request, execution of the script continues while we wait. This allows us to set up our callbacks and do whatever other housekeeping is required. When a response comes back from the server, good or bad, the appropriate callback set up in the Deferred object is called.

The success and failure callback functions get one status parameter from MochiKit.Async. Additional parameters can be sent to the callback functions by passing them to MochiKit.Async.addCallback()/MochiKit.Async.addErrback(). The status parameter always is the last parameter provided to the callback function. Success functions are called if the HTTP status code from the XMLHttpRequest is 200, 201, 204 or 304. The error function is called if the status is any other number. Success functions get a standard XMLHttpRequest object as the status object. If you've never seen one of these, the important items are responseText and status. Failure functions get an XMLHttpRequestError parameter. The important items of this object are message and number.

With all this background, we can handle our XMLHttpRequest. Remember, the idea behind this example is to do all the work required in a login screen without refreshing the page. To accomplish this, first we send an XMLHttpRequest to check the user name and password and return a session ID. In our case, the responseText from the CGI is a string whose contents are formatted as a JavaScript array. With this formatting, we could run JavaScript's eval() to get the result as a JavaScript array object, or we could simply call MochiKit.Async.evalJSONRequest() to do the same thing. In our case, the array contains (in order): a success boolean, a failure message (or an empty string, if the call succeeded) and a session ID (or 0, in the case of failure).

The success callback handleServerResult_Login() should check the success passed back from the CGI. If we have a success, it sends a second Ajax request to load the main menu. During this second request, the server checks the session ID, making sure it is valid, then returns HTML code for the main menu (or an error message). When this (second) request succeeds, the handleServerResult_Manage() clears the login controls away (which we do with a cool transition effect, courtesy of MochiKit.Visual) and inserts the main menu code. On success, cookies can be set to save the session ID (see www.quirksmode.org/js/cookies.html for cookie manipulation functions; future versions of MochiKit may include cookie manipulation functions):

function handleServerError(err)
{
    getElement("waitMsg").innerHTML = "";
    logError( err.message + " (error #" +
        err.number + ")" );
    //err.message will be like "Request Failed"
}   //end handleServerError

function handleServerResult_Manage(sessionID, res)
{
    //get rid of our login controls - we're very
    //much validated by this point
    slideUp( getElement('loginDlg') );

    //our responseText will be the HTML for the
    //"main menu"
    whereTo = getElement("Result");
    whereTo.innerHTML = res.responseText;
    MochiKit.Visual.appear( whereTo, {delay: 1} );

    createCookie("sessionID", sessionID, 1);

    getElement("waitMsg").innerHTML =
        "Cookie value = " + readCookie('sessionID');

}   //end handleServerResult_Manage


function handleServerResult_Login (res)
{
    getElement("waitMsg").innerHTML = "";
    //no more waiting required!

    //res.responseText contains our result. Our CGI
    //returns it as a JS array inside a string
    //but just let MochiKit handle it for us
    resList = MochiKit.Async.evalJSONRequest(res);
    success = resList[0];
    failMsg = resList[1];
    sessionID = resList[2];

    if (success)
    {
        //send off _another_ AJAX request
        //(passing session id), this time to get
        //the main menu screen
        d2 = MochiKit.Async.doSimpleXMLHttpRequest(
            cgiMainMenuLocation,
            {'sessionID': sessionID } );

        d2.addCallback( handleServerResult_Manage,
            sessionID );
        d2.addErrback(handleServerError);

    }
    else
    {
        logError(failMsg);
    }
}   //end handleServerResult_Login
______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Interactive Web pages

Anonymous's picture

Hi,
thanks for the informative article. chevy trucks

Thanks

Nice document

Jitesh's picture

A great informative stuff about Mochikit DnD.
Thanks for the tutorial.

Correction

jitesh's picture

Sorry mistakenly I have used the word DnD, just omit the word while reading.

Thanks
Jitesh

ucundan?

ucundan's picture

At the Voice On the Net (VON) conference in Toronto, Skype Technologies co-founder and CEO Niklas Zennstrom reported that a mobile version of Skype will be available this year.

helping

Wellnesshotel's picture

thanks for this helpfully article

Re.

zutestrane's picture

sounds like an new fancy name like mootools....

kredit

Anonymous's picture

Thanks for very interesting article. I really enjoyed reading all of your posts. It’s interesting to read ideas, and observations from someone else’s point of view… makes you think more. So please keep up the great work. Greetings

big thx

gregor's picture

Hi,
a big thanks for you - i like your article and will thank you for the examples and the code - I know it's a hard and long work to collect all the information to write such an article! Keep on your work - I will be back sonn and like to read another article written by you :)

Great job

NewSitesBlog's picture

I do congratulate you for the info. I found it to be very useful. Thank You

MochiKit

NBA's picture

Nice! You almost have me convinced. I'm going to put this page in my favorites to go over it better in the future. You covered a couple of things that I would like to be able to address in Javascript as instead of server side.

ask to you

youtube's picture

Why GPLv3 Will Supplant GPLv2

try and report

Chris's picture

Hi,
thanks for the informative article and the work with it! I will try it out and report my results soon.

Kindly regards,
Chris

Hi Should Mochikit.Visual

Balance's picture

Hi Should Mochikit.Visual Round work in all web elements like table, div, jne? I tried to use round in table, div and h1 and only h1 element worked. I used ie7 and firefox 2.0.0.4. Could someone show me a example how should I use this round function in div or other elements. Thanx allready.

looks sweet

Mac Millan's picture

dang it looks phenomenal. It is Java-based, though. IMO that's a good thing, but a lot of hosting services either don't support Java or charge more for Java support.

Thank you

güzel sözler's picture

Unfortunately, not everyone is such a big fan of Java - including myself.

Great post Ryan Wilcox.

JohnZ's picture

Great post Ryan Wilcox. However, I’m not sure I agree 100% about everything you’ve got here. I dont like JS.
Best Regards.

Slow movers are static and need to take classes...

protoman's picture

...prototypic (pronounce: 'Real') programmers are dynamic and never die.

js is....

cms's picture

Hey
I dont like JS...
I'm webmaster about 2 years...
and i use html, css, php, mysql, but sometimes JS is nessesery
at least its use full (if you can use it)

so, today i make my first own js script
and now collect js articles.. like this ;)

thx and greetings

MochiKit

ADAC's picture

Nice! You almost have me convinced. I'm going to put this page in my favorites to go over it better in the future. You covered a couple of things that I would like to be able to address in Javascript as instead of server side.

I'll be looking into this in detail in the near future!

Ajax seems to be the future

Free Software Downloads's picture

At this point, after Web 2.0 wave has pasted, I think the Ajax would be the way to come closer to what the people really want from the web.
MochiKit comes to increase the power of Ajax and offers to programmers a very powerful library. Very good article.

Would have been nice to have

Anonymous's picture

Would have been nice to have the html code for testing...

You should also check out

Anonymous's picture

You should also check out http://mochibot.com/, which is a nice flash content tracker made with monchikit. You'll see lots of sortable tables and XMLHttpRequests. The pages load extremely fast, and you can refresh the data without a full page reload.

Mochibot

MarcoR's picture

Mochibot is really one of the hottest thing i have seen in the last time, try it on your own... Cheers, Marco

SCRIPT tag syntax/usage problem

ch4dwick's picture

For some reason this doesn't work (in fact, it never worked for me in the first place):

<script type="text/javascript" charset="utf-8" src="Mochikit/MochiKit.js" />
<script type="text/javascript" charset="utf-8" src="example1.js" />

Better make it read:

<script type="text/javascript" charset="utf-8" src="Mochikit/MochiKit.js"></script>
<script type="text/javascript" charset="utf-8" src="example1.js"></script>

Best regards. :)

DTD error

Anonymous's picture

The syntax
<script type="text/javascript" charset="utf-8" src="example1.js" />
is allowed in xhtml but not in html

You´re right, but there

Maria's picture

You´re right, but there must be another problem with the syntax.

exactly.

directory's picture

exactly, but it doesn't make much difference. Does it?

One should tell users WHAT

Anonymous's picture

One should tell users WHAT BROWSER/VERSION this isn't working in as it works fine in Firefox.

ZK

ld's picture

Yet another web lib which did not understand Web 2.0...
I recommend everybody to try ZK, Ajax with no javascript (sourceforge project).

ZK apps runs a small JS engine on the browser which only reports browser events, and the web server updates the DOM via xmlrpc. This is Web 2.0 !

Mochikit has mojo

Anonymous's picture

Hmmm, I don't see why ld has to bash Mochikit. Mochikit seems like a very useful way to leverage javascript and web 2.0 is not a sharply defined term.

There was a piece about ZK in the latest Practical Webdesign. I still don't understand why you should use yet another scripting language (ZUML) and at first sight the fancy ZK components do not seem to be easy to customize.

I would vote for JSF, Tapestry or Wicket with a good AJAX framework as a java programmer.

alpella cikolata

alpella's picture

bu sitede alpella cikolatalari var dai

ZK

msn ifadeleri's picture

still don't understand why you should use yet another scripting language (ZUML) and at first sight the fancy ZK components do not seem to be easy to customize i am completely agree

Dear Mr Hammer, not everything is a nail

Xavier's picture

Yet another web lib which did not understand Web 2.0...

  • javascript framework != web lib. JavaScript is not limited to run within a browser, and to run against a web server, java or otherwise
  • javascript != Ajax != Web 2.0 Using "web 2.0" as a synonym of using xmlhttprequest+dhtml is either ill-informed or shameless jumping into the hype
  • promoting your tool != bashing other tools

ZK

Nicholas Petreley's picture

I just checked it out and it looks phenomenal. It is Java-based, though. IMO that's a good thing, but a lot of hosting services either don't support Java or charge more for Java support. Maybe that'll change once Java has been GPLed as far as Sun can take it. Maybe it's changing already and I'm just out of touch with what providers are offering. ;)

Regardless for all other needs (those other than using a hosting service), it looks fabulous.

What Java,

What Java's picture

What Java, Javascript/Mochikit isnt related to Java! btw, I can't get the rounded borders example to work. Mochikit is very well documented for n00bs. I don't understand the advanced library/packinging/classing syntaxes not covered in O'Reilly's Learning Javascript book.

One should tell users WHAT

Anonymous's picture

One should tell users WHAT BROWSER/VERSION this isn't working in as it works fine in Firefox

I meant to say, Mochikit _IS

What Java's picture

I meant to say, Mochikit _IS NOT_ well documented for n00bs, not the other way around. Typo.

Unfortunately, not everyone

ch4dwick's picture

Unfortunately, not everyone is such a big fan of Java - including myself.

I’ve tried your advices,

pilka's picture

I’ve tried your advices, but unfortunatly it doesn’t work. Don’t know maybe i’em doing something wrong. To tell the truth i’m a noob in java.