Htk.Select = new Class ({ Extends: Htk.Field ,Implements: Db.Iterator ,Tag: 'htk-combo' ,Properties: { /** * The model associated to this form. **/ model: { type: Db.Model ,set: function (x) { this.link ({_model: x}, {'status-changed-after': this._onModelChange}); this._onModelChange (); } ,get: function () { return this._model; } }, /** * The row where the form positioned, has -1 if the row is unselected. **/ row: { type: Number ,set: function (x) { if (!this._model || this._model.numRows <= x || x < -1) x = -1; if (x == this._row) return; this._row = x; this.iterChanged (); } ,get: function () { return this._row; } }, /** * The number of rows in the form. **/ numRows: { type: Number ,get: function () { if (this._model) return this._model.numRows; return 0; } }, /** * Checks if the form data is ready. **/ ready: { type: Boolean ,get: function () { return this._model && this._model.ready; } }, /** * Checks if the form data is ready. **/ placeholder: { type: String ,set: function (x) { this._placeholder = x; this._refreshShowText (x); } ,get: function () { return this._placeholder; } }, /** * Wether to allow null values. **/ notNull: { type: Boolean ,set: function (x) { this._notNull = x; } ,get: function () { return this._notNull; } } } ,_row: -1 ,_model: null ,valueColumnIndex: 0 ,valueColumnName: null ,showColumnIndex: 1 ,showColumnName: null ,_notNull: true ,_webkitRefresh: false ,initialize: function (props) { var button = this.createElement ('button'); button.className = 'htk-select input'; button.addEventListener ('mousedown', this._onButtonMouseDown.bind (this)); this.parent (props); } ,on: function (id, callback, instance) { switch (id) { case 'click': case 'mousedown': case 'focusout': this.node.addEventListener (id, callback.bind (instance, this)); break; default: this.parent (id, callback, instance); } } ,_setRow: function (row) { this._row = row; this._refreshShowText (); this.iterChanged (); } ,_onButtonMouseDown: function (e) { if (this._popup) { this._popup.hide (); return; } var model = this._model; var menu = document.createElement ('div'); menu.className = 'htk-select-menu'; var grid = new Htk.Grid ({showHeader: false}); menu.appendChild (grid.getNode ()); var gridNode = grid.getNode (); gridNode.addEventListener ('click', this._onGridClicked.bind (this, grid)); var column = new Htk.ColumnText ({columnIndex: this.showColumnIndex}); grid.appendColumn (column); grid.model = model; var popup = this._popup = new Htk.Popup ({childNode: menu}); popup.on ('closed', this._onPopupClose.bind (this)); popup.show (this.node); this.signalEmit ('menu-show'); e.stopPropagation (); } ,_onGridClicked: function (grid, e) { var target = e.target; var parentNode = target.parentNode; while (parentNode !== grid.tbody) { target = parentNode; parentNode = parentNode.parentNode; } var value; var row = target.rowIndex - 1; if (row >= 0) value = this._model.getByIndex (row, this.valueColumnIndex); else value = null; this._setRow (row); this.valueChanged (value); this._popup.hide (); e.stopPropagation (); } ,_onPopupClose: function () { this._popup = null; this.signalEmit ('menu-hide'); } ,_refreshShowText: function () { var model = this._model; if (this._row !== -1) var showText = model.getByIndex (this._row, this.showColumnIndex); else if (model && model.status === Db.Model.Status.LOADING) var showText = _('Loading...'); else if (this._placeholder) var showText = this._placeholder; else var showText = ''; Vn.Node.setText (this.node, showText); } ,_onModelChange: function () { var model = this._model; this.signalEmit ('status-changed'); if (this._popup) this._popup.reset (); if (model && model.ready) { this._selectOption (); this.signalEmit ('ready'); } else this._setRow (-1); } ,setEditable: function (editable) { this.node.disabled = !editable; } ,_selectOption: function () { var row; if (this._model && this._model.ready) row = this._model.searchByIndex (this.valueColumnIndex, this._value); else row = -1; this._setRow (row); } ,putValue: function (value) { this._selectOption (); } });