Mashing up JavaScript Advanced techniques for modern web - - PowerPoint PPT Presentation

mashing up javascript
SMART_READER_LITE
LIVE PREVIEW

Mashing up JavaScript Advanced techniques for modern web - - PowerPoint PPT Presentation

Mashing up JavaScript Advanced techniques for modern web applications Bastian Hofmann VZnet Netzwerke Ltd. Wtf? JavaScript Apps CORS and OAuth2 Local Storage OEmbed and Caja WebSockets, ActivityStrea.ms and PubsubHubbub


slide-1
SLIDE 1

Mashing up JavaScript

Advanced techniques for modern web applications Bastian Hofmann VZnet Netzwerke Ltd.

slide-2
SLIDE 2

Wtf?

slide-3
SLIDE 3
slide-4
SLIDE 4
slide-5
SLIDE 5
slide-6
SLIDE 6
slide-7
SLIDE 7
slide-8
SLIDE 8
slide-9
SLIDE 9
slide-10
SLIDE 10
  • JavaScript Apps
  • CORS and OAuth2
  • Local Storage
  • OEmbed and Caja
  • WebSockets, ActivityStrea.ms and

PubsubHubbub

slide-11
SLIDE 11
slide-12
SLIDE 12
slide-13
SLIDE 13
slide-14
SLIDE 14
slide-15
SLIDE 15

http://slideshare.net/bashofmann

slide-16
SLIDE 16

https://github.com/bashofmann/statusnet_js_mashup

slide-17
SLIDE 17

Let‘s write a JS App

slide-18
SLIDE 18

History & Bookmarking

slide-19
SLIDE 19

www.example.com#Page

slide-20
SLIDE 20

http://sammyjs.org/

slide-21
SLIDE 21

API Access

slide-22
SLIDE 22
slide-23
SLIDE 23

Same Origin Policy

slide-24
SLIDE 24

Cross-Origin Resource Sharing

Backend api.twitter.com Client client.net AJAX Access-Control-Allow-Origin: * http://www.w3.org/TR/cors/

slide-25
SLIDE 25

var html="<ul>"; for (var i=0; i < viewers.length; i++) { html += "<li>" + viewers[i].displayName + "</li>"; } html += "<ul>"; document.getElementById("#div").innerHTML = html;

Where is the error?

slide-26
SLIDE 26

Templates

slide-27
SLIDE 27

Mustache.JS

https://github.com/janl/mustache.js

}

slide-28
SLIDE 28

var feed = []; var app = Sammy('#main', function() { this.use(Sammy.Mustache, 'ms'); this.get('#/', function() { this.trigger('getFeed'); }); ... }); jQuery(function() { app.run('#/'); });

slide-29
SLIDE 29

var feed = []; var app = Sammy('#main', function() { this.use(Sammy.Mustache, 'ms'); this.get('#/', function() { this.trigger('getFeed'); }); ... }); jQuery(function() { app.run('#/'); });

slide-30
SLIDE 30

var feed = []; var app = Sammy('#main', function() { this.use(Sammy.Mustache, 'ms'); this.get('#/', function() { this.trigger('getFeed'); }); ... }); jQuery(function() { app.run('#/'); });

slide-31
SLIDE 31

var feed = []; var app = Sammy('#main', function() { this.use(Sammy.Mustache, 'ms'); this.get('#/', function() { this.trigger('getFeed'); }); ... }); jQuery(function() { app.run('#/'); });

slide-32
SLIDE 32

var feed = []; var app = Sammy('#main', function() { this.use(Sammy.Mustache, 'ms'); this.get('#/', function() { this.trigger('getFeed'); }); ... }); jQuery(function() { app.run('#/'); });

slide-33
SLIDE 33

this.bind('getFeed', function() { var that = this; $.ajax({ url: 'http://..._timeline.json', success: function(response) { feed = response; that.trigger('renderFeed'); } }); }); this.bind('renderFeed', function() { this.feed = feed; this.partial('js/templates/feed.ms'); });

slide-34
SLIDE 34

this.bind('getFeed', function() { var that = this; $.ajax({ url: 'http://..._timeline.json', success: function(response) { feed = response; that.trigger('renderFeed'); } }); }); this.bind('renderFeed', function() { this.feed = feed; this.partial('js/templates/feed.ms'); });

slide-35
SLIDE 35

this.bind('getFeed', function() { var that = this; $.ajax({ url: 'http://..._timeline.json', success: function(response) { feed = response; that.trigger('renderFeed'); } }); }); this.bind('renderFeed', function() { this.feed = feed; this.partial('js/templates/feed.ms'); });

slide-36
SLIDE 36

this.bind('getFeed', function() { var that = this; $.ajax({ url: 'http://..._timeline.json', success: function(response) { feed = response; that.trigger('renderFeed'); } }); }); this.bind('renderFeed', function() { this.feed = feed; this.partial('js/templates/feed.ms'); });

slide-37
SLIDE 37

this.bind('getFeed', function() { var that = this; $.ajax({ url: 'http://..._timeline.json', success: function(response) { feed = response; that.trigger('renderFeed'); } }); }); this.bind('renderFeed', function() { this.feed = feed; this.partial('js/templates/feed.ms'); });

slide-38
SLIDE 38

this.bind('getFeed', function() { var that = this; $.ajax({ url: 'http://..._timeline.json', success: function(response) { feed = response; that.trigger('renderFeed'); } }); }); this.bind('renderFeed', function() { this.feed = feed; this.partial('js/templates/feed.ms'); });

slide-39
SLIDE 39

<ul> {{#feed}} <li> <p>{{{statusnet_html}}}</p> <p>{{created_at}} {{#user}} {{name}} {{/user}} </p> </li> {{/feed}} </ul>

slide-40
SLIDE 40

<ul> {{#feed}} <li> <p>{{{statusnet_html}}}</p> <p>{{created_at}} {{#user}} {{name}} {{/user}} </p> </li> {{/feed}} </ul>

slide-41
SLIDE 41

<ul> {{#feed}} <li> <p>{{{statusnet_html}}}</p> <p>{{created_at}} {{#user}} {{name}} {{/user}} </p> </li> {{/feed}} </ul>

slide-42
SLIDE 42

<ul> {{#feed}} <li> <p>{{{statusnet_html}}}</p> <p>{{created_at}} {{#user}} {{name}} {{/user}} </p> </li> {{/feed}} </ul>

slide-43
SLIDE 43

DEMO

slide-44
SLIDE 44

Authorization

slide-45
SLIDE 45
slide-46
SLIDE 46

+----------+ Client Identifier +----------------+ | |>---(A)-- & Redirection URI --->| | | | | | End <--+ - - - +----(B)-- User authenticates -->| Authorization | User | | | Server | | |<---(C)--- Redirect URI -------<| | | Client | with Access Token | | | in | in Fragment +----------------+ | Browser | | | +----------------+ | |>---(D)--- Redirect URI ------->| | | | without Fragment | Web Server | | | | with Client | | (F) |<---(E)--- Web Page with ------<| Resource | | Access | Script | | | Token | +----------------+ +----------+

OAuth 2

http://tools.ietf.org/html/draft-ietf-oauth-v2

slide-47
SLIDE 47

this.bind('getFeed', function() {

  • auth2.retrieveAccessToken();

if (! oauth2.store['access_token']) { this.redirect('#Login'); return; } ... });

slide-48
SLIDE 48

this.bind('getFeed', function() {

  • auth2.retrieveAccessToken();

if (! oauth2.store['access_token']) { this.redirect('#Login'); return; } ... });

slide-49
SLIDE 49

this.get('#Login', function() { var consumerKey = 'abc....'; window.open('http://status.net/api/oauth2/ authorize?response_toke=token&client_id=' + consumerKey); });

slide-50
SLIDE 50

this.get('#Login', function() { var consumerKey = 'abc....'; window.open('http://status.net/api/oauth2/ authorize?response_toke=token&client_id=' + consumerKey); });

slide-51
SLIDE 51

<script type="text/javascript"> var fragment = location.hash.substr(1);

  • pener.parent.oauth2.storeToken(fragment);

window.close(); </script>

slide-52
SLIDE 52

<script type="text/javascript"> var fragment = location.hash.substr(1);

  • pener.parent.oauth2.storeToken(fragment);

window.close(); </script>

slide-53
SLIDE 53

<script type="text/javascript"> var fragment = location.hash.substr(1);

  • pener.parent.oauth2.storeToken(fragment);

window.close(); </script>

slide-54
SLIDE 54

<form action="#Entry" method="post"> <textarea name="comment"></textarea> <input type="submit" value="send"/> </form>

slide-55
SLIDE 55

<form action="#Entry" method="post"> <textarea name="comment"></textarea> <input type="submit" value="send"/> </form>

slide-56
SLIDE 56

<form action="#Entry" method="post"> <textarea name="comment"></textarea> <input type="submit" value="send"/> </form>

slide-57
SLIDE 57

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../ update.json?oauth_token=' +

  • auth2.store['access_token'],

type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

slide-58
SLIDE 58

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../ update.json?oauth_token=' +

  • auth2.store['access_token'],

type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

slide-59
SLIDE 59

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../ update.json?oauth_token=' +

  • auth2.store['access_token'],

type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

slide-60
SLIDE 60

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../ update.json?oauth_token=' +

  • auth2.store['access_token'],

type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

slide-61
SLIDE 61

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../ update.json?oauth_token=' +

  • auth2.store['access_token'],

type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

slide-62
SLIDE 62

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../ update.json?oauth_token=' +

  • auth2.store['access_token'],

type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

slide-63
SLIDE 63

Storing the access token

slide-64
SLIDE 64

Local Storage

http://www.w3.org/TR/webstorage/

slide-65
SLIDE 65

localStorage.setItem("key", value);

slide-66
SLIDE 66

localStorage.getItem("key");

slide-67
SLIDE 67

DEMO

slide-68
SLIDE 68

Mash it up!

slide-69
SLIDE 69

cool video: http://www.youtube.com/ watch?v=OFzkTxiwziQ

slide-70
SLIDE 70

OEmbed

http://oembed.com/

slide-71
SLIDE 71

http://www.youtube.com/watch?v=OyJd2qsRkNk

slide-72
SLIDE 72
slide-73
SLIDE 73

http://www.youtube.com/oembed?url=http%3A%2F %2Fwww.youtube.com%2Fwatch%3Fv %3DOyJd2qsRkNk&maxwidth=500&format=json

slide-74
SLIDE 74

{ "provider_url":"http:\/\/www.youtube.com\/", "title":"Jupiter Jones - Das Jahr in dem ich schlief (Musik Video)", "html":"\u003cobject width=\"500\" height=\"306\"\u003e \u003cparam name=\"movie\" value=\"http:\/\/www.youtube.com\/v\/ OyJd2qsRkNk?version=3\"\u003e\u003c\/param\u003e\u003cparam name= \"allowFullScreen\" value=\"true\"\u003e\u003c\/param\u003e \u003cparam name=\"allowscriptaccess\" value=\"always\"\u003e \u003c\/param\u003e\u003cembed src=\"http:\/\/www.youtube.com\/v\/ OyJd2qsRkNk?version=3\" type=\"application\/x-shockwave-flash \" width=\"500\" height=\"306\" allowscriptaccess=\"always \" allowfullscreen=\"true\"\u003e\u003c\/embed\u003e\u003c\/object \u003e", "author_name":"St182", "height":306, "thumbnail_width":480, "width":500, "version":"1.0", "author_url":"http:\/\/www.youtube.com\/user\/Stinkfist182", "provider_name":"YouTube", "thumbnail_url":"http:\/\/i4.ytimg.com\/vi\/OyJd2qsRkNk\/ hqdefault.jpg", "type":"video", "thumbnail_height":360 }

slide-75
SLIDE 75

cool video:

slide-76
SLIDE 76

http://embed.ly/

slide-77
SLIDE 77
slide-78
SLIDE 78

Caja

http://code.google.com/p/google-caja/

slide-79
SLIDE 79

html_sanitize(‘<script>alert(“foo“);</script>‘)

slide-80
SLIDE 80

DEMO

slide-81
SLIDE 81

Instant updates without reloading

slide-82
SLIDE 82

PubSubHubbub

retrieves Atom feed with Hub URL Hub posts sth pings every subscriber subscribes for feed acks subscription

http://code.google.com/p/pubsubhubbub/

slide-83
SLIDE 83

<link rel="alternate"href="http:// status.net.xyz:8061/index.php/api/statuses/ user_timeline/3.atom"type="application/atom +xml" title="Notice feed for bastian (Atom)"/>

slide-84
SLIDE 84

<entry> <activity:object-type>http://activitystrea.ms/schema/1.0/ note</activity:object-type> <id>http://status.net.xyz:8061/index.php/notice/20</id> <title>hello from client</title> <content type="html">hello from client</content> <link rel="alternate" type="text/html" href="http:// status.net.xyz:8061/index.php/notice/20"/> <activity:verb>http://activitystrea.ms/schema/1.0/post</ activity:verb> <published>2011-05-23T21:07:33+00:00</published> <updated>2011-05-23T21:07:33+00:00</updated> <link rel="ostatus:conversation" href="http://status.net.xyz: 8061/index.php/conversation/20"/> <georss:point>52.52437 13.41053</georss:point> <link rel="self" type="application/atom+xml"href="http:// status.net.xyz:8061/index.php/api/statuses/show/20.atom"/> <link rel="edit" type="application/atom+xml"href="http:// status.net.xyz:8061/index.php/api/statuses/show/20.atom"/> <statusnet:notice_info local_id="20" source="api" favorite="false"repeated="false"></statusnet:notice_info> </entry>

slide-85
SLIDE 85

http://activitystrea.ms/

slide-86
SLIDE 86

<link href="http://status.net.xyz:8061/ index.php/main/push/hub" rel="hub"/>

slide-87
SLIDE 87

PubSubHubbub

retrieves Atom feed with Hub URL Hub posts sth pings every subscriber subscribes for feed acks subscription

http://code.google.com/p/pubsubhubbub/

slide-88
SLIDE 88

http://nodejs.org/

slide-89
SLIDE 89

WebSockets

http://dev.w3.org/html5/websockets/

slide-90
SLIDE 90

socket.io

http://socket.io/

slide-91
SLIDE 91

Browser Notifications

slide-92
SLIDE 92

webkitNotifications.createNotification(image, title, text).show();

slide-93
SLIDE 93

webkitNotifications.requestPermission();

slide-94
SLIDE 94

retrieve Stream with Hub Ajax: request Subscription WebSockets: new Post subscribe at hub challenge ack new post Notification new post

slide-95
SLIDE 95

DEMO

slide-96
SLIDE 96

http://bit.ly/oscon_js_mashup

Rate and Comment

slide-97
SLIDE 97

h"p://twi"er.com/Bas2anHofmann h"p://profiles.google.com/bashofmann h"p://lanyrd.com/people/Bas2anHofmann/ h"p://slideshare.net/bashofmann mail@bas2anhofmann.de