Modified: struts/struts2/trunk/plugins/dojo/src/main/resources/org/apache/struts2/static/dojo/struts_dojo.js.uncompressed.js URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/dojo/src/main/resources/org/apache/struts2/static/dojo/struts_dojo.js.uncompressed.js?view=diff&rev=535556&r1=535555&r2=535556 ============================================================================== --- struts/struts2/trunk/plugins/dojo/src/main/resources/org/apache/struts2/static/dojo/struts_dojo.js.uncompressed.js (original) +++ struts/struts2/trunk/plugins/dojo/src/main/resources/org/apache/struts2/static/dojo/struts_dojo.js.uncompressed.js Sat May 5 11:45:02 2007 @@ -22263,7 +22263,7 @@ if(this.notifyTopicsArray) { dojo.lang.forEach(this.notifyTopicsArray, function(topic) { try { - dojo.event.topic.publish(topic, data, type, e); + dojo.event.topic.publish(topic, data, type, e, self); } catch(ex){ self.log(ex); } @@ -22274,25 +22274,27 @@ var topicsArray = null; switch(type) { case "before": - topicsArray = this.beforeNotifyTopicsArray; + this.notifyTo(this.beforeNotifyTopicsArray, null, e); break; case "load": - topicsArray = this.afterNotifyTopicsArray; + this.notifyTo(this.afterNotifyTopicsArray, data, e); break; case "error": - topicsArray = this.errorNotifyTopicsArray; + this.notifyTo(this.errorNotifyTopicsArray, data, e); break; } - - this.notifyTo(topicsArray, data, type, e); }, - notifyTo : function(topicsArray, data, type, e) { + notifyTo : function(topicsArray, data, e) { var self = this; if(topicsArray) { dojo.lang.forEach(topicsArray, function(topic) { try { - dojo.event.topic.publish(topic, data, type, e); + if(data) { + dojo.event.topic.publish(topic, data, e, self); + } else { + dojo.event.topic.publish(topic, e, self); + } } catch(ex){ self.log(ex); } @@ -22537,6 +22539,9 @@ highlightColor : "", highlightDuration : 2000, + //only used when inside a tabbedpanel + disabled : false, + onDownloadStart : function(event) { if(!this.showLoading) { event.returnValue = false; @@ -22581,7 +22586,7 @@ var self = this; dojo.lang.forEach(this.notifyTopicsArray, function(topic) { try { - dojo.event.topic.publish(topic, data, type, e); + dojo.event.topic.publish(topic, data, type, e, self); } catch(ex) { self.log(ex); } @@ -22592,28 +22597,30 @@ var topicsArray = null; switch(type) { case "before": - topicsArray = this.beforeNotifyTopicsArray; + this.notifyTo(this.beforeNotifyTopicsArray, null, e); break; case "load": - topicsArray = this.afterNotifyTopicsArray; + this.notifyTo(this.afterNotifyTopicsArray, data, e); break; case "error": - topicsArray = this.errorNotifyTopicsArray; + this.notifyTo(this.errorNotifyTopicsArray, data, e); break; } - - this.notifyTo(topicsArray, data, type, e); }, - notifyTo : function(topicsArray, data, type, e) { + notifyTo : function(topicsArray, data, e) { var self = this; if(topicsArray) { dojo.lang.forEach(topicsArray, function(topic) { - try { - dojo.event.topic.publish(topic, data, type, e); - } catch(ex){ - self.log(ex); + try { + if(data) { + dojo.event.topic.publish(topic, data, e, self); + } else { + dojo.event.topic.publish(topic, e, self); } + } catch(ex){ + self.log(ex); + } }); } }, @@ -28107,6 +28114,723 @@ }); +dojo.provide("dojo.widget.PageContainer"); + + + + + + +dojo.widget.defineWidget("dojo.widget.PageContainer", dojo.widget.HtmlWidget, { + // summary + // A container that has multiple children, but shows only + // one child at a time (like looking at the pages in a book one by one). + // + // Publishes topics <widgetId>-addChild, <widgetId>-removeChild, and <widgetId>-selectChild + // + // Can be base class for container, Wizard, Show, etc. + + isContainer: true, + + // doLayout: Boolean + // if true, change the size of my currently displayed child to match my size + doLayout: true, + + templateString: "<div dojoAttachPoint='containerNode'></div>", + + // selectedChild: String + // id of the currently shown page + selectedChild: "", + + fillInTemplate: function(args, frag) { + // Copy style info from input node to output node + var source = this.getFragNodeRef(frag); + dojo.html.copyStyle(this.domNode, source); + dojo.widget.PageContainer.superclass.fillInTemplate.apply(this, arguments); + }, + + postCreate: function(args, frag) { + if(this.children.length){ + // Setup each page panel + dojo.lang.forEach(this.children, this._setupChild, this); + + // Figure out which child to initially display + var initialChild; + if(this.selectedChild){ + this.selectChild(this.selectedChild); + }else{ + for(var i=0; i<this.children.length; i++){ + if(this.children[i].selected){ + this.selectChild(this.children[i]); + break; + } + } + if(!this.selectedChildWidget){ + this.selectChild(this.children[0]); + } + } + } + }, + + addChild: function(child){ + dojo.widget.PageContainer.superclass.addChild.apply(this, arguments); + this._setupChild(child); + + // in case the tab labels have overflowed from one line to two lines + this.onResized(); + + // if this is the first child, then select it + if(!this.selectedChildWidget){ + this.selectChild(child); + } + }, + + _setupChild: function(/*Widget*/ page){ + // Summary: Add the given child to this page container + + page.hide(); + + // since we are setting the width/height of the child elements, they need + // to be position:relative, or IE has problems (See bug #2033) + page.domNode.style.position="relative"; + + // publish the addChild event for panes added via addChild(), and the original panes too + dojo.event.topic.publish(this.widgetId+"-addChild", page); + }, + + removeChild: function(/*Widget*/ page){ + dojo.widget.PageContainer.superclass.removeChild.apply(this, arguments); + + // If we are being destroyed than don't run the code below (to select another page), because we are deleting + // every page one by one + if(this._beingDestroyed){ return; } + + // this will notify any tablists to remove a button; do this first because it may affect sizing + dojo.event.topic.publish(this.widgetId+"-removeChild", page); + + // in case the tab labels now take up one line instead of two lines + this.onResized(); + + if (this.selectedChildWidget === page) { + this.selectedChildWidget = undefined; + if (this.children.length > 0) { + this.selectChild(this.children[0], true); + } + } + }, + + selectChild: function(/*Widget*/ page, /*Widget*/ callingWidget){ + // summary + // Show the given widget (which must be one of my children) + page = dojo.widget.byId(page); + this.correspondingPageButton = callingWidget; + + // Deselect old page and select new one + if(this.selectedChildWidget){ + this._hideChild(this.selectedChildWidget); + } + this.selectedChildWidget = page; + this.selectedChild = page.widgetId; + this._showChild(page); + page.isFirstChild = (page == this.children[0]); + page.isLastChild = (page == this.children[this.children.length-1]); + dojo.event.topic.publish(this.widgetId+"-selectChild", page); + }, + + forward: function(){ + // Summary: advance to next page + var index = dojo.lang.find(this.children, this.selectedChildWidget); + this.selectChild(this.children[index+1]); + }, + + back: function(){ + // Summary: go back to previous page + var index = dojo.lang.find(this.children, this.selectedChildWidget); + this.selectChild(this.children[index-1]); + }, + + onResized: function(){ + // Summary: called when any page is shown, to make it fit the container correctly + if(this.doLayout && this.selectedChildWidget){ + with(this.selectedChildWidget.domNode.style){ + top = dojo.html.getPixelValue(this.containerNode, "padding-top", true); + left = dojo.html.getPixelValue(this.containerNode, "padding-left", true); + } + var content = dojo.html.getContentBox(this.containerNode); + this.selectedChildWidget.resizeTo(content.width, content.height); + } + }, + + _showChild: function(/*Widget*/ page) { + // size the current page (in case this is the first time it's being shown, or I have been resized) + if(this.doLayout){ + var content = dojo.html.getContentBox(this.containerNode); + page.resizeTo(content.width, content.height); + } + + page.selected=true; + page.show(); + }, + + _hideChild: function(/*Widget*/ page) { + page.selected=false; + page.hide(); + }, + + closeChild: function(/*Widget*/ page) { + // summary + // callback when user clicks the [X] to remove a page + // if onClose() returns true then remove and destroy the childd + var remove = page.onClose(this, page); + if(remove) { + this.removeChild(page); + // makes sure we can clean up executeScripts in ContentPane onUnLoad + page.destroy(); + } + }, + + destroy: function(){ + this._beingDestroyed = true; + dojo.event.topic.destroy(this.widgetId+"-addChild"); + dojo.event.topic.destroy(this.widgetId+"-removeChild"); + dojo.event.topic.destroy(this.widgetId+"-selectChild"); + dojo.widget.PageContainer.superclass.destroy.apply(this, arguments); + } +}); + + +dojo.widget.defineWidget( + "dojo.widget.PageController", + dojo.widget.HtmlWidget, + { + // summary + // Set of buttons to select a page in a page list. + // Monitors the specified PageContaine, and whenever a page is + // added, deleted, or selected, updates itself accordingly. + + templateString: "<span wairole='tablist' dojoAttachEvent='onKey'></span>", + isContainer: true, + + // containerId: String + // the id of the page container that I point to + containerId: "", + + // buttonWidget: String + // the name of the button widget to create to correspond to each page + buttonWidget: "PageButton", + + // class: String + // Class name to apply to the top dom node + "class": "dojoPageController", + + fillInTemplate: function() { + dojo.html.addClass(this.domNode, this["class"]); // "class" is a reserved word in JS + dojo.widget.wai.setAttr(this.domNode, "waiRole", "role", "tablist"); + }, + + postCreate: function(){ + this.pane2button = {}; // mapping from panes to buttons + + // If children have already been added to the page container then create buttons for them + var container = dojo.widget.byId(this.containerId); + if(container){ + dojo.lang.forEach(container.children, this.onAddChild, this); + } + + dojo.event.topic.subscribe(this.containerId+"-addChild", this, "onAddChild"); + dojo.event.topic.subscribe(this.containerId+"-removeChild", this, "onRemoveChild"); + dojo.event.topic.subscribe(this.containerId+"-selectChild", this, "onSelectChild"); + }, + + destroy: function(){ + dojo.event.topic.unsubscribe(this.containerId+"-addChild", this, "onAddChild"); + dojo.event.topic.unsubscribe(this.containerId+"-removeChild", this, "onRemoveChild"); + dojo.event.topic.unsubscribe(this.containerId+"-selectChild", this, "onSelectChild"); + dojo.widget.PageController.superclass.destroy.apply(this, arguments); + }, + + onAddChild: function(/*Widget*/ page){ + // summary + // Called whenever a page is added to the container. + // Create button corresponding to the page. + var button = dojo.widget.createWidget(this.buttonWidget, + { + label: page.label, + closeButton: page.closable + }); + this.addChild(button); + this.domNode.appendChild(button.domNode); + this.pane2button[page]=button; + page.controlButton = button; // this value might be overwritten if two tabs point to same container + + var _this = this; + dojo.event.connect(button, "onClick", function(){ _this.onButtonClick(page); }); + dojo.event.connect(button, "onCloseButtonClick", function(){ _this.onCloseButtonClick(page); }); + }, + + onRemoveChild: function(/*Widget*/ page){ + // summary + // Called whenever a page is removed from the container. + // Remove the button corresponding to the page. + if(this._currentChild == page){ this._currentChild = null; } + var button = this.pane2button[page]; + if(button){ + button.destroy(); + } + this.pane2button[page] = null; + }, + + onSelectChild: function(/*Widget*/ page){ + // Summary + // Called when a page has been selected in the PageContainer, either by me or by another PageController + if(this._currentChild){ + var oldButton=this.pane2button[this._currentChild]; + oldButton.clearSelected(); + } + var newButton=this.pane2button[page]; + newButton.setSelected(); + this._currentChild=page; + }, + + onButtonClick: function(/*Widget*/ page){ + // summary + // Called whenever one of my child buttons is pressed in an attempt to select a page + var container = dojo.widget.byId(this.containerId); // TODO: do this via topics? + container.selectChild(page, false, this); + }, + + onCloseButtonClick: function(/*Widget*/ page){ + // summary + // Called whenever one of my child buttons [X] is pressed in an attempt to close a page + var container = dojo.widget.byId(this.containerId); + container.closeChild(page); + }, + + onKey: function(/*Event*/ evt){ + // summary: + // Handle keystrokes on the page list, for advancing to next/previous button + + if( (evt.keyCode == evt.KEY_RIGHT_ARROW)|| + (evt.keyCode == evt.KEY_LEFT_ARROW) ){ + var current = 0; + var next = null; // the next button to focus on + + // find currently focused button in children array + var current = dojo.lang.find(this.children, this.pane2button[this._currentChild]); + + // pick next button to focus on + if(evt.keyCode == evt.KEY_RIGHT_ARROW){ + next = this.children[ (current+1) % this.children.length ]; + }else{ // is LEFT_ARROW + next = this.children[ (current+ (this.children.length-1)) % this.children.length ]; + } + + dojo.event.browser.stopEvent(evt); + next.onClick(); + } + } + } +); + +dojo.widget.defineWidget("dojo.widget.PageButton", dojo.widget.HtmlWidget, +{ + // summary + // Internal widget used by PageList. + // The button-like or tab-like object you click to select or delete a page + + templateString: "<span class='item'>" + + "<span dojoAttachEvent='onClick' dojoAttachPoint='titleNode' class='selectButton'>${this.label}</span>" + + "<span dojoAttachEvent='onClick:onCloseButtonClick' class='closeButton'>[X]</span>" + + "</span>", + + // label: String + // Name to print on the button + label: "foo", + + // closeButton: Boolean + // true iff we should also print a close icon to destroy corresponding page + closeButton: false, + + onClick: function(){ + // summary + // Basically this is the attach point PageController listens to, to select the page + this.focus(); + }, + + onCloseButtonMouseOver: function(){ + // summary + // The close button changes color a bit when you mouse over + dojo.html.addClass(this.closeButtonNode, "closeHover"); + }, + + onCloseButtonMouseOut: function(){ + // summary + // Revert close button to normal color on mouse out + dojo.html.removeClass(this.closeButtonNode, "closeHover"); + }, + + onCloseButtonClick: function(/*Event*/ evt){ + // summary + // Handle clicking the close button for this tab + }, + + setSelected: function(){ + // summary + // This is run whenever the page corresponding to this button has been selected + dojo.html.addClass(this.domNode, "current"); + this.titleNode.setAttribute("tabIndex","0"); + }, + + clearSelected: function(){ + // summary + // This function is run whenever the page corresponding to this button has been deselected (and another page has been shown) + dojo.html.removeClass(this.domNode, "current"); + this.titleNode.setAttribute("tabIndex","-1"); + }, + + focus: function(){ + // summary + // This will focus on the this button (for accessibility you need to do this when the button is selected) + if(this.titleNode.focus){ // mozilla 1.7 doesn't have focus() func + this.titleNode.focus(); + } + } +}); + +// These arguments can be specified for the children of a PageContainer. +// Since any widget can be specified as a PageContainer child, mix them +// into the base widget class. (This is a hack, but it's effective.) +dojo.lang.extend(dojo.widget.Widget, { + // label: String + // Label or title of this widget. Used by TabContainer to the name the tab, etc. + label: "", + + // selected: Boolean + // Is this child currently selected? + selected: false, + + // closable: Boolean + // True if user can close (destroy) this child, such as (for example) clicking the X on the tab. + closable: false, // true if user can close this tab pane + + onClose: function(){ + // summary: Callback if someone tries to close the child, child will be closed if func returns true + return true; + } +}); + +dojo.provide("dojo.widget.TabContainer"); + + + + + + + + +dojo.widget.defineWidget("dojo.widget.TabContainer", dojo.widget.PageContainer, { + + // summary + // A TabContainer is a container that has multiple panes, but shows only + // one pane at a time. There are a set of tabs corresponding to each pane, + // where each tab has the title (aka label) of the pane, and optionally a close button. + // + // Publishes topics <widgetId>-addChild, <widgetId>-removeChild, and <widgetId>-selectChild + // (where <widgetId> is the id of the TabContainer itself. + + // labelPosition: String + // Defines where tab labels go relative to tab content. + // "top", "bottom", "left-h", "right-h" + labelPosition: "top", + + // closeButton: String + // If closebutton=="tab", then every tab gets a close button. + // DEPRECATED: Should just say closable=true on each + // pane you want to be closable. + closeButton: "none", + + templateString: null, // override setting in PageContainer + templatePath: dojo.uri.moduleUri("dojo.widget", "templates/TabContainer.html"), + templateCssPath: dojo.uri.moduleUri("dojo.widget", "templates/TabContainer.css"), + + // selectedTab: String + // initially selected tab (widgetId) + // DEPRECATED: use selectedChild instead. + selectedTab: "", + + postMixInProperties: function() { + if(this.selectedTab){ + dojo.deprecated("selectedTab deprecated, use selectedChild instead, will be removed in", "0.5"); + this.selectedChild=this.selectedTab; + } + if(this.closeButton!="none"){ + dojo.deprecated("closeButton deprecated, use closable='true' on each child instead, will be removed in", "0.5"); + } + dojo.widget.TabContainer.superclass.postMixInProperties.apply(this, arguments); + }, + + fillInTemplate: function() { + // create the tab list that will have a tab (a.k.a. tab button) for each tab panel + this.tablist = dojo.widget.createWidget("TabController", + { + id: this.widgetId + "_tablist", + labelPosition: this.labelPosition, + doLayout: this.doLayout, + containerId: this.widgetId + }, this.tablistNode); + dojo.widget.TabContainer.superclass.fillInTemplate.apply(this, arguments); + }, + + postCreate: function(args, frag) { + dojo.widget.TabContainer.superclass.postCreate.apply(this, arguments); + + // size the container pane to take up the space not used by the tabs themselves + this.onResized(); + }, + + _setupChild: function(tab){ + if(this.closeButton=="tab" || this.closeButton=="pane"){ + // TODO: remove in 0.5 + tab.closable=true; + } + dojo.html.addClass(tab.domNode, "dojoTabPane"); + dojo.widget.TabContainer.superclass._setupChild.apply(this, arguments); + }, + + onResized: function(){ + // Summary: Configure the content pane to take up all the space except for where the tabs are + if(!this.doLayout){ return; } + + // position the labels and the container node + var labelAlign=this.labelPosition.replace(/-h/,""); + var children = [ + {domNode: this.tablist.domNode, layoutAlign: labelAlign}, + {domNode: this.containerNode, layoutAlign: "client"} + ]; + dojo.widget.html.layout(this.domNode, children); + + if(this.selectedChildWidget){ + var containerSize = dojo.html.getContentBox(this.containerNode); + this.selectedChildWidget.resizeTo(containerSize.width, containerSize.height); + } + }, + + selectTab: function(tab, callingWidget){ + dojo.deprecated("use selectChild() rather than selectTab(), selectTab() will be removed in", "0.5"); + this.selectChild(tab, callingWidget); + }, + + onKey: function(e){ + // summary + // Keystroke handling for keystrokes on the tab panel itself (that were bubbled up to me) + // Ctrl-up: focus is returned from the pane to the tab button + // Alt-del: close tab + if(e.keyCode == e.KEY_UP_ARROW && e.ctrlKey){ + // set focus to current tab + var button = this.correspondingTabButton || this.selectedTabWidget.tabButton; + button.focus(); + dojo.event.browser.stopEvent(e); + }else if(e.keyCode == e.KEY_DELETE && e.altKey){ + if (this.selectedChildWidget.closable){ + this.closeChild(this.selectedChildWidget); + dojo.event.browser.stopEvent(e); + } + } + }, + + destroy: function(){ + this.tablist.destroy(); + dojo.widget.TabContainer.superclass.destroy.apply(this, arguments); + } +}); + +dojo.widget.defineWidget( + "dojo.widget.TabController", + dojo.widget.PageController, + { + // summary + // Set of tabs (the things with labels and a close button, that you click to show a tab panel). + // Lets the user select the currently shown pane in a TabContainer or PageContainer. + // TabController also monitors the TabContainer, and whenever a pane is + // added or deleted updates itself accordingly. + + templateString: "<div wairole='tablist' dojoAttachEvent='onKey'></div>", + + // labelPosition: String + // Defines where tab labels go relative to tab content. + // "top", "bottom", "left-h", "right-h" + labelPosition: "top", + + doLayout: true, + + // class: String + // Class name to apply to the top dom node + "class": "", + + // buttonWidget: String + // the name of the tab widget to create to correspond to each page + buttonWidget: "TabButton", + + postMixInProperties: function() { + if(!this["class"]){ + this["class"] = "dojoTabLabels-" + this.labelPosition + (this.doLayout ? "" : " dojoTabNoLayout"); + } + dojo.widget.TabController.superclass.postMixInProperties.apply(this, arguments); + } + } +); + +dojo.widget.defineWidget("dojo.widget.TabButton", dojo.widget.PageButton, +{ + // summary + // A tab (the thing you click to select a pane). + // Contains the title (aka label) of the pane, and optionally a close-button to destroy the pane. + // This is an internal widget and should not be instantiated directly. + + templateString: "<div class='dojoTab' dojoAttachEvent='onClick'>" + +"<div dojoAttachPoint='innerDiv'>" + +"<span dojoAttachPoint='titleNode' tabIndex='-1' waiRole='tab'>${this.label}</span>" + +"<span dojoAttachPoint='closeButtonNode' class='close closeImage' style='${this.closeButtonStyle}'" + +" dojoAttachEvent='onMouseOver:onCloseButtonMouseOver; onMouseOut:onCloseButtonMouseOut; onClick:onCloseButtonClick'></span>" + +"</div>" + +"</div>", + + postMixInProperties: function(){ + this.closeButtonStyle = this.closeButton ? "" : "display: none"; + dojo.widget.TabButton.superclass.postMixInProperties.apply(this, arguments); + }, + + fillInTemplate: function(){ + dojo.html.disableSelection(this.titleNode); + dojo.widget.TabButton.superclass.fillInTemplate.apply(this, arguments); + }, + + onCloseButtonClick: function(/*Event*/ evt){ + // since the close button is located inside the select button, make sure that the select + // button doesn't inadvertently get an onClick event + evt.stopPropagation(); + dojo.widget.TabButton.superclass.onCloseButtonClick.apply(this, arguments); + } +}); + + +dojo.widget.defineWidget( + "dojo.widget.a11y.TabButton", + dojo.widget.TabButton, + { + // summary + // Tab for display in high-contrast mode (where background images don't show up). + // This is an internal widget and shouldn't be instantiated directly. + + imgPath: dojo.uri.moduleUri("dojo.widget", "templates/images/tab_close.gif"), + + templateString: "<div class='dojoTab' dojoAttachEvent='onClick;onKey'>" + +"<div dojoAttachPoint='innerDiv'>" + +"<span dojoAttachPoint='titleNode' tabIndex='-1' waiRole='tab'>${this.label}</span>" + +"<img class='close' src='${this.imgPath}' alt='[x]' style='${this.closeButtonStyle}'" + +" dojoAttachEvent='onClick:onCloseButtonClick'>" + +"</div>" + +"</div>" + } +); + +dojo.provide("struts.widget.StrutsTabContainer"); + + + +dojo.widget.defineWidget( + "struts.widget.StrutsTabContainer", + dojo.widget.TabContainer, { + widgetType : "StrutsTabContainer", + + afterSelectTabNotifyTopics : "", + afterSelectTabNotifyTopicsArray : null, + beforeSelectTabNotifyTopics : "", + beforeSelectTabNotifyTopicsArray : null, + + disabledTabCssClass : "strutsDisabledTab", + + postCreate : function() { + struts.widget.StrutsTabContainer.superclass.postCreate.apply(this); + + //before topics + if(!dojo.string.isBlank(this.beforeSelectTabNotifyTopics)) { + this.beforeSelectTabNotifyTopicsArray = this.beforeSelectTabNotifyTopics.split(","); + } + + //after topics + if(!dojo.string.isBlank(this.afterSelectTabNotifyTopics)) { + this.afterSelectTabNotifyTopicsArray = this.afterSelectTabNotifyTopics.split(","); + } + + // add disabled class to disabled tabs + if(this.disabledTabCssClass) { + dojo.lang.forEach(this.children, function(div){ + if(div.disabled) { + this.disableTab(div); + } + }); + } + }, + + selectChild: function (tab, callingWidget) { + if(!tab.disabled) { + var cancel = {"cancel" : false}; + + if(this.beforeSelectTabNotifyTopicsArray) { + var self = this; + dojo.lang.forEach(this.beforeSelectTabNotifyTopicsArray, function(topic) { + try { + dojo.event.topic.publish(topic, self, tab, cancel); + } catch(ex){ + dojo.debug(ex); + } + }); + } + + if(!cancel.cancel) { + struts.widget.StrutsTabContainer.superclass.selectChild.apply(this, [tab, callingWidget]); + + if(this.afterSelectTabNotifyTopicsArray) { + var self = this; + dojo.lang.forEach(this.afterSelectTabNotifyTopicsArray, function(topic) { + try { + dojo.event.topic.publish(topic, self, tab, cancel); + } catch(ex){ + dojo.debug(ex); + } + }); + } + } + } + }, + + disableTab : function(t) { + var tabWidget = this.getTabWidget(t); + tabWidget.disabled = true; + dojo.html.addClass(tabWidget.controlButton.domNode, this.disabledTabCssClass); + }, + + enableTab : function(t) { + var tabWidget = this.getTabWidget(t); + tabWidget.disabled = false; + dojo.html.removeClass(tabWidget.controlButton.domNode, this.disabledTabCssClass); + }, + + getTabWidget : function(t) { + if(dojo.lang.isNumber(t)) { + //tab index + return this.children[t]; + } else if(dojo.lang.isString(t)) { + //tab id + return dojo.widget.byId(t); + } else { + //tab widget? + return t; + } + } +}); + dojo.kwCompoundRequire({ common: ["struts.widget.Bind", "struts.widget.BindDiv", @@ -28115,7 +28839,8 @@ "struts.widget.StrutsTimePicker", "struts.widget.StrutsDatePicker", "struts.widget.BindEvent", - "struts.widget.StrutsTreeSelector"] + "struts.widget.StrutsTreeSelector", + "struts.widget.StrutsTabContainer"] }); dojo.provide("struts.widget.*");
Modified: struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/div.ftl URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/div.ftl?view=diff&rev=535556&r1=535555&r2=535556 ============================================================================== --- struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/div.ftl (original) +++ struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/div.ftl Sat May 5 11:45:02 2007 @@ -26,6 +26,9 @@ <#if parameters.preload?exists> preload="${parameters.preload?string?html}"<#rt/> </#if> + <#if parameters.disabled?exists> + disabled="${parameters.disabled?string?html}"<#rt/> + </#if> <#include "/${parameters.templateDir}/ajax/ajax-common.ftl" /> <#include "/${parameters.templateDir}/simple/scripting-events.ftl" /> <#include "/${parameters.templateDir}/simple/common-attributes.ftl" /> Modified: struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/tabbedpanel.ftl URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/tabbedpanel.ftl?view=diff&rev=535556&r1=535555&r2=535556 ============================================================================== --- struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/tabbedpanel.ftl (original) +++ struts/struts2/trunk/plugins/dojo/src/main/resources/template/ajax/tabbedpanel.ftl Sat May 5 11:45:02 2007 @@ -1,3 +1,4 @@ +<link rel="stylesheet" href="${base}/struts/TabbedPanel.css" type="text/css"/> <div dojoType="struts:StrutsTabContainer" <#if parameters.cssStyle?if_exists != ""> style="${parameters.cssStyle?html}"<#rt/> @@ -31,6 +32,9 @@ </#if> <#if parameters.afterSelectTabNotifyTopics?if_exists != ""> afterSelectTabNotifyTopics="${parameters.afterSelectTabNotifyTopics?html}"<#rt/> + </#if> + <#if parameters.disabledTabCssClass?if_exists != ""> + disabledTabCssClass="${parameters.disabledTabCssClass?html}"<#rt/> </#if> <#include "/${parameters.templateDir}/simple/scripting-events.ftl" /> <#include "/${parameters.templateDir}/simple/common-attributes.ftl" />