var Widget = require ('./widget'); module.exports = new Class ({ Extends: 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: null } } ,_builder: null ,_formId: 'form' ,render: function () { var div = this.createRoot ('div'); this._container = this.createElement ('div'); this._container.className = 'htk-repeater'; div.appendChild (this._container); } ,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].set; } ,_buildBox: function (index) { var set = new Db.SimpleIterator ({ model: this._model, row: index }); this._builder.add (this._formId, set); var res = this._builder.load (); res.link (); this._childsData.push ({ builder: res, set: set }); if (this._renderer) this._renderer (res, set); 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: { var emptyMessage = this.emptyMessage ? this.emptyMessage : _('NoData'); this._showMessage (emptyMessage, 'refresh'); break; } case Db.Model.Status.ERROR: this._showMessage (_('ErrorLoadingData'), 'error'); break; } this.node.appendChild (this._container); this.signalEmit ('change'); } ,_showNoRecordsFound: function (count) { if (this._model.numRows === 0) this._showMessage (_('EmptyList'), 'clean'); } ,_showMessage: function (message, src) { var div = this.createElement ('div'); div.className = 'message'; this._container.appendChild (div); if (src) { var img = this.createElement ('img'); img.alt = ''; img.src = 'image/icon/light/'+ src +'.svg'; div.appendChild (img); } else { var spinner = new Htk.Spinner (); spinner.start (); div.appendChild (spinner.node); } div.appendChild (this.createTextNode (message)); } ,_onRowDelete: function (model, row) { Vn.Node.remove (this._container.childNodes[row]); this._unrefChildData (row); this._childsData.splice (row, 1); for (var i = row; i < this._model.numRows; i++) this._childsData[i].set.row = i; this._showNoRecordsFound (); } ,_onRowUpdate: function (model, row, columns) { this._childsData[row].set.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.set.unref (); childData.builder.unref (); } ,_destroy: function () { this._freeChildsData (); this.parent (); } });