Jul 222014
 

CODE | SLIDES

What Did I Just Watch in That Video?

That video was the culmination of me experimenting with a Spark Core device, the Johnny Five library, a Sphero toy, and the Cylon.js library (along with some other JavaScripty stuff).

Here’s what is really going on in the video…

My computer is running a Node.JS application of my own creation called owLED (available on GitHub).

Connected to my computer is a Spark Core device (basically a wireless Arduino). Attached to the Spark Core are 2 LED lights – one red, one greenish-white – and a pushbutton, all connected with some wires via a breadboard. See the amateurish image below for something that resembles what I put together.

owLED_bb

The owLED Node.JS application does a few things…

1. Serves a page with a picture of an owl at http://localhost:3000
2. Creates a Socket.IO connection between the browser and the Node app
3. Loads a Johnny-Five module that blinks the LED lights when the button is pushed, then emits an event when the blinking is complete (along with the on/off status of each LED).
4. Loads a Cylon.js module to connect to Sphero. The module exposes a function to change Sphero’s color, and roll Sphero ‘forward’ a short distance.

With all these pieces working in concert, we have a (crappy) little game! When I push the button on the Spark Core, the LED lights blink randomly for a couple seconds then stop. The LEDs can be either on or off when the blinking sequence ends.

Meanwhile, in the browser, players try to guess if the LEDs will be on or off when the blinking ends. They do this by turning the Owl eyes ‘on’ or ‘off’. If the owl eyes match the LEDs, a point is scored. If a point is scored (by any player) Sphero rolls forward!

owledpic

Why Did You Do This?

I went to JSConf US this year (2014) and got a Spark Core device in my swag bag. We also spent a whole day playing around with NodeBots (I did the NodeRockets track)! In the spirit of community and learning and what-not, I decided to demo some of the cool stuff I learned about to the local Memphis Tech community at a Meetup event. The OwLED Guessing Game was what I came up with. It demo’d some cool JS libraries, and took advantage of what hardware I had available.

The presentation was on July 17th, 2014 and kinda flopped. Despite tons of preparation and ensuring that everything would work right, it didn’t. I only had a 15 minute speaking slot, and the Arduino I was using refused to blink during the live demo. It worked just fine an hour earlier, and of course, still works fine now, but alas. Murphy’s law was in full effect.

I Want to Try, But Don’t Have a Spark Core or Sphero…

No worries. The OWL portion can work on its own with the ‘owled-fake.js’ module swapped out for the ‘owled.js’ module. The Sphero code is on a separate branch from master in the GitHub repo. Take a look at the instructions in the README.

Also, there is alternate code in the ‘owled.js’ module for a regular Arduino Uno. A hastily drawn diagram is below…

ArduinoOWLED_bb

Anything Else?

Here’s all the things I used in a big list!

  • Node.JS – Acts as the ‘hub’
  • Express – Serves the web page
  • Socket.IO – Allows events to be ‘emmitted’ between the browser and the server in real-time.
  • AngularJS – A nice front-end framework to build the client-side functionality.
  • Redis – Used to keep track of all the blinking outcomes (click the ☰ icon in the browser).
  • Spark Core – The original hardware device used.
  • VoodooSpark Firmware – The firmware used on the Spark Core.
  • Johnny Five – The Node.JS lib to interact with Arduinos.
  • Spark-IO Node Package – Spark Core adapter for Johnny Five.
  • Sphero – A remote controlled, programmable, wireless sphere.
  • Cylon.js – A pretty badass project for controlling hardware with JavaScript.
  • Cylon-Sphero – A Cylon adapter to control Sphero.
  • Fritzing – Used to draw the Arduino diagrams.
  • NodeBots – For inspiration.
Dec 092013
 

Presentation Codepen: http://codepen.io/ericterpstra/pen/DHbaK
Original Codepen by Lucas Bebber: http://codepen.io/lbebber/pen/xrwja

Check out this Pen!

Background-clip: text

Divya Manian – Using Background Clip for Text With CSS Fallback.
Codrops – Experiments With Background-Clip: Text

RGBa

MDN – <color>
CSS-Tricks – RGBa Browser Support
Devoth’s HEX 2 RBGA Color Calculator

Text-Shadow

Mozilla Developer Network – Text-Shadow
CSS Tricks – CSS Text Shadow

CSS3 Animation

Smashing Magazine – The Guide To CSS Animation: Principles and Examples
MDN – Using CSS Animations
Justin Aguilar – CSS3 Animation Cheat Sheet
CSS3 Maker – CSS 3.0 Animation
CSS Animate (Visual animation timeline editor) Beta.

CSS3 @keyframe syntax

MDN – @keyframes
CSS-Tricks – Keyframe Animation Syntax
Smashing Magazine – An Introduction To CSS3 Keyframe Animations

Nov 222013
 

jenian

Play Game | View Code

In July of 2013, my sister-in-law, Jen, got married. To celebrate the occasion, I thought it best to create another family oriented game to commemorate the occasion. Jen and her husband-to-be are well known smarty-pantses, so I figured a quiz game would be highly appropriate. It also gave me a chance to brush up on my responsive CSS, and put my first (and only) jQuery plugin – jQuery VintageTxt – to the test.

The result was fairly successful. The interface is just a vanilla vintageTxt window with a row of buttons below. A smattering of media queries resizes the window and buttons and adjusts the font size. The brushed metal buttons are styled with CSS3 and derived from Simurai’s codepen sample. The game logic basically stemmed from stringing together functions with the onEnterKey or onFinishedTyping callbacks in the vintageTxt plugin, or click handler callbacks from one of the four action buttons. The game logic is pretty much all in aystjai/js/main.js and the data for the questions are stored as vars in aystjai/js/questions.js.

At one point, I had all the question data loaded into Parse.com and was loading it all in via the Parse SDK. I can’t quite recall why I decided to pull everything offline. I still ended up using Parse.com to store high score data (viewable here). The Footable library is used to display the high score data in a nice, responsive table. Everything ended up looking pretty nice on phones and tablets. It was pretty fun to show off at various points throughout the wedding weekend.

Hats of to Jen and Ian as well!

Nov 042013
 

Intro – Just a Blogging Platform

Ghost is a new platform just for blogging. Think WordPress, but simpler and without the expectation that you can use it for a website, ecommerce, photo gallery, or generic CMS. The focus is completely on writing and publishing long form articles.

Ghost was actually conceived as a WordPress plugin to restructure the entire interface to focus only on writing and publishing, but the limitations were too great and a new platform was created from scratch. The new platform has simplicity and focus at its core.

It’s Easy

There are quite a few new tools out there for creating blogs that are free and feature rich, but often can be difficult to set up and use. Ghost is meant for hackers and ‘non-techies’ alike.

It’s Simple

Other blogging platforms attempt to give you every option under the sun. The core focus of Ghost will always be on blogging, not providing a ‘platform for the web’. Not trying to bash WordPress at all, just stating that Ghost has different goals.

“Feature rich” is great if it’s what you need, or if you are doing more than just writing and publishing, but can be overkill/overwhelming/confusing if not.

It’s Open Source

Ghost is an open source project and MIT licensed. You can fork it and create your own blogging platform project, or integrate it into your open source CRM.

It’s Non Profit

Honestly, this is probably one of the most intriguing aspects of the Ghost project. The Ghost Foundation was formed after a very successful Kickstarter campaign which raised over $300,000.

The Ghost Foundation will be the umbrella organization that promotes the continuing development of Ghost, and also runs the Ghost hosted service. All proceeds from the hosted platform go back to funding Ghost development, growing the hosting service, and growing the Ghost ecosystem and community.

Built on NodeJS

Where WordPress, Drupal and Joomla are all PHP based, Ghost is an app built completely with Javascript. This is very interesting from a technical standpoint, but the takeaway is that Ghost is attempting to future-proof itself by using JavaScript. JS has been around for 18 years, and is only getting more and more popular.

This has all sorts of wonderful and magnificent implications for developers, but creates a slight problem for regular folks who just want to write…

Ghost Hosting

Hosting is a bit of an issue right now. You can’t call Godaddy or HostGator and get a 1-click install for Ghost, like you can with PHP software. the Ghost Foundation is remedying this by offering their own hosting service which is currently in private beta (I have a site, it works just fine).

Other hosting companies have created their own options as well. They won’t be quite as easy as Ghost.org, but may offer some incentives depending on your needs.

Extending Ghost

Right now, Ghost has a pretty decent theme system that allows you to customize the layout and style of your blog. There are already a bunch of pre-made themes in the Ghost marketplace. Also, a few Ghost theme sites have popped up as well (including my own!).

The Future of Ghost

There is a new release coming out soon which adds tons of new features, and another release is planned for late December / early January. the Roadmap and progress is listed on the GitHub wiki.

Resources

The official Ghost forum is the best place to go for help. There are also other sites dedicated to installation and hosting, as well as themes and configuration. Of course, please feel free to ask me as well.

Aug 082013
 

SlideshowShot

Slideshow | Code

Memphis flies under the radar as a technology hub, but there’s still a pretty active community of developers and other technologists that like to meet up and do stuff. I occasionally pop in on the PHP User Group, Ruby User Group, and Python User Group meetups when I get the chance. Every few months, the various user groups organize a joint meetup called the Super User Group Meetup and feature presentations on platform agnostic topics such as development tools, front-end development, processes, and whwatever else people want to talk about.

For the most recent meetup on June 20, 2013, I threw my name in the ring as a presenter and gave a talk about the what, where and how of HTML5 games. It’s nothing terribly complex or in-depth, just a brief survey of the general idea of developing games for the web using web based standards.

This was the first time I’d used the Reveal.js slideshow library. It was a pretty positive experience, especially with the help of slid.es to get started. Embedding live javascript is pretty boss. Also, there are a lot of great plugins, and I definitely took advantage of the ‘notes server’ so I could display the slides on once screen, and my notes on another. I’ll be using Reveal again in the future.

Jun 062013
 

This is no joke. I just made about $1.50 running from Zombies – and more is on the way (both cash and zombies).

Ok, the zombies are not real, but the money is. Thanks to three simple mobile apps, every time I go for a 30 minute jog, I get chased by simulated zombies, and then earn my way toward a weekly reward. The app trifecta in question contains the following:

  1. RunKeeper: The Granddaddy of running apps
  2. GymPact: Get rewarded to excersice, and penalized when you don’t
  3. Zombies, Run!: Immerse yourself in undead while you work out

The setup is simple, all you need is an iPhone or and Android device with GPS, and an internet connection. Then get signed up for three apps, and their accompanying web services, and start your engines.

Step 1: Get RunKeeper

runkeeperFirst, get RunKeeper – an app that tracks your outdoor workouts using the GPS built into most smartphones. Go to Runkeeper.com and sign up for an account. It’s free. Then go to the Apple App Store or the Google Play Store and download the RunKeeper app (also free). Open up RunKeeper on your phone and sign in to the app with the account you created online.

There are tons of options and lots of interesting features and services in RunKeeper, but I won’t get into those here. For now, all that is needed is a free account.

Step 2: Create A Gym-Pact

gympactNext, download GymPact from the App Store or Google Play. GymPact is a pretty amazing service that will penalize you for not working out. You set a goal of a certain number of workouts per week, and post a dollar amount that you are willing to risk if you do not meet that goal. Miss the goal, pay the money. Complete the goal, and split the penalty funds collected from the non-achievers with all the other winners. It works, and I’ve been using it off and on for a year now. Sign up for an account through the app itself or on GymPact.com.

Once the GymPact app is installed, you need to link it with your RunKeeper account. In the app, tap the Settings icon (the little gear) and scroll down to the RunKeeper menu entry under My Account. Tap the button to connect your accounts. Check the GymPact website for more information.

Don’t forget to set up a pact! The minimum pact is one workout per week, with a $5 penalty per workout. I’ve got mine set up for 2 workouts per week, with a $10 penalty. It earns my about $1.50 (give or take $.25) per week. Increasing the number of workouts will increase the payout. Be sure to set the penalty high enough that it stings pretty hard when you miss a workout and get fined.

Step 3: Run! From Zombies!

zombiesrunlogoFinally, head over to the Zombies, Run! website and register for a ZombieLink account (free). Zombies, Run! is a game for iOS and Android that you play while jogging. It’s basically an interactive story that plays through your headphones while you run. Every so often, your character in the story will be chased by zombies, and you’ll need to pick up the pace OR DIE!!! It’s good.

Once you’ve logged in to ZombieLink and poked around a bit, click your user name (upper right corner) and go to Settings. Click the Sharing to other networks tab on the right, and connect your RunKeeper account. Then set Auto post new runs to RunKeeper to true and remember to hit Save (it’s easy to miss this part).

Zombiesrun

Finally, go back to the App Store / Google Play and download Zombies, Run! ($3.99). There is also a 5K training version for $1.99, but I have not tested that app yet. So far, this is the only app that will cost you money up front, and if you meet your goals set in Gympact, you will earn the cost of the app back in a couple weeks.

That’s it for the setup. most of these apps will ask you if they can access your location and send you notifications. It’s important to say ‘yes’ to all of these. That way your runs/walks/jogs can be tracked properly, and you will get notified when your workouts are posted to RunKeeper, and then sync’d to GymPact.

All that’s left is to put on some running shoes, start up the Zombies, Run! app and do the first mission. Remember, in order for the workout to count, it needs to last 30 minutes or more. If you finish your Zombie mission early, just keep running until the timer reaches 30:00 or later, then stop the mission. Once the mission is complete, it should automatically post the data to RunKeeper. After a few hours, it should then sync from RunKeeper to GymPact. You do not need to have the RunKeeper or GymPact apps open while using Zombies, Run!. Or, if you prefer a zombieless run, open RunKeeper and start a workout through the app and go from there. Keep it up, and watch the river of pennies fill your GymPact account, all while saving the world from flesh eating corpses.

Here's a summary of one of me walking around my neighborhood, and jogging when zombies approach.

Here’s a summary of one of me walking around my neighborhood, and jogging when zombies approach.

Jun 032013
 

Game in Action

DEMO | CODE

Getting started with TypeScript and Phaser on OSX and Ubuntu has been a tricky proposition. My requirements for a development environment were as follows:

  • Use TypeScript as the primary language
  • Break the project into small files – preferably one module or class per file
  • Have all the benefits of TypeScript utilized by my IDE, namely code completion, error checking, and documentation for function signatures
  • File watchers that generate javascript and source maps on file save
  • Live debugging of TypeScript files

Thanks to the latest WebStorm (6.0.2 v129.541 as of this writing), Require.js, and Chrome DevTools, I have a great development environment set up to create Phaser games on OSX and Linux. Here’s how I did it:

First, grab the starter project from my GitHub account (thanks to Jesse Freeman for the inspiration).

git clone git@github.com:ericterpstra/phaser-webstorm-template.git

Then get the following four files from the Phaser ‘build’ folder:

  • phaser.js or phaser.min.js
  • phaser.d.ts
  • phaser-fx.js or phaser-fx.min.js
  • phaser-fx.d.ts

Copy those files to /phaser-webstorm-template/lib/

Then download require.js and put it in the same lib folder.

The contents of the lib folder

The contents of the lib folder

Now start WebStorm 6 (get the EAP version here). Close the existing project if it is open, and go to the welcome screen. Choose Create New Project from Existing Files. Then choose Source files are in a local directory, no Web server is yet configured and click Next.

A file selection window should appear. Find the phaser-webstorm-template folder, select it, and click the Project Root button. Then click Finish.

Find the phaser folder and make it the project root.

Find the phaser folder and make it the project root.

When the project finishes loading, open game/game.ts. After a few seconds, WebStorm should prompt you to add a ‘TypeScript’ file watcher. Click the Add Watcher link.

Click 'Add Watcher' when prompted.

Click ‘Add Watcher’ when prompted.

Once the watcher is added, go the the Webstorm menu (File menu in Linux) and open Preferences…. Click File Watchers under the Project Settings section, and double click the TypeScript entry. When the Edit Watcher window appears, add the following text to the Arguments: field:

 --target es5 --module amd
Edit the File Watcher settings.

Edit the File Watcher settings.

Click OK and return to the code editor. Open game/objects/Player.ts and also game/game.ts if it is not open already. Manually save both files to trigger the file watcher and regenerate the javascript and source map for each file. If this was successfull, the .js and .js.map files will appear underneath their respective .ts files, and can be viewed by clicking the expand arrow (see screenshot below).

Files

You should now be able to use WebStorm and have lots of assistance for TypeScript. Code completion, method signatures, documentation, error reporting, and all the other benefits of WebStorm should now be available.

Code hinting should be working in .ts files.

Code hinting should be working in .ts files.

For live debugging of code, open Google Chrome and point it to http://localhost:63342/phaser-webstorm-template/index.html and open the Chrome DevTools (Cmd-Alt-i on OSX, F12 on Linux). Click the Settings button (the little gear icon in the bottom-right corner of the DevTools window). Check the box next to Enable source maps in the General section.

Enable source maps.

Enable source maps.

Now, from the Sources tab, you should be able to open the Player.ts and game.ts files and set breakpoints and watch expressions and step through the code one line at a time! Awesome, right?

Chrome Debugging

That’s basically it. WebStorm apparently has TypeScript debugging built in as well, but I’ve had trouble getting it to work reliably. Once I do, I’ll update this post with info on live debugging from within WebStorm as well. Also in the works is a screencast and more in-depth explanation of the actual code within the project itself. Stay tuned.

Special thanks to Photon Storm for the Phaser framework, Jesse Freeman for the original Phaser project template, and Luke Hoban for help debugging my modular TypeScript.

May 222013
 

Starting a blog is not difficult. Any Joe Schmoe can start plopping ideas into the public realm with just a few mouse clicks. There are many, many tools available to get a blog rolling: WordPress has dominated the self-hosted blogging landscape for years, Tumblr is ultra-popular with certain crowds, and for some reason people still use Blogger. The landscape is changing, though. Hosted blogging services like Tumblr and Posterous are traded like horses, with users left in the dust in some cases. Also, the WordPress feature set has vaulted beyond blogging tools, and is quickly becoming a full-blown content management system capable of building just about any type of website.

So what is the average blogger to do? Risk investing time and energy into a blogging service that may wind up as a minor acquisition of AOYahooSoft? Or dig through the complexity of WordPress’s ever expanding administration menus? How about neither? A new kid on the block just showed up with two fistfulls of awesome…

Ghost.

Ghost is a new open source blogging platform dedicated solely to dead-simple publishing. It’s goal it to let writers write, and have fun doing it. No crazy heirarchy of menus to wade through, no finicky wysiwyg editor mangling HTML, nothing to worry about except creating delightful posts. Every feature going into the initial release of Ghost will exist to support the prime directive of presenting a sensible, comfortable, and useful writing environment for the web.

The underlying technology powering Ghost will be an example of simplified elegance. NodeJS will act as the foundation, and the Express framework, JugglingDB ORM, and Handlebars template system will provide the scaffolding. This means that 100% of the Ghost platform will be written in a single language – Javascript.

The benefits of using one language for the full stack are obvious. I, personally, would love to focus my attention on one language when creating an application. But there are naysayers out there who would argue that NodeJS is just not the right tool for building a blogging platform, and Ghost would be better served by established frameworks like Rails, Django, or any number of PHP packages. This attitude is a bit short-sighted, in my opinion. If 37Signals thought like this, Basecampe would have been written in PHP, and Ruby might still be an esoteric language on the fringes of the web development world. It is projects like Ghost that will bring Node from marginal to mainstream.

We’ll have to wait a few months, though, as Ghost is still in its infancy. As of this writing, the Kickstarter campaign is reaching its end and is getting close to the stretch goal (after eclipsing the original goal 7 times over). Backers (including yours truly) will get early access this Summer, and the general public will get their hands on it in November. Not only will the code be open source, but a non-profit organization is being formed as we speak to provide reasonably priced blog hosting a-la WordPress.com. Because the service is formed under a non-profit, the risk of acquisition is minimal.

There is a good amount of promotional material available on the Kickstarter page, and the official website. I highly encourage taking a look, especially for anyone with even a passing interest in web publishing. Personally, I’m betting on Ghost as the next big thing, and in five years this post will be proof that I totally called it. Internet hipsters, eat your hearts out.

May 122013
 

I have been reading a few tutorials on HTML5′s canvas tag, and decided to give it a whirl. Rather than bunch everything together in a huge javascript file, like most of the examples I read, I wanted to split files into sensible chunks of code. The RequireJS project has crossed my path on more than one occasion, so I figured it might be a good thing to try. I figured correctly, as it was super easy to set up, and works swimmingly.

There are plenty of great resources out there to learn all about modular javascript, as well as an interesting debate on the proper method of defining modules, but the RequireJS site itself has enough info to get a basic project off the ground. I had to do a bit of experimenting on my own to clear things up in my head, and thought I would post the results here.

The project basically draws a canvas that takes up the entire browser window (and redraws itself when the window is resized). A white dot is drawn on the screen and floats towards the bottom-right corner until the user swipes a finger (using a mobile device) or the mouse pointer (on a lap/desktop). The dot will switch directions to match the swipe. Try it out!. I had intended to get the dot to do more interesting things, but time gets away from me.

The folder structure holds three files in the root, and the rest of the folder structure looks like this:

Screen Shot 2013-05-12 at 9.20.17 PM

Click here for full source

Notice that the only file in the root is index.html. Also notice that the only javascript file referenced in index.html is src/require.js, which has a data-main attribute stuck in there, as well. That data-main attribute references the entry point to the application. RequireJS will automatically append ‘.js’ to the filename, and will run whatever is in that file.

At the top of catToy.js is the following code:

requirejs.config({
  baseUrl: 'src',
  paths: {
    lib: '../assets/lib'
  },
  shim: {
    'lib/Hammer': {
      exports: 'Hammer'
    }
  }
});

This bit of code tells RequireJS what’s what. The baseUrl is a relative filepath that will act as the root for all other file paths referenced in the config block. The paths object is a list of aliases (shortcuts) to other subdirectories that contain code. The key (lib) is the alias name, and the value (‘../assets/lib’) is the file path relative to the baseUrl.

The shim object allows you to define modules that originally weren’t intended to be used with RequireJS. In this case, the Hammer library is referenced, and will export a ‘Hammer’ module that can be used in the project.

Underneath the config block is a function that acts as the main starting point of the application. The first two lines are the most important, in terms of RequireJS.

requirejs(["modules/Stage","modules/Mover","modules/Vector2D"],
  function( Stage,  Mover, Vector2D) {
    ...// application code goes here
});

This is basically a function call that says, “Hey, RequireJS!, do this! And don’t forget to load these three modules before you do it!”

The three modules in question are Stage, Mover, and Vector2D. The first parameter of the requirejs() function is an array of modules that are needed in the function that is passed in as the second parameter. RequireJS will look up the modules, and pass them into the anonymous function, using whatever names you define.

Each of the modules used here are set up to be specifically compatible with RequireJS using a function called define(). The first line of each module is very similar to that of catToy.js:

define(function(){
  ...// code goes here
});

Yeah, that’s it. Just wrap your code in the define() function and it can be used as a RequireJS module. If the module needs to use code from another module, then pass in an array of module names, just like before.

define( ['lib/Hammer'], function(Hammer) {
  ...// code goes here
});
Apr 092013
 

CODE | DEMO*

UPDATE: This is the third of a three part series on CodeIgniter, Redis, and Socket.IO integration. Please be sure to read the other posts as well.
Part 1: A Sample CodeIgniter Application with Login And Session
Part 2: Use Redis instead of MySQL for CodeIgniter Session Data
Part 3: You are here.

Well here it is, folks, the moment I’ve been waiting for :) Real-time updates that actually work! Socket.IO has been integrated to work its magic alongside CodeIgniter. Now when a user is logged in, updates will tumble in like an avalanche with absolutely no refreshes or any user intervention at all! To catch up on what this is all about, be sure to check out A Sample CodeIgniter Application with Login And Session and Use Redis instead of MySQL for CodeIgniter Session Data before reading this.

Take a look at the video above to see the live updates in action. There are three different browser windows open (Chrome, Firefox, and IE9), each logged in with a different user. The top left browser is the Admin, which will get updated when any user posts a message. The Admin is also a member of team one, so when the admin posts a message, members of team one (bottom left) will see it. The browser on the right is team two, so she will not see anyone else’s posts, but the Admin will see what she posts.

* The demo may or may not be working depending on the state of my VPS. Most of my sample projects so far have been hosted on my shared hosting account, but due to the Redis and Node requirement I had to deploy this project to a VPS that I normally use for development and testing. If I am doing some development or testing, then Apache or Node or Redis might not be working properly – hence the video. Your best option really, is to download the code and try it yourself!

The Socket.IO library makes it painfully easy to work with NodeJS (aka, Node). Prior to this project I knew almost nothing about Node other than what had read in a few short books. I still don’t know much about Node, but I know that I like it and will continue to keep investigating it for future projects. One thing in particular that I think pretty cool in this project, is that all of the Node specific functionality (the real-time message updates) runs mostly parallel to the PHP application. So if Node decides to blow up, the application will still work, only without live updates.

Anyway, enough jibber jabber. Here’s the rundown on the changes to the application, and the highlights of the Socket.IO and Node code. Again, this is not meant to be a tutorial, but rather a show and tell and perhaps a nice piece of code for others to experiment with. Use at your own risk.

Installing Socket.IO

First things first: Install Socket.IO. I already had Node and NPM installed, but I needed a spot to create the node ‘server’ within my project. I created a folder in the project root called ‘nodejs’. Through the wonders of Node Package Management (NPM), I installed the socket.io package, as well as the node_redis package. This was done by simply navigating to the nodejs folder and running:

npm install socket.io
npm install redis

Yeah, that’s it. NPM will create a folder called ‘node_modules’ and download all the dependencies necessary to run the packages. After that I created the cisockServer.js file, and I was off to the races.

To get things working right away, I added code similar to the following, just to get things rolling. The first line instantiates Socket.IO and gets a Node server up and running on port 8080. An event handler is created for the ‘connection’ event, which fires whenever a Socket.IO client connects to the server. When this happens, Socket.IO will emit an event with an identifier of ‘startup’ and attach an object with a message. If the client is listening for the ‘startup’ event, it will receive the message.

var io = require('socket.io').listen(8080);

io.sockets.on('connection', function (socket) {
  // Let everyone know it's working
  socket.emit('startup', { message: 'I Am Working!!' });
});

To actually get the Node server fired up, it’s as easy as node --debug cisocketServer.js to get it going. I added the –debug option because I was using node-inspector for debugging and tracing. There is also an interesting project called Forever available from NodeJitsu that manages one or more Node processes. I use it on my VPS. It’s nice.

The Socket.IO Client

A server is all fine-and-dandy, but it won’t do much good without clients. I created a new javascript file in my CodeIgniter assets folder called ‘socket.js’ to hold all of my Socket.IO related client code. I wrapped most of the code in the MY_Socket namespace so it is more easily accessed by the javascript in main.js. The minimum amount of code needed to work with the server code above is what follows. It simply creates a socket connection, then listens for the ‘startup’ event from the socket connection. When the ‘startup’ event occurs, the attached message will be displayed on the console.

$(function(){

  window.MY_Socket = {

    // Instantiate the Socket.IO client and connect to the server
    socket : io.connect('http://localhost:8080'),

    // Set up the initial event handlers for the Socket.IO client
    bindEvents : function() {
      this.socket.on('startup',MY_Socket.startupMessage);
    },

    // This just indicates that a Socket.IO connection has begun.
    startupMessage : function(data) {
      console.log(data.message);
    }
  } // end window.MY_Socket

  // Start it up!
  MY_Socket.bindEvents();
});

To get this working, all that is needed are a couple more lines in header.php:

<script src="<?php echo base_url();?>/nodejs/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.min.js"></script>
<script src="<?php echo base_url();?>/assets/js/socket.js"></script>

Now upon visiting the login screen (or any screen, really), the words, “I am working!” will appear in the console.

Joining A Room

Socket.IO has a concept called rooms, which is a nice way to segment broadcasted messages from a server so only a subset of users receive the message. In this application, users will join a room based on their team numbers. Team 1 will join room 1, and so on. The exception here are admins. Admin users can be on a team, but will receive messages from all users regardless of their team. To handle this, I created another room called ‘admin’.

The room joining process starts when a user is logged in. I added a bit of jQuery code to check the current page for team badges, and if any are found, run the joinRoom function. Another way to do this would be to just put a call to MY_Socket.joinRoom() at the top of /application/views/main.php so it runs whenever the main view is loaded.

init: function () {
  ...
  if($('.userTeamBadge').children().length > 0){
    MY_Socket.joinRoom();
  }
}

So the joinRoom function does some interesting things. First it grabs the cookie named, “ci_session” and reads the value. This value is the session ID set by CodeIgniter. This ID will be used to look up some of the other session information stored in Redis by the application’s MY_Session class. When the session ID is obtained, a ‘joinRoom’ event is emitted with the ID attached. If no session ID is found, then nothing happens. The code below is part of the client code in the socket.js file.

joinRoom : function(){
  // get the CodeIgniter sessionID from the cookie
  var sessionId = readCookie('ci_session');

  if(sessionId) {
    // Send the sessionID to the Node server in an effort to join a 'room'
    MY_Socket.socket.emit('joinRoom',sessionId);
  } else {
    // If no sessionID exists, don't try to join a room.
    console.log('No session id found. Broadcast disabled.');
    //forward to logout url?
  }
}

Socket.IO will be listening for the ‘joinRoom’ event on the server. When it hears the event, it will grab the session ID, use it to construct a string that matches the corresponding session key in the Redis database, and get the data associated with that key. The results returned from Redis will contain the rest of the user’s session information, including teamId and isAdmin (indicating if the user is or is not an admin). The result is parsed into a JSON, and the teamId and isAdmin values are used to join the appropriate ‘rooms’.

For any of this to work, a Redis client must be set up to execute Redis commands. The following code is in cisockServer.js.

// Start up a Node server with Socket.IO
var io = require('socket.io').listen(8080);

// Let Node know that you want to use Redis
var redis = require('redis');

// Listen for the client connection event
io.sockets.on('connection', function (socket) {
  // Instantiate a Redis client that can issue Redis commands.
  var rClient = redis.createClient();
 
  // Handle a request to join a room from the client
  // sessionId should match the Session ID assigned by CodeIgniter
  socket.on('joinRoom', function(sessionId){
    var parsedRes, team, isAdmin;

    // Use the redis client to get all session data for the user
    rClient.get('sessions:'+sessionId, function(err,res){
      console.log(res);
      parsedRes = JSON.parse(res);
      team = parsedRes.teamId;
      isAdmin = parsedRes.isAdmin;

      // Join a room that matches the user's teamId
      console.log('Joining room ' + team.toString());
      socket.join(team.toString());

      // Join the 'admin' room if user is an admin
      if (isAdmin) {
        console.log('Joining room for Admins');
        socket.join('admin');
      }
    });

  });
});

Excellent.

Send and Receive Messages

When a user posts a new message, the data is sent to the web server using jQuery’s Ajax function. This happens in the App.postMessage function in the main.js file. If the post is successful, a callback function – App.successfulPost – is executed. In order for the post to be successful, it needs to be processed by the CodeIgniter controller method responsible for saving posts to the database. This method – main.post_message – had to be refactored so that it would not only save the message, but also respond to jQuery’s ajax request with the message wrapped up in the HTML template so it can be sent out to other users.

The HTML template responsible for rendering each individual message was separated out into its own view and saved as /application/views/single_posts.php. It was basically just cut and pasted from the main view.

<div class="otherPost well">
  <div class="otherAvatar">
    <img src="../../assets/img/avatars/<?php echo $avatar ?>.png"
         alt=""
         data-title="<span class='badge badge-info'><?php echo $teamId ?></span> <?php echo $firstName ?> <?php echo $lastName ?>"
         data-content="<?php echo $tagline ?>">
  </div>
  <div class="otherPostInfo">
    <div class="otherPostBody"><p><?php echo $body ?></p></div>
    <hr/>
    <div class="otherPostDate"><p class="pull-right"><?php echo $createdDate ?></p></div>
  </div>
</div>

In order to populate that template, CodeIgniter’s Loader.view method was used with the third parameter set to ‘true’ so it will return data instead of immediately rendering the view in the browser. The view is then loaded into the response data as a string, along with the user’s teamId value, and the HTML string that will be prepended to the user’s own message list. The following code is from /application/controller/main.php (the Main controller).

function post_message() {
  ... save message to db code ...

  if ( isset($saved) && $saved ) {
    // Gather up data to fill the message template
    $post_data = array();
    $post_data = $this->user_m->fill_session_data($post_data);
    $post_data['body'] = $saved['body'];
    $post_data['createdDate'] = $saved['createdDate'];

    // Create a message html partial from the 'single_post' template and $post_data
    $broadcastMessage = $this->load->view('single_post',$post_data,true);

    // Create an html snipped for the user's message table.
    $myMessage = "<tr><td>". $saved['body'] ."</td><td>". $saved['createdDate'] ."</td></tr>";

    // Create some data to return to the client.
    $output = array('myMessage'=>$myMessage,
                    'broadcastMessage'=>$broadcastMessage,
                    'team'=>$post_data['teamId']);

    // Encode the data into JSON
    $this->output->set_content_type('application/json');
    $output = json_encode($output);

    // Send the data back to the client
    $this->output->set_output($output);
  }
}

The response object is sent back to the jQuery callback function, and it begins the process of broadcasting the message out to all the appropriate users. This really only takes one extra line of code in App.successfulPost.

successfulPost : function( result ) {
  ...
  // Send socket.io notification
  MY_Socket.sendNewPost( result.broadcastMessage, result.team );
}

All this does is send two pieces of information to the MY_Socket.sendNewPost function. The MY_Socket.sendNewPost function will simply take the message and teamId value and send it to the Node server by emitting a Socket.IO event.

sendNewPost : function(msg,team) {
  MY_Socket.socket.emit('newPost',msg,team);
}

When the ‘newPost’ event is handled on the server, it will relay the message to the appropriate team room, and also to the ‘admin’ room.

socket.on('newPost', function (post,team,sessionId) {
  console.log('Broadcasting a post to team: ' + team.toString());

  // Broadcast the message to the sender's team
  var broadcastData = {message: post, team: team};
  socket.broadcast.to(team.toString()).emit('broadcastNewPost',broadcastData);
 
  // Broadcast the message to all admins
  broadcastData.team = 'admin';
  socket.broadcast.to('admin').emit('broadcastNewPost',broadcastData);
});

The ‘broadcastNewPost’ event is emitted twice, and will therefore be handled twice by the client. This is not normally a problem, unless there is an admin with the same teamId as the sender. Then the admin will receive the message twice, and duplicate messages will be displayed on the screen. To correct this, a little logic prevents the message from being displayed twice. The message attached to the ‘broadcastData’ object is forwarded to the App.showBroadcastedMessage function.

// on 'broadcastNewPost' update the message list from other users
updateMessages : function(data) {
  // Because the message is broadcasted twice (once for the team, again for the admins)
  // we need to make sure it is only displayed once if the Admin is also on the same
  // team as the sender.
  if( ( !userIsAnAdmin() && data.team != 'admin') ||
      ( userIsAnAdmin() && data.team === 'admin') ){
    // Send the html partial with the new message over to the jQuery function that will display it.
    App.showBroadcastedMessage(data.message);
  }
}

When the App.showBroadcastedMessage function receives the message, it appends it to the top of the list of messages from other users using simple jQuery.

showBroadcastedMessage : function(messageData) {
   $(messageData).hide().prependTo(App.$otherMessages).slideDown('slow');
   //App.$otherMessages.prepend(messageData);
   App.setElements();
   App.setupComponents();
 }

Whew. That’s it! The journey is complete.