<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>IAmTheRockstar</title><link>http://iamtherockstar.com/blog/</link><description>Latest entries</description><language>en-us</language><lastBuildDate>Mon, 27 Feb 2012 15:40:37 -0700</lastBuildDate><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/IAmTheRockstar" /><feedburner:info uri="iamtherockstar" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>The Death of Ubuntu One Notes on the Web
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/PwLKTpLGlXo/</link><description>&lt;p&gt;Pre-cursor note (just in case): This isn't an official Ubuntu One post.  For those, go to the &lt;a href="https://one.ubuntu.com/blog/"&gt;Ubuntu One blog&lt;/a&gt;. I just work for them, and I have my own opinions.&lt;/p&gt;
&lt;p&gt;Today I submitted and landed the branch that will kill the web UI for Ubuntu One notes.  Users can still use Tomboy to sync, but you won't be able to access them from the web.  I know a vocal minority is upset about this.  To those, it's unfortunate.  I'm sorry.  However, I think the decision was a great one.&lt;/p&gt;
&lt;p&gt;The work was done in two branches.  The first removed the links on the website and python views and entries in urls.py (it's no secret that our web app uses Django).  The second one removes everything else: css, javascript, javascript dependencies, and the rest of the python files.  Here's the diffstat of that second branch: &lt;code&gt;103735 lines (+3/-103093) 92 files modified&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Think about that: more than 100k lines of code removed there.  Sure, we didn't write some of that, but we sure as hell needed to maintain it (it's our attitude that we own the stack).  Think about all the hidden bugs in there.  Speaking as someone who knew that code intimately (it was one of my first tasks to re-factor it when &lt;a href="http://iamtherockstar.com/blog/2011/02/08/changing-jobs-launchpad-ubuntu-one/"&gt;I first came to Ubuntu One&lt;/a&gt;), there's also a lot of technical debt there&lt;sup&gt;1&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;If code is liability, that's a lot of liability.&lt;/p&gt;
&lt;p&gt;We didn't see that much usage of the Web UI for Notes.  One of the reasons I was re-factoring it a year ago was so that we could make it less fragile.  It broke a lot.  Automated tests probably would have caught that, but the fact that users didn't notice when it broke is indicative of a feature that isn't being used.  Even after it was refactored, there were browser bugs that would occasionally surface, but no one seemed to notice.&lt;/p&gt;
&lt;p&gt;If features are an asset, Notes on the web were an asset that few people valued.&lt;/p&gt;
&lt;p&gt;I'm not a business guy, but it makes total sense for us to reduce the liability with little real cost.  Our team is small (but quick and amazing), so the less time we spend maintaining unused features, the more time we can spend making things that are awesome (and we are doing amazing things; stay tuned).&lt;/p&gt;
&lt;p&gt;The last thing that I want to address is this question that keeps getting asked in some form or another: &lt;strong&gt;&lt;em&gt;Why not make it open source and have the community maintain it?&lt;/em&gt;&lt;/strong&gt;  Here's how I respond to that: You don't get bored of a piece of software and punt it to open source.  You also can't think "Oh, the community will pick this up."  They won't.  You can't just assume there will be a "community" for it.  If you can't hold someone responsible for its maintenance, you can't expect it to be maintained.&lt;/p&gt;
&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; Technical debt is a fact of life on any development team, and specifically one a team that moves as quickly and kicks as much ass as the Ubuntu One team.  We try to mitigate it where we can, but it's a balancing act.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/PwLKTpLGlXo" height="1" width="1"/&gt;</description><pubDate>Mon, 27 Feb 2012 15:40:37 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2012/02/27/death-ubuntu-one-notes-web/</guid><category>ubuntuone</category><feedburner:origLink>http://iamtherockstar.com/blog/2012/02/27/death-ubuntu-one-notes-web/</feedburner:origLink></item><item><title>Node.js and Socket.io: Authentication All The Way Down
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/GqJsWkcpfgw/</link><description>&lt;p&gt;I have a little weekend-project that I've been working on since December. It started as tinkering, got really ambitious, and then settled down into something I was just playing with to learn some new things.  Learn new things I have.  This new project is built on Node.js using the &lt;a href="http://expressjs.com/"&gt;Express&lt;/a&gt; and &lt;a href="http://socket.io/"&gt;Socket.io&lt;/a&gt; libraries to make things a little easier.  I wrote the account creation/authentication code, and backed it with MongoDB.  However, when it got to honoring that login, things got a little tricky.&lt;/p&gt;
&lt;p&gt;The first thing you'll read about is the MemoryStore object in Express.  It's used to store sessions.  Take that MemoryStore object and throw it out the window.  Let's use Redis instead (separation of concerns FTW).  First, install the &lt;code&gt;connect-redis&lt;/code&gt; library.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;npm install connect-redis
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...and stick it in your app.js...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var express = require('express')
    ...
  , RedisStore = require('connect-redis')(express)
  , sessionStore = new RedisStore()

...

app.configure(function() {
    &amp;lt;snip&amp;gt;
    app.use(express.cookieParser());
    app.use(express.session({
        secret: 'YOURSOOPERSEKRITKEY',
        store: sessionStore
    }));
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you should have a &lt;code&gt;session&lt;/code&gt; property on each routes' request object.  I only stick the user id in the session and then just look it up when I need it.  Here's the rub: if you're using Socket.io, your socket doesn't have access to that cookie by default.  That's a real bummer.  The Socket.io wiki talks about this a bit, but it's not entirely clear on how to hook it to the existing session store, and who wants to re-implement code.&lt;/p&gt;
&lt;p&gt;One that I really like about Node is that basically everything is middleware.  All we do is set the authorization function to add the session object to the socket's handshakeData.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var app = express.createServer()
  , io = require('socket.io').listen(app)

io.configure(function() {
    io.set('authorization', function(data, callback) {
        if (data.headers.cookie) {
            var cookie = parseCookie(data.headers.cookie);
            sessionStore.get(cookie['connect.sid'], function(err, session) {
                if (err || !session) {
                    callback('Error', false);
                } else {
                    data.session = session;
                    callback(null, true);
                }
            });
        } else {
            callback('No cookie', false);
        }
    });
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, when you add your socket connection handler, you can do this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;io.sockets.on('connection', function(socket) {
    var session = socket.handshake.session;
    ...
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hooray, now you can fetch session data in the web socket.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/GqJsWkcpfgw" height="1" width="1"/&gt;</description><pubDate>Tue, 14 Feb 2012 21:01:55 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2012/02/14/nodejs-and-socketio-authentication-all-way-down/</guid><category>javascript,</category><category>node,</category><category>redis</category><feedburner:origLink>http://iamtherockstar.com/blog/2012/02/14/nodejs-and-socketio-authentication-all-way-down/</feedburner:origLink></item><item><title>Tech Tasks for a High School Intern
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/keHUGgHU1Y8/</link><description>&lt;p&gt;I'm planning on "hiring" my younger brother to do some work for me during his Spring Break in a few months.  He's 16, and has some tech skills, but his school is not very technical and so he could use more opportunities to learn from folks.  I thought I'd have him do some QA and some light programming (he's a fairly new but competent pythonista).  I say "hire" because I want to add some incentive to learning enough to get a summer job.&lt;/p&gt;
&lt;p&gt;Can you think of tasks that might be good for him to do?  Maybe you have an open source project that you could mentor him on, and in so doing, gain a contributor.  If you can think of something that you wished you had known when you started hacking, I'd appreciate if you'd please leave me a comment.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/keHUGgHU1Y8" height="1" width="1"/&gt;</description><pubDate>Mon, 13 Feb 2012 11:53:46 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2012/02/13/tech-tasks-high-school-intern/</guid><category>ubuntu,</category><category>free-software</category><feedburner:origLink>http://iamtherockstar.com/blog/2012/02/13/tech-tasks-high-school-intern/</feedburner:origLink></item><item><title>Announcement: YUI 3 Nightlies
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/xlTcVuASBiQ/</link><description>&lt;p&gt;I'd like to announce the general availability of a YUI 3 Nightly combo server.  Each night, it will check out and create a new build of the YUI 3 source code, and serve it via a combo handler.  In order to use it, just point your YUI_config to the new combo loader.  Information about it can be found at the main page at &lt;a href="http://yuinightly.com"&gt;YUI Nightly Doc Page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Why did I do this? There are a few reasons.  First, &lt;a href="http://one.ubuntu.com"&gt;Ubuntu One&lt;/a&gt; can't use the Yahoo! CDN because we're using SSL.  This means we have to run our own combo loader.  The problem with this is that it's a pain to go out and get new YUI and plug it into my dev environment just to get surprised by something that broke or something that changed, etc.  With the nightlies, I can regularly just point YUI to this combo loader and let it run.&lt;/p&gt;
&lt;p&gt;I'm using this in "production" for a small personal site, but I wouldn't recommend it be used it any production site that actually has uptime requirements.&lt;/p&gt;
&lt;p&gt;Comments, questions, and &lt;a href="https://github.com/rockstar/yui3-nightly-tools"&gt;pull requests&lt;/a&gt; welcome.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; The URL has now been changed to &lt;a href="http://yuinightly.com"&gt;http://yuinightly.com/&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/xlTcVuASBiQ" height="1" width="1"/&gt;</description><pubDate>Tue, 13 Dec 2011 11:19:06 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/12/13/announcement-yui-3-nightlies/</guid><category>yuiandyou,</category><category>ubuntuone</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/12/13/announcement-yui-3-nightlies/</feedburner:origLink></item><item><title>YUI and PhoneGap Sitting in a Tree
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/LDjGY5ROtGM/</link><description>&lt;p&gt;...K-I-S-S-I-N-G&lt;/p&gt;
&lt;p&gt;The Web and Mobile &lt;a href="http://one.ubuntu.com"&gt;Ubuntu One&lt;/a&gt; team is in Buenos Aires, Argentina (along with most of the rest of the Ubuntu One teams) exploring the boundaries we may experience merging the Web and Native App experiences.  I realized very quickly in this exploration project that I needed an end goal.  Since we are already using YUI on the web part of Ubuntu One, I figured that I needed to figure out where the limitations of YUI would be there.&lt;/p&gt;
&lt;p&gt;Enter &lt;a href="http://phonegap.com/"&gt;PhoneGap&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It became very clear that it'd be much better to use one of these "glue" frameworks than to roll our own (the &lt;strong&gt;&lt;em&gt;important&lt;/em&gt;&lt;/strong&gt; reason being that we'd rather do more fun things).  One of the first things I noticed is that the default PhoneGap doesn't really "compile" out of the box, which annoys me.  Once I linked in the &lt;code&gt;www&lt;/code&gt; folder properly, I had a good stub.&lt;/p&gt;
&lt;p&gt;Using the YUI Loader in PhoneGap is not impossible, but it's relatively impractical.  It stores a whitelist of URLs that you can get to, and even then, javascript is so required on the site that we can't afford to &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; have javascript.  At this point, I realized that all the front-end tweaking/ricing I've been doing for the last year or so gets thrown out the window.  I broke down and made giant rollup files for yui.js and yui.css.&lt;/p&gt;
&lt;p&gt;As a sidenote, I also took the time to actually explore the &lt;a href="http://yuilibrary.com/yui/docs/app/"&gt;YUI App Framework&lt;/a&gt; by coding rather than reading about it (which I've done a lot).  There is an &lt;a href="http://yuilibrary.com/yui/docs/app/app-todo.html"&gt;example Todo app&lt;/a&gt; (thus, the reason why I made a todo app).  So I essentially cargo-culted that code.&lt;/p&gt;
&lt;p&gt;Sometime during this cargo-culting, I realized one very important thing: &lt;strong&gt;Debugging PhoneGap apps is a pain in the ass&lt;/strong&gt;.  It really is.  It resulted in &lt;a href="https://twitter.com/#!/rockstar_/status/144973244640931840"&gt;this late night tweet&lt;/a&gt; (which I was at least half serious about).  Unless you're a human jslint machine (and if your name is not Doug Crockford, I assert that you are &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; a human jslint machine), you're bound to make typos and syntax errors and such.  You don't really get a decent access to the console&lt;super&gt;1&lt;/super&gt;.  I tried running the app in a normal desktop browser but I found that events I was expecting either weren't firing or weren't being handled (without a console, I don't know).  I eventually went digging into the PhoneGap js that comes with the default template, and realized that I needed to just kill the PhoneGap js when testing in my browser.  The browser only takes you so far, but it at least helped me to get the YUI toolchain sorted out.&lt;/p&gt;
&lt;p&gt;I then took a bit of time sorting through the touch-specific interface and adapting the App example to that interface.  For instance, hover events are useless on mobile. I also found that the "keypress" event for the Enter key in an input wasn't firing with the keyboard "return".  Apparently, the iPhone wants the form input wrapped in a form itself, and then it'll show the "Done" button in the on-screen keyboard, which will send the right event (make sure that the form doesn't actually submit).&lt;/p&gt;
&lt;p&gt;The end result is &lt;a href="https://github.com/rockstar/MoarTodo"&gt;MoarTodo&lt;/a&gt;&lt;super&gt;2&lt;/super&gt;.  It's a really ugly app, but it's academic and I just wanted to learn about the toolchain.  I can't imagine &lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt; using something like PhoneGap (it doesn't have to actually &lt;strong&gt;&lt;em&gt;be&lt;/em&gt;&lt;/strong&gt; PhoneGap) to build a mobile web app to be distributed through the various app stores.  I expect there will be more to the debugging story, but it's still a learning curve.&lt;/p&gt;
&lt;p&gt;I still feel pretty strongly that the Native vs. Web argument will continue, and that they'll still have their various places.  I look forward to a day when that argument is settled, but I also look forward to the Year of the Linux Desktop, the rapture, and Santa Claus.&lt;/p&gt;
&lt;p&gt;&lt;super&gt;1&lt;/super&gt; I didn't try Weinre because I had switched to using iWebInspector a few weeks ago (when I wasn't using a PhoneGap container), and so didn't have it immediately on my system.  I'll probably have to go back and try it out in a PhoneGap context.&lt;/p&gt;
&lt;p&gt;&lt;super&gt;2&lt;/super&gt; Xcode creates new projects with Git. I'm not making a political statement here.  I just pushed it where it was easiest. Don't hate.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/LDjGY5ROtGM" height="1" width="1"/&gt;</description><pubDate>Fri, 09 Dec 2011 12:05:56 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/12/09/yui-and-phonegap-sitting-tree/</guid><category>javascript,</category><category>yuiandyou,</category><category>mobile,</category><category>ubuntuone</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/12/09/yui-and-phonegap-sitting-tree/</feedburner:origLink></item><item><title>THE Ubuntu Success Story
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/NYY5jhHNuGQ/</link><description>&lt;p&gt;Last night, I came home from a meeting, kissed my wife, and was walking back upstairs when my coat started vibrating.  I pulled my phone out to see that I was too late, and wasn't able to answer a phone call from my dad.  I called him back, and here's a summary of the beginning of that conversation.&lt;/p&gt;
&lt;p&gt;Me: "Hi dad."&lt;/p&gt;
&lt;p&gt;Dad: "Hi"&lt;/p&gt;
&lt;p&gt;Me: "Did you call? What did you need?"&lt;/p&gt;
&lt;p&gt;Dad: "I did.  I installed Ubuntu and now I'm trying to figure out how to install the driver for my video card."&lt;/p&gt;
&lt;p&gt;Me: "Waaaaaaaaaaitaminute. There's a backstory here that I have to know before we go any further."&lt;/p&gt;
&lt;p&gt;My dad is "technical".  I remember as a little kid realizing how excited my dad was when he was installing Windows 95 the day it came out.  I spent summers and school holidays making money at the company he worked for by being the floppy swapper when installing software.  He was also the person who introduced me to the term "freetard".  He's always been pretty resistant to free software, and sometimes for good reason (ever tried sending a document back and forth between on OpenOffice environment and a MS Office environment multiple times?). Last year for Christmas, my little brother Matt received a netbook that got infected before Christmas Day was over. I offered to put Ubuntu on it (something he wanted) but my dad was so resistant that he went out and bought a USB CD-ROM drive just so he could make sure Windows stayed on the machine.&lt;/p&gt;
&lt;p&gt;For me, Ubuntu has never been about "So easy my mom can use it", but "So simple my dad doesn't have a reason not to use it".&lt;super&gt;1&lt;/super&gt;&lt;/p&gt;
&lt;p&gt;As the story unfolded, my dad had been exploring the idea of virtual machines for a client, and had installed Ubuntu in a Virtual PC environment on Windows 7 host.  Unfortunately, his video would only give him 800x600, when his Windows XP guest would fill his dual-monitor setup easily.  He expected this to be a driver issue (Virtual PC apparently doesn't have a driver pack for guests like VirtualBox and VMWare do).  I found &lt;a href="https://help.ubuntu.com/community/HowToConfigureUbuntuForMicrosoftVirtualPC2004"&gt;this article&lt;/a&gt;, but as I looked at the instructions, I thought "Holy crap. I wouldn't even do this."  It became pretty clear that Microsoft Virtual PC was a pretty hostile environment to anything non-Windows.&lt;/p&gt;
&lt;p&gt;At this point, my dad starts asking about the Windows installer he saw for Ubuntu (Wubi).  Most of his concern centered around whether or not it was going to screw up his Windows partition (it doesn't).  After a bit of talk about Wubi, we ended the phone call.&lt;/p&gt;
&lt;p&gt;This morning, I get an email from him that says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Installed 32-bit Ubuntu on my system last night (Wubi).
   Booted this morning and found that my USB keyboard/mouse
   combo is not recognized at Ubuntu login screen.  No time to
   troubleshoot this morning before work and probably won’t
   spend a great deal of time on it, but wondered if you had any
   ideas of things I could try this evening.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Sounds like he's got a bluetooth keyboard/mouse combo that is having problems.  It's not a happy ending just yet, but it's a giant step in the right direction.&lt;/p&gt;
&lt;p&gt;The Chasm. Ubuntu is crossing it.&lt;/p&gt;
&lt;p&gt;&lt;super&gt;1&lt;/super&gt; I gave my mom my old laptop, running Ubuntu, and connected to &lt;a href="http://www.canonical.com/enterprise-services/ubuntu-advantage/landscape"&gt;Landscape&lt;/a&gt; so I can manage it for her.  She's not technical, and Ubuntu satisfies most of her computer needs (the only one that it doesn't satisfy is that she has no genealogy software that's compatible with the other software she uses).&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/NYY5jhHNuGQ" height="1" width="1"/&gt;</description><pubDate>Wed, 30 Nov 2011 12:50:21 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/11/30/ubuntu-success-story/</guid><category>ubuntu</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/11/30/ubuntu-success-story/</feedburner:origLink></item><item><title>Using Mustache templates in Express Apps
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/ZX4V-SSJEOc/</link><description>&lt;p&gt;Tonight I decided to hack on a quick little webapp and use the opportunity to explore some tech that I've only gotten to tinker with so far.  I wanted to build a small webapp with &lt;a href="http://expressjs.com/"&gt;express&lt;/a&gt;, but I &lt;strong&gt;hate&lt;/strong&gt; &lt;a href="http://jade-lang.com/"&gt;jade&lt;/a&gt; templating (I realize this may make me a javascript heretic).  Since I'd rather just write HTML, I decided to use &lt;a href="http://mustache.github.com/"&gt;Mustache&lt;/a&gt; (plus, I have previous experience with Mustache).&lt;/p&gt;
&lt;p&gt;The biggest problem with Node.js in general is that development is too fast.  Blog posts get out of date really quick.  I found a few blogs that show how to do it, but they're more than a year old, and at that point, it's almost worthless.  Then I found &lt;a href="https://github.com/fat/stache"&gt;stache&lt;/a&gt;.  The docs there helped out to get me most of the way there.  Here's what I did to get a basic express app using mustache.&lt;/p&gt;
&lt;p&gt;First, install express and stache, and then create a new express app named myApp:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo npm install -g express stache
express myApp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now change into the myApp directory.  Edit app.js.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var stache = require('stache');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...import stache and then configure the app to use stache (you'll replace the existing jade config)...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;app.set('view engine', 'mustache');
app.register('.mustache', stache);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, I'm using a .mustache extension for my templates, and then passing stache to it as the handler for mustache templates.&lt;/p&gt;
&lt;p&gt;In your views/ folder, you should see two files that the &lt;code&gt;express&lt;/code&gt; command created by default: &lt;code&gt;layout.jade&lt;/code&gt; and &lt;code&gt;index.jade&lt;/code&gt;.  We want to replace these with mustache stubs similar to these files.  Let's start with &lt;code&gt;layout.mustache&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
        &amp;lt;title&amp;gt;{{title}}&amp;lt;/title&amp;gt;
    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
        {{{yield}}}
    &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In stache, {{{yield}}} seems to be a special keyword for using the subtemplate.  Make sure you remember all three suspenders around it, or you'll spend 20 minutes scratching your head and wondering why the HTML is being escaped (a behavior I hadn't ever used in mustache).&lt;/p&gt;
&lt;p&gt;Now in &lt;code&gt;index.mustache&lt;/code&gt;, we add the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;h1&amp;gt;{{title}}&amp;lt;/h1&amp;gt;
&amp;lt;p&amp;gt;Welcome to {{title}}&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, we've got a similar layout and template to the jade templates.  The last thing left to do is change the data structure of the context we pass (since mustache wants the template context in a different format).  Crack open routes/index.js and change the res.render call to look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;res.render('index', {
    locals: {
        title: 'Express'
    }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now fire up the app with &lt;code&gt;node app.js&lt;/code&gt; and hit /.  Does everything work?  Hooray! If not, uh, sorry.  I'd be interested to know what didn't work, so I can fix the post.&lt;/p&gt;
&lt;p&gt;In fact, since Node.js posts tend to get out of date, if this one does, please let me know and I'll update it accordingly.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/ZX4V-SSJEOc" height="1" width="1"/&gt;</description><pubDate>Mon, 21 Nov 2011 20:41:54 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/11/21/using-mustache-templates-express-apps/</guid><category>nodejs,</category><category>javascript</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/11/21/using-mustache-templates-express-apps/</feedburner:origLink></item><item><title>YUIConf 2011 Day 2
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/XPrhb2wy4Ps/</link><description>&lt;p&gt;A few days late, sure...&lt;/p&gt;
&lt;p&gt;Once again, I pity the fool who looks at my notes expecting them to be coherent.  They make sense to me, and that's why I took the notes.  Here's the highlights:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Andrew Wooldridge - YUI Hidden Gems&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I didn't expect to take many notes here, since I'd taken my fair share of dives into the YUI source code (I generally no longer care to read the online docs), but Andrew pointed out a few things I had glanced over and missed the value of.  Among them, he mentioned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Y.Frame - this is a wrapper for using the IFRAME element.  It creates a YUI  instance inside the IFRAME, so there's sandboxing, etc. but without the complications that come from IFRAME communication.  There are quite a few places that we could use this in Ubuntu One.  In particular, I think we could use it for the multi-file upload that we've been wanting to do for a long time.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Y.DOM.inViewPortRegion - The previous day, I went looking into the ImageLoader source to see how it worked, since the NFL talk mentioned a WidgetFold that only rendered the widget when it came into the viewport, and I was curious how it did it.  Even though I had found this hidden gem the day before, it's worth noting its value in all sorts of cases.  What I'd like to do is make a synthetic event for Node such that we can hook eventHandlers into "enterViewPortRegion" and "exitViewPortRegion" or something similar.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Y.on('hover') - How did I miss this?  It's a synthetic event that YUI provides, since mouseOver and mouseOut can be a bit of a fun house of edge cases.  Quite useful.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Y.on('clickoutside') - I use this in my little phazr library to close on Overlay or Dialog.  It's fantastic.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Y.Later - A wrapper for setTimeout and setInterval.  I made specific notes to play with this in some of the U1 things that I'm working on right now.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Eric ForRealYo - The App Framework&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This talk Melted. My. Brain.  A common theme that I heard repeatedly was that people tend to implement things in YUI, and right when they're finished, the YUI team announces the exact same thing in YUI.  I did this recently with the App Framework.&lt;/p&gt;
&lt;p&gt;The App Framework in YUI 3.4 leaves just a bit to be desired, but Eric's talk made it clear in his talk that all those desires will be available in YUI 3.5 (with a promised pr release in December).  Eric had mentioned earlier in the week that he kind of looked at the iOS UI framework API when designing the App Framework, and I can see that connection.  It's got a pretty good disconnect between data and presentation, which can often be kind of painful if you don't give it some thought.  A nice API like the one the YUI team has designed makes it easy to design things correctly without putting too much thought into it.&lt;/p&gt;
&lt;p&gt;One of the things I'm looking forward to the most in YUI 3.5 is the addition of support for Handlebars templating.  This templating will be directly connected into Y.View, but won't be compulsory, so you can use any template system you'd like, and aren't forced in to Handlerbars.&lt;/p&gt;
&lt;p&gt;As it stands now, YUI 3.4 has some of the App Framework stuff, and in particular, it has Model and ModelList, which have events that can be hooked into.  To me, that's the best way to start using the App framework.  Create widgets that handle events in your Model and ModelList instances.  At the very least, that means that I have a clear upgrade path from my app framework to YUI's (so I don't have to maintain code, I can just file a bug and complain...  :)&lt;/p&gt;
&lt;p&gt;After all of this, it became clear that I've been neglecting the YUI Gallery, both in contributing to it and using it.  I need to remedy that.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/XPrhb2wy4Ps" height="1" width="1"/&gt;</description><pubDate>Tue, 08 Nov 2011 10:48:55 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/11/08/yuiconf-2011-day-2/</guid><category>javascript,</category><category>yuiandyou,</category><category>ubuntuone</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/11/08/yuiconf-2011-day-2/</feedburner:origLink></item><item><title>YUIConf 2011 Day 1
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/H63wcJd1kb4/</link><description>&lt;p&gt;Day 1 of YUIConf 2011 is over.  I didn't keep copious notes that are coherent to anyone but myself.  Here is a congealed version of my notes (hopefully they aren't too hard to follow).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dav Glass - Keynote&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dav said something that seemed to ring very true to me about the "Graded Browser Scale".  Instead of talking about browser support, he started referring to it as a list of platforms to test on.  If everything works on that list of platforms, it &lt;strong&gt;&lt;em&gt;should&lt;/em&gt;&lt;/strong&gt; work on everything.  This is usually the way that I think about testing my own projects, and probably the way we should start thinking about Ubuntu One (granted that we don't see too much IE 6/7 on Ubuntu One currently).&lt;/p&gt;
&lt;p&gt;The YUI team is starting to think more about time based releases.  Having worked for Canonical for so long, I love the "cadence" that time-based releases bring.  I hope this means new YUI features are available in a faster manner, but mostly I'm looking forward to the promise of being more open with what features are being worked on.  It seems that we at Ubuntu One aren't the only ones implementing things that the YUI team end up releasing right after we finish writing it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Luke Smith - From one, many; From many, one&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One of the hardest and most overwhelming things about YUI is figuring out how to implement features.  Should I use a Plugin, a Widget, or an Extension.  Along with that, if you're used to class-based inheritance, inheritance (or the oddities thereof) of javascript is a little awkward.  In general, for what I'm building, I don't need to worry about how the constructors link together, so I usually just build off of Y.Base and everything is fine.&lt;/p&gt;
&lt;p&gt;One &lt;strong&gt;&lt;em&gt;really&lt;/em&gt;&lt;/strong&gt; important thing I had previously personally asserted and Luke confirmed to me is this: Unless you have a valid reason, &lt;strong&gt;use Y.Base.create&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Jeff Craig - Demystifying Loader&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This was easily the best talk I went to today.  The YUI Loader is a fantastic little piece of YUI, but it's also a black hole for documentation and isn't something most people grok.  At Ubuntu One, we use &lt;a href="https://launchpad.net/convoy"&gt;convoy&lt;/a&gt; for combo loading YUI, and our configuration is a bit complicated.  I've known about some of the things we could do to make it less complicated, but this was pretty beneficial for me.  Particularly, the Loader can conditionally load modules, which should help in cases where we use modules to "monkey-patch" other modules in certain cases &lt;em&gt;cough&lt;/em&gt;IO&lt;em&gt;cough&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ryan Cannon - There is no off-season.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ryan talked about implementing YUI on NFL.com.  This is very similar to a talk I proposed for YUIConf this year as well.  Essentially, I like the stories of "This is how we got our site all working in YUI".  They wrote a really neat sounding widget they called WidgetFold that only rendered the widget once the user scrolled down to see the widget.  I can think of all kinds of uses for that kind of widget.&lt;/p&gt;
&lt;p&gt;The highlight of Ryan's talk was "Are you writing scripts or building applications?"  He used it in the context of picking the right tool for the job.  I often bring up this theme when people ask "Why not just use jQuery?", but the way Ryan phrased it is pretty excellent.&lt;/p&gt;
&lt;p&gt;I bypassed taking notes for the last two talks of the day.  After dinner, Douglas Crockford spoke.  My notes would make absolutely no sense, in that they are all over the place.  The talk was about jslint (which Doug wrote). As a summarizing quote (although it doesn't nearly do the talk justice), I noted "use of good style can help reduce errors".&lt;/p&gt;
&lt;p&gt;Afterwards, someone pointed me to the &lt;a href="https://github.com/douglascrockford/JSLint/issues?sort=created&amp;amp;direction=desc&amp;amp;state=closed&amp;amp;page=1"&gt;github issues page for jslint&lt;/a&gt;.  Doug's responses are &lt;strong&gt;&lt;em&gt;pure&lt;/em&gt;&lt;/strong&gt; comedy.  Next time I'm having a bad day, instead of going to laugh at bad Craigslist personals, I'm going to laugh at jslint issues on Github.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/H63wcJd1kb4" height="1" width="1"/&gt;</description><pubDate>Fri, 04 Nov 2011 00:56:37 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/11/04/yuiconf-2011-day-1/</guid><category>javascript,</category><category>yuiandyou</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/11/04/yuiconf-2011-day-1/</feedburner:origLink></item><item><title>Skeleton Jump is out!
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/ZqAkpJsrBqY/</link><description>&lt;p&gt;Last night, &lt;a href="https://www.facebook.com/SkeletonJump"&gt;Skeleton Jump&lt;/a&gt; got published to the App Store.  &lt;a href="http://itunes.apple.com/us/app/skeleton-jump/id474091868?mt=8"&gt;Download it&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;I've been working on this game for about a month, having had no previous iPhone development experience (outside of tinkering, really).  I've been terrified of putting this out there, knowing about some heinous bugs that still exist in the game (but I can't find the cause for).  It doesn't look like many people have problems with them, so I've been afraid for no reason.&lt;/p&gt;
&lt;p&gt;Hooray for releasing code!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/ZqAkpJsrBqY" height="1" width="1"/&gt;</description><pubDate>Tue, 25 Oct 2011 10:22:19 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/10/25/skeleton-jump-out/</guid><category>ios,</category><category>games,</category><category>mobile</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/10/25/skeleton-jump-out/</feedburner:origLink></item><item><title>Thoughts on Mobile Development Platforms
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/eBZ1N4puVYQ/</link><description>&lt;p&gt;I've been thinking about writing this post for about a month now.  I should preface it by saying that I've found myself internally conflicted between software freedom and making a living.  This is a fact that I'm reminded of every time I point out to a member of the Ubuntu community that &lt;a href="http://iamtherockstar.com/blog/2011/02/08/changing-jobs-launchpad-ubuntu-one/"&gt;I've moved from working on Launchpad to working on Ubuntu One&lt;/a&gt;.  Let me be straight about this: I &lt;strong&gt;love&lt;/strong&gt; Ubuntu, and I love software freedom.  I also love fistfuls of cash.  Some days, this internal conflict is maddening.&lt;/p&gt;
&lt;p&gt;I have loved games since I was young enough to remember. My interest in technology came from learning to repair my NES console when I was 5.  Last month, I met a fantastic artist named &lt;a href="http://jesssmartsmiley.wordpress.com/"&gt;Jess Smart Smiley&lt;/a&gt;.  He and I conspired to make a Halloween themed game in our spare time.&lt;/p&gt;
&lt;p&gt;I don't have much of a desire to create games professionally, so I'm more interested in designing and creating games classified as "indie".  Having &lt;a href="http://iamtherockstar.com/blog/2010/01/31/app-store-distribution-and-indie-game-creation-rev/"&gt;blogged about the potential ecosystem for indie games&lt;/a&gt; before, I already had a head start on what our first target would be.&lt;/p&gt;
&lt;p&gt;The first thing we thought about is existing and mature development libraries.  The most popular mobile game framework is &lt;a href="http://www.cocos2d-iphone.org/"&gt;cocos2d&lt;/a&gt;.  It was originally a framework for iOS, but also has &lt;a href="http://code.google.com/p/cocos2d-android/"&gt;an Android port&lt;/a&gt;.  I also considered Ansca Mobile's &lt;a href="http://www.anscamobile.com/corona/"&gt;Corona framework&lt;/a&gt;, but its high cost for both platforms (iOS and Android) made me eliminate it.  The Android port of cocos2d had it's last commit Nov 15, 2010.&lt;/p&gt;
&lt;p&gt;After looking at software, we started looking at the hardware.  I have never owned an iPhone, but I've owned every one of Google's official Android phones.  My wife has also had Android phones for a number of years now.  She's not a gadget person, but she recently fell in love with an Android tablet (the Asus Transformer) and so we have a number of Android devices around the house.  The only iOS device we had was my iPad.  As I looked at the form factors and various hardware for Android, I thought "Oh man, this is going to be a QA nightmare."  I tried out a number of Android devices and they each had their own quirks/lag/bugs.  With the exception of a weird home screen bug in my Android devices, I never had that "lag" that everyone seems to be complaining about on my Nexus phones, but my wife's first Android phone was a huge piece of junk with a plastic touchscreen and Android 1.6.  There are basically 4 different hardware configurations for iOS, and only 4 (currently).&lt;/p&gt;
&lt;p&gt;We decided that our first game would target iOS.&lt;/p&gt;
&lt;p&gt;After we decided on iOS, I had lunch and/or !coffee with a few local mobile game developers.  All but one had experience with both Android and iOS.  They all had the same problem with the Android market: people decompiling/recompiling their apps and putting them on the Android Market for free.  It's basically an arms race at that point, where you spend your days sending takedown notices to various Android stores instead of developing new stuff.  The developers who were still committed to Android said that the only way they've made money is by using ads.  I don't like that, since your mobile's screen is small enough already without ads taking up part of the screen (or dealing with artificial load times while you show ads).&lt;/p&gt;
&lt;p&gt;We'll probably move into Android in the future, especially with its market share growing like it is.  However, for the our first game, I feel confident iOS was the best platform to deploy to.&lt;/p&gt;
&lt;p&gt;If you're interested in our game, &lt;a href="https://www.facebook.com/SkeletonJump"&gt;become a fan of Skeleton Jump on Facebook&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;a href="https://twitter.com/#!/luciotorre/status/128672008782348288"&gt;Lucio points out on Twitter&lt;/a&gt; that cocos2d is actually originally &lt;a href="http://cocos2d.org/"&gt;a python implementation&lt;/a&gt;.  I knew this, but didn't see much connection between the two.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/eBZ1N4puVYQ" height="1" width="1"/&gt;</description><pubDate>Mon, 24 Oct 2011 21:04:20 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/10/24/thoughts-mobile-development-platforms/</guid><category>ios,</category><category>android,</category><category>mobile,</category><category>cocos2d,</category><category>games</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/10/24/thoughts-mobile-development-platforms/</feedburner:origLink></item><item><title>Confusing UX: Facebook's Lists
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/BMEFMjnmvAk/</link><description>&lt;p&gt;One thing I really like about Google+ is the ability to limit your posts to a "Circle" of people.  Facebook recently added a similar feature.  I decided to try it out and share a post with all my roller derby friends (&lt;a href="http://blog.paulhummer.org/my-wife-can-beat-up-your-wife"&gt;including my wife&lt;/a&gt;).  So I start exploring the UI and hit this:&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;img src="http://ubuntuone.com/19D22f50yBmZ7miKOqpECP" alt="Facebook list ui"&gt;&lt;/p&gt;

&lt;p&gt;I had no idea what to put in the "Hide this from" text box.  Maybe "everybody else"?  Turns out, you can ignore it, and it'll be limited to just that single list.  I assume that box is so that you can add a list and then exclude someone.  Please to hide that away, or even take away the feature entirely.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/BMEFMjnmvAk" height="1" width="1"/&gt;</description><pubDate>Tue, 11 Oct 2011 19:17:08 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/10/11/confusing-ux-facebooks-lists/</guid><category>ux</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/10/11/confusing-ux-facebooks-lists/</feedburner:origLink></item><item><title>I Hate the Android Back Button
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/wMbAasFCOuU/</link><description>&lt;p&gt;Android's Back button (whether in hardware or software) is braindead.  I can understand the technical reason for its behavior. It's supposed to take you to the previous Intent...&lt;/p&gt;
&lt;p&gt;...unless the current app has overridden the Back button.&lt;/p&gt;
&lt;p&gt;Here's an example:  Yesterday I attended &lt;a href="http://boulderux.com/"&gt;BLDR.UX11&lt;/a&gt;.  When I got into Boulder, I pulled over and pulled up my email with the ticket confirmation in it (using my Nexus S phone, not an Android phone with crapware on it).  From there, I opened the conference web site.  I then found an address for the venue and clicked on it, opting to open it in Maps.  Once there, I had Maps give me directions to the venue, and then hit the Navigate button for turn-by-turn navigation.  When I got to the Boulder Events Center, I grabbed my phone and hit back, which took me to the Maps app (from Navigation).  I hit back again and it went to the BLDR.UX11 page in the browser.  I hit back again.  WTF? Now I'm looking at an article I read on my phone while waiting in the doctor's office a week ago.  At this point, I repeatedly mashed the back button out of frustration until I was at the Home Screen (I realize I can use the Home button-I blame muscle memory).&lt;/p&gt;
&lt;p&gt;While at BLDR.UX11, I met lots of folks who feel that having a single unified experience across mobile devices is a myth, and almost all of them cited the Back button as the reason.  Some people go as far as to create their own back button in the app, which just makes the matter worse: now you have TWO back buttons.&lt;/p&gt;
&lt;/gripe&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/wMbAasFCOuU" height="1" width="1"/&gt;</description><pubDate>Tue, 13 Sep 2011 12:33:59 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/09/13/i-hate-android-back-button/</guid><category>bldrux11,</category><category>ux</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/09/13/i-hate-android-back-button/</feedburner:origLink></item><item><title>Cancelling my Safari Books Subscription
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/he0jZKpLIZA/</link><description>&lt;p&gt;I subscribed to Safari Books Online a few months ago.  I like the idea of monthly subscription access services à la Netflix, and I tend to read a lot of technical books, so it seemed like a good idea.  I just went through the flow for canceling that subscription, and I thought I'd document the reasons why, in case anyone else was curious.&lt;/p&gt;
&lt;p&gt;Safari subscriptions have tiers, and you pay a monthly amount based on the tier you pick.  I took the cheapest route, and opted for the 10-book "bookshelf".  I thought it'd be fine, since I try &lt;strong&gt;&lt;em&gt;real&lt;/em&gt;&lt;/strong&gt; hard not to read more than 2 books at the same time (and usually &lt;a href="http://blog.paulhummer.org/self-inflicted-force-fed-fiction"&gt;I try and make one a fiction book&lt;/a&gt;).  I went through and found a set of books I wanted to read, and added them to my bookshelf, essentially creating a backlog.&lt;/p&gt;
&lt;p&gt;In order to start reading, I had a few choices: read on my computer, download a chapter at a time, or read on a mobile device with the app.  Since I sit in front of a computer all day, I didn't want to spend my relaxing time in the same place.  Downloading a chapter at a time wasn't at all economical, since it was quite painful to assign a "download token" to the download, and I was limited in the number of download tokes I could have every month.  I installed the app on my iPad, and went to reading.&lt;/p&gt;
&lt;p&gt;The iPad app crashes &lt;strong&gt;&lt;em&gt;constantly&lt;/em&gt;&lt;/strong&gt;.  It requires an internet connection, so that limits where you can read it.  If the iPad went to sleep at all, I had to re-authenticate the app with my account, often making it lose my place in the book in the process.  When I turned pages, there was a latency that made the first-gen Kindle look blazing fast.  Some of the books were essentially glorified PDFs, so you couldn't resize text or even highlight it.  It was really painful.&lt;/p&gt;
&lt;p&gt;By the time I finished two books, I wasn't really interested in reading any more of the books I'd put on my bookshelf.  When I went to remove them, I found that they had to stay on my bookshelf for a minimum of a month.  If a book takes me a month to read, it had better be a freakin' &lt;strong&gt;&lt;em&gt;HUGE&lt;/em&gt;&lt;/strong&gt; page-turner.  At this point, the higher tiers started making more sense to me.  It was obvious why someone would want a larger bookshelf now.  I had gotten so trigger happy that I added books as a backlog that I never read, but sat in my shelf because I had to have them there for 30 days.&lt;/p&gt;
&lt;p&gt;The one saving grace is that I had added some instructional/tutorial videos.  I would regularly put these on while I cooked dinner or washed dishes in the evenings.  There was one about gamification and one about Cassandra that I particularly enjoyed.  I was never able to get the videos playing on my iPad, so I'd just prop my laptop on the microwave and play them.  There were some bugs with playback on my laptop, but I chalked most of them up to Flash just being extra stupid (which is always a safe assumption).&lt;/p&gt;
&lt;p&gt;Recently, Safari released a new mobile site, so I thought I'd give it a chance.  I read an entire book using the mobile site.  It too requires an internet connection (obviously).  There is a "Remember Me" checkbox when logging in, which I was pleased to see, since the app didn't have one.  I guess the mobile site has Alzheimer's though, since it would forget who I was even if I merely switched to another "tab" of the browser.  There was also a section of the book that was mostly code or diagrams, so I'd flip through the "pages" pretty quickly.  If I did it too quick, the site had to verify that I was human by prompting me with a captcha, which isn't very accessible, but also is a terrible thing to have to sort out on a mobile device.&lt;/p&gt;
&lt;p&gt;I understand the need for DRM on content I &lt;strong&gt;&lt;em&gt;don't&lt;/em&gt;&lt;/strong&gt; own.  If I check a book out of the public library, I'm not against the library putting protections to make sure I bring the book back.  Netflix requires DRM to stream, and I don't mind that.  The kicker here is that in both cases &lt;strong&gt;I don't notice the restrictions while enjoying the content&lt;/strong&gt;.  Safari, on the other hand, always had fiery hoops for me to jump through.  After getting a singed a few times, I think I'll pass.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/he0jZKpLIZA" height="1" width="1"/&gt;</description><pubDate>Sun, 04 Sep 2011 20:20:10 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/09/04/cancelling-my-safari-books-online-subscription/</guid><feedburner:origLink>http://iamtherockstar.com/blog/2011/09/04/cancelling-my-safari-books-online-subscription/</feedburner:origLink></item><item><title>Ubuntu One and YUI: "Stale" events
</title><link>http://feedproxy.google.com/~r/IAmTheRockstar/~3/fv2lB4Ap02w/</link><description>&lt;p&gt;A common pattern in any asynchronous web app is creating an item asynchronously, and updating the page to reflect that new item.  This is pretty core functionality of &lt;a href="http://iamtherockstar.com/blog/2011/08/18/yui-and-you-how-ubuntu-one-built-their-webapps/"&gt;Ubuntu One's Manager widgets&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What we started doing is something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;onSubmitForm: function(e) {
    var name = this.get('nameNode').get('value');
    Y.io('/notes/new', {
        method: 'POST',
        on: {
            success: Y.bind(this.onNewNoteSuccess, this)
        }
    });
},
onNewNoteSuccess: function(id, response) {
    Y.io('/notes/list', {
        on: {
            success: Y.bind(this.onNoteListSuccess, this)
        }
    });
},
onNoteListSuccess: function(id, response) {
    this.set('noteList', response.responseText);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is obviously asynchronous.  The problem is that once you start doing
this six or seven times (or ten) times, it starts to get pretty messy.  It
becomes a pain to come back even a few weeks later and trace
your steps through the code again. Part of this is asynchronous code in
general, but you can make some very easy changes that make it a little easier
to keep context in place.&lt;/p&gt;
&lt;p&gt;One of my absolute favorite things about YUI is that it creates an API
on top of the browser specific APIs, and thus allows for fun "middleware",
such as YUI's support for &lt;a href="http://yuilibrary.com/yui/docs/event/"&gt;custom events&lt;/a&gt;.  With these events, you can do
things like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Y.fire('stupidMadeUpEvent');
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...but, of course, that would be a no-op unless we had previously done...&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Y.on('stupidMadeUpEvent', function(e) {
    Y.log('The stupid event I made up just fired');
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once you start to see the vision behind it, it actually allows you to do some
pretty clever things.  For instance, I like to be able to mark page fragments
as stale, and have an event listener go and update that page fragment when
needed.  The above code then looks closer to this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;bindUI: function() {
    this.on('noteListStale', this.onNoteListStale, this);
},
onSubmitForm: function(e) {
    var name = this.get('nameNode').get('value');
    Y.io('/notes/new', {
        method: 'POST',
        on: {
            success: Y.bind(function() { this.fire('noteListStale'); }, this)
        }
    });
},
onNoteListStale: function(id, response) {
    Y.io('/notes/list', {
        on: {
            success: Y.bind(this.onNoteListSuccess, this)
        }
    });
},
onNoteListSuccess: function(id, response) {
    this.set('noteList', response.responseText);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This actually doesn't seem to be any more asynchronous or any faster, but I
will say that it makes our code a bit more maintainable.  Your mileage may
vary.&lt;/p&gt;
&lt;p&gt;You can fire an
event on any event target in scope (which includes Widget, Node, and
EventTarget objects). Between attribute change events and custom events, I
find that most of my entry points for code are specified in bindUI.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/IAmTheRockstar/~4/fv2lB4Ap02w" height="1" width="1"/&gt;</description><pubDate>Mon, 22 Aug 2011 13:59:44 -0700</pubDate><guid isPermaLink="false">http://iamtherockstar.com/blog/2011/08/22/ubuntu-one-and-yui-stale-events/</guid><category>yuiandyou,</category><category>javascript,</category><category>ubuntuone</category><feedburner:origLink>http://iamtherockstar.com/blog/2011/08/22/ubuntu-one-and-yui-stale-events/</feedburner:origLink></item></channel></rss>

