gquery a jquery clone for gwt, rivieradev 2011

41
GwtQuery: A jQuery clone for GWT, and much more ... Manuel Carrasco Moñino [email protected] @dodotis

Upload: manuel-carrasco-monino

Post on 11-May-2015

9.325 views

Category:

Technology


3 download

DESCRIPTION

Talk given at the rivieradev conferences Oct-2011

TRANSCRIPT

Page 1: GQuery a jQuery clone for Gwt, RivieraDev 2011

GwtQuery: A jQuery clone for GWT, and much more ...

Manuel Carrasco Moñ[email protected]

@dodotis

Page 2: GQuery a jQuery clone for Gwt, RivieraDev 2011

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

Page 3: GQuery a jQuery clone for Gwt, RivieraDev 2011

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

Page 4: GQuery a jQuery clone for Gwt, RivieraDev 2011

What is GWT

Is a full SDK. Not a Js FrameworkNot a Js LibraryNot a new languageNot a Web Framework

Java to Javascript Compiler, Linker, Optimizer and Obfuscator One compiled 'js' per browser (like c++ one 'exec' per processor)

Page 5: GQuery a jQuery clone for Gwt, RivieraDev 2011

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).

Page 6: GQuery a jQuery clone for Gwt, RivieraDev 2011

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)

Page 7: GQuery a jQuery clone for Gwt, RivieraDev 2011

Java Server Side

Java Client Side

Java Code (IDE)

GWT server libs RPC/RF

GWT development Debug/Hosted/Test

GWT Compiler JRE Emulation

Browser libsWidgets

Test Runner FF/IE/Ch-Plugin

JVM App-Server

J-Byte Code

3ª Party Server libs

BrowserAny Backend(php, ruby, ...)

JavaScript.Bundles (css, sprite).

3ª Party Client libs

Toolkit (SDK)

JSON/XML/HTML/TXT RPC/RF

JSON/XML/HTML/TXT

GWT Eclipse Plugin

GQuery

Page 8: GQuery a jQuery clone for Gwt, RivieraDev 2011

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

Page 9: GQuery a jQuery clone for Gwt, RivieraDev 2011

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

Page 10: GQuery a jQuery clone for Gwt, RivieraDev 2011

IDE Friendly● Eclipse, IntelliJ, Netbeans● Run, Debug, Test● Code Assist● Re-Factoring● Software Metrics

Page 11: GQuery a jQuery clone for Gwt, RivieraDev 2011

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();

Page 12: GQuery a jQuery clone for Gwt, RivieraDev 2011

The Dollar '$()' Method

// 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 ...

● As in Javascript, the symbol '$' is legal for methods and classes.

● But The Gwt Compiler disallows it for class names, So we use GQuery.

Page 13: GQuery a jQuery clone for Gwt, RivieraDev 2011

Functions

● java hasn't got closures.

● We use 'Function' inner class to emulate javascript function

● Override the appropriate 'f()' to write your code

Page 14: GQuery a jQuery clone for Gwt, RivieraDev 2011

Collections and Grabbing Values

// Returns a GQuery object GQuery g = $("div.section");

// Returns a nodelist NodeList<Element> l = $("div.section").get(); // Returns the size of the collection int size = $("div.section").size(); // Modify all elements in the collection $("div.section").addClass("highlighted"); $("a.foo").html("<em>Hello</em>"); // Iterate and runs a function around each // element $("div.section").each(new Function(){ public void f() { $(this).css("background", "red"); } });

// Some methods return results from the first // matched element int height = $("div#intro").height(); String src = $("img.photo").attr("src"); String lastP = $("p:last").html();

// Returns a jQuery object var g = $('div.section');

// Returns a nodelist var l = $('div.section').get(); // Returns the size of the collection var size = $('div.section').size(); // Modify all elements in the collection $('div.section').addClass('highlighted'); $('a.foo').html('<em>Hello</em>'); // Iterate and runs a function around each // element $('div.section').each(function(){ $(this).css('background', 'red'); });

// Some methods return results from the first // matched element var height = $("div#intro").height(); var src = $("img.photo").attr('src'); var lastP = $("p:last").html();

GQuery Java. jQuery JavaScript.

- We have to define the appropriate return type.- and to use double instead of single quotes

Page 15: GQuery a jQuery clone for Gwt, RivieraDev 2011

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.

Page 16: GQuery a jQuery clone for Gwt, RivieraDev 2011

Dynamic selectors $("#note"); $(".note"); $("body"); $("div p"); $("div + p"); $("div .example"); $("div > div"); $("div ~ p"); $("h1[id]:contains(Selectors)"); $("tr:first"); $("tr:last"); $("*:checked"); $("*:visible"); $("a[href][lang][class]"); $("div:not(.example)"); $("div[class]"); $("div[class*=e]"); $("div[class=example]"); $("div[class~=dialog]"); $("div[class^=exa]"); $("div[class$=mple]"); $("p:first-child"); $("p:last-child"); $("p:nth-child(n)"); $("p:nth-child(2n)"); $("p:nth-child(2n+1)"); $("p:nth-child(even)"); $("p:nth-child(odd)"); $("p:only-child"); [...]

● Use $(string) with dynamic selectors

● Add the context if the target elements have not been attached yet or to improve performance.

● It supports XML documents as well

String className = "note"; $("." + className);

// Specify the context to improve performance Element e = DOM.getElementById("whatever"); $(".note", e); // Use the context with unattached elements Widget w = new MyWidget(); $(".note", w);

Page 17: GQuery a jQuery clone for Gwt, RivieraDev 2011

Compiled Selectors

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); }

● Use them with immutable selectors.

● And when selector performance is a goal in your application.

● Context is supported

Page 18: GQuery a jQuery clone for Gwt, RivieraDev 2011

Selectors Performance→ Click to open the benchmarking application

Page 19: GQuery a jQuery clone for Gwt, RivieraDev 2011

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.

Page 20: GQuery a jQuery clone for Gwt, RivieraDev 2011

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();

● Like jQuery, GQuery provides enhanced methods for traversing the DOM

● 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);

Page 21: GQuery a jQuery clone for Gwt, RivieraDev 2011

Chaining Methods

$("div.section").show().addClass("comeBack");

● Most GQuery methods return another GQuery object often representing the same collection. This means that you can chain methods together.

● 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?"); } });

Page 22: GQuery a jQuery clone for Gwt, RivieraDev 2011

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

Page 23: GQuery a jQuery clone for Gwt, RivieraDev 2011

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));

Page 24: GQuery a jQuery clone for Gwt, RivieraDev 2011

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)

Page 25: GQuery a jQuery clone for Gwt, RivieraDev 2011

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); } });

Page 26: GQuery a jQuery clone for Gwt, RivieraDev 2011

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 …

● and the ability to craft sophisticated custom effects via the animate method using jquery animation syntax

● queue, delay, stop, css, attr, colors ...

$(".foo").fadeIn(2000);

$(".foo") .stop() .animate("left:'+=1000'", 2000, Easing.SWING) .delay(500) .animate("left:'-=1000'", 2000);

→ Go to zoom example

Page 27: GQuery a jQuery clone for Gwt, RivieraDev 2011

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.

Page 28: GQuery a jQuery clone for Gwt, RivieraDev 2011

Ajax methods

// Load a remote html fragment in a set of // dom elements $("#c").load("file.html #mid");

// More advanced methods GQuery.get("file.html", null, new Function(){ public void f() { alert("success " + getData()[0]); } }); GQuery.post("file.html",$$("name:'John',time:'2pm'"), new Function(){ public void f() { alert("success " + getData()[0]); }});

GQuery.getJSON("file.html",$$("name:'John',time:'2pm'"), new Function(){ public void f() { alert("success " + getData()[0]); }});

// Load a remote html fragment in a set of // dom elements $('#c').load('file.html #mid');

// Unsupported in GQuery $.getScript(url, callback); // More advanced methods $.get('file.php', null, function(data){ alert("success " + data); });

$.post('file.php', {name: 'John', time: '2pm'}, function(data){ alert("success" + data); });

$.getJSON('file.php', {name: 'John', time: '2pm'}, function(data){ alert("success" + data); });

GQuery Java. jQuery JavaScript.

- Gwt compiler disallows a class named '$', so we use 'GQuery'

Page 29: GQuery a jQuery clone for Gwt, RivieraDev 2011

Data binding

● Although Gquery

– provides the class 'Properties' to handle Json objects...

– and it is able to inspect Xml objects using css selector engine...

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.

Properties p = $$("key1: 'value1', key2: [1,2]"); String v1 = p.getStr("key1");

Element e = JsUtils.parseXML("<root><message>hello</message></root>"); String txt = $("root message", e).text();

Page 30: GQuery a jQuery clone for Gwt, RivieraDev 2011

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();

//NOTE: Setters not displayed to simplify }

GQuery.getJSON("test.json", null, new Function() { public void f() { // 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"));

[{ "id": 1234, "referer": {"id": 2, "url": "http://google.com"}, "url": "http://mochikit.com/interpreter/index.html", "title": "Interpreter", "tags": [ "mochikit","webdev","tool","tools", "javascript","interactive","interpreter","repl" ]}]

Page 31: GQuery a jQuery clone for Gwt, RivieraDev 2011

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

Page 32: GQuery a jQuery clone for Gwt, RivieraDev 2011

Plugins: Create and Usage

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; } }

$("h1").as(MyPlugin).newMethod();

Usage a Plugin.

Develop a Plugin.

// jQuery syntax $("h1").newMethod();

Page 33: GQuery a jQuery clone for Gwt, RivieraDev 2011

Progressive Enhancement

● Enhance pure Html pages: Crawlers friendly.

● Enhance Gwt Widgets: Without manipulating the class.

● Enhance Gwt Views: MVP pattern compatible.

$(".gwt-Button").prepend("<img src='help.png'>");

$("a").click(new Function() { public void f() { GWT.log("Clicked: " + $(this).text() + " " + $(this).attr("href")); } });

$("textarea").as(Enhance).richText();

Page 34: GQuery a jQuery clone for Gwt, RivieraDev 2011

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.

Page 35: GQuery a jQuery clone for Gwt, RivieraDev 2011

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.

Page 36: GQuery a jQuery clone for Gwt, RivieraDev 2011

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.

Page 37: GQuery a jQuery clone for Gwt, RivieraDev 2011

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.

Page 38: GQuery a jQuery clone for Gwt, RivieraDev 2011

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>

Page 39: GQuery a jQuery clone for Gwt, RivieraDev 2011

Links

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-plugins.googlecode.com/svn/trunk/ratings/demos/Ratings/RatingsSample.html

http://talkwheel.com

http://gwtquery-ui.googlecode.com/svn/demos/GwtQueryUi.html

Plugins

Application

GwtQueryhttp://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/

Page 40: GQuery a jQuery clone for Gwt, RivieraDev 2011

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 !!!

Page 41: GQuery a jQuery clone for Gwt, RivieraDev 2011

Announcement

GQuery 1.1.0 released today !

We wanted to match the new release announcement with the RivieraDev event.