@qooxdoo/framework
Version:
The JS Framework for Coders
390 lines (314 loc) • 9.58 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2011 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Gabriel Munteanu (gabios)
* Christopher Zuendorf (czuendorf)
************************************************************************ */
/**
* The SelectBox
*
* an example, how to use the SelectBox:
* *Example*
*
* <pre class='javascript'>
* var page1 = new qx.ui.mobile.page.Page();
* page1.addListener("initialize", function()
* {
* var sel = new qx.ui.mobile.form.SelectBox();
* page1.add(sel);
* var model = new qx.data.Array(["item1","item2"]);
* sel.setModel(model);
* model.push("item3");
*
* var but = new qx.ui.mobile.form.Button("setSelection");
* page1.add(but);
* but.addListener("tap", function(){
* sel.setSelection("item3");
* }, this);
*
* sel.addListener("changeSelection", function(evt) {
* console.log(evt.getData());
* }, this);
*
* var title = new qx.ui.mobile.form.Title("item2");
* title.bind("value",sel,"value");
* sel.bind("value",title,"value");
* page1.add(title);
* },this);
*
* page1.show();
* </pre>
*/
qx.Class.define("qx.ui.mobile.form.SelectBox",
{
extend : qx.ui.mobile.core.Widget,
include : [
qx.ui.mobile.form.MValue,
qx.ui.form.MForm,
qx.ui.mobile.form.MText,
qx.ui.mobile.form.MState
],
implement : [
qx.ui.form.IForm,
qx.ui.form.IField,
qx.ui.form.IModel
],
/*
*****************************************************************************
CONSTRUCTOR
*****************************************************************************
*/
construct : function()
{
this.base(arguments);
// This text node is for compatibility reasons, because Firefox can not
// change appearance of SelectBoxes.
this._setAttribute("type","text");
this.setReadOnly(true);
this.addListener("focus", this.blur);
this.addListener("tap", this._onTap, this);
// Selection dialog creation.
this.__selectionDialog = this._createSelectionDialog();
this.addCssClass("gap");
// When selectionDialogs changes selection, get chosen selectedIndex from it.
this.__selectionDialog.addListener("changeSelection", this._onChangeSelection, this);
},
/*
*****************************************************************************
EVENTS
*****************************************************************************
*/
events :
{
/**
* Fired when user selects an item.
*/
changeSelection : "qx.event.type.Data"
},
/*
*****************************************************************************
PROPERTIES
*****************************************************************************
*/
properties :
{
// overridden
defaultCssClass :
{
refine : true,
init : "selectbox"
},
// overridden
activatable :
{
refine :true,
init : true
},
/**
* Defines if the SelectBox has a clearButton, which resets the selection.
*/
nullable :
{
init : true,
check : "Boolean",
apply : "_applyNullable"
},
/**
* The model to use to render the list.
*/
model :
{
check : "qx.data.Array",
apply : "_applyModel",
event : "changeModel",
nullable : true,
init : null
},
/**
* The selected index of this SelectBox.
*/
selection :
{
init : null,
validate : "_validateSelection",
apply : "_applySelection",
nullable : true
}
},
members :
{
__selectionDialog : null,
// overridden
_getTagName : function()
{
// No select here, see BUG #6054
return "input";
},
/**
* Creates the menu dialog. Override this to customize the widget.
*
* @return {qx.ui.mobile.dialog.Menu} A dialog, containing a selection list.
*/
_createSelectionDialog : function() {
var menu = new qx.ui.mobile.dialog.Menu();
// Special appearance for SelectBox menu items.
menu.setSelectedItemClass("selectbox-selected");
menu.setUnselectedItemClass("selectbox-unselected");
// Hide selectionDialog on tap on blocker.
menu.setHideOnBlockerTap(true);
return menu;
},
/**
* Returns the SelectionDialog.
* @return {qx.ui.mobile.dialog.Menu} the SelectionDialog.
*/
getSelectionDialog : function() {
return this.__selectionDialog;
},
/**
* Sets the dialog title on the selection dialog.
* @param title {String} the title to set on selection dialog.
*/
setDialogTitle : function(title) {
this.__selectionDialog.setTitle(title);
},
/**
* Set the ClearButton label of the selection dialog.
* @param value {String} the value to set on the ClearButton at selection dialog.
*/
setClearButtonLabel : function(value) {
this.__selectionDialog.setClearButtonLabel(value);
},
/**
* Sets the selected text value of this SelectBox.
* @param value {String} the text value which should be selected.
*/
_setValue : function(value) {
if(this.getModel() == null) {
return;
}
if (value == "") {
if (this.isNullable()) {
this.setSelection(null);
} else {
this.setSelection(0);
}
} else if (value != null) {
this.setSelection(this.getModel().indexOf(value));
} else {
this.setSelection(null);
}
},
/**
* Get the text value of this
* It is called by setValue method of qx.ui.mobile.form.MValue mixin.
* @return {Number} the new selected index of the SelectBox.
*/
_getValue : function() {
return this._getAttribute("value");
},
/**
* Renders this SelectBox. Override this if you would like to display the
* values of the SelectBox in a different way than the default.
*/
_render : function() {
if(this.getModel() != null && this.getModel().length > 0) {
var selectedItem = this.getModel().getItem(this.getSelection());
this._setAttribute("value", selectedItem);
}
this._domUpdated();
},
/**
* Sets the model property to the new value
* @param value {qx.data.Array}, the new model
* @param old {qx.data.Array?}, the old model
*/
_applyModel : function(value, old){
value.addListener("change", this._render, this);
if (old != null) {
old.removeListener("change", this._render, this);
}
this._render();
},
/**
* Refreshs selection dialogs model, and shows it.
*/
__showSelectionDialog : function () {
if(this.isEnabled() == true) {
// Set index before items, because setItems() triggers rendering.
this.__selectionDialog.setSelectedIndex(this.getSelection());
this.__selectionDialog.setItems(this.getModel());
this.__selectionDialog.show();
}
},
/**
* Gets the selectedIndex out of change selection event and renders view.
* @param evt {qx.event.type.Data} data event.
*/
_onChangeSelection : function (evt) {
this.setSelection(evt.getData().index);
this._render();
},
/**
* Handler for <code>tap</code> event on this widget.
* @param evt {qx.event.type.Tap} the handling tap event.
*/
_onTap : function(evt) {
this.__showSelectionDialog();
// request focus so that it leaves previous widget
// such as text field and hide virtual keyboard.
evt.getOriginalTarget().focus();
},
/**
* Validates the selection value.
* @param value {Integer} the selection value to validate.
*/
_validateSelection : function(value) {
if(value != null && qx.lang.Type.isNumber(value) == false)
{
throw new qx.core.ValidationError(
"Validation Error: Input value is not a number"
);
}
if(this.getModel() === null) {
throw new qx.core.ValidationError(
"Validation Error: Please apply model before selection"
);
}
if(!this.isNullable() && value === null ) {
throw new qx.core.ValidationError(
"Validation Error: SelectBox is not nullable"
);
}
if(value != null && (value < 0 || value >= this.getModel().getLength())) {
throw new qx.core.ValidationError(
"Validation Error: Input value is out of model range"
);
}
},
// property apply
_applySelection : function(value, old) {
var selectedItem = this.getModel().getItem(value);
this.fireDataEvent("changeSelection", {index: value, item: selectedItem});
this._render();
},
// property apply
_applyNullable : function(value, old) {
// Delegate nullable property.
this.__selectionDialog.setNullable(value);
}
},
destruct : function()
{
this.__selectionDialog.removeListener("changeSelection", this._onChangeSelection, this);
this._disposeObjects("__selectionDialog","__selectionDialogTitle");
this.removeListener("focus", this.blur);
this.removeListener("tap", this._onTap, this);
}
});