Common Dream

Blogging With Octopress

I’ve been meaning to switch my blog over to Octopress since sometime last year, but haven’t ever taken the leap. Today, though, I figured I’d stop putting it off and start taking advantage of the beautiful code display and much more developer friendly workflow. I’m super glad that I did.

If you’re interested in trying out Octopress yourself, go check out the docs at http://octopress.org.

Disabling and Re-Enabling Text Selection

A few days ago I was working on a little bit of drag code for a web page, and realized that there weren’t too many clearly defined solutions for disabling and re-enabling text selection in browsers, so I went ahead and wrote up a solution. Here it is!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class TextSelection
  @returnFalse = -> false

  @disable = ->
    $('body').css
      "-moz-user-select": "none"
      "-webkit-user-select": "none"
      "-ms-user-select": "none"
    $(document).mousedown -> @returnFalse
    if $.browser.msie or $.browser.opera
      $('body').find(":not(input)").attr("unselectable", "on")

  @enable = ->
    $('body').css
      "-moz-user-select": "auto"
      "-webkit-user-select": "auto"
      "-ms-user-select": "auto"
    if $.browser.msie or $.browser.opera
      $('body').find(":not(input)").attr("unselectable", "off")

It has been tested across all major browsers, down to IE6 and including Opera. I’ve also tested it with iOS4 and iOS5. You can still select text with it on Android, at least whatever version of Android my Kindle Fire is running, but my purpose for this was primarily to disable selection while dragging around the page, and you have to click and hold to get selection to happen on the Kindle Fire anyway, so I don’t think it’s a big deal.

The script does require jQuery to work, and in case the code above looks crazy to you, it’s written in CoffeeScript. Don’t worry, here’s a version that’s converted to JavaScript if that’s more your thing. Let’s run through the script right quick:

1
@returnFalse = -> false

This is just defining a simple function that returns false. I realized a couple of the techniques I was using required callbacks that just return false, so I figured it made sense to factor out.

So now for the disable method:

1
2
3
4
$('body').css
  "-moz-user-select": "none"
  "-webkit-user-select": "none"
  "-ms-user-select": "none"

user-select isn’t part of any CSS spec, but it’s been added by Firefox, Webkit, and IE, so I wouldn’t be suprised for it to make it in there soon. It’s by far the cleanest way to disable selection in my opinion. You’ll notice all the vendor prefix there. I decided not to include the non-prefixed version, since there’s no spec for the behavior anyway.

As a side note, I think embedded objects like this is one place where CoffeeScript really shines. No commas or curly braces - it starts to almost look line CSS inline in the script rather than code.

Adding user-select handles things for most browsers, but we do still need to use one other technique to hit every browser. user-select is only supported in Internet Explorer version 10, which isn’t fully released yet. Also, Opera still doesn’t have support for user-select. Fortunately, back in the old days both IE and Opera included an attribute on elements to disable text selection, the aptly named unselectable attribute. We can use jQuery to set the attribute of that value to on for the whole page, and that’ll take care of it.

1
$('*').attr("unselectable", "on")

We’re matching everything in the document and making it unselectable. It’s really straightforward, but unfortunately * is also about one of the worst performing selectors we could use. That’s why we go ahead and use browser detection to try and limit usage on it to IE and Opera, the browsers that need that technique.

1
2
if $.browser.msie or $.browser.opera
  $('*').attr("unselectable", "on")

That’s it! We’ve now got text selection disabled across the entire document. You can call the disable method with TextSelection.disable(). I won’t run through the enable method, because it’s basically just the opposite of the disable method, and I’m pretty sure you’ve got the idea of how it works.

It can be a pain to get things like this working across all browsers, but it’s gotten more and more easy to do lately, since so many browsers are becoming so similar in their implementation of features. I was amazed that something like user-select that isn’t even part of a CSS spec was supported across most browsers as well as it is.

Where the Magic Is Supposed to Happen

 So, as we begin 1991, let’s really look at those weekly box office
 figures and hear what the numbers are saying… what I believe they
 are telling us is to stop concentrating so much on what happens in
 that little room where the tickets are sold and instead concentrate
 on what happens in the big room where the lights dim and the magic is
 supposed to happen.

Jeffrey Katzenberg, Some Thoughts on our Business, from Letters of Note

Tconsole 1.0 Is Out!

I’ve been using a little project I spiked out called tconsole for a couple of months now, so I figured I should mark the gem as 1.0 and get on with things. tconsole is a command line tool that helps me and other Rails developers test more efficiently by not requiring us to reload our environment every time we run a test. tconsole has some helpful features like allowing us to easily test single test files, or even specific tests.

Interested in tconsole? Check it out on GitHub!

Figuring Out Where a File Was Required

I’ve been working on test performance a lot lately. Tonight I ran into a strange issue and needed to figure out where a file was being required from. That can be pretty tricky in a Rails app, since often files are being autoloaded.

I used this code up at the top of the file in question to figure out where it was loaded from:

1
puts caller.join("\n")

When the file was loaded by the Rails autoload code I got a nice looking stack trace of where execution was at that point in time, and all I had to do was look back to the first place where my code was referenced to figure out what was happening.

Be Sure to Include a Rating for Gravatar

When we launched Treehouse, we decided to use Gravatar for user avatars on profile pages. Here’s my profile page, for example. When we rolled it out I copied the Gravatar code on their site and ported it to Ruby. It was a pretty simple task.

Unfortunately, I heard reports from a few users after launch that their profiles werent showing up correctly, and were instead showing the fallback image. I tested their images on some other sites, and things showed up great. I was stumped.

After more trial and error I figured out that the problem was ratings. Gravatar has a rating system for avatars, so that you don’t show an avatar that’s a bit racier than would be acceptable for your audience. By default, they set the rating to G, so no images that are rated above a G rating will be returned. Our users that were having the issue all had a PG rating on their avatars. I’m not sure why they were rated PG because they were just pictures of the peoples’ faces, but that’s what was happening.

Adding that rating parameter fixed things, though. Heres the code we use for grabbing Gravatar image urls:

1
2
3
4
5
6
7
8
9
require digest/md5

class Gravatar
  def self.url(email, default, size = 200)
    email = email.downcase
    hash = Digest::MD5.hexdigest(email)
    "http://www.gravatar.com/avatar/#{hash}?s=#{size}&d=#{default}&r=pg"
  end
end

How I GTD With Email

I read David Allen’s Getting Things Done quite a while back when I was younger, worked at an insurance company, had VP in my title and thought that was awesome, and felt like more than anything else I just needed to get things done. Now, six or so years later, my mind summarizes the book something like this:

  1. Keep a list on paper. Add things to it as you realize you need to do them.
  2. Double check that list every day. If you can knock something out in a couple of minutes, go ahead and knock it out.
  3. Work back through the list again, from highest priority to lowest.

Over the past month, since getting an iPhone 4S, Siri has pretty much rocked my world and I’ve been using the Reminders app a ton since I can easily record things I need to do by just saying them. iCloud syncs Reminders to my Mac as well, so I use Reminders a good bit there too (although I’d love to pay for a Reminders app that’s more like the iPhone one, but for Mac). In general I use the rules above to handle what I’m up to and what I need to do, but track it in Reminders instead of on paper.

I’ve always had a problem with email, though. I get a decent amount of email, and have been getting about twice what I used to consider a lot since Treehouse launched. I’ve typically considered my email inbox a sort of To Do list and worked through things, archiving them when I’m done with them, but with super high email volumes that hasn’t been nearly as possible. I realized recently that it’s taking me a week or more at times to get back to some messages, and I hate the idea of being that slow to respond because more than anything I try to make people the most important thing about what I do. That called for a new process.

For the past week or so I’ve been doing is processing emails with my normal GTD method. Here’s how it works:

  1. Read a new email.
  2. If I can handle the email in a couple of minutes, I knock it out.
  3. If I can’t handle the email in a couple of minutes, I let the person on the other side know it’ll be a bit before I can do whatever it is I need to do to handle the email, and then log the email in my Reminders list in iCal and put the email in a folder called Later.
  4. Whenever I finish handling that email, I search for it in my Later folder, respond to the person if needed, and then archive the email.

Whenever I add an email based reminder to my list I make sure I include some text that’ll make it easy to search for the email and remove it from the Later folder.

This probably isn’t that unique of a workflow, but it has worked well for me over the past week. I personally feel a lot better about a crowded list of short To Do items than a crowded email inbox with paragraphs and paragraphs of information to deal with. I’ve been able to keep my inbox pretty clear and it has helped me make sure I’m responding to everyone who emails to me in a pretty timely manner.

Cellular Automata Method for Generating Random Cave-Like Levels

C_e_l_l_u_l_a_r A_u_t_o_m_a_t_a M_e_t_h_o_d f_o_r G_e_n_e_r_a_t_i_n_g R_a_n_d_o_m C_a_v_e-L_i_k_e _L_e_v_e_l_s Ive always been super interested in cellular automata and thought it was interesting to see such a practical use case for them.

Teen Texting

G_r_u_b_e_r linked to a_n a_r_t_i_c_l_e b_y N_i_e_l_s_e_n a_b_o_u_t T_e_e_n T_e_x_t_i_n_g. He quotes the article:

 The number of messages exchanged monthly (SMS and MMS) hit 3,417 per
 teen in Q3 2011, averaging seven messages per waking hour.

At first that data point was pretty astounding to me. The average teen sends 3,417 text messages per month? 7 per waking hour? I cant imagine texting anything near that frequency. But then I realized something. In the late 90s when I was a teenager I probably sent 3,417 or more messages per month to my friends, I just did it with a different medium - instant messaging. When you think about it in that context the number of text messages sent makes a lot of sense. In many ways its even easier to text more than IMing since you always have your phone with you. Looking at the data in that light, it makes a lot of sense that Apples text messaging interface on the iPhone looks so much like iChat.

Ditching Rdio

I’ve been an Rdio member for a while now, but something kept nagging me. I love music. I have a job that lets me listen to it pretty much all day, and I definitely take advantage of that, but the whole time I used Rdio it felt like it was causing me to keep music at arms length.

I think Rdio’s social features and recommendation features are amazing because they told me what music I could be checking out and offered me all sorts of great new options. There’s one major negative to that, though. With Rdio it’s way easier to taste test tons of music but never really settle onto something and listen to it over and over again like you did when you were in high school and you bought a new album and knew that one album would be the only new album you would get to listen to that month. I’ve realized for a while that I miss paying that kind of attention to music, so I decided to ditch Rdio.

Instead I’m using iTunes again, and purchasing music through iTunes and Amazon MP3. I realized during the changeover that there were a few albums from my Rdio days that I couldn’t live without, like Torches by Foster the People, Gimme Some by Peter Bjorn and John, and Tron: Legacy Reconfigured. So my time with Rdio didn’t completely keep me from loving some albums, but I’m still sticking with my opinion that Im better off without it.

If you’re wondering, this month’s albums are Songs for Christmas by Sufjan Stevens (Adair really wanted us to get this one, but I’m really loving it), Revolver by the Beatles (how did I not own this album already?), and Maners by Passion Pit. I’m listening to them like crazy and loving every moment of it.