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
Mashing up JavaScript
Search
Bastian Hofmann
July 19, 2012
Programming
760
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Mashing up JavaScript
Bastian Hofmann
July 19, 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
270
Other Decks in Programming
See All in Programming
symfony/aiとlaravel/boost
77web
0
120
dRuby over BLE
makicamel
2
410
AI がコードを書く時代における新卒エンジニアの仕事風景 (2026) / New Graduate Engineers in the Era of AI Coding (2026)
sushichan044
0
200
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
190
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
14
6.6k
IBM Bobを活用したレガシーアプリの最新化
oniak3ibm
PRO
1
240
Hunting Vulnerabilities in Symfony with LLMs
vinceamstoutz
0
570
AIエージェントで 変わるAndroid開発環境
takahirom
1
390
技術記事、 専門家としてのプログラマ、 言語化
mizchi
14
7.3k
Haskell/Servantを通してWebミドルウェアを捉え直す
pizzacat83
0
380
これからAgentCoreを触る方へトレンドはGatewayです
har1101
6
470
Performance Engineering for Everyone
elenatanasoiu
0
250
Featured
See All Featured
The Curious Case for Waylosing
cassininazir
1
420
The agentic SEO stack - context over prompts
schlessera
0
840
What's in a price? How to price your products and services
michaelherold
247
13k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.6k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
280
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.1k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
340
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
250
Testing 201, or: Great Expectations
jmmastey
46
8.2k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
880
WCS-LA-2024
lcolladotor
0
670
Transcript
Mashing up JavaScript @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
http://speakerdeck.com/u/bastianhofmann
Let‘s write a JS App
https://github.com/bashofmann/statusnet_js_mashup_2nd
None
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
Did you like this talk? http://bit.ly/oscon12_js_mashup 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]