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:
<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:
<input id="textbox" value="hello" accesskey="h" size="25" maxlength="40"
sun="20" rain="25" snow="yes" type="text">
<INPUT id=textbox accessKey=h maxLength=40 size=25 value=hello snow="yes" rain="25" sun="20">
<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
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:
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.
<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
<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
<input value="hello " and goodbye">
<input value="hello " and goodbye">
<INPUT value='hello " and goodbye'>
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.