Skip to content

Instantly share code, notes, and snippets.

@johnspackman
Created June 17, 2019 13:53
Show Gist options
  • Save johnspackman/6ee9ddb793547b8f4ff78d5f7c341e7d to your computer and use it in GitHub Desktop.
Save johnspackman/6ee9ddb793547b8f4ff78d5f7c341e7d to your computer and use it in GitHub Desktop.
Example input field with button
"searchfield": {
include: "textfield",
style: function(states, style) {
style = qx.lang.Object.clone(style);
style.padding = 0;
style.margin = 0;
return style;
}
},
"searchfield/field": {
style: function(states, style) {
return {
padding: 0,
margin: 2
};
}
},
"inlinebutton" : {
alias : "atom",
style : function(states) {
return {
padding: 2,
margin: 0,
decorator : states.pressed
|| (states.checked && !states.hovered)
|| (states.checked && states.disabled) ? "inlinebutton-checked"
: states.hovered && !states.disabled ? "inlinebutton-hovered"
: undefined
};
}
},
/**
* Presents a search field, with an inline search button at the right hand end,
* fires a "search" event when the user pressed Enter or clicks the button.
* Optional timeout is used to fire the search event after a period of
* inactivity, although the search event is only fired by timeout if the value
* is different to the last search event.
*/
qx.Class.define("grasshopper.af.ui.SearchField", {
extend: qx.ui.core.Widget,
implement: [ qx.ui.form.IStringForm, qx.ui.form.IForm ],
include: [ qx.ui.form.MForm ],
construct: function() {
this.base(arguments);
this._setLayout(new qx.ui.layout.HBox());
this._add(this.getChildControl("field"), {
flex: 1
});
this._add(this.getChildControl("buttons"));
this.__timeout = new grasshopper.utils.Timeout(0, this._onInactivityTimeout, this);
this.bind("timeout", this.__timeout, "duration");
this.addListenerOnce("appear", function(evt) {
if (this.isAllowEmptyValue())
this.__doSearch();
}, this);
},
properties: {
/** Alignment of the text */
textAlign: {
check: [ "left", "center", "right" ],
nullable: true,
themeable: true,
apply: "_applyXxxx"
},
/** Whether the field is read only */
readOnly: {
check: "Boolean",
apply: "_applyXxxx",
event: "changeReadOnly",
init: false
},
/** Maximal number of characters that can be entered in the TextArea. */
maxLength: {
check: "PositiveInteger",
apply: "_applyXxxx",
init: Infinity
},
/**
* Whether the {@link #changeValue} event should be fired on every key
* input. If set to true, the changeValue event is equal to the
* {@link #input} event.
*/
liveUpdate: {
check: "Boolean",
init: false,
apply: "_applyXxxx"
},
/**
* String value which will be shown as a hint if the field is all of: unset,
* unfocused and enabled. Set to null to not show a placeholder text.
*/
placeholder: {
check: "String",
nullable: true,
apply: "_applyXxxx"
},
/**
* RegExp responsible for filtering the value of the textfield. the RegExp
* gives the range of valid values. The following example only allows digits
* in the textfield.
*
* <pre class='javascript'>
* field.setFilter(/[0-9]/);
* </pre>
*/
filter: {
check: "RegExp",
nullable: true,
init: null,
apply: "_applyXxxx"
},
/** Inactivity timeout (milliseconds) */
timeout: {
check: "Number",
init: 500,
nullable: false,
event: "changeTimeout"
},
/** Whether the auto search should fire if the field is empty */
allowEmptyValue: {
check: "Boolean",
init: true,
nullable: false,
event: "changeAllowEmptyValue"
},
// overridden
appearance: {
refine: true,
init: "searchfield"
},
// overridden
allowGrowY: {
refine: true,
init: false
},
// overridden
allowShrinkY: {
refine: true,
init: false
}
},
events: {
/**
* Fired when the search button is clicked, data is the value
*/
"search": "qx.event.type.Data",
/**
* The event is fired on every keystroke modifying the value of the field.
*
* The method {@link qx.event.type.Data#getData} returns the current value
* of the text field.
*/
"input": "qx.event.type.Data",
/**
* The event is fired each time the text field looses focus and the text
* field values has changed.
*
* If you change {@link #liveUpdate} to true, the changeValue event will be
* fired after every keystroke and not only after every focus loss. In that
* mode, the changeValue event is equal to the {@link #input} event.
*
* The method {@link qx.event.type.Data#getData} returns the current text
* value of the field.
*/
"changeValue": "qx.event.type.Data"
},
members: {
__timeout: null,
__lastSearchValue: null,
/**
* Callback for inactivity timeout
*/
_onInactivityTimeout: function(evt) {
if (!this.__lastSearchValue || this.__lastSearchValue != this.getValue())
this.__doSearch();
},
/**
* Callback for any keypress
*
* @param evt
*/
__onKeyPress: function(evt) {
if (evt.getKeyIdentifier() == "Enter") {
this.__timeout.killTimer();
this.__doSearch();
} else
this.__timeout.resetTimer();
},
/**
* Callback for keypress which caused input
*
* @param evt
*/
__onKeyInput: function(evt) {
this.__timeout.resetTimer();
},
/**
* Callback for a timeout
*
* @param userData
* @param timerId
*/
__doSearch: function(userData, timerId) {
var str = this.getValue();
this.debug("__doSearch: str=" + str + " getValue=" + this.getValue());
if (!str)
str = "";
this.setValue(str);
if (str || this.isAllowEmptyValue()) {
this.__lastSearchValue = str;
this.fireDataEvent("search", str);
}
},
/**
* ApplyXxxx
*/
_applyXxxx: function(value, oldValue, name) {
this.getChildControl("field")["set" + qx.lang.String.firstUp(name)](value);
},
/**
* set accessor for psuedo property
*/
setValue: function(value) {
this.__timeout.killTimer();
return this.getChildControl("field").setValue(value);
},
/**
* get accessor for psuedo property
*/
getValue: function() {
var str = this.getChildControl("field").getValue();
if (str) {
str = str.trim();
if (!str.length)
return null;
}
return str;
},
/**
* reset accessor for psuedo property
*/
resetValue: function() {
this.__timeout.killTimer();
return this.getChildControl("field").resetValue();
},
/*
* @Override
*/
_createChildControlImpl: function(id, hash) {
switch (id) {
case "field":
var fld = new qx.ui.form.TextField;
fld.addListener("input", function(evt) {
this.fireDataEvent("input", evt.getData());
}, this);
fld.addListener("changeValue", function(evt) {
this.fireDataEvent("changeValue", evt.getData());
}, this);
fld.addListener("keypress", this.__onKeyPress, this);
fld.addListener("keyinput", this.__onKeyInput, this);
return fld;
case "buttons":
var comp = new qx.ui.container.Composite(new qx.ui.layout.HBox());
comp.add(this.getChildControl("btnSearch"));
return comp;
case "btnSearch":
var btn = new grasshopper.af.ui.SearchFieldButton("Search", "grasshopper/icon/16/search.png");
btn.addListener("execute", this.__doSearch, this);
return btn;
}
return this.base(arguments, id, hash);
}
}
});
qx.Class.define("grasshopper.af.ui.SearchFieldButton", {
extend: qx.ui.form.Button,
properties: {
appearance: {
refine: true,
init: "inlinebutton"
},
show: {
refine: true,
init: "icon"
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment