join the dart side of web development 2 (use the force) - giovanni laquidara - codemotion rome 2015
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
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
! 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 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;
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);
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
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
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
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(); }}
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"; }}
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" });
});
});
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();
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://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