From 81bea17aefb26859f825b9293c7c99192874806e Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 8 Nov 2011 20:40:44 +0400 Subject: upgrade Dojo to 1.6.1 --- lib/dijit/layout/StackController.js | 484 ++++++++++++++++++++++++------------ 1 file changed, 322 insertions(+), 162 deletions(-) (limited to 'lib/dijit/layout/StackController.js') diff --git a/lib/dijit/layout/StackController.js b/lib/dijit/layout/StackController.js index 033dadf6f..e0d2075bb 100644 --- a/lib/dijit/layout/StackController.js +++ b/lib/dijit/layout/StackController.js @@ -1,174 +1,334 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit.layout.StackController"]){ -dojo._hasResource["dijit.layout.StackController"]=true; +if(!dojo._hasResource["dijit.layout.StackController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit.layout.StackController"] = true; dojo.provide("dijit.layout.StackController"); dojo.require("dijit._Widget"); dojo.require("dijit._Templated"); dojo.require("dijit._Container"); dojo.require("dijit.form.ToggleButton"); -dojo.requireLocalization("dijit","common",null,"ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); -dojo.declare("dijit.layout.StackController",[dijit._Widget,dijit._Templated,dijit._Container],{templateString:"",containerId:"",buttonWidget:"dijit.layout._StackButton",postCreate:function(){ -dijit.setWaiRole(this.domNode,"tablist"); -this.pane2button={}; -this.pane2handles={}; -this.subscribe(this.containerId+"-startup","onStartup"); -this.subscribe(this.containerId+"-addChild","onAddChild"); -this.subscribe(this.containerId+"-removeChild","onRemoveChild"); -this.subscribe(this.containerId+"-selectChild","onSelectChild"); -this.subscribe(this.containerId+"-containerKeyPress","onContainerKeyPress"); -},onStartup:function(_1){ -dojo.forEach(_1.children,this.onAddChild,this); -if(_1.selected){ -this.onSelectChild(_1.selected); -} -},destroy:function(){ -for(var _2 in this.pane2button){ -this.onRemoveChild(dijit.byId(_2)); -} -this.inherited(arguments); -},onAddChild:function(_3,_4){ -var _5=dojo.getObject(this.buttonWidget); -var _6=new _5({id:this.id+"_"+_3.id,label:_3.title,dir:_3.dir,lang:_3.lang,showLabel:_3.showTitle,iconClass:_3.iconClass,closeButton:_3.closable,title:_3.tooltip}); -dijit.setWaiState(_6.focusNode,"selected","false"); -this.pane2handles[_3.id]=[this.connect(_3,"set",function(_7,_8){ -var _9={title:"label",showTitle:"showLabel",iconClass:"iconClass",closable:"closeButton",tooltip:"title"}[_7]; -if(_9){ -_6.set(_9,_8); -} -}),this.connect(_6,"onClick",dojo.hitch(this,"onButtonClick",_3)),this.connect(_6,"onClickCloseButton",dojo.hitch(this,"onCloseButtonClick",_3))]; -this.addChild(_6,_4); -this.pane2button[_3.id]=_6; -_3.controlButton=_6; -if(!this._currentChild){ -_6.focusNode.setAttribute("tabIndex","0"); -dijit.setWaiState(_6.focusNode,"selected","true"); -this._currentChild=_3; -} -if(!this.isLeftToRight()&&dojo.isIE&&this._rectifyRtlTabList){ -this._rectifyRtlTabList(); -} -},onRemoveChild:function(_a){ -if(this._currentChild===_a){ -this._currentChild=null; -} -dojo.forEach(this.pane2handles[_a.id],this.disconnect,this); -delete this.pane2handles[_a.id]; -var _b=this.pane2button[_a.id]; -if(_b){ -this.removeChild(_b); -delete this.pane2button[_a.id]; -_b.destroy(); -} -delete _a.controlButton; -},onSelectChild:function(_c){ -if(!_c){ -return; -} -if(this._currentChild){ -var _d=this.pane2button[this._currentChild.id]; -_d.set("checked",false); -dijit.setWaiState(_d.focusNode,"selected","false"); -_d.focusNode.setAttribute("tabIndex","-1"); -} -var _e=this.pane2button[_c.id]; -_e.set("checked",true); -dijit.setWaiState(_e.focusNode,"selected","true"); -this._currentChild=_c; -_e.focusNode.setAttribute("tabIndex","0"); -var _f=dijit.byId(this.containerId); -dijit.setWaiState(_f.containerNode,"labelledby",_e.id); -},onButtonClick:function(_10){ -var _11=dijit.byId(this.containerId); -_11.selectChild(_10); -},onCloseButtonClick:function(_12){ -var _13=dijit.byId(this.containerId); -_13.closeChild(_12); -if(this._currentChild){ -var b=this.pane2button[this._currentChild.id]; -if(b){ -dijit.focus(b.focusNode||b.domNode); -} -} -},adjacent:function(_14){ -if(!this.isLeftToRight()&&(!this.tabPosition||/top|bottom/.test(this.tabPosition))){ -_14=!_14; -} -var _15=this.getChildren(); -var _16=dojo.indexOf(_15,this.pane2button[this._currentChild.id]); -var _17=_14?1:_15.length-1; -return _15[(_16+_17)%_15.length]; -},onkeypress:function(e){ -if(this.disabled||e.altKey){ -return; -} -var _18=null; -if(e.ctrlKey||!e._djpage){ -var k=dojo.keys; -switch(e.charOrCode){ -case k.LEFT_ARROW: -case k.UP_ARROW: -if(!e._djpage){ -_18=false; -} -break; -case k.PAGE_UP: -if(e.ctrlKey){ -_18=false; -} -break; -case k.RIGHT_ARROW: -case k.DOWN_ARROW: -if(!e._djpage){ -_18=true; -} -break; -case k.PAGE_DOWN: -if(e.ctrlKey){ -_18=true; -} -break; -case k.DELETE: -if(this._currentChild.closable){ -this.onCloseButtonClick(this._currentChild); -} -dojo.stopEvent(e); -break; -default: -if(e.ctrlKey){ -if(e.charOrCode===k.TAB){ -this.adjacent(!e.shiftKey).onClick(); -dojo.stopEvent(e); -}else{ -if(e.charOrCode=="w"){ -if(this._currentChild.closable){ -this.onCloseButtonClick(this._currentChild); -} -dojo.stopEvent(e); -} -} -} -} -if(_18!==null){ -this.adjacent(_18).onClick(); -dojo.stopEvent(e); -} -} -},onContainerKeyPress:function(_19){ -_19.e._djpage=_19.page; -this.onkeypress(_19.e); -}}); -dojo.declare("dijit.layout._StackButton",dijit.form.ToggleButton,{tabIndex:"-1",postCreate:function(evt){ -dijit.setWaiRole((this.focusNode||this.domNode),"tab"); -this.inherited(arguments); -},onClick:function(evt){ -dijit.focus(this.focusNode); -},onClickCloseButton:function(evt){ -evt.stopPropagation(); -}}); +dojo.requireLocalization("dijit", "common", null, "ROOT,ar,ca,cs,da,de,el,es,fi,fr,he,hu,it,ja,kk,ko,nb,nl,pl,pt,pt-pt,ro,ru,sk,sl,sv,th,tr,zh,zh-tw"); + + +dojo.declare( + "dijit.layout.StackController", + [dijit._Widget, dijit._Templated, dijit._Container], + { + // summary: + // Set of buttons to select a page in a page list. + // description: + // Monitors the specified StackContainer, and whenever a page is + // added, deleted, or selected, updates itself accordingly. + + templateString: "", + + // containerId: [const] String + // The id of the page container that I point to + containerId: "", + + // buttonWidget: [const] String + // The name of the button widget to create to correspond to each page + buttonWidget: "dijit.layout._StackButton", + + constructor: function(){ + this.pane2button = {}; // mapping from pane id to buttons + this.pane2connects = {}; // mapping from pane id to this.connect() handles + this.pane2watches = {}; // mapping from pane id to watch() handles + }, + + buildRendering: function(){ + this.inherited(arguments); + dijit.setWaiRole(this.domNode, "tablist"); // TODO: unneeded? it's in template above. + }, + + postCreate: function(){ + this.inherited(arguments); + + // Listen to notifications from StackContainer + this.subscribe(this.containerId+"-startup", "onStartup"); + this.subscribe(this.containerId+"-addChild", "onAddChild"); + this.subscribe(this.containerId+"-removeChild", "onRemoveChild"); + this.subscribe(this.containerId+"-selectChild", "onSelectChild"); + this.subscribe(this.containerId+"-containerKeyPress", "onContainerKeyPress"); + }, + + onStartup: function(/*Object*/ info){ + // summary: + // Called after StackContainer has finished initializing + // tags: + // private + dojo.forEach(info.children, this.onAddChild, this); + if(info.selected){ + // Show button corresponding to selected pane (unless selected + // is null because there are no panes) + this.onSelectChild(info.selected); + } + }, + + destroy: function(){ + for(var pane in this.pane2button){ + this.onRemoveChild(dijit.byId(pane)); + } + this.inherited(arguments); + }, + + onAddChild: function(/*dijit._Widget*/ page, /*Integer?*/ insertIndex){ + // summary: + // Called whenever a page is added to the container. + // Create button corresponding to the page. + // tags: + // private + + // create an instance of the button widget + var cls = dojo.getObject(this.buttonWidget); + var button = new cls({ + id: this.id + "_" + page.id, + label: page.title, + dir: page.dir, + lang: page.lang, + showLabel: page.showTitle, + iconClass: page.iconClass, + closeButton: page.closable, + title: page.tooltip + }); + dijit.setWaiState(button.focusNode,"selected", "false"); + + + // map from page attribute to corresponding tab button attribute + var pageAttrList = ["title", "showTitle", "iconClass", "closable", "tooltip"], + buttonAttrList = ["label", "showLabel", "iconClass", "closeButton", "title"]; + + // watch() so events like page title changes are reflected in tab button + this.pane2watches[page.id] = dojo.map(pageAttrList, function(pageAttr, idx){ + return page.watch(pageAttr, function(name, oldVal, newVal){ + button.set(buttonAttrList[idx], newVal); + }); + }); + + // connections so that clicking a tab button selects the corresponding page + this.pane2connects[page.id] = [ + this.connect(button, 'onClick', dojo.hitch(this,"onButtonClick", page)), + this.connect(button, 'onClickCloseButton', dojo.hitch(this,"onCloseButtonClick", page)) + ]; + + this.addChild(button, insertIndex); + this.pane2button[page.id] = button; + page.controlButton = button; // this value might be overwritten if two tabs point to same container + if(!this._currentChild){ // put the first child into the tab order + button.focusNode.setAttribute("tabIndex", "0"); + dijit.setWaiState(button.focusNode, "selected", "true"); + this._currentChild = page; + } + // make sure all tabs have the same length + if(!this.isLeftToRight() && dojo.isIE && this._rectifyRtlTabList){ + this._rectifyRtlTabList(); + } + }, + + onRemoveChild: function(/*dijit._Widget*/ page){ + // summary: + // Called whenever a page is removed from the container. + // Remove the button corresponding to the page. + // tags: + // private + + if(this._currentChild === page){ this._currentChild = null; } + + // disconnect/unwatch connections/watches related to page being removed + dojo.forEach(this.pane2connects[page.id], dojo.hitch(this, "disconnect")); + delete this.pane2connects[page.id]; + dojo.forEach(this.pane2watches[page.id], function(w){ w.unwatch(); }); + delete this.pane2watches[page.id]; + + var button = this.pane2button[page.id]; + if(button){ + this.removeChild(button); + delete this.pane2button[page.id]; + button.destroy(); + } + delete page.controlButton; + }, + + onSelectChild: function(/*dijit._Widget*/ page){ + // summary: + // Called when a page has been selected in the StackContainer, either by me or by another StackController + // tags: + // private + + if(!page){ return; } + + if(this._currentChild){ + var oldButton=this.pane2button[this._currentChild.id]; + oldButton.set('checked', false); + dijit.setWaiState(oldButton.focusNode, "selected", "false"); + oldButton.focusNode.setAttribute("tabIndex", "-1"); + } + + var newButton=this.pane2button[page.id]; + newButton.set('checked', true); + dijit.setWaiState(newButton.focusNode, "selected", "true"); + this._currentChild = page; + newButton.focusNode.setAttribute("tabIndex", "0"); + var container = dijit.byId(this.containerId); + dijit.setWaiState(container.containerNode, "labelledby", newButton.id); + }, + + onButtonClick: function(/*dijit._Widget*/ page){ + // summary: + // Called whenever one of my child buttons is pressed in an attempt to select a page + // tags: + // private + + var container = dijit.byId(this.containerId); + container.selectChild(page); + }, + + onCloseButtonClick: function(/*dijit._Widget*/ page){ + // summary: + // Called whenever one of my child buttons [X] is pressed in an attempt to close a page + // tags: + // private + + var container = dijit.byId(this.containerId); + container.closeChild(page); + if(this._currentChild){ + var b = this.pane2button[this._currentChild.id]; + if(b){ + dijit.focus(b.focusNode || b.domNode); + } + } + }, + + // TODO: this is a bit redundant with forward, back api in StackContainer + adjacent: function(/*Boolean*/ forward){ + // summary: + // Helper for onkeypress to find next/previous button + // tags: + // private + + if(!this.isLeftToRight() && (!this.tabPosition || /top|bottom/.test(this.tabPosition))){ forward = !forward; } + // find currently focused button in children array + var children = this.getChildren(); + var current = dojo.indexOf(children, this.pane2button[this._currentChild.id]); + // pick next button to focus on + var offset = forward ? 1 : children.length - 1; + return children[ (current + offset) % children.length ]; // dijit._Widget + }, + + onkeypress: function(/*Event*/ e){ + // summary: + // Handle keystrokes on the page list, for advancing to next/previous button + // and closing the current page if the page is closable. + // tags: + // private + + if(this.disabled || e.altKey ){ return; } + var forward = null; + if(e.ctrlKey || !e._djpage){ + var k = dojo.keys; + switch(e.charOrCode){ + case k.LEFT_ARROW: + case k.UP_ARROW: + if(!e._djpage){ forward = false; } + break; + case k.PAGE_UP: + if(e.ctrlKey){ forward = false; } + break; + case k.RIGHT_ARROW: + case k.DOWN_ARROW: + if(!e._djpage){ forward = true; } + break; + case k.PAGE_DOWN: + if(e.ctrlKey){ forward = true; } + break; + case k.HOME: + case k.END: + var children = this.getChildren(); + if(children && children.length){ + children[e.charOrCode == k.HOME ? 0 : children.length-1].onClick(); + } + dojo.stopEvent(e); + break; + case k.DELETE: + if(this._currentChild.closable){ + this.onCloseButtonClick(this._currentChild); + } + dojo.stopEvent(e); + break; + default: + if(e.ctrlKey){ + if(e.charOrCode === k.TAB){ + this.adjacent(!e.shiftKey).onClick(); + dojo.stopEvent(e); + }else if(e.charOrCode == "w"){ + if(this._currentChild.closable){ + this.onCloseButtonClick(this._currentChild); + } + dojo.stopEvent(e); // avoid browser tab closing. + } + } + } + // handle next/previous page navigation (left/right arrow, etc.) + if(forward !== null){ + this.adjacent(forward).onClick(); + dojo.stopEvent(e); + } + } + }, + + onContainerKeyPress: function(/*Object*/ info){ + // summary: + // Called when there was a keypress on the container + // tags: + // private + info.e._djpage = info.page; + this.onkeypress(info.e); + } + }); + + +dojo.declare("dijit.layout._StackButton", + dijit.form.ToggleButton, + { + // summary: + // Internal widget used by StackContainer. + // description: + // The button-like or tab-like object you click to select or delete a page + // tags: + // private + + // Override _FormWidget.tabIndex. + // StackContainer buttons are not in the tab order by default. + // Probably we should be calling this.startupKeyNavChildren() instead. + tabIndex: "-1", + + buildRendering: function(/*Event*/ evt){ + this.inherited(arguments); + dijit.setWaiRole((this.focusNode || this.domNode), "tab"); + }, + + onClick: function(/*Event*/ evt){ + // summary: + // This is for TabContainer where the tabs are rather than button, + // so need to set focus explicitly (on some browsers) + // Note that you shouldn't override this method, but you can connect to it. + dijit.focus(this.focusNode); + + // ... now let StackController catch the event and tell me what to do + }, + + onClickCloseButton: function(/*Event*/ evt){ + // summary: + // StackContainer connects to this function; if your widget contains a close button + // then clicking it should call this function. + // Note that you shouldn't override this method, but you can connect to it. + evt.stopPropagation(); + } + }); + } -- cgit v1.2.3