join the dart side of web development 2 (use the force) - giovanni laquidara - codemotion rome 2015

73
Giovanni Laquidara Join the Dart Side of Web Development 2 ( Use the Force ). [email protected] - Google Developer Group Roma Rome March 27 th 2015

Upload: codemotion

Post on 15-Jul-2015

332 views

Category:

Technology


1 download

TRANSCRIPT

Giovanni Laquidara

Join the Dart Side of Web Development 2 ( Use the Force ).

[email protected] - Google Developer Group Roma

Rome March 27th 2015

MILAN november 28th/29th 2014 – Speaker's name

What!?! Do you need a Web App?

MILAN november 28th/29th 2014 – Speaker's name

require.js

Backbone

Backbone Marionette

jQuery

Modernizr

moment.js

dest templates

PhantomJS

JasmineDocs

Docs

Docs

Docs

Docs

Docs

Docs

Docs

Docs

MILAN november 28th/29th 2014 – Speaker's name

MILAN november 28th/29th 2014 – Speaker's name

MILAN november 28th/29th 2014 – Speaker's name

! Language! Libraries! Tools! Compilation to Javascript

MILAN november 28th/29th 2014 – Speaker's name

Dart is open source! BSD-style license! dart.googlecode.com! GitHub mirror! Contributing guide! ECMA Standard (TC52)! Production ready (1.9.1)

MILAN november 28th/29th 2014 – Speaker's name

Compile to JavaScript, runs across the modern web

MILAN november 28th/29th 2014 – Speaker's name

MILAN november 28th/29th 2014 – Speaker's name

Run Dart on the server with

the Dart VM

MILAN november 28th/29th 2014 – Speaker's name import 'dart:math' show Random; // Import a class from a library.

void main() { // The app starts executing here. print(new Dice(n: 12).roll()); // Print a new object's value.}

class Dice { // Define a class. static Random shaker = new Random(); // Define a class variable. int sides, value; // Define instance variables.

String toString() => '$value'; // Define a method using shorthand syntax.

Dice({int n: 6}) { // Define a constructor. if (4 <= n && n <= 20) { sides = n; } else { throw new ArgumentError(/* */); // Support for errors and exceptions. } } int roll() { // Define an instance method. return value = shaker.nextInt(sides) + 1; // Get a random number. }}

MILAN november 28th/29th 2014 – Speaker's name class Hug { num strength;}

MILAN november 28th/29th 2014 – Speaker's name class Hug { num _strength;

num get strength { // some code return this._strength; } set strength(num value) { // do something with value; this._strength = value; }

}

MILAN november 28th/29th 2014 – Speaker's name class Hug { num _strength;

Hug(strength) { this._strength = strength; }

Hug.light(strength) { this._strength = 0; }

}

MILAN november 28th/29th 2014 – Speaker's name class Hug { num _strength;

Hug(this._strength);

}

MILAN november 28th/29th 2014 – Speaker's name class Hug { num _strength;

Hug(this._strength);

Hug operator +(Hug other) { return new Hug(strength + other.strength); }}

MILAN november 28th/29th 2014 – Speaker's name

var button = new ButtonElement();button.id = 'fancy';button.text = 'Click Point';button.classes.add('important');button.onClick.listen((e) => addTopHat());

parentElement.children.add(button);

MILAN november 28th/29th 2014 – Speaker's name

var button = new ButtonElement();..id = 'fancy';..text = 'Click Point';..classes.add(‘important');..onClick.listen((e) => addTopHat());

parentElement.children.add(button);

MILAN november 28th/29th 2014 – Speaker's name

Missing getter?

"Coffee".missing // ??

Class 'String' has no instance getter 'missing'.

NoSuchMethodError : method not found: 'missing' Receiver: "Coffee" Arguments: []

MILAN november 28th/29th 2014 – Speaker's name

String compared to number?

“2” > 1 // ??

Unhandled exception: Class 'String' has no instance method '>'.

NoSuchMethodError : method not found: '>' Receiver: "2" Arguments: [1]

MILAN november 28th/29th 2014 – Speaker's name

Lexical Closures?

var talk = (s) => print(s); talk("Hi there");

MILAN november 28th/29th 2014 – Speaker's name

void main() { String name = "Giovanni Laquidara"; print(initials(name));}

String initials(String name) { StringBuffer retValue = new StringBuffer(); name.split(" ").forEach( (String part ) { retValue.write(part[0] + '.'); }); return retValue.toString();}

MILAN november 28th/29th 2014 – Speaker's name

main() { var name = "Giovanni Laquidara"; print(initials(name));}

initials(name) { var retValue = new StringBuffer(); name.split(" ").forEach( ( part ) { retValue.write(part[0] + '.'); }); return retValue.toString();}

MILAN november 28th/29th 2014 – Speaker's name import 'dart:html';

InputElement toDoInput;UListElement toDoList;

void main() { toDoInput = querySelector("#to-do-input"); toDoList = querySelector("#to-do-list"); toDoInput.onChange.listen(addToDoItem);}

void addToDoItem(Event event) { LIElement newToDo = new LIElement(); newToDo.text = toDoInput.value; toDoInput.value = ''; toDoList.children.add(newToDo);}

MILAN november 28th/29th 2014 – Speaker's name

import 'dart:async' show Future, Completer;

void main() { loadNews().then( (news) { //Do something with news }); print("Just print!");}

Future loadNews() { Completer completer = new Completer(); //Insert very slow process here completer.complete(); return completer.future;}

MILAN november 28th/29th 2014 – Speaker's name

Old Style Async

MILAN november 28th/29th 2014 – Speaker's name

…2 Days Ago….Brand New Async

MILAN november 28th/29th 2014 – Speaker's name

import 'dart:io';

main() { HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 4040) .then((HttpServer server) { print('listening on localhost, port ${server.port}'); server.listen((HttpRequest request) { request.response.write('Hello, world!'); request.response.close(); }); }).catchError((e) => print(e.toString()));}

MILAN november 28th/29th 2014 – Speaker's name

Use the tools you already know

MILAN november 28th/29th 2014 – Speaker's name

Pub

+1500 Packages

https://pub.dartlang.org/

MILAN november 28th/29th 2014 – Speaker's name

name: gdghuntdescription: A application using google play game servicesversion: 0.1.0author: Giovanni Laquidaradependencies: googleapis: any googleapis_auth: any browser: any core_elements: ">=0.2.0 <0.3.0" polymer: ">=0.12.0 <0.13.0" paper_elements: ">=0.1.0 <0.2.0"

pubspec.yaml

MILAN november 28th/29th 2014 – Speaker's name

main Library

baz foo bar boo

imports

callsbaz

main foo bar

Tree shakingdart2js

The web is full of links, yet web dev has no linker

MILAN november 28th/29th 2014 – Speaker's name

(bigger is better)

https://www.dartlang.org/performance

MILAN november 28th/29th 2014 – Speaker's name

https://www.dartlang.org/cloud/

MILAN november 28th/29th 2014 – Speaker's name

http://goo.gl/xpFhgY

MILAN november 28th/29th 2014 – Speaker's name

Polymer

MILAN november 28th/29th 2014 – Speaker's name

Web Components

MILAN november 28th/29th 2014 – Speaker's name

MILAN november 28th/29th 2014 – Speaker's name

The Polymer Stack

MILAN november 28th/29th 2014 – Speaker's name

dependencies: polymer: ">=0.15.1 <0.17.0"transformers:- polymer

pubspec.yaml

MILAN november 28th/29th 2014 – Speaker's name

<head> ... <link rel="import" href="packages/paper_elements/paper_input.html"> ...</head><body unresolved> <paper-input label="Type something..."></paper-input> ... <script type="application/dart">export 'package:polymer/init.dart';</script></body>

MILAN november 28th/29th 2014 – Speaker's name

<link rel="import" href="../packages/polymer/polymer.html"><polymer-element name="hello-world" noscript> <template> <p>Hello from inside a custom element!</p> </template></polymer-element>

Custom Element

MILAN november 28th/29th 2014 – Speaker's name

<polymer-element name="click-counter"> <template> <button on-click="{{increment}}">Click Me</button> <p>You clicked the button {{count}} times.</p> </template> <script type="application/dart" src="click_counter.dart"></script></polymer-element>

Data binding

MILAN november 28th/29th 2014 – Speaker's name

import 'package:polymer/polymer.dart';import 'dart:html';

@CustomTag('click-counter')class ClickCounterElement extends PolymerElement { @observable int count = 0;

ClickCounterElement.created() : super.created();

void increment(Event e, var detail, Node target) { count += 1; }}

Data binding

MILAN november 28th/29th 2014 – Speaker's name

<polymer-element name="volume-nob"> <template> <p>You turned the volume to {{volume}}.</p> </template> <script type="application/dart" src="volume_nob.dart"></script></polymer-element>

Custom attributes

<volume-nob volume="11"></volume-nob>

MILAN november 28th/29th 2014 – Speaker's name

Custom attributes

import 'package:polymer/polymer.dart';import 'dart:html';

@CustomTag('volume-nob')class VolumeNobElement extends PolymerElement { // @published means 'this is an attribute', and it is observable. @published int volume = 0;

VolumeNobElement.created() : super.created();}

MILAN november 28th/29th 2014 – Speaker's name

Template conditional

<polymer-element name="click-counter"><template> <template if="{{count < 10}}"> ... </template> <template if="{{ count >= 10 }}"> ... </template></template><script type="application/dart" src="clickcounter.dart"></script></polymer-element>

MILAN november 28th/29th 2014 – Speaker's name

Template loops<polymer-element name="fav-fruits"> <template> <ul> <template repeat="{{fruit in fruits}}"> <li> I like {{ fruit }}. </li> </template> </ul> </template> <script type="application/dart" src="fav_fruits.dart"></script></polymer-element>

MILAN november 28th/29th 2014 – Speaker's name

Template loops

import 'package:polymer/polymer.dart';

@CustomTag('fav-fruits')class FavFruitsElement extends PolymerElement { final List fruits = toObservable(['apples', 'pears', 'bananas']);

FavFruitsElement.created() : super.created();}

MILAN november 28th/29th 2014 – Speaker's name

Extending DOM Elements

<button is="fancy-button">Click me</button>

MILAN november 28th/29th 2014 – Speaker's name

<polymer-element name="fancy-button" extends="button"> <template> <style> :host { background: pink; } </style> <content></content> </template> <script type="application/dart" src="fancy_button.dart"></script></polymer-element>

MILAN november 28th/29th 2014 – Speaker's name

import 'package:polymer/polymer.dart';import 'dart:html' show ButtonElement;

@CustomTag('fancy-button')class FancyButton extends ButtonElement with Polymer, Observable { FancyButton.created() : super.created() { polymerCreated(); }}

Dart Force

Realtime Web Framework

Java Developer

Use Familiar Annotations

@Controllerpublic class HelloWorldController {

@RequestMapping("/helloWorld") public String helloWorld(Model model) { model.addAttribute("message", "Hello World!"); return "helloWorld"; }}

@Controllerclass HelloWorldController {

@RequestMapping("/helloWorld") String helloWorld(Model model) { model.addAttribute("message", "Hello World!"); return "helloWorld"; }}

Realtime Dart

ForceServer fs = new ForceServer(host: “0.0.0.0", port: 3030,

clientFiles: '../build/web/', clientServe: true);

fs.start().then((_) {

fs.send("request", {'whatIwant' : 'info'});

fs.on('info', (e, sendable) {sendable.send("received", { "data": "ok" });

});

});

Inspired By

Communication Types

•Send all

•Broadcast

•Send to a specific client byID

•Send info to profiles

Profile management

Define profilesend info to profile

var profileInfo = { 'name': playName }; forceClient.initProfileInfo(profileInfo);

sendable.sendToProfile('name', name, 'private', message);

AuthenticationforceServer.on("examplerequest", (e, sendable) { // do something}, roles: ["ADMIN", "BASIC"]);

class SessionStrategy extends SecurityStrategy {

bool checkAuthorization(HttpRequest req) { HttpSession session = req.session; return (session["user"]!=null); }

Uri getRedirectUri(HttpRequest req) { var referer = req.uri.toString(); return Uri.parse("/login/?referer=$referer"); }}

forceServer.server.strategy = new SessionStrategy();

https://github.com/ForceUniverse

MILAN november 28th/29th 2014 – Speaker's name

Just Like Flash

Developers feel Dart familiar Flashers feel StageXL Familiar

mySprite.addEventListener(Event.ENTER_FRAME, enterFrameListener);mySprite.addEventListener(MouseEvent.CLICK, mouseClickListener, useCapture:true);

var subscription1 = mySprite.onEnterFrame.listen(enterFrameListener);var subscription2 = mySprite.onMouseClick.listen(mouseClickListener);var subscription3 = mySprite.on("customEvent").listen(customEventListener);//...

subscription1.cancel(); // equals removeEventListener(...)subscription2.pause(); // pause receiving eventssubscription2.resume(); // resume receiving events

var textField = new TextField();textField.defaultTextFormat = new TextFormat('Spicy Rice', 30, Color.Black);textField.text = 'The quick brown fox jumps over the lazy dog.'textField.x = 20;textField.y = 20;textField.width = 100;textField.height = 50;textField.wordWrap = true;addChild(textField);

var resourceManager = new ResourceManager() ..addBitmapData('dog', 'images/dog.png') ..addSound('plop', 'sounds/plop.mp3') ..addTextureAtlas('fl', 'images/flowers.json', TextureAtlasFormat.JSONARRAY);

resourceManager.load().then((result) { var dog = resourceManager.getBitmapData('dog'); var plop = resourceManager.getSound('plop'); var flowers = resourceManager.getTextureAtlas('fl'); var daisy = flowers.getBitmapData('daisy');});

MILAN november 28th/29th 2014 – Speaker's name

// The ResourceManager substitutes embedded resources of Flash.var resourceManager = new ResourceManager();resourceManager.addSound("plop", "sounds/plop.mp3"); // loads ogg-file in Firefox!...

var sound = resourceManager.getSound("plop");var soundTransform = new SoundTransform(0.5);var soundChannel = sound.play(false, soundTransform);

var tween = new Tween(sprite, 2.0, TransitionFunction.easeOutBounce);tween.animate.x.to(700);tween.animate.y.to(500);tween.delay = 1.0;tween.onComplete = () => sprite.removeFromParent();

renderLoop.juggler.add(tween);

MILAN november 28th/29th 2014 – Speaker's name http://toolkitfordart.github.io/

MILAN november 28th/29th 2014 – Speaker's name

http://bombemotion.herokuapp.com

Tap 3 birds with Bomb

Hope to win!

MILAN november 28th/29th 2014 – Speaker's name

Giovanni Laquidara+GiovanniLaquidara@joaolaqjoaobiriba

thanks() => new FeedBack();

getQuestions().then( (what) { answer(what); });

https://joind.in/talk/view/14108