Modernizr should prefix its classes

I had a button to toggle a site’s background audio (<a class="audio">Toggle Audio</a>) and I couldn’t figure out why this code was firing twice for a single click:

$('.audio').on('click',function(e){
  e.preventDefault();
  if ($(this).hasClass('off')) AUDIO.unmute();
  else AUDIO.mute();
});

It’s because Modernizr puts an audio class on the <html> element.

<html class="js [...] video audio [...]">

That means $(‘.audio’) contained both elements, <html> and <a>. A click on the <a> was bubbling up to the <html> and triggering the handler again.

Modernizr should do this instead <html class="... mdnzr-video mdnzr-audio ...">

iTunes Sleep Timer

Here is a simple AppleScript that will smoothly fade out your music and then pause iTunes and optionally sleep your Mac.

There are a few nice things about this script:

  • Lets you choose to sleep the machine or not at the end.
  • Puts iTunes back to its original volume after pausing it at the end.
  • Waits half of the time before starting the gradual fade, so you can enjoy the music at normal volume for a while.
  • Will default to 30 minutes if you run it but forget to click the dialog.
  • Works with AirPlay speaker setups since it uses iTunes’ master volume to do the fade.

Open up your AppleScript editor and paste this in, then save as an application.

property default_minutes : 30
property wait_percent : 50 -- wait before starting fade

set question to "Set a sleep timer for how many minutes?"
set options to {"Don't sleep after", "Sleep after", "Cancel"}

display dialog question default answer default_minutes ¬
    buttons options default button 1 giving up after 30
set {_button, _answer} to {button returned, text returned} of result

if _button = "Cancel" then return

set sleep_after to false
if _button = "Sleep after" then set sleep_after to true

try
    set sleep_seconds to _answer * 60
on error
    beep
    display dialog ¬
        "TIMER NOT RUNNING. You didn't enter a number." with icon stop ¬
        buttons {"Quit"} default button 1
    return
end try

set steps to 60
set wait_before_fading to (sleep_seconds * (wait_percent / 100))
set fade_time_step to ((sleep_seconds - wait_before_fading) / steps)

delay wait_before_fading

tell application "iTunes"
    set init_volume to sound volume
    repeat with i from 0 to steps
        set sound volume to (init_volume - (i * init_volume / steps))
        delay fade_time_step
    end repeat
    pause
    set sound volume to init_volume
end tell

if sleep_after then tell application "Finder" to sleep

When you want to use it, start your music in iTunes, set it to a comfortable volume, then run the app.

If you want to cancel the timer once it’s running, you have to either hit Command-. (Command-Period) within the app, or force-quit the app with Command-Option-ESC.

Mercurial: How to reapply a revision/changeset

Sometimes you have to collaborate with someone who doesn’t use version control. This will happen often if you’re sharing work over ftp.

If you make a change and then receive an old version of the file you changed with a new change of theirs, you can reapply your change with this command.

Let’s assume your change is in revision 78 and in file my/awesome/file.js

Go to the root of your repo and run:

hg diff -r77:78 my/awesome/file.js | patch p1

Happy merging!

Dynamic Tweet Button Text Using jQuery

I recently needed to make a tweet button that would dynamically change the text that was posted to twitter based on the date.

Here is the standard code for a tweet button:

<a href="http://twitter.com/share"
    class="twitter-share-button"
    data-text="This is what we want to change dynamically"
    data-count="none" data-via="chris_camps">Tweet</a>
<script type="text/javascript"
    src="http://platform.twitter.com/widgets.js"></script>

Now, if you were using php or some other server-side language, this would be trivial:

    data-text="<?php print $dynamic_tweet_text ?>"

My situation required a javascript-only solution though, because it was a static html project without a backend infrastructure.

My first instinct was to do a ninja swap on page load using jQuery:

<script>
$(document).ready(function(){
    $('a[data-text]').each(function(){
      $(this).attr('data-text', "This will not work");
    });
});
</script>

I suspected this would fail, and it did. The reason is that $(document).ready() will execute after all the <script> tags in the document, including twitter’s <script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>. When twitter’s js file runs, it immediately replaces the <a> with an iframe, and then it’s too late to affect it with our jQuery.

I had to somehow run twitter’s js file after my code. Thanks to jQuery the solution was easy!

<script>
$(document).ready(function(){
    $('a[data-text]').each(function(){
      $(this).attr('data-text', "This works!");
    });
    $.getScript('http://platform.twitter.com/widgets.js');
});
</script>

<a href="http://twitter.com/share"
    class="twitter-share-button"
    data-text="This is what we want to change dynamically"
    data-count="none" data-via="chris_camps">Tweet</a>
<!-- moved to the js above <script type="text/javascript"
    src="http://platform.twitter.com/widgets.js"></script> -->

Quick macports migration tip

There is a way to get macports to show you only the packages you told it to install, as opposed to the whole installed dependency tree. This is extremely useful when setting up a new system.

$ port echo requested

This will give you a nice concise list of the packages you really want, so you can pick and choose what to install on your new system.

apache2                        @2.2.17_0+preforkmpm 
git-core                       @1.7.3.4_0+doc+python26 
gnugo                          @3.8_0 
mercurial                      @1.7.2_0+bash_completion 
mysql5-server                  @5.1.53_0 
p5-app-ack                     @1.94_0 
php52                          @5.2.16_0+apache2+mysql5+pear 
python_select                  @0.3_0 
subversion                     @1.6.15_0 
wget                           @1.12_3+ssl

iPad HTML5 Video mime problem

I know. You have been beating your keyboard against your desk for hours getting that html5 video embed test working in MobileSafari on the iPad. You must have melted a small glacier re-encoding with every combination of container, encoding, and bitrate!

You checked and double checked your video tag. (You made sure to close the </video> and </source> tags right? Of course you did. You’re a professional after all.)

I know what the problem is. But I’m not going to tell you. Ok, ok, I’ll tell you, but only because I like you and I don’t want you to get fired.

Surprise! It’s your web server’s Content-Type header!

For some weird reason, browsers will disregard the mime type you explicitly wrote in the <source type="video/mp4"/> tag, and instead choose to trust the mime type coming from the server. For example, older IIS servers treat .mp4 files as application/octet-stream which seems ok to me, but simply did not fly with iPad.

Now how do you change your web server’s mime map? That’s between you and Google, buddy.

Turn your mac into a Pandora alarm clock

Here’s a tutorial for anyone wanting to turn their fancy new $2000 Mac into a $19.99 clock radio.

We’re going to use AppleScript, iCal, and the awesome PandoraBoy to get everything working. I thought this would be clunky at first but it’s actually really nice and flexible if you break things up the way I’m about to show you.

Read More
How to kill an unresponsive ssh session

I love stumbling on clean solutions to little annoyances I deal with regularly. Anyone who uses ssh on a regular basis definitely knows how this story goes.

You have all your terminal windows/tabs arranged exactly how you like them. Then BOOM, one of your ssh sessions hangs, making that entire window unusable. <CTRL>-C you say? Hah hah, I laugh ironically at your feeble term-fu. You have to either wait for the ssh process to properly die, or kill it manually from another session.

<RETURN>~.

No more! Just hit <RETURN>~. and ssh dies faster than Samuel Jackson in an underwater shark research facility.

Thanks Laszlo!

How to avoid accidentally zooming in Firefox with the mouse wheel

I got an Apple Magic Mouse recently and overall it’s quite nice. The momentum scrolling is an important evolution.

The momentum sometimes has side effects in apps that are not expecting it though. Firefox is one of these apps.

I tend to browse with many tabs open, and I like to switch between open tabs with control+tab and control+shift+tab (on mac).

The problem occurs when you flick your finger to scroll down a site and then immediately switch to another open tab with control+tab. By default, Firefox is set to “zoom” the site you’re on with control+mousewheel. Because of the momentum, Firefox still sees the mousewheel event when you press down control, and therefore starts zooming one or both of your tabs in catastrophic ways.

You can easily reset the zooming of a site by just hitting command-0 (zero), but it’s still annoying, and it happens more often than you would think.

Here’s how to disable the control+mousewheel zoom once and for all:

  1. Open a new tab and enter about:config into the address bar.
  2. Enter “mousewheel” in the filter textbox
  3. Look for any mousewheel.withXXXXXkey.action that has a value of 3 (3=zoom)
  4. Double click the 3 and change it to 0 (0=no action)

That’s it! No more inadvertent zooming. You can always set it back to default by right clicking the line you changed in about:config and choosing “reset.”

Don’t live with tiny annoyances, they add up.

How To Keep Your Data Forever

We’ve all sustained painful data losses at some point or another. After a number of years, you start to realize that you’re tired of getting sucker punched, and that you have the skill and knowledge to solve the problem once and for all. I’m going to outline here a relatively simple strategy to keep a set of data alive for the rest of your life.

Read More