Mashing up JavaScript – Advanced Techniques for modern Web Apps

Post on 24-May-2015

5,748 views 2 download

Tags:

description

My Mashing up JavaScript presentation from OSCON

transcript

Mashing up JavaScriptAdvanced techniques for modern web applications

Bastian HofmannVZnet Netzwerke Ltd.

Wtf?

• JavaScript Apps

• CORS and OAuth2

• Local Storage

• OEmbed and Caja

• WebSockets, ActivityStrea.ms and PubsubHubbub

Let‘s write a JS App

History & Bookmarking

www.example.com#Page

http://sammyjs.org/

API Access

Same Origin Policy

Cross-Origin Resource Sharing

Backendapi.twitter.com

Client client.net

AJAX

Access-Control-Allow-Origin: *

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

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?

Templates

Mustache.JS

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

}

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

jQuery(function() { app.run('#/');});

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

jQuery(function() { app.run('#/');});

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

jQuery(function() { app.run('#/');});

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

jQuery(function() { app.run('#/');});

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

jQuery(function() { app.run('#/');});

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

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

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

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

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

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

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

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

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

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

DEMO

Authorization

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

this.bind('getFeed', function() { oauth2.retrieveAccessToken(); if (! oauth2.store['access_token']) { this.redirect('#Login'); return; } ... });

this.bind('getFeed', function() { oauth2.retrieveAccessToken(); if (! oauth2.store['access_token']) { this.redirect('#Login'); return; } ... });

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

<script type="text/javascript"> var fragment = location.hash.substr(1); opener.parent.oauth2.storeToken(fragment); window.close();</script>

<script type="text/javascript"> var fragment = location.hash.substr(1); opener.parent.oauth2.storeToken(fragment); window.close();</script>

<script type="text/javascript"> var fragment = location.hash.substr(1); opener.parent.oauth2.storeToken(fragment); window.close();</script>

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

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

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

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../update.json?oauth_token=' + oauth2.store['access_token'], type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../update.json?oauth_token=' + oauth2.store['access_token'], type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../update.json?oauth_token=' + oauth2.store['access_token'], type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../update.json?oauth_token=' + oauth2.store['access_token'], type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../update.json?oauth_token=' + oauth2.store['access_token'], type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

this.post('#Entry', function() { var that = this; $.ajax({ url: 'http://status.net/.../update.json?oauth_token=' + oauth2.store['access_token'], type: 'POST', data: { 'status': that.params['comment'] }, success: function() { that.redirect('#/'); } }); });

Storing the access token

Local Storage

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

localStorage.setItem("key", value);

localStorage.getItem("key");

DEMO

Mash it up!

OEmbed

http://oembed.com/

{  "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}

cool video:

http://embed.ly/

Caja

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

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

DEMO

Instant updates without reloading

PubSubHubbubretrieves Atom feed with Hub URL

Hub

posts sthpings everysubscriber

subscribes for feed

ackssubscription

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

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

http://activitystrea.ms/

http://nodejs.org/

WebSockets

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

socket.io

http://socket.io/

Browser Notifications

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

webkitNotifications.requestPermission();

retrieve Stream with Hub

Ajax: request Subscription

WebSockets:new Post

subscribe at hubchallenge

acknew post

Notification

new post

DEMO

http://bit.ly/oscon_js_mashup

Rate and Comment