I am developing GWT application and I use
com.google.gwt.user.client.Window.open(pageUrl, "_blank", "");
to open new page. And it opens in a new tab when called, for example, directly after button click.
But I decided to do some validations on server before opening new page and placed the call to the mentioned above method to the
public void onSuccess(Object response) {
}
And it starts to open pages in new window instead of new tab (this is true only for Chrome, other browsers still open it in a new tab).
Can anybody help me?
I built a small example to illustrate the issue:
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Window.open("http://www.google.com/", "_blank", "");
MySampleApplicationServiceAsync serviceAsync = GWT.create(MySampleApplicationService.class);
serviceAsync.getMessage("Hello, Server!", new AsyncCallback() {
public void onFailure(Throwable caught) {
Window.alert("ERROR");
}
public void onSuccess(Object result) {
Window.open("http://www.bing.com/", "_blank", "");
}
}
);
}
});
Firefox(3.6.8) opens both pages in new tabs.
Chrome(6.0) opens "google.com" in new tab and "bing.com" in new window
Opera(10.10) opens in new tabs.
IE(8.0) opens both in new Windows.
I marked igorbel 's answer as the only correct cos I haven't found any proper way to specify the same behaviour in all situations.
I used this code and it works for me in google chrome and mozilla firefox 3.6.8 browsers
If you want to open a page in new window you should write code as
Window.open("www.google.com","_blank","enabled");
If you want to open a page in new tab you should write code as
Window.open("www.google.com","_blank","");
I am not sure you are going to be able to control this the way you want. The problem is that browsers can decide when to open windows and when to open tabs. For example, firefox has the option: "Open new windows in new tabs instead". And don't forget the browsers that don't support tabs (yes, those do still exist).
Since this is such a problematic aspect of the user experience, my recommendation would be to reconsider your design. Is it really that important for you application to differentiate between opening a new tab and opening a new window?
This code works for me:
Before calling the Async method keep a reference to a new window with empty parameters.
At onSuccess() method set the URL of the window.
Button someButton = new Button("test");
SelectionListener<ButtonEvent> listener = new SelectionListener<ButtonEvent>()
{
public void componentSelected(ButtonEvent ce)
{
final JavaScriptObject window = newWindow("", "", "");
someService.doSomething(new AsyncCallback()
{
public void onSuccess(Object o)
{
setWindowTarget(window, "http://www.google.com/");
}
});
}
}
someButton.addSelectionListener(listener);
private static native JavaScriptObject newWindow(String url, String name, String features)/*-{
var window = $wnd.open(url, name, features);
return window;
}-*/;
private static native void setWindowTarget(JavaScriptObject window, String target)/*-{
window.location = target;
}-*/;
Found at:
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/574b3b828271ba17
Interesting thing,
chrome will open page in new tab in case if you put window.open(...) instruction into the body of the click handler implementation.
For example:
Button someButton = new Button("test",
new ClickHandler() {
public void onClick(ClickEvent event) {
Window.open(...);
}
});
And a page will be opened in the separate window in case if I will include any Async. request into the mentioned code:
Button someButton = new Button("test",
new ClickHandler() {
public void onClick(ClickEvent event) {
someService.doSomething(new AsyncCallback() {
void onSuccess(Object o) {
Window.open(...);
}
...
});
}
});
The way Chrome looks at it, calling Window.open() is like trying to open a pop-up window in the user's face. That's frowned upon and will trigger the built-in pop-up blocker. Following a link, according to Chrome, should be the result of a user clicking on a good old anchor tag with an href attribute. But here lies the answer you're looking for: you can show a link to the user and change the link target on the fly. That would qualify as a 'proper' link in Chrome's world.
This code works for me:
public static native String getURL(String url)/*-{
return $wnd.open(url,
'target=_blank')
}-*/;
Related
I am trying to set up the SuperDevMode on a Vaadin project.
I have basically 3 problems related to this feature.
I have the following widget (created using the "New Vaadin Widget" wizard, below the code for the client-side widget, connector, state and server-side component):
// Widget:
public class CountedTextFieldWidget extends Composite {
private TextBox textBox = new TextBox();
private Label countLabel = new Label("0");
private HorizontalPanel panel = new HorizontalPanel();
public static final String CLASSNAME = "countedtextfield";
public CountedTextFieldWidget() {
initWidget(panel);
setStylePrimaryName(CLASSNAME);
textBox.setStylePrimaryName(CLASSNAME + "-field");
countLabel.setStylePrimaryName(CLASSNAME + "-label");
setStylePrimaryName(CLASSNAME);
panel.add(textBox);
panel.add(countLabel);
}
public String getText() {
return textBox.getText();
}
public void setText(String text) {
textBox.setText(text);
}
public void setCount(int count) {
countLabel.setText("" + count);
}
public int getCount() {
return Integer.parseInt(countLabel.getText());
}
// HandlerRegistration can be used to remove the key up handler (listener)
// added with this method
public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
return textBox.addKeyUpHandler(handler);
}
}
/********************************************************/
// Connector:
#Connect(CountedTextField.class)
public class CountedTextFieldConnector extends AbstractComponentConnector {
public CountedTextFieldConnector() {
getWidget().addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent event) {
String text = getWidget().getText();
getWidget().setCount(text.length());
}
});
}
#Override
protected Widget createWidget() {
return GWT.create(CountedTextFieldWidget.class);
}
#Override
public CountedTextFieldWidget getWidget() {
return (CountedTextFieldWidget) super.getWidget();
}
#Override
public CountedTextFieldState getState() {
return (CountedTextFieldState) super.getState();
}
#Override
public void onStateChanged(StateChangeEvent stateChangeEvent) {
super.onStateChanged(stateChangeEvent);
final String text = getState().text;
getWidget().setText(text);
getWidget().setCount(text.length());
}
}
/********************************************************/
// State
public class CountedTextFieldState extends com.vaadin.shared.ui.textfield.AbstractTextFieldState {
{
primaryStyleName = null;
}
}
/********************************************************/
// Server-side component:
public class CountedTextField extends com.vaadin.ui.TextField {
#Override
public String getValue() {
return getState().text;
}
public void setValue(String value) {
getState().text = value;
}
#Override
public CountedTextFieldState getState() {
return (CountedTextFieldState) super.getState();
}
}
This widget is rendered as following:
Now, I have followed the following guide on the Vaadin's wiki:
https://vaadin.com/wiki/-/wiki/Main/Using%20SuperDevMode
The CodeServer starts as expected:
The code server is ready.
Next, visit: http://localhost:9876/
But when I open the project and append ?superdevmode to the URL, get the Recompilation failed... message and there's are some errors in the browser's console:
So my first problem is related to this issue:
1) Why does recompilation fail sometimes? And what are those SEVERE: JSONP compile call failed and SEVERE: Timeout Excecution?
Then if I ... click to retry sometimes the superdevmode starts, but the custom widget is not rendered as in the previous screenshot I posted.
Instead, I get a standard Vaadin's v-textfield...
2) WTF... Why? Where is my custom component?
I noticed that I get the same issue also if I open localhost:9876, drag the Dev Mode On button to the bookmarks toolbar and then click on it while on localhost:8080/project. My custom widget is disappears and instead I get the Vaadin's v-textfield widget...
And about the Enable Source Map feature. On the wiki, they say:
To be able to debug Java code in Chrome, open the Chrome Inspector
(right click -> Inspect Element), click the settings icon in the lower
corner of the window and check "Scripts -> Enable source maps".
Refresh the page with the inspector open and you will see Java code
instead of JavaScript code in the scripts tab.
In my Chrome, I don't have a settings icon on the lower corner of the window, I clicked the gear icon on the right and went to General -> Sources and checked Enable JavaScript Source Map (There's no generic Enable source maps entry on my settings tab).
I can see the Java sources, but they are all sources for GWT and Vaadin's components:
So my third issue and related question:
3) How can I see my custom widget code also?
Thanks for the attention! Hope I was clear.
I also had a similar problem trying to use SuperDev Mode with Vaadin. I'm not quite sure why recompilation fails on occasion, but I suspect it envolves the same issue I had trying to send my Java source maps. The problem I had seemed to be a caching issue due to the fact that the code server creates a persistent cache directory in my /tmp folder. So I deleted every folder it created (they usually have "gwt" in the name somewhere) and relaunched the code server. I suggest also adding the -src <complete-path-to-project> argument in the code server configurations to specify the directory containing GWT source to be prepended to the classpath for compiling and possibly changing the log level to TRACE or DEBUG. Heres an example those arguments:
com.example.AppWidgetSet -src /home/workspace/widgetset/src/main/java
-logLevel TRACE
I should mention that the log levels are quite verbose, but can be quite useful. The log should also show the location of the cache folder.
I am new to vaadin. I have one Link like
Link link = new Link("", new ExternalResource(redirectURL));
my requirement is, I have to set value when user clicks the link. Can I add listener when user click the link. Or is there alternate ways of setting value if link is clicked.
To capture onClick on a link or a label, I always create a HorizontalLayout and put the component inside it:
HorizontalLayout hor = new HorizontalLayout();
final Link link = new Link("Click on Me!", new ExternalResource("http://www.google.com"));
hor.addComponent(link);
hor.addLayoutClickListener(new LayoutClickListener() {
#Override
public void layoutClick(LayoutClickEvent event) {
// capture the click here and do whatever you'd like to do, e.g.
// if ( event.getClickedComponent() != null ) {
// if(event.getClickedComponent().equals(link)) {}
}
});
I interpreted your question as changing the caption of the link. As far as I know it's not possibly with the Link component. Take a look at the activelink addon: http://vaadin.com/addon/activelink.
This addon behaves like Link and lets you add a LinkActivatedListener to it. The code should look like this:
final ActiveLink link = new ActiveLink("", new ExternalResource(redirectURL));
link.addListener(new LinkActivatedListener() {
#Override
public void linkActivated(LinkActivatedEvent event) {
link.setCaption("newCaption");
}
});
You could use the new BrowserWindowOpener class:
From the API:
Component extension that opens a browser popup window when the
extended component is clicked.
Example:
BrowserWindowOpener browserWindowOpener = new BrowserWindowOpener(new ExternalResource("http://google.com"));
/*
* Apparently, the BrowserWindowOpener method setWindowName uses the HTML5 target
* attribute (no longer deprecated as it was in HTML4).
* So you can use either a frame name, or one of four special attribute values:
* _blank, _self, _parent, _top
*
* browserWindowOpener.setWindowName();
*/
final Button btn = new Button("Click me");
browserWindowOpener.extend(btn);
btn.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
btn.setCaption("clicked");
}
});
More information here.
I dint work on Vaadin yet But I looked into the document. I found that the Link class internally extends AbstractComponent class which has many functions which you can override. like it has addListener function where you need to pass the Component listener as a parameter and can detect the click event and do whatever you want to.
For reference check this
and this too
Hope this will help :)
I'm wondering if what should be done for GWT com.google.gwt.user.client.ui.FileUpload
to upload to server without refresh or forwarding.
I have implemented the Form upload from this Java Doc, however it forwards the browser page to the target server URL.
How can I implement a form upload without forwarding?
Update:
final FormPanel form = new FormPanel();
form.setAction("/upload");
form.setEncoding(FormPanel.ENCODING_MULTIPART);
form.setMethod(FormPanel.METHOD_POST);
VerticalPanel panel = new VerticalPanel();
form.setWidget(panel);
final TextBox tb = new TextBox();
tb.setName("textBoxFormElement");
panel.add(tb);
// Create a FileUpload widget.
FileUpload upload = new FileUpload();
upload.setName("uploadFormElement");
panel.add(upload);
DOM.getElementById("form_panel").appendChild(panel.getElement());
Button submit = new Button("Submit");
panel.add(submit);
DOM.sinkEvents(submit.getElement(), Event.ONCLICK);
DOM.setEventListener(submit.getElement(), new EventListener(){
#Override
public void onBrowserEvent(Event event) {
if (event.getTypeInt() == Event.ONCLICK) {
form.submit();
return;
}
}});
form.addSubmitHandler(new FormPanel.SubmitHandler() {
public void onSubmit(SubmitEvent event) {
if (tb.getText().length() == 0) {
Window.alert("The text box must not be empty");
event.cancel();
}
}
});
form.addSubmitCompleteHandler(new FormPanel.SubmitCompleteHandler() {
public void onSubmitComplete(SubmitCompleteEvent event) {
Window.alert(event.getResults());
}
});
IMO you are making things more complex than they are.
I don't understand why, if you are using widgets, you are trying to manage the DOM by hand.
1.- Attach your form panel to the root panel using GWT way, otherwise you are going to break widget hierarchy.
RootPanel.get("form_panel").add(panel);
2.- Try not to use sink-events by hand, and use methods already present in widgets:
submit.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
form.submit();
}
});
FormPanel sets its target to a hidden <iframe> so you will never be redirected to another page.
BTW, I'd rather use gwtupload library which simplifies so much uploading code in GWT, and adds a lot of additional features.
I used before gwt-upload library.
You dont need to rediscover America.
Thanks for moxie group
gwt-upload-project page
The content of the tab is formed and displayed when the application is loaded. Later the content of the tab may be changed by other actions. I want to show the newer content after each action. And each time when I click the tab sheet, the content should be refresh/updated. But I failed.
//the content of the tab from the "reprintsTab" class
//in the "reprintsTab" it query data from database and print out
//later I update the data in the database from somewhere else, and I want the tab shows the new content
//I want to click the tab sheet to reload the "reprintTab" class and print out the new content
//here is what I did:
public TabSheet sheet;
//add tab and add the content from "reprintTab" into this tab
sheet.addTab(new reprintsTab());
//add the listener
sheet.addListener(new TabSheet.SelectedTabChangeListener() {
#Override
public void selectedTabChange(SelectedTabChangeEvent event) {
//I know it does not work, because it only reload the class. but not put the content under the tab I want
new reprintsTab();
}
});
What should I do? please help me, thanks.
You can use TabSheet.replaceComponent method to do this:
//Field to store current component
private reprintsTab currentComponent;
//during initialization
currentComponent = new reprintsTab();
sheet.addTab(currentComponent);
sheet.addListener(new TabSheet.SelectedTabChangeListener() {
#Override
public void selectedTabChange(SelectedTabChangeEvent event) {
reprintsTab newComponent = new reprintsTab();
sheet.replaceComponent(currentComponent, newComponent);
currentComponent = newComponent;
}
});
Also, you might want to reload this tab only when it's shown:
sheet.addListener(new TabSheet.SelectedTabChangeListener() {
#Override
public void selectedTabChange(SelectedTabChangeEvent event) {
if (event.getTabSheet().getSelectedTab() == currentComponent) {
//here goes the code
}
}
});
This should work for you, but I would suggest a cleaner approach: implement reprintsTab as a container for components, create method reload or buildInterface method to refresh its' state, so you can just call:
currentComponent.reload();
when you need to update interface.
Also, I hope reprintsTab is just an example name, java class names starting with lowercase letter look ugly.
I am trying to use UISpec4J in order to automate a Java Swing application. After adapter setup:
setAdapter(new MainClassAdapter(Main.class, new String[0]));
I am trying to obtain the main window:
Window mainWindow = getMainWindow();
Instead of a login dialog, I am getting a splash screen with logo of application. All my attempts to call this dialog manually have failed.
How can I get the list of opened dialogs/windows?
It looks like MainClassAdapter is not designed to handle a sequence of windows. However you can implement your own adapter that ignores the splash screen and returns the subsequent window. Here is a sample taken from UISpec4J forums:
setAdapter(new UISpecAdapter() {
public Window getMainWindow() {
final Window[] result = new Window[1];
WindowInterceptor.init(new MainClassTrigger(Main.class, new String[0]))
.processTransientWindow()
.process(new WindowHandler() {
public Trigger process(Window window) throws Exception {
result[0] = window;
return Trigger.DO_NOTHING;
}
})
.run();
return result[0];
}
});