Today, I went and attended the "Attack of the Squirrels" Firefox 2.0 launch party in Sunnyvale, CA, USA. Pretty good group of guys. In exchange for an early ride to Cuesta Park from the San Jose Diridon Caltrain Station, I ended up helping buy food and arrange the layout of goodies.
Thanks, everyone, for showing up and helping George have a great time. Although I have to wonder if the new Firefox 2 shirt I have should only be washed with red clothing... because I don't have many reds... :-)
(I just thought of that as I wrote this blog entry.)
For editing XML, I wanted to have some sort of template system, where XML markup could be abstracted into a simpler system for reusability and flexibility. I didn't know of any standardized template system like that, so I wrote one.
Designing the mental model proved relatively easy: XBL's anonymous content design was inspirational with its <xbl:children/> element. I also needed a repetition model, though, so I came up with a repeat element as well (very different from Web Forms 2's repeat element). I also wanted to separate the UI from the actual output of the templates. Finally, I wanted to provide, in the design, at least, placeholders for custom XML and JavaScript to override what the template normally does.
Making all that work took a lot longer. So long, in fact, that I created an "experimental" section of Verbosio's CVS repository to work on it in a minimal-code environment, long enough to get the basics working.
I finished the functionality parts of the XBL bindings two days ago. Then, because I knew no one but me would know how the thing worked, I spent several hours documenting it.
Verbosio's markup language specification, version 0.1.0.
For those of you with XULRunner trunk, and a desire to see some of it in action, read the full article link for details on testing it.
Next on Verbosio's agenda: creating the XUL wizard for creating markup templates from already-existing XML markup. If you want to edit XUL, XHTML, etc., and you've got samples on hand, this tool would guide you through creating templates you and everyone else could use. Good stuff cooking.
Execute the following:
# password is guest cvs -d :pserver:guest@mozdev.org:/cvs login cvs -d :pserver:guest@mozdev.org:/cvs co verbosio path/to/xulrunner verbosio/experimental/templates/application.ini
Hopefully you'll have a debug build, so you can see dump() output. The large text box on top is where you would enter source code to run against the template. Samples of markup for the templates can be found in a comment at the end of verbosio/experimental/templates/chrome/content/editorTest/elementTemplate.xul .
The first row of radio buttons lets you determine what the test application does. "Walk sample only" means to use the test application's tree walker (not the native Gecko TreeWalker, as I'll explain in a moment) to walk the nodes of the XML fragment you pasted into the source box.
The "Walk template only" radio button means it will walk its own internal template (which you select in the second row), just as it would for the "Walk sample only" selection. You can use this radio button, no matter what you've put into the source box.
"Walk with sample" means to walk both the template's markup and your XML fragment's markup simultaneously, in parallel. (This is why I couldn't use the native tree walker - it walks one tree at a time, and I felt it would be just more efficient to write my own walker.) The idea is to see if the template matches your fragment, much like a regular expression would match a string.
"Import node" is the magical one. It takes the XML fragment you've given it and attempts to import it into the template, using the special XBL bindings to do the needed work.
The second row of radio buttons lets you select templates. The "Ordinary markup" selection chooses a rather unimaginative MathML template. The "<markup:children/>" selection goes for a template using <svg:g/> and any number of child elements. The "<markup:repeat/>" selection uses a more complex template for a XUL radio group and any number of XUL radio buttons.
I haven't yet tested combinations of <markup:repeat/> and <markup:children/>, like you might find in a XHTML table (tables with repeating rows, rows with repeating cells, cells with arbitrary content). So it's not fully validated yet. That would be a real litmus test for the template markup language, and I'll look into it a little later.
Typically in Mozilla usage, we use tree walkers like this:
const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
function filter(aNode) {
if ((aNode.namespaceURI == "http://verbosio.mozdev.org/namespaces/foo/") && (aNode.localName == "foo")) {
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
return nsIDOMNodeFilter.FILTER_SKIP;
}
var walker = document.createTreeWalker(rootNode, nsIDOMNodeFilter.SHOW_ELEMENT, filter, true);
The NodeFilter we pass in to the tree walker is usually just a JavaScript function. If you read the DOM 2 Traversal spec carefully, though, this isn't exactly what the spec would indicate. (It makes a special exemption for JavaScript in the ECMAScript bindings.)
According to the spec, node filters are usually objects (not specifically functions) with an acceptNode(Node aNode) method. What this means is, if we shape the filter as an object, we can give special properties to the node filter.
For example, say you want to accept <foo/> and <bar/> elements, but you want to do something different in each case. You could write the filter to have an acceptedType property:
const nsIDOMNodeFilter = Components.interfaces.nsIDOMNodeFilter;
var filter = {
acceptedType: null,
acceptNode: function acceptNode(aNode) {
if (aNode.localName == "foo") {
this.acceptedType = "foo";
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
if (aNode.localName == "bar") {
this.acceptedType = "bar";
return nsIDOMNodeFilter.FILTER_ACCEPT;
}
return nsIDOMNodeFilter.FILTER_SKIP;
}
}
var walker = document.createTreeWalker(rootNode, nsIDOMNodeFilter.SHOW_ELEMENT, filter, true);
while (walker.nextNode()) {
switch (filter.acceptedType) {
case "foo":
// do something
break;
case "bar":
// do something else
break;
default:
throw new Error("Unexpected type");
}
}
Note that this node filter doesn't modify the document (no good node filter or tree walker should). It modifies itself in such a way that the code using the tree walker and node filter can detect that state change and act according to what the filter is signaling.
Also, don't forget to prevent leaks by clearing the tree walker when you're done with it:
walker = null; filter = null;
Apologies for everyone reading feeds with this and expecting technical talk. This is just a silly idea I had this morning, as a subject line to parody... Stephen Colbert. Hence, the rest of this article you'll have to read by clicking on the "Full Article" link.
According to Wikipedia (which must be true) and its article on Stephen Colbert the character,
"Despite his bluster, Colbert's character also demonstrates a notable phobia of bears, which he refers to as "godless killing machines without a soul".
O'Reilly? (Err, Oh'Really?)
Here's what I want to do. I want to make fun of Stephen Colbert (the character) and his aversion to bears by punning on his name's pronunciation. I want to do so in so outrageous a fashion that he ends up inviting one or two people involved with the joke onto his show to publicly lambast them over it (in-character). I don't necessarily have to be one of those people.
The Rules:
What's new:
With the upcoming Firefox 2 Release Parties, I thought I'd recommend a rather silly idea I had for the last Firefox release party series.
Ingredients: Ritz (TM) crackers, cream cheese, blue food coloring
Serving size: number of crackers divided by number of people, dogs, cats, cows, firefoxes, thunderbirds, sunbirds, and seamonkeys in attendance. (Note: No amount of crackers will feed or satisfy any big red stomping lizards that happen to visit your city. They don't like crackers.)
Based on the Firefox 1.0 party I attended in San Francisco, CA.
P.S. Forgive me if your comments take several days to show up. I just moved apartments, and my Internet connection won't be back on at home until Tuesday.
A little while ago, I started getting Blue Screens of Death on a very regular basis. No, I have no idea what's causing it. I'm loath to take it into the shop now, with Windows Vista coming up in a few short months - but there's another consideration I have: Linux on the second hard drive.
Having noticed Windows Vista RC2 just now available, I'm wondering if installs of Vista allow for people to still run their machines as dual-boot between Linux (in my case, Kanotix) and Windows. If Vista horks the dual-boot, but I can re-install Kanotix and dual-boot from then on, that's okay. I'm just wondering what the test results are. That will help me determine whether I upgrade to Vista final when it's out, wait a little while for the boot loader to adapt, or wait for something else to happen.
Also, for anyone who tried an upgrade to Vista from XP and already had Visual C++ 2005 Express Edition installed, I'd like to know how the upgrade went; I use VC2005 for my compiler on Windows XP, and would like to know how that affected using the compiler.
Please no "Linux is the way to go, wipe out Windows" statements or anything like that. I don't need religious puritanism in tech; I develop code for Mozilla-based applications, and having multiple operating systems at my disposal, including Windows and Linux, is essential. For those of you who say I should be on Fedora Core or some RPM-based distro instead of Kanotix's Debian approach, I'm already considering buying a laptop with Fedora Core 6 on it when that becomes available (FC5 wouldn't install on my desktop), so don't try that either. :-)