Speed up your GWT coding with gQuery Manuel Carrasco Moñino GWT.create 2015 ► Run these slides 1/35
About me... Open Source advocate Vaadin R&D GWT Maintainer Apache James PMC Jenkins Committer   @dodotis +ManuelCarrascoMoñino 2/35
What is gQuery? Write less. Do more! An entire GWT rewrite of the famous jQuery javascript library. Use the jQuery API in GWT applications without including the jQuery, while leveraging the optimizations and type safety provided by GWT. 3/35
It looks like jQuery The API and syntax of GQuery is almost identical to jQuery. Existing jQuery code can be easily adapted into GQuery and used in your GWT applications. jQuery gQuery $(".article:not(.hidden)>.header") .width($("#mainHeader").innerWidth()) .click(function(){ $(this) .siblings(".content") .load("/article/"+$(this).parent().id(), null, function(){ $(this).fadeIn(250); }); }); importstaticcom.google.gwt.query.client.GQuery.*; $(".article:not(.hidden)>.header") .width($("#mainHeader").innerWidth()) .click(newFunction(){ publicvoidf(){ $(this) .siblings(".content") .load("/article/"+$(this).parent().id(), null, newFunction(){ publicvoidf(){ $(this).fadeIn(250); } }); } }); 4/35
But it's much more It integrates gently with GWT shares and enhances its event mechanism knows about widgets hierarchy GWT Optimizers Provides a simpler deferred binding mechanism Provide many utilities for GWT. Plenty of useful methods 5/35
Current gQuery status Very active development 3000 downloads per month In the top 5 of the most popular GWT libraries Stable versions since 2010 Official sponsored & supported by ArcBees 6/35
gQuery Fundamentals 7/35
Easy DOM manipulation GQuery eases traversal and manipulation of the DOM. Use $() to wrap, find and create elements or widgets Chaining methods: select & modify several elements in just one line of code. friendly css style properties syntax. Use $$() to set style properties or for animations It also supports type safe CSS $(".slides>section").css("background-color","green") .animate($$("top:+80%")) .animate($$("top:0,background-color:transparent")).size(); $("<p>Hello</p>").appendTo(".current"); 8/35
Full GWT Widget integration Whatever you do with elements, you can do with widgets Query, Enhance, Manipulate, Modify Promote elements to widgets inserting them in gwt hierarchy Improve widgets events Adding events not implemented by the widget Buttonb=new Button("Clickme"); b.addClickHandler(new ClickHandler(){ publicvoidonClick(ClickEventevent){ console.log("ClickedonButton"); } }); //PromoteanyDOMelementtoaGWTpanel Panelp=$("section.current.jCode-div").as(Widgets).panel().widget(); //UseitasanyotherwidgetinGWThierarchy p.add(b); //EnhanceWidgetDOM $("<ahref='javascript:'>Clickme</a>").prependTo($(b)).on("click",new Function(){ publicbooleanf(Evente){ console.log("ClickedonLink"); returnfalse; } }); 9/35
Event Handling Handle and fire any native event. Create your own events. Support for event name spaces. Delegate events. Pass data to listeners using events Tip: Replacement to EventBus console.log("Clickoncodetexttoseethefontcolor."); $("#console").on("foo",new Function(){ publicbooleanf(Evente,Object...args){ console.log(args[0]); returntrue; } }); $(".current.jCode").on("tap","span",new Function(){ publicbooleanf(Evente){ $("#console").trigger("foo",$(e).css("color")); returnfalse; } }); 10/35
Promises GQuery implements the promises API existing in jQuery. when, then, and, or, progress, done, fail, always Use it as an alternative to nested callback based code. Declarative syntax. Can be used in the JVM //Launchthingsatthesametimewithwhen GQuery.when( $(".ball.yellow").animate($$("bottom:0"),1000), $(".ball.red").animate($$("bottom:0"),2000) ).done(new Function(){ publicvoidf(){ $(".ball").fadeOut(); } }); 11/35
Ajax GQuery provides an easy API for Ajax. Syntax sugar Promises Progress Works in JVM $("#response").load("gwtcreate2015.html#hello>div"); 12/35
Data Binding GQuery ships an easy data binding system to and from JSON or XML Light weight implementation: each object wraps a JS object JVM compatible. publicinterfacePersonextendsJsonBuilder{ PersonsetName(Strings); StringgetName(); PersonsetAge(inti); intgetAge(); List<Person>getChildren(); PersongetPartner(); PersonsetPartner(Personp); } Personme=GQ.create(Person.class).setAge(10).setName("Manolo"); console.log(me); 13/35
Utilities GQuery ships a set of GWT utilities which makes your live easier Avoiding writing GWT JSNI export, import Simplifying GWT Deferred binding browser.isIe, browser.isWebkit ... flags Browser syntax logging console.log, console.err ... Import external JS in JSNIBlocks JsniBundle 14/35
All Right, but how can gQuery help in my GWT project ? Writing less code ! For certain actions you can save 60-90% of code Making your code more expressive Chaining is more declarative. Promises try to solve nested and complex asynchronous blocks. Using pure DOM elements instead of creating widgets for everything. The tendency is to avoid Widgets Web-components are here Reusing existing code (js, html) 15/35
When can I use gQuery in my GWT project? 1.- Doesn't matter the final GWT architecture of your project Plain GWT, MVP, GWTP GXT, MGWT, Vaadin 2.- As usual separate Views from your Business logic. In your Views: gQuery will help you to enhance & manipulate the DOM In your Logic: you can use Ajax, Promises, and Json binding and test in the JVM 16/35
I want to write less and do more... Show me the code 17/35
Don't extend GWT widgets to change it's behavior. Modify the widget when it attaches or detaches. Modify its DOM Add effects Add events Tip: when GWT attaches/detaches you must set events again Easy to use in UiBinder classes Widgetwidget=new Label("Hello"); widget.addAttachHandler(new Handler(){ publicvoidonAttachOrDetach(AttachEventevent){ $(event.getSource()) .append("<span>GWT</span><span>Create</span>") .animate($$("y:+200px,x:+50px,color:yellow"),3000) .on("click","span",new Function(){ publicvoidf(){ console.log($(this).text()); } }); } }); RootPanel.get().add(widget); 18/35
Decouple your widgets Find any widget of a specific java class. By default it looks for widgets attached to the RootPanel Enclose your search using especific selectors like '.gwt-Label' or specific contexts. Then you can use those widgets as usual in your GWT application //YougetalistwithallMyBreadCrumbmatchingtheselector List<MyBreadCrumb>list=$(".gwt-Label").widgets(MyBreadCrumb.class); MyBreadCrumbcrumbs=list.get(0); crumbs.addCrumb("Rocks"); 19/35
GWT Ajax never was simpler. Just one line of code vs dozen of lines using RequestBuilder Reusable responses via Promises Advanced features Upload/Download progress, FormData, CORS Usable in the JVM //ConfigurableviaPropertiessyntax Ajax.get("/my-rest-service/items",$$("customer:whatever")); Ajax.post("/my-rest-service/save",$$("id:foo,description:bar")); Ajax.loadScript("/my-cdn-host/3party.js"); Ajax.importHtml("/bower_components/3party-web-component.html"); //OrviatheSettingsinterface Ajax.ajax(Ajax.createSettings() .setUrl("/my-3party-site/service") .setWithCredentials(true) .setData(GQ.create().set("parameter1","value"))) .fail(new Function(){ publicvoidf(){ console.log("Thecallshouldfailbecauseurl'sareinvalid"); } }); 20/35
Make your async code more declarative and simpler Avoid nesting callbacks Chain promises methods to add callbacks Reuse resolved promises to avoid requesting twice the same service resolved status is maintained for ever Pipe your callbacks //Wecanreusetheloginpromiseanytime PromiseloginDone=Ajax.post("/my-login-service",$$("credentials:whatever")); GQuery.when(loginDone) .then(Ajax.post("/my-rest-service",$$().set("param","value"))) .done(new Function(){ publicObjectf(Object...args){ returnsuper.f(args); } }).fail(new Function(){ publicvoidf(){ console.log("LoginError"); } }); 21/35
JSNI sucks, how does gQuery help? Export java functions to JS objects This will be covered by JsInterop But sometimes you will be interested on simply export one method Execute external functions Automatically boxes and un-boxes parameters and return values Wrap any JS object with JsonBuilders It supports functions Load external libraries via JsniBundle JsUtils.export(window,"foo",new Function(){ publicObjectf(Object...args){ returnargs[0]; } }); Stringresponse=JsUtils.jsni(window,"foo","ByeByeJSNI"); console.log(response); 22/35
Simplifying deferred binding gQuery Browser flags are set in compilation time. They return true or false, making the compiler get rid of other borwsers code Not necessity of create classes nor deal with module files if(browser.webkit){ console.log("WebKit"); }elseif(browser.ie6){ //Thiscodewillneverbeinchromepermutation Window.alert("IE6doesnothaveconsole"); }else{ //Thiscodewillneverbeinchromepermutation console.log("NotwebkitnorIE.Maybemozilla?"+browser.mozilla); } 23/35
Extending gQuery 24/35
How to extend gQuery? Plugins add new methods to GQuery objects It's easy to call new methods via the as(Plugin) method Plugins also could modify certain behaviors of gQuery: support for new selectors synthetic events new css properties ... publicstaticclassCss3AnimationsextendsGQuery{ //Wejustneedaconstructor,andareferencetothenewregisteredplugin protectedCss3Animations(GQuerygq){ super(gq); } publicstaticfinalClass<Css3Animations>Css3Animations=GQuery .registerPlugin(Css3Animations.class,new Plugin<Css3Animations>(){ publicCss3Animationsinit(GQuerygq){ returnnew Css3Animations(gq); } }); //Wecanaddnewmethodsoroverrideexistingones publicCss3Animationscss3Animate(Propertiesproperties){ super.animate(properties); returnthis; } } $(".ball").as(Css3Animations.Css3Animations).animate($$("rotateX:180deg,rotateY:180deg" 25/35
How to port a jQuery plugin to gQuery Gesture Plugin Differences Take original JS code Create JsBuider interfaces so as syntax is similar to JS Set appropriate java types to JS variables Gesture Plugin Source Gighub Gesture Plugin Demo $(".current.jCode").as(Gesture.Gesture).on("taptwo",new Function(){ publicvoidf(){ console.log("DoubleTap"); } }); 26/35
What is the future of gQuery Type safe functions and promises Full support for java 8 lambdas Mobile friendly Integration with JsInterop GQueryg=$(".ball"); g.each(new IsElementFunction(){ publicvoidrun(Elementelm){ $(elm).animate("scale:1.2"); } }); g.on("tapone",new IsEventFunction(){ publicBooleancall(Eventevt){ return$(evt).animate($$("rotateX:90deg")).animate($$("rotateX:0deg")).FALSE; } }); //PredefinedreturntypesinthegQuerychain g.on("taptwo",(e)->$(e).animate($$("x:+=50")).TRUE); //Gettheresultofmultiplecallbacks $.when(()->"aaa",()->"bbb",Ajax.get("/lambdas.html")) .done((Object[]s)->console.log(s[0],s[1],s[3])) .fail((s)->console.log("Fail")); 27/35
Show me more cool code ... 28/35
Example: Material Design Hierarchical Timing. boxes.each(new Function(){ intscale=boxes.isVisible()?0:1; publicvoidf(Elemente){ GQueryg=$(this); intdelay=(int)(g.offset().left+g.offset().top); g.animate("duration:200,delay:"+delay+",scale:"+scale); } }); 29/35
Example: Material Design Ripple Effect. //Createtherippleelementtobeanimated finalGQueryripple=$("<div>").as(Transitions.Transitions).css( $$("position:absolute,width:40px,height:40px,background:white,border-radius:50%" //Addrippleeffectstocertainelementswhentheyaretapped $(".jCode,.button,h1").on("tap.ripple",new Function(){ publicbooleanf(Evente){ GQuerytarget=$(this).css($$("overflow:hidden")).append(ripple); intx=e.getClientX()-20-target.offset().left; inty=e.getClientY()-20-target.offset().top; intf=Math.max(target.width(),target.height())/40*3; ripple.css($$("opacity:0.8,scale:0.5")).css("left",x+"px").css("top",y+"px"); ripple.animate($$("opacity:0,scale:"+f),new Function(){ publicvoidf(){ ripple.detach(); } }); returnfalse; } }); 30/35
Example: Wrapping Web Components with gQuery Use bower to install components in the public folder bower install Polymer/paper-slider Use Ajax utility methods to load polyfills and import templates Web Components can be created and manipulated as any other element. We can change its properties or bind events. Ajax.loadScript("bower_components/webcomponentsjs/webcomponents.js"); Ajax.importHtml("bower_components/paper-slider/paper-slider.html"); GQueryslider=$("<paper-slider/>").appendTo($("#sliders-container")); slider.prop("value",67); slider.on("change",(e)->{ console.log($(e).prop("value")); returntrue; }); $("#sliders-container").append("<paper-slidervalue=183max=255editable>"); 31/35
Example: Binding Attributes of Web Components. JsonBuilder can wrap any JavaScript element Light Weight wrapper Type safe Chain setters publicinterfacePaperSliderextendsJsonBuilder{ //get/setprefixesareoptional intgetValue(); //Chainingsettersisoptional PaperSlidersetValue(intvalue); PaperSlidermin(intvalue); PaperSlidermax(intvalue); PaperSliderstep(intvalue); PaperSlidersnaps(booleanvalue); PaperSliderpin(booleanvalue); } //Waituntilthepolyfillandthewebcomponenthasbeenloaded GQuery.when( Ajax.loadScript("bower_components/webcomponentsjs/webcomponents.js"), Ajax.importHtml("bower_components/paper-slider/paper-slider.html") ).done(new Function(){ publicvoidf(){ //CreateandappendtheelementasusualingQuery GQueryg=$("<paper-slider>").appendTo($("#slider-container")); //WrapthenativeelementinaPOJO PaperSliderslider=GQ.create(PaperSlider.class).load(g); //Useitasajavaobject slider.setValue(300).max(400).step(50).snaps(true).pin(true); } }); 32/35
Example: Uploading files with progress bar. finalGQueryprogress=$("<div>").css($$("height:12px,width:0%,background:#75bff4,position:absolu finalGQueryfileUpload=$("<inputtype='file'accept='image/*'>").appendTo(document).hide fileUpload.on("change",new Function(){ publicbooleanf(Evente){ finalJsArray<JavaScriptObject>files=$(e).prop("files"); JavaScriptObjectformData=JsUtils.jsni("eval","newFormData()"); for(inti=0,l=files.length();i<l;i++){ JsUtils.jsni(formData,"append","file-"+i,files.get(i)); } Ajax.ajax(Ajax.createSettings() .setUrl(uploadUrl).setData(formData).setWithCredentials(true)) .progress(new Function(){ publicvoidf(){ progress.animate("width:"+arguments(2)+"%",1000); } }).always(new Function(){ publicvoidf(){ progress.remove(); } }).done(new Function(){ publicvoidf(){ uploadImg.attr("src",uploadUrl+"&show=file-0-0"); } }); returntrue; } }).trigger("click"); 33/35
Real Examples www.GwtProject.org www.Arcbees.com GwtQuery Slides www.Talkwheel.com 34/35
Questions and Answers Rate this talk: http://gwtcreate.com/agenda when(()->"Talk") .then((o)->"Questions") .and((o)->"Answers") .done((o)->console.log("Thanks")); 35/35

Speed up your GWT coding with gQuery

  • 1.
    Speed up yourGWT coding with gQuery Manuel Carrasco Moñino GWT.create 2015 ► Run these slides 1/35
  • 2.
    About me... Open Sourceadvocate Vaadin R&D GWT Maintainer Apache James PMC Jenkins Committer   @dodotis +ManuelCarrascoMoñino 2/35
  • 3.
    What is gQuery? Writeless. Do more! An entire GWT rewrite of the famous jQuery javascript library. Use the jQuery API in GWT applications without including the jQuery, while leveraging the optimizations and type safety provided by GWT. 3/35
  • 4.
    It looks likejQuery The API and syntax of GQuery is almost identical to jQuery. Existing jQuery code can be easily adapted into GQuery and used in your GWT applications. jQuery gQuery $(".article:not(.hidden)>.header") .width($("#mainHeader").innerWidth()) .click(function(){ $(this) .siblings(".content") .load("/article/"+$(this).parent().id(), null, function(){ $(this).fadeIn(250); }); }); importstaticcom.google.gwt.query.client.GQuery.*; $(".article:not(.hidden)>.header") .width($("#mainHeader").innerWidth()) .click(newFunction(){ publicvoidf(){ $(this) .siblings(".content") .load("/article/"+$(this).parent().id(), null, newFunction(){ publicvoidf(){ $(this).fadeIn(250); } }); } }); 4/35
  • 5.
    But it's muchmore It integrates gently with GWT shares and enhances its event mechanism knows about widgets hierarchy GWT Optimizers Provides a simpler deferred binding mechanism Provide many utilities for GWT. Plenty of useful methods 5/35
  • 6.
    Current gQuery status Veryactive development 3000 downloads per month In the top 5 of the most popular GWT libraries Stable versions since 2010 Official sponsored & supported by ArcBees 6/35
  • 7.
  • 8.
    Easy DOM manipulation GQueryeases traversal and manipulation of the DOM. Use $() to wrap, find and create elements or widgets Chaining methods: select & modify several elements in just one line of code. friendly css style properties syntax. Use $$() to set style properties or for animations It also supports type safe CSS $(".slides>section").css("background-color","green") .animate($$("top:+80%")) .animate($$("top:0,background-color:transparent")).size(); $("<p>Hello</p>").appendTo(".current"); 8/35
  • 9.
    Full GWT Widgetintegration Whatever you do with elements, you can do with widgets Query, Enhance, Manipulate, Modify Promote elements to widgets inserting them in gwt hierarchy Improve widgets events Adding events not implemented by the widget Buttonb=new Button("Clickme"); b.addClickHandler(new ClickHandler(){ publicvoidonClick(ClickEventevent){ console.log("ClickedonButton"); } }); //PromoteanyDOMelementtoaGWTpanel Panelp=$("section.current.jCode-div").as(Widgets).panel().widget(); //UseitasanyotherwidgetinGWThierarchy p.add(b); //EnhanceWidgetDOM $("<ahref='javascript:'>Clickme</a>").prependTo($(b)).on("click",new Function(){ publicbooleanf(Evente){ console.log("ClickedonLink"); returnfalse; } }); 9/35
  • 10.
    Event Handling Handle andfire any native event. Create your own events. Support for event name spaces. Delegate events. Pass data to listeners using events Tip: Replacement to EventBus console.log("Clickoncodetexttoseethefontcolor."); $("#console").on("foo",new Function(){ publicbooleanf(Evente,Object...args){ console.log(args[0]); returntrue; } }); $(".current.jCode").on("tap","span",new Function(){ publicbooleanf(Evente){ $("#console").trigger("foo",$(e).css("color")); returnfalse; } }); 10/35
  • 11.
    Promises GQuery implements thepromises API existing in jQuery. when, then, and, or, progress, done, fail, always Use it as an alternative to nested callback based code. Declarative syntax. Can be used in the JVM //Launchthingsatthesametimewithwhen GQuery.when( $(".ball.yellow").animate($$("bottom:0"),1000), $(".ball.red").animate($$("bottom:0"),2000) ).done(new Function(){ publicvoidf(){ $(".ball").fadeOut(); } }); 11/35
  • 12.
    Ajax GQuery provides aneasy API for Ajax. Syntax sugar Promises Progress Works in JVM $("#response").load("gwtcreate2015.html#hello>div"); 12/35
  • 13.
    Data Binding GQuery shipsan easy data binding system to and from JSON or XML Light weight implementation: each object wraps a JS object JVM compatible. publicinterfacePersonextendsJsonBuilder{ PersonsetName(Strings); StringgetName(); PersonsetAge(inti); intgetAge(); List<Person>getChildren(); PersongetPartner(); PersonsetPartner(Personp); } Personme=GQ.create(Person.class).setAge(10).setName("Manolo"); console.log(me); 13/35
  • 14.
    Utilities GQuery ships aset of GWT utilities which makes your live easier Avoiding writing GWT JSNI export, import Simplifying GWT Deferred binding browser.isIe, browser.isWebkit ... flags Browser syntax logging console.log, console.err ... Import external JS in JSNIBlocks JsniBundle 14/35
  • 15.
    All Right, buthow can gQuery help in my GWT project ? Writing less code ! For certain actions you can save 60-90% of code Making your code more expressive Chaining is more declarative. Promises try to solve nested and complex asynchronous blocks. Using pure DOM elements instead of creating widgets for everything. The tendency is to avoid Widgets Web-components are here Reusing existing code (js, html) 15/35
  • 16.
    When can Iuse gQuery in my GWT project? 1.- Doesn't matter the final GWT architecture of your project Plain GWT, MVP, GWTP GXT, MGWT, Vaadin 2.- As usual separate Views from your Business logic. In your Views: gQuery will help you to enhance & manipulate the DOM In your Logic: you can use Ajax, Promises, and Json binding and test in the JVM 16/35
  • 17.
    I want towrite less and do more... Show me the code 17/35
  • 18.
    Don't extend GWTwidgets to change it's behavior. Modify the widget when it attaches or detaches. Modify its DOM Add effects Add events Tip: when GWT attaches/detaches you must set events again Easy to use in UiBinder classes Widgetwidget=new Label("Hello"); widget.addAttachHandler(new Handler(){ publicvoidonAttachOrDetach(AttachEventevent){ $(event.getSource()) .append("<span>GWT</span><span>Create</span>") .animate($$("y:+200px,x:+50px,color:yellow"),3000) .on("click","span",new Function(){ publicvoidf(){ console.log($(this).text()); } }); } }); RootPanel.get().add(widget); 18/35
  • 19.
    Decouple your widgets Findany widget of a specific java class. By default it looks for widgets attached to the RootPanel Enclose your search using especific selectors like '.gwt-Label' or specific contexts. Then you can use those widgets as usual in your GWT application //YougetalistwithallMyBreadCrumbmatchingtheselector List<MyBreadCrumb>list=$(".gwt-Label").widgets(MyBreadCrumb.class); MyBreadCrumbcrumbs=list.get(0); crumbs.addCrumb("Rocks"); 19/35
  • 20.
    GWT Ajax neverwas simpler. Just one line of code vs dozen of lines using RequestBuilder Reusable responses via Promises Advanced features Upload/Download progress, FormData, CORS Usable in the JVM //ConfigurableviaPropertiessyntax Ajax.get("/my-rest-service/items",$$("customer:whatever")); Ajax.post("/my-rest-service/save",$$("id:foo,description:bar")); Ajax.loadScript("/my-cdn-host/3party.js"); Ajax.importHtml("/bower_components/3party-web-component.html"); //OrviatheSettingsinterface Ajax.ajax(Ajax.createSettings() .setUrl("/my-3party-site/service") .setWithCredentials(true) .setData(GQ.create().set("parameter1","value"))) .fail(new Function(){ publicvoidf(){ console.log("Thecallshouldfailbecauseurl'sareinvalid"); } }); 20/35
  • 21.
    Make your asynccode more declarative and simpler Avoid nesting callbacks Chain promises methods to add callbacks Reuse resolved promises to avoid requesting twice the same service resolved status is maintained for ever Pipe your callbacks //Wecanreusetheloginpromiseanytime PromiseloginDone=Ajax.post("/my-login-service",$$("credentials:whatever")); GQuery.when(loginDone) .then(Ajax.post("/my-rest-service",$$().set("param","value"))) .done(new Function(){ publicObjectf(Object...args){ returnsuper.f(args); } }).fail(new Function(){ publicvoidf(){ console.log("LoginError"); } }); 21/35
  • 22.
    JSNI sucks, howdoes gQuery help? Export java functions to JS objects This will be covered by JsInterop But sometimes you will be interested on simply export one method Execute external functions Automatically boxes and un-boxes parameters and return values Wrap any JS object with JsonBuilders It supports functions Load external libraries via JsniBundle JsUtils.export(window,"foo",new Function(){ publicObjectf(Object...args){ returnargs[0]; } }); Stringresponse=JsUtils.jsni(window,"foo","ByeByeJSNI"); console.log(response); 22/35
  • 23.
    Simplifying deferred binding gQueryBrowser flags are set in compilation time. They return true or false, making the compiler get rid of other borwsers code Not necessity of create classes nor deal with module files if(browser.webkit){ console.log("WebKit"); }elseif(browser.ie6){ //Thiscodewillneverbeinchromepermutation Window.alert("IE6doesnothaveconsole"); }else{ //Thiscodewillneverbeinchromepermutation console.log("NotwebkitnorIE.Maybemozilla?"+browser.mozilla); } 23/35
  • 24.
  • 25.
    How to extendgQuery? Plugins add new methods to GQuery objects It's easy to call new methods via the as(Plugin) method Plugins also could modify certain behaviors of gQuery: support for new selectors synthetic events new css properties ... publicstaticclassCss3AnimationsextendsGQuery{ //Wejustneedaconstructor,andareferencetothenewregisteredplugin protectedCss3Animations(GQuerygq){ super(gq); } publicstaticfinalClass<Css3Animations>Css3Animations=GQuery .registerPlugin(Css3Animations.class,new Plugin<Css3Animations>(){ publicCss3Animationsinit(GQuerygq){ returnnew Css3Animations(gq); } }); //Wecanaddnewmethodsoroverrideexistingones publicCss3Animationscss3Animate(Propertiesproperties){ super.animate(properties); returnthis; } } $(".ball").as(Css3Animations.Css3Animations).animate($$("rotateX:180deg,rotateY:180deg" 25/35
  • 26.
    How to porta jQuery plugin to gQuery Gesture Plugin Differences Take original JS code Create JsBuider interfaces so as syntax is similar to JS Set appropriate java types to JS variables Gesture Plugin Source Gighub Gesture Plugin Demo $(".current.jCode").as(Gesture.Gesture).on("taptwo",new Function(){ publicvoidf(){ console.log("DoubleTap"); } }); 26/35
  • 27.
    What is thefuture of gQuery Type safe functions and promises Full support for java 8 lambdas Mobile friendly Integration with JsInterop GQueryg=$(".ball"); g.each(new IsElementFunction(){ publicvoidrun(Elementelm){ $(elm).animate("scale:1.2"); } }); g.on("tapone",new IsEventFunction(){ publicBooleancall(Eventevt){ return$(evt).animate($$("rotateX:90deg")).animate($$("rotateX:0deg")).FALSE; } }); //PredefinedreturntypesinthegQuerychain g.on("taptwo",(e)->$(e).animate($$("x:+=50")).TRUE); //Gettheresultofmultiplecallbacks $.when(()->"aaa",()->"bbb",Ajax.get("/lambdas.html")) .done((Object[]s)->console.log(s[0],s[1],s[3])) .fail((s)->console.log("Fail")); 27/35
  • 28.
    Show me morecool code ... 28/35
  • 29.
    Example: Material DesignHierarchical Timing. boxes.each(new Function(){ intscale=boxes.isVisible()?0:1; publicvoidf(Elemente){ GQueryg=$(this); intdelay=(int)(g.offset().left+g.offset().top); g.animate("duration:200,delay:"+delay+",scale:"+scale); } }); 29/35
  • 30.
    Example: Material DesignRipple Effect. //Createtherippleelementtobeanimated finalGQueryripple=$("<div>").as(Transitions.Transitions).css( $$("position:absolute,width:40px,height:40px,background:white,border-radius:50%" //Addrippleeffectstocertainelementswhentheyaretapped $(".jCode,.button,h1").on("tap.ripple",new Function(){ publicbooleanf(Evente){ GQuerytarget=$(this).css($$("overflow:hidden")).append(ripple); intx=e.getClientX()-20-target.offset().left; inty=e.getClientY()-20-target.offset().top; intf=Math.max(target.width(),target.height())/40*3; ripple.css($$("opacity:0.8,scale:0.5")).css("left",x+"px").css("top",y+"px"); ripple.animate($$("opacity:0,scale:"+f),new Function(){ publicvoidf(){ ripple.detach(); } }); returnfalse; } }); 30/35
  • 31.
    Example: Wrapping WebComponents with gQuery Use bower to install components in the public folder bower install Polymer/paper-slider Use Ajax utility methods to load polyfills and import templates Web Components can be created and manipulated as any other element. We can change its properties or bind events. Ajax.loadScript("bower_components/webcomponentsjs/webcomponents.js"); Ajax.importHtml("bower_components/paper-slider/paper-slider.html"); GQueryslider=$("<paper-slider/>").appendTo($("#sliders-container")); slider.prop("value",67); slider.on("change",(e)->{ console.log($(e).prop("value")); returntrue; }); $("#sliders-container").append("<paper-slidervalue=183max=255editable>"); 31/35
  • 32.
    Example: Binding Attributesof Web Components. JsonBuilder can wrap any JavaScript element Light Weight wrapper Type safe Chain setters publicinterfacePaperSliderextendsJsonBuilder{ //get/setprefixesareoptional intgetValue(); //Chainingsettersisoptional PaperSlidersetValue(intvalue); PaperSlidermin(intvalue); PaperSlidermax(intvalue); PaperSliderstep(intvalue); PaperSlidersnaps(booleanvalue); PaperSliderpin(booleanvalue); } //Waituntilthepolyfillandthewebcomponenthasbeenloaded GQuery.when( Ajax.loadScript("bower_components/webcomponentsjs/webcomponents.js"), Ajax.importHtml("bower_components/paper-slider/paper-slider.html") ).done(new Function(){ publicvoidf(){ //CreateandappendtheelementasusualingQuery GQueryg=$("<paper-slider>").appendTo($("#slider-container")); //WrapthenativeelementinaPOJO PaperSliderslider=GQ.create(PaperSlider.class).load(g); //Useitasajavaobject slider.setValue(300).max(400).step(50).snaps(true).pin(true); } }); 32/35
  • 33.
    Example: Uploading fileswith progress bar. finalGQueryprogress=$("<div>").css($$("height:12px,width:0%,background:#75bff4,position:absolu finalGQueryfileUpload=$("<inputtype='file'accept='image/*'>").appendTo(document).hide fileUpload.on("change",new Function(){ publicbooleanf(Evente){ finalJsArray<JavaScriptObject>files=$(e).prop("files"); JavaScriptObjectformData=JsUtils.jsni("eval","newFormData()"); for(inti=0,l=files.length();i<l;i++){ JsUtils.jsni(formData,"append","file-"+i,files.get(i)); } Ajax.ajax(Ajax.createSettings() .setUrl(uploadUrl).setData(formData).setWithCredentials(true)) .progress(new Function(){ publicvoidf(){ progress.animate("width:"+arguments(2)+"%",1000); } }).always(new Function(){ publicvoidf(){ progress.remove(); } }).done(new Function(){ publicvoidf(){ uploadImg.attr("src",uploadUrl+"&show=file-0-0"); } }); returntrue; } }).trigger("click"); 33/35
  • 34.
  • 35.
    Questions and Answers Ratethis talk: http://gwtcreate.com/agenda when(()->"Talk") .then((o)->"Questions") .and((o)->"Answers") .done((o)->console.log("Thanks")); 35/35