Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

AWUI - a simple web user interface library with AJAX support

4.33/5 (5 votes)
26 Jul 2007CPOL4 min read 3   382  
An article on creating a custom JavaScript controls set and cross-browser support library

AWUI - controls

Index

  1. Introduction
  2. Content of library
  3. Library architecture
  4. Using the code
  5. Redistribution
  6. History

Introduction

At present there are many approaches to make your web-application more attractive and useful for the user, for example Yahoo! provides Yahoo User Interface - a good choice to make your web pages more similar to desktop applications, Google proposes own controls set and so on.

The main requirement to custom JavaScript controls library is the ability to support widespread graphical browsers: Internet Explorer, Mozilla/Firefox, Safari and Opera. Other requirement is based on first and means the identity of view and behavior of custom controls in different browsers. Also this library can provide common methods to enumerate custom controls, to log different messages (events from controls), exception handling and so forth.

This article describes an attempt to implement a simple web-controls set which can help to customize your web-application. At present this library has four controls and one component which implements AJAX interaction mechanism (it supports synchronous and asynchronous calls).

All library controls works in IE6, Firefox 1.5+, Opera 9.

Content of library

  • awui.js
    Library core includes implementation of commonly used functions. Definition of aObject - base class for all custom controls
  • awui_consts.js
    Set of useful named constants - now it includes defines for keyboard codes
  • awui_xml.js
    Set of XML processing functions (implemented selectNodes and selectSingleNode for non-IE browsers)
  • aselect.js
    Combobox control (works like standard <select> in single selection mode)
  • aslider.js
    Slider control (emulates Windows slider control)
  • afileuploader.js
    Wrapper for standard <input type="file"> control with customizable style
  • acheckbox.js
    Graphical checkbox with three-state mode support
  • ahttpclient.js
    Set of object - cross-browser implementation of AJAX functionality

Library architecture

Library core is global JavaScript object AWUI defined in awui.js, thus all pages which uses controls from this library should include this file. All common functions are defined as member functions of this object and can be invoked as AWUI.global_function(...).

All controls are inherited from aObject - inheritance is implemented as in Yahoo UI - AWUI has method extend which adds superclass property to JavaScript object prototype. Methods on parent class can be invoked by construction object.prototype.method(...).

JavaScript
// call of superclass constructor
aSlider.superclass.constructor.call (this);
// call of superclass method
aSlider.superclass.processError (this, 'Cannot find slider object',
                            AWUI.ERROR_OBJECT);

The library code are written with several rules:

  1. Constants are named in capital letters
  2. Function arguments are named with "_" suffix
  3. Object's methods which are treated as private (methods which will be invoked only from other public methods) are named with "_" prefix
  4. Variables are named in Camel notation

Common AWUI methods

  • extend(subclass_, superclass_)
    Realizes inheritance mechanism - adds to subclass_.prototype property superclass
  • el(id_)
    Alias for document.getElementById(id_)
  • crel(type_)
    Alias for document.createElement (type_)
  • crtext(str_)
    Alias for document.createTextNode (str_)
  • crimg(src_, id_, width_, height_, alt_)
    Creates DOM Image object and set its properties
  • absPos(obj_)
    Returns object with top and left properties which are sums of offsetTop and offsetLeft of all object's parents - that is the absolute position of object (if the object has no "position:absolute" style)
  • appendRow(tbl_, pos_)
    Appends row to HTML table in specified position and returns it - works faster than TABLE.insertRow(pos_)
  • stopPropagation(e_)
    Cancels propagation on DOM event to parent node

    JavaScript
    this.label.onmousedown = astOnMouseDown;
    this.label.ondragstart = AWUI.stopPropagation;
    this.label.onselectstart = AWUI.stopPropagation;
    this.label.onkeydown = astOnKeyDown;
    this.label.onkeyup = astOnKeyUp;
  • setUnselectable(obj_)
    Denies selection of obj_
  • quoteXml(str_)
    Escapes XML special symbols in string (<,>,&)
  • getWuiObj(id_)
    Returns AWUI object by selected ID

AJAX Support

XML HTTP requests sending functionality are implemented by class aXmlHttpClient and support class aXmlHttpRequest. aXmlHttpClient has two main methods call(request_ /*url*/, method_, resultFormat_) and callAsync (request_/*url*/, handler_, method_, resultFormat_) where request_ is prepared aXmlHttpRequest object which can define target URL, POST content body, request timeout (which is controlled by aXmlHttpClient), HTTP method ("GET", "POST") and format of result ("text/xml" or "text/plain").

If the first argument of these methods is string then it will be treated as target URL and new request object will be created with selected method_ and resultFormat_. These methods are sent HTTP request to server and return result as XML document object when format of the result is "text/xml" and as text in other case.
On ASPX page it can be used as:

JavaScript
var TAG_SERVER_ERROR = "ServerError";
var SERVER_REQUEST_TIMEOUT = 1000;

function getServerInfo() {
    var url = "<%= Response.ApplyAppPathModifier
                    (Request.Path + "?cmd=get_info") %>";
    httpClient.callAsync (url, onLoadServerInfo);
}

function onLoadServerInfo (data) {

    if (data && data.documentElement) {

        var lblInfo = AWUI.el ("lblProcessing");
        var message = "";
        var doc = data.documentElement;
        var item = null,
            size = 0,
            name = "",
            loaded = false;

        if (doc.tagName != TAG_SERVER_ERROR) {

            var items = AWUI.xmlSelectNodes (doc, "//DocumentInfo");
            for(var ndx=0; ndx<items.length; ++ndx) {
                if (ndx > 0) message += "<br />";
                item = items[ndx];
                if (item) {
                    size = parseInt (AWUI.xmlGetText 
                    ( AWUI.xmlSelectSingleNode (item, "./Size")));
                    loaded = (AWUI.xmlGetText 
                    ( AWUI.xmlSelectSingleNode 
                    (item, "./IsLoaded")).toLowerCase() == "true");
                    name = AWUI.xmlGetText 
                    ( AWUI.xmlSelectSingleNode (item, "./Name"));
                    message += "Name: ";
                    if (loaded)
                        message += "<a href='javascript:void(0)' 
                    title='Open' onclick=\"openDocument
                    ('" + name + "')\">" + name + "</a><br />";
                    else
                        message += name + "<br />";
                    if (size < 0) {
                        message += "loading...<br />";
                    } else {
                        message += "Size: " + AWUI.xmlGetText 
                    ( AWUI.xmlSelectSingleNode 
                        (item, "./Size")) + "<br />";
                        message += "RequirementsCount: " + AWUI.xmlGetText 
                    ( AWUI.xmlSelectSingleNode 
                    (item, "./RequirementsCount")) + "<br />";
                        message += "Paragraphs: " + AWUI.xmlGetText 
                    ( AWUI.xmlSelectSingleNode 
                    (item, "./LoadedParagraphsCount")) +
                                "/" + AWUI.xmlGetText 
                    ( AWUI.xmlSelectSingleNode 
                    (item, "./ParagraphsCount"))
                                "<br />";
                    };
                };
            }

    } else {
            // process error
            message = "<span class='error'>" + "Error: " +
                AWUI.xmlGetText ( AWUI.xmlSelectSingleNode 
                (doc, "./Message")) + "<br />" +
                AWUI.xmlGetText ( AWUI.xmlSelectSingleNode 
                (doc, "./Type")) + "<br />" +
                AWUI.xmlGetText ( AWUI.xmlSelectSingleNode 
                (doc, "./StackTrace")) + "</span>" ;
        }
        lblInfo.innerHTML = message;
    }
    window.setTimeout("getServerInfo()", SERVER_REQUEST_TIMEOUT);
}

Using the code

See attached demo files for use of all kinds of AWUI controls.

aCheckBox

JavaScript
<h1>Simple CheckBoxes</h1>
Graphical CheckBox: <script language="JavaScript">    
        var cb = new aCheckBox(1);    cb.draw();</script><br>
Graphical CheckBox (2): <script language="JavaScript">    
        var cbcircle = new aCheckBox(1); 
    cbcircle.imgPath="img/cb_circle"; cbcircle.draw();</script><br>
Win98 CheckBox: <script language="JavaScript">    
        var cb2 = new aCheckBox(); cb2.imgPath="img/cb_win98";    
        cb2.draw();</script><br>
WinXP CheckBox: <script language="JavaScript">    
        var cbxp = new aCheckBox(); cbxp.imgPath="img/cb_winxp";    
        cbxp.draw();</script>
<h1>Tristate CheckBoxes</h1>
Graphical CheckBox: <script language="JavaScript">    
        var cb3 = new aCheckBox(1, true);    
        cb3.draw();</script><br>
WinXP CheckBox: <script language="JavaScript">    
        var cbxp3 = new aCheckBox(-1, true); 
        cbxp3.imgPath="img/cb_winxp";    
        cbxp3.draw();</script>

aFileUploader (ASP.NET)

JavaScript
<script language="JavaScript" src="js/awui.js"></script>
<script language="JavaScript" src="js/afileuploader.js"></script>
<script language="JavaScript"> afuPrintStyles(); </script>
...
<%
    HttpFileCollection files = Request.Files;
    string[] keys = files.AllKeys;
    for (int ndx = 0; ndx < keys.Length; ndx++)
    {
       Response.Write("<b>File</b>: " + Server.HtmlEncode(keys[ndx]) + "<br>");
       HttpPostedFile file = Request.Files [keys[ndx]];
       Response.Write("path: " + Server.HtmlEncode(file.FileName) + "<br>");
    }
%>
...
<form name="form1" method="POST" enctype="multipart/form-data">
<table border=0>
    <tr>
    <td><script>var file = new aFileUploader("file", 300, 20); file.draw();
        </script> </td>
    <td><input type="submit" class="btn" value="Upload" style="height: 20px;">
            </td>
    </tr>
</table>
</form>

aSelect

JavaScript
<script language="JavaScript" src="js/awui.js"></script>
<script language="JavaScript" src="js/awui_consts.js"></script>
<script language="JavaScript" src="js/aselect.js"></script>
...
<script language="JavaScript" >
    function onSelChange (newVal, oldVal, sel) {
        window.status = sel.name + " changed to: " + newVal + ", from: " + 
                                    oldVal;
    }
</script>
...
<script>
var data = ["A", "B", "C", "D"];
var sel1 = new aSelect("sel1", data, 0);
sel1.onselchange = onSelChange;
sel1.draw();
</script>

aSlider

JavaScript
<script language="JavaScript" src="js/awui.js"></script>
<script language="JavaScript" src="js/aslider.js"></script>
<script language="JavaScript" >
function onScroll(obj_, pos_){
    window.status = obj_ + ": " + pos_;
}
</script>
...
<script>
var slider = new aSlider(50);
slider.onscroll = onScroll;
slider.draw("", 300, 30);
</script>

Redistribution

All parts of AWUI can be used in your projects without limitations (in case you consider that it is worthwhile doing it...). Also I will appreciate if you report to me bugs in the code.

History

  • Jan 25, 2007 - AWUI - A Web User Interface Library v0.1.0.0.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)