I'm new to Wicket and I want to create an ajax-behavior that call my Javacode if a Functionkey is pressed.
My idea is to create an behavior that send some Javascript to the Browser, that only the F-Key cause an ajax-callback.
public class HomePage extends WebPage {
public HomePage(final PageParameters parameters) {
super(parameters);
add(new AbstractDefaultAjaxBehavior(){
#Override
protected void respond(AjaxRequestTarget target) {
//retrieve the Parametervalue from request
final Request request = RequestCycle.get().getRequest();
final String jsKeycode = request.getRequestParameters()
.getParameterValue("keycode").toString("");
//test output
target.appendJavaScript("alert('from wicket ajax. you pressed "+jsKeycode+"')");
}
#Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
//Append JavaScriptcode
response.render(OnDomReadyHeaderItem.forScript(
"\n\n" +
"$(document).keydown(" +
"function(event){\n" + //120, 121 Example for F9 and F10
"if((event.keyCode == 120) || (event.keyCode == 121)){\n" +
"event.preventDefault();\n" +
"window.alert('F-Key pressed');\n" +
//perform ajax-callback with keyCode
"}\n" +
"});\n"));
}
});
Now my problem is:
What I have to code, that an ajax callback will perform with the pressed keycode as an Parameter?
osmdamv give me the hint to find the "Wicketsolution" for my problem. Now here is my Code to catch a Keypress and send only in certain cases an ajaxrequest to the wicketserver.
With this example it should be possible for other user to adapt this code for their needs.
public HomePage(final PageParameters parameters) {
super(parameters);
add(new AjaxEventBehavior("keydown"){
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
IAjaxCallListener listener = new AjaxCallListener(){
#Override
public CharSequence getPrecondition(Component component) {
//this javascript code evaluates wether an ajaxcall is necessary.
//Here only by keyocdes for F9 and F10
return "var keycode = Wicket.Event.keyCode(attrs.event);" +
"if ((keycode == 120) || (keycode == 121))" +
" return true;" +
"else" +
" return false;";
}
};
attributes.getAjaxCallListeners().add(listener);
//Append the pressed keycode to the ajaxrequest
attributes.getDynamicExtraParameters()
.add("var eventKeycode = Wicket.Event.keyCode(attrs.event);" +
"return {keycode: eventKeycode};");
//whithout setting, no keyboard events will reach any inputfield
attributes.setAllowDefault(true);
}
#Override
protected void onEvent(AjaxRequestTarget target) {
//Extract the keycode parameter from RequestCycle
final Request request = RequestCycle.get().getRequest();
final String jsKeycode = request.getRequestParameters()
.getParameterValue("keycode").toString("");
target.appendJavaScript("alert('from wicket ajax. you pressed "+jsKeycode+"')");
}
});
Edit:
I insert the attributes.setAllowDefault(true). Now it works correct.
you should use AjaxEventBehavior using decorators
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
{
super.updateAjaxAttributes(AjaxRequestAttributes attributes);
IAjaxCallListener listener = new IAjaxCallListener()
{
#Override
public CharSequence getBeforeHandler(Component c) { return handler; }
.....
};
attributes.getAjaxCallListeners().add(listener);
}
Related
I've an combo box which is composed of a text field and a popup with a CellTable showing the suggestion items. The text field has a change handler that updates the CellTable's selection.
When typing a character and clicking an already selected suggestion, the first click is swallowed. The second click works and triggers the selection via the CellTable.addDomHandler(...).
Any idea why first click is swallowed?
Example code:
private static class SuggestFieldTextAndPopupSandbox extends SimplePanel {
private final TextField mText;
private CellTable<Handle<String>> mTable;
private SingleSelectionModel<Handle<String>> mTableSelection;
private SingleSelectionModel<Handle<String>> mSelection;
private ProvidesKey<Handle<String>> mKeyProvider = new SimpleKeyProvider<Handle<String>>();
private PopupPanel mPopup;
private List<Handle<String>> mData;
public SuggestFieldTextAndPopupSandbox() {
mData = Lists.newArrayList(new Handle<String>("AAA"), new Handle<String>("AAB"), new Handle<String>("ABB"));
mSelection = new SingleSelectionModel<Handle<String>>();
mText = new TextField();
mText.addKeyPressHandler(new KeyPressHandler() {
#Override
public void onKeyPress(KeyPressEvent pEvent) {
mPopup.showRelativeTo(mText);
}
});
mText.addBlurHandler(new BlurHandler() {
#Override
public void onBlur(BlurEvent pEvent) {
mTableSelection.setSelected(startsWith(mText.getValue()), true);
}
});
mText.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent pEvent) {
mText.setText(mText.getText().toUpperCase());
}
});
mTable = new CellTable<Handle<String>>(0, GWT.<TableResources>create(TableResources.class));
mTable.setTableLayoutFixed(false);
mTableSelection = new SingleSelectionModel<Handle<String>>(mKeyProvider);
mTable.setSelectionModel(mTableSelection);
mTable.addDomHandler(new ClickHandler() {
#Override
public void onClick(final ClickEvent pEvent) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
#Override
public void execute() {
mSelection.setSelected(mTableSelection.getSelectedObject(), true);
mText.setFocus(true);
mPopup.hide();
}
});
}
}, ClickEvent.getType());
mTable.addColumn(new TextColumn<Handle<String>>() {
#Override
public String getValue(Handle<String> pObject) {
return pObject.get();
}
});
mTable.setRowData(mData);
mPopup = new PopupPanel();
mPopup.setAutoHideEnabled(true);
mPopup.setWidget(mTable);
mPopup.setWidth("200px");
mPopup.setHeight("200px");
VerticalPanel p = new VerticalPanel();
p.add(mText);
setWidget(p);
}
private Handle<String> startsWith(final String pValue) {
final String val = nullToEmpty(pValue).toLowerCase();
int i = 0;
for (Handle<String> item : mData) {
String value = item.get();
if (value != null && value.toLowerCase().startsWith(val)) {
return item;
}
i++;
}
return null;
}
}
I reproduced your issue and here is the problem:
when you click on the suggestions the following is happening:
The text field is loosing focus which causes the corresponding ChangeEvent to be dealt with followed by the BlurEvent.
The click causes the popup to get the focus now which is why it is swallowed.
If you remove the ChangeHandler and the BlurHandler of the text field the issue disappears. But I think I found another solution
Try replacing the DOM handler of the mTable with a selection handler relative to the mTableSelection as follows:
mTableSelection.addSelectionChangeHandler(new Handler(){
#Override
public void onSelectionChange(SelectionChangeEvent event) {
Scheduler.get().scheduleFinally(new ScheduledCommand() {
#Override
public void execute() {
mSelection.setSelected(mTableSelection.getSelectedObject(), true);
mText.setFocus(true);
mPopup.hide();
}
});
}
});
Found a way how to properly solve this.
Skipping the blur handler when user hovers the suggestion list area seemed to fix that issue, at least from the tests that were done didn't see any more issues.
This was necessary because just before the user clicks a suggestion item, the text is blurred and it fires a selection change. This in turn cancels the selection made when user clicks an item.
I want to get values of my textBox before change its value and after changed its value.
String beforeValue = "";
TextBox textBox = new TextBox();
textBox.addFocusHandler(new FocusHandler() {
public void onFocus(final FocusEvent event) {
beforeValue = textBox.getText();
}
});
textBox.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(final ValueChangeEvent<String> event) {
System.out.println("Before value is " + beforeValue);
System.out.println("After value is " + textBox.getText());
}
});
As above codes , I need two handlers (FocusHandler and ValueChangeHadler) to get before value and after value . My question is how can I get it by one Handler or another simple and easy way ? I don't want to use two handlers to get it. Any suggestions would be appreciated. Thanks in advance !
Your idea(using 2 handlers) is fair enough but its buggy. I don't think it can be done in a better way. If you want to use a single handler, create a custom class wrapper using the two handlers.
Here is the code for you.
public abstract class MyValueChangeHandler<T> implements ValueChangeHandler<T> {
T prevValue = null;
T value = null;
public MyValueChangeHandler(final ValueBoxBase<T> widget) {
widget.addFocusHandler(new FocusHandler() {
public void onFocus(FocusEvent event) {
prevValue = widget.getValue();
}
});
}
#Override
public void onValueChange(ValueChangeEvent<T> event) {
value = event.getValue();
onValueChange(value, prevValue);
// or
// onValueChange(event, prevValue);
prevValue = value;
}
public abstract void onValueChange(T value, T prevValue);
// or
// public abstract void onValueChange(ValueChangeEvent<T> event, T prevValue);
}
And you can use it as,
TextBox box = new TextBox();
box.addValueChangeHandler(new MyValueChangeHandler<String>(box) {
#Override
public void onValueChange(String value, String prevValue) {
Window.alert("Prev Value : " + prevValue + " CurrnetValue: "
+ value);
}
});
I try to add button into rowExpander content:
so i have:
ButtonCell<Integer> viewButtonCell = new ButtonCell<Integer>();
and row expander
RowExpander<XX> expander = new RowExpander<XX>(identity, new AbstractCell<XX>() {
#Override
public void render(Context context, XX value, SafeHtmlBuilder sb) {
sb.appendHtmlConstant("<span>");
viewButtonCell.render(context, value.getId(), sb);
sb.appendHtmlConstant("</span>");
}
ButtonCell is rendered OK i can see it BUT I cannot click it, no selecthandler from ButtonCell is call :(.
Any ideas how can I make selectHandlerActive for this button ?
Thanks
i created some new RowExpander :
public class MTPRowExpander<M> extends RowExpander<M> {
public static int id = 0;
public static interface WidgetFactory<M> {
public Widget createWidget(M model);
}
private WidgetFactory<M> wf;
private Set<Integer> expandedRows;
public MTPRowExpander(IdentityValueProvider<M> valueProvider,WidgetFactory<M> wf) {
this(valueProvider,GWT.<RowExpanderAppearance<M>> create(RowExpanderAppearance.class),wf);
}
public MTPRowExpander(IdentityValueProvider<M> valueProvider,final RowExpanderAppearance<M> appearance, WidgetFactory<M> wf) {
super(valueProvider, null, appearance);
this.wf = wf;
expandedRows = new HashSet<Integer>();
}
#Override
protected boolean beforeExpand(M model, Element body, XElement row,int rowIndex) {
if (expandedRows.contains(rowIndex)) {
return true;
} else {
expandedRows.add(rowIndex);
return super.beforeExpand(model, body, row, rowIndex);
}
}
#Override
protected String getBodyContent(final M model, int rowIndex) {
final int curentid = id++;
Scheduler.get().scheduleFinally(new ScheduledCommand() {
#Override
public void execute() {
Widget widget = wf.createWidget(model);
com.google.gwt.dom.client.Element item = grid.getElement().childElement(".widget" + curentid);
item.appendChild(widget.getElement());
ComponentHelper.setParent(grid, widget);
}
});
return "<div class='widget" + curentid + "'></div>";
}
}
I know that this solution is not perfect but I didnt know how to resolve problem at more proper way.
I am using DataGrid in a GWT. One of the column is TextIntputCell. I want to place one tooltip on the same cell to show the updated value at each FieldUpdter Event.
Following is the code.
TextInputCell commentCell= new TextInputCell();{
#Override
public void render(com.google.gwt.cell.client.Cell.Context context, String value, SafeHtmlBuilder sb) {
String imagePath = GWT.getModuleBaseURL() + "/images/about.png";
sb.appendHtmlConstant(" ");
sb.appendHtmlConstant("<img src = '" + imagePath + "'height = '20px' width = '20px' title='"+value+"'/>");
}
};
commentColumn = new Column<RegisteredClasses, String>(commentCell) {
#Override
public String getValue(RegisteredClasses object) {
return "";
}
};
FieldUpdater<RegisteredClasses, String> commentUpdater = new FieldUpdater<RegisteredClasses, String>() {
#Override
public void update(int index, RegisteredClasses object, String value) {
if(value != null ){
object.setCommentsByContractor(value);
}
}
};
commentColumn.setFieldUpdater(commentUpdater);
table.addColumn(commentColumn, localizableResource.onAcceptanceComment());
table.setColumnWidth(commentColumn, "280px");
This is not working as the render event is called once only. Is there any way to call it explicitly.
I'm trying to add keyboardlistener to a canvas in GWT. But it doesn't work.
I added also mouse handlers to this canvas and it works.
here is the mouse handler's code (this works):
canvas.addMouseMoveHandler(new MouseMoveHandler() {
public void onMouseMove(MouseMoveEvent event) {
mouseX = event.getRelativeX(canvas.getElement());
mouseY = event.getRelativeY(canvas.getElement());
}
});
here is the keyboard handler's code (this doesn't work):
canvas.addKeyDownHandler(new KeyDownHandler() {
public void onKeyDown(KeyDownEvent event) {
int key = event.getNativeKeyCode();
System.out.println("key: " + (char) key);
System.out.println("keypressed :"+ event.getNativeKeyCode());
}
});
Any ideas?
edit :
Initializing my canvas is done as the same way as this class : GwtCanvasDemo.java. I just added addkeydownhandler and didn't work. I tried in Chrome and IE9.
I've tried this code. And its working for me.
RootPanel rootPanel = RootPanel.get();
final Canvas canvas = Canvas.createIfSupported();
canvas.addKeyDownHandler(new KeyDownHandler() {
public void onKeyDown(KeyDownEvent event) {
int key = event.getNativeKeyCode();
System.out.println("key: " + (char) key);
System.out.println("keypressed :"+ event.getNativeKeyCode());
}
});
rootPanel.add(canvas, 0 ,0);
Output: (when i pressed 'i','u','y' after selecting the canvas on the browser)
key: I
keypressed :73
key: U
keypressed :85
key: Y
keypressed :89