Find an element by CSS selector in GWT
Asked Answered
E

5

15

I'm trying to grab an arbitrary element using a CSS selector (eg. "#someId .className a") in GWT.

I'm building a JS widget that can live on a 3rd party website and want to be able to interact with elements on the page. Searching through the JavaDocs I don't see anything that can find an element by selector. I did come across GQuery, but it seems like the project might be dead and I'm not sure if it works with GWT 2.

One option I've considered is wrapping an existing library (jQuery, Mootools, Prototype, etc) into a GWT class and exposing the desired behavior through JSNI. It seems this might be very builky.

Anyone have experience using generic CSS selectors in GWT?

Eloign answered 9/3, 2010 at 1:10 Comment(2)
GWTQuery/GQuery seems to have been revived and the inactivity would most likely correspond to the release of GWT 2.1.Recognize
It is really frusting to not have the native querySelector[All] in GWT. I wonder if this project is doomed being run by people who hate client-side development.Erminois
M
8

There's the DOM class, that provides many wrapper methods for accessing the DOM tree. There's no function that takes a CSS selector jQuery style that I'm aware of - GWT just encourages/enforces accessing DOM elements through Widgets (and such), not directly - though I understand that in your case such "low-level" approach might be needed. The only way I see pulling that off through pure Java GWT methods is via lots and lots of (probably horrible) chaining/invocations of the DOM class. It'd be easier if all you had to do was access some id - for that there's RootPanel.get(id) (and DOM.getElementById(id), they differ in what type of objects they return).

However, like you already suggested, JSNI might offer a better solution - try returning, for example, $wnd.$("#someId .className a") from JSNI as an Element - actually, you can return anything as anything from JSNI, GWT will just crap up the second you try to use, say an int as a DOM element or something.

PS: while the GQuery project does seem dead/inactive, it might be worth checking how they wrapped the jQuery calls (such as $) so that they could be used seemingly in GWT.

Mercurialize answered 9/3, 2010 at 1:40 Comment(3)
Trying this, I get: "Uncaught TypeError: Object [object DOMWindow] has no method '$'" do I need jQuery.js on the page also or something?Flinn
Yes, you need to include jQuery .js file in your host page. Also, have a look at this question, but the $ should work fine from JSNI.Mercurialize
I am guessing document.querySelector(...) was not an option?Tersanctus
B
6

Use GwtQuery, is updated to GWT 2.4: http://code.google.com/p/gwtquery/

Selector examples :

//select an element having id equals to 'container'
GQuery myElement = $("#container");
//select all elements having 'article' as css class
GQuery allArticles = $(".article");
/select all cells of tables
GQuery allCells = $("table > tr > td");
//find the ul elements being inside a element with class 'article' itself inside a element with id 'container'
GQuery articleUls = $("#container .article ul");

http://code.google.com/p/gwtquery/wiki/GettingStarted

Burney answered 28/7, 2012 at 5:50 Comment(0)
K
3

You could use querySelector() and querySelectorAll(), available for newer browsers...

http://www.javascriptkit.com/dhtmltutors/css_selectors_api.shtml

...in terms of browser support, querySelector() and querySelectorAll() is supported in Firefox 3.1+, IE8+ (only in IE8 standards mode), and Safari 3.1+

Kowalski answered 2/7, 2010 at 10:31 Comment(6)
querySelector and querySelectorAll are not available in GWT. There is a selector rewrite of jQuery available called 'GwtQuery' or 'gQuery'.Erminois
GWT can call any Javascript method you want it to, you just have to write a little wrapper method to act as a pass-through for arguments. Please see the docs for native method access in the GWT documentation. This very method was used to access querySelector/querySelectorAll from GWT in my job.Kowalski
I wrote myself one-line GWT JSNI wrappers for doc/element querySelector and querySelectorAll and am now using them a lot with excellent results. Easy, reliable and fast.Flinn
Of course you and "add" a property accessor to GWT via JNSI, but that violates the idea of GWT. You want to be able to have GWT build a permutation to work with IE6,7,8, Safari, Gecko 1_8 and older. Poor answer. The question asks how to do this with a GWT function.Foulmouthed
Depends on needs. Targeting iOS and Android only browsers by developing your app with PhoneGap? Only need to support WebKit, so use querySelectorAll() . Targeting a single browser for an internal company app like my old workplace? Force all your salespeople to run your app on Chrome and use querySelectorAll, they won't notice the difference between a web browser window and a desktop app window. Easy with the attitude please.Kowalski
Excellent solution.Stertorous
B
3

Inspire by Asfand Yar Qazi answer.

With JSNI you can just define this method and enjoy it when you web app is running in modern browsers.

public final native NodeList<Element> querySelectorAll(String selectors) /*-{
 return $doc.querySelectorAll(selectors);
 }-*/;
Burney answered 19/6, 2015 at 21:25 Comment(4)
Does this really work? Have you tested this? I'd be quite surprised if there is some implicit conversion to NodeList<Element> from a native js return.Barbiturism
I don't see where your documented source supports this syntax. Please provide a quote. The closest I can find on that link is within the section "Passing JavaScript values into Java code". For the return type: "any other Java Object (including arrays) ", It states what must be passed is "Java Object of the correct type that must have originated in Java code; Java objects cannot be constructed from “thin air” in JavaScript". I believe that is in direct opposition to the idea you can implicitly convert return type of a NodeList<Element>.Barbiturism
Work perfect for me!Jocundity
Wow! Well, I'm surprised, but excited! That could be very useful. Nice solution then! I'll have to try that myself...Barbiturism
B
1

Here's an example using the GWT Element and Node classes to find a single nested element with a given class name. This is not as open ended and powerful as a literal CSS selector, but can be modified as needed for your specific use case:

static public Element findFirstChildElementByClassName( Widget w, String className ){
    return findFirstChildElementByClassName( w.getElement(), className );
}
static private Element findFirstChildElementByClassName( Element e, String className ){     
    for( int i=0; i != e.getChildCount(); ++i ){
        Node childNode = e.getChild(i);
        if( childNode.getNodeType() == Node.ELEMENT_NODE ){
            Element childElement = (Element)childNode;
            if( childElement.getClassName().equalsIgnoreCase( className ) )
                return childElement;
            else if( childElement.hasChildNodes() ){
                Element grandChildElement = 
                    findFirstChildElementByClassName( 
                            childElement, className );
                if( grandChildElement != null ) return grandChildElement;
            }
        }
    }
    return null;
}
Barbiturism answered 5/5, 2016 at 18:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.