Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Advanced JavaScript - Creating modern web appli...
Search
Bastian Hofmann
September 18, 2012
Programming
660
5
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Advanced JavaScript - Creating modern web applications
Web Developer Conference 2012, Hamburg
Bastian Hofmann
September 18, 2012
More Decks by Bastian Hofmann
See All by Bastian Hofmann
Monitoring in Kubernetes with Prometheus and Grafana
bastianhofmann
0
360
Creating a fast Kubernetes Development Workflow
bastianhofmann
0
150
Highly available cross-region deployments with Kubernetes
bastianhofmann
1
170
From source to Kubernetes in 30 minutes
bastianhofmann
0
200
Introduction to Kubernetes
bastianhofmann
1
140
CI/CD with Kubernetes
bastianhofmann
0
250
Creating a fast Kubernetes Development Workflow
bastianhofmann
1
290
Deploying your first Micro-Service application to Kubernetes
bastianhofmann
2
210
Creating a fast Kubernetes Development Workflow
bastianhofmann
0
280
Other Decks in Programming
See All in Programming
ローカルLLMでどこまでコードが書けるか -縮小版 / How much code can be written on a local LLM Shortened
kishida
2
200
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
340
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
180
symfony/aiとlaravel/boost
77web
0
140
Embedded SREと共に達成した会員管理システムのAWS移行 - SRE NEXT 2026 ランチスポンサーセッション
niftycorp
PRO
1
2.9k
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
150
これからAgentCoreを触る方へトレンドはGatewayです
har1101
6
500
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
520
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.6k
Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer
monochromegane
0
140
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
7
1.9k
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
Featured
See All Featured
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
460
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.3k
Paper Plane (Part 1)
katiecoart
PRO
1
9.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
350
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
[SF Ruby Conf 2025] Rails X
palkan
2
1.2k
エンジニアに許された特別な時間の終わり
watany
108
250k
Building the Perfect Custom Keyboard
takai
2
820
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
810
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
55k
Designing Experiences People Love
moore
143
24k
Transcript
Advanced JavaScript Creating Modern Web Applications @BastianHofmann
Wtf?
None
None
None
None
None
None
None
None
None
• JavaScript Apps • CORS and OAuth2 • Local Storage
• OEmbed and Caja • WebSockets, ActivityStrea.ms and PubsubHubbub • What‘s next?
None
None
None
None
None
None
None
None
Questions? Ask!
http://speakerdeck.com/u/bastianhofmann
Let‘s write a JS App
https://github.com/bashofmann/statusnet_js_mashup_2nd
https://github.com/bashofmann/vm_js_mashup
CSS Bastian
http://twitter.github.com/bootstrap
History & Bookmarking
www.example.com#Page
www.example.com/Page
http://sammyjs.org/
API Access
None
Same Origin Policy
Cross-Origin Resource Sharing Backend api.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 app = Sammy('#main', function() { var feed = [];
this.use(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'); });
<ul> {{#feed}} <li> <p>{{{statusnet_html}}}</p> <p>{{created_at}} {{#user}} {{name}} {{/user}} </p> </li>
{{/feed}} </ul>
Authorization
None
http://oauth.net/
User-Agent Profile
http://twitter.com/authorize?&clientId=... Open Popup lanyrd.com
http://twitter.com/authorize?&clientId=... Open Popup lanyrd.com HTTPS GET twitter.co m/ authorize
http://twitter.com/authorize?&clientId=... Open Popup lanyrd.com Login twitter.co m/ authorize
http://twitter.com/authorize?&clientId=... Open Popup lanyrd.com Grant Permission twitter.co m/ authorize
lanyrd.com HTTPS Redirect RedirectURI# accessToken twitter.co m/ authorize RedirectURI# accessToken
lanyrd.com
lanyrd.com RedirectURI# accessToken Parse Access Token from Fragment Send it
to opening window Close popup lanyrd.com
Same Origin Policy
lanyrd.com HTTPS Ajax Request to API Access Token twitter.com
Storing the access token
Local Storage http://www.w3.org/TR/webstorage/
this.around(function(callback) { ... if (! oauth2.isLoggedIn()) { this.redirect('/Login'); return; }
callback(); });
this.get('/Login', function() { this.partial('login.ms'); });
<form action="/Login" method="post"> <input type="submit" value="Login"/> </form>
this.post('/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>
<form action="/Feed" method="post"> <textarea name="status"></textarea> <inputtype="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['status'] }, success: function() { that.redirect('/'); } }); });
DEMO
Mash it up!
cool video: http://www.youtube.com/ watch?v=OFzkTxiwziQ
OEmbed http://oembed.com/
http://www.youtube.com/watch?v=OyJd2qsRkNk
None
http://www.youtube.com/oembed?url=http%3A%2F %2Fwww.youtube.com%2Fwatch%3Fv %3DOyJd2qsRkNk&maxwidth=500&format=json
{ "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/
this.bind('changed', function() { embeds = []; $('div.feed-item h3').embedly({ key:'...', maxWidth:
450, wmode: 'transparent', method: 'after' }); });
None
Caja http://code.google.com/p/google-caja/
html_sanitize(result.html);
DEMO
Instant updates without reloading
PubSubHubbub retrieves Atom feed with Hub URL Hub posts sth
pings every subscriber subscribes for feed acks subscription http://code.google.com/p/pubsubhubbub/
<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)"/>
<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/
<link href="http://status.net.xyz:8061/ index.php/main/push/hub" rel="hub"/>
PubSubHubbub retrieves Atom feed with Hub URL Hub posts sth
pings every subscriber subscribes for feed acks subscription http://code.google.com/p/pubsubhubbub/
http://nodejs.org/
HTTP Server for PubsubHubbub
WebSockets http://dev.w3.org/html5/websockets/
socket.io http://socket.io/
(Webkit) Browser Notifications
retrieve Stream with Hub Ajax: request Subscription WebSockets: new Post
subscribe at hub challenge ack new post Notification new post
DEMO
None
Meteor http://www.meteor.com
https://github.com/bashofmann/meteor_shoutbox_demo
DEMO
h"p://twi"er.com/Bas2anHofmann h"p://profiles.google.com/bashofmann h"p://lanyrd.com/people/Bas2anHofmann h"p://speakerdeck.com/u/bas2anhofmann h"ps://github.com/bashofmann
[email protected]