March 2007

Using yui-ext widgets from markup

I’ve written several posts about using yui-ext in Virtualmin’s new GUI, and I recommend it whole-heartedly to folks looking for a really nice set of JavaScript widgets. It, like the YUI library it is based on, is targeted to widgets useful in general applications, rather than very simple task-focused applications. It’s great for the kind of applications that have a lot of data to present, lots of pages to navigate via roughly random access, and if care isn’t taken with presentation could place quite heavy demands on the end user. We’ve got that kind of application. Virtualmin does a lot of widely varied tasks. So, yui-ext is a great fit.

But, one place where yui-ext falls down, that some other libs do better, is in building widgets from markup. It pretty much completely lacks the capacity to build any of its complex widgets from HTML markup. They must be generated with JavaScript. There are clever things like a loader function that’ll load a JSON object automagically…but nobody who’s making an app that can target a wide array of client devices, like we are, is going to be able to deliver data in that form (at least, not without major re-writes of significant portions of the application, and a new layer of abstraction).

Nonetheless, the widgets are so nice that I’ve looked past that, and with some help from Jack Slocum, I’ve begun building functions that will parse the tree and replace the elements with the yui-ext elements.

Ext.tree.TreePanel.readMarkup = function(root, el){
    function readBranch(pnode, ul){
        var cn = ul.childNodes;
        for(var i = 0, len = cn.length; i < len; i++){
            var li = cn[i];
            if(li.tagName && li.tagName.toLowerCase() == 'li'){
                var a = li.getElementsByTagName('a')[0];
                var cul = li.getElementsByTagName('ul')[0];
                var node = pnode.appendChild(new Ext.tree.TreeNode({
                    id : a.id,
                    text : a.innerHTML,
                    cls: a.className,
                    href : a.href
                }));
                if(cul){
                    readBranch(node, cul);
                }
            }
        }
    }
    readBranch(root, YAHOO.util.Dom.get(el));
    return root;
};
 
treeMenu = function(el){
  // create the hidden root
  var root = new Ext.tree.TreeNode('');
 
  // get the existing markup element
  var prenl = el.getElementsByTagName('UL');
  var nl = getEl(prenl.item(0).id);
 
  // read it
  Ext.tree.TreePanel.readMarkup(root, nl.dom);
 
  // remove the markup
  nl.remove();
 
  // initialize the tree
  var tree = new Ext.tree.TreePanel(el, {rootVisible:false, enableDD:false, animate:true});
  tree.setRootNode(root);
  tree.render();
};
 
var Trees = function(){
  return {
    init : function() {
      // Get all of the div ids of class treemenu
      var elements = YAHOO.util.Dom.getElementsByClassName('treemenu', 'div');
      YAHOO.util.Dom.batch ( elements, treeMenu );
    }
  };
}();
 
YAHOO.ext.EventManager.onDocumentReady(Trees.init, Trees, true);

Trees.init, which is run once the document has finished loading searches the DOM for elements of class “treemenu” and then uses a YUI batch to iterate over all of them with the treeMenu function. The treeMenu function is merely a wrapper for the hard work being done by readParse, which runs through the tree to figure out the structure of the list and put it into a TreePanel.

The markup read by this function looks like:

<div id="nav" class="treemenu">
  <ul id="navul1" class="nav-list">
    <li><a href="...">Leaf Node</a></li>
    <li><a href="...">Node with children</a>
      <ul>
        <li><a href="woot">Chillun 1</a></li>
        <li><a href="wooty">Chillun 2</a></li>
      </ul>
    </li>
  </ul>
</div>
 
<div id="nav2" class="treemenu">
  <ul id="navul2" class="nav-list">
    <li><a href="...">Another Leaf Node</a></li>
    <li><a href="...">Second Node with children</a>
      <ul>
        <li><a href="woot">Chillun 1</a></li>
        <li><a href="wooty">Chillun 2</a></li>
      </ul>
    </li>
  </ul>
</div>

The same kind of technique can be used for all of the Ext functions, though I believe I'll be able to use a mix of markup and JavaScript for the remainder of my conversion...the tree menus were particularly challenging because of the way they are generated in our code. Continue Reading »

Development

Comments (0)

Permalink

Some great technical and startup-related videos and audio recordings

While I enjoy seeing Mentos and Diet Coke symphonies as much as the next guy, I find myself spending a lot more time watching technical videos on Gootube and Yahoo! Video…Some of them are simply fantastic, so I thought I’d share a list of my favorites.

Guy Kawasaki’s Art of the Start presentation – Holy crap. You don’t get much better than this. Best 40 minutes you can spend if you’re starting a company or thinking of doing so.

YUI Theater – This one is awesome. Douglas Crockford has a three part workshop series that’s a soup to nuts JavaScript and DOM introduction. I learned JavaScript (by some definition of “learned”) in one weekend from this series of videos. There’s also a nice video in which Joe Hewitt introduces his FireBug, which is the greatest thing to happen to Firefox since…ummm…ever. Nothing else comes close to FireBug, and it’s been absolutely vital to my successes with JavaScript, so far. There’s a lot of other cool stuff in FireBug that this video doesn’t cover, but it’ll get you started.

Anatomy of a Debian Package – Unfortunately, I find Debian and Ubuntu documentation about packaging to be horribly opaque, due to lack of examples of the process of packaging. This video runs a little slow, but it’s at least a usable source of information. I really just want to see a “create this file, put this into it, now run some-command to build the software and bundle it into a package…and here’s the command you use to sign it”, similar to several existing examples for RPM. That part of the video starts at about 20 minutes in. I wish some of the docs would have pointed out dh_make and how to use it…would have saved me hours of frustration when I first started packaging debs. And, I also wish some of the too many options for building debs would be deprecated. There’s just too many, “or you could do it this way…or you could to it that way…or you could do it typing only with your toes”. Let me explain something to the Debian folks: I never want to build the damned thing manually. Get mentions of that stuff the hell out of the introductory packaging documentation. Same goes for signing packages and repositories. I don’t care how the hell you implemented package signing…show me what command to run and tell me where the resulting files (if any) go in my apt-get repositories. (Actually, this video doesn’t do much good with package signing, either.)

Competing on the Basis of Speed – This one isn’t particularly technical, but it’s interesting. I believe running really fast is absolutely key to success in the current tech industry. The key to this is stripping away things that are pointless or stupid about your business, product, or process. The trouble is figuring out what is pointless and/or stupid. Being a young and tiny company, it seems easier…but I suspect that even our two-man shop has some stupid and pointless pieces, which I hope we’ll shake out pretty quick once we have some infrastructure in place for measuring how our customers are really using the product.

Development
Linux
Startups

Comments (0)

Permalink