AWUI - a simple web user interface library with AJAX support






4.33/5 (5 votes)
An article on creating a custom JavaScript controls set and cross-browser support library
Index
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
andselectSingleNode
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(...)
.
// 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:
- Constants are named in capital letters
- Function arguments are named with "_" suffix
- Object's methods which are treated as private (methods which will be invoked only from other public methods) are named with "_" prefix
- Variables are named in Camel notation
Common AWUI methods
extend(subclass_, superclass_)
Realizes inheritance mechanism - adds tosubclass_.prototype
propertysuperclass
el(id_)
Alias fordocument.getElementById(id_)
crel(type_)
Alias fordocument.createElement (type_)
crtext(str_)
Alias fordocument.createTextNode (str_)
crimg(src_, id_, width_, height_, alt_)
Creates DOM Image object and set its propertiesabsPos(obj_)
Returns object withtop
andleft
properties which are sums ofoffsetTop
andoffsetLeft
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 thanTABLE.insertRow(pos_)
stopPropagation(e_)
Cancels propagation on DOM event to parent nodethis.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_)
ReturnsAWUI
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:
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
<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)
<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
<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
<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.