Lazily Initialize/Load a GXT Widget When Its Parent Becomes Visible - gwt

I am very new to GXT (and GWT/GWTP for that matter). I want to know if I can lazily load a GXT (4.0) [custom] widget when a modal Dialog that contains its panel is displayed (dialog initially not shown and only appears when a button is clicked).
The reason I want this behavior is that this widget needs to load an applet HTML code which is not available when the page initially instantiates all the other field widgets/panels/dialogs. Therefore, I need to delay obtaining the applet code from another application until the dialog is explicitly appears.
Is this possible?

Lazy loading of images and urls loaded into a GWT Frame (IFrameElement). You can catch the event once say the image/url is loaded using the LoadHandler event.
private void loadLoginPage() {
final Frame frame = new Frame(url_base + url_login); // set the frames url
frame.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
// Get the document from the loaded frame (similar to RootPanel on main page)
Document doc = IFrameElement.as(frame.getElement()).getContentDocument();
// From here you can wrap widgets in the frame like this
final TextBox username = TextBox.wrap(doc.getElementById("username")); // from the html doc using id="username"
// grab a div element
DivElement div = DivElement.as(doc.getElementById("mydiv"));
// Create content to be added to the doc
ButtonElement button_elem = doc.createPushButtonElement();
Button button = Button.wrap(button_elem);
// attach to the document
div.appendChild(button.getElement());
}
});
// Attach to DOM
RootPanel.get("mything").add(frame);
}
And similar for image loading.
Image image = new Image(image_url);
image.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
// image is ready to be used.
}
});
// attach to DOM to initiate loading of the image
Hope this helps...

Related

Frame contents loaded event in GWT

I am creating a DialogBox that contains a Frame widget. I have tried using both the addLoadHander and addAttachHandler hooks to try and capture changes to the frame with no success. Only the initial page load fires either event and after some research it appears that both actually occur when the Widget is attached to the DOM and not when the frames content is loaded.
DialogBox paymentProcessingDialog = new DialogBox(false);
private void submitPayment(String actionURL, String qryString){
Frame processCCWindow = new Frame(actionURL + "?" + qryString);
processCCWindow.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
//This is called when the frame is attached to the dom
//and not when the document is actually ready so it's
//kinda worthless for my scenario
//Note: the addAttachHandler has the same issue
//***call to JSNI idea (see below)
checkURLChange();
}
});
//...irrelevant code to style the DialogBox
VerticalPanel panel = new VerticalPanel();
panel.add(processCCWindow);
paymentProcessingDialog.setWidget(panel);
paymentProcessingDialog.center();
paymentProcessingDialog.show();
}
The URL that is loaded into the frame contains an HTML response from an external server (Paypal - transparent redirect) that immediately re-submits itself back to my server via a form. I am trying to capture the body of the frame once the submission back to my server has completed and the document in the frame has loaded.
I have also tried to use a JSNI method that uses a MutationObserver (got the code from this solution) to try and watch the frame but I believe the JSNI is actually being run inside the parent and not inside the Frame(?) so nothing happens.
I have also tried using a setTimeout to trigger another method in my presenter class but I believe that is running into the same problem as the MutationObserver idea because the console statements never fire.
private static native void checkURLChange()/*-{
new MutationObserver(function(mutations) {
mutations.some(function(mutation) {
if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
console.log(mutation);
console.log('Old src: ', mutation.oldValue);
console.log('New src: ', mutation.target.src);
return true;
}
return false;
});
}).observe(location.href, {
attributes: true,
attributeFilter: ['src'],
attributeOldValue: true,
characterData: false,
characterDataOldValue: false,
childList: false,
subtree: true
});
window.location = "foo";
setTimeout(function() {
#com.myPackage.MyoutPresenter::paymentProcessComplete(Ljava/lang/String;)(document.getElementsByTagName("body")[0].innerText);
console.log("test" + document.getElementsByTagName("body")[0].innerText);
}, 3000);
}-*/;
Does anyone have any thoughts on how I can accomplish this?
I am not familiar with Frame widget, but it appears that you add a handler after you set the URL. Try to build the Frame first (outside of submitPayment, if you use it more than once), and then set the URL:
final Frame processCCWindow = new Frame();
processCCWindow.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
// do something
}
});
private void submitPayment(String actionURL, String qryString){
processCCWindow.setUrl(actionURL + "?" + qryString);
}

Radio button change handler refreshing the page

I'm using UploadItem, RadioGroupItem and some other widgets. RadioButton is having onChangeHandler which will decide what all other components need to be displayed. I've uploaded some file using UploadItem. Then I changed the radio button selection. On changing the radio button, required widgets are getting displayed properly but whatever file I'd selected using UploadItem is going away. Fresh UploadItem widget is getting displayed. In other words page is getting refreshed.
My requirement is whenever I change radio button option, required widget should displayed along with that whatever file I had selected using UploadItem should remain same.
My Code is something like this:
UploadItem upload = new UploadItem();
RadioGroupItem radioGroup = new RadioGroupItem();
HashMap map = new HashMap();
map.put("option1","option1");
map.put("option2","option2");
radioGroup.setValueMap(map);
TextItem textbox = new TextItem();
radioGroup.addChangeHandler(new ChangeHandler(){
public void onChanged(ChangedEvent event) {
String radioValue =((String)event.getValue());
if(radioValue.equalsIgnoreCase("option2")){
textbox.show();
}else{
textbox.hide();
}
}
});
Add all created widgets to DynamicForm object using dynamicForm.setFields(all created widgets)
Changing the radio button should hide and show the textBox. But while doing that page is getting refreshed and whatever file we had selected using UploadItem is lost.
As per the documentation for hide() and show() of FormItem class, invocation of any of these methods, will cause the DynamicForm to be redrawn.
So it may cause the problem you're getting.
To overcome this issue, I would suggest you to put UploadItem in a separate DynamicForm.
fire an event on radio Selection change as
radioButton.addListener(Events.Change, new Listener<BaseEvent>() {
#Override
public void handleEvent(BaseEvent be) {
if(radioButton.getValue()){
//fire an event here for ur widget
}
}
});

GWT: How to dynamically load a new image?

I want to fetch an image from a remote server (not my app's server, but I don't think that matters) and display it in an existing Image widget. The existing widget displays its original content, from a ClientBundle ImageResource , OK.
In UiBinder template:
<g:Image ui:field='myImage' resource='{res.anImage}'/>
In code:
#UiField Image myImage;
...
int width = Window.getClientWidth();
int height = Window.getClientHeight();
String url = ...;
myImage.addErrorHandler(new ErrorHandler() {
public void onError(ErrorEvent event) {
Window.alert("Error getting image data: " + event);
}
});
myImage.addLoadHandler(new LoadHandler() {
public void onLoad(LoadEvent event) {
Window.alert("LoadEvent: " + event);
}
});
myImage.setUrlAndVisibleRect(url, 0, 0, width, height);
As far as I can tell setUrlAndVisibleRect is a no-op. FireBug reports no network activity -- no request to the server specified by the URL. What am I overlooking? In my extended thrashing about trying to get this working I have inferred that it may have something to do with myImage not being "logically attached", but I'm not entirely sure what that means and I've no idea how to correct it if that is the problem.
EDIT with SUMMARY of SOLUTION:
My initial hunch was right. Because I had chosen to implement the image code within a second pseudo-widget (...extends Composite) that shared my UiBinder template with the main pseudo-widget that implements most of my app's UI, I got into trouble. I neglected to add this second pseudo-widget to the RootPanel as is normally done in the class that implements EntryPoint. This left my Image widget unattached to the widget chain, because its parent, the second pseudo-widget, was unattached. And an Image widget must be attached to work. What I ended up doing is moving the Image code back into my main app/GUI class, i.e., into the first and now only pseudo-widget and abandoning the special class for the Image code. I did that because it's simpler and the Image code turns out not to be as long as I had originally thought.
Adding image to the DOM is little tricky,the below code which supports all the browsers(setVisibility trick added to support IE also,as It has a different way to image rendering).
I did'nt use setUrlAndVisibleRect before and AFAIK,Image must render to the DOM inorder to resize it.Just try the below codes.
image.addLoadHandler(new LoadHandler() {
#Override
public void onLoad(LoadEvent event) {
//Do your operations on image .//resize ..etc
image.getElement().getStyle().setVisibility
(Style.Visibility.Visible);
}
});
image.getElement().getStyle().setVisibility(Style.Visibility.HIDDEN);
RootPanel.get().add(image);
image.setUrl(url);
You are using ClientBundle ImageResource which is compile time. You cannot change it unless you replace the new image with exact name in the exact position of prev one. One of the possible hack which is possible is, place the image in a div with its ID set ( getElement().setId("your ID") ). Once you get you new image you use RootPanel.get("Your Id") and do your job.

How can I display an ImageResource during a drag-n-drop using dataTransfer.setDragImage()?

I am trying to drag and drop a cell in GWT and customize the drag image using dataTransfer.setDragImage().
My image is an ImageResource and here is what I have:
Here is how I construct my "draggable cell"
public CheckBoxDragCell(boolean dependsOnSelection, boolean handlesSelection,ImageResource icon) {
this(dependsOnSelection,handlesSelection);
this.icon = AbstractImagePrototype.create(icon);
}
Here is the eventHandler for the drag:
#Override
public void onBrowserEvent(Context context, Element parent, Boolean value,
NativeEvent event, ValueUpdater<Boolean> valueUpdater) {
String type = event.getType();
boolean enterPressed = "keydown".equals(type) && event.getKeyCode() == KeyCodes.KEY_ENTER;
if ("dragstart".equals(type)){
DataTransfer dataTransfer = event.getDataTransfer();
dataTransfer.setData("text", String.valueOf(context.getIndex()));
if (icon != null){
Image image = icon.createImage();
image.setVisible(true);
dataTransfer.setDragImage(ImageElement.as(image.getElement()), 25, 15);
}
But somehow the image never shows up. To debug, I created a dialogbox and displayed the image there when the eventHandler is called and sure enough it show up there... but not when I call the dataTransfer.setDragImage(....) function.
Any help will be enormously appreciated.
The reason the image did not show up in the first case is because the ImageElement is not added to the DOM.
Try adding the ImageElement.as(image.getElement()) to the DOM, then it would show.
In this case it could be an issue of browser support?
I've tried this HTML5 native drag and drop demo: http://html5doctor.com/native-drag-and-drop/
The custom drag image part of it didn't work for me (Chrome 17.0.932.0 dev-m).

How to get the webview's content which was clicked on the webview

I want to add the bookmark function to my app, when I clicked on the webview which display the HTML files (The file's main part is string), I want to capture the first line of the content which display on the screen. Anyone knows the answer?
Thanks very much in advance.
-Shawn
you can identify the some content of the page as It contains img tag or not
Use this API of webView click here
WebView.HitTestResult hr = ((WebView)v).getHitTestResult();
int i=hr.getType() ;
and use the int values of this class for the content
Hope it help
If there is a link into the WebView and you want to do a specific action when the user click on this link you must catch the link click using the following code:
Somewhere in your activity code (commonly in the onCreate method):
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState, R.layout.news_details);
...
mWebView.setWebViewClient(new MyWebViewClient());
...
}
And the WebViewClient class:
class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (DEBUG) {
Log.d(TAG, "shouldOverrideUrlLoading url= " + url);
}
if ( the url is like you want) {
// TODO: add the code to do what you need to do with the url
// the webview should not do anything with this link.
return true;
} else {
// let the webview normally handle the link
return false;
}
}
}
If what you want to do is get the actual displayed content of the WebView, there is no API to do that.
Have a look on those post:
Is it possible to get the HTML code from WebView
Retrieve webview content
Both redirect on this website:
http://lexandera.com/2009/01/extracting-html-from-a-webview/