Htk.Repeater = new Class ({ Extends: Htk.Widget ,Tag: 'htk-repeater' ,Child: 'model' ,Properties: { /** * The source data model. **/ model: { type: Db.Model ,set: function (x) { this.link ({_model: x}, { 'status-changed': this._onModelChange ,'row-deleted': this._onRowDelete ,'row-updated': this._onRowUpdate ,'row-inserted': this._onRowInsert }); this._onModelChange (); } ,get: function () { this._model; } } /** * The identifier for internal iterator. **/ ,formId: { type: String ,set: function (x) { this._formId = x; } ,get: function () { this._formId; } } /** * {Function (Vn.BuilderResult, Db.Form)} Function to call after every * box rendering. **/ ,renderer: { type: Function ,set: function (x) { this._renderer = x; } ,get: function () { this._renderer; } } /** * Message that should be displayed when source model is not ready. **/ ,emptyMessage: { type: String ,value: _('NoData') } } ,_builder: null ,_formId: 'form' ,initialize: function (props) { var div = this.createElement ('div'); this._container = document.createElement ('div'); this._container.className = 'htk-repeater'; div.appendChild (this._container); this.parent (props); } ,loadXml: function (builderResult, node) { this.parent (builderResult, node); var builder = this._builder = new Vn.Builder (); builder.setParent (builderResult); builder.loadXmlFromNode (node.firstElementChild); this._onModelChange (); } ,getChild: function (index) { return this._container.childNodes[index]; } ,getBuilder: function (index) { return this._childsData[index].builder; } ,getForm: function (index) { return this._childsData[index].form; } ,_buildBox: function (index) { var form = new Db.Form ({ model: this._model, row: index }); this._builder.add (this._formId, form); var res = this._builder.load (); res.link (); this._childsData.push ({ builder: res, form: form }); if (this._renderer) this._renderer (res, form); return res.getMain (); } ,_onModelChange: function () { if (!this._model || !this._builder) return; this.node.removeChild (this._container); Vn.Node.removeChilds (this._container); this._freeChildsData (); this._childsData = []; switch (this._model.status) { case Db.Model.Status.READY: { for (var i = 0; i < this._model.numRows; i++) this._container.appendChild (this._buildBox (i)); this._showNoRecordsFound (); break; } case Db.Model.Status.LOADING: this._showMessage (_('Loading'), null); break; case Db.Model.Status.CLEAN: this._showMessage (this.emptyMessage, 'refresh.svg'); break; case Db.Model.Status.ERROR: this._showMessage (_('ErrorLoadingData'), 'error.svg'); break; } this.node.appendChild (this._container); this.signalEmit ('change'); } ,_showNoRecordsFound: function (count) { if (this._model.numRows === 0) this._showMessage (_('EmptyList'), 'clean.svg'); } ,_showMessage: function (message, src) { var div = document.createElement ('div'); div.className = 'message'; this._container.appendChild (div); if (src) { var img = document.createElement ('img'); img.alt = ''; img.src = 'image/'+ src; div.appendChild (img); } else { var spinner = new Htk.Spinner (); spinner.start (); div.appendChild (spinner.getNode ()); } div.appendChild (document.createTextNode (message)); } ,_onRowDelete: function (model, row) { Vn.Node.remove (this._container.childNodes[row]); this._unrefChildData (row); this._showNoRecordsFound (); } ,_onRowUpdate: function (model, row, columns) { // this.form[row].signalEmit ('iter-changed'); } ,_onRowInsert: function (model, row) { var box = this._buildBox (row); this._container.appendChild (box); } ,_freeChildsData: function () { if (this._childsData) for (var i = 0; i < this._childsData.length; i++) this._unrefChildData (i); } ,_unrefChildData: function (index) { var childData = this._childsData[index]; childData.form.unref (); childData.builder.unref (); } ,destroy: function () { this._freeChildsData (); this.parent (); } });