title: Dojo Tabs as Custom Widgets
body: <p>I've created a number of widgets that are loaded as tab panes in a tabcontainer. Everything seems to work well, except I'm getting different results when using my custom widgets vs. creating everything in markup (tab content isn't taking up the whole page, 3rd party widgets aren't behaving properly, etc). This all leads me to think that I might not be creating my widgets correctly. The trick seems to be that they are not interpreted as contentpanes.</p>
  
  <p>I am using dojo 1.3.2.</p>
  
  <p>The following markup, for example, works great:</p>
  
  <pre><code>&lt;body class="soria" style="overflow-y: hidden;"&gt;
      &lt;!-- Container for whole page --&gt;
      &lt;div dojoType="dijit.layout.BorderContainer" design="headline" id="borderContainer" style="height:100%;width:100%;"&gt;
          &lt;!-- Header container --&gt;
          &lt;div dojoType="dijit.layout.ContentPane" region="top"&gt;
              Title
          &lt;/div&gt;
          &lt;!-- Left side --&gt;
          &lt;!--&lt;div dojoType="dijit.layout.ContentPane" region="left" id="addressContainer" splitter="true" style="width:100%; background-color: #F0F8FF;"&gt;--&gt;
          &lt;div dojoType="dijit.layout.ContentPane" region="left" id="addressContainer" splitter="true"&gt;
              &lt;div style="text-align: center;"&gt;
                  &lt;!-- address --&gt;
                  &lt;span id="addressInstructions"&gt;Address Contents&lt;/span&gt;
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;!-- Tabs --&gt;
          &lt;div dojoType="dijit.layout.TabContainer" id="tabs" region="center" tabPosition="top"&gt;
              &lt;div dojoType="dijit.layout.ContentPane" id="tab1" title="map"&gt;
                  &lt;p&gt;Change map to:&lt;/p&gt;
                  &lt;div id="divMapList"&gt;&lt;/div&gt;
                  &lt;div style="padding: 10px 10px 10px 10px;"&gt;
                      &lt;div id="divMap" dojoAttachPoint="divMap" style="width:300px;height:300px;border:1px solid #000;display:block;margin-left:auto;margin-right:auto;"&gt;&lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
              &lt;div dojoType="dijit.layout.ContentPane" id="tab2" title="other"&gt;
                  Some text in here.
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/body&gt;
  </code></pre>
  
  <p>Looking at the resulting HTML code, I can see that the tab itself has the following class: "dijitContentPane dijitTabPane dijitTabContainerTop-child dijitTabContainerTop-dijitContentPane dijitVisible".</p>
  
  <p>Below is the HTML of one of my custom widgets:</p>
  
  <pre><code>&lt;div&gt;
      &lt;div style="text-align: center; padding: 5px 5px 5px 5px;"&gt;
          &lt;div&gt;${i18nStrings.mapChangeMap}:&lt;/div&gt;
          &lt;div dojoAttachPoint="divMapSelection"&gt;&lt;/div&gt;
          &lt;div style="padding: 10px 10px 10px 10px;"&gt;
              &lt;div id="divMap" dojoAttachPoint="divMap" style="width:300px;height:300px;border:1px solid #000;display:block;margin-left:auto;margin-right:auto;"&gt;&lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  </code></pre>
  
  <p>And here is part of the custom widget JS (I can provide more code if necessary):</p>
  
  <pre><code>dojo.declare("xxxx.Widget.Map", [dijit._Widget, dijit._Templated],
  {
      //Specify the path of the HTML file that sets the look of the widget
      templatePath: dojo.moduleUrl("xxxx", "widget/templates/Map.html"),
  
      //The strings used to populate standard text. Populated in postMixInProperties
      i18nStrings: null,
  
      //The widget's root div identifier. Value overwritten in postMixInProperties
      id:"tabMap",
  
      //The tab's title. Value overwritten in postMixInProperties
      title: "",
  
      //True to activate the tab. False otherwise.
      activate: false,
  
      //The map &amp; current layer
      map: null,
      currentLayer: null,
  
      //Sets up some basic properties
      postMixInProperties: function() {
          this.inherited(arguments);
          var _1 = dojo.i18n.getLocalization("dijit", "loading", this.lang);
          this.loadingMessage = dojo.string.substitute(this.loadingMessage, _1);
          this.errorMessage = dojo.string.substitute(this.errorMessage, _1);
          if (!this.href &amp;&amp; this.srcNodeRef &amp;&amp; this.srcNodeRef.innerHTML) {
              this.isLoaded = true;
          }
          this.i18nStrings = dojo.i18n.getLocalization("IndyVIP","applicationStrings");
          this.title = this.i18nStrings.mapTabTitle;
      },
  &lt;/div&gt;
  </code></pre>
  
  <p>I am adding the widget to the container by creating the widget, then adding it as a child to the tabcontainer.</p>
  
  <p>This results in the following class assigned to my tab: "dijitTabPane dijitTabContainerTop-child dijitVisible".</p>
  
  <p>Does anyone know what I am doing wrong?</p>
  
  <p>Thank you!</p>
  
  <p>Emmster</p>
  
  <p>UPDATE:
  I have decided to try inheriting from dijit.layout.ContentPane &amp; dijit._Templated. I am still having problems with that though, the main one being that if I add my widget to a TabContainer, I get the error "node is null" on line 4467 of dojo.js.uncompressed.js, but the tab seems to work just fine IF it's the active tab starting out. If I add the widget to a page that only contains the widget, it works fine without errors.</p>
  
  <p>See the code below that gives me the expected results, but causes that one "node is null" error.
  HTML:</p>
  
  <pre><code>&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;
  &lt;html xmlns="http://www.w3.org/1999/xhtml" &gt;
  &lt;head&gt;
      &lt;title&gt;Test&lt;/title&gt;
      &lt;script type="text/javascript"&gt;
          var djConfig = {
              parseOnLoad: true,
              useXDomain: true,
              debugAtAllCosts: true,
              baseUrl: './',
              modulePaths: {IndyVIP: 'js'}
          };
      &lt;/script&gt;
      &lt;link rel="Stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/1.5/js/dojo/dijit/themes/soria/soria.css" /&gt;
      &lt;script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=1.5"&gt;&lt;/script&gt;
      &lt;script type="text/javascript"&gt;
          dojo.require("dojo.parser");
          dojo.require("dijit.layout.BorderContainer");
          dojo.require("dijit.layout.ContentPane");
          dojo.require("dijit.layout.TabContainer");
          dojo.require("IndyVIP.Widget.Map");
          dojo.addOnLoad(init);
          function init() {
              var tab = new IndyVIP.Widget.Map({title: 'Map'});
              var tabContainer = dijit.byId('tabs');
              tabContainer.addChild(tab);
          }
      &lt;/script&gt;
  &lt;/head&gt;
  &lt;body class="soria" style="overflow-y: hidden;"&gt;
      &lt;!-- Container for whole page --&gt;
      &lt;div dojoType="dijit.layout.BorderContainer" design="headline" id="borderContainer" style="height:100%;width:100%;"&gt;
          &lt;!-- Header container --&gt;
          &lt;div dojoType="dijit.layout.ContentPane" region="top"&gt;
              Title
          &lt;/div&gt;
          &lt;!-- Left side --&gt;
          &lt;div dojoType="dijit.layout.ContentPane" region="left" id="addressContainer" splitter="true"&gt;
              &lt;div style="text-align: center;"&gt;
                  &lt;!-- address --&gt;
                  &lt;span id="addressInstructions"&gt;Address Contents&lt;/span&gt;
              &lt;/div&gt;
          &lt;/div&gt;
          &lt;!-- Tabs--&gt;
          &lt;div dojoType="dijit.layout.TabContainer" id="tabs" region="center" tabPosition="top"&gt;
              &lt;!-- uncommenting the following results in map not acting the way it should --&gt;
              &lt;!--
              &lt;div dojoType="dijit.layout.ContentPane" id="tab2" title="other"&gt;
                  Some text in here.
              &lt;/div&gt;--&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>Map.js:</p>
  
  <pre><code>dojo.provide("IndyVIP.Widget.Map");
  dojo.require("dijit.layout.ContentPane");
  dojo.require("dijit._Templated");
  dojo.require("dijit._Widget");
  
  dojo.declare("IndyVIP.Widget.Map", [dijit.layout.ContentPane, dijit._Templated],
  {
      map: null,
  
      //Specify the path of the HTML file that sets the look of the widget
      templatePath: dojo.moduleUrl("IndyVIP", "widget/templates/Map.html"),
  
      //The tab's title. Value overwritten in postMixInProperties
      title: "",
  
      widgetsInTemplate: true,
  
      startup: function() {
          this.map = new esri.Map('divMap');
          dojo.connect(this.map, 'onLayerAdd', this, this.onLayerAdd);
          var layer = new esri.layers.ArcGISTiledMapServiceLayer('http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer');
          this.map.addLayer(layer);
      },
  
      onLayerAdd: function() {
          //Create symbol
          var lineColor = new dojo.Color('black');
          var lineSymbol = new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID,lineColor,1);
          var pointColor = new dojo.Color('red');
          var pointSymbol = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_CIRCLE,12,lineSymbol,pointColor);
  
          //Create point
          var x = 4.92;
          var y = 50.625;
          var point = new esri.geometry.Point(x,y,this.map.spatialReference);
  
          //Create template
          var template = new esri.InfoTemplate('A title','Some content');
  
          //Create graphic
          var graphic = new esri.Graphic(point,pointSymbol,null,template);
  
          //Add graphic to map
          this.map.graphics.clear();
          this.map.graphics.add(graphic);
      }
  
  });
  </code></pre>
  
  <p>And finally, here's the widget's HTML template:</p>
  
  <pre><code>&lt;div&gt;
      &lt;div id="divMap" dojoAttachPoint="divMap" style="width:300px;height:300px;border:1px solid #000;display:block;margin-left:auto;margin-right:auto;"&gt;&lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>I very much appreciate all of your suggestions so far. I feel like I am missing something elementary, but I can't quite figure it out.</p>
  
  <p>Emmster</p>