I am migrating a very complicated Dojo 1.3 page to Dojo 1.9.3. One aspect that I'm struggling with is the following:
<div id="desktopTabContainer" dojo13Type="dijit.layout.TabContainer" persist="true" class="desktopTabContainer" >
<s:iterator value="desktopViewList" var="rowValue">
<%-- A container representing each desktop tab. A desktop tab itself has no contents, it is only used to display the tab control itselfy.
The contents of the corresponding desktop are displayed in the 'desktopPane' content pane --%>
<div dojo13Type="dijit.layout.DesktopBorderContainer"
id="dijit_layout_BorderContainer_${rowValue.oid}"
desktopOid="${rowValue.oid}"
desktopVersion="${rowValue.version}"
title='
<span id="tabSpan${rowValue.oid}" title="<s:property value="%{escapeQuotes(description)}" />"><s:property value="%{escapeQuotes(name)}" /></span>
<span title="<s:text name="%{getText('label.desktop.editDesktop')}"/>" ondblclick="onEditDesktop()"><img src="<s:url value='/images/editDesktop.gif'/>" border="0" class="tabIcon" /></span>
'
closable="true" onClose="onRemoveDesktop(this)"></div>
</s:iterator>
<%-- A container representing the last 'New Desktop' tab which is displayed as a plus '+' button --%>
<div dojo13Type="dijit.layout.BorderContainer" id="addDesktopTab" title='<span id="addDesktopTabButton" title="<s:text name="%{getText('label.desktop.newDesktop')}"/>" ><img src="<s:url value='/images/addDesktop.gif'/>" border="0" /></span>' closable="false"></div>
</div>
With the following extensions and redefinitions in the javascript:
// ================================================
// The tab button component:
// ================================================
dojo13.extend(dijit13.layout._TabButton, {
onClick: function(e ) {
if( this.label.match("addDesktopTabButton") != null ) {
onNewDesktop();
}
}
});
// ================================================
// The Border Container and Stack Container components:
// ================================================
dojo13.provide("dijit.layout.DesktopBorderContainer");
dojo13.declare("dijit.layout.DesktopBorderContainer", dijit13.layout.BorderContainer,
{
desktopOid: null, desktopVersion: null,
resize: function(e) {
// fix for the tab container resizing when wrapping its tabs
tabContainer = dijit13.byId("desktopTabContainer");
if( tabContainer.domNode.style.height != tabContainer.tablist.domNode.clientHeight + 10 ) {
tabContainer.domNode.style.height = tabContainer.tablist.domNode.clientHeight + 10;
}
this.inherited(arguments);
}
});
dojo13.extend(dijit13.layout.StackController, {
onAddChild: function(/*Widget*/ page, /*Integer?*/ insertIndex){
// summary:
// Called whenever a page is added to the container.
// Create button corresponding to the page.
// tags:
// private
// add a node that will be promoted to the button widget
var refNode = dojo13.doc.createElement("span");
this.domNode.appendChild(refNode);
// create an instance of the button widget
var cls = dojo13.getObject(this.buttonWidget);
var button = new cls({label: page.title, closeButton: page.closable}, refNode);
this.addChild(button, insertIndex);
this.pane2button[page] = button;
page.controlButton = button; // this value might be overwritten if two tabs point to same container
var handles = [];
handles.push(dojo13.connect(button, "onClick", dojo13.hitch(this,"onButtonClick",page)));
if(page.closable){
handles.push(dojo13.connect(button, "onClickCloseButton", dojo13.hitch(this,"onCloseButtonClick",page)));
// add context menu onto title button
var tabMenu = new dijit13.Menu({targetNodeIds:[button.id], id:button.id+"_Menu"});
var mItemRemove = new dijit13.MenuItem({label:removeDesktopMessage, iconClass: "removeDesktopMenuItem", id: button.id+"_removeMenuItem"});
handles.push(dojo13.connect(mItemRemove, "onClick", dojo13.hitch(this, "onCloseButtonClick", page)));
tabMenu.addChild(mItemRemove);
var mItemEdit = new dijit13.MenuItem({label:editDesktopMessage, iconClass: "editDesktopMenuItem", id: button.id+"_editMenuItem"});
handles.push(dojo13.connect(mItemEdit, "onClick", dojo13.hitch(null, "onEditDesktop", page)));
tabMenu.addChild(mItemEdit);
var mItemNew = new dijit13.MenuItem({label:newDesktopMessage, iconClass: "newDesktopMenuItem", id: button.id+"_newMenuItem"});
handles.push(dojo13.connect(mItemNew, "onClick", "onNewDesktop"));
tabMenu.addChild(mItemNew);
dojo13.connect(tabMenu, "onOpen", dojo13.hitch(null,"checkTabMenuItemsState", button));
this.pane2menu[page] = tabMenu;
}
this.pane2handles[page] = handles;
if(!this._currentChild){ // put the first child into the tab order
button.focusNode.setAttribute("tabIndex", "0");
this._currentChild = page;
}
page.controlButton.closeIcon.title = removeDesktopMessage;
//make sure all tabs have the same length
if(!this.isLeftToRight() && dojo13.isIE && this._rectifyRtlTabList){
this._rectifyRtlTabList();
}
}
});
This generates a tab system that looks like this:
I have translated this in the following way:
(desktopNewDojo.jsp)
<%-- A container for the desktop tabs --%>
<div data-dojo-id="desktopTabContainer" id="desktopTabContainer" data-dojo-type="dijit/layout/TabContainer" class="desktopTabContainer" >
<s:iterator value="desktopViewList" var="rowValue">
<%-- A container representing each desktop tab. A desktop tab itself has no contents, it is only used to display the tab control itselfy.
The contents of the corresponding desktop are displayed in the 'desktopPane' content pane --%>
<div data-dojo-type="js/desktop/desktopBorderContainer" data-dojo-props="desktopOid:'${rowValue.oid}', desktopVersion:'${rowValue.version}', closable:false"
id="dijit_layout_BorderContainer_${rowValue.oid}"
title='
<span id="tabSpan${rowValue.oid}" title="<s:property value="%{escapeQuotes(description)}" />"><s:property value="%{escapeQuotes(name)}" /></span>
<span title="<s:text name="%{getText('label.desktop.editDesktop')}"/>" ondblclick="onEditDesktop()"><img src="<s:url value='/images/editDesktop.gif'/>" border="0" class="tabIcon" /></span>
'>
</div>
</s:iterator>
<%-- A container representing the last 'New Desktop' tab which is displayed as a plus '+' button --%>
<div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="closable: false" id="addDesktopTab" title='<span id="addDesktopTabButton" title="<s:text name="%{getText('label.desktop.newDesktop')}"/>" ><img src="<s:url value='/images/addDesktop.gif'/>" border="0" /></span>'></div>
</div>
(js/desktop/desktopBorderContainer.js)
// ================================================
// The Border Container and Stack Container components:
// ================================================
define(["dojo/_base/declare", "dijit/layout/BorderContainer", "dijit/registry", "js/desktop/desktopCommons"], function(declare, BorderContainer, registry, desktopCommons) {
return declare("js.desktop.desktopBorderContainer", BorderContainer, {
desktopOid : null,
desktopVersion : null,
resize : function(e) {
// fix for the tab container resizing when wrapping its tabs
tabContainer = registry.byId("desktopTabContainer");
if (tabContainer.domNode.style.height != tabContainer.tablist.domNode.clientHeight + 10) {
tabContainer.domNode.style.height = tabContainer.tablist.domNode.clientHeight + 10;
}
this.inherited(arguments);
},
onClose : function(){
desktopCommons.onRemoveDesktop(this);
}
});
});
desktop.js:
// ================================================
// The tab button component:
// ================================================
lang.extend(TabController.TabButton, {
onClick : function(e) {
if (this.label.match("addDesktopTabButton") != null) {
desktopCommons.onNewDesktop();
}
}
});
lang
.extend(
StackController,
{
onAddChild : function(/* Widget */page, /* Integer? */
insertIndex) {
// summary:
// Called whenever a page is added to the
// container.
// Create button corresponding to the page.
// tags:
// private
// add a node that will be promoted to the
// button widget
var refNode = domConstruct.create("span");
this.domNode.appendChild(refNode);
// create an instance of the button widget
var cls = lang.getObject(this
.buttonWidget().declaredClass);
var button = new cls({
label : page.title,
closeButton : page.closable
}, refNode);
this.addChild(button, insertIndex);
this.pane2button[page] = button;
page.controlButton = button;
this.own(on(button, "click", lang.hitch(this,"onButtonClick",page)));
if(page.closable){
this.own(on(button, "clickCloseButton", lang.hitch(this,"onCloseButtonClick",page)));
// add context menu onto title button
var tabMenu = new Menu({targetNodeIds:[button.id], id:button.id+"_Menu"});
var mItemRemove = new MenuItem({label:removeDesktopMessage, iconClass: "removeDesktopMenuItem", id: button.id+"_removeMenuItem"});
this.own(on(mItemRemove, "click", lang.hitch(this, "onCloseButtonClick", page)));
tabMenu.addChild(mItemRemove);
var mItemEdit = new MenuItem({label:editDesktopMessage, iconClass: "editDesktopMenuItem", id: button.id+"_editMenuItem"});
this.own(on(mItemEdit, "click", lang.hitch(null, "onEditDesktop", page)));
tabMenu.addChild(mItemEdit);
var mItemNew = new MenuItem({label:newDesktopMessage, iconClass: "newDesktopMenuItem", id: button.id+"_newMenuItem"});
this.own(on(mItemNew, "click", "onNewDesktop"));
tabMenu.addChild(mItemNew);
on(tabMenu, "open", lang.hitch(null,"checkTabMenuItemsState", button));
this.own(tabMenu);
}
if (!this._currentChild) {// put the first
// child into
// the
// tab order
button.focusNode.setAttribute(
"tabIndex", "0");
this._currentChild = page;
}
page.controlButton.closeNode.title = removeDesktopMessage;
// make sure all tabs have the same length
if (!this.isLeftToRight() && has("ie")
&& this._rectifyRtlTabList) {
this._rectifyRtlTabList();
}
}
});
The problem I'm faced with is that while my page doesn't throw any exceptions, it also doesn't show what it's supposed to show. I've placed a breakpoint in the constructor of the dijit/layout/BorderContainer class, and that doesn't appear to be called at all. I've debugged this, and I think there may be something wrong with how my DesktopBorderContainers are being formed, because as you can see below, desktopOid and desktopVersion appear twice, once as null and once as the correct value.
closable:false
containerNode:div#dijit_layout_BorderContainer_3.dijitBorderContainer.dijitContainer.dijitTabPane.dijitTabContainerTop-child.dijitTabContainerTop-dijitBorderContainer
desktopOid:"3"
desktopVersion:"1"
domNode:div#dijit_layout_BorderContainer_3.dijitBorderContainer.dijitContainer.dijitTabPane.dijitTabContainerTop-child.dijitTabContainerTop-dijitBorderContainer
id:"dijit_layout_BorderContainer_3"
ownerDocument:document
ownerDocumentBody:body.nihilo
params:Object
selected:true
srcNodeRef:div#dijit_layout_BorderContainer_3.dijitBorderContainer.dijitContainer.dijitTabPane.dijitTabContainerTop-child.dijitTabContainerTop-dijitBorderContainer
title:"↵ <span id="tabSpan3" title="">1</span>↵ <span title="Edit Desktop" ondblclick="onEditDesktop()"><img src="/alm/images/editDesktop.gif" border="0" class="tabIcon" /></span> ↵ "
_connects: Array(0)
_created:true
_inherited:Object
_supportingWidgets:Array(0)
_wrapper:div.dijitTabContainerTopChildWrapper.dijitHidden
__proto__: Object
constructor:function ()
declaredClass:"js.desktop.desktopBorderContainer"
desktopOid:null
desktopVersion:null
getInherited:function _2ef(name,args)
inherited:function _2e9(args,a,f)
isInstanceOf:function _2f2(cls)
onClose:function ()
resize:function (e)
__inherited:function _2e9(args,a,f)
__proto__:Object
I'm not sure why these appear twice, but I think it may have something to do with why it doesn't show.
What else can I do to figure out why these BorderContainers aren't showing?