Using GWTQuery to call Bootstrap JS collapse method - gwt

I want to replicate this jQuery call in gQuery to open all closed Accordion panels at once:
$('.panel-collapse:not(".in")').collapse('show');
I have tested this on my app and it works, however I am unable to successfully implement the same logic using gQuery to call the JavaScript collapse method:
#Override
public void onClick(ClickEvent event) {
GQuery.$(".panel-collapse").not(".in").trigger("collapse", "show");
}
What is the correct way to call JavaScript methods from gQuery?
Further Info - I have successfully tested this gQuery code in my onClick method to add a test class to the affected divs - so I am certain the selector part of the above query works:
GQuery.$(".panel-collapse").not(".in, .MENU").addClass("test");

Why you can't use collapse with GQuery
IIRC collapse() is not a jQuery API method. Maybe you're using Bootstrap JS, or some jQuery plugin that provides this functionality, but it's not one of the jQuery API methods and thus it's not provided by GQuery.
Why trigger wouldn't work either
GQuery, or GwtQuery, is not a wrapper for jQuery, but a full Java implementation of the jQuery API.
What this means is that, when you do something like this:
GQuery.$(".panel-collapse").not(".in").slideToggle();
You're not invoking jQuery's $(), not(), or slideToggle(); you are using a Java library to achieve the same result.
That's the reason why trying something like trigger("slideToggle") won't work: because a) slideToggle() is not an event, but a function; and b) GQuery doesn't make use of jQuery's JS functions.
Solution with GQuery
You can achieve the same "accordion" effect using the slideUp(), slideDown() and slideToggle() functions methods. To open all the collapsed elements, just calling slideDown() on them should work:
GQuery.$(".panel-collapse").not(".in").slideDown();
For full accordion effect, combine those with the toggleClass() and removeClass() methods to mark which elements are open / closed so you know which ones to toggle when clicked.
Solution with native collapse()
Now, if you don't mind the advice... GQuery is great, but the animations are far from being as smooth as in native jQuery. I guess the same happens with Bootstrap.
If you can (and I can't see a reason why you couldn't), just use JSNI to make a native call to collapse() like this:
private native void collapseAll() /*-{
$wnd.$('.panel-collapse:not(".in")').collapse('show');
}-*/;
This requires that you load jQuery (or Bootstrap) in your page, but since you said that invoking collapse() in plain JS worked, I guess that's your case.

Related

gwt datagrid Bootstrap Select cell (need to execute javascript after cell has been added/rendered)

I inherited a project that uses GWT to create a web application. It uses a GWT wrapper for Bootstrap3 to do the styling of elements. This is working nicely for the most part. Now I hit a road block trying to add a Bootstrap3 Select to a GWT DataGrid table that currently uses a GWT SelectionCell. The problem is that a SelectionCell is not 'Bootstrap styled' and therefore doesn't match the style of the rest of web application.
Unfortunately, I cannot simply add the Select to a GWT DataGrid as the Select does not implement the GWT Cell interface nor does it extend a class that can be added to a Column that is then added to the DataGrid. Sub classing Select and implementing Cell fixes this problem. However, I cannot get the Select to render properly as it requires a JavaScript function to be executed after the Select has been attached to the DOM which it never is being wrapped by a Column in a DataGrid.
Instead, it is rendered into a SafeHtmlBuilder by the render function of Cell.
// GWTBootstrap3::Select function to render the Select
public void render() {
if (isAttached())
command(getElement(), SelectCommand.RENDER);
}
protected native void command(Element e, String command) /*-{
$wnd.jQuery(e).selectpicker(command);
}-*/;
Since the Select is never attached to the DOM I need to call the selectpicker function manually. For his, I created my own native function which I need to call after the SafeHtmlBuilder has been added to the DataGrid. If my Select subclass accepts CLICK events through Cell's onBrowserEvent and calling the native function after clicking into the cell renders the Select properly.
What I cannot figure out is when to call the selectpicker function programatically to render the Select automatically after a row has been added by an RPC call. I tried to register different handlers to no avail. The handlers are called and my native function wrapping the selectpicker function is called as well but it seems like the HTML select has not yet been added to the table. Calling the above JavaScript snipped from the JavaScript console of a browser also works. So it should work find but I need to find the right place to call :(
Handlers in DataGrid that I am using:
addLoadingStateChangeHandler
addRowCountChangeHandler
I also tried to call it at different places after the calls to add to DataGrid the data have been made. Again, the HTML select doesn't seem to have been added to the table. ie. when I call the JavaScript snipped right after a call to myListDataProviderObject.getList()addAll(my data).
Most likely you need to add a Scheduler call before calling your native method to make sure that the browser finished rendering the UI (e.g. your DataGrid) before this call is executed.

gwt Event Handler not working any way

I have a get with this weird thing in GWT
when i set my uibinder to the getBody().addpend() the event is not firing but it works when i use RootPanel.get().add(new p1()); works. Looks like its something to do with the way you add the uibinder to the page?
working event:: RootPanel.get().add(new p1());
not working:
Document.get().getBody().appendChild(new p1().getElement());`
the event handler looks:
not working event:: Document.get().getBody().appendChild(new p1().getElement());
not working event:: Document.get().getBody().appendChild(new p1().getElement());
#UiHandler ("bleh")
void handleClick(ClickEvent e)
if (lEntidad.getText().length()>1)
lEntidad.setText("");
I can't see all of your code to confirm this, but if you are adding widgets to your app using getElement(), then any events you add through gwt won't trickle through. There's special event logic GWT handle behind the scenes to make things work in a memory-leak safe environment.
Instead of using Document.appendChild(), you should be using whatever your parent widget is, or whatever the root of your ui.xml file is. For example, an HTLMPanel. Add your new widget directly to that, then your events on the widget should pass through.
Summary
Don't add elements if you have an event on the element. Add widgets instead. That solved the issue when I had it happen.

gwt Composite open/visible handler

I have got several Composite and I would like to add an Handler to one of them which fire an event if the user open this composite. Is there any Handler for?
Thank you
A good/easy way to fire events is by the use of the GQuery library, which emulates JQuery in GWT code.
It allows you to do things like:
$(yourWidget).blur();
to fire a blur event on yourWidget, for example... if you don't mind adding a dependency to GQuery to your project, this is the way to go in my opinion.
You can even provide a Function which will be called after the event has fired, as in:
$(yourWidget).click(new Function() {
public boolean f(Event e) {
e.preventDefault();
return false;
}
}
I am not sure how you would do that in pure GWT, but it's obviously possible... you may want to see how GQuery does that.
http://code.google.com/p/gwtquery/

Passing a GWT Widget to a js function

I want to pass a complex widget with many click handlers to a js function, via jsni, so that it is included in a div element of my js code (in fact it's for the infoWindow content of the maps v3 api).
If I pass the element I loose all my handlers, for some reason. The result is that nothing is triggered when I click on buttons or links.
I thought I could sort it out by first passing a flowpanel and its node and then adding the widget to the flowpanel itslef. But it works sometimes and some times not, in particular not with the infoWindow. The widget appears fine but all handlers won't work.
Please send me any suggestions or ideas you might have!
OK I got the trick from... stackoverflow, suprise ;-)
Here's the post:
http://www.google.com/url?sa=D&q=https://stackoverflow.com/questions/6183181/how-to-add-a-custom-widget-to-an-element
So in the end I did the following
in my jsni function:
var newDiv = $doc.createElement('div');
the function returns the div as an Element which I in turn wrap in an HTMLPanel using HTMLPanel.wrap and then I add the widget!

google wave: how did they make divs clickable

As we are facing GWT performance issues in a mobile app I peeked into Google Wave code since it is developed with GWT.
I thought that all the buttons there are widgets but if you look into generated HTML with firebug you see no onclick attribute set on clickable divs. I wonder how they achieve it having an element that issues click or mousedown events and seemingly neither being a widget nor injected with onclick attribute.
Being able to create such components would surely take me one step further to optimizing performance.
Thanks.
ps: wasnt google going to open source client code too. Have not been able to find it.
You don't have to put an onclick attribute on the HTML to make it have an onclick handler. This is a very simple example:
<div id="mydiv">Regular old div</div>
Then in script:
document.getElementById('mydiv').onclick = function() {
alert('hello!');
}
They wouldn't set the onclick property directly, it would have been set in the GWT code or via another Javascript library.
The GWT documentation shows how to create handlers within a GWT Java app:
public void anonClickHandlerExample() {
Button b = new Button("Click Me");
b.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// handle the click event
}
});
}
This will generate an HTML element and bind a click handler to it. However, in practice this has the same result as using document.getElementById('element').onclick() on an existing element in your page.
You can hook functions to the onclick event using JavaScript. Here's an example using jQuery:
$(document).ready(function(){
$("#div-id").click(function(){
/* Do something */
});
});
If you're interested in optimizing performance around this, you may need to investigate event delegation, depending on your situation.
A click event is generated for every DOM element within the Body. The event travels from the Body down to the element clicked (unless you are using Internet Explorer), hits the element clicked, and then bubbles back up. The event can be captured either through DOM element attributes, event handlers in the javascript, or attributes at any of the parent levels (the bubbling or capturing event triggers this).
I'd imagine they've just set it in a .js file.
Easily done with say jQuery with $(document).ready() for example.