hedera-web/js/htk/field/combo.js

352 lines
5.9 KiB
JavaScript

var ColumnText = require ('../column/text');
module.exports = new Class
({
Extends: Htk.Field
,Implements: Vn.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.rowChanged ();
}
,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;
}
},
/**
* The field to use for internal value.
*/
valueField:
{
type: String,
value: 'id'
},
/**
* The field to display.
*/
showField:
{
type: String,
value: 'name'
},
params:
{
type: Object
,set: function (x)
{
this.setAll (x);
}
,get: function ()
{
return this._params;
}
}
,$:
{
type: Object
,set: function (x)
{
this.setAll (x);
}
,get: function ()
{
return this._params;
}
}
}
,_row: -1
,_model: null
,_notNull: false
,_selected: false
,render: function ()
{
var node = this.createRoot ('div');
Vn.Node.addClass (node, 'input clickable');
node.tabIndex = 0;
node.addEventListener ('mousedown',
this._onMouseDown.bind (this));
var icons = this.createElement ('div');
icons.className = 'icons';
node.appendChild (icons);
var clearButton = this.createElement ('htk-icon');
clearButton.className = 'clear button';
clearButton.icon = 'close';
clearButton.node.title = _('Clear');
clearButton.on ('click', this._onClearClick, this);
clearButton.on ('mousedown', this._onClearMouseDown, this);
icons.appendChild (clearButton.node);
var downIcon = this.createElement ('htk-icon');
downIcon.className = 'down';
downIcon.icon = 'down';
icons.appendChild (downIcon.node);
var text = this.createElement ('div');
text.className = 'text';
node.appendChild (text);
this.text = text;
this.clearButton = clearButton;
this._refreshShowText ();
}
,_onClearClick: function ()
{
this.value = null;
}
,_onClearMouseDown: function (_, event)
{
event.preventDefault ();
}
,_onMouseDown: function (e)
{
if (e.defaultPrevented)
return;
if (this._popup)
{
this._popup.hide ();
return;
}
var model = this._model;
if (model.status === Db.Model.Status.CLEAN)
model.refresh ();
var menu = this.createElement ('div');
menu.className = 'htk-combo-menu';
var grid = new Htk.Grid ({showHeader: false});
menu.appendChild (grid.node);
var gridNode = grid.node;
gridNode.addEventListener ('click',
this._onGridClicked.bind (this, grid));
var column = new ColumnText ({column: this.showField});
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, true, e);
this.emit ('menu-show');
}
,_onGridClicked: function (grid, e)
{
e.stopPropagation ();
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.get (row, this.valueField);
else
value = null;
this._popup.hide ();
var changed = this._putValue (value);
this._selected = false;
this._setRow (row, true);
if (changed)
{
if (this.conditionalFunc)
this.conditionalFunc (this, newValue);
this._notifyChanges ();
}
}
,_onPopupClose: function ()
{
this._popup = null;
this.emit ('menu-hide');
}
,_setRow: function (row)
{
this._row = row;
if (!this._selected)
{
if (row != -1)
this._selected = true;
this.rowChanged ();
this._refreshShowText ();
}
}
,_onModelChange: function ()
{
var model = this._model;
this.emit ('status-changed');
if (this._popup)
this._popup.reset ();
this._selectOption ();
if (model && model.ready)
this.emit ('ready');
}
,_selectOption: function ()
{
var row;
if (this._model && this._model.ready)
row = this._model.search (this.valueField, this._value);
else
row = -1;
this._setRow (row);
}
,_putFieldValue: function ()
{
this._selected = false;
this._selectOption ();
}
,_refreshShowText: function ()
{
var model = this._model;
if (this._value != null)
var showText = this.$[this.showField];
else if (model && model.status === Db.Model.Status.LOADING)
var showText = _('Loading...');
else if (this._placeholder)
var showText = this._placeholder;
else
var showText = '';
if (this.node)
{
var display;
if (this._value && !this._notNull)
display = '';
else
display = 'none';
this.clearButton.node.style.display = display;
Vn.Node.setText (this.text, showText);
}
}
,setEditable: function (editable)
{
this.node.disabled = !editable;
}
});