a:115:{s:9:"#provides";s:24:"dojox.widget.RollingList";s:9:"#resource";s:21:"widget/RollingList.js";s:9:"#requires";a:7:{i:0;a:3:{i:0;s:6:"common";i:1;s:16:"dijit._Templated";i:2;s:5:"dijit";}i:1;a:3:{i:0;s:6:"common";i:1;s:24:"dijit.layout.ContentPane";i:2;s:5:"dijit";}i:2;a:3:{i:0;s:6:"common";i:1;s:26:"dijit.layout._LayoutWidget";i:2;s:5:"dijit";}i:3;a:3:{i:0;s:6:"common";i:1;s:10:"dijit.Menu";i:2;s:5:"dijit";}i:4;a:2:{i:0;s:6:"common";i:1;s:18:"dojox.html.metrics";}i:5;a:3:{i:0;s:6:"common";i:1;s:17:"dijit.form.Button";i:2;s:5:"dijit";}i:6;a:3:{i:0;s:6:"common";i:1;s:9:"dojo.i18n";i:2;s:4:"dojo";}}s:29:"dojox.widget._RollingListPane";a:5:{s:4:"type";s:8:"Function";s:6:"chains";a:2:{s:9:"prototype";a:1:{i:0;s:24:"dijit.layout.ContentPane";}s:4:"call";a:3:{i:0;s:24:"dijit.layout.ContentPane";i:1;s:16:"dijit._Templated";i:2;s:16:"dijit._Contained";}}s:6:"mixins";a:1:{s:9:"prototype";a:2:{i:0;s:26:"dijit._Templated.prototype";i:1;s:26:"dijit._Contained.prototype";}}s:7:"summary";s:84:"a core pane that can be attached to a RollingList. All panes
should extend this one";s:9:"classlike";b:1;}s:44:"dojox.widget._RollingListPane.templateString";a:3:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:6:"string";s:7:"summary";s:12:"our template";}s:42:"dojox.widget._RollingListPane.parentWidget";a:3:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:24:"dojox.widget.RollingList";s:7:"summary";s:23:"Our rolling list widget";}s:40:"dojox.widget._RollingListPane.parentPane";a:3:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:29:"dojox.widget._RollingListPane";s:7:"summary";s:39:"The pane that immediately precedes ours";}s:35:"dojox.widget._RollingListPane.store";a:3:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:5:"store";s:7:"summary";s:21:"the store we must use";}s:35:"dojox.widget._RollingListPane.items";a:4:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:8:"instance";s:29:"dojox.widget._RollingListPane";s:4:"type";s:5:"item[";s:7:"summary";s:284:"an array of (possibly not-yet-loaded) items to display in this.
If this array is null, then the query and query options are used to
get the top-level items to use. This array is also used to watch and
see if the pane needs to be reloaded (store notifications are handled)
by the pane";}s:35:"dojox.widget._RollingListPane.query";a:3:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:6:"object";s:7:"summary";s:70:"a query to pass to the datastore. This is only used if items are null";}s:42:"dojox.widget._RollingListPane.queryOptions";a:3:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:6:"object";s:7:"summary";s:129:"query options to be passed to the datastore
focusByNode: boolean
set to false if the subclass will handle its own node focusing";}s:42:"dojox.widget._RollingListPane._focusByNode";a:3:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:7:"private";b:1;s:7:"summary";s:0:"";}s:38:"dojox.widget._RollingListPane.minWidth";a:4:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:8:"instance";s:29:"dojox.widget._RollingListPane";s:4:"type";s:7:"integer";s:7:"summary";s:31:"the width (in px) for this pane";}s:50:"dojox.widget._RollingListPane._setContentAndScroll";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:4:"cont";a:1:{s:4:"type";s:23:"String|DomNode|Nodelist";}s:13:"isFakeContent";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:82:" this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);";s:7:"summary";s:54:"sets the value of the content and scrolls it into view";s:7:"private";b:1;}s:46:"dojox.widget._RollingListPane._updateNodeWidth";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:1:"n";a:1:{s:4:"type";s:0:"";}s:3:"min";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:113:" n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}";s:7:"summary";s:52:"updates the min width of the pane to be minPaneWidth";s:7:"private";b:1;}s:47:"dojox.widget._RollingListPane._onMinWidthChange";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:1:"v";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:2450:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: '
|
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);";s:7:"private";b:1;s:7:"summary";s:0:"";}s:46:"dojox.widget._RollingListPane._setMinWidthAttr";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:1:"v";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:82:" if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}";s:7:"private";b:1;s:7:"summary";s:0:"";}s:37:"dojox.widget._RollingListPane.startup";a:4:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:6:"source";s:691:" if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);";s:7:"summary";s:0:"";}s:39:"dojox.widget._RollingListPane._focusKey";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:1:"e";a:1:{s:4:"type";s:5:"Event";}}s:6:"source";s:310:" if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}";s:7:"summary";s:44:"called when a keypress happens on the widget";s:7:"private";b:1;}s:35:"dojox.widget._RollingListPane.focus";a:5:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"force";a:1:{s:4:"type";s:7:"boolean";}}s:6:"source";s:269:" if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}";s:7:"summary";s:37:"sets the focus to this current widget";}s:40:"dojox.widget._RollingListPane._loadCheck";a:5:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:6:"source";s:324:" if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}";s:7:"summary";s:31:"checks that the store is loaded";s:7:"private";b:1;}s:40:"dojox.widget._RollingListPane._loadQuery";a:5:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:6:"source";s:186:" this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}";s:7:"summary";s:77:"sets the "loading" message and then kicks off a query asyncronously";s:7:"private";b:1;}s:42:"dojox.widget._RollingListPane._doLoadItems";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:5:"items";a:1:{s:4:"type";s:6:"item[]";}s:8:"callback";a:1:{s:4:"type";s:8:"function";}}s:6:"source";s:434:" var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
} ";s:7:"summary";s:74:"loads the given items, and then calls the callback when they
are finished.";s:7:"private";b:1;}s:38:"dojox.widget._RollingListPane._doQuery";a:5:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:6:"source";s:552:" var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}";s:7:"summary";s:64:"either runs the query or loads potentially not-yet-loaded items.";s:7:"private";b:1;}s:38:"dojox.widget._RollingListPane._hasItem";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:4:"item";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:177:" var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;";s:7:"summary";s:61:"returns whether or not the given item is handled by this
pane";s:7:"private";b:1;}s:40:"dojox.widget._RollingListPane._onSetItem";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:4:{s:4:"item";a:1:{s:4:"type";s:4:"item";}s:9:"attribute";a:1:{s:4:"type";s:21:"attribute-name-string";}s:8:"oldValue";a:1:{s:4:"type";s:14:"object | array";}s:8:"newValue";a:1:{s:4:"type";s:14:"object | array";}}s:6:"source";s:6622:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}";s:7:"private";b:1;s:7:"summary";s:0:"";}s:40:"dojox.widget._RollingListPane._onNewItem";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:7:"newItem";a:1:{s:4:"type";s:4:"item";}s:10:"parentInfo";a:2:{s:8:"optional";b:1;s:4:"type";s:6:"object";}}s:6:"source";s:7154:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}
},
_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
// Summary: called when an item is added to the store
var sel;
if((!parentInfo && !this.parentPane) ||
(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
this.items.push(newItem);
this._loadCheck(true);
}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
this._loadCheck(true);
}";s:7:"private";b:1;s:7:"summary";s:0:"";}s:43:"dojox.widget._RollingListPane._onDeleteItem";a:6:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:11:"deletedItem";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:7426:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}
},
_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
// Summary: called when an item is added to the store
var sel;
if((!parentInfo && !this.parentPane) ||
(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
this.items.push(newItem);
this._loadCheck(true);
}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
this._loadCheck(true);
}
},
_onDeleteItem: function(/* item */ deletedItem){
// Summary: called when an item is removed from the store
if(this._hasItem(deletedItem)){
this.items = dojo.filter(this.items, function(i){
return (i != deletedItem);
});
this._loadCheck(true);
}";s:7:"private";b:1;s:7:"summary";s:0:"";}s:42:"dojox.widget._RollingListPane.onFetchStart";a:4:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:6:"source";s:29:" return this.loadingMessage;";s:7:"summary";s:28:"called before a fetch starts";}s:42:"dojox.widget._RollingListPane.onFetchError";a:5:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"error";a:1:{s:4:"type";s:5:"Error";}}s:6:"source";s:27:" return this.errorMessage;";s:7:"summary";s:33:"called when a fetch error occurs.";}s:41:"dojox.widget._RollingListPane.onLoadStart";a:4:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:6:"source";s:29:" return this.loadingMessage;";s:7:"summary";s:27:"called before a load starts";}s:41:"dojox.widget._RollingListPane.onLoadError";a:5:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"error";a:1:{s:4:"type";s:5:"Error";}}s:6:"source";s:27:" return this.errorMessage;";s:7:"summary";s:32:"called when a load error occurs.";}s:37:"dojox.widget._RollingListPane.onItems";a:4:{s:9:"prototype";s:29:"dojox.widget._RollingListPane";s:4:"type";s:8:"Function";s:6:"source";s:26:" this._onLoadHandler(); ";s:7:"summary";s:135:"called after a fetch or load - at this point, this.items should be
set and loaded. Override this function to "do your stuff"";}s:55:"dojox.widget._RollingListPane.parentWidget._focusedPane";a:3:{s:8:"instance";s:29:"dojox.widget._RollingListPane";s:7:"private";b:1;s:7:"summary";s:0:"";}s:38:"dojox.widget._RollingListPane.isLoaded";a:2:{s:8:"instance";s:29:"dojox.widget._RollingListPane";s:7:"summary";s:0:"";}s:34:"dojox.widget._RollingListGroupPane";a:4:{s:4:"type";s:8:"Function";s:6:"chains";a:2:{s:9:"prototype";a:1:{i:0;s:29:"dojox.widget._RollingListPane";}s:4:"call";a:1:{i:0;s:29:"dojox.widget._RollingListPane";}}s:7:"summary";s:58:"a pane that will handle groups (treats them as menu items)";s:9:"classlike";b:1;}s:49:"dojox.widget._RollingListGroupPane.templateString";a:3:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:6:"string";s:7:"summary";s:12:"our template";}s:40:"dojox.widget._RollingListGroupPane._menu";a:5:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:8:"instance";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:10:"dijit.Menu";s:7:"summary";s:57:"The menu that we will call addChild() on for adding items";s:7:"private";b:1;}s:45:"dojox.widget._RollingListGroupPane._loadCheck";a:5:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:175:" var displayState = this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}";s:7:"summary";s:31:"checks that the store is loaded";s:7:"private";b:1;}s:46:"dojox.widget._RollingListGroupPane._setContent";a:6:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:4:"cont";a:1:{s:4:"type";s:23:"String|DomNode|Nodelist";}}s:6:"source";s:111:" if(!this._menu){
// Only set the content if we don't already have a menu
this.inherited(arguments);
}";s:7:"private";b:1;s:7:"summary";s:0:"";}s:52:"dojox.widget._RollingListGroupPane._onMinWidthChange";a:6:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:1:"v";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:9326:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}
},
_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
// Summary: called when an item is added to the store
var sel;
if((!parentInfo && !this.parentPane) ||
(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
this.items.push(newItem);
this._loadCheck(true);
}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
this._loadCheck(true);
}
},
_onDeleteItem: function(/* item */ deletedItem){
// Summary: called when an item is removed from the store
if(this._hasItem(deletedItem)){
this.items = dojo.filter(this.items, function(i){
return (i != deletedItem);
});
this._loadCheck(true);
}
},
onFetchStart: function(){
// summary:
// called before a fetch starts
return this.loadingMessage;
},
onFetchError: function(/*Error*/ error){
// summary:
// called when a fetch error occurs.
return this.errorMessage;
},
onLoadStart: function(){
// summary:
// called before a load starts
return this.loadingMessage;
},
onLoadError: function(/*Error*/ error){
// summary:
// called when a load error occurs.
return this.errorMessage;
},
onItems: function(){
// summary:
// called after a fetch or load - at this point, this.items should be
// set and loaded. Override this function to "do your stuff"
this._onLoadHandler();
}
});
dojo.declare("dojox.widget._RollingListGroupPane",
[dojox.widget._RollingListPane], {
// summary: a pane that will handle groups (treats them as menu items)
// templateString: string
// our template
templateString: '',
// _menu: dijit.Menu
// The menu that we will call addChild() on for adding items
_menu: null,
_loadCheck: function(){
// summary: checks that the store is loaded
var displayState = this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_setContent: function(/*String|DomNode|Nodelist*/cont){
if(!this._menu){
// Only set the content if we don't already have a menu
this.inherited(arguments);
}
},
_onMinWidthChange: function(v){
// override and resize the menu instead
if(!this._menu){ return; }
var dWidth = dojo.marginBox(this.domNode).w;
var mWidth = dojo.marginBox(this._menu.domNode).w;
this._updateNodeWidth(this._menu.domNode, v - (dWidth - mWidth));";s:7:"private";b:1;s:7:"summary";s:0:"";}s:42:"dojox.widget._RollingListGroupPane.onItems";a:4:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:1505:" var selectItem, hadChildren = false;
if(this._menu){
selectItem = this._getSelected();
this._menu.destroyRecursive();
}
this._menu = this._getMenu();
var child, selectMenuItem;
if(this.items.length){
dojo.forEach(this.items, function(item){
child = this.parentWidget._getMenuItemForItem(item, this);
if(child){
if(selectItem && this.parentWidget._itemsMatch(child.item, selectItem.item)){
selectMenuItem = child;
}
this._menu.addChild(child);
}
}, this);
}else{
child = this.parentWidget._getMenuItemForItem(null, this);
if(child){
this._menu.addChild(child);
}
}
if(selectMenuItem){
this._setSelected(selectMenuItem);
if((selectItem && !selectItem.children && selectMenuItem.children) ||
(selectItem && selectItem.children && !selectMenuItem.children)){
var itemPane = this.parentWidget._getPaneForItem(selectMenuItem.item, this, selectMenuItem.children);
if(itemPane){
this.parentWidget.addChild(itemPane, this.getIndexInParent() + 1);
}else{
this.parentWidget._removeAfter(this);
this.parentWidget._onItemClick(null, this, selectMenuItem.item, selectMenuItem.children);
}
}
}else if(selectItem){
this.parentWidget._removeAfter(this);
}
this.containerNode.innerHTML = "";
this.containerNode.appendChild(this._menu.domNode);
this.parentWidget.scrollIntoView(this);
this._checkScrollConnection(true);
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);";s:7:"summary";s:28:"called after a fetch or load";}s:57:"dojox.widget._RollingListGroupPane._checkScrollConnection";a:6:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:6:"doLoad";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:326:" var store = this.store
if(this._scrollConn){
this.disconnect(this._scrollConn);
}
delete this._scrollConn;
if(!dojo.every(this.items, function(i){return store.isItemLoaded(i);})){
if(doLoad){
this._loadVisibleItems();
}
this._scrollConn = this.connect(this.domNode, "onscroll", "_onScrollPane");
} ";s:7:"summary";s:65:"checks whether or not we need to connect to our onscroll
function";s:7:"private";b:1;}s:42:"dojox.widget._RollingListGroupPane.startup";a:4:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:89:" this.inherited(arguments);
this.parentWidget._updateClass(this.domNode, "GroupPane");";s:7:"summary";s:0:"";}s:40:"dojox.widget._RollingListGroupPane.focus";a:5:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"force";a:1:{s:4:"type";s:7:"boolean";}}s:6:"source";s:1139:" if(this._menu){
if(this._pendingFocus){
this.disconnect(this._pendingFocus);
}
delete this._pendingFocus;
// We focus the right widget - either the focusedChild, the
// selected node, the first menu item, or the menu itself
var focusWidget = this._menu.focusedChild;
if(!focusWidget){
var focusNode = dojo.query(".dojoxRollingListItemSelected", this.domNode)[0];
if(focusNode){
focusWidget = dijit.byNode(focusNode);
}
}
if(!focusWidget){
focusWidget = this._menu.getChildren()[0] || this._menu;
}
this._focusByNode = false;
if(focusWidget.focusNode){
if(!this.parentWidget._savedFocus || force){
try{focusWidget.focusNode.focus();}catch(e){}
}
window.setTimeout(function(){
try{
dijit.scrollIntoView(focusWidget.focusNode);
}catch(e){}
}, 1);
}else if(focusWidget.focus){
if(!this.parentWidget._savedFocus || force){
focusWidget.focus();
}
}else{
this._focusByNode = true;
}
this.inherited(arguments);
}else if(!this._pendingFocus){
this._pendingFocus = this.connect(this, "onItems", "focus");
}";s:7:"summary";s:37:"sets the focus to this current widget";}s:43:"dojox.widget._RollingListGroupPane._getMenu";a:5:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:1188:" var self = this;
var menu = new dijit.Menu({
parentMenu: this.parentPane ? this.parentPane._menu : null,
onCancel: function(/*Boolean*/ closeAll){
if(self.parentPane){
self.parentPane.focus(true);
}
},
_moveToPopup: function(/*Event*/ evt){
if(this.focusedChild && !this.focusedChild.disabled){
this.focusedChild._onClick(evt);
}
}
}, this.menuNode);
this.connect(menu, "onItemClick", function(/*dijit.MenuItem*/ item, /*Event*/ evt){
if(item.disabled){ return; }
evt.alreadySelected = dojo.hasClass(item.domNode, "dojoxRollingListItemSelected");
if(evt.alreadySelected &&
((evt.type == "keypress" && evt.charOrCode != dojo.keys.ENTER) ||
(evt.type == "internal"))){
var p = this.parentWidget.getChildren()[this.getIndexInParent() + 1];
if(p){
p.focus(true);
this.parentWidget.scrollIntoView(p);
}
}else{
this._setSelected(item, menu);
this.parentWidget._onItemClick(evt, this, item.item, item.children);
if(evt.type == "keypress" && evt.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
}
});
if(!menu._started){
menu.startup();
}
return menu;";s:7:"summary";s:53:"returns a widget to be used for the container widget.";s:7:"private";b:1;}s:48:"dojox.widget._RollingListGroupPane._onScrollPane";a:5:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:177:" if(this._visibleLoadPending){
window.clearTimeout(this._visibleLoadPending);
}
this._visibleLoadPending = window.setTimeout(dojo.hitch(this, "_loadVisibleItems"), 500);";s:7:"summary";s:132:"called when the pane has been scrolled - it sets a timeout
so that we don't try and load our visible items too often during
a scroll";s:7:"private";b:1;}s:46:"dojox.widget._RollingListGroupPane._layoutHack";a:5:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:288:" if(dojo.isFF == 2 && !this._layoutHackHandle){
var node=this.domNode;
var old = node.style.opacity;
node.style.opacity = "0.999";
this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
this._layoutHackHandle = null;
node.style.opacity = old;
}), 0);
}";s:7:"summary";s:112:"work around table sizing bugs on FF2 by forcing redraw
note - this function is taken from dijit.form._FormWidget";s:7:"private";b:1;}s:52:"dojox.widget._RollingListGroupPane._loadVisibleItems";a:5:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:1733:" delete this._visibleLoadPending
var menu = this._menu;
if(!menu){ return; }
var children = menu.getChildren();
if(!children || !children.length){ return; }
var gpbme = function(n, m, pb){
var s = dojo.getComputedStyle(n);
var r = 0;
if(m){ r += dojo._getMarginExtents(n, s).t; }
if(pb){ r += dojo._getPadBorderExtents(n, s).t; }
return r;
};
var topOffset = gpbme(this.domNode, false, true) +
gpbme(this.containerNode, true, true) +
gpbme(menu.domNode, true, true) +
gpbme(children[0].domNode, true, false);
var h = dojo.contentBox(this.domNode).h;
var minOffset = this.domNode.scrollTop - topOffset - (h/2);
var maxOffset = minOffset + (3*h/2);
var menuItemsToLoad = dojo.filter(children, function(c){
var cnt = c.domNode.offsetTop;
var s = c.store;
var i = c.item;
return (cnt >= minOffset && cnt <= maxOffset && !s.isItemLoaded(i));
})
var itemsToLoad = dojo.map(menuItemsToLoad, function(c){
return c.item;
});
var onItems = dojo.hitch(this, function(){
var selectItem = this._getSelected();
var selectMenuItem;
dojo.forEach(itemsToLoad, function(item, idx){
var newItem = this.parentWidget._getMenuItemForItem(item, this);
var oItem = menuItemsToLoad[idx];
var oIdx = oItem.getIndexInParent();
menu.removeChild(oItem);
if(newItem){
if(selectItem && this.parentWidget._itemsMatch(newItem.item, selectItem.item)){
selectMenuItem = newItem;
}
menu.addChild(newItem, oIdx);
if(menu.focusedChild == oItem){
menu.focusChild(newItem);
}
}
oItem.destroy();
}, this);
this._checkScrollConnection(false);
this._layoutHack();
});
this._doLoadItems(itemsToLoad, onItems);";s:7:"summary";s:54:"loads the items that are currently visible in the pane";s:7:"private";b:1;}s:47:"dojox.widget._RollingListGroupPane._getSelected";a:6:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:4:"menu";a:2:{s:8:"optional";b:1;s:4:"type";s:10:"dijit.Menu";}}s:6:"source";s:258:" if(!menu){ menu = this._menu; }
if(menu){
var children = this._menu.getChildren();
for(var i = 0, item; (item = children[i]); i++){
if(dojo.hasClass(item.domNode, "dojoxRollingListItemSelected")){
return item;
}
}
}
return null;";s:7:"summary";s:61:"returns the selected menu item - or null if none are selected";s:7:"private";b:1;}s:47:"dojox.widget._RollingListGroupPane._setSelected";a:6:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:4:"item";a:2:{s:8:"optional";b:1;s:4:"type";s:14:"dijit.MenuItem";}s:4:"menu";a:2:{s:8:"optional";b:1;s:4:"type";s:10:"dijit.Menu";}}s:6:"source";s:217:" if(!menu){ menu = this._menu;}
if(menu){
dojo.forEach(menu.getChildren(), function(i){
this.parentWidget._updateClass(i.domNode, "Item", {"Selected": (item && (i == item && !i.disabled))});
}, this);
}";s:7:"summary";s:67:"selectes the given item in the given menu (defaults to pane's menu)";s:7:"private";b:1;}s:42:"dojox.widget._RollingListGroupPane.destroy";a:4:{s:9:"prototype";s:34:"dojox.widget._RollingListGroupPane";s:4:"type";s:8:"Function";s:6:"source";s:103:" if(this._layoutHackHandle){
clearTimeout(this._layoutHackHandle);
}
this.inherited(arguments);";s:7:"summary";s:0:"";}s:58:"dojox.widget._RollingListGroupPane.containerNode.innerHTML";a:2:{s:8:"instance";s:34:"dojox.widget._RollingListGroupPane";s:7:"summary";s:0:"";}s:46:"dojox.widget._RollingListGroupPane._scrollConn";a:3:{s:8:"instance";s:34:"dojox.widget._RollingListGroupPane";s:7:"private";b:1;s:7:"summary";s:0:"";}s:47:"dojox.widget._RollingListGroupPane._focusByNode";a:3:{s:8:"instance";s:34:"dojox.widget._RollingListGroupPane";s:7:"private";b:1;s:7:"summary";s:0:"";}s:48:"dojox.widget._RollingListGroupPane._pendingFocus";a:3:{s:8:"instance";s:34:"dojox.widget._RollingListGroupPane";s:7:"private";b:1;s:7:"summary";s:0:"";}s:54:"dojox.widget._RollingListGroupPane._visibleLoadPending";a:3:{s:8:"instance";s:34:"dojox.widget._RollingListGroupPane";s:7:"private";b:1;s:7:"summary";s:0:"";}s:52:"dojox.widget._RollingListGroupPane._layoutHackHandle";a:3:{s:8:"instance";s:34:"dojox.widget._RollingListGroupPane";s:7:"private";b:1;s:7:"summary";s:0:"";}s:24:"dojox.widget.RollingList";a:5:{s:4:"type";s:8:"Function";s:6:"chains";a:2:{s:9:"prototype";a:1:{i:0;s:13:"dijit._Widget";}s:4:"call";a:3:{i:0;s:13:"dijit._Widget";i:1;s:16:"dijit._Templated";i:2;s:16:"dijit._Container";}}s:6:"mixins";a:1:{s:9:"prototype";a:2:{i:0;s:26:"dijit._Templated.prototype";i:1;s:26:"dijit._Container.prototype";}}s:7:"summary";s:61:"a rolling list that can be tied to a data store with children";s:9:"classlike";b:1;}s:37:"dojox.widget.RollingList.templatePath";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:6:"string";s:7:"summary";s:19:"our template to use";}s:42:"dojox.widget.RollingList.widgetsInTemplate";a:2:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:7:"summary";s:0:"";}s:34:"dojox.widget.RollingList.className";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:6:"string";s:7:"summary";s:70:"an additional class (or space-separated classes) to add for our widget";}s:30:"dojox.widget.RollingList.store";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:8:"instance";s:24:"dojox.widget.RollingList";s:4:"type";s:5:"store";s:7:"summary";s:21:"the store we must use";}s:30:"dojox.widget.RollingList.query";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:6:"object";s:7:"summary";s:70:"a query to pass to the datastore. This is only used if items are null";}s:37:"dojox.widget.RollingList.queryOptions";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:6:"object";s:7:"summary";s:43:"query options to be passed to the datastore";}s:38:"dojox.widget.RollingList.childrenAttrs";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:7:"String[";s:7:"summary";s:53:"one ore more attributes that holds children of a node";}s:35:"dojox.widget.RollingList.parentAttr";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:6:"string";s:7:"summary";s:58:"the attribute to read for finding our parent item (if any)";}s:30:"dojox.widget.RollingList.value";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:8:"instance";s:24:"dojox.widget.RollingList";s:4:"type";s:4:"item";s:7:"summary";s:32:"The value that has been selected";}s:42:"dojox.widget.RollingList.executeOnDblClick";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:7:"boolean";s:7:"summary";s:183:"Set to true if you want to call onExecute when an item is
double-clicked, false if you want to call onExecute yourself. (mainly
used for popups to control how they want to be handled)";}s:37:"dojox.widget.RollingList.preloadItems";a:3:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:7:"boolean";s:7:"summary";s:390:"or int
if set to true, then onItems will be called only *after* all items have
been loaded (ie store.isLoaded will return true for all of them). If
false, then no preloading will occur. If set to an integer, preloading
will occur if the number of items is less than or equal to the value
of the integer. The onItems function will need to be aware of handling
items that may not be loaded";}s:36:"dojox.widget.RollingList.showButtons";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:8:"instance";s:24:"dojox.widget.RollingList";s:4:"type";s:7:"boolean";s:7:"summary";s:87:"if set to true, then buttons for "OK" and "Cancel" will be provided";}s:38:"dojox.widget.RollingList.okButtonLabel";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:8:"instance";s:24:"dojox.widget.RollingList";s:4:"type";s:6:"string";s:7:"summary";s:94:"The string to use for the OK button - will use dijit's common "OK" string
if not set";}s:42:"dojox.widget.RollingList.cancelButtonLabel";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:8:"instance";s:24:"dojox.widget.RollingList";s:4:"type";s:6:"string";s:7:"summary";s:102:"The string to use for the Cancel button - will use dijit's common
"Cancel" string if not set";}s:37:"dojox.widget.RollingList.minPaneWidth";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:8:"instance";s:24:"dojox.widget.RollingList";s:4:"type";s:7:"integer";s:7:"summary";s:117:"the minimum pane width (in px) for all child panes. If they are narrower,
the width will be increased to this value.";}s:44:"dojox.widget.RollingList.postMixInProperties";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:216:" this.inherited(arguments);
var loc = dojo.i18n.getLocalization("dijit", "common");
this.okButtonLabel = this.okButtonLabel || loc.buttonOk;
this.cancelButtonLabel = this.cancelButtonLabel || loc.buttonCancel;";s:7:"summary";s:38:"Mix in our labels, if they are not set";}s:44:"dojox.widget.RollingList._setShowButtonsAttr";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:6:"doShow";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:396:" var needsLayout = false;
if((this.showButtons != doShow && this._started) ||
(this.showButtons == doShow && !this.started)){
needsLayout = true;
}
dojo.toggleClass(this.domNode, "dojoxRollingListButtonsHidden", !doShow);
this.showButtons = doShow;
if(needsLayout){
if(this._started){
this.layout();
}else{
window.setTimeout(dojo.hitch(this, "layout"), 0);
}
}";s:7:"summary";s:49:"Sets the visibility of the buttons for the widget";s:7:"private";b:1;}s:36:"dojox.widget.RollingList._itemsMatch";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:5:"item1";a:1:{s:4:"type";s:4:"item";}s:5:"item2";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:21149:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}
},
_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
// Summary: called when an item is added to the store
var sel;
if((!parentInfo && !this.parentPane) ||
(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
this.items.push(newItem);
this._loadCheck(true);
}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
this._loadCheck(true);
}
},
_onDeleteItem: function(/* item */ deletedItem){
// Summary: called when an item is removed from the store
if(this._hasItem(deletedItem)){
this.items = dojo.filter(this.items, function(i){
return (i != deletedItem);
});
this._loadCheck(true);
}
},
onFetchStart: function(){
// summary:
// called before a fetch starts
return this.loadingMessage;
},
onFetchError: function(/*Error*/ error){
// summary:
// called when a fetch error occurs.
return this.errorMessage;
},
onLoadStart: function(){
// summary:
// called before a load starts
return this.loadingMessage;
},
onLoadError: function(/*Error*/ error){
// summary:
// called when a load error occurs.
return this.errorMessage;
},
onItems: function(){
// summary:
// called after a fetch or load - at this point, this.items should be
// set and loaded. Override this function to "do your stuff"
this._onLoadHandler();
}
});
dojo.declare("dojox.widget._RollingListGroupPane",
[dojox.widget._RollingListPane], {
// summary: a pane that will handle groups (treats them as menu items)
// templateString: string
// our template
templateString: '',
// _menu: dijit.Menu
// The menu that we will call addChild() on for adding items
_menu: null,
_loadCheck: function(){
// summary: checks that the store is loaded
var displayState = this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_setContent: function(/*String|DomNode|Nodelist*/cont){
if(!this._menu){
// Only set the content if we don't already have a menu
this.inherited(arguments);
}
},
_onMinWidthChange: function(v){
// override and resize the menu instead
if(!this._menu){ return; }
var dWidth = dojo.marginBox(this.domNode).w;
var mWidth = dojo.marginBox(this._menu.domNode).w;
this._updateNodeWidth(this._menu.domNode, v - (dWidth - mWidth));
},
onItems: function(){
// summary:
// called after a fetch or load
var selectItem, hadChildren = false;
if(this._menu){
selectItem = this._getSelected();
this._menu.destroyRecursive();
}
this._menu = this._getMenu();
var child, selectMenuItem;
if(this.items.length){
dojo.forEach(this.items, function(item){
child = this.parentWidget._getMenuItemForItem(item, this);
if(child){
if(selectItem && this.parentWidget._itemsMatch(child.item, selectItem.item)){
selectMenuItem = child;
}
this._menu.addChild(child);
}
}, this);
}else{
child = this.parentWidget._getMenuItemForItem(null, this);
if(child){
this._menu.addChild(child);
}
}
if(selectMenuItem){
this._setSelected(selectMenuItem);
if((selectItem && !selectItem.children && selectMenuItem.children) ||
(selectItem && selectItem.children && !selectMenuItem.children)){
var itemPane = this.parentWidget._getPaneForItem(selectMenuItem.item, this, selectMenuItem.children);
if(itemPane){
this.parentWidget.addChild(itemPane, this.getIndexInParent() + 1);
}else{
this.parentWidget._removeAfter(this);
this.parentWidget._onItemClick(null, this, selectMenuItem.item, selectMenuItem.children);
}
}
}else if(selectItem){
this.parentWidget._removeAfter(this);
}
this.containerNode.innerHTML = "";
this.containerNode.appendChild(this._menu.domNode);
this.parentWidget.scrollIntoView(this);
this._checkScrollConnection(true);
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_checkScrollConnection: function(doLoad){
// summary: checks whether or not we need to connect to our onscroll
// function
var store = this.store
if(this._scrollConn){
this.disconnect(this._scrollConn);
}
delete this._scrollConn;
if(!dojo.every(this.items, function(i){return store.isItemLoaded(i);})){
if(doLoad){
this._loadVisibleItems();
}
this._scrollConn = this.connect(this.domNode, "onscroll", "_onScrollPane");
}
},
startup: function(){
this.inherited(arguments);
this.parentWidget._updateClass(this.domNode, "GroupPane");
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this._menu){
if(this._pendingFocus){
this.disconnect(this._pendingFocus);
}
delete this._pendingFocus;
// We focus the right widget - either the focusedChild, the
// selected node, the first menu item, or the menu itself
var focusWidget = this._menu.focusedChild;
if(!focusWidget){
var focusNode = dojo.query(".dojoxRollingListItemSelected", this.domNode)[0];
if(focusNode){
focusWidget = dijit.byNode(focusNode);
}
}
if(!focusWidget){
focusWidget = this._menu.getChildren()[0] || this._menu;
}
this._focusByNode = false;
if(focusWidget.focusNode){
if(!this.parentWidget._savedFocus || force){
try{focusWidget.focusNode.focus();}catch(e){}
}
window.setTimeout(function(){
try{
dijit.scrollIntoView(focusWidget.focusNode);
}catch(e){}
}, 1);
}else if(focusWidget.focus){
if(!this.parentWidget._savedFocus || force){
focusWidget.focus();
}
}else{
this._focusByNode = true;
}
this.inherited(arguments);
}else if(!this._pendingFocus){
this._pendingFocus = this.connect(this, "onItems", "focus");
}
},
_getMenu: function(){
// summary: returns a widget to be used for the container widget.
var self = this;
var menu = new dijit.Menu({
parentMenu: this.parentPane ? this.parentPane._menu : null,
onCancel: function(/*Boolean*/ closeAll){
if(self.parentPane){
self.parentPane.focus(true);
}
},
_moveToPopup: function(/*Event*/ evt){
if(this.focusedChild && !this.focusedChild.disabled){
this.focusedChild._onClick(evt);
}
}
}, this.menuNode);
this.connect(menu, "onItemClick", function(/*dijit.MenuItem*/ item, /*Event*/ evt){
if(item.disabled){ return; }
evt.alreadySelected = dojo.hasClass(item.domNode, "dojoxRollingListItemSelected");
if(evt.alreadySelected &&
((evt.type == "keypress" && evt.charOrCode != dojo.keys.ENTER) ||
(evt.type == "internal"))){
var p = this.parentWidget.getChildren()[this.getIndexInParent() + 1];
if(p){
p.focus(true);
this.parentWidget.scrollIntoView(p);
}
}else{
this._setSelected(item, menu);
this.parentWidget._onItemClick(evt, this, item.item, item.children);
if(evt.type == "keypress" && evt.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
}
});
if(!menu._started){
menu.startup();
}
return menu;
},
_onScrollPane: function(){
// summary: called when the pane has been scrolled - it sets a timeout
// so that we don't try and load our visible items too often during
// a scroll
if(this._visibleLoadPending){
window.clearTimeout(this._visibleLoadPending);
}
this._visibleLoadPending = window.setTimeout(dojo.hitch(this, "_loadVisibleItems"), 500);
},
_layoutHack: function(){
// summary: work around table sizing bugs on FF2 by forcing redraw
// note - this function is taken from dijit.form._FormWidget
if(dojo.isFF == 2 && !this._layoutHackHandle){
var node=this.domNode;
var old = node.style.opacity;
node.style.opacity = "0.999";
this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
this._layoutHackHandle = null;
node.style.opacity = old;
}), 0);
}
},
_loadVisibleItems: function(){
// summary: loads the items that are currently visible in the pane
delete this._visibleLoadPending
var menu = this._menu;
if(!menu){ return; }
var children = menu.getChildren();
if(!children || !children.length){ return; }
var gpbme = function(n, m, pb){
var s = dojo.getComputedStyle(n);
var r = 0;
if(m){ r += dojo._getMarginExtents(n, s).t; }
if(pb){ r += dojo._getPadBorderExtents(n, s).t; }
return r;
};
var topOffset = gpbme(this.domNode, false, true) +
gpbme(this.containerNode, true, true) +
gpbme(menu.domNode, true, true) +
gpbme(children[0].domNode, true, false);
var h = dojo.contentBox(this.domNode).h;
var minOffset = this.domNode.scrollTop - topOffset - (h/2);
var maxOffset = minOffset + (3*h/2);
var menuItemsToLoad = dojo.filter(children, function(c){
var cnt = c.domNode.offsetTop;
var s = c.store;
var i = c.item;
return (cnt >= minOffset && cnt <= maxOffset && !s.isItemLoaded(i));
})
var itemsToLoad = dojo.map(menuItemsToLoad, function(c){
return c.item;
});
var onItems = dojo.hitch(this, function(){
var selectItem = this._getSelected();
var selectMenuItem;
dojo.forEach(itemsToLoad, function(item, idx){
var newItem = this.parentWidget._getMenuItemForItem(item, this);
var oItem = menuItemsToLoad[idx];
var oIdx = oItem.getIndexInParent();
menu.removeChild(oItem);
if(newItem){
if(selectItem && this.parentWidget._itemsMatch(newItem.item, selectItem.item)){
selectMenuItem = newItem;
}
menu.addChild(newItem, oIdx);
if(menu.focusedChild == oItem){
menu.focusChild(newItem);
}
}
oItem.destroy();
}, this);
this._checkScrollConnection(false);
this._layoutHack();
});
this._doLoadItems(itemsToLoad, onItems);
},
_getSelected: function(/*dijit.Menu?*/ menu){
// summary:
// returns the selected menu item - or null if none are selected
if(!menu){ menu = this._menu; }
if(menu){
var children = this._menu.getChildren();
for(var i = 0, item; (item = children[i]); i++){
if(dojo.hasClass(item.domNode, "dojoxRollingListItemSelected")){
return item;
}
}
}
return null;
},
_setSelected: function(/*dijit.MenuItem?*/ item, /*dijit.Menu?*/ menu){
// summary:
// selectes the given item in the given menu (defaults to pane's menu)
if(!menu){ menu = this._menu;}
if(menu){
dojo.forEach(menu.getChildren(), function(i){
this.parentWidget._updateClass(i.domNode, "Item", {"Selected": (item && (i == item && !i.disabled))});
}, this);
}
},
destroy: function(){
if(this._layoutHackHandle){
clearTimeout(this._layoutHackHandle);
}
this.inherited(arguments);
}
});
dojo.declare("dojox.widget.RollingList",
[dijit._Widget, dijit._Templated, dijit._Container], {
// summary: a rolling list that can be tied to a data store with children
// templatePath: string
// our template to use
templatePath: dojo.moduleUrl("dojox.widget", "RollingList/RollingList.html"),
widgetsInTemplate: true,
// className: string
// an additional class (or space-separated classes) to add for our widget
className: "",
// store: store
// the store we must use
store: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// childrenAttrs: String[]
// one ore more attributes that holds children of a node
childrenAttrs: ["children"],
// parentAttr: string
// the attribute to read for finding our parent item (if any)
parentAttr: "",
// value: item
// The value that has been selected
value: null,
// executeOnDblClick: boolean
// Set to true if you want to call onExecute when an item is
// double-clicked, false if you want to call onExecute yourself. (mainly
// used for popups to control how they want to be handled)
executeOnDblClick: true,
// preloadItems: boolean or int
// if set to true, then onItems will be called only *after* all items have
// been loaded (ie store.isLoaded will return true for all of them). If
// false, then no preloading will occur. If set to an integer, preloading
// will occur if the number of items is less than or equal to the value
// of the integer. The onItems function will need to be aware of handling
// items that may not be loaded
preloadItems: false,
// showButtons: boolean
// if set to true, then buttons for "OK" and "Cancel" will be provided
showButtons: false,
// okButtonLabel: string
// The string to use for the OK button - will use dijit's common "OK" string
// if not set
okButtonLabel: "",
// cancelButtonLabel: string
// The string to use for the Cancel button - will use dijit's common
// "Cancel" string if not set
cancelButtonLabel: "",
// minPaneWidth: integer
// the minimum pane width (in px) for all child panes. If they are narrower,
// the width will be increased to this value.
minPaneWidth: 0,
postMixInProperties: function(){
// summary: Mix in our labels, if they are not set
this.inherited(arguments);
var loc = dojo.i18n.getLocalization("dijit", "common");
this.okButtonLabel = this.okButtonLabel || loc.buttonOk;
this.cancelButtonLabel = this.cancelButtonLabel || loc.buttonCancel;
},
_setShowButtonsAttr: function(doShow){
// summary: Sets the visibility of the buttons for the widget
var needsLayout = false;
if((this.showButtons != doShow && this._started) ||
(this.showButtons == doShow && !this.started)){
needsLayout = true;
}
dojo.toggleClass(this.domNode, "dojoxRollingListButtonsHidden", !doShow);
this.showButtons = doShow;
if(needsLayout){
if(this._started){
this.layout();
}else{
window.setTimeout(dojo.hitch(this, "layout"), 0);
}
}
},
_itemsMatch: function(/*item*/ item1, /*item*/ item2){
// Summary: returns whether or not the two items match - checks ID if
// they aren't the exact same object
if(!item1 && !item2){
return true;
}else if(!item1 || !item2){
return false;
}
return (item1 == item2 ||
(this._isIdentity && this.store.getIdentity(item1) == this.store.getIdentity(item2)));";s:7:"private";b:1;s:7:"summary";s:0:"";}s:37:"dojox.widget.RollingList._removeAfter";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:3:"idx";a:1:{s:4:"type";s:13:"Widget or int";}}s:6:"source";s:553:" if(typeof idx != "number"){
idx = this.getIndexOfChild(idx);
}
if(idx >= 0){
dojo.forEach(this.getChildren(), function(c, i){
if(i > idx){
this.removeChild(c);
c.destroyRecursive();
}
}, this);
}
var children = this.getChildren(), child = children[children.length - 1];
var selItem = null;
while(child && !selItem){
var val = child._getSelected ? child._getSelected() : null;
if(val){
selItem = val.item;
}
child = child.parentPane;
}
if(!this._setInProgress){
this._setValue(selItem);
}";s:7:"summary";s:53:"removes all widgets after the given widget (or index)";s:7:"private";b:1;}s:33:"dojox.widget.RollingList.addChild";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:6:"widget";a:1:{s:4:"type";s:6:"Widget";}s:11:"insertIndex";a:2:{s:8:"optional";b:1;s:4:"type";s:3:"int";}}s:6:"source";s:254:" if(insertIndex > 0){
this._removeAfter(insertIndex - 1);
}
this.inherited(arguments);
if(!widget._started){
widget.startup();
}
widget.attr("minWidth", this.minPaneWidth);
this.layout();
if(!this._savedFocus){
widget.focus();
}";s:7:"summary";s:153:"adds a child to this rolling list - if passed an insertIndex,
then all children from that index on will be removed and destroyed
before adding the child.";}s:45:"dojox.widget.RollingList._setMinPaneWidthAttr";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"value";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:155:" if(value !== this.minPaneWidth){
this.minPaneWidth = value;
dojo.forEach(this.getChildren(), function(c){
c.attr("minWidth", value);
});
}";s:7:"summary";s:39:"Sets the min pane width of all children";s:7:"private";b:1;}s:37:"dojox.widget.RollingList._updateClass";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:3:{s:4:"node";a:1:{s:4:"type";s:4:"Node";}s:4:"type";a:1:{s:4:"type";s:6:"String";}s:7:"options";a:3:{s:8:"optional";b:1;s:4:"type";s:6:"Object";s:7:"summary";s:119:"an object with key-value-pairs. The values are boolean, if true,
the key is added as a class, if false, it is removed.";}}s:6:"source";s:612:" if(!this._declaredClasses){
this._declaredClasses = ("dojoxRollingList " + this.className).split(" ");
}
dojo.forEach(this._declaredClasses, function(c){
if(c){
dojo.addClass(node, c + type);
for(var k in options||{}){
dojo.toggleClass(node, c + type + k, options[k]);
}
dojo.toggleClass(node, c + type + "FocusSelected",
(dojo.hasClass(node, c + type + "Focus") && dojo.hasClass(node, c + type + "Selected")));
dojo.toggleClass(node, c + type + "HoverSelected",
(dojo.hasClass(node, c + type + "Hover") && dojo.hasClass(node, c + type + "Selected")));
}
});";s:7:"summary";s:64:"sets the state of the given node with the given type and options";s:7:"private";b:1;}s:39:"dojox.widget.RollingList.scrollIntoView";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:11:"childWidget";a:1:{s:4:"type";s:6:"Widget";}}s:6:"source";s:324:" if(this._scrollingTimeout){
window.clearTimeout(this._scrollingTimeout);
}
delete this._scrollingTimeout;
this._scrollingTimeout = window.setTimeout(dojo.hitch(this, function(){
if(childWidget.domNode){
dijit.scrollIntoView(childWidget.domNode);
}
delete this._scrollingTimeout;
return;
}), 1);";s:7:"summary";s:34:"scrolls the given widget into view";}s:31:"dojox.widget.RollingList.resize";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:4:"args";a:1:{s:4:"type";s:0:"";}}s:6:"source";s:63:" dijit.layout._LayoutWidget.prototype.resize.call(this, args);";s:6:"chains";a:1:{s:4:"call";a:1:{i:0;s:43:"dijit.layout._LayoutWidget.prototype.resize";}}s:7:"summary";s:0:"";}s:31:"dojox.widget.RollingList.layout";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:524:" var children = this.getChildren();
if(this._contentBox){
var bn = this.buttonsNode;
var height = this._contentBox.h - dojo.marginBox(bn).h -
dojox.html.metrics.getScrollbar().h;
dojo.forEach(children, function(c){
dojo.marginBox(c.domNode, {h: height});
});
}
if(this._focusedPane){
var foc = this._focusedPane;
delete this._focusedPane;
if(!this._savedFocus){
foc.focus();
}
}else if(children && children.length){
if(!this._savedFocus){
children[0].focus();
}
}";s:7:"summary";s:0:"";}s:34:"dojox.widget.RollingList._onChange";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"value";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:23:" this.onChange(value);";s:7:"private";b:1;s:7:"summary";s:0:"";}s:34:"dojox.widget.RollingList._setValue";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"value";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:126:" delete this._setInProgress;
if(!this._itemsMatch(this.value, value)){
this.value = value;
this._onChange(value);
}";s:7:"summary";s:44:"internally sets the value and fires onchange";s:7:"private";b:1;}s:38:"dojox.widget.RollingList._setValueAttr";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"value";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:3476:" if(this._itemsMatch(this.value, value) && !value){ return; }
if(this._setInProgress && this._setInProgress === value){ return; }
this._setInProgress = value;
if(!value || !this.store.isItem(value)){
var pane = this.getChildren()[0];
pane._setSelected(null);
this._onItemClick(null, pane, null, null);
return;
}
var fetchParentItems = dojo.hitch(this, function(/*item*/ item, /*function*/callback){
// Summary: Fetchs the parent items for the given item
var store = this.store, id;
if(this.parentAttr && store.getFeatures()["dojo.data.api.Identity"] &&
((id = this.store.getValue(item, this.parentAttr)) || id === "")){
// Fetch by parent attribute
var cb = function(i){
if(store.getIdentity(i) == store.getIdentity(item)){
callback(null);
}else{
callback([i]);
}
};
if(id === ""){
callback(null);
}else if(typeof id == "string"){
store.fetchItemByIdentity({identity: id, onItem: cb});
}else if(store.isItem(id)){
cb(id);
}
}else{
// Fetch by finding children
var numCheck = this.childrenAttrs.length;
var parents = [];
dojo.forEach(this.childrenAttrs, function(attr){
var q = {};
q[attr] = item;
store.fetch({query: q, scope: this,
onComplete: function(items){
if(this._setInProgress !== value){
return;
}
parents = parents.concat(items);
numCheck--;
if(numCheck === 0){
callback(parents);
}
}
});
}, this);
}
});
var setFromChain = dojo.hitch(this, function(/*item[]*/itemChain, /*integer*/idx){
// Summary: Sets the value of the widget at the given index in the chain - onchanges are not
// fired here
var set = itemChain[idx];
var child = this.getChildren()[idx];
var conn;
if(set && child){
var fx = dojo.hitch(this, function(){
if(conn){
this.disconnect(conn);
}
delete conn;
if(this._setInProgress !== value){
return;
}
var selOpt = dojo.filter(child._menu.getChildren(), function(i){
return this._itemsMatch(i.item, set);
}, this)[0];
if(selOpt){
idx++;
child._menu.onItemClick(selOpt, {type: "internal",
stopPropagation: function(){},
preventDefault: function(){}});
if(itemChain[idx]){
setFromChain(itemChain, idx);
}else{
this._setValue(set);
this.onItemClick(set, child, this.getChildItems(set));
}
}
});
if(!child.isLoaded){
conn = this.connect(child, "onLoad", fx);
}else{
fx();
}
}else if(idx === 0){
this.attr("value", null);
}
});
var parentChain = [];
var onParents = dojo.hitch(this, function(/*item[]*/ parents){
// Summary: recursively grabs the parents - only the first one is followed
if(parents && parents.length){
parentChain.push(parents[0]);
fetchParentItems(parents[0], onParents);
}else{
if(!parents){
parentChain.pop();
}
parentChain.reverse();
setFromChain(parentChain, 0);
}
});
// Only set the value in display if we are shown - if we are in a dropdown,
// and are hidden, don't actually do the scrolling in the display (it can
// mess up layouts)
var ns = this.domNode.style;
if(ns.display == "none" || ns.visibility == "hidden"){
this._setValue(value);
}else if(!this._itemsMatch(value, this._visibleItem)){
onParents([value]);
}";s:7:"summary";s:53:"sets the value of this widget to the given store item";s:7:"private";b:1;}s:37:"dojox.widget.RollingList._onItemClick";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:4:{s:3:"evt";a:1:{s:4:"type";s:5:"Event";}s:4:"pane";a:1:{s:4:"type";s:16:"dijit._Contained";}s:4:"item";a:1:{s:4:"type";s:4:"item";}s:8:"children";a:2:{s:8:"optional";b:1;s:4:"type";s:6:"item[]";}}s:6:"source";s:806:" if(evt){
var itemPane = this._getPaneForItem(item, pane, children);
var alreadySelected = (evt.type == "click" && evt.alreadySelected);
if(alreadySelected && itemPane){
this._removeAfter(pane.getIndexInParent() + 1);
var next = pane.getNextSibling();
if(next && next._setSelected){
next._setSelected(null);
}
this.scrollIntoView(next);
}else if(itemPane){
this.addChild(itemPane, pane.getIndexInParent() + 1);
if(this._savedFocus){
itemPane.focus(true);
}
}else{
this._removeAfter(pane);
this.scrollIntoView(pane);
}
}else if(pane){
this._removeAfter(pane);
this.scrollIntoView(pane);
}
if(!evt || evt.type != "internal"){
this._setValue(item);
this.onItemClick(item, pane, children);
}
this._visibleItem = item;";s:7:"summary";s:55:"internally called when a widget should pop up its child";s:7:"private";b:1;}s:40:"dojox.widget.RollingList._getPaneForItem";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:3:{s:4:"item";a:2:{s:8:"optional";b:1;s:4:"type";s:4:"item";}s:10:"parentPane";a:2:{s:8:"optional";b:1;s:4:"type";s:16:"dijit._Contained";}s:8:"children";a:2:{s:8:"optional";b:1;s:4:"type";s:6:"item[]";}}s:6:"source";s:328:" var ret = this.getPaneForItem(item, parentPane, children);
ret.store = this.store;
ret.parentWidget = this;
ret.parentPane = parentPane||null;
if(!item){
ret.query = this.query;
ret.queryOptions = this.queryOptions;
}else if(children){
ret.items = children;
}else{
ret.items = [item];
}
return ret;";s:7:"summary";s:152:"gets the pane for the given item, and mixes in our needed parts
Returns the pane for the given item (null if the root pane) - after mixing in
its stuff.";s:7:"private";b:1;}s:44:"dojox.widget.RollingList._getMenuItemForItem";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:2:{s:4:"item";a:1:{s:4:"type";s:4:"item";}s:10:"parentPane";a:1:{s:4:"type";s:16:"dijit._Contained";}}s:6:"source";s:2494:" var store = this.store;
if(!item || !store || !store.isItem(item)){
var i = new dijit.MenuItem({
label: dojo.i18n.getLocalization("dojox.widget", "RollingList", this.lang).empty,
disabled: true,
iconClass: "dojoxEmpty",
focus: function(){
// Do nothing on focus of this guy...
}
});
this._updateClass(i.domNode, "Item");
return i;
}else{
var itemLoaded = store.isItemLoaded(item);
var childItems = itemLoaded ? this.getChildItems(item) : undefined;
var widgetItem;
if(childItems){
widgetItem = this.getMenuItemForItem(item, parentPane, childItems);
widgetItem.children = childItems;
this._updateClass(widgetItem.domNode, "Item", {"Expanding": true});
if(!widgetItem._started){
var c = widgetItem.connect(widgetItem, "startup", function(){
this.disconnect(c);
dojo.style(this.arrowWrapper, "display", "");
});
}else{
dojo.style(widgetItem.arrowWrapper, "display", "");
}
}else{
widgetItem = this.getMenuItemForItem(item, parentPane, null);
if(itemLoaded){
this._updateClass(widgetItem.domNode, "Item", {"Single": true});
}else{
this._updateClass(widgetItem.domNode, "Item", {"Unloaded": true});
widgetItem.attr("disabled", true);
}
}
widgetItem.store = this.store;
widgetItem.item = item;
if(!widgetItem.label){
widgetItem.attr("label", this.store.getLabel(item).replace(/,"<"));
}
if(widgetItem.focusNode){
var self = this;
widgetItem.focus = function(){
// Don't set our class
if(!this.disabled){try{this.focusNode.focus();}catch(e){}}
};
widgetItem.connect(widgetItem.focusNode, "onmouseenter", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": true});
}
});
widgetItem.connect(widgetItem.focusNode, "onmouseleave", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": false});
}
});
widgetItem.connect(widgetItem.focusNode, "blur", function(){
self._updateClass(this.domNode, "Item", {"Focus": false, "Hover": false});
});
widgetItem.connect(widgetItem.focusNode, "focus", function(){
self._updateClass(this.domNode, "Item", {"Focus": true});
self._focusedPane = parentPane;
});
if(this.executeOnDblClick){
widgetItem.connect(widgetItem.focusNode, "ondblclick", function(){
self._onExecute();
});
}
}
return widgetItem;
}";s:7:"summary";s:165:"returns a widget for the given store item. The returned
item will be added to this widget's container widget. null will
be passed in for an "empty" item.";s:7:"private";b:1;}s:34:"dojox.widget.RollingList._setStore";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"store";a:1:{s:4:"type";s:18:"dojo.data.api.Read";}}s:6:"source";s:215:" if(store === this.store && this._started){ return; }
this.store = store;
this._isIdentity = store.getFeatures()["dojo.data.api.Identity"];
var rootPane = this._getPaneForItem();
this.addChild(rootPane, 0);";s:7:"summary";s:33:"sets the store for this widget */";s:7:"private";b:1;}s:31:"dojox.widget.RollingList._onKey";a:6:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:1:"e";a:1:{s:4:"type";s:5:"Event";}}s:6:"source";s:355:" if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.ESCAPE && this._savedFocus){
try{dijit.focus(this._savedFocus);}catch(e){}
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW ||
e.charOrCode == dojo.keys.RIGHT_ARROW){
dojo.stopEvent(e);
return;
}";s:7:"summary";s:51:"called when a keypress event happens on this widget";s:7:"private";b:1;}s:36:"dojox.widget.RollingList._resetValue";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:33815:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}
},
_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
// Summary: called when an item is added to the store
var sel;
if((!parentInfo && !this.parentPane) ||
(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
this.items.push(newItem);
this._loadCheck(true);
}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
this._loadCheck(true);
}
},
_onDeleteItem: function(/* item */ deletedItem){
// Summary: called when an item is removed from the store
if(this._hasItem(deletedItem)){
this.items = dojo.filter(this.items, function(i){
return (i != deletedItem);
});
this._loadCheck(true);
}
},
onFetchStart: function(){
// summary:
// called before a fetch starts
return this.loadingMessage;
},
onFetchError: function(/*Error*/ error){
// summary:
// called when a fetch error occurs.
return this.errorMessage;
},
onLoadStart: function(){
// summary:
// called before a load starts
return this.loadingMessage;
},
onLoadError: function(/*Error*/ error){
// summary:
// called when a load error occurs.
return this.errorMessage;
},
onItems: function(){
// summary:
// called after a fetch or load - at this point, this.items should be
// set and loaded. Override this function to "do your stuff"
this._onLoadHandler();
}
});
dojo.declare("dojox.widget._RollingListGroupPane",
[dojox.widget._RollingListPane], {
// summary: a pane that will handle groups (treats them as menu items)
// templateString: string
// our template
templateString: '',
// _menu: dijit.Menu
// The menu that we will call addChild() on for adding items
_menu: null,
_loadCheck: function(){
// summary: checks that the store is loaded
var displayState = this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_setContent: function(/*String|DomNode|Nodelist*/cont){
if(!this._menu){
// Only set the content if we don't already have a menu
this.inherited(arguments);
}
},
_onMinWidthChange: function(v){
// override and resize the menu instead
if(!this._menu){ return; }
var dWidth = dojo.marginBox(this.domNode).w;
var mWidth = dojo.marginBox(this._menu.domNode).w;
this._updateNodeWidth(this._menu.domNode, v - (dWidth - mWidth));
},
onItems: function(){
// summary:
// called after a fetch or load
var selectItem, hadChildren = false;
if(this._menu){
selectItem = this._getSelected();
this._menu.destroyRecursive();
}
this._menu = this._getMenu();
var child, selectMenuItem;
if(this.items.length){
dojo.forEach(this.items, function(item){
child = this.parentWidget._getMenuItemForItem(item, this);
if(child){
if(selectItem && this.parentWidget._itemsMatch(child.item, selectItem.item)){
selectMenuItem = child;
}
this._menu.addChild(child);
}
}, this);
}else{
child = this.parentWidget._getMenuItemForItem(null, this);
if(child){
this._menu.addChild(child);
}
}
if(selectMenuItem){
this._setSelected(selectMenuItem);
if((selectItem && !selectItem.children && selectMenuItem.children) ||
(selectItem && selectItem.children && !selectMenuItem.children)){
var itemPane = this.parentWidget._getPaneForItem(selectMenuItem.item, this, selectMenuItem.children);
if(itemPane){
this.parentWidget.addChild(itemPane, this.getIndexInParent() + 1);
}else{
this.parentWidget._removeAfter(this);
this.parentWidget._onItemClick(null, this, selectMenuItem.item, selectMenuItem.children);
}
}
}else if(selectItem){
this.parentWidget._removeAfter(this);
}
this.containerNode.innerHTML = "";
this.containerNode.appendChild(this._menu.domNode);
this.parentWidget.scrollIntoView(this);
this._checkScrollConnection(true);
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_checkScrollConnection: function(doLoad){
// summary: checks whether or not we need to connect to our onscroll
// function
var store = this.store
if(this._scrollConn){
this.disconnect(this._scrollConn);
}
delete this._scrollConn;
if(!dojo.every(this.items, function(i){return store.isItemLoaded(i);})){
if(doLoad){
this._loadVisibleItems();
}
this._scrollConn = this.connect(this.domNode, "onscroll", "_onScrollPane");
}
},
startup: function(){
this.inherited(arguments);
this.parentWidget._updateClass(this.domNode, "GroupPane");
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this._menu){
if(this._pendingFocus){
this.disconnect(this._pendingFocus);
}
delete this._pendingFocus;
// We focus the right widget - either the focusedChild, the
// selected node, the first menu item, or the menu itself
var focusWidget = this._menu.focusedChild;
if(!focusWidget){
var focusNode = dojo.query(".dojoxRollingListItemSelected", this.domNode)[0];
if(focusNode){
focusWidget = dijit.byNode(focusNode);
}
}
if(!focusWidget){
focusWidget = this._menu.getChildren()[0] || this._menu;
}
this._focusByNode = false;
if(focusWidget.focusNode){
if(!this.parentWidget._savedFocus || force){
try{focusWidget.focusNode.focus();}catch(e){}
}
window.setTimeout(function(){
try{
dijit.scrollIntoView(focusWidget.focusNode);
}catch(e){}
}, 1);
}else if(focusWidget.focus){
if(!this.parentWidget._savedFocus || force){
focusWidget.focus();
}
}else{
this._focusByNode = true;
}
this.inherited(arguments);
}else if(!this._pendingFocus){
this._pendingFocus = this.connect(this, "onItems", "focus");
}
},
_getMenu: function(){
// summary: returns a widget to be used for the container widget.
var self = this;
var menu = new dijit.Menu({
parentMenu: this.parentPane ? this.parentPane._menu : null,
onCancel: function(/*Boolean*/ closeAll){
if(self.parentPane){
self.parentPane.focus(true);
}
},
_moveToPopup: function(/*Event*/ evt){
if(this.focusedChild && !this.focusedChild.disabled){
this.focusedChild._onClick(evt);
}
}
}, this.menuNode);
this.connect(menu, "onItemClick", function(/*dijit.MenuItem*/ item, /*Event*/ evt){
if(item.disabled){ return; }
evt.alreadySelected = dojo.hasClass(item.domNode, "dojoxRollingListItemSelected");
if(evt.alreadySelected &&
((evt.type == "keypress" && evt.charOrCode != dojo.keys.ENTER) ||
(evt.type == "internal"))){
var p = this.parentWidget.getChildren()[this.getIndexInParent() + 1];
if(p){
p.focus(true);
this.parentWidget.scrollIntoView(p);
}
}else{
this._setSelected(item, menu);
this.parentWidget._onItemClick(evt, this, item.item, item.children);
if(evt.type == "keypress" && evt.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
}
});
if(!menu._started){
menu.startup();
}
return menu;
},
_onScrollPane: function(){
// summary: called when the pane has been scrolled - it sets a timeout
// so that we don't try and load our visible items too often during
// a scroll
if(this._visibleLoadPending){
window.clearTimeout(this._visibleLoadPending);
}
this._visibleLoadPending = window.setTimeout(dojo.hitch(this, "_loadVisibleItems"), 500);
},
_layoutHack: function(){
// summary: work around table sizing bugs on FF2 by forcing redraw
// note - this function is taken from dijit.form._FormWidget
if(dojo.isFF == 2 && !this._layoutHackHandle){
var node=this.domNode;
var old = node.style.opacity;
node.style.opacity = "0.999";
this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
this._layoutHackHandle = null;
node.style.opacity = old;
}), 0);
}
},
_loadVisibleItems: function(){
// summary: loads the items that are currently visible in the pane
delete this._visibleLoadPending
var menu = this._menu;
if(!menu){ return; }
var children = menu.getChildren();
if(!children || !children.length){ return; }
var gpbme = function(n, m, pb){
var s = dojo.getComputedStyle(n);
var r = 0;
if(m){ r += dojo._getMarginExtents(n, s).t; }
if(pb){ r += dojo._getPadBorderExtents(n, s).t; }
return r;
};
var topOffset = gpbme(this.domNode, false, true) +
gpbme(this.containerNode, true, true) +
gpbme(menu.domNode, true, true) +
gpbme(children[0].domNode, true, false);
var h = dojo.contentBox(this.domNode).h;
var minOffset = this.domNode.scrollTop - topOffset - (h/2);
var maxOffset = minOffset + (3*h/2);
var menuItemsToLoad = dojo.filter(children, function(c){
var cnt = c.domNode.offsetTop;
var s = c.store;
var i = c.item;
return (cnt >= minOffset && cnt <= maxOffset && !s.isItemLoaded(i));
})
var itemsToLoad = dojo.map(menuItemsToLoad, function(c){
return c.item;
});
var onItems = dojo.hitch(this, function(){
var selectItem = this._getSelected();
var selectMenuItem;
dojo.forEach(itemsToLoad, function(item, idx){
var newItem = this.parentWidget._getMenuItemForItem(item, this);
var oItem = menuItemsToLoad[idx];
var oIdx = oItem.getIndexInParent();
menu.removeChild(oItem);
if(newItem){
if(selectItem && this.parentWidget._itemsMatch(newItem.item, selectItem.item)){
selectMenuItem = newItem;
}
menu.addChild(newItem, oIdx);
if(menu.focusedChild == oItem){
menu.focusChild(newItem);
}
}
oItem.destroy();
}, this);
this._checkScrollConnection(false);
this._layoutHack();
});
this._doLoadItems(itemsToLoad, onItems);
},
_getSelected: function(/*dijit.Menu?*/ menu){
// summary:
// returns the selected menu item - or null if none are selected
if(!menu){ menu = this._menu; }
if(menu){
var children = this._menu.getChildren();
for(var i = 0, item; (item = children[i]); i++){
if(dojo.hasClass(item.domNode, "dojoxRollingListItemSelected")){
return item;
}
}
}
return null;
},
_setSelected: function(/*dijit.MenuItem?*/ item, /*dijit.Menu?*/ menu){
// summary:
// selectes the given item in the given menu (defaults to pane's menu)
if(!menu){ menu = this._menu;}
if(menu){
dojo.forEach(menu.getChildren(), function(i){
this.parentWidget._updateClass(i.domNode, "Item", {"Selected": (item && (i == item && !i.disabled))});
}, this);
}
},
destroy: function(){
if(this._layoutHackHandle){
clearTimeout(this._layoutHackHandle);
}
this.inherited(arguments);
}
});
dojo.declare("dojox.widget.RollingList",
[dijit._Widget, dijit._Templated, dijit._Container], {
// summary: a rolling list that can be tied to a data store with children
// templatePath: string
// our template to use
templatePath: dojo.moduleUrl("dojox.widget", "RollingList/RollingList.html"),
widgetsInTemplate: true,
// className: string
// an additional class (or space-separated classes) to add for our widget
className: "",
// store: store
// the store we must use
store: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// childrenAttrs: String[]
// one ore more attributes that holds children of a node
childrenAttrs: ["children"],
// parentAttr: string
// the attribute to read for finding our parent item (if any)
parentAttr: "",
// value: item
// The value that has been selected
value: null,
// executeOnDblClick: boolean
// Set to true if you want to call onExecute when an item is
// double-clicked, false if you want to call onExecute yourself. (mainly
// used for popups to control how they want to be handled)
executeOnDblClick: true,
// preloadItems: boolean or int
// if set to true, then onItems will be called only *after* all items have
// been loaded (ie store.isLoaded will return true for all of them). If
// false, then no preloading will occur. If set to an integer, preloading
// will occur if the number of items is less than or equal to the value
// of the integer. The onItems function will need to be aware of handling
// items that may not be loaded
preloadItems: false,
// showButtons: boolean
// if set to true, then buttons for "OK" and "Cancel" will be provided
showButtons: false,
// okButtonLabel: string
// The string to use for the OK button - will use dijit's common "OK" string
// if not set
okButtonLabel: "",
// cancelButtonLabel: string
// The string to use for the Cancel button - will use dijit's common
// "Cancel" string if not set
cancelButtonLabel: "",
// minPaneWidth: integer
// the minimum pane width (in px) for all child panes. If they are narrower,
// the width will be increased to this value.
minPaneWidth: 0,
postMixInProperties: function(){
// summary: Mix in our labels, if they are not set
this.inherited(arguments);
var loc = dojo.i18n.getLocalization("dijit", "common");
this.okButtonLabel = this.okButtonLabel || loc.buttonOk;
this.cancelButtonLabel = this.cancelButtonLabel || loc.buttonCancel;
},
_setShowButtonsAttr: function(doShow){
// summary: Sets the visibility of the buttons for the widget
var needsLayout = false;
if((this.showButtons != doShow && this._started) ||
(this.showButtons == doShow && !this.started)){
needsLayout = true;
}
dojo.toggleClass(this.domNode, "dojoxRollingListButtonsHidden", !doShow);
this.showButtons = doShow;
if(needsLayout){
if(this._started){
this.layout();
}else{
window.setTimeout(dojo.hitch(this, "layout"), 0);
}
}
},
_itemsMatch: function(/*item*/ item1, /*item*/ item2){
// Summary: returns whether or not the two items match - checks ID if
// they aren't the exact same object
if(!item1 && !item2){
return true;
}else if(!item1 || !item2){
return false;
}
return (item1 == item2 ||
(this._isIdentity && this.store.getIdentity(item1) == this.store.getIdentity(item2)));
},
_removeAfter: function(/*Widget or int*/ idx){
// summary: removes all widgets after the given widget (or index)
if(typeof idx != "number"){
idx = this.getIndexOfChild(idx);
}
if(idx >= 0){
dojo.forEach(this.getChildren(), function(c, i){
if(i > idx){
this.removeChild(c);
c.destroyRecursive();
}
}, this);
}
var children = this.getChildren(), child = children[children.length - 1];
var selItem = null;
while(child && !selItem){
var val = child._getSelected ? child._getSelected() : null;
if(val){
selItem = val.item;
}
child = child.parentPane;
}
if(!this._setInProgress){
this._setValue(selItem);
}
},
addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
// summary: adds a child to this rolling list - if passed an insertIndex,
// then all children from that index on will be removed and destroyed
// before adding the child.
if(insertIndex > 0){
this._removeAfter(insertIndex - 1);
}
this.inherited(arguments);
if(!widget._started){
widget.startup();
}
widget.attr("minWidth", this.minPaneWidth);
this.layout();
if(!this._savedFocus){
widget.focus();
}
},
_setMinPaneWidthAttr: function(value){
// summary:
// Sets the min pane width of all children
if(value !== this.minPaneWidth){
this.minPaneWidth = value;
dojo.forEach(this.getChildren(), function(c){
c.attr("minWidth", value);
});
}
},
_updateClass: function(/* Node */ node, /* String */ type, /* Object? */ options){
// summary:
// sets the state of the given node with the given type and options
// options:
// an object with key-value-pairs. The values are boolean, if true,
// the key is added as a class, if false, it is removed.
if(!this._declaredClasses){
this._declaredClasses = ("dojoxRollingList " + this.className).split(" ");
}
dojo.forEach(this._declaredClasses, function(c){
if(c){
dojo.addClass(node, c + type);
for(var k in options||{}){
dojo.toggleClass(node, c + type + k, options[k]);
}
dojo.toggleClass(node, c + type + "FocusSelected",
(dojo.hasClass(node, c + type + "Focus") && dojo.hasClass(node, c + type + "Selected")));
dojo.toggleClass(node, c + type + "HoverSelected",
(dojo.hasClass(node, c + type + "Hover") && dojo.hasClass(node, c + type + "Selected")));
}
});
},
scrollIntoView: function(/* Widget */ childWidget){
// summary: scrolls the given widget into view
if(this._scrollingTimeout){
window.clearTimeout(this._scrollingTimeout);
}
delete this._scrollingTimeout;
this._scrollingTimeout = window.setTimeout(dojo.hitch(this, function(){
if(childWidget.domNode){
dijit.scrollIntoView(childWidget.domNode);
}
delete this._scrollingTimeout;
return;
}), 1);
},
resize: function(args){
dijit.layout._LayoutWidget.prototype.resize.call(this, args);
},
layout: function(){
var children = this.getChildren();
if(this._contentBox){
var bn = this.buttonsNode;
var height = this._contentBox.h - dojo.marginBox(bn).h -
dojox.html.metrics.getScrollbar().h;
dojo.forEach(children, function(c){
dojo.marginBox(c.domNode, {h: height});
});
}
if(this._focusedPane){
var foc = this._focusedPane;
delete this._focusedPane;
if(!this._savedFocus){
foc.focus();
}
}else if(children && children.length){
if(!this._savedFocus){
children[0].focus();
}
}
},
_onChange: function(/*item*/ value){
this.onChange(value);
},
_setValue: function(/* item */ value){
// summary: internally sets the value and fires onchange
delete this._setInProgress;
if(!this._itemsMatch(this.value, value)){
this.value = value;
this._onChange(value);
}
},
_setValueAttr: function(/* item */ value){
// summary: sets the value of this widget to the given store item
if(this._itemsMatch(this.value, value) && !value){ return; }
if(this._setInProgress && this._setInProgress === value){ return; }
this._setInProgress = value;
if(!value || !this.store.isItem(value)){
var pane = this.getChildren()[0];
pane._setSelected(null);
this._onItemClick(null, pane, null, null);
return;
}
var fetchParentItems = dojo.hitch(this, function(/*item*/ item, /*function*/callback){
// Summary: Fetchs the parent items for the given item
var store = this.store, id;
if(this.parentAttr && store.getFeatures()["dojo.data.api.Identity"] &&
((id = this.store.getValue(item, this.parentAttr)) || id === "")){
// Fetch by parent attribute
var cb = function(i){
if(store.getIdentity(i) == store.getIdentity(item)){
callback(null);
}else{
callback([i]);
}
};
if(id === ""){
callback(null);
}else if(typeof id == "string"){
store.fetchItemByIdentity({identity: id, onItem: cb});
}else if(store.isItem(id)){
cb(id);
}
}else{
// Fetch by finding children
var numCheck = this.childrenAttrs.length;
var parents = [];
dojo.forEach(this.childrenAttrs, function(attr){
var q = {};
q[attr] = item;
store.fetch({query: q, scope: this,
onComplete: function(items){
if(this._setInProgress !== value){
return;
}
parents = parents.concat(items);
numCheck--;
if(numCheck === 0){
callback(parents);
}
}
});
}, this);
}
});
var setFromChain = dojo.hitch(this, function(/*item[]*/itemChain, /*integer*/idx){
// Summary: Sets the value of the widget at the given index in the chain - onchanges are not
// fired here
var set = itemChain[idx];
var child = this.getChildren()[idx];
var conn;
if(set && child){
var fx = dojo.hitch(this, function(){
if(conn){
this.disconnect(conn);
}
delete conn;
if(this._setInProgress !== value){
return;
}
var selOpt = dojo.filter(child._menu.getChildren(), function(i){
return this._itemsMatch(i.item, set);
}, this)[0];
if(selOpt){
idx++;
child._menu.onItemClick(selOpt, {type: "internal",
stopPropagation: function(){},
preventDefault: function(){}});
if(itemChain[idx]){
setFromChain(itemChain, idx);
}else{
this._setValue(set);
this.onItemClick(set, child, this.getChildItems(set));
}
}
});
if(!child.isLoaded){
conn = this.connect(child, "onLoad", fx);
}else{
fx();
}
}else if(idx === 0){
this.attr("value", null);
}
});
var parentChain = [];
var onParents = dojo.hitch(this, function(/*item[]*/ parents){
// Summary: recursively grabs the parents - only the first one is followed
if(parents && parents.length){
parentChain.push(parents[0]);
fetchParentItems(parents[0], onParents);
}else{
if(!parents){
parentChain.pop();
}
parentChain.reverse();
setFromChain(parentChain, 0);
}
});
// Only set the value in display if we are shown - if we are in a dropdown,
// and are hidden, don't actually do the scrolling in the display (it can
// mess up layouts)
var ns = this.domNode.style;
if(ns.display == "none" || ns.visibility == "hidden"){
this._setValue(value);
}else if(!this._itemsMatch(value, this._visibleItem)){
onParents([value]);
}
},
_onItemClick: function(/* Event */ evt, /* dijit._Contained */ pane, /* item */ item, /* item[]? */ children){
// summary: internally called when a widget should pop up its child
if(evt){
var itemPane = this._getPaneForItem(item, pane, children);
var alreadySelected = (evt.type == "click" && evt.alreadySelected);
if(alreadySelected && itemPane){
this._removeAfter(pane.getIndexInParent() + 1);
var next = pane.getNextSibling();
if(next && next._setSelected){
next._setSelected(null);
}
this.scrollIntoView(next);
}else if(itemPane){
this.addChild(itemPane, pane.getIndexInParent() + 1);
if(this._savedFocus){
itemPane.focus(true);
}
}else{
this._removeAfter(pane);
this.scrollIntoView(pane);
}
}else if(pane){
this._removeAfter(pane);
this.scrollIntoView(pane);
}
if(!evt || evt.type != "internal"){
this._setValue(item);
this.onItemClick(item, pane, children);
}
this._visibleItem = item;
},
_getPaneForItem: function(/* item? */ item, /* dijit._Contained? */ parentPane, /* item[]? */ children){ // summary: gets the pane for the given item, and mixes in our needed parts
// Returns the pane for the given item (null if the root pane) - after mixing in
// its stuff.
var ret = this.getPaneForItem(item, parentPane, children);
ret.store = this.store;
ret.parentWidget = this;
ret.parentPane = parentPane||null;
if(!item){
ret.query = this.query;
ret.queryOptions = this.queryOptions;
}else if(children){
ret.items = children;
}else{
ret.items = [item];
}
return ret;
},
_getMenuItemForItem: function(/*item*/ item, /* dijit._Contained */ parentPane){
// summary: returns a widget for the given store item. The returned
// item will be added to this widget's container widget. null will
// be passed in for an "empty" item.
var store = this.store;
if(!item || !store || !store.isItem(item)){
var i = new dijit.MenuItem({
label: dojo.i18n.getLocalization("dojox.widget", "RollingList", this.lang).empty,
disabled: true,
iconClass: "dojoxEmpty",
focus: function(){
// Do nothing on focus of this guy...
}
});
this._updateClass(i.domNode, "Item");
return i;
}else{
var itemLoaded = store.isItemLoaded(item);
var childItems = itemLoaded ? this.getChildItems(item) : undefined;
var widgetItem;
if(childItems){
widgetItem = this.getMenuItemForItem(item, parentPane, childItems);
widgetItem.children = childItems;
this._updateClass(widgetItem.domNode, "Item", {"Expanding": true});
if(!widgetItem._started){
var c = widgetItem.connect(widgetItem, "startup", function(){
this.disconnect(c);
dojo.style(this.arrowWrapper, "display", "");
});
}else{
dojo.style(widgetItem.arrowWrapper, "display", "");
}
}else{
widgetItem = this.getMenuItemForItem(item, parentPane, null);
if(itemLoaded){
this._updateClass(widgetItem.domNode, "Item", {"Single": true});
}else{
this._updateClass(widgetItem.domNode, "Item", {"Unloaded": true});
widgetItem.attr("disabled", true);
}
}
widgetItem.store = this.store;
widgetItem.item = item;
if(!widgetItem.label){
widgetItem.attr("label", this.store.getLabel(item).replace(/,"<"));
}
if(widgetItem.focusNode){
var self = this;
widgetItem.focus = function(){
// Don't set our class
if(!this.disabled){try{this.focusNode.focus();}catch(e){}}
};
widgetItem.connect(widgetItem.focusNode, "onmouseenter", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": true});
}
});
widgetItem.connect(widgetItem.focusNode, "onmouseleave", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": false});
}
});
widgetItem.connect(widgetItem.focusNode, "blur", function(){
self._updateClass(this.domNode, "Item", {"Focus": false, "Hover": false});
});
widgetItem.connect(widgetItem.focusNode, "focus", function(){
self._updateClass(this.domNode, "Item", {"Focus": true});
self._focusedPane = parentPane;
});
if(this.executeOnDblClick){
widgetItem.connect(widgetItem.focusNode, "ondblclick", function(){
self._onExecute();
});
}
}
return widgetItem;
}
},
_setStore: function(/* dojo.data.api.Read */ store){
// summary: sets the store for this widget */
if(store === this.store && this._started){ return; }
this.store = store;
this._isIdentity = store.getFeatures()["dojo.data.api.Identity"];
var rootPane = this._getPaneForItem();
this.addChild(rootPane, 0);
},
_onKey: function(/*Event*/ e){
// summary: called when a keypress event happens on this widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.ESCAPE && this._savedFocus){
try{dijit.focus(this._savedFocus);}catch(e){}
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW ||
e.charOrCode == dojo.keys.RIGHT_ARROW){
dojo.stopEvent(e);
return;
}
},
_resetValue: function(){
// Summary: function called when the value is reset.
this.attr("value", this._lastExecutedValue);";s:7:"private";b:1;s:7:"summary";s:0:"";}s:34:"dojox.widget.RollingList._onCancel";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:34027:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}
},
_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
// Summary: called when an item is added to the store
var sel;
if((!parentInfo && !this.parentPane) ||
(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
this.items.push(newItem);
this._loadCheck(true);
}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
this._loadCheck(true);
}
},
_onDeleteItem: function(/* item */ deletedItem){
// Summary: called when an item is removed from the store
if(this._hasItem(deletedItem)){
this.items = dojo.filter(this.items, function(i){
return (i != deletedItem);
});
this._loadCheck(true);
}
},
onFetchStart: function(){
// summary:
// called before a fetch starts
return this.loadingMessage;
},
onFetchError: function(/*Error*/ error){
// summary:
// called when a fetch error occurs.
return this.errorMessage;
},
onLoadStart: function(){
// summary:
// called before a load starts
return this.loadingMessage;
},
onLoadError: function(/*Error*/ error){
// summary:
// called when a load error occurs.
return this.errorMessage;
},
onItems: function(){
// summary:
// called after a fetch or load - at this point, this.items should be
// set and loaded. Override this function to "do your stuff"
this._onLoadHandler();
}
});
dojo.declare("dojox.widget._RollingListGroupPane",
[dojox.widget._RollingListPane], {
// summary: a pane that will handle groups (treats them as menu items)
// templateString: string
// our template
templateString: '',
// _menu: dijit.Menu
// The menu that we will call addChild() on for adding items
_menu: null,
_loadCheck: function(){
// summary: checks that the store is loaded
var displayState = this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_setContent: function(/*String|DomNode|Nodelist*/cont){
if(!this._menu){
// Only set the content if we don't already have a menu
this.inherited(arguments);
}
},
_onMinWidthChange: function(v){
// override and resize the menu instead
if(!this._menu){ return; }
var dWidth = dojo.marginBox(this.domNode).w;
var mWidth = dojo.marginBox(this._menu.domNode).w;
this._updateNodeWidth(this._menu.domNode, v - (dWidth - mWidth));
},
onItems: function(){
// summary:
// called after a fetch or load
var selectItem, hadChildren = false;
if(this._menu){
selectItem = this._getSelected();
this._menu.destroyRecursive();
}
this._menu = this._getMenu();
var child, selectMenuItem;
if(this.items.length){
dojo.forEach(this.items, function(item){
child = this.parentWidget._getMenuItemForItem(item, this);
if(child){
if(selectItem && this.parentWidget._itemsMatch(child.item, selectItem.item)){
selectMenuItem = child;
}
this._menu.addChild(child);
}
}, this);
}else{
child = this.parentWidget._getMenuItemForItem(null, this);
if(child){
this._menu.addChild(child);
}
}
if(selectMenuItem){
this._setSelected(selectMenuItem);
if((selectItem && !selectItem.children && selectMenuItem.children) ||
(selectItem && selectItem.children && !selectMenuItem.children)){
var itemPane = this.parentWidget._getPaneForItem(selectMenuItem.item, this, selectMenuItem.children);
if(itemPane){
this.parentWidget.addChild(itemPane, this.getIndexInParent() + 1);
}else{
this.parentWidget._removeAfter(this);
this.parentWidget._onItemClick(null, this, selectMenuItem.item, selectMenuItem.children);
}
}
}else if(selectItem){
this.parentWidget._removeAfter(this);
}
this.containerNode.innerHTML = "";
this.containerNode.appendChild(this._menu.domNode);
this.parentWidget.scrollIntoView(this);
this._checkScrollConnection(true);
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_checkScrollConnection: function(doLoad){
// summary: checks whether or not we need to connect to our onscroll
// function
var store = this.store
if(this._scrollConn){
this.disconnect(this._scrollConn);
}
delete this._scrollConn;
if(!dojo.every(this.items, function(i){return store.isItemLoaded(i);})){
if(doLoad){
this._loadVisibleItems();
}
this._scrollConn = this.connect(this.domNode, "onscroll", "_onScrollPane");
}
},
startup: function(){
this.inherited(arguments);
this.parentWidget._updateClass(this.domNode, "GroupPane");
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this._menu){
if(this._pendingFocus){
this.disconnect(this._pendingFocus);
}
delete this._pendingFocus;
// We focus the right widget - either the focusedChild, the
// selected node, the first menu item, or the menu itself
var focusWidget = this._menu.focusedChild;
if(!focusWidget){
var focusNode = dojo.query(".dojoxRollingListItemSelected", this.domNode)[0];
if(focusNode){
focusWidget = dijit.byNode(focusNode);
}
}
if(!focusWidget){
focusWidget = this._menu.getChildren()[0] || this._menu;
}
this._focusByNode = false;
if(focusWidget.focusNode){
if(!this.parentWidget._savedFocus || force){
try{focusWidget.focusNode.focus();}catch(e){}
}
window.setTimeout(function(){
try{
dijit.scrollIntoView(focusWidget.focusNode);
}catch(e){}
}, 1);
}else if(focusWidget.focus){
if(!this.parentWidget._savedFocus || force){
focusWidget.focus();
}
}else{
this._focusByNode = true;
}
this.inherited(arguments);
}else if(!this._pendingFocus){
this._pendingFocus = this.connect(this, "onItems", "focus");
}
},
_getMenu: function(){
// summary: returns a widget to be used for the container widget.
var self = this;
var menu = new dijit.Menu({
parentMenu: this.parentPane ? this.parentPane._menu : null,
onCancel: function(/*Boolean*/ closeAll){
if(self.parentPane){
self.parentPane.focus(true);
}
},
_moveToPopup: function(/*Event*/ evt){
if(this.focusedChild && !this.focusedChild.disabled){
this.focusedChild._onClick(evt);
}
}
}, this.menuNode);
this.connect(menu, "onItemClick", function(/*dijit.MenuItem*/ item, /*Event*/ evt){
if(item.disabled){ return; }
evt.alreadySelected = dojo.hasClass(item.domNode, "dojoxRollingListItemSelected");
if(evt.alreadySelected &&
((evt.type == "keypress" && evt.charOrCode != dojo.keys.ENTER) ||
(evt.type == "internal"))){
var p = this.parentWidget.getChildren()[this.getIndexInParent() + 1];
if(p){
p.focus(true);
this.parentWidget.scrollIntoView(p);
}
}else{
this._setSelected(item, menu);
this.parentWidget._onItemClick(evt, this, item.item, item.children);
if(evt.type == "keypress" && evt.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
}
});
if(!menu._started){
menu.startup();
}
return menu;
},
_onScrollPane: function(){
// summary: called when the pane has been scrolled - it sets a timeout
// so that we don't try and load our visible items too often during
// a scroll
if(this._visibleLoadPending){
window.clearTimeout(this._visibleLoadPending);
}
this._visibleLoadPending = window.setTimeout(dojo.hitch(this, "_loadVisibleItems"), 500);
},
_layoutHack: function(){
// summary: work around table sizing bugs on FF2 by forcing redraw
// note - this function is taken from dijit.form._FormWidget
if(dojo.isFF == 2 && !this._layoutHackHandle){
var node=this.domNode;
var old = node.style.opacity;
node.style.opacity = "0.999";
this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
this._layoutHackHandle = null;
node.style.opacity = old;
}), 0);
}
},
_loadVisibleItems: function(){
// summary: loads the items that are currently visible in the pane
delete this._visibleLoadPending
var menu = this._menu;
if(!menu){ return; }
var children = menu.getChildren();
if(!children || !children.length){ return; }
var gpbme = function(n, m, pb){
var s = dojo.getComputedStyle(n);
var r = 0;
if(m){ r += dojo._getMarginExtents(n, s).t; }
if(pb){ r += dojo._getPadBorderExtents(n, s).t; }
return r;
};
var topOffset = gpbme(this.domNode, false, true) +
gpbme(this.containerNode, true, true) +
gpbme(menu.domNode, true, true) +
gpbme(children[0].domNode, true, false);
var h = dojo.contentBox(this.domNode).h;
var minOffset = this.domNode.scrollTop - topOffset - (h/2);
var maxOffset = minOffset + (3*h/2);
var menuItemsToLoad = dojo.filter(children, function(c){
var cnt = c.domNode.offsetTop;
var s = c.store;
var i = c.item;
return (cnt >= minOffset && cnt <= maxOffset && !s.isItemLoaded(i));
})
var itemsToLoad = dojo.map(menuItemsToLoad, function(c){
return c.item;
});
var onItems = dojo.hitch(this, function(){
var selectItem = this._getSelected();
var selectMenuItem;
dojo.forEach(itemsToLoad, function(item, idx){
var newItem = this.parentWidget._getMenuItemForItem(item, this);
var oItem = menuItemsToLoad[idx];
var oIdx = oItem.getIndexInParent();
menu.removeChild(oItem);
if(newItem){
if(selectItem && this.parentWidget._itemsMatch(newItem.item, selectItem.item)){
selectMenuItem = newItem;
}
menu.addChild(newItem, oIdx);
if(menu.focusedChild == oItem){
menu.focusChild(newItem);
}
}
oItem.destroy();
}, this);
this._checkScrollConnection(false);
this._layoutHack();
});
this._doLoadItems(itemsToLoad, onItems);
},
_getSelected: function(/*dijit.Menu?*/ menu){
// summary:
// returns the selected menu item - or null if none are selected
if(!menu){ menu = this._menu; }
if(menu){
var children = this._menu.getChildren();
for(var i = 0, item; (item = children[i]); i++){
if(dojo.hasClass(item.domNode, "dojoxRollingListItemSelected")){
return item;
}
}
}
return null;
},
_setSelected: function(/*dijit.MenuItem?*/ item, /*dijit.Menu?*/ menu){
// summary:
// selectes the given item in the given menu (defaults to pane's menu)
if(!menu){ menu = this._menu;}
if(menu){
dojo.forEach(menu.getChildren(), function(i){
this.parentWidget._updateClass(i.domNode, "Item", {"Selected": (item && (i == item && !i.disabled))});
}, this);
}
},
destroy: function(){
if(this._layoutHackHandle){
clearTimeout(this._layoutHackHandle);
}
this.inherited(arguments);
}
});
dojo.declare("dojox.widget.RollingList",
[dijit._Widget, dijit._Templated, dijit._Container], {
// summary: a rolling list that can be tied to a data store with children
// templatePath: string
// our template to use
templatePath: dojo.moduleUrl("dojox.widget", "RollingList/RollingList.html"),
widgetsInTemplate: true,
// className: string
// an additional class (or space-separated classes) to add for our widget
className: "",
// store: store
// the store we must use
store: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// childrenAttrs: String[]
// one ore more attributes that holds children of a node
childrenAttrs: ["children"],
// parentAttr: string
// the attribute to read for finding our parent item (if any)
parentAttr: "",
// value: item
// The value that has been selected
value: null,
// executeOnDblClick: boolean
// Set to true if you want to call onExecute when an item is
// double-clicked, false if you want to call onExecute yourself. (mainly
// used for popups to control how they want to be handled)
executeOnDblClick: true,
// preloadItems: boolean or int
// if set to true, then onItems will be called only *after* all items have
// been loaded (ie store.isLoaded will return true for all of them). If
// false, then no preloading will occur. If set to an integer, preloading
// will occur if the number of items is less than or equal to the value
// of the integer. The onItems function will need to be aware of handling
// items that may not be loaded
preloadItems: false,
// showButtons: boolean
// if set to true, then buttons for "OK" and "Cancel" will be provided
showButtons: false,
// okButtonLabel: string
// The string to use for the OK button - will use dijit's common "OK" string
// if not set
okButtonLabel: "",
// cancelButtonLabel: string
// The string to use for the Cancel button - will use dijit's common
// "Cancel" string if not set
cancelButtonLabel: "",
// minPaneWidth: integer
// the minimum pane width (in px) for all child panes. If they are narrower,
// the width will be increased to this value.
minPaneWidth: 0,
postMixInProperties: function(){
// summary: Mix in our labels, if they are not set
this.inherited(arguments);
var loc = dojo.i18n.getLocalization("dijit", "common");
this.okButtonLabel = this.okButtonLabel || loc.buttonOk;
this.cancelButtonLabel = this.cancelButtonLabel || loc.buttonCancel;
},
_setShowButtonsAttr: function(doShow){
// summary: Sets the visibility of the buttons for the widget
var needsLayout = false;
if((this.showButtons != doShow && this._started) ||
(this.showButtons == doShow && !this.started)){
needsLayout = true;
}
dojo.toggleClass(this.domNode, "dojoxRollingListButtonsHidden", !doShow);
this.showButtons = doShow;
if(needsLayout){
if(this._started){
this.layout();
}else{
window.setTimeout(dojo.hitch(this, "layout"), 0);
}
}
},
_itemsMatch: function(/*item*/ item1, /*item*/ item2){
// Summary: returns whether or not the two items match - checks ID if
// they aren't the exact same object
if(!item1 && !item2){
return true;
}else if(!item1 || !item2){
return false;
}
return (item1 == item2 ||
(this._isIdentity && this.store.getIdentity(item1) == this.store.getIdentity(item2)));
},
_removeAfter: function(/*Widget or int*/ idx){
// summary: removes all widgets after the given widget (or index)
if(typeof idx != "number"){
idx = this.getIndexOfChild(idx);
}
if(idx >= 0){
dojo.forEach(this.getChildren(), function(c, i){
if(i > idx){
this.removeChild(c);
c.destroyRecursive();
}
}, this);
}
var children = this.getChildren(), child = children[children.length - 1];
var selItem = null;
while(child && !selItem){
var val = child._getSelected ? child._getSelected() : null;
if(val){
selItem = val.item;
}
child = child.parentPane;
}
if(!this._setInProgress){
this._setValue(selItem);
}
},
addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
// summary: adds a child to this rolling list - if passed an insertIndex,
// then all children from that index on will be removed and destroyed
// before adding the child.
if(insertIndex > 0){
this._removeAfter(insertIndex - 1);
}
this.inherited(arguments);
if(!widget._started){
widget.startup();
}
widget.attr("minWidth", this.minPaneWidth);
this.layout();
if(!this._savedFocus){
widget.focus();
}
},
_setMinPaneWidthAttr: function(value){
// summary:
// Sets the min pane width of all children
if(value !== this.minPaneWidth){
this.minPaneWidth = value;
dojo.forEach(this.getChildren(), function(c){
c.attr("minWidth", value);
});
}
},
_updateClass: function(/* Node */ node, /* String */ type, /* Object? */ options){
// summary:
// sets the state of the given node with the given type and options
// options:
// an object with key-value-pairs. The values are boolean, if true,
// the key is added as a class, if false, it is removed.
if(!this._declaredClasses){
this._declaredClasses = ("dojoxRollingList " + this.className).split(" ");
}
dojo.forEach(this._declaredClasses, function(c){
if(c){
dojo.addClass(node, c + type);
for(var k in options||{}){
dojo.toggleClass(node, c + type + k, options[k]);
}
dojo.toggleClass(node, c + type + "FocusSelected",
(dojo.hasClass(node, c + type + "Focus") && dojo.hasClass(node, c + type + "Selected")));
dojo.toggleClass(node, c + type + "HoverSelected",
(dojo.hasClass(node, c + type + "Hover") && dojo.hasClass(node, c + type + "Selected")));
}
});
},
scrollIntoView: function(/* Widget */ childWidget){
// summary: scrolls the given widget into view
if(this._scrollingTimeout){
window.clearTimeout(this._scrollingTimeout);
}
delete this._scrollingTimeout;
this._scrollingTimeout = window.setTimeout(dojo.hitch(this, function(){
if(childWidget.domNode){
dijit.scrollIntoView(childWidget.domNode);
}
delete this._scrollingTimeout;
return;
}), 1);
},
resize: function(args){
dijit.layout._LayoutWidget.prototype.resize.call(this, args);
},
layout: function(){
var children = this.getChildren();
if(this._contentBox){
var bn = this.buttonsNode;
var height = this._contentBox.h - dojo.marginBox(bn).h -
dojox.html.metrics.getScrollbar().h;
dojo.forEach(children, function(c){
dojo.marginBox(c.domNode, {h: height});
});
}
if(this._focusedPane){
var foc = this._focusedPane;
delete this._focusedPane;
if(!this._savedFocus){
foc.focus();
}
}else if(children && children.length){
if(!this._savedFocus){
children[0].focus();
}
}
},
_onChange: function(/*item*/ value){
this.onChange(value);
},
_setValue: function(/* item */ value){
// summary: internally sets the value and fires onchange
delete this._setInProgress;
if(!this._itemsMatch(this.value, value)){
this.value = value;
this._onChange(value);
}
},
_setValueAttr: function(/* item */ value){
// summary: sets the value of this widget to the given store item
if(this._itemsMatch(this.value, value) && !value){ return; }
if(this._setInProgress && this._setInProgress === value){ return; }
this._setInProgress = value;
if(!value || !this.store.isItem(value)){
var pane = this.getChildren()[0];
pane._setSelected(null);
this._onItemClick(null, pane, null, null);
return;
}
var fetchParentItems = dojo.hitch(this, function(/*item*/ item, /*function*/callback){
// Summary: Fetchs the parent items for the given item
var store = this.store, id;
if(this.parentAttr && store.getFeatures()["dojo.data.api.Identity"] &&
((id = this.store.getValue(item, this.parentAttr)) || id === "")){
// Fetch by parent attribute
var cb = function(i){
if(store.getIdentity(i) == store.getIdentity(item)){
callback(null);
}else{
callback([i]);
}
};
if(id === ""){
callback(null);
}else if(typeof id == "string"){
store.fetchItemByIdentity({identity: id, onItem: cb});
}else if(store.isItem(id)){
cb(id);
}
}else{
// Fetch by finding children
var numCheck = this.childrenAttrs.length;
var parents = [];
dojo.forEach(this.childrenAttrs, function(attr){
var q = {};
q[attr] = item;
store.fetch({query: q, scope: this,
onComplete: function(items){
if(this._setInProgress !== value){
return;
}
parents = parents.concat(items);
numCheck--;
if(numCheck === 0){
callback(parents);
}
}
});
}, this);
}
});
var setFromChain = dojo.hitch(this, function(/*item[]*/itemChain, /*integer*/idx){
// Summary: Sets the value of the widget at the given index in the chain - onchanges are not
// fired here
var set = itemChain[idx];
var child = this.getChildren()[idx];
var conn;
if(set && child){
var fx = dojo.hitch(this, function(){
if(conn){
this.disconnect(conn);
}
delete conn;
if(this._setInProgress !== value){
return;
}
var selOpt = dojo.filter(child._menu.getChildren(), function(i){
return this._itemsMatch(i.item, set);
}, this)[0];
if(selOpt){
idx++;
child._menu.onItemClick(selOpt, {type: "internal",
stopPropagation: function(){},
preventDefault: function(){}});
if(itemChain[idx]){
setFromChain(itemChain, idx);
}else{
this._setValue(set);
this.onItemClick(set, child, this.getChildItems(set));
}
}
});
if(!child.isLoaded){
conn = this.connect(child, "onLoad", fx);
}else{
fx();
}
}else if(idx === 0){
this.attr("value", null);
}
});
var parentChain = [];
var onParents = dojo.hitch(this, function(/*item[]*/ parents){
// Summary: recursively grabs the parents - only the first one is followed
if(parents && parents.length){
parentChain.push(parents[0]);
fetchParentItems(parents[0], onParents);
}else{
if(!parents){
parentChain.pop();
}
parentChain.reverse();
setFromChain(parentChain, 0);
}
});
// Only set the value in display if we are shown - if we are in a dropdown,
// and are hidden, don't actually do the scrolling in the display (it can
// mess up layouts)
var ns = this.domNode.style;
if(ns.display == "none" || ns.visibility == "hidden"){
this._setValue(value);
}else if(!this._itemsMatch(value, this._visibleItem)){
onParents([value]);
}
},
_onItemClick: function(/* Event */ evt, /* dijit._Contained */ pane, /* item */ item, /* item[]? */ children){
// summary: internally called when a widget should pop up its child
if(evt){
var itemPane = this._getPaneForItem(item, pane, children);
var alreadySelected = (evt.type == "click" && evt.alreadySelected);
if(alreadySelected && itemPane){
this._removeAfter(pane.getIndexInParent() + 1);
var next = pane.getNextSibling();
if(next && next._setSelected){
next._setSelected(null);
}
this.scrollIntoView(next);
}else if(itemPane){
this.addChild(itemPane, pane.getIndexInParent() + 1);
if(this._savedFocus){
itemPane.focus(true);
}
}else{
this._removeAfter(pane);
this.scrollIntoView(pane);
}
}else if(pane){
this._removeAfter(pane);
this.scrollIntoView(pane);
}
if(!evt || evt.type != "internal"){
this._setValue(item);
this.onItemClick(item, pane, children);
}
this._visibleItem = item;
},
_getPaneForItem: function(/* item? */ item, /* dijit._Contained? */ parentPane, /* item[]? */ children){ // summary: gets the pane for the given item, and mixes in our needed parts
// Returns the pane for the given item (null if the root pane) - after mixing in
// its stuff.
var ret = this.getPaneForItem(item, parentPane, children);
ret.store = this.store;
ret.parentWidget = this;
ret.parentPane = parentPane||null;
if(!item){
ret.query = this.query;
ret.queryOptions = this.queryOptions;
}else if(children){
ret.items = children;
}else{
ret.items = [item];
}
return ret;
},
_getMenuItemForItem: function(/*item*/ item, /* dijit._Contained */ parentPane){
// summary: returns a widget for the given store item. The returned
// item will be added to this widget's container widget. null will
// be passed in for an "empty" item.
var store = this.store;
if(!item || !store || !store.isItem(item)){
var i = new dijit.MenuItem({
label: dojo.i18n.getLocalization("dojox.widget", "RollingList", this.lang).empty,
disabled: true,
iconClass: "dojoxEmpty",
focus: function(){
// Do nothing on focus of this guy...
}
});
this._updateClass(i.domNode, "Item");
return i;
}else{
var itemLoaded = store.isItemLoaded(item);
var childItems = itemLoaded ? this.getChildItems(item) : undefined;
var widgetItem;
if(childItems){
widgetItem = this.getMenuItemForItem(item, parentPane, childItems);
widgetItem.children = childItems;
this._updateClass(widgetItem.domNode, "Item", {"Expanding": true});
if(!widgetItem._started){
var c = widgetItem.connect(widgetItem, "startup", function(){
this.disconnect(c);
dojo.style(this.arrowWrapper, "display", "");
});
}else{
dojo.style(widgetItem.arrowWrapper, "display", "");
}
}else{
widgetItem = this.getMenuItemForItem(item, parentPane, null);
if(itemLoaded){
this._updateClass(widgetItem.domNode, "Item", {"Single": true});
}else{
this._updateClass(widgetItem.domNode, "Item", {"Unloaded": true});
widgetItem.attr("disabled", true);
}
}
widgetItem.store = this.store;
widgetItem.item = item;
if(!widgetItem.label){
widgetItem.attr("label", this.store.getLabel(item).replace(/,"<"));
}
if(widgetItem.focusNode){
var self = this;
widgetItem.focus = function(){
// Don't set our class
if(!this.disabled){try{this.focusNode.focus();}catch(e){}}
};
widgetItem.connect(widgetItem.focusNode, "onmouseenter", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": true});
}
});
widgetItem.connect(widgetItem.focusNode, "onmouseleave", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": false});
}
});
widgetItem.connect(widgetItem.focusNode, "blur", function(){
self._updateClass(this.domNode, "Item", {"Focus": false, "Hover": false});
});
widgetItem.connect(widgetItem.focusNode, "focus", function(){
self._updateClass(this.domNode, "Item", {"Focus": true});
self._focusedPane = parentPane;
});
if(this.executeOnDblClick){
widgetItem.connect(widgetItem.focusNode, "ondblclick", function(){
self._onExecute();
});
}
}
return widgetItem;
}
},
_setStore: function(/* dojo.data.api.Read */ store){
// summary: sets the store for this widget */
if(store === this.store && this._started){ return; }
this.store = store;
this._isIdentity = store.getFeatures()["dojo.data.api.Identity"];
var rootPane = this._getPaneForItem();
this.addChild(rootPane, 0);
},
_onKey: function(/*Event*/ e){
// summary: called when a keypress event happens on this widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.ESCAPE && this._savedFocus){
try{dijit.focus(this._savedFocus);}catch(e){}
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW ||
e.charOrCode == dojo.keys.RIGHT_ARROW){
dojo.stopEvent(e);
return;
}
},
_resetValue: function(){
// Summary: function called when the value is reset.
this.attr("value", this._lastExecutedValue);
},
_onCancel: function(){
// Summary: function called when the cancel button is clicked. It
// resets its value to whatever was last executed and then cancels
this._resetValue();
this.onCancel();";s:7:"private";b:1;s:7:"summary";s:0:"";}s:35:"dojox.widget.RollingList._onExecute";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:34263:"dojo.provide("dojox.widget.RollingList");
dojo.experimental("dojox.widget.RollingList");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.Menu");
dojo.require("dojox.html.metrics");
dojo.require("dijit.form.Button");
dojo.require("dojo.i18n");
dojo.requireLocalization("dojox.widget", "RollingList");
dojo.requireLocalization("dijit", "common");
dojo.declare("dojox.widget._RollingListPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained], {
// summary: a core pane that can be attached to a RollingList. All panes
// should extend this one
// templateString: string
// our template
templateString: ' |
',
// parentWidget: dojox.widget.RollingList
// Our rolling list widget
parentWidget: null,
// parentPane: dojox.widget._RollingListPane
// The pane that immediately precedes ours
parentPane: null,
// store: store
// the store we must use
store: null,
// items: item[]
// an array of (possibly not-yet-loaded) items to display in this.
// If this array is null, then the query and query options are used to
// get the top-level items to use. This array is also used to watch and
// see if the pane needs to be reloaded (store notifications are handled)
// by the pane
items: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// focusByNode: boolean
// set to false if the subclass will handle its own node focusing
_focusByNode: true,
// minWidth: integer
// the width (in px) for this pane
minWidth: 0,
_setContentAndScroll: function(/*String|DomNode|Nodelist*/cont, isFakeContent){
// summary: sets the value of the content and scrolls it into view
this._setContent(cont, isFakeContent);
this.parentWidget.scrollIntoView(this);
},
_updateNodeWidth: function(n, min){
// summary: updates the min width of the pane to be minPaneWidth
n.style.width = "";
var nWidth = dojo.marginBox(n).w;
if(nWidth < min){
dojo.marginBox(n, {w: min});
}
},
_onMinWidthChange: function(v){
// Called when the min width of a pane has changed
this._updateNodeWidth(this.domNode, v);
},
_setMinWidthAttr: function(v){
if(v !== this.minWidth){
this.minWidth = v;
this._onMinWidthChange(v);
}
},
startup: function(){
if(this._started){ return; }
if(this.store && this.store.getFeatures()["dojo.data.api.Notification"]){
window.setTimeout(dojo.hitch(this, function(){
// Set connections after a slight timeout to avoid getting in the
// condition where we are setting them while events are still
// being fired
this.connect(this.store, "onSet", "_onSetItem");
this.connect(this.store, "onNew", "_onNewItem");
this.connect(this.store, "onDelete", "_onDeleteItem");
}), 1);
}
this.connect(this.focusNode||this.domNode, "onkeypress", "_focusKey");
this.parentWidget._updateClass(this.domNode, "Pane");
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_focusKey: function(/*Event*/e){
// summary: called when a keypress happens on the widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW && this.parentPane){
this.parentPane.focus();
this.parentWidget.scrollIntoView(this.parentPane);
}else if(e.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this.parentWidget._focusedPane != this){
this.parentWidget._focusedPane = this;
this.parentWidget.scrollIntoView(this);
if(this._focusByNode && (!this.parentWidget._savedFocus || force)){
try{(this.focusNode||this.domNode).focus();}catch(e){}
}
}
},
_loadCheck: function(){
// summary: checks that the store is loaded
if(!this._started){
var c = this.connect(this, "startup", function(){
this.disconnect(c);
this._loadCheck();
});
}
var displayState = this.domNode && this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_loadQuery: function(){
// summary: sets the "loading" message and then kicks off a query asyncronously
this.isLoaded = false;
if(this.items){
this._setContentAndScroll(this.onLoadStart(), true);
window.setTimeout(dojo.hitch(this, "_doQuery"), 1);
}else{
this._doQuery();
}
},
_doLoadItems: function(/*item[]*/items, /*function*/callback){
// summary: loads the given items, and then calls the callback when they
// are finished.
var _waitCount = 0, store = this.store;
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){ _waitCount++; }
});
if(_waitCount === 0){
callback();
}else{
var onItem = function(item){
_waitCount--;
if((_waitCount) === 0){
callback();
}
};
dojo.forEach(items, function(item){
if(!store.isItemLoaded(item)){
store.loadItem({item: item, onItem: onItem});
}
});
}
},
_doQuery: function(){
// summary: either runs the query or loads potentially not-yet-loaded items.
var preload = this.parentWidget.preloadItems;
preload = (preload === true || (this.items && this.items.length <= Number(preload)));
if(this.items && preload){
this._doLoadItems(this.items, dojo.hitch(this, "onItems"));
}else if(this.items){
this.onItems();
}else{
this._setContentAndScroll(this.onFetchStart(), true);
this.store.fetch({query: this.query,
onComplete: function(items){
this.items = items;
this.onItems();
},
onError: function(e){
this._onError("Fetch", e);
},
scope: this});
}
},
_hasItem: function(/* item */ item){
// summary: returns whether or not the given item is handled by this
// pane
var items = this.items || [];
for(var i = 0, myItem; (myItem = items[i]); i++){
if(this.parentWidget._itemsMatch(myItem, item)){
return true;
}
}
return false;
},
_onSetItem: function(/* item */ item,
/* attribute-name-string */ attribute,
/* object | array */ oldValue,
/* object | array */ newValue){
// Summary: called when an item in the store has changed
if(this._hasItem(item)){
this._loadCheck(true);
}
},
_onNewItem: function(/* item */ newItem, /*object?*/ parentInfo){
// Summary: called when an item is added to the store
var sel;
if((!parentInfo && !this.parentPane) ||
(parentInfo && this.parentPane && this.parentPane._hasItem(parentInfo.item) &&
(sel = this.parentPane._getSelected()) && this.parentWidget._itemsMatch(sel.item, parentInfo.item))){
this.items.push(newItem);
this._loadCheck(true);
}else if(parentInfo && this.parentPane && this._hasItem(parentInfo.item)){
this._loadCheck(true);
}
},
_onDeleteItem: function(/* item */ deletedItem){
// Summary: called when an item is removed from the store
if(this._hasItem(deletedItem)){
this.items = dojo.filter(this.items, function(i){
return (i != deletedItem);
});
this._loadCheck(true);
}
},
onFetchStart: function(){
// summary:
// called before a fetch starts
return this.loadingMessage;
},
onFetchError: function(/*Error*/ error){
// summary:
// called when a fetch error occurs.
return this.errorMessage;
},
onLoadStart: function(){
// summary:
// called before a load starts
return this.loadingMessage;
},
onLoadError: function(/*Error*/ error){
// summary:
// called when a load error occurs.
return this.errorMessage;
},
onItems: function(){
// summary:
// called after a fetch or load - at this point, this.items should be
// set and loaded. Override this function to "do your stuff"
this._onLoadHandler();
}
});
dojo.declare("dojox.widget._RollingListGroupPane",
[dojox.widget._RollingListPane], {
// summary: a pane that will handle groups (treats them as menu items)
// templateString: string
// our template
templateString: '',
// _menu: dijit.Menu
// The menu that we will call addChild() on for adding items
_menu: null,
_loadCheck: function(){
// summary: checks that the store is loaded
var displayState = this._isShown();
if((this.store || this.items) && ((this.refreshOnShow && displayState) || (!this.isLoaded && displayState))){
this._loadQuery();
}
},
_setContent: function(/*String|DomNode|Nodelist*/cont){
if(!this._menu){
// Only set the content if we don't already have a menu
this.inherited(arguments);
}
},
_onMinWidthChange: function(v){
// override and resize the menu instead
if(!this._menu){ return; }
var dWidth = dojo.marginBox(this.domNode).w;
var mWidth = dojo.marginBox(this._menu.domNode).w;
this._updateNodeWidth(this._menu.domNode, v - (dWidth - mWidth));
},
onItems: function(){
// summary:
// called after a fetch or load
var selectItem, hadChildren = false;
if(this._menu){
selectItem = this._getSelected();
this._menu.destroyRecursive();
}
this._menu = this._getMenu();
var child, selectMenuItem;
if(this.items.length){
dojo.forEach(this.items, function(item){
child = this.parentWidget._getMenuItemForItem(item, this);
if(child){
if(selectItem && this.parentWidget._itemsMatch(child.item, selectItem.item)){
selectMenuItem = child;
}
this._menu.addChild(child);
}
}, this);
}else{
child = this.parentWidget._getMenuItemForItem(null, this);
if(child){
this._menu.addChild(child);
}
}
if(selectMenuItem){
this._setSelected(selectMenuItem);
if((selectItem && !selectItem.children && selectMenuItem.children) ||
(selectItem && selectItem.children && !selectMenuItem.children)){
var itemPane = this.parentWidget._getPaneForItem(selectMenuItem.item, this, selectMenuItem.children);
if(itemPane){
this.parentWidget.addChild(itemPane, this.getIndexInParent() + 1);
}else{
this.parentWidget._removeAfter(this);
this.parentWidget._onItemClick(null, this, selectMenuItem.item, selectMenuItem.children);
}
}
}else if(selectItem){
this.parentWidget._removeAfter(this);
}
this.containerNode.innerHTML = "";
this.containerNode.appendChild(this._menu.domNode);
this.parentWidget.scrollIntoView(this);
this._checkScrollConnection(true);
this.inherited(arguments);
this._onMinWidthChange(this.minWidth);
},
_checkScrollConnection: function(doLoad){
// summary: checks whether or not we need to connect to our onscroll
// function
var store = this.store
if(this._scrollConn){
this.disconnect(this._scrollConn);
}
delete this._scrollConn;
if(!dojo.every(this.items, function(i){return store.isItemLoaded(i);})){
if(doLoad){
this._loadVisibleItems();
}
this._scrollConn = this.connect(this.domNode, "onscroll", "_onScrollPane");
}
},
startup: function(){
this.inherited(arguments);
this.parentWidget._updateClass(this.domNode, "GroupPane");
},
focus: function(/*boolean*/force){
// summary: sets the focus to this current widget
if(this._menu){
if(this._pendingFocus){
this.disconnect(this._pendingFocus);
}
delete this._pendingFocus;
// We focus the right widget - either the focusedChild, the
// selected node, the first menu item, or the menu itself
var focusWidget = this._menu.focusedChild;
if(!focusWidget){
var focusNode = dojo.query(".dojoxRollingListItemSelected", this.domNode)[0];
if(focusNode){
focusWidget = dijit.byNode(focusNode);
}
}
if(!focusWidget){
focusWidget = this._menu.getChildren()[0] || this._menu;
}
this._focusByNode = false;
if(focusWidget.focusNode){
if(!this.parentWidget._savedFocus || force){
try{focusWidget.focusNode.focus();}catch(e){}
}
window.setTimeout(function(){
try{
dijit.scrollIntoView(focusWidget.focusNode);
}catch(e){}
}, 1);
}else if(focusWidget.focus){
if(!this.parentWidget._savedFocus || force){
focusWidget.focus();
}
}else{
this._focusByNode = true;
}
this.inherited(arguments);
}else if(!this._pendingFocus){
this._pendingFocus = this.connect(this, "onItems", "focus");
}
},
_getMenu: function(){
// summary: returns a widget to be used for the container widget.
var self = this;
var menu = new dijit.Menu({
parentMenu: this.parentPane ? this.parentPane._menu : null,
onCancel: function(/*Boolean*/ closeAll){
if(self.parentPane){
self.parentPane.focus(true);
}
},
_moveToPopup: function(/*Event*/ evt){
if(this.focusedChild && !this.focusedChild.disabled){
this.focusedChild._onClick(evt);
}
}
}, this.menuNode);
this.connect(menu, "onItemClick", function(/*dijit.MenuItem*/ item, /*Event*/ evt){
if(item.disabled){ return; }
evt.alreadySelected = dojo.hasClass(item.domNode, "dojoxRollingListItemSelected");
if(evt.alreadySelected &&
((evt.type == "keypress" && evt.charOrCode != dojo.keys.ENTER) ||
(evt.type == "internal"))){
var p = this.parentWidget.getChildren()[this.getIndexInParent() + 1];
if(p){
p.focus(true);
this.parentWidget.scrollIntoView(p);
}
}else{
this._setSelected(item, menu);
this.parentWidget._onItemClick(evt, this, item.item, item.children);
if(evt.type == "keypress" && evt.charOrCode == dojo.keys.ENTER){
this.parentWidget._onExecute();
}
}
});
if(!menu._started){
menu.startup();
}
return menu;
},
_onScrollPane: function(){
// summary: called when the pane has been scrolled - it sets a timeout
// so that we don't try and load our visible items too often during
// a scroll
if(this._visibleLoadPending){
window.clearTimeout(this._visibleLoadPending);
}
this._visibleLoadPending = window.setTimeout(dojo.hitch(this, "_loadVisibleItems"), 500);
},
_layoutHack: function(){
// summary: work around table sizing bugs on FF2 by forcing redraw
// note - this function is taken from dijit.form._FormWidget
if(dojo.isFF == 2 && !this._layoutHackHandle){
var node=this.domNode;
var old = node.style.opacity;
node.style.opacity = "0.999";
this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
this._layoutHackHandle = null;
node.style.opacity = old;
}), 0);
}
},
_loadVisibleItems: function(){
// summary: loads the items that are currently visible in the pane
delete this._visibleLoadPending
var menu = this._menu;
if(!menu){ return; }
var children = menu.getChildren();
if(!children || !children.length){ return; }
var gpbme = function(n, m, pb){
var s = dojo.getComputedStyle(n);
var r = 0;
if(m){ r += dojo._getMarginExtents(n, s).t; }
if(pb){ r += dojo._getPadBorderExtents(n, s).t; }
return r;
};
var topOffset = gpbme(this.domNode, false, true) +
gpbme(this.containerNode, true, true) +
gpbme(menu.domNode, true, true) +
gpbme(children[0].domNode, true, false);
var h = dojo.contentBox(this.domNode).h;
var minOffset = this.domNode.scrollTop - topOffset - (h/2);
var maxOffset = minOffset + (3*h/2);
var menuItemsToLoad = dojo.filter(children, function(c){
var cnt = c.domNode.offsetTop;
var s = c.store;
var i = c.item;
return (cnt >= minOffset && cnt <= maxOffset && !s.isItemLoaded(i));
})
var itemsToLoad = dojo.map(menuItemsToLoad, function(c){
return c.item;
});
var onItems = dojo.hitch(this, function(){
var selectItem = this._getSelected();
var selectMenuItem;
dojo.forEach(itemsToLoad, function(item, idx){
var newItem = this.parentWidget._getMenuItemForItem(item, this);
var oItem = menuItemsToLoad[idx];
var oIdx = oItem.getIndexInParent();
menu.removeChild(oItem);
if(newItem){
if(selectItem && this.parentWidget._itemsMatch(newItem.item, selectItem.item)){
selectMenuItem = newItem;
}
menu.addChild(newItem, oIdx);
if(menu.focusedChild == oItem){
menu.focusChild(newItem);
}
}
oItem.destroy();
}, this);
this._checkScrollConnection(false);
this._layoutHack();
});
this._doLoadItems(itemsToLoad, onItems);
},
_getSelected: function(/*dijit.Menu?*/ menu){
// summary:
// returns the selected menu item - or null if none are selected
if(!menu){ menu = this._menu; }
if(menu){
var children = this._menu.getChildren();
for(var i = 0, item; (item = children[i]); i++){
if(dojo.hasClass(item.domNode, "dojoxRollingListItemSelected")){
return item;
}
}
}
return null;
},
_setSelected: function(/*dijit.MenuItem?*/ item, /*dijit.Menu?*/ menu){
// summary:
// selectes the given item in the given menu (defaults to pane's menu)
if(!menu){ menu = this._menu;}
if(menu){
dojo.forEach(menu.getChildren(), function(i){
this.parentWidget._updateClass(i.domNode, "Item", {"Selected": (item && (i == item && !i.disabled))});
}, this);
}
},
destroy: function(){
if(this._layoutHackHandle){
clearTimeout(this._layoutHackHandle);
}
this.inherited(arguments);
}
});
dojo.declare("dojox.widget.RollingList",
[dijit._Widget, dijit._Templated, dijit._Container], {
// summary: a rolling list that can be tied to a data store with children
// templatePath: string
// our template to use
templatePath: dojo.moduleUrl("dojox.widget", "RollingList/RollingList.html"),
widgetsInTemplate: true,
// className: string
// an additional class (or space-separated classes) to add for our widget
className: "",
// store: store
// the store we must use
store: null,
// query: object
// a query to pass to the datastore. This is only used if items are null
query: null,
// queryOptions: object
// query options to be passed to the datastore
queryOptions: null,
// childrenAttrs: String[]
// one ore more attributes that holds children of a node
childrenAttrs: ["children"],
// parentAttr: string
// the attribute to read for finding our parent item (if any)
parentAttr: "",
// value: item
// The value that has been selected
value: null,
// executeOnDblClick: boolean
// Set to true if you want to call onExecute when an item is
// double-clicked, false if you want to call onExecute yourself. (mainly
// used for popups to control how they want to be handled)
executeOnDblClick: true,
// preloadItems: boolean or int
// if set to true, then onItems will be called only *after* all items have
// been loaded (ie store.isLoaded will return true for all of them). If
// false, then no preloading will occur. If set to an integer, preloading
// will occur if the number of items is less than or equal to the value
// of the integer. The onItems function will need to be aware of handling
// items that may not be loaded
preloadItems: false,
// showButtons: boolean
// if set to true, then buttons for "OK" and "Cancel" will be provided
showButtons: false,
// okButtonLabel: string
// The string to use for the OK button - will use dijit's common "OK" string
// if not set
okButtonLabel: "",
// cancelButtonLabel: string
// The string to use for the Cancel button - will use dijit's common
// "Cancel" string if not set
cancelButtonLabel: "",
// minPaneWidth: integer
// the minimum pane width (in px) for all child panes. If they are narrower,
// the width will be increased to this value.
minPaneWidth: 0,
postMixInProperties: function(){
// summary: Mix in our labels, if they are not set
this.inherited(arguments);
var loc = dojo.i18n.getLocalization("dijit", "common");
this.okButtonLabel = this.okButtonLabel || loc.buttonOk;
this.cancelButtonLabel = this.cancelButtonLabel || loc.buttonCancel;
},
_setShowButtonsAttr: function(doShow){
// summary: Sets the visibility of the buttons for the widget
var needsLayout = false;
if((this.showButtons != doShow && this._started) ||
(this.showButtons == doShow && !this.started)){
needsLayout = true;
}
dojo.toggleClass(this.domNode, "dojoxRollingListButtonsHidden", !doShow);
this.showButtons = doShow;
if(needsLayout){
if(this._started){
this.layout();
}else{
window.setTimeout(dojo.hitch(this, "layout"), 0);
}
}
},
_itemsMatch: function(/*item*/ item1, /*item*/ item2){
// Summary: returns whether or not the two items match - checks ID if
// they aren't the exact same object
if(!item1 && !item2){
return true;
}else if(!item1 || !item2){
return false;
}
return (item1 == item2 ||
(this._isIdentity && this.store.getIdentity(item1) == this.store.getIdentity(item2)));
},
_removeAfter: function(/*Widget or int*/ idx){
// summary: removes all widgets after the given widget (or index)
if(typeof idx != "number"){
idx = this.getIndexOfChild(idx);
}
if(idx >= 0){
dojo.forEach(this.getChildren(), function(c, i){
if(i > idx){
this.removeChild(c);
c.destroyRecursive();
}
}, this);
}
var children = this.getChildren(), child = children[children.length - 1];
var selItem = null;
while(child && !selItem){
var val = child._getSelected ? child._getSelected() : null;
if(val){
selItem = val.item;
}
child = child.parentPane;
}
if(!this._setInProgress){
this._setValue(selItem);
}
},
addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
// summary: adds a child to this rolling list - if passed an insertIndex,
// then all children from that index on will be removed and destroyed
// before adding the child.
if(insertIndex > 0){
this._removeAfter(insertIndex - 1);
}
this.inherited(arguments);
if(!widget._started){
widget.startup();
}
widget.attr("minWidth", this.minPaneWidth);
this.layout();
if(!this._savedFocus){
widget.focus();
}
},
_setMinPaneWidthAttr: function(value){
// summary:
// Sets the min pane width of all children
if(value !== this.minPaneWidth){
this.minPaneWidth = value;
dojo.forEach(this.getChildren(), function(c){
c.attr("minWidth", value);
});
}
},
_updateClass: function(/* Node */ node, /* String */ type, /* Object? */ options){
// summary:
// sets the state of the given node with the given type and options
// options:
// an object with key-value-pairs. The values are boolean, if true,
// the key is added as a class, if false, it is removed.
if(!this._declaredClasses){
this._declaredClasses = ("dojoxRollingList " + this.className).split(" ");
}
dojo.forEach(this._declaredClasses, function(c){
if(c){
dojo.addClass(node, c + type);
for(var k in options||{}){
dojo.toggleClass(node, c + type + k, options[k]);
}
dojo.toggleClass(node, c + type + "FocusSelected",
(dojo.hasClass(node, c + type + "Focus") && dojo.hasClass(node, c + type + "Selected")));
dojo.toggleClass(node, c + type + "HoverSelected",
(dojo.hasClass(node, c + type + "Hover") && dojo.hasClass(node, c + type + "Selected")));
}
});
},
scrollIntoView: function(/* Widget */ childWidget){
// summary: scrolls the given widget into view
if(this._scrollingTimeout){
window.clearTimeout(this._scrollingTimeout);
}
delete this._scrollingTimeout;
this._scrollingTimeout = window.setTimeout(dojo.hitch(this, function(){
if(childWidget.domNode){
dijit.scrollIntoView(childWidget.domNode);
}
delete this._scrollingTimeout;
return;
}), 1);
},
resize: function(args){
dijit.layout._LayoutWidget.prototype.resize.call(this, args);
},
layout: function(){
var children = this.getChildren();
if(this._contentBox){
var bn = this.buttonsNode;
var height = this._contentBox.h - dojo.marginBox(bn).h -
dojox.html.metrics.getScrollbar().h;
dojo.forEach(children, function(c){
dojo.marginBox(c.domNode, {h: height});
});
}
if(this._focusedPane){
var foc = this._focusedPane;
delete this._focusedPane;
if(!this._savedFocus){
foc.focus();
}
}else if(children && children.length){
if(!this._savedFocus){
children[0].focus();
}
}
},
_onChange: function(/*item*/ value){
this.onChange(value);
},
_setValue: function(/* item */ value){
// summary: internally sets the value and fires onchange
delete this._setInProgress;
if(!this._itemsMatch(this.value, value)){
this.value = value;
this._onChange(value);
}
},
_setValueAttr: function(/* item */ value){
// summary: sets the value of this widget to the given store item
if(this._itemsMatch(this.value, value) && !value){ return; }
if(this._setInProgress && this._setInProgress === value){ return; }
this._setInProgress = value;
if(!value || !this.store.isItem(value)){
var pane = this.getChildren()[0];
pane._setSelected(null);
this._onItemClick(null, pane, null, null);
return;
}
var fetchParentItems = dojo.hitch(this, function(/*item*/ item, /*function*/callback){
// Summary: Fetchs the parent items for the given item
var store = this.store, id;
if(this.parentAttr && store.getFeatures()["dojo.data.api.Identity"] &&
((id = this.store.getValue(item, this.parentAttr)) || id === "")){
// Fetch by parent attribute
var cb = function(i){
if(store.getIdentity(i) == store.getIdentity(item)){
callback(null);
}else{
callback([i]);
}
};
if(id === ""){
callback(null);
}else if(typeof id == "string"){
store.fetchItemByIdentity({identity: id, onItem: cb});
}else if(store.isItem(id)){
cb(id);
}
}else{
// Fetch by finding children
var numCheck = this.childrenAttrs.length;
var parents = [];
dojo.forEach(this.childrenAttrs, function(attr){
var q = {};
q[attr] = item;
store.fetch({query: q, scope: this,
onComplete: function(items){
if(this._setInProgress !== value){
return;
}
parents = parents.concat(items);
numCheck--;
if(numCheck === 0){
callback(parents);
}
}
});
}, this);
}
});
var setFromChain = dojo.hitch(this, function(/*item[]*/itemChain, /*integer*/idx){
// Summary: Sets the value of the widget at the given index in the chain - onchanges are not
// fired here
var set = itemChain[idx];
var child = this.getChildren()[idx];
var conn;
if(set && child){
var fx = dojo.hitch(this, function(){
if(conn){
this.disconnect(conn);
}
delete conn;
if(this._setInProgress !== value){
return;
}
var selOpt = dojo.filter(child._menu.getChildren(), function(i){
return this._itemsMatch(i.item, set);
}, this)[0];
if(selOpt){
idx++;
child._menu.onItemClick(selOpt, {type: "internal",
stopPropagation: function(){},
preventDefault: function(){}});
if(itemChain[idx]){
setFromChain(itemChain, idx);
}else{
this._setValue(set);
this.onItemClick(set, child, this.getChildItems(set));
}
}
});
if(!child.isLoaded){
conn = this.connect(child, "onLoad", fx);
}else{
fx();
}
}else if(idx === 0){
this.attr("value", null);
}
});
var parentChain = [];
var onParents = dojo.hitch(this, function(/*item[]*/ parents){
// Summary: recursively grabs the parents - only the first one is followed
if(parents && parents.length){
parentChain.push(parents[0]);
fetchParentItems(parents[0], onParents);
}else{
if(!parents){
parentChain.pop();
}
parentChain.reverse();
setFromChain(parentChain, 0);
}
});
// Only set the value in display if we are shown - if we are in a dropdown,
// and are hidden, don't actually do the scrolling in the display (it can
// mess up layouts)
var ns = this.domNode.style;
if(ns.display == "none" || ns.visibility == "hidden"){
this._setValue(value);
}else if(!this._itemsMatch(value, this._visibleItem)){
onParents([value]);
}
},
_onItemClick: function(/* Event */ evt, /* dijit._Contained */ pane, /* item */ item, /* item[]? */ children){
// summary: internally called when a widget should pop up its child
if(evt){
var itemPane = this._getPaneForItem(item, pane, children);
var alreadySelected = (evt.type == "click" && evt.alreadySelected);
if(alreadySelected && itemPane){
this._removeAfter(pane.getIndexInParent() + 1);
var next = pane.getNextSibling();
if(next && next._setSelected){
next._setSelected(null);
}
this.scrollIntoView(next);
}else if(itemPane){
this.addChild(itemPane, pane.getIndexInParent() + 1);
if(this._savedFocus){
itemPane.focus(true);
}
}else{
this._removeAfter(pane);
this.scrollIntoView(pane);
}
}else if(pane){
this._removeAfter(pane);
this.scrollIntoView(pane);
}
if(!evt || evt.type != "internal"){
this._setValue(item);
this.onItemClick(item, pane, children);
}
this._visibleItem = item;
},
_getPaneForItem: function(/* item? */ item, /* dijit._Contained? */ parentPane, /* item[]? */ children){ // summary: gets the pane for the given item, and mixes in our needed parts
// Returns the pane for the given item (null if the root pane) - after mixing in
// its stuff.
var ret = this.getPaneForItem(item, parentPane, children);
ret.store = this.store;
ret.parentWidget = this;
ret.parentPane = parentPane||null;
if(!item){
ret.query = this.query;
ret.queryOptions = this.queryOptions;
}else if(children){
ret.items = children;
}else{
ret.items = [item];
}
return ret;
},
_getMenuItemForItem: function(/*item*/ item, /* dijit._Contained */ parentPane){
// summary: returns a widget for the given store item. The returned
// item will be added to this widget's container widget. null will
// be passed in for an "empty" item.
var store = this.store;
if(!item || !store || !store.isItem(item)){
var i = new dijit.MenuItem({
label: dojo.i18n.getLocalization("dojox.widget", "RollingList", this.lang).empty,
disabled: true,
iconClass: "dojoxEmpty",
focus: function(){
// Do nothing on focus of this guy...
}
});
this._updateClass(i.domNode, "Item");
return i;
}else{
var itemLoaded = store.isItemLoaded(item);
var childItems = itemLoaded ? this.getChildItems(item) : undefined;
var widgetItem;
if(childItems){
widgetItem = this.getMenuItemForItem(item, parentPane, childItems);
widgetItem.children = childItems;
this._updateClass(widgetItem.domNode, "Item", {"Expanding": true});
if(!widgetItem._started){
var c = widgetItem.connect(widgetItem, "startup", function(){
this.disconnect(c);
dojo.style(this.arrowWrapper, "display", "");
});
}else{
dojo.style(widgetItem.arrowWrapper, "display", "");
}
}else{
widgetItem = this.getMenuItemForItem(item, parentPane, null);
if(itemLoaded){
this._updateClass(widgetItem.domNode, "Item", {"Single": true});
}else{
this._updateClass(widgetItem.domNode, "Item", {"Unloaded": true});
widgetItem.attr("disabled", true);
}
}
widgetItem.store = this.store;
widgetItem.item = item;
if(!widgetItem.label){
widgetItem.attr("label", this.store.getLabel(item).replace(/,"<"));
}
if(widgetItem.focusNode){
var self = this;
widgetItem.focus = function(){
// Don't set our class
if(!this.disabled){try{this.focusNode.focus();}catch(e){}}
};
widgetItem.connect(widgetItem.focusNode, "onmouseenter", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": true});
}
});
widgetItem.connect(widgetItem.focusNode, "onmouseleave", function(){
if(!this.disabled){
self._updateClass(this.domNode, "Item", {"Hover": false});
}
});
widgetItem.connect(widgetItem.focusNode, "blur", function(){
self._updateClass(this.domNode, "Item", {"Focus": false, "Hover": false});
});
widgetItem.connect(widgetItem.focusNode, "focus", function(){
self._updateClass(this.domNode, "Item", {"Focus": true});
self._focusedPane = parentPane;
});
if(this.executeOnDblClick){
widgetItem.connect(widgetItem.focusNode, "ondblclick", function(){
self._onExecute();
});
}
}
return widgetItem;
}
},
_setStore: function(/* dojo.data.api.Read */ store){
// summary: sets the store for this widget */
if(store === this.store && this._started){ return; }
this.store = store;
this._isIdentity = store.getFeatures()["dojo.data.api.Identity"];
var rootPane = this._getPaneForItem();
this.addChild(rootPane, 0);
},
_onKey: function(/*Event*/ e){
// summary: called when a keypress event happens on this widget
if(e.charOrCode == dojo.keys.BACKSPACE){
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.ESCAPE && this._savedFocus){
try{dijit.focus(this._savedFocus);}catch(e){}
dojo.stopEvent(e);
return;
}else if(e.charOrCode == dojo.keys.LEFT_ARROW ||
e.charOrCode == dojo.keys.RIGHT_ARROW){
dojo.stopEvent(e);
return;
}
},
_resetValue: function(){
// Summary: function called when the value is reset.
this.attr("value", this._lastExecutedValue);
},
_onCancel: function(){
// Summary: function called when the cancel button is clicked. It
// resets its value to whatever was last executed and then cancels
this._resetValue();
this.onCancel();
},
_onExecute: function(){
// Summary: function called when the OK button is clicked or when an
// item is selected (double-clicked or "enter" pressed on it)
this._lastExecutedValue = this.attr("value");
this.onExecute();";s:7:"private";b:1;s:7:"summary";s:0:"";}s:30:"dojox.widget.RollingList.focus";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:420:" var wasSaved = this._savedFocus;
this._savedFocus = dijit.getFocus(this);
if(!this._savedFocus.node){
delete this._savedFocus;
}
if(!this._focusedPane){
var child = this.getChildren()[0];
if(child && !wasSaved){
child.focus(true);
}
}else{
this._savedFocus = dijit.getFocus(this);
var foc = this._focusedPane;
delete this._focusedPane;
if(!wasSaved){
foc.focus(true);
}
}";s:7:"summary";s:35:"sets the focus state of this widget";}s:34:"dojox.widget.RollingList.handleKey";a:2:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:7:"summary";s:0:"";}s:44:"dojox.widget.RollingList._updateChildClasses";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:302:" var children = this.getChildren();
var length = children.length;
dojo.forEach(children, function(c, idx){
dojo.toggleClass(c.domNode, "dojoxRollingListPaneCurrentChild", (idx == (length - 1)));
dojo.toggleClass(c.domNode, "dojoxRollingListPaneCurrentSelected", (idx == (length - 2)));
});";s:7:"summary";s:143:"Called when a child is added or removed - so that we can
update the classes for styling the "current" one differently than
the others";s:7:"private";b:1;}s:32:"dojox.widget.RollingList.startup";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:419:" if(this._started){ return; }
if(!this.getParent || !this.getParent()){
this.resize();
this.connect(dojo.global, "onresize", "resize");
}
this.connect(this, "addChild", "_updateChildClasses");
this.connect(this, "removeChild", "_updateChildClasses");
this._setStore(this.store);
this.attr("showButtons", this.showButtons);
this.inherited(arguments);
this._lastExecutedValue = this.attr("value");";s:7:"summary";s:0:"";}s:38:"dojox.widget.RollingList.getChildItems";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:4:"item";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:239:" var childItems, store = this.store;
dojo.forEach(this.childrenAttrs, function(attr){
var vals = store.getValues(item, attr);
if(vals && vals.length){
childItems = (childItems||[]).concat(vals);
}
});
return childItems;";s:7:"summary";s:48:"Returns the child items for the given store item";}s:43:"dojox.widget.RollingList.getMenuItemForItem";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:3:{s:4:"item";a:1:{s:4:"type";s:4:"item";}s:10:"parentPane";a:1:{s:4:"type";s:16:"dijit._Contained";}s:8:"children";a:2:{s:8:"optional";b:1;s:4:"type";s:6:"item[]";}}s:6:"source";s:32:" return new dijit.MenuItem({});";s:7:"summary";s:81:"user overridable function to return a widget for the given item
and its children.";}s:39:"dojox.widget.RollingList.getPaneForItem";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:3:{s:4:"item";a:2:{s:8:"optional";b:1;s:4:"type";s:4:"item";}s:10:"parentPane";a:2:{s:8:"optional";b:1;s:4:"type";s:16:"dijit._Contained";}s:8:"children";a:2:{s:8:"optional";b:1;s:4:"type";s:6:"item[]";}}s:6:"source";s:107:" if(!item || children){
return new dojox.widget._RollingListGroupPane({});
}else{
return null;
}";s:7:"summary";s:283:"user-overridable function to return a pane that corresponds
to the given item in the store. It can return null to not add a new pane
(ie, you are planning on doing something else with it in onItemClick)
Item is undefined for the root pane, children is undefined for non-group panes";}s:36:"dojox.widget.RollingList.onItemClick";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:3:{s:4:"item";a:1:{s:4:"type";s:4:"item";}s:4:"pane";a:1:{s:4:"type";s:16:"dijit._Contained";}s:8:"children";a:2:{s:8:"optional";b:1;s:4:"type";s:6:"item[]";}}s:6:"source";s:73:" // summary: called when an item is clicked - it receives the store item";s:7:"summary";s:59:"called when an item is clicked - it receives the store item";}s:34:"dojox.widget.RollingList.onExecute";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:60:" // summary: exists so that popups don't disappear too soon";s:7:"summary";s:46:"exists so that popups don't disappear too soon";}s:33:"dojox.widget.RollingList.onCancel";a:4:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:6:"source";s:62:" // summary: exists so that we can close ourselves if we wish";s:7:"summary";s:48:"exists so that we can close ourselves if we wish";}s:33:"dojox.widget.RollingList.onChange";a:5:{s:9:"prototype";s:24:"dojox.widget.RollingList";s:4:"type";s:8:"Function";s:10:"parameters";a:1:{s:5:"value";a:1:{s:4:"type";s:4:"item";}}s:6:"source";s:62:" // summary: called when the value of this widget has changed";s:7:"summary";s:48:"called when the value of this widget has changed";}s:41:"dojox.widget.RollingList._declaredClasses";a:3:{s:8:"instance";s:24:"dojox.widget.RollingList";s:7:"private";b:1;s:7:"summary";s:0:"";}s:42:"dojox.widget.RollingList._scrollingTimeout";a:3:{s:8:"instance";s:24:"dojox.widget.RollingList";s:7:"private";b:1;s:7:"summary";s:0:"";}s:39:"dojox.widget.RollingList._setInProgress";a:3:{s:8:"instance";s:24:"dojox.widget.RollingList";s:7:"private";b:1;s:7:"summary";s:0:"";}s:37:"dojox.widget.RollingList._visibleItem";a:3:{s:8:"instance";s:24:"dojox.widget.RollingList";s:7:"private";b:1;s:7:"summary";s:0:"";}s:36:"dojox.widget.RollingList._isIdentity";a:3:{s:8:"instance";s:24:"dojox.widget.RollingList";s:7:"private";b:1;s:7:"summary";s:0:"";}s:43:"dojox.widget.RollingList._lastExecutedValue";a:3:{s:8:"instance";s:24:"dojox.widget.RollingList";s:7:"private";b:1;s:7:"summary";s:0:"";}s:36:"dojox.widget.RollingList._savedFocus";a:3:{s:8:"instance";s:24:"dojox.widget.RollingList";s:7:"private";b:1;s:7:"summary";s:0:"";}s:12:"dojox.widget";a:2:{s:4:"type";s:6:"Object";s:7:"summary";s:0:"";}s:5:"dojox";a:2:{s:4:"type";s:6:"Object";s:7:"summary";s:0:"";}}