online advertising

What’s New in PHP 5

The PHP 5 release comes with a slew of new features aimed at simplifying development with PHP. With PHP 5 comes the introduction of exception handling, the Standard PHP Library (SPL), enhanced support for XML, reflection, and quite a few enhancements to the object oriented features of the language. PHP 5 also offers a sizable list of new functions, many of which will not be covered in this article but are available in the manual.XML

PHP 5 by default installs XML support and offers a new extension, SimpleXML. All XML functions are now standardized on the libxml2 library and are fully W3C standards compliant. SimpleXML is quite possibly the most valuable addition to PHP in years, providing a traversable structure to work on XML documents, allowing you to simply change values in the structure and write the file out with only a few lines of code. The XML functionality that has been available through PHP in the past has been quite rudimentary and required a fair amount of programming work to use, so it is not uncommon to see PHP 4 applications using XML without ever touching the xml functions.

PHP 5 also offers a replacement extension for DOMXL (available in “experimental” form in PHP 4) with the DOM extension. This extension allows you to work on your XML files using the DOM object model and is superior to SimpleXML particularly when you are not certain what document format to expect with your application. While DOM is more powerful, SimpleXML is much quicker to implement and easier to get a handle on for beginner programmers. Both of the extensions are robust and well thought out, and whichever suits your programming needs and taste, you will be using a powerful extension that is light years beyond what was available in PHP 4.

Database Support

PHP 5 offers some big enhancements to its ability to interact with databases. The most significant addition is the embedded SQLite database, a quick, lightweight database engine made specifically for embedded applications. This means there is no RDBMS process running on the server; SQLite reads and writes directly to files on disk. This results in significantly lower memory overhead when the database is not being used, but major performance problems arise if the system is used in a high traffic environment. SQLite is intended for small scale use, as best I can gather.

When testing it with small tables and less than one thousand rows per table, it was comparable to MySQL in executing simple joins with only one concurrent request, but performance from SQLite degraded exponentially with five or more concurrent connections coming in, which makes perfect sense. This is a good database solution for a small site that needs minimal features and expects minimal usage. It could also be useful for storing embedded configuration data in a PHP 5 application that may house its main data store in another RDBMS, and only run small queries against SQLite. SQLite is relatively standards compliant with a few major exceptions, most notably the lack of an ALTER TABLE statement.

PHP 5 also introduces support for the MySQL 4.1 client library with the introduction of the mysqli extension. The mysqli extension provides some basic objects for working with the MySQL server. The mysqli class is used as a connection object and as the ability to open and close connections as well as get context and state information from the server. The mysqli_stmt class represents a prepared statement that allows you to execute “prepare” and “execute” queries against the database. Lastly, the mysqli_result object provides a cursor based interface for reading results, providing similar functionality to the functions available in the standard MySQL extension using a MySQL resource handle. The new extension also adds support for SSL and input/output parameters.

The last notable addition in the database area is enhanced support for Firebird/InterBase, an RDBMS that offers most ANSI SQL-92 features and runs on most operating systems. The ibase extension provides most of the same functionality for Firebird/InterBase as the new mysqli extension does for MySQL but in the same manner as the old MySQL extension – that is, no objects.

SPL: Exceptions and Iterators

PHP 5 comes with the Standard PHP Library (SPL), a collection of objects built to handle various tasks such as exception handling and object traversal (iteration). There are basically six groups of classes/interfaces available natively to the SPL.

  1. Iterators: SPL provides built in iterators to assist in a common task – object traversal. Iterators provide a way to traverse an object’s contents without exposing the inner workings of the object to the outside world. Iterators can be built to work on any data structure and provide a standardized interface. Some of the iterator classes and interfaces available in the SPL are: Iterator, OuterIterator, RecursiveIterator, IteratorIterator, ParentIterator, SeekableIterator, NoRewindIterator, and InifiniteIterator.

    Each iterator has a specific purpose and details can be found in the PHP manual.

  2. Directories: Two directory classes are available in the SPL: DirectoryIterator and RecursiveDirectoryIterator. These classes allow iterator based directory traversal and eliminates the need for messy directory handles.
  3. XML: There is one XML handling class in SPL, SimpleXMLIterator, which provides iteration over a simplexml object.
  4. Arrays: SPL offers something that has long been in need in PHP – ArrayObject and ArrayIterator. These object provide, as you may have guessed, an array object as well as an object to traverse the contents of an array without making assumptions on the way the array is storing it’s internal data.
  5. Counting: The SPL interface Countable allows you to hook into the standard array function count(), meaning you can use the count() function on a user defined object and get a meaningful result by implementing the Countable interface. This is very useful for non-simple data structures.
  6. Exceptions: Probably the biggest feature addition via the SPL, exceptions allow graceful error handling through try/catch blocks. The Exception class is simple to extend and the SPL provides a few standard classes of exceptions for common problems, such as LogicException, BadFunctionCallException, DomainException, OutOfRangeException, and InvalidArgumentException. Error handling has been a longtime problem in PHP and has resulted in some of the ugliest code I’ve ever seen, particularly using the PEAR error class. Exceptions should eliminate this sort of problem in the future.

OOP: Object Enhancements

PHP 5 makes leaps and bounds in its support for objects. Aside from all the new features, Zend claims to have addressed the performance problems involved with object creation and usage in previous versions of PHP, a fact that in itself should encourage more developers to use object-based PHP. PHP 5 offers enhancements in a few key areas including object autoloading, destructors, visibility, static methods, class constants, type hinting, interfaces, cloning, reflection and several magic methods.

Autoloading is a great new feature that provides a way for developers to make sure all dependencies for a class are in place before using it. If you attempt to instantiate a class that has not yet been defined, PHP 5 will call the __autoload() function as a last attempt to load the class before failing with an error. Since most developers put one class per file, and many classes often depend on another either by way of inheritance or encapsulation, __autoload() allows you to make sure all the necessary class files have been included. While PHP 4 had constructors, PHP 5 offers a new features: destructors. Destructors are called when an object is destroyed or all references to it have been removed. Destructors are implemented in classes by use of the __destruct function. The __construct function has also been introduced and takes precedence over the old-style constructor function. The old style still works, but it is recommended that __construct is used as it takes higher priority.

One of the biggest additions to PHP’s support for objects is visibility modifiers, also known as access modifiers. The var keyword has been deprecated and class variables are now to be declared as public, private, or protected. Public class variables are available to any other part of the program. Private variables are only available to that class. Protected variables are available to a class as well as its child classes, unlike private which only allows the class itself to access the variable. Methods can also be declared as public, private, or protected, and if none are declared a method is assumed to be public. Access modifiers allow PHP programmers to programmatically hide the inner workings of one object from another by preventing other objects from accessing class data directly. PHP 5 also introduces the static keyword. Static methods are called without an object instance and calls to static methods are resolved at compile time, not runtime. Static properties are accessed by the :: operator, not ->, and the special variable $this is not available in static methods.

Not only can you declares constants in C-style syntax, const constant = ‘constant value’;, but a class can contain it’s own constants and access them internally using self::constant. This simplifies management of constants and keeps them contained within the classes they belong to, preventing code clutter and conflicts with other constants in the same application that may need the same name but a different value. PHP 5 also allows type hints in method parameter declarations. If a parameter is given a type hint and an object of the wrong type is passed to it, PHP will generate a fatal error. It would be preferable for an exception to be thrown, but type hinting does at least allow responsibility to be placed in the calling code for making sure the proper data type is passed into a function call. Type hints can be used in any function, not strictly in class methods.

PHP 5 also introduces abstract classes and interfaces, which is probably THE most significant enhancement to the language. Abstract classes and interfaces allow high level design principles to be semantically applied to PHP classes. PHP includes three special method keywords, final, abstract and virtual, to facilitate the use of inheritance and interfaces. When a method is declared as final, it cannot be overridden by a child class. When a method is declared as abstract, it must be defined in a child class. When a method is declared as virtual, it may be inherited as is or overridden by a child class. When used in combination, abstract classes and interfaces enforce high level design throughout all levels of implementation and support properly coded objects. They can be used in excess, as can anything else, but used properly these are the most powerful tools available to object oriented developers.

The last features of note are object cloning, some more magic functions and the reflection class. Object cloning allows the implementation of a magic method, __clone() to define what exactly takes place when clone is called on an object. It allows developers to implement deep copying of object data when cloning without writing messy code. A few other noteworthy magic functions are __sleep() and __wakeup(), which are used in conjunction with serialize and unserialize to ensure proper destruction and recreation of resources used within an object. Additionally, the __toString magic method allows a class to decide how to react when it is used in string context. The reflection class works as the name implies; it allows developers to programmatically reverse-engineer classes, interfaces, functions and extensions. Reflection is a powerful tool in developing custom application frameworks.

Conclusion

Overall, PHP 5 offers dramatic improvements over PHP 4 in a lot of areas. These improvements are, by and large, geared toward advanced PHP developers. With the exception of the SimpleXML extension, most of the new functionality will probably have no appeal to the largest segment of the PHP programming population – that is, developers who look at PHP as a simple scripting language and use it to accomplish one task at a time. For PHP application developers though, I see PHP 5 quickly becoming the de facto standard. Start putting pressure on your hosts now to upgrade, because PHP 5 was definitely worth the wait.

by David Fells

55 Reasons to Design in XHTML-CSS

In no particular order 55 reasons for me to do “tableless” websites using valid XHTML for markup, CSS for layout and Flash sparingly, only as an ingredient. By tableless I mean avoiding tables (or a tagsoup of unnecessary divs substituting table trs and tds) for layout purposes and aiming towards as semantic markup as possible. Some of the reasons are “over HTML”, some “over Flash full monty” and some over both.

I know this topic has been discussed a plenty, I just needed to reaffirm myself :)

Here we go:

  1. You can get free links from showcase sites like zengarden, stylegala, cssimport or cssbeauty
  2. You don’t have to spend extra thought and time deciding on styling the mark up of your document (upper- or lowercase, quotes or no quotes on attributes)
  3. You don’t need to spend extra thought on which tags should be closed and which can (or should) be left open
  4. You “help” the search engines to deliver more relevant content using semantic markup
  5. You can save in bandwidth costs and visitors will see them faster by making slimmer pages
  6. It’s going to be easier for you to switch to XHTML 2.0 which will give you more semantic tools
  7. Once you’ve practised enough, coding pages becomes a whole lot simpler and faster than any table/tr/td tagsoup
  8. When the coding is faster you can spend more time on thinking about the user experience
  9. Thinking about semantics of a document helps you to make design and information architecture decisions
  10. You can quickly make a dummy site to test your sites information architecture and append a look and feel later with only minor code changes
  11. You can do the design after most of the backend is done which will help your client (or boss) to think realistically about how much work is still needed
  12. It’s possible to link directly to your content pages (compared to Flash)
  13. browser controls like text-size and back and forward buttons work (compared to Flash)
  14. Redesigns and realigns over the whole site are simpler
  15. it’s simpler to make small last minute changes to your designs
  16. Clean markup makes it easier or even unnecessary to build a CMS
  17. Clean markup makes it easier for another developer to jump on board
  18. You can make the backend almost totally independently from the frontend design, by completely different person
  19. You have plenty of ways to play with the markup trying to optimize for search engines, without affecting visible layout
  20. You have total control on print layouts of your pages
  21. Your sites are automatically accessible to all kinds of browsers
  22. Promoting web standards will help your work in the future, not having to code differently to each browser
  23. With all elemets closed you mark up look cleaner
  24. Well-formed code ensures your site works in more browsers
  25. Well-formed code would help browser coders to spend more time on useful features than rendering engines that try to understand borken code
  26. Your website will work in future browsers
  27. Your website works in mobile (and other new) devices
  28. You learn the basics of XML which has many other uses
  29. CSS files are saved in browser cache for fast retrieval and less bandwidth use
  30. Your documents are easy to convert back and forth another format using XSLT
  31. Thinking semantics makes you think more about the content
  32. Learning semantics makes you appreciate organization and write your other documents (even emails) in more organized way
  33. You can write new technologies in your CV or portfolio
  34. Modern browsers render a valid document faster
  35. You feel better about yourself when you are making sites “the right way”
  36. They are doing it: Dan Cederholm, Jeffrey Zeldman, Jason Santa Maria, Shaun Inman, Cameron Moll, Douglas Bowman, Dave Shea
  37. You will belong in a “movement”, make good contacts etc.
  38. You learn to appreciate newer browsers which makes for more competition and later for better browsers
  39. Blink tag is gone
  40. Strict coding makes you learn to see mistakes quicker
  41. You can aim to making some money writing a book about it
  42. There are more job opportunities if you know these new ways
  43. You learn better to understand how a browser works
  44. You can use hacks and techniques with cool names like “be nice to Opera”
  45. you start to care more about metadata, document and character types
  46. With more people making slimmer pages, the amount of data moving in the whole web will be smaller and all connections faster
  47. XHTML has a cooler name than HTML
  48. There are more people thinking about the advantages and disadvantages and coding tricks of XHTML which makes for a bigger learning forum
  49. You can use basically same markup template for many different websites
  50. Learning to read and write it fast makes it possible to use cheaper tools (notepad)
  51. Google knows this:
    • 4,380,000 xhtml better than html > 4,370,000 html better than xhtml
    • 206 “xhtml is better than html” > 87 “html is better than xhtml”
    • 2,130,000 xhtml sucks < 10,300,000 html sucks
  52. When all browsers start to understand the correct MIME-type (xml), you don’t have to convert all your websites from html, just to switch to correct MIME
  53. By more people using xhtml you ensure that in the future IE will need to understand the correct MIME-type
  54. Accessibility is enforced with requiring Alt attribute for images
  55. There just aren’t this many reasons to use HTML or entirely Flash instead

Widget Walkthrough

The first half of this tutorial introduced you to making a rudimentary but functional widget of the sort you can find on Yahoo’s site since its purchase of Konfabulator. In this article, you’ll add the finishing touches to increase its functionality.Widget Walkthrough

The preferences that you created in the first part of this article won’t actually do anything on their own; they’ll need the following JavaScript in order to actually make the required changes:

<action trigger=”onLoad”>
<![CDATA[
function updatepreferences() {
datatextarea.font = preferences.textfontpref.value;
datatextarea.color = preferences.textcolorpref.value;
datatextarea.size = preferences.textsizepref.value;
datatextarea.style = preferences.textstylepref.value;
}
updatepreferences();
]]>
</action>
<action trigger =”onPreferencesChanged”>
updatepreferences();
</action>

As you can see, each action (onLoad and onPreferencesChanged) is contained within its own <action> element. All each line of the updatepreferences() function is doing is setting the attributes of the textarea element, much as CSS would with HTML. I’ve included the opening CDATA tag as we’ll need it for one of the next functions.

Widget Walkthrough – Getting the headlines

Now you need to actually get the news headlines from the BBC web server. To do this, you’ll need to make use of the URL widget engine object:

function getdata() {
var url = new URL();

url.location =
“http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/
technology/rss.xml”;
feeddata = url.fetch();
}
getdata();

This will instruct the widget to fetch whatever file is waiting at the above URL. You now need to display the file:

function setdata() {
datatextarea.data = feeddata;
}
setdata();

This function can be added into the existing onLoad <action> and simply creates a new URL object, sets the location attribute to the source of the feed, and then retrieves the information as the specified location. At this point, you should have something that looks a little like this:

widget_feeding.jpg

The function works; it grabs the file located at the target URL, but unfortunately, this happens to be in an XML format! This means our textarea is currently displaying the entire XML file! Another function, to traverse the XML document and pull out just the headlines, is going to be needed. Fortunately, the widget engine provides XPath 1.0 support to make extracting the required items relatively easy.

There are several steps involved in getting the data that we want; if you look at the XML document obtained by the url.fetch command, you’ll see that the news headlines we want to grab appear in an element called title, which is a child of the item element, which is a child of the channel element, which finally, is a child of the rss element. Therefore, the element we need is a great-grandchild of the root element. Remove the setData() function as we can extend the getData() function to display the headlines once they have been extracted.

Widget Walkthrough – Using loops

The Widget reference manual states that you should use a try catch loop to perform XPath functions, so you can add one to your getData() function. You will first need to obtain the XML document and place it in a variable using the parse method:

try {
doc = XMLDOM.parse(feeddata);

Next, you need to specify which elements in the XML file you want to match. This is the XPath element of your function:

titlelist = doc.evaluate( “rss/channel/item/title” );
datatextarea.data = “”;

You now need to create an array to hold the headlines as separate DOMElement objects:

titles = new Array();

In this particular rss file, there are always 19 headlines, however, if you were using a different feed, you may not know the number of headlines in advance so it is a good idea to use a for loop that operates on the length of your array:

for (n = 0; n < titlelist.length; n++) {

The DOMNodeList returned by the XPath function has a built-in property of item() which can be used to specify which DOMElement in the list you are referring to. In this case, we can match the number of the array item with the item we want to store in the array:

titles[n] = titlelist.item(n);

Finally, each time the loop iterates, you can set the data property of the <textarea> to the data held in the array item. The actual item held in the array is the DOMElement; to get the actual text held in the object you need to address the firstChild of the element. The JavaScript new line character is also specified (twice) to break up the headlines:

datatextarea.data += titles[n].firstChild.data + “nn”;
}
}
catch(e) {
print(e);
}

Widget Walkthrough – Fine tuning headline retrieval

If you save the changes and reload the file now, the headlines should appear as if by magic! Using the <textarea> is good because it makes setting the preferences easy and handles the word wrapping well. One major flaw of this though is that it’s not possible to set the URL of each individual headline. To compensate for this, you can add a right-click menu item to the widget that takes you to either the main news front page, or a page containing the list of headlines displayed. To do this, you can add the following code block to the <textarea> element:

<contextMenuItems>
<menuItem title=”Open BBC Technology News”>
<onSelect>openURL
(”http://news.bbc.co.uk/1/hi/technology/default.stm”);</onSelect>
</menuItem>
<menuItem title=”Open the actual headlines page”>
<onSelect>openURL
(http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/technology/rss.xml);
</onSelect>
</menuitem>
</contextMenuItems>

This at least provides you with a way of reading the full news stories. Another thing that you need to consider is a way of updating the file used as the source of the data; if the computer and widget are left running, the reader will just display the same data, forever. A timer element can be used to specify that an action could be carried out repeatedly on a set interval:

<timer>
<interval>10</interval>
<onTimerFired>getdata();</onTimerFired>
</timer>

The interval is measured in seconds, but this kind of widget wouldn’t really need to grab a new rss file every ten seconds. Depending on the frequency of updates at the source, you could probably set it to update maybe several times daily.

widget_finished.jpg

Widget Walkthrough – Publishing your widget

In order to get your widget published on the Yahoo! Widget Gallery, you need to switch off debugging and package your widget. Right at the top of the file, you’ll find the <debug> element; set this to off. To package the application and produce the flat, one-file version of the existing files and folder structure, you’ll need to get to grips with the command line interface (CLI) included in the SDK. The converter is situated (on a Windows XP system) at the following location:

C:Program FilesYahoo!Yahoo! Widget Engine

You need to create an output directory at this stage so create a folder, also at the above location, called feeder or something similar. Now open a command prompt. It will probably open (on a Windows XP system) in your My Document folder so you’ll need to use the cd (change directory) command to browse to the location of the CLI. You should also move your widget folder into the same directory as the CLI and output directory. Once this has been done, use the following command to package your creation:

converter_4a convert -v -flat TechFeeder.widget -o outputDirName

You should then end up with a flat file package containing all of the files that make up the widget in the output folder. Your widget should now be ready to go onto the gallery, but don’t submit this one (because I already have).

The tagline displayed on the home page of the Widget gallery is “The grass is greener on both sides” which pays homage to widgets’ cross platform compatibility. When creating widgets, you should ensure that you test your widget on a Mac and that it runs on both Mac and Windows platforms. I have tested this widget on a Mac and unfortunately, it doesn’t work as well as it does on Windows systems; instead, it just displays the first headline. I don’t actually know why this is, but I am investigating. In the meantime however, I’ve specified on the gallery that it’s Windows only. Also, the Widget optimizer tool is supposed to be used to remove unnecessary memory forks on widget created on the Mac, but like the converter tool it isn’t currently available, so for the time being, those of you on Macs I guess will have to forgo this at present.

There is a lot more that could be done to refine the widget. At this stage it really is just a version 1.0 release. You could add a function that automatically scrolls the headlines perhaps, or create the headlines as individual text elements, each with their own URL property to make them clickable links to each of the news stories, or even include the description in a title element that displays when the mouse runs over each text element; the possibilities are endless. But what you have now is a very basic, but fully functional widget, produced with ease and in not much time at all. This is the beauty of the Yahoo! Widget Engine, speed and ease of deployment and fully functional information management right on your desktop.

Displaying ADO Retrieved Data with XML Islands

An XML data island is a piece of well-formed XML embedded into an HTML file. This article will show you how to retrieve data in an XML format from a database using ADO; you will also learn how to bind this data into an HTML document.Introduction

The previous tutorial, The Why and How of XML Data Islands, considered embedding a well formed XML fragment into an HTML file to create an XML data island. The article also showed how one could access data embedded in the XML file. The tutorial also described data binding to various HTML tags. However the XML data used was a hard-coded XML fragment.

In this tutorial, how data in XML format can be retrieved from a database using ADO will be described. The XML data obtained using ADO will be reviewed. An example of how Jet Data types are associated with XML data types will be shown. This will be followed by how to use the data to bind it to an HTML document. After all, this is what the client is after. It will be helpful if the reader reviews the previous article and the XML related articles to which you can find links on this site.

Data to XML Conversion using ADO

Persisting data in the XML format is one of the most important features of ADO since the 2.5 version. This means that ADO recordsets can be saved as an XML file to a location of your choice. Alternatively they can also be saved to a Stream object. Since the data is derived from a database together with the data, the data structure comes with it. Ideally this format should be able to be transparently used by any machine.

Displaying ADO Retrieved Data with XML Islands – Extracting XML formatted data example

Using the save() method of ADO, you could save the recordset to a file as shown in the next paragraph. The recordset is created by accessing an MDB file on the hard drive. Not all the columns in the ‘Employees‘ table in the Northwind database will be saved as an XML file. The variable fileName points to the location on the hard drive where the XML file will be saved.

adoxml011.jpg

Create UI to test code

On a form in your MS Access application add a button, and to the click event of this button add the following code. The statement

rs.save fileName, adPersistXML >

can also be saved as

rs.save fileName2, adPersistADTG

where fileName2 will have an .adtg extension. This is yet another proprietary format called the Advanced Data TableGram format. We will only look at the persisted XML formatted file.

Private Sub Command0_Click()
Dim rs As New ADODB.Recordset
fileName = "C:NwindEmployees.xml"
rs.Open "Select * from Employees where LastName='Peacock'", _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=C:Documents and SettingsJayMy DocumentsRetrieve.mdb;" & _
"Persist Security Info=False", adOpenKeyset, adLockOptimistic,
adCmdText
If Dir$(fileName) <> "" Then Kill fileName
rs.Save fileName, adPersistXML
End Sub

In the above code the recordset for the indicated SQL statement will be saved.

Displaying ADO Retrieved Data with XML Islands – The Saved XML file

If you open the file C:NwindEmployees.xml in a text editor you can see the full details.

<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
        xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
        xmlns:rs='urn:schemas-microsoft-com:rowset'
        xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
        <s:ElementType name='row' content='eltOnly' rs:updatable='true'>
               <s:AttributeType name='Address' rs:number='8'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='Address'>
                       <s:datatype dt:type='string' dt:maxLength='60'/>
               </s:AttributeType>
               <s:AttributeType name='BirthDate' rs:number='6'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='BirthDate'>
                       <s:datatype dt:type='DateTime'rs:dbtype='variantdate' dt:maxLength='16' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='City' rs:number='9'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='City'>
                       <s:datatype dt:type='string' dt:maxLength='15'/>
               </s:AttributeType>
               <s:AttributeType name='Country' rs:number='12'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='Country'>
                       <s:datatype dt:type='string' dt:maxLength='15'/>
               </s:AttributeType>
               <s:AttributeType name='EmployeeID' rs:number='1'rs:maydefer='true' rs:writeunknown='true' rs:basetable='Employees'
                        rs:basecolumn='EmployeeID'rs:autoincrement='true'>
                       <s:datatype dt:type='int' dt:maxLength='4'rs:precision='10' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='Extension' rs:number='14'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='Extension'>
                       <s:datatype dt:type='string' dt:maxLength='4'/>
               </s:AttributeType>
               <s:AttributeType name='FirstName' rs:number='3'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='FirstName'>
                       <s:datatype dt:type='string' dt:maxLength='10'/>
               </s:AttributeType>
               <s:AttributeType name='HireDate' rs:number='7'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='HireDate'>
                       <s:datatype dt:type='dateTime'rs:dbtype='variantdate' dt:maxLength='16' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='HomePhone' rs:number='13'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='HomePhone'>
                       <s:datatype dt:type='string' dt:maxLength='24'/>
               </s:AttributeType>
               <s:AttributeType name='LastName' rs:number='2'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='LastName'>
                       <s:datatype dt:type='string' dt:maxLength='20'/>
               </s:AttributeType>
               <s:AttributeType name='Notes' rs:number='16'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='Notes'>
                       <s:datatype dt:type='string'dt:maxLength='536870910' rs:long='true'/>
               </s:AttributeType>
               <s:AttributeType name='Photo' rs:number='15'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='Photo'>
                       <s:datatype dt:type='string' dt:maxLength='255'/>
               </s:AttributeType>
               <s:AttributeType name='PostalCode' rs:number='11'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='PostalCode'>
                       <s:datatype dt:type='string' dt:maxLength='10'/>
               </s:AttributeType>
               <s:AttributeType name='Region' rs:number='10'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='Region'>
                       <s:datatype dt:type='string' dt:maxLength='15'/>
               </s:AttributeType>
               <s:AttributeType name='ReportsTo' rs:number='17'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='ReportsTo'>
                       <s:datatype dt:type='int' dt:maxLength='4'rs:precision='10' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='Title' rs:number='4'rs:nullable='true' rs:maydefer='true' rs:write='true'rs:basetable='Employees'
                        rs:basecolumn='Title'>
                       <s:datatype dt:type='string' dt:maxLength='30'/>
               </s:AttributeType>
               <s:AttributeType name='TitleOfCourtesy'rs:number='5' rs:nullable='true' rs:maydefer='true' rs:write='true'
                        rs:basetable='Employees'rs:basecolumn='TitleOfCourtesy'>
                       <s:datatype dt:type='string' dt:maxLength='25'/>
               </s:AttributeType>
               <s:extends type='rs:rowbase'/>
        </s:ElementType>
</s:Schema>
<rs:data>
        <z:row Address='4110 Old Redmond Rd.'BirthDate='1958-09-19T00:00:00' City='Redmond' Country='USA'EmployeeID='4'
                Extension='5176' FirstName='Margaret'HireDate='1993-05-03T00:00:00' HomePhone='(206) 555-8122'LastName='Peacock'
                Notes='Margaret holds a BA in English literature fromConcordia College and an MA from the American Institute of Culinary Arts.She was temporarily assigned to the London office before returning to her

permanent post in Seattle.'
                Photo='EmpID4.bmp' PostalCode='98052' Region='WA'ReportsTo='2' Title='Sales Representative' TitleOfCourtesy='Mrs.'/>
</rs:data>
</xml>

Displaying ADO Retrieved Data with XML Islands – Reviewing the saved file

Although the file is large, it consists basically of two parts, as shown in the browser display of this file after collapsing all the details. As seen in the next picture, the file’s two parts are the ‘Schema’ and the ‘Data’ represented by their prefixes, ‘s:‘ and ‘rs:‘ as shown in the namespaces — the first four lines in the document which have the prefix xmlns.

adoxml021.jpg

The schema section

The next picture shows just one element from the expanded ‘s‘ node in the displayed XML file in the browser. You can also see that it is updatable. This particular slice corresponds to the ‘Address‘ field of the Employees table shown in the first picture. The fields are listed alphabetically in the persisted file. The other elements also show the various attributes of the Address field. In the original table, the Address field’s Data type is text and field size is 60. The XML attribute with the prefix ‘dt’ which marks the beginning of each row shows this information. The ‘text’ has become ’string’ and the field size has become ‘maxlength.’ The schema information therefore is an accurate representation of the data structure.

The Data Section

The next section shows the only row of data taken from the data section. The prefix ‘z’ marks the beginning of the data. The XML file has only one row of the table returned corresponding to the LastName=’Peacock.

peacock1.jpg

Displaying ADO Retrieved Data with XML Islands – Data types in Access 2003 and XML file

In MS Access there are several data types that are typical to its Jet Library. In order to look at how the data goes over into XML, a table, called ‘Whimsical‘ was contrived which has all the data types but contains only a single row of data. This was opened just like the previous table and the saved file was examined. In the next picture you see the table and in the one that follows, you see the ’schema’ section. The data types, ‘bitmap’, and ‘hyperlink’ can take up a large amount of space. This one row of data saved to file takes up as much as 0.5 MB.

adoxml061.jpg

This is the ‘Schema’ section of the above file. Review each of the data types and you’ll see the corresponding dt:type in the XML file.

adoxml051.jpg

Displaying ADO Retrieved Data with XML Islands – Displaying retrieved XML in an HTML document

Creating an XML Data Island

From the previous tutorial we know that we need to embed the XML in an XML document to produce the XML Data Island. The ADO’s save() method does not produce a data island. This can be built in two steps. First of all, to associate the ‘Data’ contained in the XML to the bondable tags of the HTML, we need a basis of association. This is given by the following XML block with the id=’test.’

<XML id="test">


</XML>

In the second step, you will notice that XML is already the first tag in the saved file. Since you cannot have two XML tags, you modify the saved file by prefixing ado to xml and changing it to adoxml as shown. This will be embedded in the previous block and the resulting XML is the XML Data Island.

<adoxml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
        xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
        xmlns:rs='urn:schemas-microsoft-com:rowset'
        xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
        <s:ElementType name='row' content='eltOnly' rs:updatable='true'>
               <s:AttributeType name='Address' rs:number='8'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='Address'>
                       <s:datatype dt:type='string' dt:maxLength='60'/>
               </s:AttributeType>
               <s:AttributeType name='BirthDate' rs:number='6'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='BirthDate'>
                       <s:datatype dt:type='dateTime'rs:dbtype='variantdate' dt:maxLength='16' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='City' rs:number='9'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='City'>
                       <s:datatype dt:type='string' dt:maxLength='15'/>
               </s:AttributeType>
               <s:AttributeType name='Country' rs:number='12'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='Country'>
                       <s:datatype dt:type='string' dt:maxLength='15'/>
               </s:AttributeType>
               <s:AttributeType name='EmployeeID' rs:number='1'rs:maydefer='true' rs:writeunknown='true' rs:basetable='Employees'
                        rs:basecolumn='EmployeeID'rs:autoincrement='true'>
                       <s:datatype dt:type='int' dt:maxLength='4'rs:precision='10' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='Extension' rs:number='14'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='Extension'>
                       <s:datatype dt:type='string' dt:maxLength='4'/>
               </s:AttributeType>
               <s:AttributeType name='FirstName' rs:number='3'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='FirstName'>
                       <s:datatype dt:type='string' dt:maxLength='10'/>
               </s:AttributeType>
               <s:AttributeType name='HireDate' rs:number='7'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='HireDate'>
                       <s:datatype dt:type='dateTime'rs:dbtype='variantdate' dt:maxLength='16' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='HomePhone' rs:number='13'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='HomePhone'>
                       <s:datatype dt:type='string' dt:maxLength='24'/>
               </s:AttributeType>
               <s:AttributeType name='LastName' rs:number='2'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='LastName'>
                       <s:datatype dt:type='string' dt:maxLength='20'/>
               </s:AttributeType>
               <s:AttributeType name='Notes' rs:number='16'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='Notes'>
                       <s:datatype dt:type='string'dt:maxLength='536870910' rs:long='true'/>
               </s:AttributeType>
               <s:AttributeType name='Photo' rs:number='15'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='Photo'>
                       <s:datatype dt:type='string' dt:maxLength='255'/>
               </s:AttributeType>
               <s:AttributeType name='PostalCode' rs:number='11'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='PostalCode'>
                       <s:datatype dt:type='string' dt:maxLength='10'/>
               </s:AttributeType>
               <s:AttributeType name='Region' rs:number='10'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='Region'>
                       <s:datatype dt:type='string' dt:maxLength='15'/>
               </s:AttributeType>
               <s:AttributeType name='ReportsTo' rs:number='17'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='ReportsTo'>
                       <s:datatype dt:type='int' dt:maxLength='4'rs:precision='10' rs:fixedlength='true'/>
               </s:AttributeType>
               <s:AttributeType name='Title' rs:number='4'rs:nullable='true' rs:maydefer='true' rs:write='true'

rs:basetable='Employees'
                        rs:basecolumn='Title'>
                       <s:datatype dt:type='string' dt:maxLength='30'/>
               </s:AttributeType>
               <s:AttributeType name='TitleOfCourtesy' rs:number='5'rs:nullable='true' rs:maydefer='true' rs:write='true'
                        rs:basetable='Employees'rs:basecolumn='TitleOfCourtesy'>
                       <s:datatype dt:type='string' dt:maxLength='25'/>
               </s:AttributeType>
               <s:extends type='rs:rowbase'/>
        </s:ElementType>
</s:Schema>
<rs:data>
        <z:row Address='4110 Old Redmond Rd.'BirthDate='1958-09-19T00:00:00' City='Redmond' Country='USA'

EmployeeID='4'
                Extension='5176' FirstName='Margaret'HireDate='1993-05-03T00:00:00' HomePhone='(206) 555-8122'

LastName='Peacock'
                Notes='Margaret holds a BA in English literature fromConcordia College and an MA from the American Institute of Culinary Arts.

She was temporarily assigned to the London office before returning to her

permanent post in Seattle.'
                Photo='EmpID4.bmp' PostalCode='98052' Region='WA'ReportsTo='2' Title='Sales Representative' TitleOfCourtesy='Mrs.'/>
</rs:data>
</adoxml>

Displaying ADO Retrieved Data with XML Islands – Creating an HTML document which can display the XML Data

AdoIsland.html

In the code shown next, insert the XML data island created in the previous section and save it as AdoIsland.htm. Make sure the DATASRC attribute of the table corresponds to the ID field of the XML Data Island. The DATAFIELD attribute refers respectively to the data fields in the XML data island.

<html><head><title></title></head>
<body>
<table DATASRC="#Test">
<tr>
<tr><td>
<table DATAsrc="#Test" DATAFLD="rs:data" border="1"
bgcolor="yellow">
<tr><td>
<table DATAsrc="#Test" DATAFLD="z:row">
<tr>
<td><span DATAFLD="EmployeeID"></span</td>
<td><span DATAFLD="FirstName"></span</td>
<td><span DATAFLD="LastName"></span</td>
</tr>
</table>
</td></tr>
</table>
</td></tr>
</table>
<!--Here plug in the XML Data Island -->
</body>
</html>

Displaying the XML Data retrieved on the IE

Now if you browse the AdoIsland.htm file the display should appear as follows. If you refer to the table above, you can see that although all fields are in the XML Data Island, only three of them are called while displaying.

adoxml071.jpg

Displaying the image saved as an embedded BMP file

From the XML file you could retrieve the field for the ‘Photo’ and display the image on the browser. For this, you need to add another cell to the table and insert the following for the cell.

<td><img src=""  DATAFLD="Photo"></td>

With the above table cell added to the table, the display now appears as shown here. For this to display correctly you should have the corresponding BMP file at the same location as the AdoIsland.htm file.

adoxml081.jpg

Summary

This tutorial extends the previous tutorial to show how to access data and display it using the ADO’s save() method. An example to display the persisted data using the XML Data Island was described. More importantly, the data types in MS Access as they relate to data types in the persisted XML file were shown in detail. Similar ideas will help in accessing data from a web server with Active Server Pages as well.

Introduction to Widgets

Widget Walkthrough

A widget should be created to fill a need; it should actually do something useful. What I decided on in the end was a news reader. Every day, when I turn on my computer, one of the first things I do is to go to the BBC news website and check out the technology section headlines. I decided that my news reader would take the RSS feed supplied by the BBC and list the daily technology headlines. Thus the idea for TechFeeder was born.

The very first thing that I did was draw the main element of my widget in Photoshop (any decent graphic tool will do, but you won’t be able to use the Photoshop script if you use a different application). I won’t go into extreme detail over exactly what I did, but the tutorial I followed advised that aqua style icons are made using a layered mixture of shading, opacity and lighting effects. There are plenty of guides out there on aquifying pictures so if you’ve never created one before, I’d recommend searching for one and practicing a bit before the main event.

It took a couple of attempts before I had something that looked like I wanted it to, but soon enough I had the basic appearance that I had envisioned and settled with it. I think you’ll agree that while it isn’t perfect and has obvious flaws, it works reasonably well. Perhaps I’ll improve it for release 1.1 of my widget! While you have Photoshop open, you may as well create the image that you’ll use for the about-box for your widget. The about box should match the style of your widget if possible and list things such as the version number, author details and anything else you feel is appropriate. You can create the whole thing in Photoshop or just the background and use XML to add the text. It’s up to you, but in order to demonstrate some of the about-box capabilities, I just created the background in my image editor.

widget_background.jpg

widget_about.jpg

When you run the widget creation.jsx file, you’ll be asked to submit your name, the widget version and choose a location for the widget directory to be created. Once it has finished, you’ll need to go into the contents folder and open the .kon file in a text editor.

You should be presented with some code that looks very similar to this:

<?xml version=”1.0″ encoding=”UTF-8″?>
<widget version=”1.0″ minimumVersion=”2.0″ author=”Dan Wellman”>
<debug>on</debug>
<window title=”TechFeeder”>
<name>mainWindow</name>
<width>206</width>
<height>141</height>
<visible>1</visible>
<shadow>0</shadow>
</window>
<image src=”Resources/Shape 1.png”>
<name>Shape_1</name>
<hOffset>0</hOffset>
<vOffset>5</vOffset>
<width>206</width>
<height>136</height>
<opacity>70%</opacity>
</image>

This should make sense at first glance to anyone who’s worked with XML before. The XML declaration comes first, followed by the <widget> tag which is the container into which all other tags must be placed. Next is the <window> tag, which in this case specifies the main window. Notice that the image that makes up the main background of the widget is specified in its own <image> block, separate from (not nested within) the window element. To make the widget semi-transparent, as many are, I’ve lowered the opacity of the image. I have used a percentage here, but you could also use an integer from 0 to 255 to specify the opacity.

Introduction to Widgets – Adding Your Own Code

Now you need to start adding code yourself. What I focused on first was the about-box, which is an element used solely to display a little window listing the program version, the creator, and anything else as a programmer that you want or need to display. As I’m using content from the BBC site, I felt it necessary to include their copyright information:

<about-box>
<image>Resources/about-backg.png</image>

<about-version>
<font>Arial</font>
<size>12</size>
<style>bold</style>
<hOffset>90</hOffset>
<vOffset>45</vOffset>
<color>#ffffff</color>
</about-version>
<about-text>
<data>BBC TechFeeder</data>
<font>Arial</font>
<size>18</size>
<style>bold</style>
<color>#ffffff</color>
<hOffset>90</hOffset>
<vOffset>30</vOffset>
</about-text>

<about-text>
<data>Copyright:(C)</data>
<font>Arial</font>
<size>12</size>
<style>bold</style>
<color>#ffffff</color>
<hOffset>90</hOffset>
<vOffset>90</vOffset>
</about-text>
<about-text>
<data>British Broadcasting Corporation</data>
<font>Arial</font>
<size>10</size>
<style>bold</style>
<color>#ffffff</color>
<hOffset>90</hOffset>
<vOffset>105</vOffset>
</about-text>
<about-text>
<data>Click here for terms and conditions</data>
<url>http://news.bbc.co.uk/1/hi/help/rss/4498287.stm</url>
<font>Arial</font>
<size>10</size>
<style>bold</style>
<color>#ffffff</color>
<hOffset>90</hOffset>
<vOffset>120</vOffset>
</about-text>
<about-text>
<data>of reuse.</data>
<font>Arial</font>
<size>10</size>
<style>bold</style>
<color>#ffffff</color>
<hOffset>90</hOffset>
<vOffset>130</vOffset>
</about-text>

<about-text>
<data>By Dan Wellman</data>
<font>Arial</font>
<size>14</size>
<style>bold</style>
<color>#ffffff</color>
<hOffset>90</hOffset>
<vOffset>185</vOffset>
</about-text>
<about-text>
<data>2006</data>
<font>Arial</font>
<size>12</size>
<style>bold</style>
<color>#ffffff</color>
<hOffset>90</hOffset>
<vOffset>200</vOffset>
</about-text>
</about-box>

It’s a whopping amount of code for one small window, most of which is graphic, but it’s easy code and should make absolute sense at a glance. The about-version code actually pulls the version number from the main kon file at run time. The reason it’s so large is that at present, text in the about-box doesn’t wrap and is simply cut off at the end of the window. This is why there are so many <about-text> blocks; each line is its own separate object. The <about-version> and <about-text> blocks are listed separately, much like the <image> element above. Note that the about box must feature an image in order to function and that the bit of the text that is a hyperlink must have the <url> attribute set in the relevant code block. Once complete, the about box will appear like this:

widget_about2.jpg

Introduction to Widgets – Displaying Data

The application will be getting information from a news feed and it is going to need to display the information somewhere in order to carry out its function. I’ve created a text area to display the data for its multi-line facility, and I’ve enclosed it in a frame element primarily because of the automatic scrollbar capabilities that this element features:

<frame name=”dataframe”>
<textarea name=”datatextarea”>
<data>Loading…</data>
<font>Arial</font>
<editable>false</editable>
<color>#000000</color>
<size>12</size>
<style>bold</style>
<height>80</height>
<width>150</width>
<voffset>35</voffset>
<hoffset>30</hoffset>
<bgcolor>#cccccc</bgcolor>
<bgopacity>0</bgopacity>
</textarea>
</frame>

If you set the data element to hold the text “Loading…” this is what will be displayed when the widget first appears on screen. This is important because it takes a few seconds before the data is pulled through and parsed from the RSS feed. You’ll see in one of the functions later on that the data property of the text area is loaded after the source file has been obtained.

It’s great that the scroll bar handles, track and face are all drawn for you with absolutely no additional coding when using a frame element. You can also specify a frame element that will override this automaton and can be controlled via script. Doing this is a bit beyond the scope of this article, but such an element could be used as part of a function that automatically scrolls the text displayed in the text area.

Introduction to Widgets – Setting the Preferences

Next, I tackled the preferences. The widget engine will draw the preferences box for you and include the common options such as locking the widget’s position and setting the opacity. All you have to do is specify any additional options, and write the JavaScript to make them work:

<preference>
<name>textfontpref</name>
<defaultValue>Arial</defaultValue>
<title>Text Font:</title>
<type>font</type>
<description>Select a font for the news text.</description>
</preference>

<preference>
<name>textcolorpref</name>
<defaultvalue>#000000</defaultvalue>
<title>Text Color:</title>
<type>color</type>
<defaultValue>#000000</defaultValue>
<description>Select a colour for the news text.</description>
</preference>
<preference>
<name>textsizepref</name>
<defaultvalue>12</defaultvalue>
<title>Text Size:</title>
<type>popup</type>
<option>8</option>
<option>10</option>
<option>12</option>
<option>14</option>
<description>Select a font size for the news text.</description>
</preference>

<preference>
<name>textstylepref</name>
<defaultvalue>Bold</defaultvalue>
<title>Text Color:</title>
<type>popup</type>
<option>Bold</option>
<option>Italic</option>
<option>Narrow</option>
<option>Expanded</option>
<option>Condensed</option>
<option>Smallcap</option>
<option>Poster</option>
<option>Compressed</option>
<option>Fixed</option>
<option>No Style</option>
<description>Select a text style for the news text (it will only be applied if
supported by the font).</description>
</preference>

Widgets should be as customizable as possible; therefore, I’ve given the user control over everything that isn’t an image, which in this case is just the text from the BBC news feed. Each property you are able to change has its own segment of code. The <type> attributes of the first two preferences are used by the engine to automatically create a font chooser that previews all of your installed fonts, and a color picker, as seen in other applications.

In part two of this article I’ll show you how to wire up these preferences with a little bit of script to actually make them work. We’ll also work on the main script that makes the whole thing tick, and look at packaging and preparing the widget for upload to the online gallery.

By Dan Wellman

Creating an XUL App Installer

It is surprisingly easy to package and create an installer for a XUL application that you’ve written. Anyone who uses your application will thank you for it; it will save them a lot of time and effort. Keep reading to see how it’s done.You may have just finished working through our previous XUL tutorial, or you may have been creating applications for a while now, and find yourself in a position where you have a collection of files that when used together form a working application. You will recall that in order to use a XUL application, be that within the Mozilla browser, or as a standalone application, you need to modify certain core Mozilla files. This may be fine for you, but what about your market? Do you think people will want to download a collection of files, set up directories for them and then modify the Mozilla source files?

It’s unlikely that many people will, unless your application is targeted solely at developers that actually enjoy doing that kind of thing of course! What you need is a method of packaging all of the files needed to run your application into effectively one file that can be downloaded, double-clicked and then perform the install itself, putting the right files in the right places and updating the relevant Mozilla source files automatically.

Thankfully, XUL does provide a method of doing what we want natively; it’s called XPInstall which stands for Cross-Platform Install. The system involves the use of a JavaScript file that controls the copying of files to their destinations and the updating of the installed-chrome text file that forms part of the chrome registry. XPInstall files, that have an XPI extension, are typically deployed by a web page, which you navigate to using Mozilla and install by clicking on a link rather than by downloading an executable setup launcher. If you have downloaded an XPI file, you can also install it by dragging it into an instance of the Mozilla browser window.

Possibly the only thing that it isn’t possible for the install script to do is edit the environment variable, which is a shame, because it means that the application in this case isn’t completely automated. This can be achieved in other ways. Additionally, on systems successfully configured with XULRunner, users may not need this environment variable set anyway (I don’t know in all honesty as I haven’t tried myself). XULRunnner is a project aimed at making applications written in XUL run outside of Mozilla so that Mozilla doesn’t even need to be installed to run XUL applications. It’s still in its early stages at this point and can be tricky to configure, but it will improve. XUL programs designed to run within Mozilla don’t have the environment variable drawback.

Creating an XUL App Installer – Getting Started

I’ll be using the application created in the last XUL series as an example for this installer. If you’re not, you’ll need to adjust the file names and stuff accordingly, but the basic premise should be the same.

You will know from looking at the source files of Mozilla that most of the files needed to run any of the applications of the Mozilla suite are packed into JAR, or Java Archive, files. These archives then contain the standard directory structure of working XUL applications, making use of content, locale and skin folders. This means that your XPI file can be made up of just two files: the JAR file containing all of the XUL, RDF and other associated files, and the special JavaScript file that controls the install process.

This JavaScript file must be called install.js and is a surprisingly small and simple file when used with relatively small and simple applications. We will look at how to construct this file now. As usual when working with XUL, you’ll need nothing more complex than a text editor at this point.

First, we need to set a few variables:

appName = “XUL Edit Lite”;
author = “ProCOM”;
chromeName = “interface”;
version = “1.0″;

These variables represent information also found in the contents.rdf file located with your main application file. Next, create a variable to hold the name of the file that will be copied to the user’s system:

file = “xuleditlite.jar”;

Finally, we can save time later by creating variables to hold the information to be written to the installed-chrome file:

contentPath = “content/”+chromeName+”/”;
localePath = “locale/en-US/”+chromeName+”/”;

Creating an XUL App Installer – The Installation Process

To start the installation process, we need to initialize it and provide the chrome registry with the registry key:

initInstall(appName, “/”+author+”/”+chromeName, version);

The initInstall method takes the plain-text, or friendly, name of your application, followed by ‘/author name/application name/’ which should match the information in the main contents.rdf file.

To tell XPInstall where to copy your application files to, you use the getFolder method to obtain the target directory, and the setPackageFolder method to set it as the target directory:

installDir = getFolder(”Chrome”,”");
setPackageFolder(installDir);

The addFile method assigns a source file to be copied to the target directory. It takes just one parameter; the name of the source file:

addFile(file);

You can also use the addFolder method to assign the source files for the installation if your XPI archive contains a directory structure instead of a JAR file.

You now need to specify what information is added to the installed-chrome file, a key element of the chrome-registry. This is done using the registerChrome method which takes three parameters: what to install and how to install it, where the files can be found, and the path to the files:

registerChrome(CONTENT | DELAYED_CHROME, getFolder(”Chrome”,
file), contentPath);
registerChrome(LOCALE | DELAYED_CHROME, getFolder(”Chrome”,
file), localePath);

Note that skin packages normally reside within their own JAR archives, which is why I haven’t specified a SKIN| DELAYED_CHROME install. DELAYED_CHROME means that the new chrome will be installed once Mozilla has been restarted (when the chrome.rdf file is regenerated).

Finally, the performaInstall method is called, which actually performs the installation. This is the point where the specified files are actually copied, and the necessary file updates occur:

performInstall();

Creating an XUL App Installer – Packaging Your Files

To package your installation files into an XPI file, you can use standard archiving applications such the popular WinZip or WinRAR. You simply need to select the option to create a new archive, select an appropriate name that ends with .XPI then set the Files of Type listbox to All Files. Now choose the files to be packaged and hey presto! Your XPI archive should now exist.

As you’ll need to have a directory structure within the XPI file, I’d recommend using WinRAR as it is easier to create relative folder paths to set up the internal structure of the archive. Ensure that you set the archive type to Zip however, and not RAR or it won’t work; when you try to install it, you’ll get an error message stating “Not a valid installation package.” Note that the JAR file inside the XPI archive must also be in ZIP format or the application won’t work after the install. Once this has been done, your XPI package should appear like this:

XPI Package

The JAR file should contain folders for each element of the package, in this case, the content and locale directories:

JAR Package

Each of these folders should contain the relative paths to the application files:

Folder Structure

Once your application is packaged, there is very little else that needs to be done; you just need to focus on deployment now, which is likely to be via a web page. To run the XPI file, all you need to do is create a hyperlink to it; when the hyperlink is selected with a Mozilla browser, the installation process will begin:

Click the following link to install XULEditLite: <a href=”xuleditlite.xpi”>Install</a>

This is all you need. Mozilla will handle the confirmation or error reporting, giving you either a success dialog when the installation is complete or an error message if things go wrong. The default, unconfigured messages don’t provide much information however, so it is advisable to create your own alerts, such as one that informs the user that Mozilla will need to be restarted before the new application will be available. It may also be wise to inform users that your application (if it is anything like this one) is best run stand-alone, and therefore, should perhaps also contain instructions on how to do this.

I like to run my XUL application as a stand-alone application in its own window, rather than within Mozilla itself. Mozilla still powers my program; it just doesn’t display anything on screen. The only problem that I’ve found with this is that I have to open a command window and type out a command that will launch my application every time I want to use it. One way that I’ve got around this is to create a batch file, which is pretty much just the same command to launch the program typed into a text file and saved with a .bat extension. Linux users will know these files as shell scripts.

Add the following code to a text file and save it appropriately:

START mozilla -chrome chrome://interface/content

This will effectively create an executable that will launch your application without the need for manual intervention. As part of the installation process, it would be relatively simple to assign this file to be installed to the desktop instead of the chrome directory to go that extra mile for the end user.

So you have seen how easy it is to package and create an installer for a XUL application that you have written. You’ll find that knowing about packing makes things easier when creating skins as well, as downloadable skins for Mozilla or other XUL applications are also packaged in this way and installed using XPInstall. All in all, the various elements that make up the packaging and installation medium are an excellent way of going about things. Everything is open source and relatively straight forward.

The Why and How of XML Data Islands

This article explains a useful way to embed data in an HTML document, and store it on the client, using XML. With XML becoming ever more pervasive and the client side implementation gaining a lot of ground, you will probably find yourself using this technique in many projects.

Introduction

What is an XML data island? Simply stated it is data in the form of XML embedded in an HTML document. By embedding XML data you create an XML data island, thereby storing your data on the client. This is not good enough. You also want to know how to access it. The HTML elements on the page can be bound to the XML data island and make them come to life, on the client. In reality an XML data island represents a built-in Data Source Object in the IE browser. This means you do not need <object/> tags to embed the control.

Example describing an XML data island

First of all, to get a handle on XML data islands, let us start with a simple HTML file, Simple.htm, with some embedded XML. Of course, you can create your own XML file, but for this tutorial please follow the code shown in the next paragraph. For the embedded XML file, the webstudents.xml file used in our other tutorials will be used. This is how this XML is displayed by the parser on the IE. In the HTML file the XML data island is a different color.

island05.jpg

Simple.htm

<HTML>
<HEAD>
<TITLE> </TITLE>
</HEAD>

<BODY>
<h3>Html file with embedded XML</h3>
<P>Here begins the XML Data Island</P>
  <xml id="WebStudents">
<wclass>
<!-- My students who attended my web programming class -->
<student id="1">
<name>Linda Jones</name>
<legacySkill>Access, VB5.0</legacySkill>
</student>
<student id="2">
<name>Adam Davidson</name>
<legacySkill>Cobol, MainFrame</legacySkill>
</student>
<student id="3">
<name>Charles Boyer</name>
<legacySkill>HTML, Photoshop</legacySkill>
</student>
<student id="4">
<name>Charles Mann</name>
<legacySkill>Cobol, MainFrame</legacySkill>
</student>
</wclass>
</xml>  <P>Here ends the XML Data Island</P>
</BODY>
</HTML>

When you display this page in the browser, what you will see is only this. There is nothing to indicate that something is embedded.

island01.jpg

If you review the embedded XML file you notice that it has an id called “WebStudents.” You also notice that it has well formed XML content. The data content of this file includes the student ids, student names and their skill sets.

The Why and How of XML Data Islands – Getting the names of students

It was mentioned that the XML data island represents the built-in Data Source Object DATASRC, which is identified by the id property. Associated with the data source are its fields, which are identified by the DATAFLD property. For example, the student “Linda Jones” will fit in as a DATAFLD. Let’s add the following HTML code to this file:

<table DATAsrc="#WebStudents">
<tr>
<td><span DATAFLD="name"></span></td>
</tr>
</table>

and call the new file Basic.htm, whose source is shown in the next paragraph:

Basic.htm

<HTML>
<HEAD>
<TITLE> </TITLE>
</HEAD>
<BODY>

<h3>Html file with embedded XML</h3>
<P>Here begins the XML Data Island</P>
 <xml id="WebStudents">
<wclass>
<!-- My students who attended my web programming class -->
<student id="1">
<name>Linda Jones</name>
<legacySkill>Access, VB5.0</legacySkill>
</student>
<student id="2">
<name>Adam Davidson</name>
<legacySkill>Cobol, MainFrame</legacySkill>
</student>
<student id="3">
<name>Charles Boyer</name>
<legacySkill>HTML, Photoshop</legacySkill>
</student>
<student id="4">
<name>Charles Mann</name>
<legacySkill>Cobol, MainFrame</legacySkill>
</student>
</wclass>
</xml>
 <P>Here ends the XML Data Island</P>  <table DATAsrc="#WebStudents">
<tr>
<td><span DATAFLD="name"></span></td>
</tr>
</table>  </BODY>
</HTML>

In the above added snippet, you have identified the DATASRC as “#WebStudents” and out of the three elements, student id, name, and legacySkill you have opted to show only the “name.” Now if you browse the file Basic.htm, your display will appear as shown in the next picture. Although you have only a single <td/> element, you have all the rows of data.

island02.jpg

The Why and How of XML Data Islands – Showing the complete data
(Page 3 of 4 )

You may complete this picture by adding the other two DATAFLDs, namely student id and legacySkill, and your display would be as shown in the next picture. Some additional formatting has been added to make the display a little more jazzy. You may also notice that the data may be accessed in any order and need not follow the same one as in the original XML. If you choose not to show this data, you may leave them out as in Basic.htm.

island03.jpg

Referencing an XML file on a web server

In Simple.htm the XML file was hard coded into the page. Instead of this you may also reference a file on the web server by referencing its “src” property as shown in the next snippet.

<xml DATAsrc=”WebStudents” src=”http://localhost/webstudents.xml” ></xml>The source of the htm file, Basic2.htm with XML being referenced to a file saved on the web server, is shown in the next paragraph.

Basic 2.htm

<HTML>
<HEAD>
<TITLE> </TITLE>
</HEAD>
<BODY>

<h3>Html file with embedded XML</h3>
<P>Here begins the XML Data Island</P>
 <xml id="WebStudents" src="http://localhost/webstudents.xml"></xml>
 <P>Here ends the XML Data Island</P>
 <table DATAsrc="#WebStudents" border="1" bgcolor="powderblue">
<tr>
<td><span DATAFLD="name"></td>
<td><span DATAFLD="id"></td>
<td><span DATAFLD="legacySkill"</td>
</tr>
</table>
 </BODY>
</HTML>  

The Why and How of XML Data Islands – HTML tags that can be bound to an XML island
(Page 4 of 4 )
An HTML table is but one of the elements for which you can bind data from an XML data island. Here are a few examples that should work.

The Button object

<input type=”button” DATAsrc=”#WebStudents” DataFld=”name”/>
will show up when browsed as:

button.jpg

The Textbox object

<input type=”text” DATAsrc=”#WebStudents” DataFld=”name”/>
will show up as:

textbox.jpg

The Span tag

<span DATAsrc=”#WebStudents” DATAFld=”legacySkill”></span>
will show up as:

span.jpg

The DIV tag

<div DATAsrc=”#webstudents” DataFld=”name”/></div>

div.jpg

The marquee tag

<marquee DATAsrc=”#WebStudents” DataFld=”name”> </marquee> caught at a fixed location as:

marquee.jpg

Summary

This tutorial considered embedding a well formed XML fragment into an HTML file to create an XML data island and showed how one could access data embedded in the XML file. The tutorial also showed the different HTML tags to which the data from the XML data island can be bound. With XML becoming ever more pervasive and the client side implementation gaining a lot of ground, a working knowledge of XML data islands is deemed essential; this tutorial is addressed to provide such a background. The browser specific nature of the source code makes it necessary to hide the XML island from non-IE browsers. This concern is not addressed in the tutorial.

Roaming Through XMLDOM: An AJAX Prerequisite

The twin tasks of the XMLHttp are handling the HTTP request, and then processing the XML response. The first one is easily done by writing the appropriate syntax for creating this object. This is what is accomplished in AJAX by invoking the new constructor for XMLHTTP object. This is but one of the objects of the XMLDOM -XML Document Object Model. In this article, we look at XMLDOM in some detail before calling the XML document in an AJAX rendition in a future article.

A quick look at XMLDOM

The DOM of HTML and XMLDOM share some common traits. The basic precept that documents are hierarchically structured with nodes and nested nodes is common to both of them. The DOM object model as seen in W3C documentation is described in full here.

XMLDOM can be understood through two types of metaphors, a tree representation and a family representation. In the tree representation, the tree has nodes. Nodes can have other nodes growing out of them, or a node can stand by itself without any other nodes sprouting from it. In the family metaphor you have parents, children, siblings, and so on.

Accessing XML via XMLDOM is facilitated by ActiveX. All that is needed is to create a new ActiveXObject, via the call:

var xml_doc=new ActiveXObject (”Microsoft.XMLDOM”);

Once this is created, an XML document from a given location can be loaded. Then we can look at the various properties of this object as detailed in the XMLDOM. The following listing gives a brief description of the XMLDOM objects that are well suited for client side scripting.

In XMLDOM as well as HTML’s DOM the following interfaces are used for accessing. In the present tutorial we will only look at a subset of the properties and methods of the highlighted objects.

  • Attr
  • CharacterData
  • Comment
  • DocumentFragment
  • Document
  • DOMException
  • DOMImplementation
  • Element
  • Node
  • NodeList
  • NamedNodeMap
  • Text

Document

Document is the root of the XML document.

ElementThe element object represents the Document’s various elements, such as root and other elements.

Node“Node” is a single node in the document tree representation. This has support for data types, namespaces, DTDs and XML Schemas.

Attribute“Attribute” represents the single attribute node of an element.

Text“Text” represents the text of an element or attribute.

Roaming through XMLDOM: An AJAX Prerequisite – Getting at the Innards of an XML Document

We will briefly look at some of the XML Dom objects. In order to show how the code accesses the various parts of a document, consider the following well formed XML document WebClass.xml which is located on my hard drive at:

C:/Documents and settings/computer user/Desktop/todo/Ajax/WebClass.xml.

XML document probed

<?xml version="1.0" encoding="ISO-8859-1" ?><wclass>

<!-- My students who attended my web programming class -->

<student id="1">

<name>Linda Jones</name>

<legacySkill>Access, VB5.0</legacySkill>

</student>

<student id="2">

<name>Adam Davidson</name>

<legacySkill>Cobol, MainFrame</legacySkill>

</student>

<student id="3">

<name>Charles Boyer</name>

<legacySkill>HTML, Photoshop</legacySkill>

</student>

<student id="4">

<name>Charles Mann</name>

<legacySkill>Cobol, MainFrame</legacySkill>

</student>

</wclass>

Slicing the XML document

First things first: we need to instantiate an XMLDocument object. This is done easily by running the following code as shown:

<SCRIPT LANGUAGE="JavaScript">var xml_doc = new ActiveXObject("Microsoft.XMLDOM");

xml_doc.async = false;

xml_doc.load ("C:/Documents and settings/computer user/Desktop/todo/Ajax/WebClass.xml");

</SCRIPT>

After this step we will look at a number of properities that can be accessed using code.

First Child and Last Child Properties

These properties can be accessed if you insert the following lines after loading the document as shown above but before </Script>,

document.write ("This documents first child is a " +xml_doc.documentElement.firstChild.nodeName);

document.write("<br>");

document.write ("This document's  last child= " +

xml_doc.documentElement.lastChild.nodeName);

and if you display it in a browser you would see the following:

This documents first child is a #commentThis document's last child= student

Roaming through XMLDOM: An AJAX Prerequisite – Continuing the Dissection
Document Element Properties

The Document element has a child nodes collection you can access by iterating through the index. You can also access the attributes, which consist of a name and a value as shown here. The following code should be inserted after creating the XMLDOC object.

document.write("<br>"+xdoc.documentElement.childNodes.item(0).text +"<br>");document.write("<br>"+xdoc.documentElement.childNodes.item(1).

attributes[0].name +"<br>");

document.write("<br>"+xdoc.documentElement.childNodes.item(1).

attributes[0].value +"<br>");

When the above snippet is run you would see the following.

My students who took web programming class with meid

1

Nodes Collection

In the document we are looking at, we have a number of student nodes. We can get a reference to the student nodes using the getElementsByTagName method. From this we can find the number of such student nodes. Once we know how many there are (nodes.length), we can iterate through the collection and find the individuals as shown in the following code.

var nodes=xdoc.getElementsByTagName("student");document.write("<br>Number of student nodes is "+nodes.length+"<br>");

for (i=0; i< nodes.length; i++)

{document.write("<br>"+nodes.item(i).text+"<br>");}

If you were to include the code in the script after instantiating the xdoc object you would see the following:

Number of student nodes is 4Linda Jones Access, VB5.0

Adam Davidson Cobol, MainFrame

Charles Boyer HTML, Photoshop

Charles Mann Cobol, MainFrame
Node’s name, type and value

Once you locate an element’s child node through its collection, as in the declaration of Elem in the next snippet, you could determine its name, type and value by calling respectively the nodeName, nodeType and nodeValue properties as shown.

var Elem=xdoc.documentElement.childNodes.item(2);document.write("<br>"+Elem.nodeName+"<br>");

document.write("<br>"+Elem.nodeType+"<br>");

document.write("<br>"+Elem.nodeValue+"<br>");

We have located the second child and its properties by running the above script as shown.

student1

null
Family metaphor related items

As mentioned earlier, in addition to the tree representation (tree metaphor) there is also the family representation (somewhat seniority based). These are usually parent, sibling, previous sibling, next sibling, and so on. The next few lines of code will give you an idea how we may access them. We will be starting with the second student whose id=2.

//second student is referenced.var midElem = xdoc.documentElement.childNodes.item(2);

document.write("<br>"+midElem.attributes[0].value+"<br>");

document.write("<br>"+midElem.previousSibling.text+"<br>");

document.write("<br>"+midElem.nextSibling.text+"<br>");

document.write("<br>"+midElem.parentNode.nodeName+"<br>");

document.write("<br>"+midElem.parentNode.nodeType+"<br>");

document.write("<br>"+midElem.parentNode.nodeValue+"<br>");

When the above code is inserted after instantiating xdoc as described previously, you would see the following displayed.

2Linda Jones Access, VB5.0

Charles Boyer HTML, Photoshop

wclass

1

null

Roaming through XMLDOM: An AJAX Prerequisite – Manipulating the XML Document
(Page 4 of 4 )

The XMLDOC object also has a large number of methods that can be invoked to create, modify, and delete nodes. The document object represents the XML file in its entirety and is also a node in the DOM. It has a large number of properties and many methods. For complete documentation the reader is referred to the W3C site. In addition to W3C there are also Microsoft extensions.

Adding a new student to the web class

Being a node, XMLDOC shares the properties of the nodes as well. A complete usage of the methods is not attempted, but a few examples are shown as related to the XML document we have been considering, the WebClass.xml file. XMLDOC object’s methods will be invoked to add another student to the web class file. This is what a student node looks like. We will add another student according to this scheme.

<student id="1">  <name>Linda Jones</name><legacySkill>Access, VB5.0</legacySkill>

</student>

Looking at the node, student, we see that in order to add a new student node we need to add the name and legacySkill child nodes. Also we need to add the attribute Id and give a value to it. Finally we need to add the proper texts for the name and legacySkill nodes.

We assume that the new student will have:

id –> 7
name–>John Doe
legacySkill–>Fortran, Soroban
The code for adding the new student is as follows:

//This creates a new student:
var newElem= xdoc.createElement(”student”);

//This line creates the attribute to the new student:
var newAtt=newElem.setAttribute(”id”,7);

//The next two lines creates elements name and legacySkill
var part1=xdoc.createElement(”name”);
var part2=xdoc.createElement(”legacyskill”);

//The next two lines create the required text for the nodes:
var newText1=xdoc.createTextNode(”John Doe “);
var newText2=xdoc.createTextNode(”Fortran, Soroban”);

//Appending the name and legacySkill to the student node
var part11=newElem.appendChild(part1);
var part21=newElem.appendChild(part2);

//Adding the text content to the name and legacySkill nodes
part11.appendChild(newText1);

part21.appendChild(newText2);

In this fashion you build the tree so that the node is defined according to the blueprint from the XML document. This completes the building of the student node.

Verifying the new student information

In order to verify, we again invoke the XMLDOC’s properties as shown in the early part of this tutorial. In particular we will be using the following code to verify:

//We created newElem and the node’s name is given by: document.write(newElem.nodeName);

//We get the following result for this line:
student

//We have not added the newElem to xdoc and presently the number of //nodes in xdoc are given by:
var totalnodes=xdoc.getElementsByTagName(”student”);
document.write(”<br>”+totalnodes.length);

//the result of this code gives the number of student nodes in xdoc:
4

//We look at the attributes of the new student node:
document.write(”<br>”+ newElem.attributes[0].name);
document.write(”<br>”+ newElem.attributes[0].value);

//We get the following result for the above code snippet:
id
7

//We now grab the text for the entire student node:
document.write(”<br>”+newElem.text);

//This snippet gives the following browser display:
John Doe Fortran, Soroban

//Now we get a reference to the last child of the xdoc before adding the //new student:
var lastnode=xdoc.lastChild;

//This is important. We add the newElem student node to the xdoc:
lastnode.appendChild(newElem);

//We now count the number of nodes in the new document which have //the student nodes:
var totalnodes=xdoc.getElementsByTagName(”student”);
document.write(”<br>”+totalnodes.length);

//The result of this in the browser display is:
5

This verifies that the new student has been added (we started out with 4). The file can be saved using the save (ObjTarget) method of the XMLDOC object.

Summary

Understanding and manipulating the XMLDOM objects is a prerequisite to writing successful code, whether it be for AJAX or for anything to do with XML files especially using Microsoft tools. It is the author’s hope that the surgical presentation of this tutorial in dissecting the XMLDOM object will provide a guide to this understanding. XMLHTTP request is another object belonging to the XMLDOM; it is discussed in a previous tutorial and will be revisited again in discussing the responseXML method of the request object.

Step by Step to AJAX

AJAX has been exciting many programmers as the latest and greatest thing in web development. This article takes a step-by-step look at the Microsoft way to script for AJAX.

Introduction This tutorial is not about Ajax Telamon from the Iliad who fought Hercules, but the latest and greatest (at least in the opinion of some) thing in web development. Ever since Google charmed the web at large with those AJAX-created Google Maps apps, the number of amount of adherence to AJAX has been growing exponentially. In this tutorial, we look mainly at the Microsoft way of scripting for AJAX. Like my previous tutorials, it’s step by step all the way after a brief introduction.

Web Application EvolutionSince 1992 developers have relentlessly pursued ways to make the web more appealing, more productive and more interactive. The plain text html at birth soon saw embedded images followed by appealing colors conferred by cascading style sheets. But it was left for JavaScript to bring user interaction, and thus began the heydays of scripting languages.

However, there were two major browsers sharing the web space, and two scripts to serve the user (the third, ECMA came later). This was not enough, and DHTML was born – not a new language, but a good mix of html, CSS, and JavaScript that made user interaction extremely satisfying.

AJAX came along to make the interaction more responsive without needing to refresh the page. AJAX is an acronym, and the credit for coining this name goes to Adaptive Path’s S. S. Garret. However, Microsoft appears to be the progenitor, with its flagship ActiveX Technology making this possible. Now it is a mélange of XHTML, CSS, JavaScript, XmlHttpRequest, and XML, and its DHTML déjà vu all over.

Step by Step to AJAX – Ajax’s Model of Interaction

The figure shown next is derived from Garret’s article on Ajax, redrawn to render it horizontally. The figure shows both the prior art (classic interaction) as well as the AJAX embodiment. In the classic version, the client sends an HTTP(S) request to the server, the server checks to see whether any server side processing is to be carried out, processes the server related instructions and sends back the html with CSS, if it is defined. There is a synchronicity between client request and server response.

In the AJAX model, the client sends a JavaScript to AJAX, and AJAX sends the HTTP(S) request to the web server which can also serve XML. The web/XML server sends back the result in the form of XML, and AJAX relies on the Document Object Model (DOM: blue print of web document) to transmit the result in XHTML and CSS. It does so by reading the returned XML’s node tree using DOM. The interaction could be synchronous or asynchronous.

AJAX

Step by Step to AJAX – XmlHttpRequest

One of the key objects needed for working with AJAX is the XMLHttpRequest Object. This object does two things: it handles the httpRequest, and then it processes the XML response. This was implemented in Internet Explorer 5 for Windows as an ActiveX Object. This has been implemented by Mozilla 1.0, Apple and others in compatible forms. The W3C has similar standards for the DOM Level 3 specification. We will take a brief look at this object before we put it to work. Some of the highlighted methods and properties are later used while fetching a web page to show what values they do return.

Creating the XML HttpRequest objectThis is the easy part, if you need to deal only with Microsoft IE. For Mozilla you would instantiate the object using the following syntax:

var xhr=new XMLHttpRequest();

where as for IE you would use the following:

var xhr=new ActiveXObject(”Microsoft.XMLHTTP”);

Both of these methods create an object which is hidden from the user. Its methods and properties take control of the server interaction. For cross browser applications you need to come up with a branching syntax. This is not so difficult; see for example the cross-browser boiler plate code (Listing 2.0 in the link).

Step by Step to AJAX – XMLHttpRequest Object Methods

This short list of methods is shared by all supported browsers. In this tutorial we shall look at some of the highlighted methods.

abort()
current request is stopped
getAllResponseHeaders()
returns a string containing information of headers
getResponseHeader (”headerlabel”)
returns a string containing information about a single header
open(”method”, “URL”[,asyncFlag[,"userName"[,"password"]]])
assigns various request attributes
send(content)
Transmits the data with information that may be posted, if needed
setRequestHeader (”label”, “value”)
assigns label, value pair for the header

While open() and send() are most often used, the others are also useful in some cases. The open() method begins the interaction and takes two mandatory arguments; the “method” used to open, which is either GET or POST, and the URL to which the request is made.

The GET and POST methods are similar to those used in ASP, as some of you might recognize. The GET is indicated for retrieving read only data while POST is for sending data to the server.

The URL could be complete, or a relative URL.

The third parameter which is optional (default value TRUE being asynchronous) sets the interaction to be synchronous (FALSE) or asynchronous (TRUE). If you choose the synchronous route, the script waits for the response to arrive before acting. The useful mode is to set the interaction to be asynchronous and use the onreadystatechange event (to be discussed) to get at the response.

XMLHttpRequest Object PropertiesThe following read only properties are browser agnostic (all supported browsers understand them).

onreadystatechange
Event handler which fires every time the state changes
readState
Integer representing the status of the object
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete
responseText
Data returned in string format
responseXML
Data returned in DOM Compatible format
status
Numeric code returned by server indicating status
404: Not found
200: OK
statusText
Message string that came with the status

Step by Step to AJAX – Fetching a page using AJAX

Working with AJAX is quite simple. The code will be explained by explaining the component parts with reference to an html file, AjaxTest.htm. First you need to create an XMLHttpRequest Object along the lines discussed above. Then you make a request, in this case pass an URL as an argument to the getPage() function. Since you are getting back a page you just need to use the GET argument. Since an asynchronous interaction is intended, use TRUE for the third argument in the open() method.

Before the open() method is called the onreadystatechange eventhandler calls the statusCheck() function, where the readyState of the request is verified and the status code is verified to return OK. Both of these functions are in the <Head/> and are evaluated before the rest of the page is loaded. Review the two functions just described for the html page AjaxTest.htm. Some of the properties and methods previously described and highlighted are also returned. The script that follows this paragraph is in the <head/> section of AjaxTest.htm.

You also include code to alert you if, for some reason, the XMLHttpRequest object instantiation failed. It also needs to alert the user if the request failed because the page was unavailable, or the server was not responding, or for any other reason.

If the status is OK and the readyState shows completion, then you get the response, for this example, in the text format. Now you invoke the DOM API to get the element whose ID=”x”, in this case the <div/>, and set its innerHTML property the same as the returned text. If you look at the response produced by the alert(xhr.responseText) you would see the html of the page you requested as shown in the next picture. I particularly like the preference to use the ECMA scripting style.

<SCRIPT LANGUAGE=javascript>
<!--
var xhr = false;
function getPage (url) {
xhr = false;
//this is the Microsoft browser compatible instantiation
xhr = new ActiveXObject("Microsoft.XMLHTTP");
if (!xhr) {
alert ('XMLHttpRequest failed to instantiate');
return false;
}
xhr.onreadystatechange = statusCheck;
xhr.open ('GET', url, true);
xhr.send (null);
}
function statusCheck() {
txt1.value="XmlHttpRequest_Status: " + xhr.status;
txt2.value="XmlHttpRequest_readyState: " + xhr.readyState;
TEXTAREA1.value="XmlHttpRequest_getallResponseHeaders(): " +
xhr.getAllResponseHeaders();
txt5.value="XmlHttpRequest_statusText: " + xhr.statusText
if (xhr.readyState == 4) {
if (xhr.status == 200) {
alert(xhr.responseText);
document.getElementById("x").innerHTML =(xhr.responseText);
} else {
alert ('There was a problem with the request.');
}
}
}
//-->
</SCRIPT>

Alert

However, when you use the DOM API, you get the following as shown:

AJAX Test

The <body/> of the AjaxTest.htm consists of just the following controls so that the properties, the methods and their values can be displayed. The onclick event starts the process rolling. Of course the <div/> is where the innerHTML property gets written. The html for these controls is as shown:

<P><STRONG><SPAN
style="FONT-SIZE: large; COLOR: red">A</SPAN>synchronous <SPAN
style="FONT-SIZE: large; COLOR: red">J</SPAN>avascript <SPAN
style="FONT-SIZE: large; COLOR: red">A</SPAN>nd <SPAN
style="FONT-SIZE: large; COLOR: red">X</SPAN>ML= <SPAN
style="FONT-SIZE: large; COLOR: blue">AJAX</SPAN></STRONG></P>
<P>
</P>
<P> </P>
<P><INPUT id=button1 type=button
onclick="getPage ('http://xphtek/TestXMLHttp/Greeting.asp')"
value="Get the page by XmlHttpRequest" name=button1></P>
<P><INPUT id=txt1 style="WIDTH: 396px; HEIGHT: 22px" size=51></P>
<P><INPUT id=txt2 style="WIDTH: 395px; HEIGHT: 22px" size=50></P>
<P><TEXTAREA id=TEXTAREA1 style="WIDTH: 393px; HEIGHT: 72px"
name=TEXTAREA1 cols=42></TEXTAREA></P>
<P><INPUT id=txt5 style="WIDTH: 389px; HEIGHT: 22px"
size=50></P>
<div id="x"></div>

As previously mentioned you can reference the URL completely, as in http://xphtek/TestXMLHttp/Greeting.asp or simply by its relative URL Greeting.asp. The Greeting.asp page is a simple page as shown:

 <%@ Language=VBScript %>
<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
<script language="javascript">
document.write (document.lastModified);
</script>
</HEAD>
<BODY>
<%Response.Write("<b>Welcome to programming with AJAX</b>")%><br>
<% =Date()%><br>
Hello<br>

</BODY>
</HTML>

Summary The tutorial has looked at the various properties and methods of this interesting XMLHttpRequest object. It goes without saying that the browser should support JavaScript, and as a developer you should appropriately warn the user to enable JavaScript, if it is not. For Microsoft IE there is the additional requirement of browser support for ActiveX objects.

For recent browsers the older method of using iframes to update parts of a page will be replaced. However iframes may still find favor with much older browsers. In this tutorial we saw most of the properties, but the lastmodified property returned null; the syntax was double checked but to no avail. Although AjaxTest.htm was coded on Visual Interdev 6.0, it is not a requirement; plain Notepad should work as well.

Overlays in XUL

Overlays are an important aspect of XUL, but this is a subject that I’ve barely mentioned in previous articles. Overlays can be used for a variety of purposes when designing/writing XUL applications and come in either explicit or dynamic flavors. Explicit overlays are used within your own application and form the basis of code modularization.If you are creating a large application with several windows, local overlays can be used to share common elements between the various windows; if for example you have two windows in your application and both of them have a file menu, rather than having the file menu code in both of the windows, you can define an overlay and then share this one file between both windows. This centralizes the code for the file menu and makes updating/extending the menu much easier because code changes are only required in one place. The Mozilla suite of applications makes extensive use of overlays for this very purpose, with all of the main applications in the suite sharing many of their menus and functionality.

When creating XUL applications, remember that if you need a file menu in your application, you can easily make use of the Mozilla overlay for this feature and cut down massively on the amount of coding you need to do (I’ve avoided this in previous tutorials as it is counter-productive to the learning process when getting to know and understand XUL).

Dynamic overlays work in a subtly different way and can be used to add additional content to an existing application at runtime.  If you write an application designed to run as an add-on to the navigator part of the Mozilla suite, you are going to want to perhaps add a menu item to launch it or control it, and to do this without having to modify the Mozilla source files you use a dynamic overlay to add the additional content at run-time.

The main files of a XUL application are known as the base files; the master, or default, skin is called the base skin and shares the same name as the base XUL file.  In the application developed in earlier XUL tutorials the base XUL file is called interface.xul and the base skin file is called interface.css for example.  Overlay files should share the name of the application they are used with, with Overlay at the end: interfaceOverlay.xul for example, would be appropriate.

You can use any element within an overlay, and when the overlay is processed the children of the overlay element become the children of the element the overlay targets.  By default these children are placed below the children of the targeted element, so in a dynamic overlay an additional menu item would appear after the existing items in the targeted menu, although this can be changed with the use of attributes to specify where in the element tree the overlaid children appear.

Overlays in XUL – Creating an overlay

Creating overlays is easy; you still need the XML declaration and the XUL namespace is added as an attribute of an <overlay> element instead of a <window> element.  Elements within the overlay file should have an ID attribute which is used to match the overlaid content with the main application.  Create a XUL file that contains the following code:

<?xml version=”1.0″?>
<overlay xmlns=”http://www.mozilla.org/keymaster/gatekeeper/
there.is.only.xul”>
<menu id=”overlaidMenu”>
<menupopup id=”newPopup”>
<menuitem id=”menuitem1″ label=”New item 1″/>
<menuitem id=”menuitem1″ label=”New item 2″/>
<menuitem id=”menuitem1″ label=”New item 3″/>
<menuitem id=”menuitem1″ label=”New item 4″/>
</menupopup>
</menu>
</overlay>

Now save this file into the content folder of your application with a filename of newmenuOverlay.xul.  Next, we need to import the overlay content into the main XUL file of the application; in this case, I am using the XUL editor created in previous articles as an example.  Near the top of the file, add the following processing instruction:

<?xul-overlay
href=”chrome://interface/content/newmenuOverlay.xul”?>

Finally, in the location that you would like the new menu to appear, add this code:

<menu id=”overlaidMenu” label=”New Menu”/>

As you can see, the ID of the element in both the overlay file itself, and the final line of code in the main application file are the same.  Notice also that the overlay file is understood and processed by Mozilla using a chrome URL, even though we haven’t registered the overlay with the chrome in the same way that we have had to register some of the other key elements of the application such as the DTD and skin files.  The chrome is intelligent enough to pick these up without special instructions.

Overlays in XUL – Adjusting the overlay to your application
If you use a locale with your application and read in things like menuitem labels, you should do the same with any overlays, so in this example, I should change the menu code within the overlay file to something like:

<menuitem id=”menuitem1″ label=”&newlabel1;”/>
<menuitem id=”menuitem1″ label=”&newlabel2;”/>
<menuitem id=”menuitem1″ label=”&newlabel3;”/>
<menuitem id=”menuitem1″ label=”&newlabel4;”/>

Then create a new DTD file with the code:

<!ENTITY newlabel1 “New item 1″>
<!ENTITY newlabel2 “New item 2″>
<!ENTITY newlabel3 “New item 3″>
<!ENTITY newlabel4 “New item 4″>

This DTD file should be saved with the name newmenuOverlay.dtd to match the overlay file and should be saved in your existing locale directory.  This way, you won’t have to register the new DTD file with the chrome either; although before it can be used, you’ll need to add the following DOCTYPE declaration to your newmenuOverlay.xul file:

<!DOCTYPE overlay SYSTEM
“chrome://interface/locale/newmenuOverlay.dtd”>

So now, any window that needs to contain this menu can simply have the statement that imports the overlay, and an ID matched menu element (or whatever element is being overlaid), and it can make use of the overlay file.  This is also the same means by which files can be taken from Mozilla itself to cut down on the amount of coding that is required.  You know that Mozilla is going to be installed on the end users system in order for XUL to work, so when creating XUL applications for deployment, you can rely on being able to borrow elements like these from Mozilla.

Overlays can also overlay other overlay files as well as JavaScript or CSS files, so when using Mozilla content in your own applications not only can you overlay the elements used to build the desired menus, you can also use overlays to import the functionality which can cut down massively on the amount of coding you need to do, especially when it comes to some of the complicated XPCOM interfaces that are required in order to build things like the file open/save functionality that is often required in applications.

Overlays in XUL – Creating a dynamic overlay

Creating dynamic overlays is very similar to creating explicit overlays; although this time the overlays do need to be registered fully with the chrome in order to instruct Mozilla to apply the overlay files to the target application. With this method, the source file of the application that has the overlay applied to it doesn’t need to be modified.  This makes it an excellent method of creating updates or add-ons to an application that are fully packaged and made available for distribution or download.  It also means that you can create add-on components to Mozilla itself without modifying Mozilla’s source code.

You could add a menuitem to one of Mozilla’s menus in this way so that an application you’ve written can be accessed easily.  To do this, you first create the main overlay file, like you would any other overlay by starting with the XML declaration and the overlay container:

<?xml version=”1.0″?>
<overlay id=”xuleditOverlay” xmlns=”http://www.mozilla.org/keymaster/gatekeeper/
there.is.only.xul”>

As the menuitem is to be used to open your application, you’ll need a little bit of JavaScript to do this.  Normally this would go into its own JS file, but as it’s just the one little function, there’s no harm in adding it in here:

<script type=”application/x-javascript”>
function openXulEdit() {
window.openDialog(’chrome://interface/content/’, ‘_blank’,
‘chrome,dialog=no’);
}
</script>

This simple little script calls the openDialog method and takes, most importantly, the relevant chrome URL and two additional parameters.

All you need now is the new menuitem that you want added to Mozilla and the closing tag:

<menupopup id=”windowPopup”>
<menuitem label=”XUL Edit Lite 1.0″ oncommand=”openXulEdit
();” insertbefore=”sep-window-list”/>
</menupopup>
</overlay>

The menupopup ID must match that of the menupopup in Mozilla that you want to influence, in this case, the Window menu.  The oncommand attribute calls our little JavaScript snippet and the insertbefore attribute tells Mozilla to add the new menuitem right before the separator (take a look at the Window menu in Mozilla to see the separator I mean).  Save this file as xuleditOverlay.xul in your main content directory.  Next, you need to add a couple of lines of code to your existing main contents.rdf file:

<RDF:Seq about=”urn:mozilla:overlays”>
<RDF:li resource=”chrome://communicator/content/tasksOverlay.xul”/>
</RDF:Seq>
<RDF:Seq about=”chrome://communicator/content/tasksOverlay.xul”>
<RDF:li>chrome://interface/content/xuleditOverlay.xul</RDF:li>
</RDF:Seq>

The first code block lists the file that you are going to overlay, the second lists the file to be used as the overlay.  Add these just before the closing </RDF:RDF> tag.

Finally, you need to browse to the Mozilla Chrome directory and delete the folder called “overlayinfo.”  This directory will be recreated when Mozilla is next launched, so launch Mozilla and go into the overlayinfo directory.  There will be several folders in here depending on which Mozilla suite components are installed; if you go into the one called communicator, then into the content folder, you’ll find an overlays.rdf file.  Open this file in a text editor and if everything worked, there will be an Li statement that matches the one you just added to your applications contents.rdf file. One final check that it has worked of course is to open the Window menu in Mozilla to check that your overlaid menuitem appears and that it launches your application when selected.

In addition to adding content to Mozilla without altering the base files of the applications, this is the same mechanism that you can use to release additional or add-on content to your own XUL applications once they have been distributed.  You could simply create a new XUL module for your application and then package it in an installer that adds the required files and the new contents.rdf file to the existing directory structure.

So as you can see, overlays are an important aspect of XUL that can be used to add modularity to the bigger applications you create or add to the functionality of either Mozilla itself, or applications that you write.