ExtJS


My last post was about using Ext.extend to render my web pages. Now I’ll show how I use pre-configured classes to render my Genealogist application. This is the default.brail file I’m using for my default layout page.

   1: <html>
   2: <head>
   3:     <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>
   4:     <link rel=”stylesheet” type=”text/css” href=”../../Content/extJS/resources/css/ext-all.css” />
   5:     <link rel=”stylesheet” type=”text/css” href=”../../Content/extJS/resources/css/genealogist.css” />
   6:     <script type=”text/javascript” src=”../../Content/extJS/adapter/ext/ext-base.js”></script>
   1:  
   2:     <script type=“text/javascript” src=“../../Content/extJS/ext-all-debug.js”>
   1: </script>
   2:     <script type=“text/javascript” src=“../../Content/js/layout/GenealogistFunctions.js”>
   1: </script>
   2:     <script type=“text/javascript” src=“../../Content/js/layout/GenealogistTab.js”>
   1: </script>
   2:     <script type=“text/javascript” src=“../../Content/js/default.js”>

</script>

   7:     
   8:     <title>CrawBuck Genealogist</title>
   9: </head>
  10: <body>
  11:     <div id=”west”></div>
  12:     <div id=”north”>Genealogist</div>
  13:     <div id=”center2″></div>
  14:     <div id=”center1″></div>
  15:     <div id=”south”>Copyright 2008 CrawBuck</div>
  16: </body>
  17: </html>

I start by setting up the necessary ExtJS files: ext-all.css, genealogist.css, ext-base.js and ext-all-debug.js. These are the normal files that are required by ExtJS. The next file, GenealogistFunctions.js is the first pre-configured class. In this file I’m using an Ext.Panel to create my pre-configured class. This panel is going to be an accordion panel that is located in the ‘west’ region of the Ext.Viewport. The code looks like this:

   1: Ext.ns(‘Ext.ux.Genealogist’);
   2:  
   3: Ext.ux.Genealogist.GenealogistFunctions = Ext.extend(Ext.Panel, {
   4:     region:‘west’,
   5:     id:‘west-panel’,
   6:     title:‘Genealogist Functions’,
   7:     split:true,
   8:     width: 200,
   9:     minSize: 175,
  10:     maxSize: 400,
  11:     collapsible: true,
  12:     margins:‘0 0 0 5′,
  13:     layout:‘accordion’,
  14:     layoutConfig:{animate:true},
  15:     
  16:     initComponent: function(){
  17:         Ext.apply(this, { 
  18:             items:[{
  19:                 title:‘Person’,
  20:                 html:‘<p>Manages person in here.</p>’,
  21:                 border:false,
  22:                 iconCls:‘nav’
  23:             },{
  24:                 title:‘Life Events’,
  25:                 html:‘<p>Manages life events in here.</p>’,
  26:                 border:false,
  27:                 iconCls:’settings’
  28:             },{
  29:                 title:‘Family’,
  30:                 html:‘<p>Manages family in here.</p>’,
  31:                 border:false,
  32:                 iconCls:’settings’
  33:             },{
  34:                 title:‘Search’,
  35:                 html:‘<p>Searching in here.</p>’,
  36:                 border:false,
  37:                 iconCls:’settings’
  38:             },{
  39:                 title:‘Reports’,
  40:                 html:‘<p>Reporting in here.</p>’,
  41:                 border:false,
  42:                 iconCls:’settings’
  43:             },{
  44:                 title:‘Lists’,
  45:                 html:‘<p>Listing in here.</p>’,
  46:                 border:false,
  47:                 iconCls:’settings’
  48:             }]
  49:         });
  50:         
  51:         Ext.ux.Genealogist.GenealogistFunctions.superclass.initComponent.apply(this, arguments);
  52:     },
  53:     
  54:     onRender:function() {
  55:         Ext.ux.Genealogist.GenealogistFunctions.superclass.onRender.apply(this, arguments);
  56:     }
  57:     
  58: }); // eo GenealogistFunctions
  59:  
  60: Ext.reg(‘genealogistFunctions’, Ext.ux.Genealogist.GenealogistFunctions);

The next file in the web page is GenealogistTab.js. This is an Ext.TabPanel that is located in the ‘center’ region of the Ext.Viewport. The code looks like this:

   1: Ext.ns(‘Ext.ux.Genealogist’);
   2:  
   3: Ext.ux.Genealogist.GenealogistTab = Ext.extend(Ext.TabPanel,{
   4:     region:‘center’,
   5:     deferredRender:false,
   6:     activeTab:0,
   7:     
   8:     initComponent: function(){
   9:         Ext.apply(this, {
  10:             items:[{
  11:                 contentEl:‘center1′,
  12:                 title: ‘Add Person’,
  13:                 closable:true,
  14:                 autoScroll:true
  15:             },{
  16:                 contentEl:‘center2′,
  17:                 title: ‘Edit Person’,
  18:                 autoScroll:true
  19:             }]
  20:         });
  21:         
  22:         Ext.ux.Genealogist.GenealogistTab.superclass.initComponent.apply(this, arguments);
  23:     },
  24:     
  25:     onRender: function() {
  26:         Ext.ux.Genealogist.GenealogistTab.superclass.onRender.apply(this, arguments);
  27:     }
  28:     
  29: }); // eo Ext.Genealogist.genealogistTab
  30:  
  31: Ext.reg(‘genealogistTab’, Ext.ux.Genealogist.GenealogistTab);

The HomeController class for Monorail is brain dead at this time. All it does is pair the default layout with the Genealogist view. The code looks like this:

   1: using Castle.MonoRail.Framework;
   2:  
   3: namespace Genealogist.Controllers {
   4:     public class HomeController : SmartDispatcherController {
   5:         public void Index() {}
   6:  
   7:         [Layout(“default”)]
   8:         public void Genealogist() {}
   9:     }
  10: }

The one file that ties them all together is the default.js file that contains the Ext.onReady function. Also notice that the default.js file comes after the GenealogistFunctions.js and GenealogistTab.js. The ordering is important because the default.js file uses the two pre-configured classes, genealogistFunctions and genealogistTab. The code looks like this:

   1: Ext.BLANK_IMAGE_URL = ‘../../Content/images/s.gif’;
   2: Ext.namespace(‘Ext.ux.Genealogist’)
   3:  
   4: Ext.onReady(function() {
   5:     var viewPort = new Ext.Viewport({
   6:         layout:‘border’,
   7:         items:[
   8:             new Ext.BoxComponent({ // raw
   9:                 region:‘north’,
  10:                 el: ‘north’,
  11:                 height:100,
  12:                 style:‘background-image:url(../Content/images/BannerBackground.png);background-repeat:repeat-x;border:solid 1px #1D6241;text-align:right;vertical-align:middle;padding-right:10px;font-family:Georgia;font-size:75px;color:#ED7014;’
  13:             }),
  14:             new Ext.BoxComponent({ 
  15:                 region:’south’,
  16:                 el: ’south’,
  17:                 height:25,
  18:                 style:‘background-image:url(../Content/images/FooterBackground.png);background-repeat:repeat-x;border:solid 1px #1D6241;text-align:center;font-family:Verdana;font-weight:bold;color:#ED7014;padding-top:5px;’
  19:             }),{xtype:‘genealogistFunctions’},
  20:                {xtype:‘genealogistTab’} // end of TabPanel
  21:         ] // end of items
  22:     }); // end of Viewport
  23: }); // eo function onReady

What I like about this is that the default.js file is small and easy to understand. Leveraging the two pre-configured classes in the Ext.Viewport are a matter of using xtype and placing the two in {xtype:’genealogistFunctions’} and {xtype:’genealogistTab’}. Now that is a lot easier to read then having all the ExtJS code in one monolithic file.

I’ve been busy on a SP1 release for the my day job and haven’t spent much time on figuring out ExtJS. I’ve blogged before about how I am having difficulty coming up to speed on this product. I have been trying for weeks to use the pre-configured concept of ExtJS without success. ExtJS’s examples show very simple usages and I’m trying to make use more complex usages. So it has been a lot of trial and run. I’ve finally got the accordion panel to work outside of my Genealogist layout and I’m going to try and incorporate it. Here is how it looks:

Wizard1

This has the accordion panel on the left and the right panel can be used for multiple purposes. The goal is to have the accordion panel expose the various functions of the Genealogist project and the right panel will provide the implementation of the functions. I’m going to incorporate this into the Genealogist layout:

Wizard2

I’m using the pre-configured classes that are talked about here. The general pattern is:

   1: MyScope = Ext.extend(Ext.form.ComboBox, {
   2:     // configurables
   3:     // anything what is here can be configured from outside
   4:      border:false
   5:  
   6:     // {{{
   7:     ,initComponent:function() {
   8:         // {{{
   9:         Ext.apply(this, {
  10:             // anything here, e.g. items, tools or buttons arrays,
  11:             // cannot be changed from outside
  12:         }); // e/o apply
  13:         // }}}
  14:  
  15:         // call parent
  16:         MyScope.superclass.initComponent.apply(this, arguments);
  17:  
  18:         // after parent code here, e.g. install event handlers
  19:  
  20:     } // e/o function initComponent
  21:     // }}}
  22:     // {{{
  23:     ,onRender:function() {
  24:  
  25:         // before parent code
  26:  
  27:         // call parent
  28:         MyScope.superclass.onRender.apply(this, arguments);
  29:  
  30:         // after parent code, e.g. install event handlers on rendered components
  31:         
  32:     } // e/o function onRender
  33:     // }}}
  34:     
  35:     // any other added/overrided methods
  36:  
  37: }); // e/o extend
  38:  
  39: // register xtype
  40: Ext.reg(‘mycomponentxtype’, MyScope); 

I’m using a single file for the AccordionPanel class and the code is:

   1: Ext.ux.AccordionPanel = Ext.extend(Ext.Panel, {
   2:     region:‘west’,       
   3:     margins:‘5 0 5 5′,
   4:     split:true,
   5:     width: 210,
   6:     layout:‘accordion’,
   7:         
   8:     initComponent: function(){
   9:         Ext.apply(this, {
  10:             items:[{
  11:                 title: ‘Accordion Item 1′,
  12:                 html: ‘&lt;empty panel&gt;’,
  13:                 xtype: ‘panel’
  14:             },{
  15:                 title: ‘Accordion Item 2′,
  16:                 html: ‘&lt;empty panel&gt;’,
  17:                 xtype: ‘panel’
  18:             },{
  19:                 title: ‘Accordion Item 3′,
  20:                 html: ‘&lt;empty panel&gt;’,
  21:                 xtype: ‘panel’
  22:             },{
  23:                 title: ‘Accordion Item 4′,
  24:                 html: ‘&lt;empty panel&gt;’,
  25:                 xtype: ‘panel’
  26:             },{
  27:                 title: ‘Accordion Item 5′,
  28:                 html: ‘&lt;empty panel&gt;’,
  29:                 xtype: ‘panel’
  30:             }]
  31:         });
  32:         
  33:         Ext.ux.AccordionPanel.superclass.initComponent.apply(this, arguments);
  34:     },
  35:     
  36:     onRender:function(){
  37:         Ext.ux.AccordionPanel.superclass.onRender.apply(this, arguments);
  38:     }
  39:  
  40: });
  41:  
  42: Ext.reg(‘accordionPanel’, Ext.ux.AccordionPanel);

The .brail page looks like this:

   1: <html>
   2: <head>
   3:     <title>Accordion Layout</title>
   4:     <link rel=”stylesheet” type=”text/css” href=”../../Content/ExtJS/resources/css/ext-all.css”/>
   5:  
   6:     <!– GC –>
   7:     <!– LIBS –>
   8:     <script type=”text/javascript” src=”../../Content/ExtJS/adapter/ext/ext-base.js”></script>
   1:  
   2:     <!– ENDLIBS –>
   3:  
   4:     <script type=“text/javascript” src=“../../Content/ExtJS/ext-all-debug.js”>
   1: </script>
   2:     <script type=“text/javascript” src=“../../Content/ExtJS/js/AccordionPanel.js”>
   1: </script>
   2:  
   3:     <style type=“text/css”>
   4:         html, body {
   5:             font: normal 12px verdana;
   6:             margin: 0;
   7:             padding: 0;
   8:             border: 0 none;
   9:             overflow: hidden;
  10:             height: 100%;
  11:         }
  12:         .empty .x-panel-body {
  13:             padding-top:20px;
  14:             text-align:center;
  15:             font-style:italic;
  16:             color: gray;
  17:             font-size:11px;
  18:         }
  19:     </style>
  20:     <script type=“text/javascript”>
  21:         Ext.onReady(function() {
  22:                         
  23:             var viewport = new Ext.Viewport({
  24:                 layout:‘border’,
  25:                 renderTo:Ext.getBody(),
  26:                 items:[{
  27:                     xtype:‘accordionPanel’
  28:                 },{
  29:                     region:‘center’,
  30:                     margins:‘5 5 5 0′,
  31:                     cls:‘empty’,
  32:                     bodyStyle:‘background:#f1f1f1′,
  33:                     html:‘<br/><br/>&lt;empty center panel&gt;’
  34:                 }]
  35:             });
  36:             
  37:         });
  38:     

</script>

   9: </head>
  10: <body>
  11:  
  12: </body>
  13: </html>

I can’t believe it has taken me this long to do this. I still don’t understand ExtJS very well but I’m slowly picking up pieces. My hope is that starting this week I will be able to spend my day job increasing my understanding of ExtJS.

First off I need to state that learning to use ExtJS has been extremely difficult for me. The roadblocks are:

  • I’ve made a career out of saying, “I don’t do no stinking UI”
  • I don’t know HTML or CSS very well
  • The tutorials, articles and APIs aren’t the best.
  • I have no Intellisense for ExtJS

Some of these problems are my own but some of them are ExtJS too. I’ve decided to fix the problems that are mine by learning more about HTML and CSS. The problems with ExtJS resources are they are mainly of the introductory type. That is fine if all you want to do is use their ‘templates’. Of course I want to modify and change from the ‘templates’. This has taken me a lot of time with the ‘experiment and run’ iterations. The Intellisense issue is being addressed but the project is being attached to VS 2008 so if you’re using VS 2005 you’ll be out of luck.

Here is what I’ve now got:

Wizard1

This is similar to what I had using pure CSS/HTML but now it is being rendered using ExtJS. Here is the HTML:

   1: <html>
   2: <head>
   3:     <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>
   4:     <link rel=”stylesheet” type=”text/css” href=”../../Content/extJS/resources/css/ext-all.css” />
   5:     <link rel=”stylesheet” type=”text/css” href=”../../Content/extJS/resources/css/genealogist.css” />
   6:     <script type=”text/javascript” src=”../../Content/extJS/adapter/ext/ext-base.js”></script>
   1:  
   2:     <script type=“text/javascript” src=“../../Content/extJS/ext-all-debug.js”>
   1: </script>
   2:     <script type=“text/javascript” src=“../../Content/js/default.js”>

</script>

   7:     
   8:     <title>CrawBuck Genealogist</title>
   9: </head>
  10: <body>
  11:     <div id=”west”></div>
  12:     <div id=”north”>Genealogist</div>
  13:     <div id=”center2″></div>
  14:     <div id=”center1″></div>
  15:     <div id=”south”>Copyright 2008 CrawBuck</div>
  16: </body>
  17: </html>

Here is the default.js file:

   1: Ext.BLANK_IMAGE_URL = ‘../../Content/images/s.gif’;
   2: Ext.onReady(function() {
   3:   
   4:     var viewPort = new Ext.Viewport({
   5:         layout:‘border’,
   6:         items:[
   7:                 new Ext.BoxComponent({ // raw
   8:                     region:‘north’,
   9:                     el: ‘north’,
  10:                     height:100,
  11:                     style:‘background-image:url(../Content/images/BannerBackground.png);background-repeat:repeat-x;border:solid 1px #1D6241;text-align:right;vertical-align:middle;padding-right:10px;font-family:Georgia;font-size:75px;color:#ED7014;’
  12:                 }), 
  13:                 new Ext.BoxComponent({ 
  14:                     region:’south’,
  15:                     el: ’south’,
  16:                     height:25,
  17:                     style:‘background-image:url(../Content/images/FooterBackground.png);background-repeat:repeat-x;border:solid 1px #1D6241;text-align:center;font-family:Verdana;font-weight:bold;color:#ED7014;padding-top:5px;’
  18:                  }),{
  19:                     region:‘west’,
  20:                     id:‘west-panel’,
  21:                     title:‘West’,
  22:                     split:true,
  23:                     width: 200,
  24:                     minSize: 175,
  25:                     maxSize: 400,
  26:                     collapsible: true,
  27:                     margins:‘0 0 0 5′,
  28:                     layout:‘accordion’,
  29:                     layoutConfig:{
  30:                         animate:true
  31:                     },
  32:                     items: [{
  33:                         contentEl: ‘west’,
  34:                         title:‘Navigation’,
  35:                         border:false,
  36:                         iconCls:‘nav’
  37:                     },{
  38:                         title:‘Settings’,
  39:                         html:‘<p>Some settings in here.</p>’,
  40:                         border:false,
  41:                         iconCls:’settings’
  42:                     }]
  43:                 },
  44:                 new Ext.TabPanel({
  45:                     region:‘center’,
  46:                     deferredRender:false,
  47:                     activeTab:0,
  48:                     items:[{
  49:                         contentEl:‘center1′,
  50:                         title: ‘Close Me’,
  51:                         closable:true,
  52:                         autoScroll:true
  53:                     },{
  54:                         contentEl:‘center2′,
  55:                         title: ‘Center Panel’,
  56:                         autoScroll:true
  57:                     }]
  58:             }) // end of TabPanel
  59:         ] // end of items
  60:     });
  61:   
  62: }); // eo function onReady
  63:   
  64: // eof

This is modified from the Complex BorderLayout template. This template provides north, south, center, east and west regions. If you look at the HTML you will notice I have removed the east region. For the north region I have added the banner rendering and in the south region I have added the footer rendering. The west region will be an accordian panel and the center region will be a tab panel. The west and center will have to interact with one another.

I also want to create components that can be used to render the accordian and the center regions. ExtJS allows this but I’m again stuck learning this through ‘experiment and run’ iterations.

I will explain one of the problems I had in getting this to render. This is what I started with for the south region. The problem was that the height wasn’t taking and the south region was rendering much more than 25 pixels.

   1: }),{ 
   2:     region:’south’,
   3:     el: ’south’,
   4:     height:25,
   5:     style:‘background-image:url(../Content/images/FooterBackground.png);background-repeat:repeat-x;border:solid 1px #1D6241;text-align:center;font-family:Verdana;font-weight:bold;color:#ED7014;padding-top:5px;’
   6: },{
   7:     region:‘west’,

So I tried to put the footer inside a BoxComponent like this:

   1: }),{ new Ext.BoxComponent({ 
   2:     region:’south’,
   3:     el: ’south’,
   4:     height:25,
   5:     style:‘background-image:url(../Content/images/FooterBackground.png);background-repeat:repeat-x;border:solid 1px #1D6241;text-align:center;font-family:Verdana;font-weight:bold;color:#ED7014;padding-top:5px;’
   6: }),{
   7:     region:‘west’,

This won’t render and I didn’t know why. This is where Intellisense would have really helped. It turned out that I shouldn’t have the ‘}’ in the }),{ new Ext.BoxComponent. The correct syntax is this:

   1: }),
   2:     new Ext.BoxComponent({ 
   3:     region:’south’,
   4:     el: ’south’,
   5:     height:25,
   6:     syle:‘background-image:url(../Content/images/FooterBackground.png);background-repeat:repeat-x;border:solid 1px #1D6241;text-align:center;font-family:Verdana;font-weight:bold;color:#ED7014;padding-top:5px;’
   7: }),{
   8:      region:‘west’,

That only took me about 3 hours to figure out.

The first attempt at bringing together Brail and ExtJS was admittedly a little more than cut-and-paste. Now I want to create a simple page using Brail, ExtJS and the HomeController. One of the goals is to have a way to get most of the ExtJS scripting out of the Brail page and into a .js file. http://localhost:1999/home/BlowItAway.castle is the URL to get this to render in VS 2005.

Wizard1

I admit this doesn’t look like much but it is the beginning foundation that can be built upon to create what I hope will be a rich internet application. What I have done here is create a default.brail page that is analogous to a Master Page in ASP.NET. The default.brail page leverages a default.js file to reduce that amount of javascript that would normally be found between the <head></head> tags. I think this makes the default.brail page easier to understand.

   1: <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
   2: <html xmlns=“http://www.w3.org/1999/xhtml” >
   3: <head>
   4:     <title>Master Layout</title>
   5:     
   6:     <link rel=“stylesheet” type=“text/css” href=“../../Content/extJS/resources/css/ext-all.css” />
   7:     <!– GC –>
   8:     <!– LIBS –>
   9:     <script type=“text/javascript” src=“../../Content/extJS/adapter/ext/ext-base.js”></script>
  10:     <!– ENDLIBS –>
  11:     <script type=“text/javascript” src=“../../Content/extJS/ext-all.js”></script>
  12:     <script type=“text/javascript” src=“../../Content/js/default.js”></script>
  13:        
  14: </head>
  15: <body>
  16: <div id=“Banner”>Banner</div>
  17: <div id=“MainContent”>${ChildOutput}</div>
  18: <div id=“Footer”>Footer</div>
  19: </body>
  20: </html>

As you can see I have the <link> tag for the stylesheet location that I’m not really using at this time. There is also the ext-base.js and the ext-all.js script locations. Default.js allows me to move much of the code that is needed to support ExtJS into its own file.

   1: Ext.onReady(function(){
   2:     var banner = Ext.get(‘Banner’);
   3:     banner.setHeight(100);
   4:     banner.boxWrap();
   5:     var mainContent = Ext.get(‘MainContent’);
   6:     mainContent.setHeight(500);
   7:     mainContent.boxWrap();
   8:     var footer = Ext.get(‘Footer’);
   9:     footer.setHeight(25);
  10:     footer.boxWrap();
  11: }); 

Granted that this doesn’t do much now but the goal was to get it out off default.brail page and that goal has been met. I’m hoping to use this technique to build some generic RIA that will be reusable.

The HomeController is very simple right now too.

   1: using Castle.MonoRail.Framework;
   2:  
   3: namespace Genealogist.Controllers {
   4:     public class HomeController : SmartDispatcherController {
   5:         public void Index() {}
   6:  
   7:         [Layout(“default”)]
   8:         public void BlowItAway() {}
   9:     }
  10: }

BlowItAway.brail looks like this:

   1: Here it is

On the one hand I can’t believe it has taken me so long to get this far. I’m not sure if this is a reflection of my lack to intellect or the lack of good documentation. It’s probably more likely to be some combination of both. Being new to the Castle project (MonoRail, ActiveRecord, Windsor Container, Brail) and ExtJS definitely slows me down. I’m not new to MVC but so far their is very little MVC here.

There isn’t a lot of good documentation on how to pair up Brail View Engine with ExtJS. Through experimenting I have gotten this to show up in the Firefox browser:

Wizard1

This is done by redirecting from the Default.aspx page to ~/home/index.castle in the OnLoad event.

The code for the Default.aspx page is:

 

 

   1: <%@ Page Language=“C#” %>
   2: <script runat=“server”>
   3:   protected override void OnLoad(EventArgs e)
   4:   {
   5:     Response.Redirect(“~/home/index.castle”);
   6:     base.OnLoad(e);
   7:   }
   8: </script>

The code for the index.brail page is basically a cut-and-paste for the ExtJS ext-2.1/examples/layout/complex.html. I did have to do some modification to make it work with my directory structure. My directory structure for the ExtJS files looks like this:

Wizard1

The /adapter directory contains the ext-base.js. I have the cascade style sheets and the images in the resource directory. I had to add the examples.js file to the Content/js directory.

I ended up making modification to all of the ’src=’ references in the script tags to point to these locations.

 

 

   1: <link rel=“stylesheet” type=“text/css” href=“../../Content/extJS/resources/css/ext-all.css” />
   2: <!– GC –>
   3: <!– LIBS –>
   4: <script type=“text/javascript” src=“../../Content/extJS/adapter/ext/ext-base.js”></script>
   5: <!– ENDLIBS –>
   6:
   7: <script type=“text/javascript” src=“../../Content/extJS/ext-all.js”></script>

The HomeController code just had an empty Index() method. It took me about 1 hour to figure this out.

There are a lot of little pieces to use ExtJS. I still need to understand how it all fits together. I’ll work on that next.

Last night I left off with the creation of a Castle MonoRail template project and got it to display the ’sample demo’. Tonight I’m going to add ExtJS components to the project and remove the ’sample demo’ components from the project.

I blogged about ExtJS earlier with a link but what you also need to know is the licensing agreement. It comes in three flavors: Commercial, Open Source and OEM/Reseller. I’m not planning on commercializing the Genealogist project so I can go with the Open Source (GNU GPL license v3). At my day job we are seriously considering going with this and if our lawyers bless it we will be using the Commercial license.

This is what the Solution Explorer looks like after creating it using the Castle MonoRail Wizard3 project template.

I kept the files in the config directory but I opened the controllers.config file and deleted the login.controller and contact.controller components from the file. I kept the home.controller component.

In the Controllers directory I deleted the ContactController and the LoginController. I also deleted both files, ContactInfo.cs and Country.cs from the Models directory.

The Views directory had a Contact and Login directories that I deleted but I kept the Home, layouts and rescues directories.

In the layouts directory I replaced the existing code in the default.brail file with ExtJS code from the Writing a Big Application in ExtJS tutorial.

   1: <html>
   2: <head>
   3:   <meta http-equiv=“Content-Type” content=“text/html; charset=utf-8″>
   4:   <link rel=“stylesheet” type=“text/css” href=“../../Content/ext/resources/css/ext-all.css”>
   5:   <link rel=“stylesheet” type=“text/css” href=“../../Content/css/application.css”>
   6:   <script type=“text/javascript” src=“../../Content/extJS/adapter/ext/ext-base.js”></script>
   7:   <script type=“text/javascript” src=“../../Content/extJS/ext-all-debug.js”></script>
   8:   <script type=“text/javascript” src=“../../Content/js/application.js”></script>
   9:   <title>A Big Application</title>
  10: </head>
  11: <body>
  12:     <div>Banner</div>
  13:     <div>MainContent</div>
  14:     <div>Footer</div>
  15: </body>
  16: </html>

The Default.aspx page has no code behind and only contains a script section that overrides the OnLoad event of the page lifecycle.

   1: <%@ Page Language=“C#” %>
   2: <script runat=“server”>
   3:   protected override void OnLoad(EventArgs e)
   4:   {
   5:     Response.Redirect(“~/home/index.castle”);
   6:     base.OnLoad(e);
   7:   }
   8: </script>

Even though this redirects to the ~/home/index.castle page the ~/layout/default.brail page gets run and there is no content holder, ${ChildOutput}, to render the ~/home/index.brail page in. So what is rendered is this:

Wizard2

If you’re paying attention you will notice that the redirect is to ~/home/index.castle and there is no ~/home/index.castle file. This confused me at first until I realized that in the web.config file this section mapped the .castle extension to the .brail extension.

   1: <httpHandlers>
   2:     <add verb=“*” path=“*.castle” type=“Castle.MonoRail.Framework.MonoRailHttpHandlerFactory, Castle.MonoRail.Framework” />
   3:     <!– block direct user access to template files –>
   4:     <add verb=“*” path=“*.vm” type=“System.Web.HttpForbiddenHandler” />
   5:     <add verb=“*” path=“*.njs” type=“System.Web.HttpForbiddenHandler” />
   6:     <add verb=“*” path=“*.brail” type=“System.Web.HttpForbiddenHandler” />
   7:     <add verb=“*” path=“*.brailjs” type=“System.Web.HttpForbiddenHandler” />
   8:     <add verb=“*” path=“*.st” type=“System.Web.HttpForbiddenHandler” />
   9: </httpHandlers>

You can replace the path=”*.castle” with whatever you want as the extension and it will map the extensions: .vm, .nis, .brail, .brailjs and .st to it.

For a long time in my software career I made the statement, “I don’t do no stinkin’ UI”. The UI I just rendered above shows how little I know about UI but at this point I’m going to start working with .css and images and other UI components. This is just the start.