Russell Tyndall's Tech Blog

The Shizzle Fa Rizzle at Acceleration.net

Home Contact Syndicate this Site (RSS 2.0) Syndicate this Site (Atom) Login
  80 Posts :: 6 Stories :: 69 Comments :: 19 Trackbacks

News

Listed on BlogShares

Archives

Post Categories

Image Galleries

Favorite Web Locations

Tech Tool Links


Also see post: The XBL Template / Repeater control
Repeater.XBL :
?<xml version="1.0" encoding="utf-8" ?> 
<xbl:bindings
   xmlns:xbl="http://www.mozilla.org/xbl"
   xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    <xbl:binding id="repeater">
        <xbl:content>
            <children />
        </xbl:content>
        <xbl:implementation>
            <xbl:method name="init_bind">
                <xbl:parameter name="datasource" />
                <xbl:body><![CDATA[
                var thisElem = this;
                thisElem.datasource = datasource;
                var parentNode = this.parentNode;
                parentNode.repeater = thisElem;
                parentNode.removeChild(thisElem);
                var template = thisElem.childNodes;//document.getAnonymousNodes(thisElem);
                thisElem.template = template;
                
                var attribArr = [];
                var innerRepeaters = [];
                var reg = /{(.*)}/ ;
                for(var i=0; i< template.length ; i++){  // for every root node in the template
                
                    // this function looks for the attributes it needs to replace and creates functions that
                    // are keyed by the replace term and allow the filling in of those values
                    // the path allows me to clone the template but still point to the correct place in the template
                    function traverseNodeTreeFindingAttributes(node, pathToNode){
                        for(var k=0 ; k < node.attributes.length ;k++){
                        // for every attribute on the current node see if we need to fill data on this template
                        
                            if(node.attributes[k].value.match(reg)){
                                (function(){ // this function just closes values
                                    var attrib = node.attributes[k].name;
                                    var attribVal = node.attributes[k].value;
                                    var key = node.attributes[k].value.match(reg)[1];
                                    
                                    // puts a vale in the array of attributes that need attention
                                    attribArr.push([ key, function( node, val ){ 
                                        var str = 'node'+pathToNode;
                                        node = eval(str);
                                        if(!node) throw "couldnt find the node located at "+str;
                                        node.setAttribute(attrib, attribVal.replace('{'+key+'}', val));
                                    }]);
                                })();
                            }
                        }
                        // if we are not another repeater traverse down the tree farther looking for attributes
                        if(node.tagName.toLowerCase() != 'repeater'){ 
                            for(var j=0; j < node.childNodes.length ;j++){
                                traverseNodeTreeFindingAttributes(node.childNodes[j], pathToNode+"['childNodes']["+j+"]" );
                            }
                        }
                        else{ // if we are a repeater create a function that from a copy of this
                              // template root allows us to get the inner repeater
                            innerRepeaters.push(function( node ){
                                return eval('node'+pathToNode);
                            });
                        }
                    }
                    traverseNodeTreeFindingAttributes(template[i], ''); //start the traversal at this current root
                }
                
                //add a function that will allow rebinding
                //(for example you sort the data set and wish to see that represented)
                thisElem.bind = function(){

                    // for each row in the dataset buils a hash of keys values
                    // then use this to fill in all the attribute values on the nodes                
                    for( var row=0 ; row < thisElem.datasource.rows.length ; row++ ){
                    
                        // for each template root, copy the template root and then set its attributes
                        for( var i=0 ; i < template.length ; i++){
                            var newElem = template[i].cloneNode( true ); 
                            parentNode.appendChild(newElem);
                            
                            var obj = new Object();
                            for( var col=0 ; col < thisElem.datasource.columnHeaders.length ;col++){
                               obj[thisElem.datasource.columnHeaders[col]] = thisElem.datasource.rows[row][col];
                            }
                            
                            // from the root we are at call all the attribute setting functions with the values from the object
                            for( var attrib=0 ; attrib < attribArr.length ; attrib++ ){
                                attribArr[attrib][1](newElem, obj[attribArr[attrib][0]]);
                            }
                            
                            // if we had inner repeaters go ahead and process
                            // them now that their attributes have been set
                            for(var i=0 ; i < innerRepeaters.length ; i++){
                                var node = innerRepeaters[i](newElem);
                                var ds = null;
                                
                                //if we have a datasource go ahead and bind the inner repeater template
                                if( (ds = node.getAttribute('datasource')) ){ 
                                    try{
                                        ds = eval(ds);
                                    }
                                    catch( e ){
                                        throw "the datasource didnt eval :"+ds;    
                                    }
                                    
                                    node.init_bind(ds);
                                    node.bind();
                                    
                                }
                            }
                        }
                    };
                };
             ]]></xbl:body>
            </xbl:method>
        </xbl:implementation>
    </xbl:binding>
</xbl:bindings>
DataSource :
DataSource = function ( dataTable){
   if(!dataTable) return null;
   this.columnHeaders = dataTable[0];
   dataTable.remove(0);
   this.rows = dataTable;
   this.datasourceConstructor = arguments.callee;
   this.getNewPartialDataSource = function( col , value ){
      var newTable = [ this.columnHeaders ];
      var idx = this.columnHeaders.indexOfValue( col );
      if(idx == -1) throw "There is no such column in the dataset";
      else{
         for(var row=0 ; row < this.rows.length ; row++){
            if( this.rows[row][idx] == value ) newTable.push(this.rows[row]);
         }
      }
      return new DataSource( newTable );
   }
}
posted on Wednesday, May 04, 2005 4:21 PM