Meetup provides an API for accessing streams of real-time data about its service which can be fun to play with. In this post, we’re going to consume one of those streams via their javascript interface and mash up event registrations with a google map. When it’s complete, the end result is going to look something like this handy little animated gif we created:
As people RSVP to meetup events around the world, we receive the stream of RSVP’s and display them on the map in the appropriate location. Depending on the time of day, it’s fun to watch and see what parts of the world are awake and RSVP’ing to events.
Is this super useful? Maybe not, but it lets us look at how the Meetup API uses WebSockets, so just come along for the ride.
You can get all the code for this example here: https://github.com/agilityfeat/meetup-streaming
To start, create an index.html file that looks like the following. You’ll notice it’s pretty simple – we’re just putting a div in place for google’s map canvas, and then referencing some javascript files:
Underneath the map div, we’re linking to a few javascript files that provide the real work. First, we’re just including a jquery library, and then the google maps api.
Must.js is an important file provided by Meetup, which refers to “Meet Up STreaming”. It’s part of the Meetup API, and the must.js project provides a nice interface to the streaming API from Meetup.
The simplest way to get a copy of just this file is to go directly to the GitHub project for must. But you should use bower instead, which is a handy tool created by Twitter for managing any front end dependencies that your project might have, like third party javascript applications such as must.js. Once you have bower installed, you can get must.js by running this from your project:
bower install must
If you take a look inside the must.js file, you’ll notice wrappers for a variety of streaming API’s: event RSVP’s, comments, check-ins, and photos. We’re just going to use the RSVP’s endpoint in this example, but you can extend our example to also display comments from users about events, check-in’s at events, or display photos as they are uploaded to Meetup in real-time.
Here is the relevant part of must.js for event RSVP’s:
Our code will need to pass a callback method to must.js so that they know where to send rsvp objects as they come in. Must.js itself is just making a call to the root webservice for streaming rsvps, and passing them back to our callback method.
By default must.js is doing this using WebSockets so that it is done in an efficient socket model, but if your browser doesn’t support WebSockets, then must.js will automatically fall back to a less efficient long polling method. Must.js checks to see if you can support WebSockets here:
Assuming that you can in fact support WebSockets, then the must.js code is going to drop down to this chunk of code for receiving call back events from the meetup API:
In this code snippet, the .onmessage event is fired whenever there is data to process from Meetup, and then the must.js code above will parse the JSON data returned, and as long as there are no errors, it calls a local method handleJson which will basically just pass the json data (now stored in the variable “ary”) along to our callback method.
Now that we see how must.js works, let’s look at calling it ourselves. Back in our index.html file, the last javascript we are including is our own:
js/meetupmashup/app.js
You can see the complete file here, but let’s look at just a few key code snippets.
At the very bottom of the file, the first javascript that is executed is this statement:
geo_code_app.init();
This calls to the init method, just above, where we see the two key actions that happen on page load:
In the init() function, we are referencing a local object we created called geo_code_app, which is at the top of the javascript file and is where we store our key methods. The first thing we do is call the load_map function, which does pretty standard initialization of the google maps api so we get a full world map displayed on our page. We won’t explain that here, but you can see the code in the app.js file (link to file in repository)
Below the call to the map initialization, is this statement:
This is the call we make to tell must.js to stream all rsvp callbacks to our method display_rsvp(). Display_rsvp lives in our app.js file, and let’s look at the full method here:
This method will be called once for each rsvp that comes in from the Meetup streaming api. An object named “rsvp” will be passed into our method, and that object from Meetup contains information about the group name for the rsvp, the name of the meetup member who registered, the date and time of the meetup event, venue name, and more. We take all that information and throw it into a few div tags for display as a marker on the map.
The rsvp.venue object also contains latitude and longitude for the venue, which is obviously crucial for the google maps Marker object that we’re going to create on the map. Once the Marker and the associated InfoWindow are created, we call the google maps method to open those.
We’re dealing with real-time data from a very popular website, and so our map would fill up with markers if we didn’t close them down automatically. The last part of the display_rsvp method sets a timeout function on the Marker and InfoWindow so that they are removed from the map after a second to make space for the next set of RSVP’s coming in from Meetup.
This all makes for a fun and relatively simple way to see the power of WebSockets and real-time data streams. What free and publicly available data streams do you want to see us build an example with? Contact me at Arin@AgilityFeat.com and let me know, maybe we’ll use it as the basis of a future blog post.
You can see a live version of this example up at RealTimeWeb.co/geocode, and you can learn more about building real-time web applications in our book at RealTimeWeb.co. In this book, our team shows you how to use publish/subscribe networks and WebRTC to build real-time web applications that involve video, audio, and data applications.
Many thanks go to Allan Naranjo for his work on this example. Allan is a developer at AgilityFeat and lead developer on the example application for our RealTimeWeb.co book.