In our previous post, we looked at how to setup a Node.js development environment on a Mac. In this post, we’ll write some minimal code to get a functional web-site going, and get ready to style it up and push it out to someplace useful.
It seems many Node.js projects have a main file named “index.js”, so I chose that convention for mine as well. My index.js file is below. Read through the code first. We’ll discuss it in detail below.
The first things to notice are the “var xxx = requre(“something”);” lines at the top. Node.js uses something called a module loader to load in modules (which in Node.js are just other *.js files). It uses this mechanism to decide what depends on what, in a fashion (to me, at least) that seems reminiscent of the AMD API in RequireJS or even the IoC pattern in type-safe languages.
For us, we require express and socket.io, which we talked about in the previous post. The third requirement, something called “targetprocess”, is just another js file that I wrote that encapsulates access to the Target Process REST API.
Second is a line that tells the express application variable to listen on port 8080. This is a good practice for dev macines where something else, such as a web server, might normally be listening on the usual port 80. After that are a couple of routing calls. These calls tell the routing functionality in express to route all requests for the root web site to a page called “index.html”, and all requests to the root index.css file to a similarly named file in the directory requested.
Next is a variable to hold the names of all users currently connected to the system, and a call to the targetprocess.js component to set the username/password combination for the Target Process (it uses basic authentication) and the URL to its API.
Then come the Socket.IO calls. Socket.IO contains libraries for both server and client-side functionality. Without going through every line in detail, here is a brief summary of the methods that I use…
- socket.emit – sends a “message” (I would think of it as creating an “event” to which the client html page can respond) to the client represented by “socket”
- io.sockets.emit – sends a message to all clients connected to the application (including the one represented by “socket”)
- socket.broadcast.emit – exactly like io.sockets.emit, except that the client represented by “socket” does not receive the message. In other words, this sends a message to everyone except “yourself”.
Documentation is pretty limited on the main Socket.IO site, but check out the links provided in the answer here for more information.
Here in index.js, we are handling various messages. Again, without going line-by-line, below is a list of each with a rough description of purpose…
- connection – This is a built-in message that triggers whenever a client connects. All further code goes in the handler for this message, and the “socket” argument is used to send messages back to that client.
- adduser – Triggers when a client sends its username to the server, shortly after connecting
- updateaudit – A message sent from the server to the client whenever the server has some interesting information that should be displayed in an “Audit” or “Recent Activity” area of the client web page
- updateusers – A message sent from the server to the client when the user list has been modified
- changeactiveitem – Triggers when a client clicks on a particular item (user story or bug) on the web page to indicate that a new item is currently being demonstrated.
- activeitemchanged – A message sent from the server to all clients to indicate that the currently active item has changed
- disconnect – Another built-in message that triggers when the client represented by “socket” disconnects
Next we see the initial connection being made to the root of the web site, followed by a bunch of message handlers. Here is a rough list of descriptions of each…
- connect – Built-in message for initial connection. The handler here sends back the “adduser” message along with the user’s name
- updateaudit – Listens for audit messages from the server, and lists them out on the web page, in reverse chronological order
- updateusers – Listens for messages from the server indicating that the user list has changed, and re-renders it to the web page
- entitiesretrieved – Listens for the message from the server with teh same name, and renders the list to the web page. Also wires up a handler that will send a message to the server to change the active item in the list whenever the user clicks on one in the web page.
- activeitemchanged – Responds to the message from the server by adding a highlight to the currently active item, and removing the highlight from all other items.
Oh, the Humanity!: An “Issue” With Underscore
One thing to note here is that as I was working with Underscore, I kept getting an error related to an equals sign being invalid. After much fighting, it turns out that whenever you reference a variable or object property inside your template, you ABSOLUTELY MUST put a space between the equals sign and the variable or object property.
i.e. “<%= name %>” works, “<% =name %>” does not
The targetprocess.js file, as discussed above, is simply a wrapper for calling into the Target Process REST API. Let’s look at the code…
Other than that, the only action method available is “getEntitiesForActiveIteration”. This method retrieves all UserStory and Bug objects from Target Process that were completed in an iteration ending on a specific date. Right now, this specific date is hard-coded, but I hope to get that calculated or passed in later, which should be easy enough. For more details on how to form these HTTPGet queries to retrieve Target Process objects, see the Target Process REST API.
One final thing to note is the line at the very bottom of the code file. Whenever a Node.js module is written, you must declare which methods, if any, will be exposed publicly to the modules that use your module. In our case, only the “api” method is exposed publicly.
Oh, the Humanity!: An “Issue” With The Target Process REST API
On my first few attempts, I kept getting a message back from Restler saying that it couldn’t parse the JSON coming back from Target Process because the less-than sign (<) was an invalid character. At first, I thought that this was caused by the fact that we sometimes put HTML into the comments or descriptions of our Bug and UserStory objects. But I narrowed the query to only select one item, and the issue persisted. As it turns out, I had a bad query that I hadn’t tested in the browser, and Target Process was giving an error message back in the form of an HTML response. Apparently when errors occur, they appear in the form of HTML-formatted responses, even if you ask for JSON in the request URL.
Last (and probably least) is index.css. As of now I have only some minimal formatting, just to make sure that the highlight of the active item shows up, and that my lists aren’t blindingly ugly. Code is as follows…
Testing the App
To test the app, fire up bash (Terminal Window on a Mac), navigate to the path where index.js exists, and type “node index.js”.
Then fire up a couple of instances of your favorite web browser (they need not be on the same computer, just able to see the web site – I used my Windows computer), type your username on each…
…and then start clicking on items in the list.
Clicking on an item in one browser will make that item highlight in every browser that is connected.
Next time, we’ll add some styling to improve the look of the application, and (hopefully) get it running in a real website somewhere (like hieroku).