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
http://slideshare.net/bashofmann
https://github.com/bashofmann/statusnet_js_mashup
Let‘s write a JS App
History & Bookmarking
www.example.com#Page
http://sammyjs.org/
API Access
Same Origin Policy
Cross-Origin Resource Sharing Backend Client api.twitter.com 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
OAuth 2 +----------+ 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 | +----------------+ +----------+ 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); });
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);
Recommend
More recommend