222 lines
6.9 KiB
JavaScript
222 lines
6.9 KiB
JavaScript
//>>built
|
|
define("dojox/form/_SelectStackMixin", [
|
|
"dojo/_base/lang",
|
|
"dojo/_base/array",
|
|
"dijit/_base/manager",
|
|
"dojo/_base/connect",
|
|
"dojo/_base/declare"
|
|
], function(lang, array, manager, connect, declare){
|
|
|
|
return declare("dojox.form._SelectStackMixin", null, {
|
|
// summary:
|
|
// Mix this class in to a dijit.form._FormSelectWidget in order to
|
|
// provide support for "selectable" multiforms. The widget is pointed
|
|
// to a dijit.layout.StackContainer and will handle displaying and
|
|
// submitting the values of only the appropriate pane.
|
|
//
|
|
// The options for this widget will be automatically set - based on
|
|
// the panes that are in the stack container. The "title" attribute of
|
|
// the pane will be used for the display of the option. The "id" attribute
|
|
// of the pane will be used as the value of the option. In order to
|
|
// avoid running into unique ID constraint issues, a stackPrefix mechanism
|
|
// is provided.
|
|
|
|
// stackId: string
|
|
// The id of the stack that this widget is supposed to control
|
|
stackId: "",
|
|
|
|
// stackPrefix: string
|
|
// A prefix to remove from our stack pane ids when setting our options.
|
|
// This exists so that we won't run into unique ID constraints. For
|
|
// example, if stackPrefix is set to "foo_", and there are three panes
|
|
// in our stack with ids of "foo_a", "foo_b", and "foo_c", then the values
|
|
// of the options created for the stack controller widget will be "a",
|
|
// "b", and "c". This allows you to have multiple select stack widgets
|
|
// with the same values - without having to have the panes require the
|
|
// same ids.
|
|
stackPrefix: "",
|
|
|
|
_paneIdFromOption: function(/*String*/ oVal){
|
|
// summary: Gets the pane ID given an option value
|
|
return (this.stackPrefix || "") + oVal; // String
|
|
},
|
|
|
|
_optionValFromPane: function(/*String*/ id){
|
|
// summary: Gets the option value given a pane ID
|
|
var sp = this.stackPrefix;
|
|
if(sp && id.indexOf(sp) === 0){
|
|
return id.substring(sp.length); // String
|
|
}
|
|
return id; // String
|
|
},
|
|
|
|
_togglePane: function(/*dijit._Widget*/ pane, /*Boolean*/ shown){
|
|
// summary: called when a pane is either shown or hidden (so that
|
|
// we can toggle the widgets on it)
|
|
|
|
if(pane._shown != undefined && pane._shown == shown){ return; }
|
|
var widgets = array.filter(pane.getDescendants(), "return item.name;");
|
|
if(!shown){
|
|
// We are hiding - save the current state and then disable them
|
|
savedStates = {};
|
|
array.forEach(widgets, function(w){
|
|
savedStates[w.id] = w.disabled;
|
|
w.set("disabled", true);
|
|
});
|
|
pane._savedStates = savedStates;
|
|
}else{
|
|
// We are showing - restore our saved states
|
|
var savedStates = pane._savedStates||{};
|
|
array.forEach(widgets, function(w){
|
|
var state = savedStates[w.id];
|
|
if(state == undefined){
|
|
state = false;
|
|
}
|
|
w.set("disabled", state);
|
|
});
|
|
delete pane._savedStates;
|
|
}
|
|
pane._shown = shown;
|
|
},
|
|
|
|
_connectTitle: function(/*dijit._Widget*/ pane, /*String*/ value){
|
|
var fx = lang.hitch(this, function(title){
|
|
this.updateOption({value: value, label: title});
|
|
});
|
|
if(pane._setTitleAttr){
|
|
this.connect(pane, "_setTitleAttr", fx);
|
|
}else{
|
|
this.connect(pane, "attr", function(attr, val){
|
|
if(attr == "title" && arguments.length > 1){
|
|
fx(val);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
onAddChild: function(/*dijit._Widget*/ pane, /*Integer?*/ insertIndex){
|
|
// summary: Called when the stack container adds a new pane
|
|
if(!this._panes[pane.id]){
|
|
this._panes[pane.id] = pane;
|
|
var v = this._optionValFromPane(pane.id);
|
|
this.addOption({value: v, label: pane.title});
|
|
this._connectTitle(pane, v);
|
|
}
|
|
if(!pane.onShow || !pane.onHide || pane._shown == undefined){
|
|
pane.onShow = lang.hitch(this, "_togglePane", pane, true);
|
|
pane.onHide = lang.hitch(this, "_togglePane", pane, false);
|
|
pane.onHide();
|
|
}
|
|
},
|
|
|
|
_setValueAttr: function(v){
|
|
if("_savedValue" in this){
|
|
return;
|
|
}
|
|
this.inherited(arguments);
|
|
},
|
|
attr: function(/*String|Object*/name, /*Object?*/value){
|
|
if(name == "value" && arguments.length == 2 && "_savedValue" in this){
|
|
this._savedValue = value;
|
|
}
|
|
return this.inherited(arguments);
|
|
},
|
|
|
|
onRemoveChild: function(/*dijit._Widget*/ pane){
|
|
// summary: Called when the stack container removes a pane
|
|
if(this._panes[pane.id]){
|
|
delete this._panes[pane.id];
|
|
this.removeOption(this._optionValFromPane(pane.id));
|
|
}
|
|
},
|
|
|
|
onSelectChild: function(/*dijit._Widget*/ pane){
|
|
// summary: Called when the stack container selects a new pane
|
|
this._setValueAttr(this._optionValFromPane(pane.id));
|
|
},
|
|
|
|
onStartup: function(/*Object*/ info){
|
|
// summary: Called when the stack container is started up
|
|
var selPane = info.selected;
|
|
this.addOption(array.filter(array.map(info.children, function(c){
|
|
var v = this._optionValFromPane(c.id);
|
|
this._connectTitle(c, v);
|
|
var toAdd = null;
|
|
if(!this._panes[c.id]){
|
|
this._panes[c.id] = c;
|
|
toAdd = {value: v, label: c.title};
|
|
}
|
|
if(!c.onShow || !c.onHide || c._shown == undefined){
|
|
c.onShow = lang.hitch(this, "_togglePane", c, true);
|
|
c.onHide = lang.hitch(this, "_togglePane", c, false);
|
|
c.onHide();
|
|
}
|
|
if("_savedValue" in this && v === this._savedValue){
|
|
selPane = c;
|
|
}
|
|
return toAdd;
|
|
}, this), function(i){ return i;}));
|
|
var _this = this;
|
|
var fx = function(){
|
|
// This stuff needs to be run after we show our child, if
|
|
// the stack is going to show a different child than is
|
|
// selected - see trac #9396
|
|
delete _this._savedValue;
|
|
_this.onSelectChild(selPane);
|
|
if(!selPane._shown){
|
|
_this._togglePane(selPane, true);
|
|
}
|
|
};
|
|
if(selPane !== info.selected){
|
|
var stack = manager.byId(this.stackId);
|
|
var c = this.connect(stack, "_showChild", function(sel){
|
|
this.disconnect(c);
|
|
fx();
|
|
});
|
|
}else{
|
|
fx();
|
|
}
|
|
},
|
|
|
|
postMixInProperties: function(){
|
|
this._savedValue = this.value;
|
|
this.inherited(arguments);
|
|
this.connect(this, "onChange", "_handleSelfOnChange");
|
|
},
|
|
|
|
postCreate: function(){
|
|
this.inherited(arguments);
|
|
this._panes = {};
|
|
this._subscriptions = [
|
|
connect.subscribe(this.stackId + "-startup", this, "onStartup"),
|
|
connect.subscribe(this.stackId + "-addChild", this, "onAddChild"),
|
|
connect.subscribe(this.stackId + "-removeChild", this, "onRemoveChild"),
|
|
connect.subscribe(this.stackId + "-selectChild", this, "onSelectChild")
|
|
];
|
|
var stack = manager.byId(this.stackId);
|
|
if(stack && stack._started){
|
|
// If we have a stack, and it's already started, call our onStartup now
|
|
this.onStartup({children: stack.getChildren(), selected: stack.selectedChildWidget});
|
|
}
|
|
},
|
|
|
|
destroy: function(){
|
|
array.forEach(this._subscriptions, connect.unsubscribe);
|
|
delete this._panes; // Fixes memory leak in IE
|
|
this.inherited("destroy", arguments);
|
|
},
|
|
|
|
_handleSelfOnChange: function(/*String*/ val){
|
|
// summary: Called when form select widget's value has changed
|
|
var pane = this._panes[this._paneIdFromOption(val)];
|
|
if(pane){
|
|
var s = manager.byId(this.stackId);
|
|
if(pane == s.selectedChildWidget){
|
|
s._transition(pane);
|
|
}else{
|
|
s.selectChild(pane);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}); |