cross domain webmashups with jquery and google app engine
DESCRIPTION
An example of how to do a mashup of Google App Engine applications using jQuery and JSONPTRANSCRIPT
![Page 1: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/1.jpg)
Cross Domain Web Mashups with JQuery and Google App Engine
Andy McKay. Clearwind Consultinghttp://clearwind.ca
![Page 2: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/2.jpg)
Also known as
A bunch of cool buzz words to try and describesome of the stuff I’m doing these days
and get me in to talk at cool conferences
![Page 3: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/3.jpg)
Cross Domain JQuery
App Engine
![Page 4: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/4.jpg)
Cross Domain JQuery
App Engine
![Page 5: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/5.jpg)
mashup
“a web page or application that combines data from two or more external online sources”
![Page 6: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/6.jpg)
reusable web applications
![Page 7: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/7.jpg)
that aren't SOAP and WSDL
"The three chief virtues of a programmer are: Laziness, Impatience and Hubris”. Larry Wall
![Page 8: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/8.jpg)
back in time...
![Page 9: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/9.jpg)
Zope 2PloneRails
Django
![Page 10: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/10.jpg)
rewriting things constantly is good for billable hours
![Page 11: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/11.jpg)
small web applicationsreturning xml
![Page 12: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/12.jpg)
browser: rails.site.ca
browser: django.site.ca
server: another.ca
Ajax
![Page 13: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/13.jpg)
there's a problem
![Page 14: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/14.jpg)
Single origin policy
![Page 15: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/15.jpg)
browser: clearwind.ca server: some.other.ca
The same origin policy prevents document or script loaded from one origin from getting or setting properties of a document from a different origin.-- From http://www.mozilla.org/projects/security/components/same-origin.html
![Page 16: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/16.jpg)
1. proxy
browser: clearwind.ca server: clearwind.ca server: some.other.ca
![Page 17: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/17.jpg)
2. hacks
flashiframe
documentscript
![Page 18: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/18.jpg)
3. JSONP
JavaScript Object Notation with Padding
![Page 19: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/19.jpg)
Example: json-time
By Simon Willisonhttp://json-time.appspot.com/
http://github.com/simonw/json-time/tree/master
![Page 20: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/20.jpg)
JSON{ "tz": "America\/Chicago", "hour": 3, "datetime": "Tue, 19 May 2009 03:06:50 -0500", "second": 50, "error": false, "minute": 6}
![Page 21: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/21.jpg)
JSONP
process_time({ "tz": "America\/Chicago", "hour": 3, "datetime": "Tue, 19 May 2009 03:09:09 -0500", "second": 9, "error": false, "minute": 9})
![Page 22: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/22.jpg)
Cross Domain JQuery
App Engine
![Page 23: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/23.jpg)
JQuery for json-time
var url = "http://json-time.appspot.com/timezones.json?"
$.getJSON(url + "callback=?", function (json) { ... });
![Page 24: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/24.jpg)
JSON time demo
![Page 25: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/25.jpg)
$(document).ready(function() { var url = "http://json-time.appspot.com";
function showTime(data) { $.getJSON(url + "/time.json?tz=" + $("#zones").val() + '&callback=?', function (json){ $("#zones-msg").text('The time is now ' + json["datetime"] + '.'); }); }; $.getJSON(url + "/timezones.json?callback=?", function (json) { var zones = $("#zones"); for (var k = 0; k < json.length; k++) { zones.append("<option>" + json[k] + "</option>"); }; zones.bind("change", showTime) });});
Complete JSON time demo
![Page 26: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/26.jpg)
Cross Domain JQuery
App Engine
![Page 27: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/27.jpg)
Easiest deploymentBest scalabilityMinimal effort
![Page 28: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/28.jpg)
Not straight PythonHas it's limitations and quirks
![Page 29: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/29.jpg)
And it's free
![Page 30: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/30.jpg)
Example Mashup
The coolest technology of 2006Google Maps
The most hyped technology of 2009Twitter
![Page 31: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/31.jpg)
Twitter messages with a mapby hash tag eg: #owv2009
![Page 32: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/32.jpg)
Step 1: Assign hash tag to location
![Page 33: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/33.jpg)
geohashtag.appspot.com
browser: geohashtag.appspot.com server: geohashtag.appspot.com
![Page 34: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/34.jpg)
from google.appengine.ext import db
class Tag(db.Model): name = db.StringProperty(required=True) geostring = db.StringProperty(required=True)
Model
![Page 35: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/35.jpg)
You cannot do an inequality test on two fields in one query. Or use GeoPt.
GeoHash solves this problem:http://en.wikipedia.org/wiki/Geohash
Issue
![Page 36: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/36.jpg)
tag.json (returns location for a tag)bounds.json (returns all the tags in a rectangle)
JSON
![Page 37: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/37.jpg)
Geohashtag demo
![Page 38: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/38.jpg)
Step 2: Parse RSS into JSONP
![Page 39: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/39.jpg)
atomtojsonp.appspot.com
browser: atomtojsonp.appspot.com server: search.twitter.com
server: atomtojsonp.appspot.com
![Page 40: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/40.jpg)
Because twitter doesn't have JSON exportOther services like Google RSS or Yahoo YQL have
problems
But checkout: http://developer.yahoo.com/yql/ and http://code.google.com/apis/ajaxfeeds/
Proxy?
![Page 41: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/41.jpg)
No Model
Quite common for App Engine
![Page 42: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/42.jpg)
class JSONHandler(webapp.RequestHandler): def get(self): url = self.request.get("url") data = feedparser.parse(url) if self.request.get("callback"): data = "%s(%s)" % (self.request.get("callback"), data) self.response.out.write(data)
Just feedparserhttp://www.feedparser.org/
![Page 43: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/43.jpg)
twitter.json (smaller twitter version for a search term)atom.json (a whole atom file for a url)
JSON
![Page 44: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/44.jpg)
Atomtwojsonp demo
![Page 45: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/45.jpg)
Step 3: Mash it up
![Page 46: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/46.jpg)
geojsontweet.appspot.com
browser: geojsontweet.appspot.com server: maps.google.com
browser: geojsontweet.appspot.com
![Page 47: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/47.jpg)
browser: geojsontweet.appspot.com server: geohashtag.appspot.com
browser: geojsontweet.appspot.com server: maps.google.com
browser: geojsontweet.appspot.com
geojsontweet.appspot.com
![Page 48: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/48.jpg)
browser: geojsontweet.appspot.com server: geohashtag.appspot.com
server: search.twitter.com
server: atomtojsonp.appspot.com
browser: geojsontweet.appspot.com server: maps.google.com
browser: geojsontweet.appspot.com
geojsontweet.appspot.com
![Page 49: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/49.jpg)
No ModelIn fact, completely static HTML
(with JS, no server side code)
![Page 50: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/50.jpg)
function move() { var bounds = map.getBounds(); var sw = bounds.getSouthWest(); var ne = bounds.getNorthEast(); var url = map_details.tags_domain + '/bounds.json?nelat='; url += ne.lat() + '&nelon=' + ne.lng(); url += '&swlon=' + sw.lng() + '&swlat=' + sw.lat() + '&callback=?' if (map_details.last_url != url) { map_details.last_url = url $.getJSON(url, function(json) { if (json) { for (var k = 0; k < json.length; k++) { ...
Some Javascript
![Page 51: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/51.jpg)
function twitter() { var tag = null; for (var obj in tags) { var url = map_details.atom_domain + '/twitter.json?tag=' + obj + '&callback=?' $.getJSON(url, function(json) { var tweet = null; for (var k = 0; k < json.length; k++) { ....
Some more Javascript
![Page 52: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/52.jpg)
$("#tweets-" + tweet["tag"]).parent().scrollable({ interval: 4000, loop: true, speed: 600, onBeforeSeek: function() { this.getItems().fadeTo(300, 0.2); }, onSeek: function() { this.getItems().fadeTo(300, 1); }});
Slideshowhttp://flowplayer.org/tools/scrollable.html
![Page 53: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/53.jpg)
Geojsontweet demo
![Page 54: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/54.jpg)
Serious issues
![Page 55: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/55.jpg)
TrustYou are executing someone else's JavaScript
in your site. Better be trustworthy.
![Page 56: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/56.jpg)
Single points of failure?
![Page 57: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/57.jpg)
Single points of failure?
![Page 58: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/58.jpg)
EnterpriseInternal servers?
![Page 59: Cross Domain WebMashups with JQuery and Google App Engine](https://reader030.vdocuments.us/reader030/viewer/2022013101/555a2f07d8b42a900d8b4e94/html5/thumbnails/59.jpg)