Neil's Place

September 27, 2004

Getting Started with XUL
Kurt provides a brief introduction to XUL

September 20, 2004

9:33 AM XUL Slider

There are a couple of XUL widgets which aren't finished yet, so they aren't documented on XULPlanet. One such widget is the <spinbuttons> tag, which is a textbox with two arrow buttons for adjusting the value. While there is some code for it, it is missing both images and code to do something when the arrow buttons are pressed. That said, finishing it is something that anyone with a bit of XUL knowledge can do, perhaps with a bit of help. (meaning, no C++ knowledge is needed.) If you'd like to help, let me know.

The other widget is the <slider> tag which allows one to select a value by sliding a thumb, much like a scrollbar. There is such a tag in XUL, however, it is really just a piece of a scrollbar, rather than a completed widget. The first step is getting it to look like a slider. I spent a bit of time with this, both with the slider code and the underlying GTK theme code. Here's an image, and I'd say it looks pretty good, and it works too.

I'll probably try a Windows version soon. The other problem is that the slider needs a few extra features to make it more useful as a slider, rather than a scrollbar with a different appearance. Most importantly is to display the current value in a label nearby. Not too hard, but the shared slider/scrollbar code assumes that the valid range always starts at 0 and ends at the value of the maxpos attribute. A minpos attribute could be added easily enough, but there are also cases where the slider might be used to choose a percentage, a decimal, or some other fixed set of strings.

Another common slider feature supported by other toolkits is showing tick marks along one edge. Unfortunately, GTK doesn't seem to support tick marks in its slider, so I don't think it's possible to make ticks theme-indepependant.

Comments ( 55 )

September 12, 2004

12:10 PM Examining innerHTML and custom attribute implementations

Someone asked a while ago if Mozilla supported 'expando' properties, which are an IE feature. I had some idea of what they were but I wasn't completely sure, so I went and looked at the MSDN documentation. Naturally, I left more confused than I was before. So I did some investigation of my own to see if I could determine what expando properties were. It turns out that an expando property is just a silly term for a custom property or attribute on an HTML tag. And Mozilla does support custom attributes and properties. It doesn't support the automatic mapping between attributes and properties as IE does, but that is done for all attributes, recognized or otherwise, so I don't think that's as relevant. Why was this extra 'expando' term created? It turns out to be due to an implementation detail in IE that makes such a term necessary. In Mozilla, such as term isn't necessary as we'll see below.

I decided to write up some examples of bits of HTML to see what happens in various browsers. In each case, I grab the innerHTML property of a form and display it, in an attempt to see what is being stored and generated. I start with this example:

<form id="simpleform">
  <input id="textbox" type="text" value="hello" accesskey="h" size="25" maxlength=40
         sun="20" rain=25 snow="yes">

Here is the result from various browsers:

Mozilla 1.7.1:

  <input id="textbox" value="hello" accesskey="h" size="25" maxlength="40"
         sun="20" rain="25" snow="yes" type="text">
IE 6:

  <INPUT id=textbox accessKey=h maxLength=40 size=25 value=hello snow="yes" rain="25" sun="20">
Opera 7.54:

  <INPUT ID="textbox" TYPE="TEXT" VALUE="hello" ACCESSKEY="h" SIZE="25" MAXLENGTH="40"/>

As you can see, there are very different results in each browser. Of course, since innerHTML isn't defined by any public specification, none are more correct than others, although some later examples will show various bugs that would seem wrong. Mozilla returns something similar to the original HTML except that the type attribute is moved to the end of the attributes. It shows the custom attributes in the same order as they were specified. Opera also returns the attributes in the order that they were specified, although they have been returned in uppercase. Opera drops all of the attributes that it does not recognize as valid for the input tag. Finally, Opera adds a slash at the end of tag as if it thought the element was XHTML, despite that the document is not. It's not even valid backwards compatible XHTML since there is no space before the slash. But anyway.

IE seems to return the id attribute first, followed by the valid recognized attributes in alphabetical order, followed by the unrecognized attributes in a random order. The attributes are mixed case, and the quotes have been left off of the recognized attributes, but added to the unrecognized attributes. Also, the type attribute isn't output.

What does this tell us? It tells us that Mozilla and Opera probably store the attributes of an element in an array, as they are returned in the same order as they were specified. During parsing of the HTML, each attribute is appended to end of the array. From the way that the attributes are displayed in IE, we can assume that the attributes are stored in an object, presumably of the interface IHTMLInputElement. The innerHTML implementation goes though the interfaces supported by the element, takes the value of each property and outputs it. This is supported by the mixed case of the accessKey and maxLength attributes, as if they were the property names in the interface.

Here's where the 'expando' feature comes in. Since interfaces like IHTMLInputElement can't support anything but the properties that the interface has been defined to have, custom properties need to be done in a special way in IE. Judging from the random order in which they are returned, I'd imagine the expando properties are stored in a hashtable in a private property somewhere.

Since Mozilla just stores all attributes in an array, it doesn't need to distinguish between known and unknown attributes, and thus, doesn't have a special term for it. Which is why I had trouble understanding them, since I didn't think that they were any different from normal attributes. That explains expandos, but while investigating I found a number of interesting things about the innerHTML implementations of the browsers.

Note above that IE doesn't return the type attribute. Why is this? This is because the value is set to the default value. If you changed the type to 'password', it would be displayed in the innerHTML. This also applies to all other recognized attributes. The following example shows this:

<input size="20">

This example will display '<INPUT>' in IE, since 20 is the default value of the size attribute. The innerHTML implementation assumes that any attribute set to the default value means the same as an attribute that was not specified. This is probably because the size is stored in an integer field in the class, and there is no way to store a null or unspecified value in an integer field. Mozilla and Opera can handle this case as an unspecified attribute will not be in the attributes list, whereas one set to the default value will be in the list. The last example will be returned with the size attribute included. (The default size in Mozilla and Opera is 25 however). I don't know why the type attribute is returned last in Mozilla, nor why the value is converted to uppercase in Opera. Possibly an optimization for some purpose, as only the type attribute works this way.

Another example:

<input value="hello" value="goodbye">

The above example will show that Opera, while disallowing unrecognized attributes, doesn't remove duplicate attributes. Both value attributes will be returned in the innerHTML, which suggests that Opera doesn't check for duplicates when parsing attributes. Mozilla does check for duplicates however, and only the first value attribute (with the value 'hello') will exist. However, getAttribute will always return the first value in all three browsers.

Note from earlier that IE doesn't put quotes around the known attributes. It suggests different code is used for recognized and unrecognized attributes. Let's see what happens here:

<form id="simpleform">
  <input value="hello and goodbye">
  <input size="25 and 30">

In this case IE does put quotes around the attribute when there are spaces in it. Also, all three browsers parse the size attribute as 25 and ignore the 'and 30' part. Also, I note that IE doesn't add linebreaks between the tags, whereas Mozilla and Opera do. Let's see if we can break the attribute serialization.

<input value="hello " and goodbye">

Mozilla 1.7.1:

  <input value="hello " and goodbye">
IE 6:

  <INPUT value='hello " and goodbye'>
Opera 7.54:

  <INPUT VALUE="hello

Mozilla leaves the entity intact, or escapes it again on serialization. IE notices the quote and switches to using single quotes around the attribute. Opera notices the quote and appears to just give up. In fact, Opera will give up completely and return immediately, even if there are other tags to serialize.

Comments ( 17 )