source: [view]
dojo.provide("dojox.form.manager._Mixin");
dojo.require("dijit._Widget");
(function(){
var fm = dojox.form.manager,
aa = fm.actionAdapter = function(action){
// summary:
// Adapter that automates application of actions to arrays.
// action: Function:
// Function that takes three parameters: a name, an object
// (usually node or widget), and a value. This action will
// be applied to all elements of array.
return function(name, elems, value){
if(dojo.isArray(elems)){
dojo.forEach(elems, function(elem){
action.call(this, name, elem, value);
}, this);
}else{
action.apply(this, arguments);
}
};
},
ia = fm.inspectorAdapter = function(inspector){
// summary:
// Adapter that applies an inspector only to the first item of the array.
// inspector: Function:
// Function that takes three parameters: a name, an object
// (usually node or widget), and a value.
return function(name, elem, value){
return inspector.call(this, name, dojo.isArray(elem) ? elem[0] : elem, value);
};
},
skipNames = {domNode: 1, containerNode: 1, srcNodeRef: 1, bgIframe: 1},
keys = fm._keys = function(o){
// similar to dojox.lang.functional.keys
var list = [], key;
for(key in o){
if(o.hasOwnProperty(key)){
list.push(key);
}
}
return list;
},
registerWidget = function(widget){
var name = widget.get("name");
if(name && widget instanceof dijit.form._FormWidget){
if(name in this.formWidgets){
var a = this.formWidgets[name].widget;
if(dojo.isArray(a)){
a.push(widget);
}else{
this.formWidgets[name].widget = [a, widget];
}
}else{
this.formWidgets[name] = {widget: widget, connections: []};
}
}else{
name = null;
}
return name;
},
getObserversFromWidget = function(name){
var observers = {};
aa(function(_, w){
var o = w.get("observer");
if(o && typeof o == "string"){
dojo.forEach(o.split(","), function(o){
o = dojo.trim(o);
if(o && dojo.isFunction(this[o])){
observers[o] = 1;
}
}, this);
}
}).call(this, null, this.formWidgets[name].widget);
return keys(observers);
},
connectWidget = function(name, observers){
var t = this.formWidgets[name], w = t.widget, c = t.connections;
if(c.length){
dojo.forEach(c, dojo.disconnect);
c = t.connections = [];
}
if(dojo.isArray(w)){
// radio buttons
dojo.forEach(w, function(w){
dojo.forEach(observers, function(o){
c.push(dojo.connect(w, "onChange", this, function(evt){
// TODO: for some reason for radio button widgets
// w.checked != w.focusNode.checked when value changes.
// We test the underlying value to be 100% sure.
if(this.watching && dojo.attr(w.focusNode, "checked")){
this[o](w.get("value"), name, w, evt);
}
}));
}, this);
}, this);
}else{
// the rest
// the next line is a crude workaround for dijit.form.Button that fires onClick instead of onChange
var eventName = w.declaredClass == "dijit.form.Button" ?
"onClick" : "onChange";
dojo.forEach(observers, function(o){
c.push(dojo.connect(w, eventName, this, function(evt){
if(this.watching){
this[o](w.get("value"), name, w, evt);
}
}));
}, this);
}
};
dojo.declare("dojox.form.manager._Mixin", null, {
// summary:
// Mixin to orchestrate dynamic forms.
// description:
// This mixin provideas a foundation for an enhanced form
// functionality: unified access to individual form elements,
// unified "onchange" event processing, general event
// processing, I/O orchestration, and common form-related
// functionality. See additional mixins in dojox.form.manager
// namespace.
watching: true,
startup: function(){
// summary:
// Called after all the widgets have been instantiated and their
// dom nodes have been inserted somewhere under dojo.doc.body.
if(this._started){ return; }
this.formWidgets = {};
this.formNodes = {};
this.registerWidgetDescendants(this);
this.inherited(arguments);
},
destroy: function(){
// summary:
// Called when the widget is being destroyed
for(var name in this.formWidgets){
dojo.forEach(this.formWidgets[name].connections, dojo.disconnect);
}
this.formWidgets = {};
this.inherited(arguments);
},
// register/unregister widgets and nodes
registerWidget: function(widget){
// summary:
// Register a widget with the form manager
// widget: String|Node|dijit.form._FormWidget:
// A widget, or its widgetId, or its DOM node
// returns: Object:
// Returns self
if(typeof widget == "string"){
widget = dijit.byId(widget);
}else if(widget.tagName && widget.cloneNode){
widget = dijit.byNode(widget);
}
var name = registerWidget.call(this, widget);
if(name){
connectWidget.call(this, name, getObserversFromWidget.call(this, name));
}
return this;
},
unregisterWidget: function(name){
// summary:
// Removes the widget by name from internal tables unregistering
// connected observers
// name: String:
// Name of the to unregister
// returns: Object:
// Returns self
if(name in this.formWidgets){
dojo.forEach(this.formWidgets[name].connections, this.disconnect, this);
delete this.formWidgets[name];
}
return this;
},
registerWidgetDescendants: function(widget){
// summary:
// Register widget's descendants with the form manager
// widget: String|Node|dijit._Widget:
// A widget, or its widgetId, or its DOM node
// returns: Object:
// Returns self
// convert to widget, if required
if(typeof widget == "string"){
widget = dijit.byId(widget);
}else if(widget.tagName && widget.cloneNode){
widget = dijit.byNode(widget);
}
// build the map of widgets
var widgets = dojo.map(widget.getDescendants(), registerWidget, this);
// process observers for widgets
dojo.forEach(widgets, function(name){
if(name){
connectWidget.call(this, name, getObserversFromWidget.call(this, name));
}
}, this);
// do the same with nodes, if available
return this.registerNodeDescendants ?
this.registerNodeDescendants(widget.domNode) : this;
},
unregisterWidgetDescendants: function(widget){
// summary:
// Unregister widget's descendants with the form manager
// widget: String|Node|dijit._Widget:
// A widget, or its widgetId, or its DOM node
// returns: Object:
// Returns self
// convert to widget, if required
if(typeof widget == "string"){
widget = dijit.byId(widget);
}else if(widget.tagName && widget.cloneNode){
widget = dijit.byNode(widget);
}
// unregister widgets by names
dojo.forEach(
dojo.map(
widget.getDescendants(),
function(w){
return w instanceof dijit.form._FormWidget && w.get("name") || null;
}
),
function(name){
if(name){
this.unregisterNode(name);
}
},
this
);
// do the same with nodes, if available
return this.unregisterNodeDescendants ?
this.unregisterNodeDescendants(widget.domNode) : this;