Category Archives: XUL, XBL, JS and DOM

Discriminating user input errors from other errors

(This entry is a follow-up of my design-by-contract blog entry a few days ago.)
Last night, while working on certain user-interface scripting, I caught myself using assert() to validate user input. This is not smart. The assert() function is intended for bugs in the source code. It only throws exceptions or warnings if there’s a certain debug flag activated. Since the end-user product will have that debug flag off, the assert() does no good for checking user input.
There has to be some other bailout mechanism in place. Firing an exception with the throw statement works great… if you have something to catch it. But we only want to catch certain errors.
The first step is the creation of an exception constructor which is unique. In my assert() function, each error which leaves it has a name property of “AssertionError”. This is unlike any other error JavaScript natively supports. It also identifies a particular class of exceptions to the application.
So, if I want a unique class of errors to catch, one of the best ways is to make sure each error created in that class has a specific name property.

function UserError(aMessage) {
var e = new Error(aMessage);
e.name = "UserError";
return e;
}

Then I can go back to the old-fashioned if statements to check user input:

if (userDidSomethingWrong) {
throw new UserError("You broke one of my rules!");
}

Okay, so what catches this error before it hits the JavaScript Console?
In my particular application, I have a global object called editor. Each XUL button to execute a user-interface function would call a method of this editor object. For instance, if I want to do a search, I call editor.search().
Because of the beauty of the apply method of functions, I can do a little redirection and call another function instead which will then itself call search. (The apply method allowed me to write the constructNew function I talked about in my ecmaDebug.js script. The constructNew function may get renamed, though…) So, why not set up a special try…catch for user errors in an intermediary function?

editor = {
search: function() {
throw new UserError("search failed");
},
watchUserErrors: function(methodName) {
var args = [];
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
try {
this[methodName].apply(this, args);
}
catch(e) {
if (e.name == "UserError") {
doSomethingWithTheError(e);
} else {
throw e;
}
}
},
toString: function() {
return "[object AbacusEditor]";
}
}

Now I can instead call editor.watchUserErrors('search').
One other possibility exists. If you note how the assert() function processes its results, it's almost a macro.
assert(false, "The sky is falling!", true);
works much like:

if (!false) {
throw new Error("The sky is falling!");
}

Only the last argument of the assert() makes it an error instead of a warning. Of course, if I can create this macro, I can create another:
assertAboutInput(false, "The sky is falling!");
might work like:

if (!false) {
throw new UserError("The sky is falling!");
}

With ecmaDebug.js included, I can simply write:

function assertAboutInput(mustBeTrue, errMsg) {
var throwException = arguments.length > 2 ? arguments[2] : false;
try {
if (!mustBeTrue) {
var aError = new UserError(errMsg);
throw aError;
}
}
catch(e) {
e.shiftStack(2) // this takes us to the actual stack error.
if (throwException) {
e.message = errMsg; // reset
throw e;
} else {
warn(e);
}
}
return mustBeTrue;
}

I'm undecided about that throwException default. Setting it to false means consistency with the standard assert() macro. Setting it to true means the developer doesn't have to override a bias towards warnings when errors are the true intent of the function. (Developers can use a false value for throwException to indicate deprecated methods, for example.) I prefer consistency over bias...

I need a scrollable content object model

I have been having a lot of fun in the last 24 hours trying to “control the scroll” of an element’s content. I don’t think anyone really took the time to make scrolling friendly to scripting.
There are four general categories of scrollable content I’m aware of (bear in mind this is from a DOM point of view):
(1) <html:textarea/>
(2) <browser/>, <editor/> <iframe>, etc.
(3) <box style=”scroll:overflow;” />
(4) <arrowscrollbox/>
Textareas provide basic properties (scrollTop, scrollLeft, scrollHeight, scrollWidth) for determining which portion of the content to show. This is good. But it doesn’t easily expose the scrollbars themselves as objects a script can access. The same goes for the rest of them. There really is no native (that is, implemented directly in Mozilla) way to script the scrolling of such scrollable content directly.
It’d be really nice if there was an nsIScrollableContent.idl (or whatever) set of properties for any time you have a content box with at least one scrollbar. References to the scrollbars themselves (<xul:scrollbar/>?) would be great. References to the properties which determine where the content is scrolled to would be almost as good.
Solutions?
I thought to myself, this just won’t do. So I started asking myself, how can I create my own scrollable content? One way to simulate content which has scrolled partially is by setting the following style:

.scrollableContent {
overflow: hidden;
margin-top: 0px;
margin-left: 0px;
clip: rect(0px 0px 0px 0px);
}

Then, by adjusting the margin-top and margin-left properties, the content could appear to scroll. After a little tinkering, I created a widget which is halfway to a scriptable scrolling content. You can see it here. (The demo currently also checks for DOMAttrModified elements bubbling up — this lets me check for when a scrollbar in the demo actually moves.)
I haven’t yet implemented the scrolling of content yet; there’s some linear mathematics I need to do, including resizing the thumb of each bar appropriately. I’ve also filed bug 243128 for adding a few properties to <xul:scrollbar/> elements. They basically expose the scrollbar’s attributes to JS as properties.
If the first patch passes muster, I’ll propose code for percentage-based handling of scrollbars.
Use cases: This is where I usually get hung up. My current motivation is to create a line-numbered multiline textbox control. Other advantages of this would be to directly expose a scrolling capability to JavaScript; dynamic effects, anyone?

Two widgets released

http://weblogs.mozillazine.org/weirdal/archives/serverpost/serverpost.css
http://weblogs.mozillazine.org/weirdal/archives/serverpost/serverpost.xml
http://weblogs.mozillazine.org/weirdal/archives/integerControl/integerControl.css
http://weblogs.mozillazine.org/weirdal/archives/integerControl/integerControl.xml
I do try to keep my promises. 🙂 I left the license out of the integerControl files; I am releasing these under the MPL/LGPL/GPL trilicense.
Serverpost I’ve talked about extensively already; I never did get that change made that I was thinking about. But it’s still pretty stable imho.
The integer control widget is pretty simple. It’s simply a widget that lets you set an integer value. If the size is set to 1, then typing in a digit (0-9) on the control sets the value. Up and down arrow keys also allow for scrolling.

“The widgets are coming! The widgets are coming!”

Okay, so I don’t sound all that great on my high horse. I have been annoyingly busy, (though it’s nice to get paid) and so I haven’t devoted as much time to the Mozilla-based work as I usually do.
Someone recently asked me to post my serverpost widget in a finalized form here. I will do that, but there’s a couple more things I want to tweak first. Also, with my hampered Internet access right now (plus a few other problems which are more serious), I have mainly stuck to science fiction I’d also been putting off. I usually switch between sci-fi and hacking code every few weeks just to give myself a break from the norm. I’m coming off a sci-fi binge, so I’m guessing I’ll be putting together some code again soon.

Oops.

I almost never screw up a testcase. Almost. But, I screwed one up, on XBL, and sent a bunch of Mozilla VIPs on a wild-goose chase.
That hurts. Particularly since I take pride in making damn sure that I have a valid bug to file before I file one.
Even more embarrassing, I filed bug 117469 ages ago for almost exactly the same kind of bug, but which at the time was causing a crash. (Bug 231396 is the bug where I fouled up, and the similarities between the two bugs are startling…)

A bigger toolkit, better tools

It’s semi-official: we are going to have a Mozilla 2.0.
I’m happy about that, somewhat. Sure, the number itself doesn’t mean a whole lot. But there’s been a lot of work done since 1.0.
Given that we are indeed going for 2.0, maybe mozilla.org’s contributors should consider adding new XUL (and XBL-based) widgets to the mix.
For instance, I’m working on an <xul:form/> element so that XUL can be a client-side user interface for a server-side application. XUL was originally designed to be the Mozilla chrome language, but HTML forms occasionally leave something to be desired. It’s a worthwhile goal, I think.
Seriously, I’d like to start creating widgets in XBL+JavaScript which Mozilla App Suite and its child applications (Mozilla Firebird, Mozilla Thunderbird, Composer++ to name a few) can start using. I’d really like to see others contribute such widgets, and maybe we can get a few of them in for Mozilla 2.0.
There are of course good reasons to not add every widget we come across (think code bloat). But a few good ones would be beneficial. I invite you to comment not only on whether or not widgets should be added for 2.0, but also widgets you can implement (but not widgets you’d like to see and haven’t got a clue how to do).
UPDATE: Turns out <xul:form/> wasn’t such a bright element name, so, here is a partially tested demonstration XUL file for <xul:serverpost/>.
Probably won’t work until Monday noon PST (thanks to bsmedberg for graciously hosting, though I had to fix a couple bugs and the corrected version won’t be there until then)
SECOND UPDATE:
I filed Bug 231833 to implement this widget. Keep your fingers crossed…

Document Object Model Utility Widgets

Test page with source code
Mozilla’s XUL widgets are great; I love them to death. But for another application I’m developing,
where it’s important to see the structure of a node, and to keep several nodes identical after mutations, XUL just doesn’t have those capabilities. (It wasn’t designed to. Not mozilla.org’s fault.)
So, over the last few days, I’ve come up with the following test page, complete with four new DOM-related widgets and one (independent) function which should help me keep my XUL code in working order.
The new independent function I filed an enhancement bug for adding to Mozilla. It’s a JavaScript-based assert() function, probably not quite in line with how other assert() macros work… but it’s a start.
All this code is under the MPL tri-license, so please do offer feedback, particularly improvements!
UPDATE: Added a new widget which I hope to propose for the Mozilla suite, <xul:menuDeck/>. It selects an entry out of a deck based on a corresponding menuitem being selected.

XBL DOM Help Requested

I like the XBL anonymous content model a great deal, but there are a few questions I have unanswered.
I particularly like the proposed <xbl:element/> . If and when it’s implemented, it would give me a lot of flexibility for defining new XBL bindings. You could have a node list represented by an element with the following anonymous content model:

<content>
<children/>
<element/>
</content>

As I’m starting to explore C++ and building Mozilla, I’m thinking maybe this is something I should implement (bug 98712 ). But there are a few points which I don’t think the XBL spec really made clear when it came to how the DOM treats these anonymous nodes and their relationship to bound elements…
XBL Questions
I’d really appreciate any advice on what the blank fields in the document’s final table should be.

HTML DOM for XHTML docs as XML?

Bug 111514, including comments up to 80
There’s been a long and sharp debate on how Mozilla should treat an XHTML document’s DOM as the mime-type indicates it. I’ve made a static copy of the first 80 comments on the bug, so as to cut down on Bugzilla server load, and invite the discussion over here.
There are four mime-types for XHTML documents. The first, text/html, is irrelevant as that automatically triggers HTMLDocument. The best, application/xhtml+xml, currently is XMLDocument. (jst has a patch to make that HTMLDocument as well.)
The other two, application/xml and text/xml, are gray areas. My thinking now is these two mime-types we should continue to treat as XMLDocument for DOM purposes.
Extended debate welcome.

Thoughts on MathML, the DOM, and XML

I apologize for this seeming a mish-mash of two separate articles; I
couldn’t figure out a clean way to state one set of issues without stating
the other.
Identity Problems
ID-type and IDREF-type attributes are wonderful. They offer a conveinient
way for XML documents to reference and cross-reference elements in a
document. The DOM’s handling of these attributes seems a little bit lacking,
though. The problems start when you clone a node, or when you wish to use
similar markup in multiple sections without XML ID attribute validity
problems.
Example: MathML embedded in XML
Technically ID attributes don’t present much of a problem to an XML
document with embedded MathML. You could have several MathML fragments
describing the progress of a simple theorem (such as the Fundamental Theorem
of Calculus). But to use the powerful xref attribute of MathML,
each element you reference by xref must have a unique
id attribute. With possibly dozens of elements per fragment
needing id attributes, and several fragments slowly changing
from one to another, you need a systemized ID attribute naming system for the
XML document. The W3C has not yet suggested a particular scheme for ID
attributes in this scenario.
A simple, if less-than-elegant, solution would be for each id
and xref attribute within each MathML fragment to have its value
prefixed with the id attribute value of the MathML fragment’s
root node.
On another note, the XML Schemas specification does allow for “keys” to be
defined. However, MathML 2.0 does not involve XML Schemas. Perhaps, a
revision to MathML 2.0 would use XML Schemas to create “local”
id and xref attributes.
Example: Cloning a node
If the document’s author includes a feature for cloning a node and then
appending it to the document somewhere, the XML ID-type attributes pose a
particular type of problem. Unless the author explicitly changed or removed
all ID-type attributes, the cloned node cannot be appended to the document
without violating XML validity. Likewise, the author must update all
corresponding IDREF-type attributes.
The DOM does not currently provide any specifications on retrieving
IDREF-type attributes. A NodeFilter may be constructed to
retrieve elements via the names and/or values of attributes, but not by the
schema type of attributes. (Note: DOM Level 3 Core, WD, adds the
schemaType property to attributes; this property would have a
name property which for IDREF-type attributes corresponds to
“IDREF”.)
Opinions on MathML
MathML 2.0 is a specification with limited flexibility compared to more
recent XML specifications. Although written as an XHTML-compatible module
per Modularization of XHTML, it does not lend itself well to containing other
XML languages in its content. For instance, to include XML markup from a
theoretical Geometry Markup Language, you might very well end up using the
csymbol and semantics elements significantly.
Moreover, as noted above, id and xref are not very
flexible with regards to multiple MathML fragments in an XML document.
For that matter, I am continually stunned to see the Math WG
specifications completely ignore geometry. The SVG specification has done an
excellent job of describing graphical images; the mathematical approach to
geometry is not quite included in SVG, and I would hope SVG WG looks at that
for version 2.0. I have e-mailed the SVG WG on this issue some time ago. It
is my opinion that the SVG and Math Working Groups should coauthor a
specification for a Geometry Markup Language which would fit seamlessly into
MathML, SVG and XHTML.
It is also my opinion, for these reasons, that the the W3C Math Working
Group should consider starting a new minor version of MathML, tentatively
MathML 2.1. The basic foundations of MathML 2.0 are solid (though I have
heard complaints about the MathML DOM as well). However, two years have
passed for MathML 2.0. MathML is very useful from a mathematical standpoint,
but not as useful from a XML/DOM standpoint.
Opinions on the DOM
Thank God for DOM 2 Traversal! Had I known about it when I was writing
JavaScript Developer’s Dictionary, I would have certainly included it. (I
use the same excuse for JavaScript strict warnings…) It’s even better than
DOM 2 Range.
With it and support for DOM 3 Core (when it becomes a Candidate
Recommendation), it should be trivial to write NodeFilters for
appropriate cleanup of ID- and IDREF-type attributes — without knowing the
type of each attribute beforehand. Then you could be completely certain that
you won’t violate XML validity appending a cloned node.
Also with Traversal, you could implement a “sub-identity” attribute. The
idea is a subset of an XML Schemas key: basically an ancestor element has a
specific ID-type attribute which you use as the root node in your
NodeIterator or TreeWalker. The sub-identity
attribute being unique only within the contents of the root node,
you could then iterate through the descendant elements to find the target
element.
Similarly, you could also define and find “sub-identity reference”
attributes, serving the same purpose IDREF-type attributes serve for ID-type
attributes.
XML Schemas could easily enforce uniqueness constraints on the id+sub_id
combination via the element, and serve a
similar purpose for id+sub_idref via the
element. Traversal could then help us define several methods:
* Node.getElementById(id) (for nodes which haven’t
been appended yet)
* (Node/Document).getElementsByIdRef(id) returns
NodeList
* (Node/Document).getElementBySubId(id, sub_id) returns
Element
* (Node/Document).getElementsBySubIdRef(id, sub_id)
returns NodeList
* (Node/Document).getElementByKey(key) returns
Element
* (Node/Document).getElementsByKeyRef(key) returns
NodeList
The first four in this list I can implement using DOM 2 Traversal and an
XML language where I already know the IDREF-type amd “sub”-id and -idref
attributes, or DOM 2 Traversal and DOM 3 Core. The last two are much more
difficult; they would require a specific definition of how a XML Schemas key
would be referenced in the DOM. This is something I would not expect the DOM
Working Group to attempt before Level 4, but they should consider it.
Opinions on XBL Note
XBL has a wonderful potential that I think no one is aware of:
* It can serve as an alternative to XSLT.
* It allows you to treat a bound element as part of the DOM
* It allows you to add custom extensions to the bound element — in
essence, creating your own DOM for the element. (Properties and methods,
not just anonymous nodes!)
XBL cannot replace XSLT, and vice versa. But for simple transformations
or extensions, XBL is beautiful. The W3C should really look at standardizing
XBL and integrating it into its other XML specifications wherever feasible.
XBL is a gold mine for XML application developers.