110 lines
3.5 KiB
JavaScript
110 lines
3.5 KiB
JavaScript
//>>built
|
|
define("dojox/mvc/Repeat", [
|
|
"dojo/_base/declare",
|
|
"dojo/dom",
|
|
"./_Container"
|
|
], function(declare, dom, _Container){
|
|
/*=====
|
|
declare = dojo.declare;
|
|
dom = dojo.dom;
|
|
_Container = dojox.mvc._Container;
|
|
=====*/
|
|
|
|
return declare("dojox.mvc.Repeat", [_Container], {
|
|
// summary:
|
|
// A model-bound container which binds to a collection within a data model
|
|
// and produces a repeating user-interface from a template for each
|
|
// iteration within the collection.
|
|
//
|
|
// description:
|
|
// A repeat is bound to an intermediate dojo.Stateful node corresponding
|
|
// to an array in the data model. Child dijits or custom view components
|
|
// inside it inherit their parent data binding context from it.
|
|
|
|
// index: Integer
|
|
// An index used to track the current iteration when the repeating UI is
|
|
// produced. This may be used to parameterize the content in the repeat
|
|
// template for the current iteration.
|
|
//
|
|
// For example, consider a collection of search or query results where
|
|
// each item contains a "Name" property used to prime the "Results" data
|
|
// model. Then, the following CRUD-style UI displays all the names in
|
|
// the search results in text boxes where they may be updated or such.
|
|
//
|
|
// | <div dojoType="dojox.mvc.Repeat" ref="Results">
|
|
// | <div class="row" dojoType="dojox.mvc.Group" ref="${this.index}">
|
|
// | <label for="nameInput${this.index}">Name:</label>
|
|
// | <input dojoType="dijit.form.TextBox" id="nameInput${this.index}" ref="'Name'"></input>
|
|
// | </div>
|
|
// | </div>
|
|
index : 0,
|
|
|
|
// summary:
|
|
// Override and save template from body.
|
|
postscript: function(params, srcNodeRef){
|
|
this.srcNodeRef = dom.byId(srcNodeRef);
|
|
if(this.srcNodeRef){
|
|
if(this.templateString == ""){ // only overwrite templateString if it has not been set
|
|
this.templateString = this.srcNodeRef.innerHTML;
|
|
}
|
|
this.srcNodeRef.innerHTML = "";
|
|
}
|
|
this.inherited(arguments);
|
|
},
|
|
|
|
////////////////////// PRIVATE METHODS ////////////////////////
|
|
|
|
_updateBinding: function(name, old, current){
|
|
// summary:
|
|
// Rebuild repeating UI if data binding changes.
|
|
// tags:
|
|
// private
|
|
this.inherited(arguments);
|
|
this._buildContained();
|
|
},
|
|
|
|
_buildContained: function(){
|
|
// summary:
|
|
// Destroy any existing contained view, recreate the repeating UI
|
|
// markup and parse the new contents.
|
|
// tags:
|
|
// private
|
|
|
|
// TODO: Potential optimization: only create new widgets for insert, only destroy for delete.
|
|
this._destroyBody();
|
|
this._updateAddRemoveWatch();
|
|
|
|
var insert = "";
|
|
for(this.index = 0; this.get("binding").get(this.index); this.index++){
|
|
insert += this._exprRepl(this.templateString);
|
|
}
|
|
var repeatNode = this.srcNodeRef || this.domNode;
|
|
repeatNode.innerHTML = insert;
|
|
|
|
// srcNodeRef is used in _createBody, so in the programmatic create case where repeatNode was set
|
|
// from this.domNode we need to set srcNodeRef from repeatNode
|
|
this.srcNodeRef = repeatNode;
|
|
|
|
this._createBody();
|
|
},
|
|
|
|
_updateAddRemoveWatch: function(){
|
|
// summary:
|
|
// Updates the watch handle when binding changes.
|
|
// tags:
|
|
// private
|
|
if(this._addRemoveWatch){
|
|
this._addRemoveWatch.unwatch();
|
|
}
|
|
var pThis = this;
|
|
this._addRemoveWatch = this.get("binding").watch(function(name,old,current){
|
|
if(/^[0-9]+$/.test(name.toString())){
|
|
if(!old || !current){
|
|
pThis._buildContained();
|
|
} // else not an insert or delete, will get updated in above
|
|
}
|
|
});
|
|
}
|
|
});
|
|
});
|