'Web' Articles

Cleanly declaring AngularJS services with CoffeeScript

, , ,

I’ve recently fallen in love with AngularJS for building JavaScript applications. I’ve also come to rely on CoffeeScript to provide a more comfortable, concise syntax than plain JavaScript. It’s common to define many services when writing AngularJS applications. Services are just plain JavaScript objects that are registered with AngularJS’ dependency injection system, which makes them available to other parts of your application. If you have experience with Java, this will be familiar from Spring or Guice. I prefer to have very little logic in my controllers, and instead create a domain model from layers of services that each have their own responsibility.

One thing I’ve gone back and forth on is how best to declare AngularJS services using CoffeeScript. Let’s imagine a somewhat contrived example service named Tweets that depends on the built-in $http service. When it’s constructed it saves a timestamp, makes an HTTP call and saves the result to a property. Here’s a pretty straightforward way to declare this service using CoffeeScript’s class syntax:

app.service 'Tweets', ['$http', class Tweets
  constructor: (@$http) ->
    @timestamp = Date.now() - 900000
    @getNewTweets()

  getNewTweets: ->
    request = @$http.get '/tweets', params: { ts: @timestamp }
    request.then (result) =>
      @tweets = result.data
      @timestamp = Date.now()
]

This works pretty well. The first time this service is needed in the application, AngularJS will call new Tweets() and save that one (and only one) instance to be provided to any other code that requests it. Because AngularJS calls the Tweets constructor, the first call to getNewTweets is performed right away. But one thing bugs me - a reference to $http is saved as a property of the Tweets instance in the constructor. First, this results in some ugly-looking code like @$http thanks to AngularJS’ habit of naming services with $. It gets even worse when you depend on a lot of different things, and you now have to refer to them all via @ (which is this in CoffeeScript, by the way). Second, this exposes the $http service to anything that depends on Tweets. Anything that depends on Tweets can simply call Tweets.$http, which is a violation of encapsulation. It doesn’t look too bad in this example, but imagine a deep chain of services, each with its own responsibility, declared with this method. Any caller could reach down into that chain and pull out dependencies of dependencies. Or worse, they could change the reference to $http to point to something else.

Let’s try something else. If we are only ever going to have one instance of this class, why have a class at all? We can use the factory method instead of servicefactory just calls the function you provide instead of calling new on it - and have our factory function return a literal object:

app.factory 'Tweets', ['$http', ($http) ->
  obj = 
    timestamp: Date.now() - 900000

    getNewTweets: ->
      request = $http.get '/tweets', params: { ts: @timestamp }
      request.then (result) =>
        @tweets = result.data
        @timestamp = Date.now()

  obj.getNewTweets()

  obj
]

We’ve solved the problem of exposing $http, since now it’s simply captured by the function closure of our getNewTweets function, making it visible to that method but not elsewhere. However, we now have to assign our object to a variable so that we can do our initialization outside the object declaration before returning it. This is ugly, and it feels out of order. A more subtle problem is that stack traces and object dumps in the console will print this as Object, wheras in the first example it will say Tweets. Never underestimate the value of clear debug output.

There’s also a potential for confusion around CoffeeScript’s function binding fat arrow =>, which will bind to the this of the factory function if it’s used when declaring methods on the object literal. I actually ran into this problem when I wanted to bind a function to its object so it could be passed as a callback to another function, and ended up with it bound to the wrong this.

Note that I can declare timestamp as a property of the object literal in this form, wheras in the first version I set it in the constructor - this is because when CoffeeScript creates a class, all the properties are set on the prototype, not the instance, so you can’t store per-instance state there. Well, you can get away with it because AngularJS will only make one instance of your class, but you’re still modifying the prototype rather than the real instance, which isn’t what you want. It pays to understand exactly what CoffeeScript is generating for you.

Let’s go back to using class and try again:

app.factory 'Tweets', ['$http', ($http) ->
  class Tweets
    constructor: ->
      @timestamp = Date.now() - 900000
      @getNewTweets()

    getNewTweets: ->
      request = $http.get '/tweets', params: { ts: @timestamp }
      request.then (result) =>
        @tweets = result.data
        @timestamp = Date.now()

  new Tweets()
]

The difference between this and our first example are subtle. First, we’re using factory instead of service, like in the second example. This means instead of having our dependencies provided to the Tweets constructor, they’re provided to the factory function, and our declaration of the Tweets class can simply close over those parameters, meaning we no longer need to take them as constructor arguments. That solves the problem of $http being visible to other objects, and means we don’t need to write @$http. As I’ve explored AngularJS, I’ve actually found myself always using factory instead of service because it provides more flexibility in how I provide my service value.

However, we also have to be very careful to remember to actually instantiate our class at the end, since AngularJS won’t be doing it for us. That could be really easy to miss after a long class definition.

We can change this a little bit to make it better:

app.factory 'Tweets', ['$http', ($http) ->
  new class Tweets
    constructor: ->
      @timestamp = Date.now() - 900000
      @getNewTweets()

    getNewTweets: ->
      request = $http.get '/tweets', params: { ts: @timestamp }
      request.then (result) =>
        @tweets = result.data
        @timestamp = Date.now()
]

Now we call new right away to instantiate the class we’re defining. I think this is very clear, and there’s nothing after the class definition to forget. This is the pattern I’ve settled into whenever I declare singleton services – it’s clean, readable and concise, and it solves all the problems we’d identified:

  1. Dependencies of our service are not exposed.
  2. Our service will print with a meaningful name in the console.
  3. There is no out-of-order code, or extra code after the class declaration.
  4. We never have to put the characters @ and $ next to each other. Sorry, I’m still recovering from exposure to Perl and I can’t take it.

I’ve written up a more detailed example in this gist, which shows the pattern I’ve been using to produce ActiveRecord-style APIs with private dependencies. I hope this helps you write clean, understandable AngularJS services in CoffeeScript.

Redesigning evafunderburgh.com

My wife Eva Funderburgh (Hollis) is a professional artist, and has been making sculptures full-time since we both moved to Seattle in 2005. I don’t have much talent for clay, so my main contribution is to help with her website. A few weeks ago we launched the third iteration of her site, which we’d been working on for several months.

Old site

The previous version (shown above) was launched around 2008 and was basically just a Wordpress theme. Eva had hand-drawn some creatures and wiggly borders to make it all feel less digital, but there’s only so far you could go with that on a web page. The resulting site had a lot of character, but ultimately failed to put her gorgeous art front and center. Worse, it had failed to keep up with the increasing sophistication and complexity of her work. It also scaled poorly to mobile devices, and just plain looked outdated.

I had a lot of goals for the new site. First and foremost, it needed to be dominated by pictures of Eva’s art, especially on the homepage. The way I see it, any part of the screen that doesn’t include a picture of her sculptures is wasted space. I also wanted the design to be clean, contemporary, and focused. We have so many great pictures of her creatures that any ornamentation or empty space is a wasted opportunity. Beyond that, I had a bunch of technical goals befitting a website built in 2013. The first was that the site should work well on mobile, with a responsive design that supported everything from phones to tablets to widescreen desktop monitors. A related goal was that the site should support high-DPI or “retina” screens – both of us are eagerly awaiting new Retina MacBook Pros, and browsing with high-resolution phones and tablets is more and more popular. It seems safe to assume that screen resolutions will only increase over time, and I wanted Eva’s art to appear as sharp and beautiful as it could on nice devices. Also related to the goal to work on mobile, I wanted the site to be fast. This meant minimizing download size, number of external resources, and JavaScript computation. It also meant leveraging CSS transitions and animations to provide smooth, GPU-accelerated motion to give the site a nice feel. Helpfully, one of the decisions I made up front was that this site was going to target the latest browsers and the advanced CSS and JavaScript features they support. Fortunately, most browsers aggressively update themselves these days, so the age of supporting old browsers for years and years is coming to a close.

The site itself was built using Middleman, an open-source static website generator I help maintain. This allowed me to use CoffeeScript for all my JavaScript, which I have come to appreciate after a rocky first experience, and to use Haml and Sass/Compass for HTML and CSS respectively. One of my coworkers challenged me to write all my JavaScript without using jQuery, which was actually pretty straightforward and improved the performance of the site while dropping quite a bit of size from the overall download. I did rely on the indispensable Underscore for templating and utilities, however.

New site

The redesign started with the new homepage, which presents a grid of cropped pictures that fill up the whole window. First, we chose a basic grid unit or “block” that the whole page is divided into. Eva selected a bunch of pictures she liked, and used Lightroom to crop them all into tiles of specific sizes, with dimensions of 1x1, 2x1, or 3x1 blocks. She also exported double-resolution versions of each block for retina displays. Each picture was associated with a full-frame version on Flickr. JavaScript on the homepage uses that information to randomly select images and las them down like a bricklayer would to make a wall, creating a solid grid of pictures. If the browser reports itself as high-DPI, the double-resolution images are used to provide retina sharpness. A quick CSS transition animates each block into the page as they load. To make the page responsive to different browser sizes, there are media-query breakpoints at each multiple of the block size and when the browser is resized, the blocks are laid out again. You can see the effect by resizing your browser – it will reduce the width of the grid one block at a time. Once the browser gets below a certain size, the block size is halved to fit more images onto a smaller screen. Using blocks for the breakpoints instead of the classic “iPhone, iPad, Desktop” breakpoints means that the design works nicely on many devices and browser window sizes – this way it looks good on devices from non-retina smartphones all the way up to HDTVs, and not just the Apple devices I happen to own.

On mobile

The other part of the homepage is the “lightbox” that appears when each tile is tapped. This is built from scratch rather than using any lightbox plugin, and uses CSS transitions to display smoothly. It also allows for keyboard navigation, so you can use the arrow keys to browse through pictures. The full-size image for the lightbox is linked directly from Flickr, and I use the Flickr API to select the perfect image size that won’t stretch and blur, but won’t waste time with a too-large download. This can end up showing a dramatically different sized image between a phone and a Retina Macbook!

Lightbox

After the homepage, the rest of the site was relatively easy. For the most part, it’s still a Wordpress theme, though it reuses the responsive breakpoints at each integer multiple of the block size to provide nice reading on every screen. I also reused the exact same code from the homepage to provide a row of random tiles at the top of the page. Beyond that, there are just some SVG icons for the social media links (to ensure that they too display nicely on retina screens) and a few more subtle fit-and-polish tweaks to make it feel great. The “Art” page was designed by hand to provide high-resolution banners linking to Flickr, Etsy, and the various galleries that showcase Eva’s work, and the rest is editable directly from Wordpress so that Eva can maintain and update the content. A series of IFTTT rules make it easier for her to update the site while she’s working by piping specially-tagged Flickr uploads into the blog (and to Tumblr, Facebook, and Twitter).

Art page

I’m rarely satisfied with the website designs I produce, but this time I’m extremely proud of what we’ve built. Please check out the site, resize your browser, try it out on your phone, but most of all, enjoy the pretty pictures.

Middleman 3.0

,

For the last 8 months or so, I’ve been contributing to Thomas Reynolds‘ open source project Middleman. Middleman is a Ruby framework for building static websites using all the nice tools (Haml, Sass, Compass, CoffeeScript, partials, layouts, etc.) that we’re used to from the Ruby on Rails world, and then some. This website is built with Middleman, and I think it’s the best way to put together a site that doesn’t need dynamic content. Since I started working on Middleman in November 2011, I’ve been contributing to the as-yet-unreleased version 3.0, which overhauls almost every part of the framework. Today, after many betas and release candidates, Middleman 3.0 is finally released and ready for general use, and I’m really proud of what I’ve been able to help build.

Middleman Logo

I’ve been building web sites for myself since the early 90s, before I even had an internet connection at home (I could see some primitive sites on Mosaic on my father’s university network). Early on I was inspired by HyperCard and Quicktime VR and I wanted to make my own browseable worlds, but I didn’t have a Mac (nor did I know what I was doing). Starting with Notepad and early Netscape, I started building sites full of spinning animated GIFs, blinking text, and bad Star Wars fanfiction. As time went on and I learned more bout how to actually build websites, the duplication of common elements like menus, headers, and footers became too much to manage. Around the same time I discovered how to make dynamic websites backed by a database, using ASP. For my static websites, I just used ASP includes and functions to encapsulate these common elements and do a little templating. With the release of .NET, I switched to writing sites, static and dynamic, in ASP.NET. Far too long after, I realized that hosting websites on Windows was a terrible idea, and I switched to using PHP to handle light templating duty. For dynamic, database-driven sites I switched to using Ruby on Rails, and I fell in love with its powerful templating and layout system, the Ruby language, Haml, Sass, and all the rest. However, the gulf between my Rails projects and my cheesy PHP sites was huge – all my tools were missing, and I still needed PHP available to host sites even though they were essentially static.

My first attempt to reconcile the two worlds was a Ruby static site generator called Staticmatic. Staticmatic had Haml built in, and worked mostly like Rails. I had just finished moving my site over to it when the developer discontinued the project. In its place, he recommended Middleman. However, as I started transitioning my site to Middleman, I found a few bugs, and wishing to be a good open source citizen, I included new tests with my bug reports. Thomas Reynolds, the project’s creator, encouraged me to keep contributing, and even gave me commit access to the GitHub repository very early on (at which point I broke the build on my first commit). From that point I started fixing more and more bugs, and then eventually answering issue reports, and finally adding new features and helping to overhaul large parts of the project. I’d contributed to open source projects before, but just with a bugfix here and there. Middleman has been my first real contribution, with ongoing effort and a real sense of ownership in the project.

My contributions have focused mainly in three areas. First, I’ve helped to get the new Sitemap feature working. I liked the way similar frameworks like Nanoc had a way to access a view of all the pages in a site in code, to help with automatically generating navigation. Middleman’s sitemap goes beyond that, providing a way to inspect all the files in a project, (including virtual pages), and even add to the list via extensions.

The next area I worked on is the blogging extension. I like the way Jekyll handles static blogging, but I wanted my blog to be just one part of my whole site – Jekyll is a little too focused on blog-only sites. I basically rewrote the fledgling blog extension that Thomas had started, and I’m really proud of the result. It not only handles basic blogging, but also generates tag and date pages, supports next/previous article links, and is extremely customizable. I moved my blog over from Wordpress (no more security vulnerabilities, yay!) and it’s been great.

The last place I focused was on website performance. I’ve always been interested in how to build very fast websites, and I wanted Middleman to support best practices around caching and compression. To that end, I built an extension that appends content-based hashes to asset filenames so you can give them long cache expiration times, and another extension that will pre-gzip your files to take load off your web server and deliver smaller payloads.

Beyond that I’ve fixed a lot of bugs, sped things up, written a lot of documentation, and added a lot of little features. I’m really happy that 3.0 is finally out there for people to use, and I hope more people will choose to contribute. And I’m looking forward to all the new stuff we’re going to add for 3.1!

Searchable tab switching in Firefox 3.6

As an emacs user, I’ve found iswitchb (interactive-switch-buffers) to be a huge time saver. Basically, to switch files (buffers) you enter a typically byzantine key combination and then type to search through your open files - as less and less files match your search, the choices narrow down, and you can choose between them. This ends up being way faster than switching with a mouse even in tabbed editors, and I’ve managed to set up a similar thing in Eclipse/Aptana. But until recently I didn’t have the same functionality for switching tabs in Firefox.

The good news is that Firefox 3.6 has this feature built in, though it takes a bit of work to enable. Apparently they’ve been trying to get this feature into Firefox since 3.0, but there’s been a lot of different opinions, so even though they finally shipped it with 3.6, it isn’t on by default. You can turn it on by going to about:config (just type that right into your address bar), then searching for “ctrlTab”. Double-click browser.ctrlTab.previews to turn it to “true”. Now, when you hit Ctrl-Tab, you’ll get a tab switcher that looks a bit like the default Windows Alt-Tab window switcher (though with a much lighter glass effect that honestly looks pretty bad compared to Windows’ Alt-Tab). On other platforms you’ll get a similarly system-integrated look. Unfortunately this popup isn’t exactly what we’re looking for - it doesn’t show all your tabs and you can’t search! However, you can navigate down to “show all X tabs” at the bottom and you get a search box and a list of every tab. That’s a real pain to do every time you want to switch tabs, though. Fortunately, there’s a solution. Instead of hitting Ctrl-Tab, use Ctrl-Shift-Tab, and you’ll start out right at the big tab switcher with search. From here you can type to narrow down your selection and hit Enter to choose your tab. I wish there was a preference to make this full search show up when you hit Ctrl-Tab, but it doesn’t look like there is.

Firefox Ctrl-Shift-Tab tab switcher
Switching between tabs (man, that glass effect is a mess)

Visual issues aside, I wish every program with a tab-oriented UI had a feature like this to make their app faster to use for keyboard users. While we’re at it, Windows and OSX should add search to their built-in window switchers - it could really help when I have a lot of windows open and don’t want to reach for the mouse.

Note: There are a couple extensions for Google Chrome that theoretically give a similar searchable tab switcher, but of the few I tried, none of them could appear with a keyboard shortcut - you had to click an icon on the toolbar, which seems to defeat the point. Apparently the Chrome Extensions API has known problems with keyboard shortcuts, so maybe things will get better soon.

Apple text emboss

,

Back in the days of OS X 10.1 I wasn’t a really big fan of the striped backgrounds, overblown transparency, and over-the-top animations Apple was using to show off their new desktop. However, in the last few releases they’ve tightened up the look of their OS, made it much more consistent, and have ended up with a really nice design that I find very inspiring. The OS X aesthetic has of course translated over to the iPhone, where it’s even more elegant.

One of the little touches that I really like is that label-style text on a gradient or colored background has a slight emboss effect that really makes it pop off the background and gives everything a nice 3D physicality without being too overt. You can see examples on the iPhone, in button and header text as well as the icons on the top bar:

iPhone button emboss

I fiddled around in Fireworks for a while trying to replicate the effect, but I couldn’t quite get it right until I asked a friend at work, who quickly pointed out that it’s really just a simple drop shadow, not any sort of emboss effect. I guess my eye had seen a more complex effect than what what actually there. Anyway, it’s pretty simple: you add a drop shadow with no fuzz, 50% opacity. If you have light text, you add a black shadow that is cast straight up, and if you have dark text, a white shadow that’s cast straight down. That’s all there is to it!

shadow

I went ahead and applied this effect to the “BRH.numbera.com” text on the top of my site, and I really like the way it makes the text pop off of the background.

Now that I knew how to do it, I decided that the low-contrast menu text on my site could also benefit from such an effect, but I wasn’t going to go and replace every bit of text in the menu with images. So instead, I used a CSS3 property that’s supported in Safari 3, Opera 9.5, and the upcoming Firefox 3.1: text-shadow. I’d already used text-shadow to put some soft drop shadows on the links across the top of my site and the section header, so it wasn’t too hard to add them to the links. All that was required is:

text-shadow: 0 1px 0 #C9DFF3;

So that says to make a shadow straight down (0px right, 1px down), 0 fuzz, and the color #C9DFF3. I had to pick that color because text-shadow doesn’t have an opacity property built in. Of course, using another CSS3 feature, HSLA colors, I can make a shadow that works on any background:

text-shadow: 0 1px 0 rgba(255, 255, 255, .5);

And for light-colored text:

text-shadow: 0 -1px 0 rgba(0, 0, 0, .5);

I ended up keeping the hand-chosen background color in addition to the HSLA version since Opera supports text-shadow but not HSLA. So now I have a cute little enhancement to my site that users of cutting-edge browsers will get to enjoy.

Comparison of Apple Text in different browsers

Note that Google Chrome, despite being based on the same WebKit core as Safari, doesn’t support text-shadow since Google had to provide their own rendering layer (Apple uses their own proprietary renderer).

Posts I haven't written

, , , , , , ,

I haven’t been updating this blog too much recently. I never meant for this blog to run on a schedule, but I did intend to post more frequently than this. My original idea was that the blog would serve two major purposes. First, it is a place for me to announce new projects or updates to software and websites I’ve already released. It’s done that quite well, though I haven’t had much to announce recently. My job has been taking the majority of my development time, and most of the projects I’ve been working on at home are either private or haven’t been released in the form I’d like to because my employer hasn’t approved them for release yet.

The second major purpose for my blog is as a place for me to record the solution to problems I run across while developing software, so that others won’t have to spend hours Googling or using trial and error to come to the same conclusion. I didn’t intend to rehash things that were easily found or that had already been discussed - only to post when I felt it was something that added value to the internet that hadn’t been there before. So a lot of the blog posts are not really a narrative or running commentary - they’re not meant to be subscribed to, but found individually. It’s for this reason that my most popular posts tend to include the exact text of error messages. This type of post has suffered both because I haven’t been doing as much development, because I can’t discuss a lot of what I’ve learned due to the nature of the projects I’m working on, and because I’ve been learning new stuff (like Ruby on Rails) and haven’t done enough to have solved problems others haven’t already posted solutions for.

The third reason I have this blog is to occasionally talk about my thoughts on different technical topics, from web development to video games. Again, I don’t like to make a post unless I think I’m adding something new, and most of the topics I’ve wanted to talk about have already been covered. I had a lot of draft posts sitting around about web development, web standards, and the evolution of browsers, but then I discovered Alex Russell’s blog and it turns out he’s already said most of what I wanted to say, and better than I could. Other stuff, like my impressions of Windows Vista, critique of stackoverflow.com and suggestions for the Xbox Live Arcade lineup, have been covered to my satisfaction in plenty of places. Maybe some of them will end up posted, but probably not.

Another part of the reason I haven’t posted much is the sheer weight of unfinished posts I have. Right now I have 64 drafts and only 52 real posts! So I’m going to attempt to clear things out by writing a little about what I haven’t posted. A lot of this stuff wasn’t posted because it fell under that third point above, but some of it I was just too lazy to flesh out into real posts. Some of it’s just random stuff. So here’s what’s been happening in the last year:

I got on the bandwagon and picked up iPhone 3Gs for myself and my wife. Everything good you’ve heard about the iPhone is true. Also, almost everything bad you’ve heard about them is true. I really like the device, the UI, and the web browsing, and now that the NDA over the SDK is gone, I might even try to write an app if I get an idea.

I built a new computer in March of ‘07 to replace the machine I had built for college. The new machine is set up as a developer machine primarily, with the additional goal of being as quiet as possible. I can’t say I’m entirely happy with it, since I’ve had some trouble with the hardware and overheating issues mean I have to run the fans above “totally silent” mode. It does its job well enough but I might just buy a Dell next time. The huge CPU heatsink I used is awesome, though.

I’ve been running Windows Vista x64 since my new machine came online. While I think it’s a disappointing release given the 5-year gap between it and Windows XP, I generally like it. It’s certainly better than Windows XP and I wouldn’t go back. I’ve hit some trouble related to using x64, but overall it’s pleasant.

Before that, I was getting pretty sick of the aging Windows XP, so I bought a Mac Mini and ran it, using OS X 10.4, on a second screen next to my XP machine, joined via Synergy. I liked it a lot, but never moved much of my work over there. After getting set up with Windows Vista, the difference between OS X and Windows wasn’t so great, and I unplugged the Mac so I could have both screens for Windows. I moved the Mini up to my TV and used it with Front Row as a media center. Then the Xbox 360 got the ability to play DivX videos, so I stopped using it for that and brought it back downstairs. I was using it for browser testing, but then Apple released a Windows version of Safari. Now it mostly stays off, except when I want to use Handbrake (which won’t work on Vista x64). I still like it, and I really miss having an OS with a real command line, especially now that I’m doing Rails stuff and spelunking through a lot of badly-documented libraries. I’m not sure I’ll ever make the switch though. That said, my trusty old Thinkpad finally died last week, and if I can’t revive it I might look towards the rumored lower-priced MacBooks that should come out soon.

I got two awesome cats named Ozette and Skagit. A lot of my time at home just involves relaxing and petting the cats these days.

After years of using Thunderbird, I switched to GMail as my main mail client so I could use it from the web and use IMAP on my iPhone. I set it up to read all my old POP mailboxes, and I use Google Chrome’s application mode (I used to use Mozilla Prism) to make it look like a standalone app on my desktop. It’s an OK mail reader, especially since I get a lot less email to my personal accounts these days. The main annoyance is spam - I used to use POPFile to filter spam, and it was perfect, with almost no false positives. In contrast, I get maybe 50 pieces of spam leaking through on GMail a week.

Spam has not been limited to my inbox: my support forums are basically nothing but spam and people complaining about stuff I’ve given them for free. It takes a lot of maintenance, and I’m thinking of either trying to transition them to something less attractive to spammers, or just shutting them down entirely.

Back when IE7 was in beta I wrote a handful of bug repro’s for problems I found with it. Recently I’ve been running across all kinds of crazy things in both Firefox and IE, so I’ve been cataloguing them with little examples. Most of them have been fixed with the latest release of each browser, but I figure they’re still useful if anybody’s seeing those problems happen.

I went to Southeast Asia for two and a half weeks. We toured Vietnam, Cambodia and Thailand. It was incredible.

I finally got so sick of CSS that I decided to write a processor that would take an “evolved” CSS syntax that supported named constants, nested selectors, arithmetic, mixins, and such and spit out real CSS. I had it all sketched out and was ready to start implementing when I found SASS, from the same guy who awesome-ified HTML with HAML. SASS is feature-by-feature the exact same thing I wanted to do (except for the whitespace-significant thing, but I can deal). I love it.

I’ve been pretty disillusioned with ASP.NET as a web platform - the web forms are too inflexible and unfriendly to clean markup and unobtrusive JavaScript, and C# feels too rigid and verbose for what I’m doing. LINQ and the other 3.5 features help a lot, but my host is stuck on 2.0. I still haven’t found any templating system that trumps Web Forms, which is why I’m still stuck on Windows hosting for the most part - a lot of my sites are built on ASP.NET for nothing more than the templating. While I’m keeping my eye on ASP.NET MVC, I’m more interested in cross-platform web technologies that give me a bit more choice in hosting.

To that effect, I’ve started a personal project on Ruby on Rails, mostly to learn the platform. So far I’ve really been liking it - having a functional, dynamic language is great, and the structure Rails gives you really helps to quickly get things running. Hopefully I’ll be able to show what I’m making at some point, assuming it works to my satisfaction.

I actually went through a big comparison of different web platforms and different languages, trying to gauge what would be the best for me to develop for. I’m not sure I’ll ever publish my full results, but Ruby on Rails was obviously up there, and Django / Python looked good too.

Speaking of languages, before I discovered jQuery I didn’t really do much JavaScript if I could avoid it. Now I’m writing tons of JavaScript to produce some really nice interactive web apps. I have never been as impressed with a library or platform as I have been with jQuery.

I’ve actually been using Eclipse a lot lately, both for Aptana and for straight Java development, and while it’s slower and buggier than Visual Studio, a free copy of Eclipse plus all the free plugins make it much more compelling than the Visual Studio Express products I use for C# work. Stuff like the outline view, refactoring support, quick fix mode, and real unit testing and source control plugins make all the difference.

I think that’s about all I wanted to get off my chest for now. Hopefully I’ll have a chance to flesh some of that out into full posts sometime, but at least I won’t have so many unwritten drafts staring at me every time I log in to Wordpress.

Setting up IIS7 (with bonus PHP instructions!)

, , ,

Every time I try to set up IIS7 on a Windows Vista machine I run into the same series of problems. You’d think I’d have learned by now, but I usually just struggle through the cryptic error messages and get it working one way or another, then forget about it until the next time I need IIS7 on a machine that doesn’t have it. Finally I’d had enough and so I decided to write myself a little guide here so I won’t waste as much time next time. These instructions are basically the same as these, but with additional detail and screenshots.

The first step is to actually install IIS7. Unlike in Windows XP, IIS isn’t installed by default. That’s great, but it can be kind of hard to find it when I need it.

Add or remove Windows features

You’ve got to click this link that says “Turn Windows features on or off” which will (after some time) bring up a big tree of features you can check or uncheck.

Windows Features - IIS

You’re going to want most of “World Wide Web Services”. If you are also interested in installing PHP, make sure everything I’ve circled in red is checked. I just added everything to be safe. What’s important is that you have the ISAPI and CGI stuff. I also checked the IIS6 compatibility bit so that installers for things like PHP might have a better chance at automatically configuring things (fat chance).

At this point you can start dropping things into C:\inetpub\wwwroot and everything should be peachy. I don’t put my sites there since I have them checked out into various folders in my Documents folder. So I need to create some virtual directories to point to my sites. This probably won’t work off the bat - you’ll get 403 errors that complain about wrong permissions or something. You need to make sure that the “IIS_IUSRS” and “Authenticated Users” users have read access to the directory. I’m not sure why “Authenticated Users” needs to be there but it made it work. Make it look like this:

Setting permissions for IIS7

At this point your folder should be accessible from the virtual directory, and any ASP.NET stuff will probably work. If you’re not interested in installing PHP, you can stop here.

Installing PHP on IIS7

PHP doesn’t really play well with IIS. However, we can get it going good enough for local testing of your PHP code. First, go install PHP5 from php.net. Choose to install it as an ISAPI extension for IIS, but don’t worry too much, since it won’t work anyway. Now open up IIS Manager. If you’ve followed the steps above (specifically, selecting the correct “Windows features”), your IIS manager should look something like this:

IIS Manager with ISAPI and CGI

What’s important is that you have the parts outlined in red - the “CGI” icon, the “ISAPI Filters” icon, and the “ISAPI and CGI Restrictions” icon. Those mean the right bits are installed.

Now double-click the “Handler Mappings” icon, and click “Add Script Map…” Fill out the form like this:

Add PHP script map

Make sure it’s pointing to your real copy of php5isapi.dll. At this point your Handler Mappings screen should look like this:

IIS handler mappings

Also make sure that your “ISAPI Filters” screen looks like this:

ISAPI filters

If not, add PHP like this:

Edit ISAPI filters

If you’re running the 64-bit version of Vista like I am, there’s one last thing to do in IIS Manager. Since the PHP ISAPI extension is a 32-bit app, you’ll need to set your app pool to run in 32-bit mode. I’ve already written one blog post on this (to get MySQL working with ASP.NET), and the instructions are the same. Basically open up the app pool’s advanced settings dialog and flip it to 32-bit mode:

IIS 32-bit app pool

If you forget this you’re likely to get errors that look like “Calling LoadLibraryEx on ISAPI filter "C:\Program Files (x86)\PHP\php5isapi.dll” failed".

If you load up your PHP files you’ll probably get something like “failed opening required” blah blah. This is because the PHPRC environment variable isn’t set correctly by the PHP installer. We’ll have to do it ourselves. Go to the Control Panel and search for “env”:

Environment variable link

Now add a System environment variable like this (point it at the directory PHP is installed):

PHPRC env variable

At this point you must reboot your computer to get the environment variable to take effect. Annoying but true. At this point PHP should work, more or less.

I still have some problems with PHP the way I’ve described configuring it. The most obvious is that the IIS worker crashes every once in a while:

IIS worker crash because of PHP

I suspect reconfiguring PHP to be run as a CGI handler instead of an ISAPI module would help here, but it hasn’t been annoying enough to make me go change it. Another avenue to investigate is the new FastCGI support that’s available for IIS7.

The other problem I’ve had is that I have a handful of image files in one of my sites that are managed by Subversion and get locked and unlocked pretty frequently. After I’ve committed an image, it loses its permissions and can’t be served from IIS anymore, and I need to go reset the permissions. That’s pretty annoying, and I’m not sure if it’s a bug in Subversion or in one of my SVN clients (TortoiseSVN and Subclipse).

At least this setup works enough to try things out quickly. I hope it helps anyone else who’s struggling with one of these setups.

Update: You might want to try out the new Microsoft Web Platform Installer which purports to set up PHP along with anything else you might need.

Firefox bug rendering list items next to floated elements

I was working on a web app a couple weeks ago when I hit a weird problem. I had a sidebar floated right, and an unordered list right next to it. What was weird is that each list item was getting “pushed aside” by the floated sidebar. This went against what I thought I knew about how floats work in CSS. My understanding was that floats should be removed from the page layout, and appear above any other block level elements, like my list items. Reading CSS Float Theory: Things You Should Know and the W3C spec on floats only backed up what I thought. Floats should always appear above block boxes, like LIs. I wrote up a minimal test case and tried it out. What I expected was something like this, where the green boxes are LIs, the red box is my floated DIV, and the purple box is a normal block element like a P:

CSS compliant float rendering

Instead, what I saw in Firefox 2 was:

Firefox bug 163110

It actually took me a very long time to get to this point because I hadn’t even bothered to try it out in non-Firefox browsers, since I assumed Firefox was right and I was missing some arcana in the spec. I had tried it out in Internet Explorer 6, but I had taken that as even more evidence that Firefox was right (if it differs between IE6 and Firefox, it’s usually IE6 doing it wrong). However, when I finally popped my test case into Safari 3 and Opera 9 and they agreed with IE, I realized that it was really a Firefox bug. Not too much searching later I came across this css-discuss post which pointed out the bug and offered two solutions. Either I could force my LIs to take up the whole space by setting “width: 100%” on them, or I could use the proprietary Mozilla CSS property “-moz-float-edge: content-box”. Either one made the list items act like I expected them to, though you give up some flexibility with the first method, and the second won’t validate.

This bug has been filed as Bug 163110 since August 2002, and many duplicate bugs or similar-but-not-quite-duplicate bugs have been filed since. Unfortunately, it doesn’t look like anyone is working on fixing it, and I don’t expect to see this problem go away in Firefox 3, which should be shipping relatively soon. I’m just going to have to add it to the list of bugs and workarounds I need to keep in mind whenever I’m navigating the minefield of modern web design.

Update (5/29/08): This has been fixed as of Firefox 3 RC1. Yay!

MSN Messenger needs to be able to sign in from multiple locations at once

,

Like most Americans, I’ve been using the AOL Instant Messenger IM network for the last 10 years or so. As I’ve made more friends who prefer other networks, I expanded to multi-platform IM clients that let me sign into all the major IM networks at once. I’ve used Trillian, Adium, Meebo, and Pidgin over the years, and I have active screen names on AIM, MSN, Yahoo, GTalk, and various Jabber services. So when it was announced that the Xbox 360 would include an MSN Messenger client with the Spring update, I was excited. I’m already signed in to MSN all the time, so I thought this would just be another great way to stay connected.

Unfortunately, MSN has a pretty big problem. Whenever you sign in to your MSN account from one location, it signs off, all the other locations. If I’m running Pidgin on my desktop and I open Meebo on my laptop, my desktop gets signed out. And when I start my Xbox, it automatically signs on and knocks everybody else off. The end result is that I’m almost never signed in to MSN, which pretty much defeats the purpose. My buddy list reflects this - my friends are online only when their Xboxes are on. It’s worth pointing out that Yahoo Messenger suffers from this problem too, but it doesn’t bother me as much since I don’t have many Yahoo friends.

MSN getting kicked off

With more and more devices getting IM capability, I can’t see how this restriction can continue. My desktop is always on and signed in to my IM client. My phone will have an always-on IM client. Another one on my Xbox. Another on my laptop. Another at work. And I’m switching between them all the time. And with more and more people using multi-protocol clients, they’re less likely to notice the one account that’s decided to sign itself off. It’s especially frustrating on the Xbox, since it means I can’t just use my laptop to send IMs to my friends while I play and still get notifications on my TV. IM has the potential to be awesome on the Xbox, but not as long as it’s stuck with a one-device-at-a-time protocol.

Installing Aptana on Windows Vista with Aero Glass

, ,

I’ve recently given up Dreamweaver entirely in favor of Aptana, a great (and free!) Eclipse-based web development IDE. It features great JavaScript IntelliSense, document outline view, AJAX library function autocomplete, and an FTP component that should make Dreamweaver users very comfortable. Even better, with plugins like Subclipse, you get source control for your websites. Basically, it’s one of my favorite programs.

However, all is not rosy. The Aptana documentation’s guide to installing and running Aptana on Windows Vista recommends turning on XP compatibility mode, disabling desktop compositing, and always running it as Administrator. If you haven’t had an app turn off Aero Glass for you before, you’re in for a shock - it really sucks after you’ve gotten used to Glass. And running as Administrator isn’t that great an idea with a product as connected as Eclipse.

Fortunately, all is not lost. First, go to Sun and download the JavaSE 6 JRE (32-bit). It’s a huge upgrade from the Java 1.4.2 JVM that Aptana usually comes with, and it includes some major Vista compatibility features. Next, download and install Aptana minus the JRE from the Aptana downloads page. Already installed Aptana? Just go into the program directory and delete the “jre” folder. Now, make sure the Aptana shortcut doesn’t have any compatibility features checked. (Disclaimer: you might actually need to run as Administrator the first time you use Aptana, but certainly never again.) Start up Aptana, and everything should be glassy and smooth.

Aptana with Aero Glass

If Aptana complains that it can’t find the JRE, go into your Aptana program directory and open up aptana.ini. Add the line -vm='C:\Program Files (x86)\Java\jre1.6.0\bin\java.exe' to the top of the file, and save it. I had to do this mainly because I have both the 64-bit and 32-bit JREs installed, and while most Java apps work on the 64-bit JRE, Eclipse (and thus Aptana) doesn’t support 64-bit yet.

Update: Newer versions of Aptana come with Java 1.6, so this isn’t a problem anymore.