I am trying to create a button that prints the current browser window.
This is my current code, that uses (or at least it tries to use) JSNI:
private Button print = new Button(constants.print(), new ClickHandler() {
#Override
public void onClick(final ClickEvent event) {
/*-{
if ($wnd.print) {
$wnd.print();
return true;
} else {
return false;
}
}-*/
}
});
But when I click the button, nothing happens. It is my first GWT application, so I am not sure about how to implement it.
new Button(constants.print(), new ClickHandler() {
#Override
public void onClick(final ClickEvent event) {
print();
}
private native boolean print( ) /*-{
if ($wnd.print) {
$wnd.print();
return true;
} else {
return false;
}
}-*/; });
Should work! Always place JSNI within a native method.
Since GWT version 1.5, there's a built-in print function:
import com.google.gwt.user.client.Window
public class PrintHandler implements ClickHandler {
public void onClick (ClickEvent event) {
Window.print()
}
}
Here is my 2 cents:
Create a re-usable class:
public class PrintHandler implements ClickHandler {
public void onClick (ClickEvent event) {
print();
}
private native boolean print ()
/*-{
if ($wnd.print) {
$wnd.print();
return true;
} else {
return false;
}
}-*/;
}
And use it anywhere you like:
new Button( constants.print(), new PrintHandler() )
Related
For a quite simple element
public static class ToolHtml extends Anchor {
private Long toolId;
public ToolHtml(ToolDetails toolDetails) {
this.toolId = toolDetails.getToolId();
this.setText(toolDetails.getName());
Style style = this.getElement().getStyle();
style.setColor("orange");
this.getElement().setId(DOM.createUniqueId());
}
public Long getToolId() {
return this.toolId;
}
}
I am trying to add some event handlers. I am interested in the DragStartEvent but not even the ClickEvent seems to work and I simply can't figure out why:
public void addOfferItem(ToolHtml toolHtml) {
Set<ToolHtml> toolHtmlSet = this.toolIdToToolHtml.get(toolHtml.getToolId());
if (toolHtmlSet == null) {
toolHtmlSet = new HashSet<>();
this.toolIdToToolHtml.put(toolHtml.getToolId(), toolHtmlSet);
}
toolHtml.getElement().setAttribute("contenteditable", "false");
toolHtml.getElement().setAttribute("draggable", "true");
toolHtml.addBitlessDomHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
LOGGER.fine("Click");
LOGGER.fine("Click");
LOGGER.fine("Click");
}
}, ClickEvent.getType());
toolHtml.addDomHandler((DragStartEvent event) -> {
LOGGER.fine("HANDLER DRAG START");
},
DragStartEvent.getType());
toolHtml.addDomHandler((DragStartEvent event) -> {
LOGGER.fine("DOM DRAG START");
},
DragStartEvent.getType());
toolHtml.addBitlessDomHandler((DragStartEvent event) -> {
LOGGER.fine("DRAG START");
},
DragStartEvent.getType());
toolHtmlSet.add(toolHtml);
// Attach/append to DOM
this.getElement().appendChild(toolHtml.getElement());
}
Does anybody know what the issue is here?
You append an element, not a Widget to which your handlers have been attached. You need to add a widget to a widget for all the functionality to work.
NB: Instead of toolHtml.addBitlessDomHandler you need to use
toolHtml.addClickHandler
I have a SuggestionBox in GWT. Is there a way to clear it when it blurs (unless the user made a selection, in which case an action should happen)?
Add a BlurHandler:
suggestionBox.getValueBox().addBlurHandler(new BlurHandler() {
#Override
public void onBlur(BlurEvent event) {
// your code goes here
}
});
Try this one using ValueChangeHandler:
Note: ValueChange event has same behavior as Blue event but it is fired only if value is changed in SuggestBox.
class MyMultiWordSuggestOracle extends MultiWordSuggestOracle {
private Set<String> values = new HashSet<String>();
#Override
public void add(String value) {
super.add(value);
values.add(value);
}
#Override
public void clear(){
super.clear();
values.clear();
}
public boolean contains(String value) {
return values.contains(value);
}
}
You code:
final MyMultiWordSuggestOracle oracle = new MyMultiWordSuggestOracle();
oracle.add("A");
oracle.add("AB");
oracle.add("BCD");
oracle.add("BCDE");
final SuggestBox suggestionBox = new SuggestBox(oracle);
suggestionBox.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
if (!oracle.contains(event.getValue())) {
suggestionBox.setValue("");
}
}
});
So I have a timer and it keeps on firing even though I cleared the Panel and loaded other model... my question is, how to cancel a timer when I unload a model?
So here is part of my code
public Display(List<Clarification> result) {
if (result.size() == 0) {
Window.alert("EMPTY");
} else {
RootPanel.get("Dev1").clear();
t = new Timer() {
public void run() {
cd = new ClarificationDispatcher();
cd.getClarificationsCount(result.size());
}
};
t.scheduleRepeating(5000);
}
I tried to cancel the Timer onUnload() method however, I don't believe it is getting called at all...
Thanks!
Steps to follow
use window.onunload event that is called when page is refreshed
first export cancelTimer() method to java script using JSNI and register cancelTimerFunction as java script function that is called on page unload
cancel timer on window close
Code:
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
private static Timer timer = null;
public void onModuleLoad() {
exportCancelTimer();
final Label label = new Label("Hello ");
timer = new Timer() {
#Override
public void run() {
label.setText("Hello " + Math.random() * 100);
}
};
timer.scheduleRepeating(500);
RootPanel.get().add(label);
Window.addCloseHandler(new CloseHandler<Window>() {
#Override
public void onClose(CloseEvent<Window> event) {
timer.cancel();
}
});
}
public static void cancelTimer() {
if (timer != null) {
System.out.println("cancel");
timer.cancel();
}
}
public static native void exportCancelTimer() /*-{
$wnd.cancelTimerFunction = $entry(#com.x.y.z.GWTProject::cancelTimer());
$wnd.onunload = $wnd.cancelTimerFunction;
}-*/;
So I have implemented a very simple drag and drop file upload widget. Basically my widget is a vertical panel with a couple of labels and a button inside. The user can either drag file into vertical panel or click button and browse for file.
My problem is that when I drag a file into the vertical panel it fires the DragLeaveEvent every time I drag the item over the space that the labels or button occupies. I want it to know that the item is in the vertical panel even when it is on top of the label or button. Im sure I am missing something simple. I provide the drag functionality by adding these dom handlers to the vertical panel:
addDomHandler(new DragEnterHandler() {
#Override
public void onDragEnter(DragEnterEvent event) {
System.out.println("drag enter");
highlight(true);
}
}, DragEnterEvent.getType());
addDomHandler(new DragLeaveHandler() {
#Override
public void onDragLeave(DragLeaveEvent event) {
System.out.println("drag leave");
highlight(false);
}
}, DragLeaveEvent.getType());
addDomHandler(new DragOverHandler() {
#Override
public void onDragOver(DragOverEvent event) {
}
}, DragOverEvent.getType());
addDomHandler(new DropHandler() {
#Override
public void onDrop(DropEvent event) {
System.out.println("drop");
// stop default behaviour
event.preventDefault();
event.stopPropagation();
// starts the fetching, reading and callbacks
if (fileUploadHandler != null) {
handleFiles(event.getDataTransfer(), fileUploadHandler);
}
highlight(false);
}
}, DropEvent.getType());
Check that the event target is a child (or grand child) of your panel, or in this case maybe rather whether the event target is exactly your panel's element:
if (verticalPanel.getElement().isOrHasChild(Node.as(event.getNativeEvent().getEventTarget()))) {
// within the panel (possibly on a child)
}
if (verticalPanel.getElement() == Node.as(event.getNativeEvent().getEventTarget())) {
// targetting exactly the panel (e.g. leaving the panel, not one of its children)
}
Through lots of research I have come to the only solution I could find. I set highlight to true in the dragover handler instead of drag enter.
panel.addDomHandler(new DragEnterHandler() {
#Override
public void onDragEnter(DragEnterEvent event) {
}
}, DragEnterEvent.getType());
panel.addDomHandler(new DragLeaveHandler() {
#Override
public void onDragLeave(DragLeaveEvent event) {
highlight(false);
}
}, DragLeaveEvent.getType());
panel.addDomHandler(new DragOverHandler() {
#Override
public void onDragOver(DragOverEvent event) {
highlight(true);
}
}, DragOverEvent.getType());
panel.addDomHandler(new DropHandler() {
#Override
public void onDrop(DropEvent event) {
// stop default behaviour
event.preventDefault();
event.stopPropagation();
// starts the fetching, reading and callbacks
handleFiles(event.getDataTransfer());
highlight(false);
}
}, DropEvent.getType());
I copy pasted your code, but also added a:
RootPanel.get().addHandler(dropHandler, DropEvent.getType());
My drophandler looks like this:
DropHandler dropHandler = new DropHandler() {
#Override
public void onDrop(DropEvent event) {
handleFiles(event.getDataTransfer(), new FileUploadHandler() {
#Override
public TYPE specifyFileType() {
return TYPE.BINARY;
}
#Override
public void handleFileContent(String fileName, String fileContent) {
// do stuff with filename and content
}
#Override
public boolean checkFileName(String fileName) {
return true;
}
});
event.preventDefault();
event.stopPropagation();
}
};
and the file-upload interface:
public interface FileUploadHandler {
static public enum TYPE {
TEXT, BINARY, DATAURL
};
// check the filename and extension and return true if you are happy with
// proceeding
// returnning false will prevent the file from being read
boolean checkFileName(String fileName);
// tell the method to use to read this file
TYPE specifyFileType();
// do your stuff here, eg upload to a server
void handleFileContent(String fileName, String fileContent);
}
and the handle files func: (note you will have to change classpath to the FileUploadHandler-interface)
// native method to make use of the HTML5 file API functionality
private final native void handleFiles(JavaScriptObject dataTransfer, FileUploadHandler fileUploadHandler) /*-{
var files = dataTransfer.files;
var i;
var file;
var reader = new FileReader();
for (i = 0; i < files.length; i++) {
file = files[i];
if (fileUploadHandler.#<classpath_to>.FileUploadHandler::checkFileName(Ljava/lang/String;)(file.name)) {
var type = fileUploadHandler.#<classpath_to>.FileUploadHandler::specifyFileType()();
reader.onload = function(e) {
fileUploadHandler.#<classpath_to>.FileUploadHandler::handleFileContent(Ljava/lang/String;Ljava/lang/String;)(file.name, e.target.result);
}
if (type == "TEXT") {
reader.readAsText(file);
} else if (type == "BINARY") {
reader.readAsBinaryString(file);
} else if (type == "DATAURL") {
reader.readAsDataURL(file);
// not supported
} else if (type == "ARRAYBUFFER") {
reader.readAsArrayBuffer(file);
} else {
}
}
}
}-*/;
To clarify what double submit is: When the user clicks on a submit button twice, the server will process the same POST data twice. To avoid this (apart from disabling the button after a single submit), most web frameworks like Struts provide a token mechanism. I am searching for the equivalent of this in GWT.
If you want to avoid submitting twice, how about:
boolean processing = false;
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
if (!processing) {
processing = true;
button.setEnabled(false);
// makes an RPC call, does something you only want to do once.
processRequest(new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
// do stuff
processing = false;
button.setEnabled(true);
});
});
}
}
});
That's the gist of it.
This will be helpfull for you -
final Button btn = new Button("Open");
btn.addSelectionListener(new SelectionListener<ButtonEvent>() {
#Override
public void componentSelected(ButtonEvent ce) {
btn.setEnabled(false);
openMethod(name, new AsyncCallback<Void>() {
public void onFailure(Throwable caught) {
btn.setEnabled(true);
}
public void onSuccess(Void result) {
MessageBox.alert(info, "Opened Window", null);
btn.setEnabled(true);
window.hide();
}
});
}
});