You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mu...@apache.org on 2007/05/05 20:45:03 UTC
svn commit: r535556 [3/3] - in /struts/struts2/trunk/plugins/dojo/src/main:
java/org/apache/struts2/dojo/components/
java/org/apache/struts2/dojo/views/jsp/ui/
resources/org/apache/struts2/static/
resources/org/apache/struts2/static/dojo/ resources/org...
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" />