GwtQuery: A jQuery clone for GWT, and much more ... Manuel Carrasco Moñino manolo@apache.org @dodotis
About me ● Apache James ● HUPA ● GWT ● Gquery & Gquery-plugins ● GwtExporter ● GwtUpload ● Chronoscope ● Jenkins ● Performance plugin ● Emma plugin ● Linux ● LXP a light and visual window manager based on icewm
Contents ● What is GWT ● What is Gquery ● Learning Gquery – GQuery, $(), Function – Collections & grabbing Values – Selectors – Traversing the DOM – Method Chaining – CSS – Events – Effects – Ajax – Data binding – Plugins ● Js Size ● jsQuery
What is GWT Java to Javascript Compiler, Linker, Optimizer and Obfuscator One compiled 'js' per browser (like c++ one 'exec' per processor) Is a full SDK. Not a Js Framework Not a Js Library Not a new language Not a Web Framework
Advantages of using Java. ● A high level language allows that the developer doesn't get lost with low level details: DOM, Ajax, Cross-domain, Compression, Obfuscation, Dependencies, Browser differences, etc. ● Huge Java ecosystem: IDE, Re-factoring, Debug, Code assist, Maven. ● Metrics, TDD, CI, Reusing (libraries) ● Patterns, Builders … ● Type safe, syntax checking, reduce errors. ● Separate code maintenance from the effectiveness of the executable. ● Normally, the compiler would produce better js code than the code we could write by hand (less code, compressed, obfuscated, remove dead code, etc).
What does the Gwt SDK provide ● Generators, Compiler, Linker, Optimizer, Obfuscater. ● Client side libraries: DOM, XML, JSON, RPC, RF, I18n, MVP, Widgets ● Server libraries: RPC, RF ● Eclipse plugin ● Multi-browser Dev mode ● Unit testing and Debug tools. ● Performance tools (speed tracer) ● Compiler Statistics ● Everything is open sourced (Apache v2.0)
GWT Eclipse Java Code (IDE) Plugin Java Server Java Client Side Side Toolkit (SDK) GWT development GWT Compiler Debug/Hosted/Test JRE Emulation Browser libs GWT server Widgets libs RPC/RF Test Runner FF/IE/Ch-Plugin 3ª Party 3ª Party Server libs Client libs JavaScript. GQuery J-Byte Code Bundles (css, sprite). JSON/XML/HTML/TXT JSON/XML/HTML/TXT RPC/RF Browser Any Backend JVM App-Server (php, ruby, ...)
What is GQuery ● A library for GWT ● Provides jQuery API and syntax (small differences) ● Entirely re-written in java, not a wrapper, optimized for Gwt. ● Has many features not available in jQuery. – Data binding generators – Type-safe structures – Compile selectors ● It is a useful complement for Gwt. – CSS selectors – Widget finders – Light weight collections – DOM and Widget enhancers. ● Can be used as an alternative to traditional Gwt developing (progressive enhancement) ● Performance in mind, Unit tested. ● Extensible via Plugins
Easy to getting started ● Use the gquery maven Archetype. mvn archetype:generate -DarchetypeGroupId=com.googlecode.gwtquery -DarchetypeArtifactId=gquery-archetype -DarchetypeVersion=1.1.2 -DgroupId=fr.rivieradev -DartifactId=hello -DprojectName=HelloWorld ● Maven Ready (see README.txt). mvn clean package mvn gwt:run
IDE Friendly ● Eclipse, IntelliJ, Netbeans ● Run, Debug, Test ● Code Assist ● Re-Factoring ● Software Metrics
The GQuery Object ● Like in jQuery ... ● Selectors return an object ... ● Which represents a collection of Elements ... ● And each has plenty of useful methods. ● Most methods return the object itself so you can chain them. ● Other methods return a value of the first element GQuery g = $("img.photo"); g.attr("src", "/default.png"); String color = g.css("color"); int size = $("img.photo").css("border", "none").size();
The Dollar '$()' Method ● As in Javascript, the symbol '$' is legal for methods and classes. ● But The Gwt Compiler disallows it for class names, So we use GQuery. // Import GQuery utility methods statically // it should be ...client.$.* but the compiler complains import static com.google.gwt.query.client.GQuery.*; // The '$' method always returns a GQuery object GQuery g; // Use '$' to create new DOM elements g = $("<div>hello</div>"); // Use '$' to select DOM elements g = $("div:hidden"); // Use '$' to wrap existing elements g = $(document); // Use '$' to wrap Gwt widgets Button button = new Button(); g = $(button); // '$' can handle other arguments: // Function, Event, Element[], NodeList ...
Functions ● java hasn't got closures. ● We use 'Function' inner class to emulate javascript function ● Override the appropriate 'f()' to write your code
Collections and Grabbing Values GQuery Java. jQuery JavaScript. // Returns a GQuery object // Returns a jQuery object GQuery g = $("div.section"); var g = $('div.section'); // Returns a nodelist // Returns a nodelist NodeList<Element> l = $("div.section").get(); var l = $('div.section').get(); // Returns the size of the collection // Returns the size of the collection int size = $("div.section").size(); var size = $('div.section').size(); // Modify all elements in the collection // Modify all elements in the collection $("div.section").addClass("highlighted"); $('div.section').addClass('highlighted'); $("a.foo").html("<em>Hello</em>"); $('a.foo').html('<em>Hello</em>'); // Iterate and runs a function around each // Iterate and runs a function around each // element // element $("div.section").each(new Function(){ $('div.section').each(function(){ public void f() { $(this).css('background', 'red'); $(this).css("background", "red"); }); } }); // Some methods return results from the first // Some methods return results from the first // matched element // matched element int height = $("div#intro").height(); var height = $("div#intro").height(); String src = $("img.photo").attr("src"); var src = $("img.photo").attr('src'); String lastP = $("p:last").html(); var lastP = $("p:last").html(); - We have to define the appropriate return type. - and to use double instead of single quotes
Selectors ● Both GQuery and jQuery are built around selectors. ● Both support CSS standard selectors plus extra selectors (:text :password :hidden etc). ● jQuery uses the sizzle engine. A javascript engine which works with any browser and has optimizations per browser. ● GQuery has optimized engines written in java. ● The more appropriate engine is selected in compile time. ● GQuery uses a modified sizzle version for IE6/7 ● GQuery adds compile-time optimizations when using compiled selectors.
Dynamic selectors $("#note"); ● Use $(string) with dynamic selectors $(".note"); $("body"); $("div p"); ● Add the context if the target $("div + p"); $("div .example"); elements have not been attached yet $("div > div"); $("div ~ p"); or to improve performance. $("h1[id]:contains(Selectors)"); $("tr:first"); $("tr:last"); ● It supports XML documents as well $("*:checked"); $("*:visible"); $("a[href][lang][class]"); $("div:not(.example)"); $("div[class]"); $("div[class*=e]"); String className = "note"; $("div[class=example]"); $("." + className); $("div[class~=dialog]"); $("div[class^=exa]"); // Specify the context to improve performance $("div[class$=mple]"); Element e = DOM.getElementById("whatever"); $("p:first-child"); $(".note", e); $("p:last-child"); $("p:nth-child(n)"); // Use the context with unattached elements $("p:nth-child(2n)"); Widget w = new MyWidget(); $("p:nth-child(2n+1)"); $(".note", w); $("p:nth-child(even)"); $("p:nth-child(odd)"); $("p:only-child"); [...]
Compiled Selectors ● Use them with immutable selectors. ● And when selector performance is a goal in your application. ● Context is supported interface MySelectors extends Selectors { @Selector("*:checked") GQuery allChecked(); @Selector("*:checked") GQuery allChecked(Node context); } public void onModuleLoad() { MySelectors selectors = GWT.create(MySelectors.class); selectors.allChecked(); Element e = DOM.getElementById("whatever"); selectors.allChecked(e); }
Selectors Performance → Click to open the benchmarking application
Selectors Performance ● GQuery in compiled mode produces the faster javascript code to select DOM elements. ● GQuery dynamic selectors are, in most cases, faster or equal than any other library.
Traversing the Dom ● Like jQuery, GQuery provides enhanced methods for traversing the DOM GQuery nextSibling = $("div.section").next(); GQuery prevSibling = $("div.section").prev(); GQuery prevAnchorSibling = $("div.section").prev("a"); GQuery firstParent = $("div.section").parent(); GQuery allParents = $("div.section").parents(); ● Additionally it provides useful method to locate Gwt Widgets. // We can traverse the DOM to locate widgets // Return the CellTree widget whose id is myTree CellTree tree = $("#myTree").widget(); // Now we can use the instance tree.addCloseHandler(...); // Return all gwt Labels in the dom List<Label> allLabels = $("div").widgets(Label.class);
Chaining Methods ● Most GQuery methods return another GQuery object often representing the same collection. This means that you can chain methods together. $("div.section").show().addClass("comeBack"); ● Crazy chaining. $("form#login") // hide all the labels inside the form with the "optional" class .find("label.optional").hide().end() // add a red border to any password fields in the form .find("input:password").css("border", "1px solid red").end() // add a submit handler to the form .submit(new Function(){ public boolean f(Event e) { return confirm("Are you sure you want to submit?"); } });
CSS // jQuery like syntax: property, value $("#myId") .css("color", "red"); // jQuery like syntax: javascript object $("#myId") .css($$("top: '50px', left: '25px', color: 'red'")); // Additionally GQuery supports css style-sheet syntax (copy and paste) $("#myId") .css($$("margin: 3px; padding: 3px; font-size: small;")); // Many properties require a strict syntax: // background: color url repeat attachment position $("#myId").css("background", "transparent url('back.jpg') no-repeat scroll center"); // border: width style color $("#myId").css("border", "medium dotted #cdcd"); - We use the '$$' method to generate javascript property structures
CSS Type-safe // Set the border style of a button widget to 'dotted' value Button myButton = new Button(); $(myButton).css(CSS.BORDER_STYLE.with(BorderStyle.DOTTED)); // vertical-align can take a constant value $("#myId").css(CSS.VERTICAL_ALIGN.with(VerticalAlign.MIDDLE)); // or a length : here 120 px $("#myId").css(CSS.VERTICAL_ALIGN.with(Length.px(120))); // it easy now to specify shorthand property, // we do not have to remember the order! $("#myId").css(CSS.BACKGROUND.with( RGBColor.TRANSPARENT, UriValue.url("back.jpg"), BackgroundRepeat.NO_REPEAT, BackgroundAttachment.SCROLL, BackgroundPosition.CENTER)); // specify margin, padding, text-decoration and font-size in one pass $("#myId").css(CSS.MARGIN.with(Length.px(3)), CSS.PADDING.with(Length.px(3), Length.px(5)), CSS.TEXT_DECORATION.with(TextDecoration.NONE), CSS.FONT_SIZE.with(FontSize.SMALL));
Events ● GQuery provides methods for assigning event in a cross-browser way. ● GQuery event system is compatible with Gwt. ● issues: – When Gwt detaches a widget, events added via GQuery are lost. – If you use 'live' for future elements, consider performance (be carefully with 'onmouse...' events)
Events examples // GQuery provides methods for assigning event // handlers to elements in a cross-browser way. $("a").click(new Function() { public boolean f(Event ev) { $(this).css("backgroundColor", "orange"); // return false to stop default action and event-bubbling return false; } }); // Fires the event click on all labels $(".gwt-Label").click(); // Remove event handlers $("a").unbind("click"); // Attach a handler to all elements matching the // selector, now and in the future $("a") .live("over", new Function(){ public void f() { $(this).css("color", "red"); } }) // Type-safe .live(Event.ONMOUSEOUT, new Function(){ public void f() { $(this).css("color", null); } });
Effects ● GQuery provides several techniques for adding animations to a web page. ● These include simple, standard animations that are frequently used: ● fadeIn, fadeOut, slideDown, slideUp … $(".foo").fadeIn(2000); ● and the ability to craft sophisticated custom effects via the animate method using jquery animation syntax ● queue, delay, stop, css, attr, colors ... $(".foo") .stop() .animate("left:'+=1000'", 2000, Easing.SWING) .delay(500) .animate("left:'-=1000'", 2000); → Go to zoom example
Ajax ● Gwt includes its own facilities for performing communications with the server: ● RPC, Request Factory (Only Java) ● Request Builder ● But GQuery complements it adding: ● jQuery syntax. ● Builders to handle JSON and XML.
Ajax methods GQuery Java. jQuery JavaScript. // Load a remote html fragment in a set of // Load a remote html fragment in a set of // dom elements // dom elements $("#c").load("file.html #mid"); $('#c').load('file.html #mid'); // Unsupported in GQuery // More advanced methods $.getScript(url, callback); GQuery.get("file.html", null, new Function(){ public void f() { // More advanced methods alert("success " + getData()[0]); $.get('file.php', null, function(data){ } alert("success " + data); }); }); GQuery.post("file.html",$$("name:'John',time:'2pm'"), $.post('file.php', {name: 'John', time: '2pm'}, new Function(){ public void f() { function(data){ alert("success " + getData()[0]); alert("success" + data); }}); }); GQuery.getJSON("file.html",$$("name:'John',time:'2pm'"), $.getJSON('file.php', {name: 'John', time: '2pm'}, new Function(){ public void f() { function(data){ alert("success " + getData()[0]); alert("success" + data); }}); }); - Gwt compiler disallows a class named '$', so we use 'GQuery'
Data binding ● Although Gquery – provides the class 'Properties' to handle Json objects... Properties p = $$("key1: 'value1', key2: [1,2]"); String v1 = p.getStr("key1"); – and it is able to inspect Xml objects using css selector engine... Element e = JsUtils.parseXML("<root><message>hello</message></root>"); String txt = $("root message", e).text(); GQuery provides generators to produce builders and handle Xml and Json as 'java' objects. ● Data binding objects support getters, setters and attribute renaming via annotations ● The usage of data binding makes the code more readable, type- safe, checks null conditions, castings, etc.
Data binding example // GQuery generator will create the implementation interface Site extends JsonBuilder { long getId(); String getUrl(); String[] getTags(); // change the name to fix the misspelling @Name("referer") Site getReferrer(); String getTitle(); [{ "id": 1234, "referer": {"id": 2, "url": "http://google.com"}, //NOTE: Setters not displayed to simplify "url": "http://mochikit.com/interpreter/index.html", } "title": "Interpreter", "tags": [ GQuery.getJSON("test.json", null, new Function() { "mochikit","webdev","tool","tools", public void f() { "javascript","interactive","interpreter","repl" // Create the Site instance ] Site s = GWT.create(Site.class); }] // Load the data got from the server s.load(getData()[0]); // We can use standard getters and setters, // making the code more readable and type-safe alert("OK " + s.getUrl() + " " + s.getTags()[0] + " " + s.getReferrer().getUrl()); } }); // Alternative: handle data using GQuery Properties class Properties p = (Properties)getData()[0]; alert ("OK " + p.getStr("url") + " " + p.getArray("tags").getString(0) + " " + ((Properties)p.getJavaScriptObject("referer")).getStr("url"));
Plugins ● GQuery is extensible through plugins, adding new features for different purposes. ● Because of java constrains, we can not add new methods to the GQuery class so we have to use the method 'as' to use plugin methods. ● Core already includes: Events, Effects, Widgets and Ajax plugins ● GQuery has its own site to host plugins. Contributions welcomed! → Go to the plugins site
Plugins: Create and Usage Usage a Plugin. // jQuery syntax $("h1").as(MyPlugin).newMethod(); $("h1").newMethod(); Develop a Plugin. public static class MyPlugin extends GQuery { // Register the plugin in the GQuery plugin system public static final Class<MyPlugin> MyPlugin = Gquery.registerPlugin(MyPlugin.class, new Plugin<MyPlugin>() { public MyPlugin init(GQuery gq) { return new MyPlugin(gq); } }); // Initialization protected MyPlugin(GQuery gq) { super(gq); } // Add a new methods to GQuery objects public GQuery newMethod() { // Write your code here return this; } }
Progressive Enhancement ● Enhance pure Html pages: Crawlers friendly. $("a").click(new Function() { public void f() { GWT.log("Clicked: " + $(this).text() + " " + $(this).attr("href")); } }); ● Enhance Gwt Widgets: Without manipulating the class. $(".gwt-Button").prepend("<img src='help.png'>"); ● Enhance Gwt Views: MVP pattern compatible. $("textarea").as(Enhance).richText();
JavaScript size ● Gquery takes advantage of the gwt compiler which produces optimized and striped code. ● Gquery core tends to use light-weight stuff to reduce the javascript size and improve the performance. ● A small GQuery application normally is smaller than the jQuery minimized library. ● The js size which GQuery adds to a Gwt application is 3 or more times smaller than the jquery library.
Comparing sizes ● The ImageZoom Example needs a 17% less of javascript code (FF). ● When using deflate-gzip in webserver, gwt js code is pre-ordered so the compression factor is better.
jsQuery ● The latest work in GQuery is to produce a clone of jquery which could be used as a replacement of jQuery. We call this library jsQuery. ● The goal is not to compete against jquery, but ● To avoid including jquery in Gwt applications which need some native jQuery methods like jquery plugins. ● As an investigative work which demonstrates that any js API can be developed in Gwt (jQuery is the js API most widely used). ● We use the gwt-exporter library which is able to expose Gwt classes and methods to javascript. ● Right now most GQuery object methods are exposed but we have to implement and export many static methods which are in jQuery like extend, each, map … ● The main goal is to encourage people to wrap jQuery plugins, just including them as jsni and creating java wrappers methods around it.
jsQuery issues ● Gwt-exporter introduces a high amount of extra code to deal with types and wrappers. If we consider compression, jsQuery is only 8KB greater ● Gwt-exporter spends time figuring out which methods to call and how to wrap parameters and return objects. ● Apart of the code in GQuery, we will need extra code to emulate all jQuery API.
jsQuery example <!-- <script src="http://code.jquery.com/jquery-latest.min.js" /> --> <script src="http://code.google.com/p/gwtquery/source/browse/api/jsquery.nocache.js" /> <script type="text/javascript"> $(document).ready(function(){ $("ul.thumb li").hover(function() { $(this).css({'z-index' : '10'}); $(this).find('img').addClass("hover").stop() .animate({ marginTop: '-110px', marginLeft: '-110px', top: '50%', left: '50%', width: '174px', height: '174px', padding: '20px' }, 200); } , function() { $(this).css({'z-index' : '0'}); $(this).find('img').removeClass("hover").stop() .animate({ marginTop: '0', marginLeft: '0', top: '0', left: '0', width: '100px', height: '100px', padding: '5px' }, 400); }); }); </script>
Links GwtQuery http://code.google.com/p/gwtquery/ http://gwtquery.googlecode.com/svn/trunk/gwtquery-core/javadoc/com/google/gwt/query/client/GQuery.html http://code.google.com/p/gwtquery/w/list http://code.google.com/p/gwtquery-plugins/ Plugins http://gwtquery-plugins.googlecode.com/svn/trunk/ratings/demos/Ratings/RatingsSample.html http://gwtquery-plugins.googlecode.com/svn/trunk/enhance/demos/Enhance/EnhanceSample.html http://gwtquery-plugins.googlecode.com/svn/trunk/droppable/demo/GFinderSample/GFinderSample.html http://gwtquery-plugins.googlecode.com/svn/trunk/droppable/demo/GwtPortletSample/GwtPortletSample.html http://gwtquery-ui.googlecode.com/svn/demos/GwtQueryUi.html Application http://talkwheel.com
Conclusions ● People knowing jquery can easily use GQuery because share the API. ● GQuery uses java : – Type safe, discover errors early (compile time instead of runtime) – Advanced IDE (code completion, refactoring) – Most people knows java but only a few js. ● GQuery uses gwt: – Do not worry about compression, obfuscation … – TDD, Debug – Many libraries available ● GQuery complements the Gwt world making easier code: write less, do more. ● GQuery helps to develop applications using the jquery paradigm based on Enhancement, instead of the Gwt one based on Widgets. ● GQuery is mature, just released version 1.1.0, and well documented. ● The GQuery plugin system is simple. ● Contributors are Welcome !!!
Announcement GQuery 1.1.0 released today ! We wanted to match the new release announcement with the RivieraDev event.

GQuery a jQuery clone for Gwt, RivieraDev 2011

  • 1.
    GwtQuery: A jQuery clonefor GWT, and much more ... Manuel Carrasco Moñino manolo@apache.org @dodotis
  • 2.
    About me ● Apache James ● HUPA ● GWT ● Gquery & Gquery-plugins ● GwtExporter ● GwtUpload ● Chronoscope ● Jenkins ● Performance plugin ● Emma plugin ● Linux ● LXP a light and visual window manager based on icewm
  • 3.
    Contents ● What is GWT ● What is Gquery ● Learning Gquery – GQuery, $(), Function – Collections & grabbing Values – Selectors – Traversing the DOM – Method Chaining – CSS – Events – Effects – Ajax – Data binding – Plugins ● Js Size ● jsQuery
  • 4.
    What is GWT Javato Javascript Compiler, Linker, Optimizer and Obfuscator One compiled 'js' per browser (like c++ one 'exec' per processor) Is a full SDK. Not a Js Framework Not a Js Library Not a new language Not a Web Framework
  • 5.
    Advantages of usingJava. ● A high level language allows that the developer doesn't get lost with low level details: DOM, Ajax, Cross-domain, Compression, Obfuscation, Dependencies, Browser differences, etc. ● Huge Java ecosystem: IDE, Re-factoring, Debug, Code assist, Maven. ● Metrics, TDD, CI, Reusing (libraries) ● Patterns, Builders … ● Type safe, syntax checking, reduce errors. ● Separate code maintenance from the effectiveness of the executable. ● Normally, the compiler would produce better js code than the code we could write by hand (less code, compressed, obfuscated, remove dead code, etc).
  • 6.
    What does theGwt SDK provide ● Generators, Compiler, Linker, Optimizer, Obfuscater. ● Client side libraries: DOM, XML, JSON, RPC, RF, I18n, MVP, Widgets ● Server libraries: RPC, RF ● Eclipse plugin ● Multi-browser Dev mode ● Unit testing and Debug tools. ● Performance tools (speed tracer) ● Compiler Statistics ● Everything is open sourced (Apache v2.0)
  • 7.
    GWT Eclipse Java Code (IDE) Plugin Java Server Java Client Side Side Toolkit (SDK) GWT development GWT Compiler Debug/Hosted/Test JRE Emulation Browser libs GWT server Widgets libs RPC/RF Test Runner FF/IE/Ch-Plugin 3ª Party 3ª Party Server libs Client libs JavaScript. GQuery J-Byte Code Bundles (css, sprite). JSON/XML/HTML/TXT JSON/XML/HTML/TXT RPC/RF Browser Any Backend JVM App-Server (php, ruby, ...)
  • 8.
    What is GQuery ● A library for GWT ● Provides jQuery API and syntax (small differences) ● Entirely re-written in java, not a wrapper, optimized for Gwt. ● Has many features not available in jQuery. – Data binding generators – Type-safe structures – Compile selectors ● It is a useful complement for Gwt. – CSS selectors – Widget finders – Light weight collections – DOM and Widget enhancers. ● Can be used as an alternative to traditional Gwt developing (progressive enhancement) ● Performance in mind, Unit tested. ● Extensible via Plugins
  • 9.
    Easy to gettingstarted ● Use the gquery maven Archetype. mvn archetype:generate -DarchetypeGroupId=com.googlecode.gwtquery -DarchetypeArtifactId=gquery-archetype -DarchetypeVersion=1.1.2 -DgroupId=fr.rivieradev -DartifactId=hello -DprojectName=HelloWorld ● Maven Ready (see README.txt). mvn clean package mvn gwt:run
  • 10.
    IDE Friendly ● Eclipse, IntelliJ, Netbeans ● Run, Debug, Test ● Code Assist ● Re-Factoring ● Software Metrics
  • 11.
    The GQuery Object ● Like in jQuery ... ● Selectors return an object ... ● Which represents a collection of Elements ... ● And each has plenty of useful methods. ● Most methods return the object itself so you can chain them. ● Other methods return a value of the first element GQuery g = $("img.photo"); g.attr("src", "/default.png"); String color = g.css("color"); int size = $("img.photo").css("border", "none").size();
  • 12.
    The Dollar '$()'Method ● As in Javascript, the symbol '$' is legal for methods and classes. ● But The Gwt Compiler disallows it for class names, So we use GQuery. // Import GQuery utility methods statically // it should be ...client.$.* but the compiler complains import static com.google.gwt.query.client.GQuery.*; // The '$' method always returns a GQuery object GQuery g; // Use '$' to create new DOM elements g = $("<div>hello</div>"); // Use '$' to select DOM elements g = $("div:hidden"); // Use '$' to wrap existing elements g = $(document); // Use '$' to wrap Gwt widgets Button button = new Button(); g = $(button); // '$' can handle other arguments: // Function, Event, Element[], NodeList ...
  • 13.
    Functions ● java hasn't got closures. ● We use 'Function' inner class to emulate javascript function ● Override the appropriate 'f()' to write your code
  • 14.
    Collections and GrabbingValues GQuery Java. jQuery JavaScript. // Returns a GQuery object // Returns a jQuery object GQuery g = $("div.section"); var g = $('div.section'); // Returns a nodelist // Returns a nodelist NodeList<Element> l = $("div.section").get(); var l = $('div.section').get(); // Returns the size of the collection // Returns the size of the collection int size = $("div.section").size(); var size = $('div.section').size(); // Modify all elements in the collection // Modify all elements in the collection $("div.section").addClass("highlighted"); $('div.section').addClass('highlighted'); $("a.foo").html("<em>Hello</em>"); $('a.foo').html('<em>Hello</em>'); // Iterate and runs a function around each // Iterate and runs a function around each // element // element $("div.section").each(new Function(){ $('div.section').each(function(){ public void f() { $(this).css('background', 'red'); $(this).css("background", "red"); }); } }); // Some methods return results from the first // Some methods return results from the first // matched element // matched element int height = $("div#intro").height(); var height = $("div#intro").height(); String src = $("img.photo").attr("src"); var src = $("img.photo").attr('src'); String lastP = $("p:last").html(); var lastP = $("p:last").html(); - We have to define the appropriate return type. - and to use double instead of single quotes
  • 15.
    Selectors ● Both GQuery and jQuery are built around selectors. ● Both support CSS standard selectors plus extra selectors (:text :password :hidden etc). ● jQuery uses the sizzle engine. A javascript engine which works with any browser and has optimizations per browser. ● GQuery has optimized engines written in java. ● The more appropriate engine is selected in compile time. ● GQuery uses a modified sizzle version for IE6/7 ● GQuery adds compile-time optimizations when using compiled selectors.
  • 16.
    Dynamic selectors $("#note"); ● Use $(string) with dynamic selectors $(".note"); $("body"); $("div p"); ● Add the context if the target $("div + p"); $("div .example"); elements have not been attached yet $("div > div"); $("div ~ p"); or to improve performance. $("h1[id]:contains(Selectors)"); $("tr:first"); $("tr:last"); ● It supports XML documents as well $("*:checked"); $("*:visible"); $("a[href][lang][class]"); $("div:not(.example)"); $("div[class]"); $("div[class*=e]"); String className = "note"; $("div[class=example]"); $("." + className); $("div[class~=dialog]"); $("div[class^=exa]"); // Specify the context to improve performance $("div[class$=mple]"); Element e = DOM.getElementById("whatever"); $("p:first-child"); $(".note", e); $("p:last-child"); $("p:nth-child(n)"); // Use the context with unattached elements $("p:nth-child(2n)"); Widget w = new MyWidget(); $("p:nth-child(2n+1)"); $(".note", w); $("p:nth-child(even)"); $("p:nth-child(odd)"); $("p:only-child"); [...]
  • 17.
    Compiled Selectors ● Use them with immutable selectors. ● And when selector performance is a goal in your application. ● Context is supported interface MySelectors extends Selectors { @Selector("*:checked") GQuery allChecked(); @Selector("*:checked") GQuery allChecked(Node context); } public void onModuleLoad() { MySelectors selectors = GWT.create(MySelectors.class); selectors.allChecked(); Element e = DOM.getElementById("whatever"); selectors.allChecked(e); }
  • 18.
    Selectors Performance → Click to open the benchmarking application
  • 19.
    Selectors Performance ● GQuery in compiled mode produces the faster javascript code to select DOM elements. ● GQuery dynamic selectors are, in most cases, faster or equal than any other library.
  • 20.
    Traversing the Dom ● Like jQuery, GQuery provides enhanced methods for traversing the DOM GQuery nextSibling = $("div.section").next(); GQuery prevSibling = $("div.section").prev(); GQuery prevAnchorSibling = $("div.section").prev("a"); GQuery firstParent = $("div.section").parent(); GQuery allParents = $("div.section").parents(); ● Additionally it provides useful method to locate Gwt Widgets. // We can traverse the DOM to locate widgets // Return the CellTree widget whose id is myTree CellTree tree = $("#myTree").widget(); // Now we can use the instance tree.addCloseHandler(...); // Return all gwt Labels in the dom List<Label> allLabels = $("div").widgets(Label.class);
  • 21.
    Chaining Methods ● Most GQuery methods return another GQuery object often representing the same collection. This means that you can chain methods together. $("div.section").show().addClass("comeBack"); ● Crazy chaining. $("form#login") // hide all the labels inside the form with the "optional" class .find("label.optional").hide().end() // add a red border to any password fields in the form .find("input:password").css("border", "1px solid red").end() // add a submit handler to the form .submit(new Function(){ public boolean f(Event e) { return confirm("Are you sure you want to submit?"); } });
  • 22.
    CSS // jQuery likesyntax: property, value $("#myId") .css("color", "red"); // jQuery like syntax: javascript object $("#myId") .css($$("top: '50px', left: '25px', color: 'red'")); // Additionally GQuery supports css style-sheet syntax (copy and paste) $("#myId") .css($$("margin: 3px; padding: 3px; font-size: small;")); // Many properties require a strict syntax: // background: color url repeat attachment position $("#myId").css("background", "transparent url('back.jpg') no-repeat scroll center"); // border: width style color $("#myId").css("border", "medium dotted #cdcd"); - We use the '$$' method to generate javascript property structures
  • 23.
    CSS Type-safe // Setthe border style of a button widget to 'dotted' value Button myButton = new Button(); $(myButton).css(CSS.BORDER_STYLE.with(BorderStyle.DOTTED)); // vertical-align can take a constant value $("#myId").css(CSS.VERTICAL_ALIGN.with(VerticalAlign.MIDDLE)); // or a length : here 120 px $("#myId").css(CSS.VERTICAL_ALIGN.with(Length.px(120))); // it easy now to specify shorthand property, // we do not have to remember the order! $("#myId").css(CSS.BACKGROUND.with( RGBColor.TRANSPARENT, UriValue.url("back.jpg"), BackgroundRepeat.NO_REPEAT, BackgroundAttachment.SCROLL, BackgroundPosition.CENTER)); // specify margin, padding, text-decoration and font-size in one pass $("#myId").css(CSS.MARGIN.with(Length.px(3)), CSS.PADDING.with(Length.px(3), Length.px(5)), CSS.TEXT_DECORATION.with(TextDecoration.NONE), CSS.FONT_SIZE.with(FontSize.SMALL));
  • 24.
    Events ● GQuery provides methods for assigning event in a cross-browser way. ● GQuery event system is compatible with Gwt. ● issues: – When Gwt detaches a widget, events added via GQuery are lost. – If you use 'live' for future elements, consider performance (be carefully with 'onmouse...' events)
  • 25.
    Events examples // GQueryprovides methods for assigning event // handlers to elements in a cross-browser way. $("a").click(new Function() { public boolean f(Event ev) { $(this).css("backgroundColor", "orange"); // return false to stop default action and event-bubbling return false; } }); // Fires the event click on all labels $(".gwt-Label").click(); // Remove event handlers $("a").unbind("click"); // Attach a handler to all elements matching the // selector, now and in the future $("a") .live("over", new Function(){ public void f() { $(this).css("color", "red"); } }) // Type-safe .live(Event.ONMOUSEOUT, new Function(){ public void f() { $(this).css("color", null); } });
  • 26.
    Effects ● GQuery provides several techniques for adding animations to a web page. ● These include simple, standard animations that are frequently used: ● fadeIn, fadeOut, slideDown, slideUp … $(".foo").fadeIn(2000); ● and the ability to craft sophisticated custom effects via the animate method using jquery animation syntax ● queue, delay, stop, css, attr, colors ... $(".foo") .stop() .animate("left:'+=1000'", 2000, Easing.SWING) .delay(500) .animate("left:'-=1000'", 2000); → Go to zoom example
  • 27.
    Ajax ● Gwt includes its own facilities for performing communications with the server: ● RPC, Request Factory (Only Java) ● Request Builder ● But GQuery complements it adding: ● jQuery syntax. ● Builders to handle JSON and XML.
  • 28.
    Ajax methods GQuery Java. jQuery JavaScript. // Load a remote html fragment in a set of // Load a remote html fragment in a set of // dom elements // dom elements $("#c").load("file.html #mid"); $('#c').load('file.html #mid'); // Unsupported in GQuery // More advanced methods $.getScript(url, callback); GQuery.get("file.html", null, new Function(){ public void f() { // More advanced methods alert("success " + getData()[0]); $.get('file.php', null, function(data){ } alert("success " + data); }); }); GQuery.post("file.html",$$("name:'John',time:'2pm'"), $.post('file.php', {name: 'John', time: '2pm'}, new Function(){ public void f() { function(data){ alert("success " + getData()[0]); alert("success" + data); }}); }); GQuery.getJSON("file.html",$$("name:'John',time:'2pm'"), $.getJSON('file.php', {name: 'John', time: '2pm'}, new Function(){ public void f() { function(data){ alert("success " + getData()[0]); alert("success" + data); }}); }); - Gwt compiler disallows a class named '$', so we use 'GQuery'
  • 29.
    Data binding ● Although Gquery – provides the class 'Properties' to handle Json objects... Properties p = $$("key1: 'value1', key2: [1,2]"); String v1 = p.getStr("key1"); – and it is able to inspect Xml objects using css selector engine... Element e = JsUtils.parseXML("<root><message>hello</message></root>"); String txt = $("root message", e).text(); GQuery provides generators to produce builders and handle Xml and Json as 'java' objects. ● Data binding objects support getters, setters and attribute renaming via annotations ● The usage of data binding makes the code more readable, type- safe, checks null conditions, castings, etc.
  • 30.
    Data binding example // GQuery generator will create the implementation interface Site extends JsonBuilder { long getId(); String getUrl(); String[] getTags(); // change the name to fix the misspelling @Name("referer") Site getReferrer(); String getTitle(); [{ "id": 1234, "referer": {"id": 2, "url": "http://google.com"}, //NOTE: Setters not displayed to simplify "url": "http://mochikit.com/interpreter/index.html", } "title": "Interpreter", "tags": [ GQuery.getJSON("test.json", null, new Function() { "mochikit","webdev","tool","tools", public void f() { "javascript","interactive","interpreter","repl" // Create the Site instance ] Site s = GWT.create(Site.class); }] // Load the data got from the server s.load(getData()[0]); // We can use standard getters and setters, // making the code more readable and type-safe alert("OK " + s.getUrl() + " " + s.getTags()[0] + " " + s.getReferrer().getUrl()); } }); // Alternative: handle data using GQuery Properties class Properties p = (Properties)getData()[0]; alert ("OK " + p.getStr("url") + " " + p.getArray("tags").getString(0) + " " + ((Properties)p.getJavaScriptObject("referer")).getStr("url"));
  • 31.
    Plugins ● GQuery is extensible through plugins, adding new features for different purposes. ● Because of java constrains, we can not add new methods to the GQuery class so we have to use the method 'as' to use plugin methods. ● Core already includes: Events, Effects, Widgets and Ajax plugins ● GQuery has its own site to host plugins. Contributions welcomed! → Go to the plugins site
  • 32.
    Plugins: Create andUsage Usage a Plugin. // jQuery syntax $("h1").as(MyPlugin).newMethod(); $("h1").newMethod(); Develop a Plugin. public static class MyPlugin extends GQuery { // Register the plugin in the GQuery plugin system public static final Class<MyPlugin> MyPlugin = Gquery.registerPlugin(MyPlugin.class, new Plugin<MyPlugin>() { public MyPlugin init(GQuery gq) { return new MyPlugin(gq); } }); // Initialization protected MyPlugin(GQuery gq) { super(gq); } // Add a new methods to GQuery objects public GQuery newMethod() { // Write your code here return this; } }
  • 33.
    Progressive Enhancement ● Enhance pure Html pages: Crawlers friendly. $("a").click(new Function() { public void f() { GWT.log("Clicked: " + $(this).text() + " " + $(this).attr("href")); } }); ● Enhance Gwt Widgets: Without manipulating the class. $(".gwt-Button").prepend("<img src='help.png'>"); ● Enhance Gwt Views: MVP pattern compatible. $("textarea").as(Enhance).richText();
  • 34.
    JavaScript size ● Gquery takes advantage of the gwt compiler which produces optimized and striped code. ● Gquery core tends to use light-weight stuff to reduce the javascript size and improve the performance. ● A small GQuery application normally is smaller than the jQuery minimized library. ● The js size which GQuery adds to a Gwt application is 3 or more times smaller than the jquery library.
  • 35.
    Comparing sizes ● The ImageZoom Example needs a 17% less of javascript code (FF). ● When using deflate-gzip in webserver, gwt js code is pre-ordered so the compression factor is better.
  • 36.
    jsQuery ● The latest work in GQuery is to produce a clone of jquery which could be used as a replacement of jQuery. We call this library jsQuery. ● The goal is not to compete against jquery, but ● To avoid including jquery in Gwt applications which need some native jQuery methods like jquery plugins. ● As an investigative work which demonstrates that any js API can be developed in Gwt (jQuery is the js API most widely used). ● We use the gwt-exporter library which is able to expose Gwt classes and methods to javascript. ● Right now most GQuery object methods are exposed but we have to implement and export many static methods which are in jQuery like extend, each, map … ● The main goal is to encourage people to wrap jQuery plugins, just including them as jsni and creating java wrappers methods around it.
  • 37.
    jsQuery issues ● Gwt-exporter introduces a high amount of extra code to deal with types and wrappers. If we consider compression, jsQuery is only 8KB greater ● Gwt-exporter spends time figuring out which methods to call and how to wrap parameters and return objects. ● Apart of the code in GQuery, we will need extra code to emulate all jQuery API.
  • 38.
    jsQuery example <!-- <scriptsrc="http://code.jquery.com/jquery-latest.min.js" /> --> <script src="http://code.google.com/p/gwtquery/source/browse/api/jsquery.nocache.js" /> <script type="text/javascript"> $(document).ready(function(){ $("ul.thumb li").hover(function() { $(this).css({'z-index' : '10'}); $(this).find('img').addClass("hover").stop() .animate({ marginTop: '-110px', marginLeft: '-110px', top: '50%', left: '50%', width: '174px', height: '174px', padding: '20px' }, 200); } , function() { $(this).css({'z-index' : '0'}); $(this).find('img').removeClass("hover").stop() .animate({ marginTop: '0', marginLeft: '0', top: '0', left: '0', width: '100px', height: '100px', padding: '5px' }, 400); }); }); </script>
  • 39.
    Links GwtQuery http://code.google.com/p/gwtquery/ http://gwtquery.googlecode.com/svn/trunk/gwtquery-core/javadoc/com/google/gwt/query/client/GQuery.html http://code.google.com/p/gwtquery/w/list http://code.google.com/p/gwtquery-plugins/ Plugins http://gwtquery-plugins.googlecode.com/svn/trunk/ratings/demos/Ratings/RatingsSample.html http://gwtquery-plugins.googlecode.com/svn/trunk/enhance/demos/Enhance/EnhanceSample.html http://gwtquery-plugins.googlecode.com/svn/trunk/droppable/demo/GFinderSample/GFinderSample.html http://gwtquery-plugins.googlecode.com/svn/trunk/droppable/demo/GwtPortletSample/GwtPortletSample.html http://gwtquery-ui.googlecode.com/svn/demos/GwtQueryUi.html Application http://talkwheel.com
  • 40.
    Conclusions ● People knowing jquery can easily use GQuery because share the API. ● GQuery uses java : – Type safe, discover errors early (compile time instead of runtime) – Advanced IDE (code completion, refactoring) – Most people knows java but only a few js. ● GQuery uses gwt: – Do not worry about compression, obfuscation … – TDD, Debug – Many libraries available ● GQuery complements the Gwt world making easier code: write less, do more. ● GQuery helps to develop applications using the jquery paradigm based on Enhancement, instead of the Gwt one based on Widgets. ● GQuery is mature, just released version 1.1.0, and well documented. ● The GQuery plugin system is simple. ● Contributors are Welcome !!!
  • 41.
    Announcement GQuery 1.1.0 released today ! We wanted to match the new release announcement with the RivieraDev event.