- XML Reference Guide
- Overview
- What Is XML?
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Table of Contents
- The Document Object Model
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- DOM and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- Implementations
- DOM and JavaScript
- Using a Repeater
- Repeaters and XML
- Repeater Resources
- DOM and .NET
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Downloads
- DOM and C++
- DOM and C++ Resources
- DOM and Perl
- DOM and Perl Resources
- DOM and PHP
- DOM and PHP Resources
- DOM Level 3
- DOM Level 3 Core
- DOM Level 3 Load and Save
- DOM Level 3 XPath
- DOM Level 3 Validation
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Implementations
- The Simple API for XML (SAX)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- SAX and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- SAX and .NET
- Informit Articles and Sample Chapters
- SAX and Perl
- SAX and Perl Resources
- SAX and PHP
- SAX and PHP Resources
- Validation
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Document Type Definitions (DTDs)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XML Schemas
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- RELAX NG
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Schematron
- Official Documentation and Implementations
- Validation in Applications
- Informit Articles and Sample Chapters
- Books and e-Books
- XSL Transformations (XSLT)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XSLT in Java
- Java in XSLT Resources
- XSLT and RSS in .NET
- XSLT and RSS in .NET Resources
- XSL-FO
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XPath
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XML Base
- Informit Articles and Sample Chapters
- Official Documentation
- XHTML
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XHTML 2.0
- Documentation
- Cascading Style Sheets
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XUL
- XUL References
- XML Events
- XML Events Resources
- XML Data Binding
- Informit Articles and Sample Chapters
- Books and e-Books
- Specifications
- Implementations
- XML and Databases
- Informit Articles and Sample Chapters
- Books and e-Books
- Online Resources
- Official Documentation
- SQL Server and FOR XML
- Informit Articles and Sample Chapters
- Books and e-Books
- Documentation and Implementations
- Service Oriented Architecture
- Web Services
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Creating a Perl Web Service Client
- SOAP::Lite
- Amazon Web Services
- Creating the Movable Type Plug-in
- Perl, Amazon, and Movable Type Resources
- Apache Axis2
- REST
- REST Resources
- SOAP
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- SOAP and Java
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- WSDL
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- UDDI
- UDDI Resources
- XML-RPC
- XML-RPC in PHP
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Ajax
- Asynchronous Javascript
- Client-side XSLT
- SAJAX and PHP
- Ajax Resources
- JSON
- Ruby on Rails
- Creating Objects
- Ruby Basics: Arrays and Other Sundry Bits
- Ruby Basics: Iterators and Persistence
- Starting on the Rails
- Rails and Databases
- Rails: Ajax and Partials
- Rails Resources
- Web Services Security
- Web Services Security Resources
- SAML
- Informit Articles and Sample Chapters
- Books and e-Books
- Specification and Implementation
- XML Digital Signatures
- XML Digital Signatures Resources
- XML Key Management Services
- Resources for XML Key Management Services
- Internationalization
- Resources
- Grid Computing
- Grid Resources
- Web Services Resource Framework
- Web Services Resource Framework Resources
- WS-Addressing
- WS-Addressing Resources
- WS-Notifications
- New Languages: XML in Use
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Google Web Toolkit
- GWT Basic Interactivity
- Google Sitemaps
- Google Sitemaps Resources
- Accessibility
- Web Accessibility
- XML Accessibility
- Accessibility Resources
- The Semantic Web
- Defining a New Ontology
- OWL: Web Ontology Language
- Semantic Web Resources
- Google Base
- Microformats
- StructuredBlogging
- Live Clipboard
- WML
- XHTML-MP
- WML Resources
- Google Web Services
- Google Web Services API
- Google Web Services Resources
- The Yahoo! Web Services Interface
- Yahoo! Web Services and PHP
- Yahoo! Web Services Resources
- eBay REST API
- WordML
- WordML Part 2: Lists
- WordML Part 3: Tables
- WordML Resources
- DocBook
- Articles
- Books and e-Books
- Official Documentation and Implementations
- XML Query
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- XForms
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Resource Description Framework (RDF)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Topic Maps
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation, Implementations, and Other Resources
- Rich Site Summary (RSS)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- Simple Sharing Extensions (SSE)
- Atom
- Podcasting
- Podcasting Resources
- Scalable Vector Graphics (SVG)
- Informit Articles and Sample Chapters
- Books and e-Books
- Official Documentation
- OPML
- OPML Resources
- Summary
- Projects
- JavaScript TimeTracker: JSON and PHP
- The Javascript Timetracker
- Refactoring to Javascript Objects
- Creating the Yahoo! Widget
- Web Mashup
- Google Maps
- Indeed Mashup
- Mashup Part 3: Putting It All Together
- Additional Resources
- Frequently Asked Questions About XML
- What's XML, and why should I use it?
- What's a well-formed document?
- What's the difference between XML and HTML?
- What's the difference between HTML and XHTML?
- Can I use XML in a browser?
- Should I use elements or attributes for my document?
- What's a namespace?
- Where can I get an XML parser?
- What's the difference between a well-formed document and a valid document?
- What's a validating parser?
- Should I use DOM or SAX for my application?
- How can I stop a SAX parser before it has parsed the entire document?
- 2005 Predictions
- 2006 Predictions
- Nick's Book Picks
I'm not a Graphical User Interface kind of guy. Not that I don't like GUIs, (when they're done well) but I'm not the kind of person who wants to get bogged down in the intricacies of a particular operating system in order to determine where to put all the widgets that make up a GUI interface, such as menus, text boxes, tabs, and so on.
That was one of the things I've always liked about HTML; I didn't have to worry about all of that in order to put together some kind of coherent interface. Of course, there's only so much you can do with HTML. I mean, you couldn't build an interface as complex as, say, the mail program that comes with Mozilla with it. Or can you?
Well, no. But you can do it with Extensible User Interface Language, or XUL, an XML language that was used to build all of the interfaces for the Netscape browser (and its open-source basis, Mozilla). In fact, XUL is so powerful that it makes me think that perhaps the idea of a "weblication" isn't as far-fetched as it sounds. I mean, if we can avoid some of the pitfals and limitations of HTML, why not?>/p>
I'd need a whole book to explain everything there is about XUL, but let's take a look at a simple application that points out some of the differences between XUL and HTML, as well as some of the similarities.
What we're going to build here is a simple "image browser", in which the user can "scroll" through a list of books by yours truly. Like an HTML page, it will reside in the browser, and will use JavaScript to control much of the functionality. Unlike HTML, we will have the ability to easily lay out items on the page and add images to form buttons, among other things.
Let's start by creating the basic window:
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <button id="prev" style="font-size:large" label="Previous!" /> <button id="next" style="font-size:large" label="Next!" /> </window>
In XUL, the window
element replaces the html
element
as the root element; everything will be inside this element. Notice also that the
namespace has been specifically set to the XUL namespace. (And for those of you
who've noticed, yes, that is a Ghostbusters reference. And yes, it is
pronounced "zool".) Using namespaces gives us another advantage: we can place
HTML inside XUL, and vice-versa.
Within the window
element, I've added two buttons. Notice that
there is no form
element; all of XUL is oriented towards one kind of
form or another, so there's no need for one. Now, if you save this text in a
file with an .xul
extension and open it in a Mozilla-based browser,
you'll see something different than you might expect from an HTML page, as you
can see in Figure 1.
Figure 1
Notice that the buttons have stretched to fill the window. Notice also that they are on subsequent lines, even though we didn't add a line break between them. If we want to change both of those behaviors, we can put the buttons into a "horizontal box" element:
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <hbox> <button id="prev" style="font-size:large" label="Previous!" /> <button id="next" style="font-size:large" label="Next!" /> </hbox> </window>
Figure 2 shows the changes in their behavior.
Figure 2
Now let's add some images.
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <vbox> <hbox> <image id="cover" height="350" width="283" src="https://www.informit.com/ShowCover.asp?isbn=0672324229&type=a" /> </hbox> <hbox> <button id="prev" style="font-size:large" label="Previous!" image="http://www.informit.com/ShowCover.asp?isbn=0789722615&type=e" /> <button id="next" style="font-size:large" label="Next!" image="http://www.informit.com/ShowCover.asp?isbn=0130310549&type=e" /> </hbox> </vbox> </window>
Here I've added a regular image. Note that it's an image
tag,
and not an img
tag as it would be in HTML. Note that I've
also added images to the buttons using the image
attribute. Doing
it this way is handy because we can use the DOM setAttribute()
method to change the image associated with the button.
I've also added an hbox
around the image becuase if I don't,
it'll get stretched just the way the buttons did. I've put both hbox
es
in a vbox
, which stacks them vertically. It's also handy because
we can use it to align the elements both horizontally and vertically
by using the pack
attribute:
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <vbox pack="center" height="475"> <hbox pack="center"> <image id="cover" height="350" width="283" src="https://www.informit.com/ShowCover.asp?isbn=0672324229&type=a" /> </hbox> <hbox pack="center"> <button id="prev" style="font-size:large" label="Previous!" image="http://www.informit.com/ShowCover.asp?isbn=0789722615&type=e" /> <button id="next" style="font-size:large" label="Next!" image="http://www.informit.com/ShowCover.asp?isbn=0130310549&type=e" /> </hbox> </vbox> </window>
If we set the window to the same height as the vertical box, we can see the effects in Figure 3.
Figure 3
OK, so now we've got it set up, what do we do with it? Well, we create a
script that enables us to change out the images when the buttons are clicked.
Save the following in a .js
file:
var thisPage = 2; var coverSm = new Array(4); var coverLg = new Array(4); coverSm[1] = "http://www.informit.com/ShowCover.asp?isbn=0789722615&type=e"; coverSm[2] = "http://www.informit.com/ShowCover.asp?isbn=0672324229&type=e"; coverSm[3] = "http://www.informit.com/ShowCover.asp?isbn=0130310549&type=e"; coverLg[1] = "http://www.informit.com/ShowCover.asp?isbn=0789722615&type=a"; coverLg[2] = "http://www.informit.com/ShowCover.asp?isbn=0672324229&type=a"; coverLg[3] = "http://www.informit.com/ShowCover.asp?isbn=0130310549&type=a"; function next(){ thisPage++; setImages(); } function previous(){ thisPage--; setImages(); } function setImages(){ if (thisPage > 1){ document.getElementById("prev").setAttribute("image", coverSm[thisPage - 1]); } else { document.getElementById("prev").setAttribute("image", null); } if (thisPage < 3){ document.getElementById("next").setAttribute("image", coverSm[thisPage + 1]); } else { document.getElementById("next").setAttribute("image", null); } document.getElementById("cover").setAttribute("src", coverLg[thisPage]); }
and then add it to the page:
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> <script src="imagetestscript.js" /> <vbox pack="center" height="475"> <hbox pack="center"> <image id="cover" height="350" width="283" src="https://www.informit.com/ShowCover.asp?isbn=0672324229&type=a" /> </hbox> <hbox pack="center"> <button id="prev" style="font-size:large" label="Previous!" image="http://www.informit.com/ShowCover.asp?isbn=0789722615&type=e" onclick="previous()" /> <button id="next" style="font-size:large" label="Next!" image="http://www.informit.com/ShowCover.asp?isbn=0130310549&type=e" onclick="next()" /> </hbox> </vbox> </window>
The coding's pretty straightforward. When the user clicks one of the buttons, the current
page is incremented or decremented, and the setImages()
function sets
appropriate values for the src
and image
attributes. In fact,
if we call the setImages()
function when the window loads, we don't need to
set these values on the elements at all:
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="setImages()"> <script src="imagetestscript.js" /> <vbox pack="center" height="475"> <hbox pack="center"> <image id="cover" height="350" width="283" /> </hbox> <hbox pack="center"> <button id="prev" style="font-size:large" label="Previous!" onclick="previous()" /> <button id="next" style="font-size:large" label="Next!" onclick="next()" /> </hbox> </vbox> </window>
All of this should be pretty familiar. After all, most of it
we could have done using HTML. But XUL has a more advanced and managable
eventing system based on XML Events, and commands are easier to deal with.
For example, we can take the actual actions off the buttons and instead
refer to command
objects:
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="setImages()"> <script src="imagetestscript.js" /> <command id="xultest_previous" oncommand="previous()" /> <command id="xultest_next" oncommand="next()" /> <vbox pack="center" height="475"> <hbox pack="center"> <image id="cover" height="350" width="283" /> </hbox> <hbox pack="center"> <button id="prev" style="font-size:large" label="Previous!" command="xultest_previous" /> <button id="next" style="font-size:large" label="Next!" command="xultest_next" /> </hbox> </vbox> </window>
This gives us several advantages. First off, we can refer to the same command from multiple locations. Second, we can dynamically change what command a button references. Third, the command is executed no matter how the user activates the button. Also, it's easy for us to disable a button, removing the command altogether:
... function setImages(){ if (thisPage > 1){ document.getElementById("prev").setAttribute("image", coverSm[thisPage - 1]); document.getElementById("prev").setAttribute("disabled", "false"); } else { document.getElementById("prev").setAttribute("image", null); document.getElementById("prev").setAttribute("disabled", "true"); } if (thisPage < 3){ document.getElementById("next").setAttribute("image", coverSm[thisPage + 1]); document.getElementById("next").setAttribute("disabled", "false"); } else { document.getElementById("next").setAttribute("image", null); document.getElementById("next").setAttribute("disabled", "true"); } document.getElementById("cover").setAttribute("src", coverLg[thisPage]); }
This way, when we've reached the last book, we can simply disable the button, as you can see in Figure 4. Not only does the browser then represent it as "greyed out" but the command is also disabled.
Figure 4
This is just the tiniest tip of what XUL can do. For one thing, you have the advantage that all elements are part of the "chrome" system, in which you can specify themes that control the appearance of buttons, menus, and so on. I highly recommend you check out some of the resources and get a better handle on what this technology can do for you. Building web apps can actually be fun again!