<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Eric Terpstra</title>
	<atom:link href="http://ericterpstra.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://ericterpstra.com</link>
	<description>On web development. Mostly.</description>
	<lastBuildDate>Thu, 23 May 2013 01:28:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Ghost: Just A Blogging Platform: Of the Future</title>
		<link>http://ericterpstra.com/2013/05/ghost-just-a-blogging-platform-of-the-future/</link>
		<comments>http://ericterpstra.com/2013/05/ghost-just-a-blogging-platform-of-the-future/#comments</comments>
		<pubDate>Thu, 23 May 2013 01:16:18 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[ghost]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=527</guid>
		<description><![CDATA[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 <a href='http://ericterpstra.com/2013/05/ghost-just-a-blogging-platform-of-the-future/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p>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 <a href="http://mashable.com/2013/02/15/posterous-shutting-down/" target="_blank">left in the dust</a> 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.  </p>
<p>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&#8217;s ever expanding administration menus?  How about neither?  A new kid on the block just showed up with two fistfulls of awesome&#8230;</p>
<p><a href="http://tryghost.org" title="Ghost Website">Ghost</a>.</p>
<p>Ghost is a new open source blogging platform dedicated solely to dead-simple publishing.  It&#8217;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.</p>
<p>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 &#8211; Javascript.</p>
<p>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.</p>
<p>We&#8217;ll have to wait a few months, though, as Ghost is still in its infancy.  As of this writing, the <a href="http://www.kickstarter.com/projects/johnonolan/ghost-just-a-blogging-platform" target="_blank">Kickstarter</a> 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.</p>
<p>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&#8217;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.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2013/05/ghost-just-a-blogging-platform-of-the-future/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple require.js setup (with canvas and Hammer.js)</title>
		<link>http://ericterpstra.com/2013/05/a-simple-require-js-setup-with-canvas-and-hammer-js/</link>
		<comments>http://ericterpstra.com/2013/05/a-simple-require-js-setup-with-canvas-and-hammer-js/#comments</comments>
		<pubDate>Mon, 13 May 2013 03:01:33 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[requirejs]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=520</guid>
		<description><![CDATA[I have been reading a few tutorials on HTML5&#8242;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 <a href='http://ericterpstra.com/2013/05/a-simple-require-js-setup-with-canvas-and-hammer-js/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p>I have been reading a few tutorials on HTML5&#8242;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.</p>
<p>There are plenty of <a href="http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html">great</a> <a href="http://backbonetutorials.com/organizing-backbone-using-modules/">resources</a> <a href="http://blog.teamtreehouse.com/organize-your-code-with-requirejs">out</a> <a href="http://www.dafishinsea.com/blog/2011/03/07/modular-javascript-development-with-requirejs/">there</a> to <a href="http://superherojs.com/#organizing">learn</a> all about modular javascript, as well as an <a href="http://tomdale.net/2012/01/amd-is-not-the-answer/">interesting</a> <a href="http://unscriptable.com/code/AMD-vs-CommonJS/#0">debate</a> on the <a href="http://addyosmani.com/writing-modular-js/">proper</a> method of defining <a href="http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules/">modules</a>, but the <a href="http://requirejs.org/">RequireJS site</a> 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.</p>
<p>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. <a href="http://ericterpstra.com/apps/catToy/">Try it out!</a>. I had intended to get the dot to do more interesting things, but time gets away from me.</p>
<p>The folder structure holds three files in the root, and the rest of the folder structure looks like this:</p>
<p><img src="http://ericterpstra.com/wp-content/uploads/2013/05/Screen-Shot-2013-05-12-at-9.20.17-PM.png" alt="Screen Shot 2013-05-12 at 9.20.17 PM" width="780" height="408" class="aligncenter size-full wp-image-522" /></p>
<h5><a href="https://bitbucket.org/eterpstra/cattoy/src">Click here for full source</a></h5>
<p>Notice that the only file in the root is index.html.  Also notice that the only javascript file referenced in index.html is <em>src/require.js</em>, 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 &#8216;.js&#8217; to the filename, and will run whatever is in that file.</p>
<p>At the top of catToy.js is the following code:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">requirejs.<span style="color: #660066;">config</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; baseUrl<span style="color: #339933;">:</span> <span style="color: #3366CC;">'src'</span><span style="color: #339933;">,</span><br />
&nbsp; paths<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; lib<span style="color: #339933;">:</span> <span style="color: #3366CC;">'../assets/lib'</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; shim<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #3366CC;">'lib/Hammer'</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; exports<span style="color: #339933;">:</span> <span style="color: #3366CC;">'Hammer'</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>This bit of code tells RequireJS what&#8217;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 (&#8216;../assets/lib&#8217;) is the file path relative to the baseUrl.</p>
<p>The shim object allows you to define modules that originally weren&#8217;t intended to be used with RequireJS.  In this case, the Hammer library is referenced, and will export a &#8216;Hammer&#8217; module that can be used in the project.</p>
<p>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.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">requirejs<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;modules/Stage&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;modules/Mover&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;modules/Vector2D&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> Stage<span style="color: #339933;">,</span> &nbsp;Mover<span style="color: #339933;">,</span> Vector2D<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; ...<span style="color: #006600; font-style: italic;">// application code goes here</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>This is basically a function call that says, &#8220;Hey, RequireJS!, do this!  And don&#8217;t forget to load these three modules before you do it!&#8221;</p>
<p>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.  </p>
<p>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:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">define<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; ...<span style="color: #006600; font-style: italic;">// code goes here</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Yeah, that&#8217;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.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">define<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'lib/Hammer'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>Hammer<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; ...<span style="color: #006600; font-style: italic;">// code goes here</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2013/05/a-simple-require-js-setup-with-canvas-and-hammer-js/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Live Updates in CodeIgniter with Socket.IO and Redis</title>
		<link>http://ericterpstra.com/2013/04/live-updates-in-codeigniter-with-socket-io-and-redis/</link>
		<comments>http://ericterpstra.com/2013/04/live-updates-in-codeigniter-with-socket-io-and-redis/#comments</comments>
		<pubDate>Tue, 09 Apr 2013 23:23:00 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Resources]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[socketio]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=495</guid>
		<description><![CDATA[CODE &#124; DEMO* Well here it is, folks, the moment I&#8217;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 <a href='http://ericterpstra.com/2013/04/live-updates-in-codeigniter-with-socket-io-and-redis/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p><iframe width="560" height="315" src="http://www.youtube.com/embed/N1I2yWlm6MU" frameborder="0" allowfullscreen></iframe></p>
<h4><a href="https://github.com/ericterpstra/ci_sock" title="CI_Sock Code on GitHub">CODE</a> | <a href="http://terpstra.co/ci_sock/part_three/" title="CI_Sock 3 demo">DEMO</a>*</h4>
<p>Well here it is, folks, the moment I&#8217;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 href="http://ericterpstra.com/2013/03/a-sample-codeigniter-application-with-login-and-session/" title="A Sample CodeIgniter Application with Login And Session">A Sample CodeIgniter Application with Login And Session</a> and <a href="http://ericterpstra.com/2013/03/use-redis-instead-of-mysql-for-codeigniter-session-data/" title="Use Redis instead of MySQL for CodeIgniter Session Data">Use Redis instead of MySQL for CodeIgniter Session Data</a> before reading this.  </p>
<p>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&#8217;s posts, but the Admin will see what she posts.</p>
<p>* 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 &#8211; hence the video.  Your best option really, is to <a href="https://github.com/ericterpstra/ci_sock" title="CI_Sock Code">download the code</a> and try it yourself!</p>
<p>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 <a href="http://book.mixu.net/" title="MIxu's Node Book">short</a> <a href="http://www.nodebeginner.org/" title="Node for Beginners">books</a>.  I still don&#8217;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.</p>
<p>Anyway, enough jibber jabber.  Here&#8217;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.</p>
<h3>Installing Socket.IO</h3>
<p>First things first: Install Socket.IO.  I already had <a href="http://nodejs.org/download/" title="Download Node and NPM">Node and NPM</a> installed, but I needed a spot to create the node &#8216;server&#8217; within my project.  I created a folder in the project root called &#8216;nodejs&#8217;.  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:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">npm <span style="color: #c20cb9; font-weight: bold;">install</span> socket.io<br />
npm <span style="color: #c20cb9; font-weight: bold;">install</span> redis</div></div>
<p>Yeah, that&#8217;s it.  NPM will create a folder called &#8216;node_modules&#8217; 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.  </p>
<p>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 &#8216;connection&#8217; 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 &#8216;startup&#8217; and attach an object with a message.  If the client is listening for the &#8216;startup&#8217; event, it will receive the message.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> io <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'socket.io'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8080</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
io.<span style="color: #660066;">sockets</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'connection'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>socket<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// Let everyone know it's working</span><br />
&nbsp; socket.<span style="color: #660066;">emit</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'startup'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> message<span style="color: #339933;">:</span> <span style="color: #3366CC;">'I Am Working!!'</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>To actually get the Node server fired up, it&#8217;s as easy as <code class="codecolorer bash default"><span class="bash">node <span style="color: #660033;">--debug</span> cisocketServer.js</span></code> to get it going.  I added the &#8211;debug option because I was using <a href="https://github.com/dannycoates/node-inspector" title="node-inspector code">node-inspector</a> for debugging and tracing.  There is also an interesting project called <a href="https://github.com/nodejitsu/forever" title="Forever code">Forever</a> available from <a href="http://blog.nodejitsu.com/keep-a-nodejs-server-up-with-forever" title="NodeJitsu blog post about Forever">NodeJitsu</a> that manages one or more Node processes.  I use it on my VPS.  It&#8217;s nice. </p>
<h3>The Socket.IO Client</h3>
<p>A server is all fine-and-dandy, but it won&#8217;t do much good without clients.  I created a new javascript file in my CodeIgniter assets folder called &#8216;socket.js&#8217; 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 &#8216;startup&#8217; event from the socket connection.  When the &#8216;startup&#8217; event occurs, the attached message will be displayed on the console.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; window.<span style="color: #660066;">MY_Socket</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Instantiate the Socket.IO client and connect to the server</span><br />
&nbsp; &nbsp; socket <span style="color: #339933;">:</span> io.<span style="color: #660066;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'http://localhost:8080'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Set up the initial event handlers for the Socket.IO client</span><br />
&nbsp; &nbsp; bindEvents <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">socket</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'startup'</span><span style="color: #339933;">,</span>MY_Socket.<span style="color: #660066;">startupMessage</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// This just indicates that a Socket.IO connection has begun.</span><br />
&nbsp; &nbsp; startupMessage <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #006600; font-style: italic;">// end window.MY_Socket</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// Start it up!</span><br />
&nbsp; MY_Socket.<span style="color: #660066;">bindEvents</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>To get this working, all that is needed are a couple more lines in header.php:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;script src=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> base_url<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>/nodejs/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.min.js&quot;&gt;&lt;/script&gt;<br />
&lt;script src=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> base_url<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>/assets/js/socket.js&quot;&gt;&lt;/script&gt;</div></div>
<p>Now upon visiting the login screen (or any screen, really), the words, &#8220;I am working!&#8221; will appear in the console.</p>
<h3>Joining A Room</h3>
<p>Socket.IO has a concept called <em>rooms</em>, 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 &#8216;admin&#8217;. </p>
<p>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.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">init<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; ...<br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.userTeamBadge'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">children</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">length</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; MY_Socket.<span style="color: #660066;">joinRoom</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>So the joinRoom function does some interesting things.  First it grabs the cookie named, &#8220;ci_session&#8221; 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&#8217;s MY_Session class.  When the session ID is obtained, a &#8216;joinRoom&#8217; 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.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">joinRoom <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// get the CodeIgniter sessionID from the cookie</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> sessionId <span style="color: #339933;">=</span> readCookie<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ci_session'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>sessionId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Send the sessionID to the Node server in an effort to join a 'room'</span><br />
&nbsp; &nbsp; MY_Socket.<span style="color: #660066;">socket</span>.<span style="color: #660066;">emit</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'joinRoom'</span><span style="color: #339933;">,</span>sessionId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// If no sessionID exists, don't try to join a room.</span><br />
&nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'No session id found. Broadcast disabled.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">//forward to logout url?</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Socket.IO will be listening for the &#8216;joinRoom&#8217; 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&#8217;s session information, including <em>teamId</em> and <em>isAdmin</em> (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 &#8216;rooms&#8217;.  </p>
<p>For any of this to work, a Redis client must be set up to execute Redis commands.  The following code is in cisockServer.js.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// Start up a Node server with Socket.IO</span><br />
<span style="color: #003366; font-weight: bold;">var</span> io <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'socket.io'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">listen</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">8080</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// Let Node know that you want to use Redis</span><br />
<span style="color: #003366; font-weight: bold;">var</span> redis <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'redis'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #006600; font-style: italic;">// Listen for the client connection event</span><br />
io.<span style="color: #660066;">sockets</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'connection'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>socket<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// Instantiate a Redis client that can issue Redis commands.</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> rClient <span style="color: #339933;">=</span> redis.<span style="color: #660066;">createClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <br />
&nbsp; <span style="color: #006600; font-style: italic;">// Handle a request to join a room from the client</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// sessionId should match the Session ID assigned by CodeIgniter</span><br />
&nbsp; socket.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'joinRoom'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>sessionId<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> parsedRes<span style="color: #339933;">,</span> team<span style="color: #339933;">,</span> isAdmin<span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Use the redis client to get all session data for the user</span><br />
&nbsp; &nbsp; rClient.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sessions:'</span><span style="color: #339933;">+</span>sessionId<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>err<span style="color: #339933;">,</span>res<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; parsedRes <span style="color: #339933;">=</span> JSON.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span>res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; team <span style="color: #339933;">=</span> parsedRes.<span style="color: #660066;">teamId</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; isAdmin <span style="color: #339933;">=</span> parsedRes.<span style="color: #660066;">isAdmin</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Join a room that matches the user's teamId</span><br />
&nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Joining room '</span> <span style="color: #339933;">+</span> team.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; socket.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span>team.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Join the 'admin' room if user is an admin</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>isAdmin<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Joining room for Admins'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; socket.<span style="color: #660066;">join</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'admin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>Excellent.</p>
<h3>Send and Receive Messages</h3>
<p>When a user posts a new message, the data is sent to the web server using jQuery&#8217;s Ajax function. This happens in the App.postMessage function in the main.js file.  If the post is successful, a callback function &#8211; App.successfulPost &#8211; 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 &#8211; main.post_message &#8211; had to be refactored so that it would not only save the message, but also respond to jQuery&#8217;s ajax request with the message wrapped up in the HTML template so it can be sent out to other users.</p>
<p>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.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;div class=&quot;otherPost well&quot;&gt;<br />
&nbsp; &lt;div class=&quot;otherAvatar&quot;&gt;<br />
&nbsp; &nbsp; &lt;img src=&quot;../../assets/img/avatars/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$avatar</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>.png&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;alt=&quot;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data-title=&quot;&lt;span class='badge badge-info'&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$teamId</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/span&gt; <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$firstName</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$lastName</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data-content=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$tagline</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;<br />
&nbsp; &lt;/div&gt;<br />
&nbsp; &lt;div class=&quot;otherPostInfo&quot;&gt;<br />
&nbsp; &nbsp; &lt;div class=&quot;otherPostBody&quot;&gt;&lt;p&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$body</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;&lt;/div&gt;<br />
&nbsp; &nbsp; &lt;hr/&gt;<br />
&nbsp; &nbsp; &lt;div class=&quot;otherPostDate&quot;&gt;&lt;p class=&quot;pull-right&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$createdDate</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;&lt;/div&gt;<br />
&nbsp; &lt;/div&gt;<br />
&lt;/div&gt;</div></div>
<p>In order to populate that template, CodeIgniter&#8217;s <a href="http://ellislab.com/codeigniter/user-guide/libraries/loader.html" title="CodeIgniter Loader Class">Loader.view</a> method was used with the third parameter set to &#8216;true&#8217; 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&#8217;s teamId value, and the HTML string that will be prepended to the user&#8217;s own message list.  The following code is from /application/controller/main.php (the Main controller).</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">function post_message() {<br />
&nbsp; ... save message to db code ...<br />
<br />
&nbsp; if ( isset($saved) &amp;&amp; $saved ) {<br />
&nbsp; &nbsp; // Gather up data to fill the message template<br />
&nbsp; &nbsp; $post_data = array();<br />
&nbsp; &nbsp; $post_data = $this-&gt;user_m-&gt;fill_session_data($post_data);<br />
&nbsp; &nbsp; $post_data['body'] = $saved['body'];<br />
&nbsp; &nbsp; $post_data['createdDate'] = $saved['createdDate'];<br />
<br />
&nbsp; &nbsp; // Create a message html partial from the 'single_post' template and $post_data<br />
&nbsp; &nbsp; $broadcastMessage = $this-&gt;load-&gt;view('single_post',$post_data,true);<br />
<br />
&nbsp; &nbsp; // Create an html snipped for the user's message table.<br />
&nbsp; &nbsp; $myMessage = &quot;&lt;tr&gt;&lt;td&gt;&quot;. $saved['body'] .&quot;&lt;/td&gt;&lt;td&gt;&quot;. $saved['createdDate'] .&quot;&lt;/td&gt;&lt;/tr&gt;&quot;;<br />
<br />
&nbsp; &nbsp; // Create some data to return to the client.<br />
&nbsp; &nbsp; $output = array('myMessage'=&gt;$myMessage,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'broadcastMessage'=&gt;$broadcastMessage,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'team'=&gt;$post_data['teamId']);<br />
<br />
&nbsp; &nbsp; // Encode the data into JSON<br />
&nbsp; &nbsp; $this-&gt;output-&gt;set_content_type('application/json');<br />
&nbsp; &nbsp; $output = json_encode($output);<br />
<br />
&nbsp; &nbsp; // Send the data back to the client<br />
&nbsp; &nbsp; $this-&gt;output-&gt;set_output($output);<br />
&nbsp; } <br />
}</div></div>
<p>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.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">successfulPost <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> result <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; ...<br />
&nbsp; <span style="color: #006600; font-style: italic;">// Send socket.io notification</span><br />
&nbsp; MY_Socket.<span style="color: #660066;">sendNewPost</span><span style="color: #009900;">&#40;</span> result.<span style="color: #660066;">broadcastMessage</span><span style="color: #339933;">,</span> result.<span style="color: #660066;">team</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>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.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">sendNewPost <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>msg<span style="color: #339933;">,</span>team<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; MY_Socket.<span style="color: #660066;">socket</span>.<span style="color: #660066;">emit</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'newPost'</span><span style="color: #339933;">,</span>msg<span style="color: #339933;">,</span>team<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>When the &#8216;newPost&#8217; event is handled on the server, it will relay the message to the appropriate team room, and also to the &#8216;admin&#8217; room.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">socket.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'newPost'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>post<span style="color: #339933;">,</span>team<span style="color: #339933;">,</span>sessionId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Broadcasting a post to team: '</span> <span style="color: #339933;">+</span> team.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// Broadcast the message to the sender's team</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> broadcastData <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>message<span style="color: #339933;">:</span> post<span style="color: #339933;">,</span> team<span style="color: #339933;">:</span> team<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; socket.<span style="color: #660066;">broadcast</span>.<span style="color: #660066;">to</span><span style="color: #009900;">&#40;</span>team.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">emit</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'broadcastNewPost'</span><span style="color: #339933;">,</span>broadcastData<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <br />
&nbsp; <span style="color: #006600; font-style: italic;">// Broadcast the message to all admins</span><br />
&nbsp; broadcastData.<span style="color: #660066;">team</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'admin'</span><span style="color: #339933;">;</span><br />
&nbsp; socket.<span style="color: #660066;">broadcast</span>.<span style="color: #660066;">to</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'admin'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">emit</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'broadcastNewPost'</span><span style="color: #339933;">,</span>broadcastData<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>The &#8216;broadcastNewPost&#8217; 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 &#8216;broadcastData&#8217; object is forwarded to the App.showBroadcastedMessage function.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #006600; font-style: italic;">// on 'broadcastNewPost' update the message list from other users</span><br />
updateMessages <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// Because the message is broadcasted twice (once for the team, again for the admins)</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// we need to make sure it is only displayed once if the Admin is also on the same</span><br />
&nbsp; <span style="color: #006600; font-style: italic;">// team as the sender.</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span>userIsAnAdmin<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> data.<span style="color: #660066;">team</span> <span style="color: #339933;">!=</span> <span style="color: #3366CC;">'admin'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#40;</span> userIsAnAdmin<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> data.<span style="color: #660066;">team</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">'admin'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Send the html partial with the new message over to the jQuery function that will display it.</span><br />
&nbsp; &nbsp; App.<span style="color: #660066;">showBroadcastedMessage</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>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.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">showBroadcastedMessage <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>messageData<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp;$<span style="color: #009900;">&#40;</span>messageData<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">hide</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">prependTo</span><span style="color: #009900;">&#40;</span>App.$otherMessages<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">slideDown</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'slow'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;<span style="color: #006600; font-style: italic;">//App.$otherMessages.prepend(messageData);</span><br />
&nbsp; &nbsp;App.<span style="color: #660066;">setElements</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp;App.<span style="color: #660066;">setupComponents</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp;<span style="color: #009900;">&#125;</span></div></div>
<p>Whew. That&#8217;s it! The journey is complete.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2013/04/live-updates-in-codeigniter-with-socket-io-and-redis/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Use Redis instead of MySQL for CodeIgniter Session Data</title>
		<link>http://ericterpstra.com/2013/03/use-redis-instead-of-mysql-for-codeigniter-session-data/</link>
		<comments>http://ericterpstra.com/2013/03/use-redis-instead-of-mysql-for-codeigniter-session-data/#comments</comments>
		<pubDate>Fri, 29 Mar 2013 03:18:14 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[redis]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=488</guid>
		<description><![CDATA[In my effort to add awesome real-time live updates to a plain ol&#8217; CodeIgniter application, I decided to move the session information usually stored in a database table to a key-value store &#8211; namely, Redis. Not only does this alleviate some load from the MySQL database, but it also provides an easy way to expose <a href='http://ericterpstra.com/2013/03/use-redis-instead-of-mysql-for-codeigniter-session-data/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p>In my effort to add awesome real-time live updates to a plain ol&#8217; CodeIgniter application, I decided to move the session information usually stored in a database table to a key-value store &#8211; namely, Redis.  Not only does this alleviate some load from the MySQL database, but it also provides an easy way to expose user session data to a NodeJS server. This will be important in the future when adding Socket.IO.  </p>
<p>The process for converting my existing application to use Redis rather than MySQL was painfully simple. It was pretty much just a handful of step-by-step instructions via the command line, and voila! PHP and Redis! BFFs 4Ever!</p>
<p>Here were the basic steps I followed:</p>
<h3>1. Install Redis</h3>
<p>Simply follow the instructions on in the <a href="http://redis.io/topics/quickstart" title="Redis Quickstart">Redis quickstart guide</a>.  These instructions were written for linux, and should work on most distributions.  It might work on a Mac, but I&#8217;m not sure.  Windows&#8230; you&#8217;re on your own. Below is the tl;dr version with just the commands.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>download.redis.io<span style="color: #000000; font-weight: bold;">/</span>redis-stable.tar.gz<br />
<span style="color: #c20cb9; font-weight: bold;">tar</span> xvzf redis-stable.tar.gz<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> redis-stable<br />
<span style="color: #c20cb9; font-weight: bold;">make</span><br />
<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> src<br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">cp</span> redis-server <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">cp</span> redis-cli <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span><br />
<br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>redis<br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>redis<br />
<br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">cp</span> utils<span style="color: #000000; font-weight: bold;">/</span>redis_init_script <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span>redis_6379<br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">cp</span> redis.conf <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>redis<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">6379</span>.conf<br />
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>redis<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">6379</span></div></div>
<p>From the <a href="http://redis.io/topics/quickstart" title="Redis Quickstart">Redis Quickstart Guide</a>:</p>
<blockquote><p>Edit the configuration file, making sure to perform the following changes:<br />
Set daemonize to yes (by default it is set to no).<br />
Set the pidfile to /var/run/redis_6379.pid (modify the port if needed).<br />
Change the port accordingly. In our example it is not needed as the default port is already 6379.<br />
Set your preferred loglevel.<br />
Set the logfile to /var/log/redis_6379.log<br />
Set the dir to /var/redis/6379 (very important step!)</p></blockquote>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">sudo</span> update-rc.d redis_6379 defaults<br />
<span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span>redis_6379 start</div></div>
<p>Boom. Done.</p>
<h3>2. Install phpredis</h3>
<p>PHP needs an extension to talk to Redis.  There are a <a href="http://redis.io/clients" title="Redis Clients">few options</a> for this listed on the Redis site.  I went with <a href="https://github.com/nicolasff/phpredis" title="phpredis repo">phpredis</a> by <a href="https://twitter.com/yowgi" title="Twitter Link">Nicolas Favre-Felix</a> mainly because it is required for the My_Session class used below.  It&#8217;s also a great project that is still updated frequently.  </p>
<p>To install, follow the directions in the README for your system.  The default directions worked just fine for me.</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #c20cb9; font-weight: bold;">git clone</span> https:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>nicolasff<span style="color: #000000; font-weight: bold;">/</span>phpredis.git<br />
phpize<br />
.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #7a0874; font-weight: bold;">&#91;</span>--enable-redis-igbinary<span style="color: #7a0874; font-weight: bold;">&#93;</span><br />
<span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></div></div>
<p>Then add <code class="codecolorer bash default"><span class="bash"><span style="color: #007800;">extension</span>=redis.so</span></code> to /etc/php5/apache2/php.ini and /etc/php5/cli/php.ini (if you are using Apache on linux). Finally, restart Apache.</p>
<p>Done, son.</p>
<h3>3. Configure CodeIgniter to use Redis for session data storage</h3>
<p>Finally, we just drop one class into the application&#8217;s library folder, and add a couple of lines to the config file to get everything working.  </p>
<p>Really. That&#8217;s it.  I&#8217;m not joking. It&#8217;s that easy.</p>
<p>Grab the MY_Session.php class from Ming Zhou&#8217;s gist: <a href="https://gist.github.com/zhouming/3672207" title="Gist">https://gist.github.com/zhouming/3672207</a> and drop it into /application/libraries.  CodeIgniter will automatically use it as a subclass of Session.  Most of the essential functions are overridden by My_Session so that Redis is used to store session data that will be used to authenticate user sessions while the application is running.  The only thing left is to add the following two lines to /application/config/config.php:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$config['redis_host'] = 'localhost';<br />
$config['redis_port'] = '6379';</div></div>
<p>Obvously you will need to change &#8216;localhost&#8217; to the IP address of your Redis server if it is on a different machine from your application.</p>
<p>And that&#8217;s it!  The application is Redis ready!</p>
<p><strong>Note:</strong> I&#8217;ve added the MY_Session class and some installation notes to the <a href="https://github.com/ericterpstra/ci_sock" title="CI_Sock project">ci_sock</a> project in my GitHub repo, just in case the links become broken or you want an easy reference.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2013/03/use-redis-instead-of-mysql-for-codeigniter-session-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Sample CodeIgniter Application with Login And Session</title>
		<link>http://ericterpstra.com/2013/03/a-sample-codeigniter-application-with-login-and-session/</link>
		<comments>http://ericterpstra.com/2013/03/a-sample-codeigniter-application-with-login-and-session/#comments</comments>
		<pubDate>Mon, 25 Mar 2013 02:27:56 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[codeigniter]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[twitter bootstrap]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=468</guid>
		<description><![CDATA[CODE &#124; DEMO I was assigned to work on a PHP project a few weeks back that utilized the CodeIgniter framework. I&#8217;ve used MVC frameworks in the past in other languages, and because CodeIgniter does not deviate too far from common MVC patterns, it was pretty easy to pick up. To get myself up to <a href='http://ericterpstra.com/2013/03/a-sample-codeigniter-application-with-login-and-session/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p><img src="http://ericterpstra.com/wp-content/uploads/2013/03/ciapp.png" alt="Code Igniter App Screenshot" width="600" height="444" class="aligncenter size-medium wp-image-470" /></p>
<h3><a href="https://github.com/ericterpstra/ci_sock" title="GitHub Repo">CODE</a> | <a href="http://apps.ericterpstra.com/ci_sock/part_one/" title="Demo">DEMO</a></h3>
<p>I was assigned to work on a PHP project a few weeks back that utilized the <a href="http://ellislab.com/codeigniter/user-guide/" title="CodeIgniter">CodeIgniter</a> framework.  I&#8217;ve used MVC frameworks in the past in other languages, and because CodeIgniter does not deviate too far from common MVC patterns, it was pretty easy to pick up. To get myself up to speed, I put together a sample project based of what I learned from the documentation and a few tutorials. It&#8217;s a small microblogging app with very basic user auth and CRUD functionality. The basics of it go like this&#8230;</p>
<ul>
<li>User login screen with basic password authentication.</li>
<li>Each user is assigned a &#8216;team&#8217; number. Users can only view posts from their teammates.</li>
<li>An admin can view all posts from all users.</li>
<li>Each user has a &#8216;tagline&#8217;.</li>
<li>The tagline can be edited by clicking on it and typing something new (modern browsers only, as it uses &#8216;contenteditable&#8217;)</li>
<li>Hovering over a user&#8217;s avatar reveals the username and tagline for that user.</li>
<li>Admins can create new user accounts.</li>
<li>A user&#8217;s own messages appear below their profile. This is limited by 5 posts, currently.</li>
<li>Careful, there is not much form validation going on at the moment.</li>
</ul>
<p>Building it gave me a good feel for the basic mechanics of CodeIgniter and allowed me to brush up on some PHP.  The real motivation behind this project, however, is to eventually work in a Socket.IO implementation to allow real time updates for the user.  I&#8217;ve been eyeing NodeJS for quite some time now, but never really had cause to use it.  Fortunately, the project I was working on needed a more robust and scalable &#8216;real time&#8217; framework to replace a rudimentary long-polling system.  Socket.IO would have been a pretty good solution, in my opinion.  Unfortunately, the project was cancelled before I could get started.  But since I&#8217;ve already got the ball rolling on this sample application, I figure I might as well finish, and learn a few things in case a situation like this arises again.  You never know&#8230;</p>
<h4>The Setup</h4>
<p>The front end of the application uses Twitter Bootstrap for styling and layout, jQuery for client-side interactivity, PHP and CodeIgniter for most of the functionality, and MySQL for data storage. This is a fairly common toolset that runs on most L/W/M/AMP-style environment stacks.  The code available on <a href="https://github.com/ericterpstra/ci_sock">GitHub</a> has everything you need to run the app yourself, provided you have a web server, MySQL, and PHP 5.3 or greater.</p>
<p>You&#8217;ll need to create a database (preferably called &#8216;cisock&#8217;), and then import cisock.sql in the root of the &#8216;partOne&#8217; folder in the repository.  You can do this with the following command from the command line (be sure to change &#8216;yourusername&#8217; and &#8216;/path/to/&#8217; to match your local setup):</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">mysql <span style="color: #660033;">-u</span> yourusername <span style="color: #660033;">-p</span> <span style="color: #660033;">-h</span> localhost cisock <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>cisock.sql</div></div>
<p>Once you&#8217;ve gotten the code checked out into your web root and the SQL imported, you&#8217;ll need to do some slight configuration before getting started.  In &#8216;part_one/application/config/config.php&#8217; you will need to change line 17 to reflect your local URL.  If you simply cloned the project directly into your &#8216;localhost&#8217; web root, then no changes will likely be needed.  A similar fix is necessary in &#8216;part_one/assets/js/main.js&#8217; line 6. The context root of your application goes here.  Again, if you cloned to your web root, the default value should be fine.  Ideally, the context root should only have to be configured in one place, but it is what it is for now.</p>
<p>Secondly, the settings in &#8216;part_one/application/config/database.php&#8217; must be set to reflect your local database configuration.  The following entries are specific to your local environment:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$db</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'default'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'hostname'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'localhost'</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$db</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'default'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'username'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'yourdatabaseusernamehere'</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$db</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'default'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'yourdatabasepasswordhere'</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$db</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'default'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'database'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'cisock'</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//or use the database name you chose, if it is different</span></div></div>
<p>Once that is done, you should be able to navigate your browser to the /part_one/ directory and see the login screen.</p>
<h5>To recap:</h5>
<ol>
<li>Clone the repo</li>
<li>Set up the database and import the tables from cisock.sql</li>
<li>Edit database.php and also config.php and main.js if necessary</li>
</ol>
<h4>The Code</h4>
<p>I tried to follow suggested CodeIgniter conventions as closely as possible.  As such, the file and directory structure is pretty much as it is out of the box.  I altered /application/config/routes.php to set the login controller as the entry point for the application like so:</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$route</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'default_controller'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;login&quot;</span><span style="color: #339933;">;</span></div></div>
<p>The index method in /application/controllers/login.php checks to see if the user is logged in, and if not will redirect to the login screen by calling the show_login function.  The code immediately below is login/index &#8211; which will run when application&#8217;s url is loaded in the browser.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> index<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">userdata</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'isLoggedIn'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; redirect<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/main/show_main'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show_login</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>Because the &#8216;isLoggedIn&#8217; session variable starts out as false, the show_login() function is called. The &#8216;false&#8217; argument indicates that an error message is not to be shown.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">function</span> show_login<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$show_error</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'error'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$show_error</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">helper</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'form'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login'</span><span style="color: #339933;">,</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>That last line there: <code class="codecolorer php default"><span class="php"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login'</span><span style="color: #339933;">,</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></span></code> is what opens up the login view ( /application/views/login.php ).  When the user types in credentials and clicks the &#8216;sign-in&#8217; button, the login_user function is called through a normal form POST as indicated by this line of code in /application/views/login.php: <code class="codecolorer php default"><span class="php"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> form_open<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'login/login_user'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span></code>.  The form_open function is part of CodeIgniter&#8217;s Form Helper, which generates the form&#8217;s HTML for you.</p>
<p>The login/login_user function gives us our first taste of a CodeIgniter model.  It loads up an instance of a user model and calls the validate_user method on that model, passing it the email and password typed in by the user.  Take a look at the code below for the entire sequence.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color: #000000; font-weight: bold;">function</span> login_user<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Create an instance of the user model</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">model</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user_m'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Grab the email and password from the form POST</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$email</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #000088;">$pass</span> &nbsp;<span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">input</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">post</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">//Ensure values exist for email and pass, and validate the user's credentials</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$email</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$pass</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">user_m</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validate_user</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$email</span><span style="color: #339933;">,</span><span style="color: #000088;">$pass</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// If the user is valid, redirect to the main view</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; redirect<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/main/show_main'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Otherwise show the login screen with an error message.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show_login</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span></div></div>
<p>In the &#8216;user&#8217; model, a couple of interesting things happen.  First, a query is built using CodeIgniter&#8217;s ActiveRecord implementation.  The username and password entered by the user are compared to the user table in the database to see if the credentials exist.  If so, the corresponding record in the database will be retrieved.  If that happens, the data retrieved from the database will be used to set session variables using the set_session function of CodeIgniter&#8217;s Session class.  All the code for this is in /application/model/user_m.php and can be seen below.</p>
<div class="codecolorer-container php default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">var</span> <span style="color: #000088;">$details</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> validate_user<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$email</span><span style="color: #339933;">,</span> <span style="color: #000088;">$password</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Build a query to retrieve the user's details</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// based on the received username and password</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'email'</span><span style="color: #339933;">,</span><span style="color: #000088;">$email</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'password'</span><span style="color: #339933;">,</span> <a href="http://www.php.net/sha1"><span style="color: #990000;">sha1</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$password</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$login</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">result</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// The results of the query are stored in $login.</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// If a value exists, then the user account exists and is validated</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <a href="http://www.php.net/is_array"><span style="color: #990000;">is_array</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$login</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <a href="http://www.php.net/count"><span style="color: #990000;">count</span></a><span style="color: #009900;">&#40;</span><span style="color: #000088;">$login</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Set the users details into the $details property of this class</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$login</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// Call set_session to set the user's session vars via CodeIgniter</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set_session</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">function</span> set_session<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// session-&gt;set_userdata is a CodeIgniter function that</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// stores data in a cookie in the user's browser. &nbsp;Some of the values are built in</span><br />
&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// to CodeIgniter, others are added (like the IP address). &nbsp;See CodeIgniter's documentation for details.</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">session</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set_userdata</span><span style="color: #009900;">&#40;</span> <a href="http://www.php.net/array"><span style="color: #990000;">array</span></a><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'id'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'name'</span><span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">firstName</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastName</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'email'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">email</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'avatar'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">avatar</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'tagline'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">tagline</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'isAdmin'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAdmin</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'teamId'</span><span style="color: #339933;">=&gt;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">details</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">teamId</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'isLoggedIn'</span><span style="color: #339933;">=&gt;</span><span style="color: #009900; font-weight: bold;">true</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
<p>So now that the user is authenticated and their session info is set in a cookie, CodeIgniter will take an extra step and store the user&#8217;s IP address, session ID, user agent string and last activity timestamp in the database.  So when the user logs out, closes the browser, or is idle for too long, the session will expire and be cleared from the database.  If someone with a cookie containing the same session ID then tries to connect to the application, it will be invalid because it won&#8217;t match any of the sessions stored in the database. Check out the <a href="http://ellislab.com/codeigniter/user-guide/libraries/sessions.html" title="CodeIgniter Session Class">Session class documentation</a> for a more thorough explanation.</p>
<p>So now that the user is logged in, the &#8216;main&#8217; controller can do its thing.  The show_main function runs just before loading the main view, and does a number of things to prepare for displaying the view to the user. The user&#8217;s details are used to change certain parts of the view, such as which posts to display (team only, or everyone) and the admin controls.</p>
<p>The show_main function grabs some data from the user&#8217;s session, retrieves all the user&#8217;s posted messages, counts the total number of messages posted by the user, and retrieves the messages from other users.  All of this info is placed into the $data object and passed to the &#8216;main&#8217; view (/application/views/main.php).  Much of the heavy lifting is taken care of by <a href="http://ellislab.com/codeigniter/user-guide/database/active_record.html" title="CodeIgniter ActiveRecord">ActiveRecord</a> commands in the Post model (/application/model/post_m).</p>
<p>That&#8217;s about it, as far as logging in goes.  Now that everything is set up using conventional CodeIgniter practices, I can begin the process of converting the server side session data to be stored in Redis, rather than in a MySQL table&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2013/03/a-sample-codeigniter-application-with-login-and-session/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>My First jQuery Plugin: VintageTxt</title>
		<link>http://ericterpstra.com/2013/03/my-first-jquery-plugin-vintagetxt/</link>
		<comments>http://ericterpstra.com/2013/03/my-first-jquery-plugin-vintagetxt/#comments</comments>
		<pubDate>Sat, 09 Mar 2013 06:46:45 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=453</guid>
		<description><![CDATA[DEMO &#124; SOURCE Ever hearken back to the good ol&#8217; days of the Apple II, with its monochrome screen and visible scanlines? No? Me either, really. I don&#8217;t even know what hearken means. But I do know that vintage looking stuff is cool, and people love it when all that is old is new again. <a href='http://ericterpstra.com/2013/03/my-first-jquery-plugin-vintagetxt/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p><a href="http://ericterpstra.com/apps/vintageTxt/demo/index.html"><img src="http://ericterpstra.com/wp-content/uploads/2013/03/plainvintagetxt.jpg" alt="VintageTxt<br />
Default" width="461" height="353" class="aligncenter size-full wp-image-459" /></a></p>
<h3><a href="http://ericterpstra.com/apps/vintageTxt/demo/index.html" title="VintageTxt Demo">DEMO</a> | <a href="https://github.com/ericterpstra/jqVintageTxt" title="VintageTxt Source">SOURCE</a></h3>
<p>Ever hearken back to the good ol&#8217; days of the Apple II, with its monochrome screen and visible scanlines? No? Me either, really. I don&#8217;t even know what hearken means. But I do know that vintage looking stuff is cool, and people love it when all that is old is new again.  So here is a jQuery plugin (new) that injects a green monochromatic scanlined fake computer screen (old) right onto any webpage.  You can even make it type out a bunch of text, one character at a time &#8211; like that stupid computer from Wargames.  No annoying voice-over though.  And of course there is an input prompt, so you can bang away at your keyboard while pretending to break through 8 levels of top secret encryption to re-route the protocols through the mainframe and unleash your most advanced viruses&#8230; all while chanting, &#8220;<a href="http://www.youtube.com/watch?v=KiqkclCJsZs" title="Enhance" target="_blank">enhance</a>.&#8221;</p>
<p>Why make this? Fun, naturally.  Plus I&#8217;ve been wondering lately what it would be like to make a jQuery plugin.  I know I&#8217;m a little late to the jQuery party, and all the cool kids have move on <a href="http://emberjs.com" title="EmberJS" target="_blank">bigger</a> and <a href="http://meteor.com" title="Meteor" target="_blank">better</a> things, but the ability to whip up a jQuery plugin seems like one of those skills a self-respecting web developer should acquire at some point.  Two <a href="http://docs.jquery.com/Plugins/Authoring" title="jQuery Plugin Authoring">helpful</a> <a href="http://www.websanova.com/tutorials/jquery/the-ultimate-guide-to-writing-jquery-plugins#.UTrSCXG4bVM" title="The Ultimate Guide to jQuery Plugins">guides</a> stocked the pot, and I threw in a bit of my own spicy sauce as I went along.  I&#8217;m fairly satisfied with the end result, and the knowledge gained.  To play around with a fully functional demo, click the link or image above.  But to have some real fun, go <a href="https://github.com/ericterpstra/jqVintageTxt" title="jQuery VintageTxt">grab the source</a> from GitHub and VintageTxt your face off!</p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2013/03/my-first-jquery-plugin-vintagetxt/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Construct 2 HTML5 Mobile Game: Turkey Trot of Doom!!</title>
		<link>http://ericterpstra.com/2012/11/construct-2-html5-mobile-game-turkey-trot-of-doom/</link>
		<comments>http://ericterpstra.com/2012/11/construct-2-html5-mobile-game-turkey-trot-of-doom/#comments</comments>
		<pubDate>Fri, 30 Nov 2012 04:47:34 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[game development]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[mobile]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=430</guid>
		<description><![CDATA[So it&#8217;s a week before Thanksgiving and I get an email from the hostess of the dinner I plan on attending. Included was a list of dishes assigned for guests to bring. The usual suspects were present: stuffing, cranberry sauce, pie, lots of pie&#8230; But when I finally got to my name, a &#8216;holiday themed <a href='http://ericterpstra.com/2012/11/construct-2-html5-mobile-game-turkey-trot-of-doom/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p><img src="http://ericterpstra.com/wp-content/uploads/2012/11/ttod.png" alt="" title="Turkey Trot" width="580" height="393" class="aligncenter size-full wp-image-431" /></p>
<p>So it&#8217;s a week before Thanksgiving and I get an email from the hostess of the dinner I plan on attending.  Included was a list of dishes assigned for guests to bring.  The usual suspects were present: stuffing, cranberry sauce, pie, lots of pie&#8230;</p>
<p>But when I finally got to my name, a &#8216;holiday themed video game&#8217; was requested.  </p>
<p>&#8220;Ha!&#8221; I thought, funny joke, can&#8217;t be done.  But then I thought some more. Perhaps it could be done.  I&#8217;ve always wanted to try making one of those newfangled mobile HTML5 games that all the kids are talking about, and here was the perfect motivation.  To make things even more interesting, I decided to try out Construct 2 &#8211; a drag-n-drop game maker that exports to HTML5.  I haven&#8217;t used anything of the sort since Klik &#8216;n Play back in 1995.  Construct 2 is much, much cooler.  </p>
<p><a href="http://ericterpstra.com/wp-content/uploads/2012/11/const2.png"><img src="http://ericterpstra.com/wp-content/uploads/2012/11/const2-300x162.png" alt="" title="Construct 2" width="300" height="162" class="alignleft size-medium wp-image-432" /></a> The interface is mostly intuitive, but reading the manual is definitely necessary to do anything meaningful.  After a few hours of fiddling with the sample projects and reading bits and pieces from the manual and a few tutorials I was confident enough to at least begin my own project.  After I got started, many grand ideas popped into my head, but there just wasn&#8217;t time.  I had an hour here, and an hour there to work, and Turkey Day was quickly approaching.  In the end, I managed to get one major feature from my wishlist working &#8211; accelerometer controls.  When playing the game on a mobile browser, the player moves by tilting the device.  It works pretty well on a modern iPhone (4, 4s, 5) and iPads.  Doesn&#8217;t work so great on Android, but you can still get the gist of it.</p>
<p>Rather than go into too much detail on how the game was assembled within Construct 2, I&#8217;ll just post the game file for download.  There&#8217;s nothing terribly complicated going on, and the way the event sheets are organized, it reads almost like a book. <a href="https://www.box.com/s/jfvvtt9pjqjdofswi06i" title="TurkeyTrot Capx file">You can download the file here</a>.</p>
<p>To play the game, simply visit http://turkey.thebogstras.com.  If you are using a mobile device, make sure it is in landscape orientation with the home button on the right.  It takes a while to get used to the tilt controls, and you will probably die very quickly.  If playing on a desktop browser, click the mouse where you want the character to move.  </p>
<p>Remember, this game was never intended to be fun. It&#8217;s sole purpose was to be a game, and have some Thanksgivingy stuff in it.  Fun was never a requirement.</p>
<p>Credits for artwork:<br />
Boss Turkey &#8211; <a href="http://www.puppetnightmares.com/gallery/sprites/guest-works/zombie-turkey/" title="Puppet Nightmares">Puppet Nightmares </a><br />
Turkey Leg &#8211; <a href="http://kenj.deviantart.com/" title="deviantArt">Kenj</a><br />
Mini Turkey &#8211; <a href="http://mikaristar.deviantart.com/" title="deviantArt">MikariStar</a><br />
Evil Turkeys &#8211; <a href="http://dmn666.deviantart.com/" title="deviantArt">DMN666</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2012/11/construct-2-html5-mobile-game-turkey-trot-of-doom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AngularJS SignIt! &#8211; Custom directives and form controls</title>
		<link>http://ericterpstra.com/2012/10/angularjs-signit-custom-directives-and-form-controls/</link>
		<comments>http://ericterpstra.com/2012/10/angularjs-signit-custom-directives-and-form-controls/#comments</comments>
		<pubDate>Sun, 21 Oct 2012 19:35:11 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=409</guid>
		<description><![CDATA[Note: This is a companion post to Example CRUD App – Starring AngularJS, Backbone, Parse, StackMob and Yeoman. If you haven&#8217;t read that yet, please do so, otherwise this might not make much sense. The most prominent feature, by far, of AngularJS SignIt! is the signature pad. It&#8217;s a fixed-size canvas that can be drawn <a href='http://ericterpstra.com/2012/10/angularjs-signit-custom-directives-and-form-controls/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p><em>Note: This is a companion post to <a href="http://ericterpstra.com/2012/10/example-crud-app-starring-angularjs-backbone-parse-stackmob-and-yeoman/" title="Example CRUD App – Starring AngularJS, Backbone, Parse, StackMob and Yeoman">Example CRUD App – Starring AngularJS, Backbone, Parse, StackMob and Yeoman</a>.  If you haven&#8217;t read that yet, please do so, otherwise this might not make much sense.</em></p>
<p>The most prominent feature, by far, of AngularJS SignIt! is the signature pad.  It&#8217;s a fixed-size canvas that can be drawn upon with a mouse pointer or finger.  The code for this wonderful widget is provided as a jQuery plugin by <a href="http://thomasjbradley.ca/" title="Thomas Bradley">Thomas Bradley</a>.  There are a few more features for the signature pad than I use in this app, and I encourage you to check out the <a href="http://thomasjbradley.ca/lab/signature-pad/" title="Signature Pad ">full documentation</a> if you get a chance.  It&#8217;s pretty great.</p>
<p>In order to implement the signature pad into my form, It must be a required field, and have the data included with the other fields when the form is submitted.  The sig pad works by creating objects of x/y coordinates that correspond to marks on the canvas.  When drawing on the pad, all that data gets set into a hidden form field. The data from that field is what needs to get into the Angular scope, and get validated by Angular&#8217;s form validation routine.  Oh, and Angular somehow needs to fire the custom validation function built into the signature pad.</p>
<p>Luckily, this is the type of thing directives were built for. Custom directives let you create custom html tags that get parsed and rendered by Angular.  So to start out, I created a custom directive called <em>sigpad</em> that is used by placing <code class="codecolorer html4strict default"><span class="html4strict"><span style="color: #009900;">&lt;sigpad&gt;&lt;<span style="color: #66cc66;">/</span>sigpad&gt;</span></span></code> in my HTML.  The sigpad tag then gets replaced by the directive&#8217;s template HTML.  The template for the HTML5 signature pad is just the default snippet taken directly from the <a href="http://thomasjbradley.ca/lab/signature-pad/#accept-html" title="Sigpad documentation">signature pad documentation</a>.  See below:</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;control sigPad&quot;</span>&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a> <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;sig sigWrapper&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;canvas <span style="color: #000066;">class</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pad&quot;</span> <span style="color: #000066;">width</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;436&quot;</span> <span style="color: #000066;">height</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;120&quot;</span> ng-mouseup<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;updateModel()&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span>canvas&gt;</span><br />
&nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/div.html"><span style="color: #000000; font-weight: bold;">div</span></a>&gt;</span></div></div>
<p>The logic for the directive is defined in a separate Angular module (see <a href="https://github.com/ericterpstra/ngSignIt/blob/master/app/scripts/modules/directives.js" title="directives.js">directives.js</a> for full code).  Take a look at the code below, and be sure to review Angular&#8217;s <a href="http://docs.angularjs.org/guide/directive" title="Angular Directives Docs">documentation on directives</a>.  The Angular docs give a great conceptual overview, but the examples are a bit lacking.  I reviewed the docs many, many times, and still needed some help from the <a href="https://groups.google.com/forum/?fromgroups=#!topic/angular/uvAUMju5GSc" title="Angular google group">mailing list</a> to get this working correctly (thanks P.B. Darwin!).  </p>
<p>My biggest stumbling block was not using ngModelController, and instead trying to manipulate scope data directly.  When working with a form, Angular provides all sorts of awesome code to work with data and do some validation.  Basically, it all went down like this&#8230;</p>
<p>Insert the sigpad directive into the form with</p>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;sigpad ng-model<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'user.signature'</span> clearBtn<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;.clearButton&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;signature&quot;</span> required&gt;&lt;<span style="color: #66cc66;">/</span>sigpad&gt;</span></div></div>
<p>Now Angular knows to replace the sigpad element with the template defined earlier.  After this happens, Angular runs the <em>linking function</em> which contains all the logic for the directive.  The  little snippet shown below is in the linking function. It uses jQuery to select the template element (passed into the linking function as &#8216;element&#8217;) and runs the signaturePad function from the <a href="http://thomasjbradley.ca/lab/signature-pad/#api-ref" title="Sigpad API">signature pad API</a>.  This is what creates the actual, drawable canvas.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> sigPadAPI <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>element<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">signaturePad</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;drawOnly<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;lineColour<span style="color: #339933;">:</span> <span style="color: #3366CC;">'#FFF'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>The ng-model=&#8217;user.signature&#8217; bit is key. This is how data is shared between the signature pad and Angular.  Also, go back up and look at the template. You will see <code class="codecolorer html4strict default"><span class="html4strict">ng-mouseup=&quot;updateModel()</span></code> as an attribute of the canvas element.  This tells Angular to run the updateModel() function when your mouse click ends on the signature pad.  The updateModel() function is defined in the <em>linking function</em> of the sigpad directive.</p>
<p>When the updateModel() function is executed, it will wait for a split second so the signature pad can finish writing data to its hidden form field, then it will assign all that data to the <em>Angular model</em> value of the directive. Sounds confusing, and it is. The signature pad is off doing its own thing, completely oblivious to the fact that it is in an AngularJS app.  It is Angular&#8217;s responsibility to grab data from the sigpad to get that data into its own scope.  That is what $setViewValue is for. It hands the signature data over to Angular, so when the form is submitted, Angular has it available in scope. </p>
<p>Below is the entire directive for the drawable signature pad.  You can see that it relies heavily on the signature pad API, but only after certain events handled by Angular have occurred.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #660066;">directive</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sigpad'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$timeout<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; templateUrl<span style="color: #339933;">:</span> <span style="color: #3366CC;">'views/sigPad.html'</span><span style="color: #339933;">,</span> &nbsp; <span style="color: #006600; font-style: italic;">// Use a template in an external file</span><br />
&nbsp; &nbsp; restrict<span style="color: #339933;">:</span> <span style="color: #3366CC;">'E'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #006600; font-style: italic;">// Must use &lt;sigpad&gt; element to invoke directive</span><br />
&nbsp; &nbsp; scope <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Create a new scope for the directive</span><br />
&nbsp; &nbsp; require<span style="color: #339933;">:</span> <span style="color: #3366CC;">'ngModel'</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Require the ngModel controller for the linking function</span><br />
&nbsp; &nbsp; link<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>scope<span style="color: #339933;">,</span>element<span style="color: #339933;">,</span>attr<span style="color: #339933;">,</span>ctrl<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Attach the Signature Pad plugin to the template and keep a reference to the signature pad as 'sigPadAPI'</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> sigPadAPI <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span>element<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">signaturePad</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drawOnly<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lineColour<span style="color: #339933;">:</span> <span style="color: #3366CC;">'#FFF'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Clear the canvas when the 'clear' button is clicked</span><br />
&nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>attr.<span style="color: #660066;">clearbtn</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigPadAPI.<span style="color: #660066;">clearCanvas</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; $<span style="color: #009900;">&#40;</span>element<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.pad'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">on</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'touchend'</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>obj<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; scope.<span style="color: #660066;">updateModel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// when the mouse is lifted from the canvas, set the signature pad data as the model value</span><br />
&nbsp; &nbsp; &nbsp; scope.<span style="color: #660066;">updateModel</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $timeout<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctrl.$setViewValue<span style="color: #009900;">&#40;</span>sigPadAPI.<span style="color: #660066;">getSignature</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Render the signature data when the model has data. Otherwise clear the canvas.</span><br />
&nbsp; &nbsp; &nbsp; ctrl.$render <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> ctrl.$viewValue <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sigPadAPI.<span style="color: #660066;">regenerate</span><span style="color: #009900;">&#40;</span>ctrl.$viewValue<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// This occurs when signatureData is set to null in the main controller</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sigPadAPI.<span style="color: #660066;">clearCanvas</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Validate signature pad.</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// See http://docs.angularjs.org/guide/forms for more detail on how this works.</span><br />
&nbsp; &nbsp; &nbsp; ctrl.$parsers.<span style="color: #660066;">unshift</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>viewValue<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> sigPadAPI.<span style="color: #660066;">validateForm</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctrl.$setValidity<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sigpad'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> viewValue<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ctrl.$setValidity<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sigpad'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> undefined<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></div></div>
<p>And what about the tiny signatures that show up in the signatories list? Also a custom directive.  This one is smaller, but still tricky.  The signature is displayed as an image on-screen, but a canvas element is still required to generate the signature from raw data before it can be converted to an image.</p>
<p>The directive is implemented with <code class="codecolorer html4strict default"><span class="html4strict"><span style="color: #009900;">&lt;regensigpad sigdata<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#123;</span>signed.get<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'signature'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#125;</span>&gt;&lt;<span style="color: #66cc66;">/</span>regensigpad&gt;</span></span></code>. The &#8216;signed&#8217; value is a single signature in the signature collection pulled from the back-end when the user picks a petition.  the signature data from <em>signed</em> is passed into the directive scope using <code class="codecolorer javascript default"><span class="javascript">scope<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>sigdata<span style="color: #339933;">:</span><span style="color: #3366CC;">'@'</span><span style="color: #009900;">&#125;</span></span></code>.  </p>
<p>When a list of signatures is retrieved, each signature record (including first &#038; last name, email, and signature data) goes into a table row using ngRepeat.  The <em>regensigpad</em> directive is executed for each row.  The linking function will create a canvas element and make a <em>displayOnly</em> signature pad from it.  The signature drawing is regenerated from the data, and then the canvas is converted to PNG format.</p>
<p>This PNG data is then used in the <em>pic</em> scope value, which is bound to the ng-src of an img tag.  This img tag is the directive&#8217;s template, and will be inserted into the page.  The full code for this directive is below.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #660066;">directive</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'regensigpad'</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; template<span style="color: #339933;">:</span> <span style="color: #3366CC;">'&lt;img ng-src=&quot;{{pic}}&quot; /&gt;'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; restrict<span style="color: #339933;">:</span> <span style="color: #3366CC;">'E'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; scope<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>sigdata<span style="color: #339933;">:</span><span style="color: #3366CC;">'@'</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; link<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>scope<span style="color: #339933;">,</span>element<span style="color: #339933;">,</span>attr<span style="color: #339933;">,</span>ctrl<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// When the sigdata attribute changes...</span><br />
&nbsp; &nbsp; &nbsp; attr.$observe<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'sigdata'</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>val<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// ... create a blank canvas template and attach the signature pad plugin</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> sigPadAPI <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;div class=&quot;sig sigWrapper&quot;&gt;&lt;canvas class=&quot;pad&quot; width=&quot;436&quot; height=&quot;120&quot;&gt;&lt;/canvas&gt;&lt;/div&gt;'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">signaturePad</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; displayOnly<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// regenerate the signature onto the canvas</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigPadAPI.<span style="color: #660066;">regenerate</span><span style="color: #009900;">&#40;</span>val<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// convert the canvas to a PNG (Newer versions of Chrome, FF, and Safari only.)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; scope.<span style="color: #660066;">pic</span> <span style="color: #339933;">=</span> sigPadAPI.<span style="color: #660066;">getSignatureImage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>But that&#8217;s not all!  You might have noticed that the select box holding the names of each petition looks kinda fancy, and allows you to type stuff to filter the list.  This fancy form control is the <a href="http://ivaynberg.github.com/select2/" title="select2">select2</a> widget which is based of the <a href="http://harvesthq.github.com/chosen/" title="Chosen">Chosen</a> library. </p>
<p>I didn&#8217;t have to write my own directive for it though.  The <a href="http://angular-ui.github.com/" title="AngularUI">Angular-UI</a> project has already done the honors.  Angular-UI is an open-source <em>companion suite</em> for AngularJS.  It provides a whole pile of custom directives, and even a few extra filters.  Many of the directives are wrappers for other widgets and open source projects, like CodeMirror, Google Maps, Twitter Bootstrap modal windows, and many more.  It&#8217;s definitely worth looking into for any AngularJS project. </p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2012/10/angularjs-signit-custom-directives-and-form-controls/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AngularJS SignIt! &#8211; Interchangeable Parse, StackMob and Backbone Services</title>
		<link>http://ericterpstra.com/2012/10/angularjs-signit-interchangeable-parse-stackmob-and-backbone-services/</link>
		<comments>http://ericterpstra.com/2012/10/angularjs-signit-interchangeable-parse-stackmob-and-backbone-services/#comments</comments>
		<pubDate>Sun, 21 Oct 2012 18:31:37 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Resources]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[parse]]></category>
		<category><![CDATA[stackmob]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=403</guid>
		<description><![CDATA[Note: This is a companion post to Example CRUD App – Starring AngularJS, Backbone, Parse, StackMob and Yeoman. If you haven&#8217;t read that yet, please do so, otherwise this might not make much sense. The AngularJS SignIt! application basically has three different interactions with a web service &#8211; fetch petitions, save a signature, and fetch <a href='http://ericterpstra.com/2012/10/angularjs-signit-interchangeable-parse-stackmob-and-backbone-services/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p><em>Note: This is a companion post to <a href="http://ericterpstra.com/2012/10/example-crud-app-starring-angularjs-backbone-parse-stackmob-and-yeoman/" title="Example CRUD App – Starring AngularJS, Backbone, Parse, StackMob and Yeoman">Example CRUD App – Starring AngularJS, Backbone, Parse, StackMob and Yeoman</a>.  If you haven&#8217;t read that yet, please do so, otherwise this might not make much sense.</em></p>
<p>The AngularJS SignIt! application basically has three different interactions with a web service &#8211; fetch petitions, save a signature, and fetch a list of signatures based on the selected petition.  That&#8217;s it &#8211; a get, a save, and a query.  Initially, I was only using <a href="http://parse.com" title="Parse">Parse.com</a> to store data, so it was possible to include Parse specific objects and methods in my controller to save and get data.  </p>
<p>But then I remembered I have a <a href="http://www.stackmob.com" title="StackMob">StackMob</a> account just sitting around doing nothing, and thought I should put it to good use.  So now I have two (slightly) different options to store my signatures.  Rather than jumbling up my controller with code specific to StackMob and Parse, I created a module to abstract the Parse and StackMob APIs into their own services.  These services could then hide any code specific to Parse or StacMob behind a common interface used by the controller.</p>
<p>With the back-end(s) abstracted, all the controller needs to worry about is calling saveSignature, getPetitions, and getSignatures.  Below is a severely truncated version of the <a href="https://github.com/ericterpstra/ngSignIt/blob/master/app/scripts/controllers/main.js" title="Main Controller">Main Controller</a> that shows the three methods in use. Notice there is no mention of Parse or StackMob.</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> MainCtrl <span style="color: #339933;">=</span> ngSignItApp.<span style="color: #660066;">controller</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'MainCtrl'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$scope<span style="color: #339933;">,</span>DataService<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// GET A LIST OF SIGNATURES FOR A PETITION</span><br />
&nbsp; $scope.<span style="color: #660066;">getSignatures</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> getSignatures <span style="color: #009900;">&#40;</span>petitionId<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; DataService.<span style="color: #660066;">getSignatures</span><span style="color: #009900;">&#40;</span>petitionId<span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; $scope.$apply<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; $scope.<span style="color: #660066;">signatureList</span> <span style="color: #339933;">=</span> results<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// SAVE A SIGNATURE</span><br />
&nbsp; $scope.<span style="color: #660066;">saveSignature</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> saveSignature<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> &nbsp;<br />
&nbsp; &nbsp; DataService.<span style="color: #660066;">saveSignature</span><span style="color: #009900;">&#40;</span>$scope.<span style="color: #660066;">user</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #006600; font-style: italic;">//user is an object with firstName, lastName, email and signature attributes.</span><br />
&nbsp; &nbsp; &nbsp; $scope.<span style="color: #660066;">getSignatures</span><span style="color: #009900;">&#40;</span>$scope.<span style="color: #660066;">select2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//select2 is the value from the petition dropdown</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp;<br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #006600; font-style: italic;">// GET ALL PETITIONS</span><br />
&nbsp; DataService.<span style="color: #660066;">getPetitions</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; $scope.$apply<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; $scope.<span style="color: #660066;">petitionCollection</span> <span style="color: #339933;">=</span> results<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; $scope.<span style="color: #660066;">petitions</span> <span style="color: #339933;">=</span> results.<span style="color: #660066;">models</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>If you look closely, you&#8217;ll see that each service method is prefixed with <em>DataService</em>. This is the injectable that provides either the StackMob service, or Parse service to the controller. Each of those services has an implementation of the getSignatures, saveSignature, and getPetitions.  Take a look:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">angular.<span style="color: #660066;">module</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'DataServices'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <br />
<span style="color: #006600; font-style: italic;">// PARSE SERVICE</span><br />
.<span style="color: #660066;">factory</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'ParseService'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; Parse.<span style="color: #660066;">initialize</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&lt;PLEASE USE YOUR OWN APP KEY&gt;&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;&lt;PLEASE USE YOUR OWN API KEY&gt;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> Signature <span style="color: #339933;">=</span> Parse.<span style="color: #660066;">Object</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;signature&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> SignatureCollection <span style="color: #339933;">=</span> Parse.<span style="color: #660066;">Collection</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> model<span style="color: #339933;">:</span> Signature <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> Petition <span style="color: #339933;">=</span> Parse.<span style="color: #660066;">Object</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;petition&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> PetitionCollection <span style="color: #339933;">=</span> Parse.<span style="color: #660066;">Collection</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> model<span style="color: #339933;">:</span> Petition <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> ParseService <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// GET ALL PETITIONS</span><br />
&nbsp; &nbsp; &nbsp; getPetitions <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> getPetitions<span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> petitions <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> PetitionCollection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; petitions.<span style="color: #660066;">fetch</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>petitions<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// SAVE A SIGNATURE</span><br />
&nbsp; &nbsp; &nbsp; saveSignature <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> saveSignature<span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> sig <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Signature<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sig.<span style="color: #660066;">save</span><span style="color: #009900;">&#40;</span> data<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>obj<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>callback<span style="color: #009900;">&#40;</span>obj<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// GET A LIST OF SIGNATURES FOR A PETITION</span><br />
&nbsp; &nbsp; &nbsp; getSignatures <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> getSignatures<span style="color: #009900;">&#40;</span>petitionId<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> query <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Parse.<span style="color: #660066;">Query</span><span style="color: #009900;">&#40;</span>Signature<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; query.<span style="color: #660066;">equalTo</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;petitionId&quot;</span><span style="color: #339933;">,</span> petitionId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; query.<span style="color: #660066;">find</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> ParseService<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #006600; font-style: italic;">// STACKMOB SERVICE</span><br />
.<span style="color: #660066;">factory</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'StackMobService'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Init the StackMob API. This information is provided by the StackMob app dashboard</span><br />
&nbsp; &nbsp; StackMob.<span style="color: #660066;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; appName<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;ngsignit&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; clientSubdomain<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;&lt;PLEASE USE YOUR OWN SUBDOMAIN&gt;&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; publicKey<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;&lt;PLEASE USE YOUR OWN PUBLICKEY&gt;&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; apiVersion<span style="color: #339933;">:</span> <span style="color: #CC0000;">0</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> Signature <span style="color: #339933;">=</span> StackMob.<span style="color: #660066;">Model</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span>schemaName<span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;signature&quot;</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> SignatureCollection <span style="color: #339933;">=</span> StackMob.<span style="color: #660066;">Collection</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> model<span style="color: #339933;">:</span> Signature <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> Petition <span style="color: #339933;">=</span> StackMob.<span style="color: #660066;">Model</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span>schemaName<span style="color: #339933;">:</span><span style="color: #3366CC;">&quot;petition&quot;</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> PetitionCollection <span style="color: #339933;">=</span> StackMob.<span style="color: #660066;">Collection</span>.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> model<span style="color: #339933;">:</span> Petition <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> StackMobService <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; getPetitions <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> getPetitions<span style="color: #009900;">&#40;</span>callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> petitions <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> PetitionCollection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> q <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> StackMob.<span style="color: #660066;">Collection</span>.<span style="color: #660066;">Query</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; petitions.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span>q<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>petitions.<span style="color: #660066;">add</span><span style="color: #009900;">&#40;</span>results<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; error<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span> results<span style="color: #339933;">,</span>error<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Collection Error: &quot;</span> <span style="color: #339933;">+</span> error.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> &nbsp; &nbsp; <br />
<br />
&nbsp; &nbsp; &nbsp; saveSignature <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> saveSignature<span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> sigToSave <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Signature<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigToSave.<span style="color: #660066;">set</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; firstname<span style="color: #339933;">:</span> data.<span style="color: #660066;">firstName</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lastname<span style="color: #339933;">:</span> data.<span style="color: #660066;">lastName</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; petitionid<span style="color: #339933;">:</span> data.<span style="color: #660066;">petitionId</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; email<span style="color: #339933;">:</span> data.<span style="color: #660066;">email</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; signature<span style="color: #339933;">:</span> JSON.<span style="color: #660066;">stringify</span><span style="color: #009900;">&#40;</span>data.<span style="color: #660066;">signature</span><span style="color: #009900;">&#41;</span> <span style="color: #006600; font-style: italic;">//Also, StackMob does not allow arrays of objects, so we need to stringify the signature data and save it to a 'String' data field.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Then save, as usual.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; sigToSave.<span style="color: #660066;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>result<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>result<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; error<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>obj<span style="color: #339933;">,</span> error<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Error: &quot;</span> <span style="color: #339933;">+</span> error.<span style="color: #660066;">message</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
<br />
&nbsp; &nbsp; &nbsp; getSignatures <span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span> getSignatures<span style="color: #009900;">&#40;</span>petitionId<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> signatures <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> SignatureCollection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> q <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> StackMob.<span style="color: #660066;">Collection</span>.<span style="color: #660066;">Query</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> signatureArray <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; q.<span style="color: #660066;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'petitionid'</span><span style="color: #339933;">,</span>petitionId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; signatures.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span>q<span style="color: #339933;">,</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; success<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>collection<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; collection.<span style="color: #660066;">each</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">set</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; signature<span style="color: #339933;">:</span> JSON.<span style="color: #660066;">parse</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'signature'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; firstName<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'firstname'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lastName<span style="color: #339933;">:</span> <span style="color: #000066; font-weight: bold;">item</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'lastname'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; signatureArray.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #009900;">&#40;</span>signatureArray<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// The factory function returns StackMobService, which is injected into controllers.</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> StackMobService<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></div></div>
<p>This is an abridged version of the DataServices module.  To see the <a href="https://github.com/ericterpstra/ngSignIt/blob/master/app/scripts/modules/services.js" title="ngSignIt Services.js">full code</a>, as well as many more comments explaining the code, head over to <a href="https://github.com/ericterpstra/ngSignIt/tree/master/app/scripts" title="ngSIgnIt code">GitHub</a>.  The main point to observe here is that each service has slightly different code for getSignatures, getPetitions, and saveSignature.  Also, each service has its own initialization code for its respective back-end service.  The controller could care less though, because as long as the service methods accept and provide data in the right format, it&#8217;s happy.</p>
<p>But how does the controller know which service to use?  Well, if you paid attention to the controller code, you&#8217;ll see that &#8216;DataService&#8217; is injected, which is not defined yet.  In the full code, there is a service defined all the way at the bottom of the file.  It looks like this:</p>
<div class="codecolorer-container javascript default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.<span style="color: #660066;">factory</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'DataService'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>ParseService<span style="color: #339933;">,</span>StackMobService<span style="color: #339933;">,</span>BackboneService<span style="color: #339933;">,</span>$location<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; <span style="color: #003366; font-weight: bold;">var</span> serviceToUse <span style="color: #339933;">=</span> BackboneService<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> $location.<span style="color: #660066;">absUrl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">indexOf</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;stackmob&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span> <span style="color: #339933;">||</span> $location.<span style="color: #660066;">absUrl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">indexOf</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;4567&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span> <span style="color: #009900;">&#41;</span> serviceToUse <span style="color: #339933;">=</span> StackMobService<span style="color: #339933;">;</span><br />
&nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span> $location.<span style="color: #660066;">path</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">'/parse'</span> <span style="color: #009900;">&#41;</span> serviceToUse <span style="color: #339933;">=</span> ParseService<span style="color: #339933;">;</span><br />
<br />
&nbsp; <span style="color: #000066; font-weight: bold;">return</span> serviceToUse<span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>All the other services (ParseService, StackMobService, and BackboneService) are injected into this service.  In case you are wondering, BackboneService is yet another back-end service that can be used in place of the others &#8211; see the full code for details.  The code above simply examines the URL and decides which service get injected via DataService.  If &#8216;parse&#8217; appears as the url path (e.g. www.example.com/app/#/parse), then ParseService is returned.  StackMob requires that HTML apps be hosted on their servers, so just check the domain name for &#8216;stackmob&#8217; and return the StackMob service.  If neither of these conditions occur, then the BackboneService is returned, and no data is saved.</p>
<p>In retrospect, I think what I&#8217;ve got here is the beginnings of an OO-like interface &#8211; where a set of functions are defined to form a contract with the client ensuring their existence.  And the implementations of that interface are a set of adapters (or is it proxies?).  If I had to do this over, I would use a proper inheritance pattern with DataService as the abstract parent, and the other services as the implementations or subclasses.  One of these days I&#8217;ll get around to refactoring. One day&#8230;</p>
<p>Full Source: <a href="https://github.com/ericterpstra/ngSignIt" title="ngSignIt on GitHub">https://github.com/ericterpstra/ngSignIt</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2012/10/angularjs-signit-interchangeable-parse-stackmob-and-backbone-services/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Example CRUD App &#8211; Starring AngularJS, Backbone, Parse, StackMob and Yeoman</title>
		<link>http://ericterpstra.com/2012/10/example-crud-app-starring-angularjs-backbone-parse-stackmob-and-yeoman/</link>
		<comments>http://ericterpstra.com/2012/10/example-crud-app-starring-angularjs-backbone-parse-stackmob-and-yeoman/#comments</comments>
		<pubDate>Fri, 19 Oct 2012 15:33:26 +0000</pubDate>
		<dc:creator>eterps</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Resources]]></category>
		<category><![CDATA[angularjs]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[parse]]></category>
		<category><![CDATA[stackmob]]></category>

		<guid isPermaLink="false">http://ericterpstra.com/?p=390</guid>
		<description><![CDATA[AngularJS SignIt! After finishing my first experimental project in AngularJS, I wanted to try saving data, rather than just retrieving it. Angular has some great mechanisms for creating forms, so I put together a small application to test out more of what Angular has to offer. Oh, and I also wanted to build this using <a href='http://ericterpstra.com/2012/10/example-crud-app-starring-angularjs-backbone-parse-stackmob-and-yeoman/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p><a href="http://ericterpstra.com/wp-content/uploads/2012/10/ngSignIt.png"><img src="http://ericterpstra.com/wp-content/uploads/2012/10/ngSignIt-251x300.png" alt="" title="ngSignIt" width="251" height="300" class="alignright size-medium wp-image-391" /></a></p>
<h2>AngularJS SignIt!</h2>
<p>After finishing my <a href="http://ericterpstra.com/2012/09/angular-cats-an-angularjs-adventure-anthology/" title="Angular Cats! An AngularJS Adventure Anthology">first experimental project</a> in <a href="http://angularjs.org/" title="AngularJS">AngularJS</a>, I wanted to try saving data, rather than just retrieving it.  Angular has some great mechanisms for creating forms, so I put together a small application to test out more of what Angular has to offer. Oh, and I also wanted to build this using <a href="http://yeoman.io/" title="Yeoman">Yeoman</a>. More on that in a minute.</p>
<p>The app I ended up with is a petition signer.  A user chooses a petition from the select-box, enters a first name, last name and email into the form, and then signs the signature pad either by drawing with the mouse, or using a finger on a touchscreen.  Hitting the <em>Save</em> button will capture the information, and add it to the list of signatories for the selected petition. Pretty simple, no?</p>
<p>The really fun part comes when the data is saved.  Depending on the url, the application will choose a place to save the data.  If &#8216;parse&#8217; shows up in the url path, then Parse.com is used as the back-end.  If the application is hosted on StackMob&#8217;s server, then data is stored with StackMob.com.  If neither of these things occur, then data is just saved to a temporary Backbone collection and cleared out when you refresh the page. </p>
<p><strong>Try it out!</strong></p>
<ul>
<li><a href="http://ericterpstra.com/apps/ngSignIt/#/" title="Backbone SignIt">SignIt! &#8211; No saving, just signing</a></li>
<li><a href="http://ericterpstra.com/apps/ngSignIt/#/parse" title="Parse SignIt">SignIt! &#8211; Save signatures to Parse</a></li>
<li><a href="http://dev.ngsignit.bourbonbasement.stackmobapp.com/dist/#/" title="StackMob SignIt!">SignIt! &#8211; Try the StackMob version</a></li>
</ul>
<p>Please note that a modern browser is needed. This <em>will not work</em> on IE8 or lower. I have only tested it in the latest Chrome, Firefox 15, and Safari on iOS 5. YMMV with other browsers.  If I find the time, I&#8217;ll add in the fixes for IE later on.</p>
<p><strong>Get the Code</strong>: <a href="https://github.com/ericterpstra/ngSignIt" title="ngSignIt at Github">https://github.com/ericterpstra/ngSignIt</a></p>
<h2>A few more things&#8230;</h2>
<p>Aside from AngularJS, Parse, and StackMob, I threw in plenty of other nifty libraries and snippets to get this thing working and looking (kinda) nice.</p>
<ul>
<li>The <a href="http://ivaynberg.github.com/select2/" title="Select2">select2</a> component, wrapped in a directive provided by <a href="http://angular-ui.github.com/" title="Angular-UI">Angular-UI</a>. Angular-UI is a great add-on library for AngularJS that provides some neat widgets and additional functionality to directives.</li>
<li><a href="http://thomasjbradley.ca/lab/signature-pad/" title="HTML5 Signature Pad">HTML5 SignaturePad</a> jQuery plugin from <a href="http://thomasjbradley.ca" title="Thomas Bradley">Thomas Bradley</a>. </li>
<li><a href="http://twitter.github.com/bootstrap/" title="Twitter Bootstrap">Twitter Bootstrap</a> responsive stylesheet (try it on mobile!)</li>
<li>A font-face generated from fontsquirrel.com using Estrya&#8217;s Handwriting font.</li>
<li>Stack of paper CSS3 snippet from CSS-Tricks.com</li>
</ul>
<p>And, of course, Yeoman was involved. There is tons of functionality built into Yeoman for handling unit-tests, live compilation of SASS and CoffeeScript, dependency management, and other stuff.  I basically just used it for it&#8217;s AngularJS scaffolding, and to download some libraries via Bower.  It went something like this:</p>
<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">yeoman init angular ngSignIt<br />
<span style="color: #7a0874; font-weight: bold;">cd</span> ngSignIt<br />
yeoman <span style="color: #c20cb9; font-weight: bold;">install</span> jquery<br />
yeoman <span style="color: #c20cb9; font-weight: bold;">install</span> json2<br />
... etc ...</div></div>
<p>Then I went about building my application as usual.  Upon completion, I ran</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">yeoman build</div></div>
<p>to package everything that is needed into the &#8216;dist&#8217; folder, and plopped that on my web server. Done.</p>
<h2> // TODO</h2>
<p>In upcoming blog posts, I&#8217;ll go over some of the more interesting bits of code &#8211; namely the services module and custom directives. There are a fair number of comments in the code now, but I think a higher-level overview would add some value. Stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericterpstra.com/2012/10/example-crud-app-starring-angularjs-backbone-parse-stackmob-and-yeoman/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
