Widget system prototype

Uses jQuery and jQuery Templates plugin

HTML

<script src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>

JavaScript

/**
 * Widget constructor
 */
var Widget = function(config) {
   
    // apply config
    $.extend(this, config);
    // attempt to render
    this.render();
};
/**
 * Widget prototype
 */
$.extend(Widget.prototype, {
    // render target
    renderTo: null,
    // template
    tpl: '<div class="container-panel">' +
            '<p>${txt}</p>' +
            '<div class="items-container"></div>' +
        '</div>',
    // template data
    tplData: null,
    // child items array
    children: null,
    // initial collapsed state
    collapsed: false,
    // widget's root element
    el: null,
    // default render target selector for child items
    renderTarget: '.items-container',
    
    render: function() {
        var me = this,
            renderDom

        // render the widget
        if(!this.rendered && this.renderTo && this.tpl) {
            renderDom = $.tmpl(this.tpl, this.tplData);
            // assume that first element is widget's root element
            this.el = renderDom[0];
            $(this.renderTo).append(renderDom);
         
             // clear the reference
            renderDom = undefined;
        
            // THIS IS JUST EXAMPLE CODE! Bind click handler...
            $(this.el).find('p').first().click(function() {
                me.collapsed ? me.expand() : me.collapse();
            });    

            // find render target for children
            this.renderTarget = $(this.el).find(this.renderTarget).first();
            
            // render children if not collapsed
            this.renderChildren();
        
            // set rendered flag
            this.rendered = true;
        }
    },
    
    renderChildren: function() {
        var children = this.children;
        if(!this.collapsed && children && children.length) {
            for(var i = 0, len = children.length; i < len; i++) {
                // render children inside 
                children[i].renderTo = this.renderTarget;
               ...