ClickHandler doesn't fire in jquery-mobile header & footer - gwt

after hours of searching and trying, I decided to ask here.
JqmHeader.java
public class JqmHeader extends ComplexPanel {
public JqmHeader() {
setElement(DOM.createDiv());
getElement().setAttribute("data-role", "header");
}
public void add(Widget widget) {
super.add(widget, getElement());
}
}
JqmPage.java
public class JqmPage extends ComplexPanel {
...
public JqmPage(String id) {
setElement(Document.get().createDivElement());
getElement().setAttribute("data-role", "page");
getElement().setAttribute("data-url", id);
RootPanel.get().add(page);
render(page.getId());
}
private native void render(String id) /*-{
$wnd.$("#" + id).page();
}-*/;
...
}
MyPage.java extends JqmPage.java
...
JqmHeader header = new JqmHeader();
Button b = new Button("TestButton");
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert("TestButton clicked");
}
});
header.add(b);
this.add(header);
...
My Problem
So, my Problem is, that the ClickHandler from the Button in the header bar doesn't fire. If I add the Button not to the header, but to the "RootPage", like
this.add(b)
, everything works.
I think it must lie at the jquery-mobile header implementation. Are there any workarounds /ideas?
Thanks from Berlin,
Alex

JQuery Mobile swallows the events on headers so they are not propagated to GWT. What I did in solving this for jqm4gwt (https://github.com/sksamuel/jqm4gwt) was to have a general listener on the page level and then compare event source. If it was a button in the header then I fire that event on the button manually.
Take a look at bindHeaderEvents in https://github.com/sksamuel/jqm4gwt/blob/master/src/main/java/com/sksamuel/jqm4gwt/JQMPage.java
Also, the jqm4gwt project might be a good solution for you to save you having to invent all these widgets yourself.

If you want to take a look at a pure GWT solution for building mobile apps you could take a look at http://www.m-gwt.com

Related

How to add click handler to GWT ImageResource cell?

Please help me out with this problem.
I have this code below,I actually want to insert an image into a GWT datagrid and add a click handler to the image. But it is not responding to clicks, pls what do you think might be the problem?
This is the Resource interface
public interface Resources extends ClientBundle {
#Source("delete.png")
ImageResource getDeleteImage();
#Source("edit.png")
ImageResource getEditImage();
}
Below is the ImageResource Cell that I coded, but it is not responding to clicks.
DataGrid<AccountDTO> dataGrid = new DataGrid<AccountDTO>();
Column<AccountDTO, ImageResource>delete = new Column<AccountDTO, ImageResource>(new ImageResourceCell()) {
#Override
public ImageResource getValue(AccountDTO object) {
return resources.getDeleteImage();
}
};
delete.setFieldUpdater(new FieldUpdater<AccountDTO, ImageResource>() {
#Override
public void update(int arg0, AccountDTO object, ImageResource resource) {
Window.alert(object.getId() + "" + object.getChargeAccount());
dataProvider.getList().remove(object);
dataProvider.refresh();
dataGrid.redraw();
}
dataGrid.addColumn(delete, "");
dataGrid.setColumnWidth(delete, 3.0, Unit.EM)
In the same way you have use a custom cell by extending AbstractCell for cell table you would extend ClickableTextCell (have a look a this answer). But as you are using image in your cell it gets tricky. This tutorial worked for us.
This is an old question, but there is a much simpler solution than suggested in the other answer.
datagrid.addCellPreviewHandler(new Handler<AccountDTO>() {
#Override
public void onCellPreview(CellPreviewEvent<AccountDTO> event) {
if ("click".equals(event.getNativeEvent().getType())) {
if (event.getColumn() == datagrid.getColumnIndex(myImageColumn)) {
AccountDTO account = event.getValue();
// Do what you need with a click
}
}
}
});

Gwt form question

I have a gwt form which has about 70-100 widgets (textboxes,listboxes,custom widgets etc)
I am trying to implement the features of CUT ,COPY in this form .For this i have 2 buttons right on top of the form.
Now the problem i have is that when i click on the copy button , the widget that was focused in the form looses focus and i dont know which text to copy(or which widget was last focused before the focus getting to the copy button)
I was planning to implement blur handlers on all the widgets but i feel is a very laborious and not a good solution.
How can i get around this issue?
Thanks
Perhaps someone with a deeper insight might provide a better approach but I beleive adding blur handlers is perfectly valid. I do not quite see why you think it would be laborious, after all you don't need a different handler for each of your widgets, you can get away with only one(at most a couple for a variety of controls..), here is a very simple example,
public class CustomBlurHandler implements BlurHandler{
Object lastSource;
String text;
#Override
public void onBlur(BlurEvent event) {
if (event.getSource() instanceof TextBox) {
lastSource = event.getSource();
text = textBox.getSelectedText();
}
}
public Object getLastSource() {
return lastSource;
}
public String getText() {
return text;
}
}
and onModuleLoad :
public class Test implements EntryPoint {
CustomBlurHandler handler = new CustomBlurHandler();
public void onModuleLoad() {
TextBox text1 = new TextBox();
TextBox text2 = new TextBox();
text1.addBlurHandler(handler);
text2.addBlurHandler(handler);
Button b = new Button("Get last selected text");
b.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
Window.alert(handler.getLastSource()+ " " + handler.getText());
}
});
RootPanel.get().add(text1);
RootPanel.get().add(text2);
RootPanel.get().add(b);
}
}

not able to set focus on TextBox in a GWT app

This should not be causing me so much pain but it is. It is a very weird problem. In a GWT application, I have two .java files, login.java and application.java.
In login.java, I'm creating a user login page where if the username and password is verified the user is logged into the application and application.java takes from here.
Now in application. java's onModuleLoad() this is how i'm starting with a login page.
public void onModuleLoad() {
Login login = new Login();
login.textBoxUsername.setFocus(true);
RootLayoutPanel.get().add(login);}
This works great, except for the tiny problem of not being able to set focus on the username TextBox when the page loads. I have tried evrything I can think of. But the focus just doesn't get set on the TextBox. If anyone can suggest a solution, please do. Your help is greatly appreciated.
Solution: (In case it helps anyone facing the same issue)
final Login login = new Login();
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
Try using Scheduler.scheduleDeferred():
public void onModuleLoad() {
Login login = new Login();
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand () {
public void execute () {
login.textBoxUsername.setFocus(true);
}
});
RootLayoutPanel.get().add(login);
}
Update: answer updated to use Scheduler.get().scheduleDeferred() instead of DeferredCommand, which is deprecated.
Why using DefferedCommand, I think it's better to use someWidget.getElement().focus() which is a native Javascript. I'm using it everywhere, I've not seen any problem.
If your Widget extends Composite, you can:
#Override
protected void onAttach() {
super.onAttach();
textBoxUsername.setFocus(true);
}
It would be so easy for GWT to store a 'wantsFocus' in the internal state, and call focus after the widget is attached. We are still waiting after many years for that feature however...
Still, even after the attach handler is called, setFocus does not always work.
So in the meantime, our GwtUtil library has used the following code. It is a combination of several other solutions, and has been wrapped in a utility function:
static public void setFocus(final FocusWidget focusWidget) {
if (focusWidget.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
} else {
focusWidget.addAttachHandler(new AttachEvent.Handler() {
#Override
public void onAttachOrDetach(AttachEvent event) {
if (event.isAttached()) {
Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
#Override
public void execute() {
focusWidget.setFocus(true);
}
});
}
}
});
}
}
And call it like this:
setFocus(myTextBox);
It makes sense to use a utility function; If and when GWT finally makes setFocus work, you won't have to change your source code in multiple places.

DialogBox in GWT isn't draggable or centred

I'm new to GWT programming. So far I have a DialogBox which is supposed to collect a login and a password, which can if required launch another DialogBox that allows someone to create a new account.
The first of these two DialogBoxes always appears at the top left of the browser screen, and can't be dragged, although part of the definition of a DialogBox is that it can be dragged. However, the second DialogBox can be dragged about the screen without any problem.
What I'd really like is for the first DialogBox to appear in the middle of the screen & be draggable, both of which I thought would happen automatically, but there's not.
So, what things can stop a DialogBox from being draggable? There is nothing on the RootPanel yet. Does that make a difference?
Code fragments available if they help, but perhaps this general outline is enough for some pointers.
Thanks
Neil
Use dialogBox.center() This will center your DialogBox in the middle of the screen. Normally a DialogBox is by default draggable.
Just tried it out and it doens't matter if your RootPanel is empty our not. When I just show the DialogBox on ModuleLoad it is draggable and it is centered. Probably the problem is situated somewhere else.
This is the example of google itself:
public class DialogBoxExample implements EntryPoint, ClickListener {
private static class MyDialog extends DialogBox {
public MyDialog() {
// Set the dialog box's caption.
setText("My First Dialog");
// DialogBox is a SimplePanel, so you have to set its widget property to
// whatever you want its contents to be.
Button ok = new Button("OK");
ok.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
MyDialog.this.hide();
}
});
setWidget(ok);
}
}
public void onModuleLoad() {
Button b = new Button("Click me");
b.addClickListener(this);
RootPanel.get().add(b);
}
public void onClick(Widget sender) {
// Instantiate the dialog box and show it.
new MyDialog().show();
}
}
Here more information about the DialogBox.
Without seeing any of your code it's hard to tell what's going wrong. The following code works for me (ignore the missing styling...):
public void onModuleLoad() {
FlowPanel login = new FlowPanel();
Button create = new Button("create");
login.add(new TextBox());
login.add(new TextBox());
login.add(create);
create.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
final DialogBox box = new DialogBox();
FlowPanel panel = new FlowPanel();
Button close = new Button("close");
close.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
box.hide();
}
});
panel.add(new Label("some content"));
panel.add(close);
box.setWidget(panel);
box.center();
}
});
DialogBox firstBox = new DialogBox(false, true);
firstBox.setWidget(login);
firstBox.center();
}
Both boxes are draggable and shown in the center of your browser window.
Looks like you're overriding this method in Widget:
public void fireEvent(GwtEvent<?> event) {
if (handlerManager != null) {
handlerManager.fireEvent(event);
}
}
In Widget, handlerManager refers to a private HandlerManager.
Either add super.fireEvent(event) to your method or as you have done rename it.
Well, with vast amounts of trial and error I have found the problem, which was just this: I had a method in an object I'd based on DialogBox called fireEvent, which looked like this:
public void fireEvent(GwtEvent<?> event)
{
handlerManager.fireEvent(event);
}
Then, when a button was clicked on the DialogBox, an event would be created and sent off to the handlerManager to be fired properly.
And it turns out that if I change it to this (LoginEvent is a custom-built event):
public void fireEvent(LoginEvent event)
{
handlerManager.fireEvent(event);
}
... or to this ....
public void fireAnEvent(GwtEvent<?> event)
{
handlerManager.fireEvent(event);
}
the DialogBox is draggable. However, if the method begins with the line
public void fireEvent(GwtEvent<?> event)
then the result is a DialogBox which can't be dragged.
I'm a bit unsettled by this, because I can't fathom a reason why my choice of name of a method should affect the draggability of a DialogBox, or why using a base class (GwtEvent) instead of a custom class that extends it should affect the draggability. And I suspect there are dozens of similar pitfalls for a naive novice like me.
(Expecting the DialogBox to centre itself was simply my mistake.)

Drag and Drop in GWT using gwt dnd

I have been really struggling to get Drag and Drop working in GWT. Last 3 days, I was trying to create a basic drag and drop application and failed. Currently I can drag it around, but I am unable to drop to any location.
How can we solve it? Do we need to modify onDragEnd - I am under the impression that unless I specifically have to do something, I dont have to? I am quite confused.
Also, how do I limit the drop to any single area? I do understand that we can do it using DropController. But I have defined the panels using UiBinder, so how do I get that panel back to link in the DropController? i.e. RootPanel.get() gives me the basic root panel and not the actual panel I want. I tried RootPanel.get("field-id"), but that is showing null even if that id is available. What am I doing wrong?
The code I have written is as follows:
public class TestPanel extends Composite implements
DragHandler, HasMouseDownHandlers, HasMouseUpHandlers, HasMouseMoveHandlers, HasMouseOutHandlers {
interface Binder extends UiBinder<Widget, TestPanel> { }
private static final Binder binder = GWT.create(Binder.class);
#UiField AbsolutePanel absolutePanel;
private PickupDragController TestDragController;
private Image img = new Image("./testicon.png");
public TestPanel(){
initWidget(binder.createAndBindUi(this));
absolutePanel.add(img);
TestDragController = new PickupDragController(RootPanel.get(), false);
AbsolutePositionDropController dropController = new AbsolutePositionDropController(
RootPanel.get());
TestDragController.registerDropController(dropController);
TestDragController.addDragHandler(this);
TestDragController.makeDraggable(this, getDragHandle());
}
private Widget getDragHandle() {
return img;
}
#Override
public void onDragEnd(DragEndEvent event) { }
#Override
public void onDragStart(DragStartEvent event) { }
#Override
public void onPreviewDragEnd(DragEndEvent event) throws VetoDragException { }
#Override
public void onPreviewDragStart(DragStartEvent event) throws VetoDragException { }
#Override
public HandlerRegistration addMouseDownHandler(MouseDownHandler handler) {
return addDomHandler(handler, MouseDownEvent.getType());
}
#Override
public HandlerRegistration addMouseUpHandler(MouseUpHandler handler) {
return addDomHandler(handler, MouseUpEvent.getType());
}
#Override
public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler) {
return addDomHandler(handler, MouseMoveEvent.getType());
}
#Override
public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
return addDomHandler(handler, MouseOutEvent.getType());
}
}
and the testpanel uibinder looks like the following:
<g:AbsolutePanel ui:field="absolutePanel" styleName="{style.panel}">
</g:AbsolutePanel>
If somebody can help me out, I will be very much obliged.
K
P.S: To explain more: I was able to solve the first question by updating onDragEnd as the following:
#Override
public void onDragEnd(DragEndEvent event) {
DragContext context = event.getContext();
RootPanel.get().add(context.draggable, context.desiredDraggableX, context.desiredDraggableY);
}
but, I am not sure whether this is the correct solution - since I think I should not be doing the positioning myself.
If you're new to GWT dnd, why don't you try the working demo ?
There is a lot of examples and all the source code is available.
(And no, you're not supposed to do the positionning yourself)
You have to add a DragOverHandler on the drop target(s): even if it does nothing, it defines the component as a drop target.
Of course, you still need to define the DropHandler too on this component (and optionally, DragEnterHandler and DragLeaveHandler for visual feedback, in general).
The DragEndHandler is called even if the target isn't reached (drag abandoned in a non-drop area), it is used to change the state of the dragged object, you might need to set a way for the DropHandler to communicate success on dropping to the DragEndHandler (shared variable, EventBus, etc.).