In just over an hour with no prior experience, I created a mashup using Microsoft's Popfly application to allow WalkJogRun visitors to enter their username to see an overview of their running routes plotted on Microsoft's Virtual Earth. Next, through the magic of the Popfly Facebook plug-in, I can share my new application with all my Facebook friends.
I learned about Popfly just over an hour ago when my wife was reading the New York Times and asked me if I had heard of it. From her description it sounded like a Yahoo Pipes wannabe so my initial reaction was lukewarm. As I kept reading my Michael Crichton novel, my brain kept spinning so I finished the chapter and turned on my laptop to play around. Within minutes I had mashed up my geo-tagged Flickr photos with Virtual Earth and so I looked at the Yahoo code block to see what kind of magic was occurring.
The blocks can all be inspected and there are two important pieces:
- Block Description: this XML document describes your application and defines the functions in terms of inputs, outputs and any custom object definitions.
- Block Code: this is JavaScript code and implements your methods
In my case I used the Yahoo Flickr code as a starter since it has a "getUserPhotos" method very similar to an existing function at WalkJogRun called getUserRoutes. After three or four attempts I was able to remove any unnecessary code from the other functions used by the Flickr block, and had a working block that would retrieve the XML from my site and generate an RSS feed of routes by user.
Here is my block description
<?xml version="1.0" encoding="utf-8"?>
<block xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.popfly.com/schemas/blockschema.xsd"
class="WalkJogRunClass">
<providerName>walkjogrun</providerName>
<providerUrl>http://www.walkjogrun.net/</providerUrl>
<providerLogoUrl>/images/wjrlogo_tag.gif</providerLogoUrl>
<blockIconUrl>/images/tshirt_pocket_6x6.png</blockIconUrl>
<suggest output="geodisplay" input="userinput"/>
<operations>
<operation name="getUserRoutes" callMode="auto">
<description>Get user routes.</description>
<inputs>
<input name="userName" required="true" type="string">
<description>username</description>
<defaultValue>Earnshavian</defaultValue>
<constraints />
</input>
</inputs>
<outputs>
<output isArray="true" type="custom" object="Route" />
</outputs>
</operation>
</operations>
<objects>
<object name="Route">
<field name="Route Number" type="rn" isArray="false" />
<field name="latitude" type="latitude" isArray="false" />
<field name="longitude" type="longitude" isArray="false" />
<field name="pintext" type="pintext" isArray="false" />
<field name="Description" type="desc" isArray="false" />
<field name="Long Description" type="longdesc" isArray="false" />
<field name="Distance (m)" type="dist" isArray="false" />
<field name="Distance (km)" type="distkm" isArray="false" />
<field name="Owner" type="submit_by" isArray="false" />
<field name="Route ID" type="rid" isArray="false" />
<field name="Elevation string" type="elev8ngraph" isArray="false" />
<field name="Severity" type="severity" isArray="false" />
<field name="isPrivate" type="prv" isArray="false" />
<field name="Create Date" type="c_dt" isArray="false" />
</object>
</objects>
</block>
and here is my block code
function WalkJogRunClass() {
}
WalkJogRunClass.prototype.getUserRoutes = function(userName, number) {
// Retrieves a user's routes.
//
// userName (required): WalkJogRun user name
// get userid
var params = "&userid=" + escape(userName);
var routes = this._getWalkJogRunRoutes(params);
return routes;
};
WalkJogRunClass.prototype._getWalkJogRunRoutes = function(extraParams)
{
var root = this._getWalkJogRunXml(extraParams);
var routes = this._getRouteArrayFromXml(root);
return routes;
};
WalkJogRunClass.prototype._getWalkJogRunXml = function(params)
{
var root = environment.getXml("http://www.walkjogrun.net/functions/act_getRoutes.cfm?1=1"+ params, "walkjogrun");
var rsp = root.getElementsByTagName("markers")[0];
if(rsp == 'undefined')
{
var errMsg = "walkjogrun returned an unknown error";
throw errMsg;
}
return root;
};
WalkJogRunClass.prototype._getRouteArrayFromXml = function(root)
{
var routeArray = new Array();
var routes = root.getElementsByTagName("marker");
var count = routes.length;
for(var i = 0; i < count; i++)
{
var route = routes[i];
var rn = route.getAttribute("rn");
var lat = route.getAttribute("lat");
var lng = route.getAttribute("lng");
var desc = route.getAttribute("desc");
var longdesc = route.getAttribute("longdesc");
var dist = route.getAttribute("dist");
var distkm = route.getAttribute("distkm");
var submit_by = route.getAttribute("submit_by");
var rid = route.getAttribute("rid");
var elev8ngraph = route.getAttribute("elev8ngraph");
var severity = route.getAttribute("severity");
var prv = route.getAttribute("prv");
var c_dt = route.getAttribute("c_dt");
routeArray.push(new Route(rn,lat,lng,desc,longdesc,dist,distkm,submit_by,rid,elev8ngraph,severity,prv,c_dt));
}
return routeArray;
};
function Route(rn,lat,lng,desc,longdesc,dist,distkm,submit_by,rid,elev8ngraph,severity,prv,c_dt)
{
this.rn = rn;
this.latitude = lat;
this.longitude = lng;
this.desc = desc;
this.longdesc = longdesc;
this.dist = dist;
this.distkm = distkm;
this.submit_by = submit_by;
this.rid = rid;
this.elev8ngraph = elev8ngraph;
this.severity = severity;
this.prv = prv;
this.c_dt = c_dt;
this.toString = function()
{
return "<a href='http://www.walkjogrun.net/index.cfm?rid="+this.rid+"'>" + environment.escapeQuotes(this.desc) + "</a><br />"+
"Description: " + environment.escapeQuotes(this.longdesc) + "<br />"+
"Distance: "+ environment.escapeQuotes(this.dist) + " miles /" + environment.escapeQuotes(this.distkm)+" km<br />"+
"Created By: " + environment.escapeQuotes(this.submit_by) + "<br />"+
"Create Date: " + environment.escapeQuotes(this.c_dt) + "<br />";
}
this.pintext = this.toString();
}
Next I added the Virtual Earth application to a Popfly mashup page along with my WalkJogRun block and connected them so the geoRSS pumps into Virtual Earth's addPushpin method. Some case issues were causing some trouble initially but after a couple of attempts, my block was publishing the format required for auto-discovery of inputs for Virtual Earth and I could run the application.
WalkJogRun User Contributed Route Viewer mashup
To my surprise, it asked me where I would like to share my new mashup including the option to share on Facebook or add it to my profile. By adding it to my profile it added the Popfly application to my profile so that my mashups are now shared. Best of all, it gave me the ability to share my embedded Facebook app with my friends.
Process Overview
So the overview of the whole process is as follows:
- Login to Popfly
- Create a block by editing the block description and block code or modifying an existing app with similar functions
- Save and publish the block
- Create a mashup by adding your block and any other components
- Save and publish the mashup
- Publish it to your Facebook profile
SummaryThat took just over an hour for me since I already had a page generating XML based on URL parameters. I'm planning to add more functions to my block soon too but for now, that's a great start.
How does Microsoft Popfly compare to Yahoo Pipes?
It's a completely different beast. Yahoo Pipes for me offered great promise but without adding too much value - just a way to repurpose and aggregate multiple RSS feeds. Microsoft Popfly goes much further in adding end points to the feeds with visualization tools and the ability to share your applications more widely than I had imagined. It's certainly worth an hour of ANY programmer's time.