Easy Table of Contents
To make the table of contents on this page, I really wanted to do everything server side. That way, I would offer a consistent experience for users with and without Javascript. But I didn't want to have to maintain an actual table of contents section of this page by hand, as I'm just not into that. The solution then was to use a snippet of PHP to scan this page for sections and generate the ToC for me.
Each project on this page is in a div of class "project."
The id of the div is how we will navigate to each, either with or
without Javascript.
Each div has a child h2 with the title of the project inside.
We, then, want to make a list of links with targets taken from the div
elements and their text taken from the h2 elements.
Because the page is structured logically, I didn't bother parsing out the DOM
structure; rather, I just used grep and new that every time I find a div
I'm going to find a corresponding h2.
I modified these regexes to make sure that they don't detect themselves in the page.
Using the various utilities for stripping out all PHP and HTML tags would
have been cool too, but I wanted to avoid unnecessary processing.
$lines = file(__FILE__);
$ids = preg_grep('/^[ \t]+<div.*class="project"/', $lines);
$projects = preg_grep("/^[ \t]+<h2>/", $lines);
$ids = array_values($ids); //normalize the arrays to be 0 based
$projects = array_values($projects);
$patterns = array("/<h2/","/\/h2/");
foreach($projects as $key => $value)
{
$id = trim(preg_replace(array("/<.*id=\"/","/\">/"),array('',''),$ids[$key]));
$replacements = array(' <li><a href="'."#$id".'"',"/a></li"); //replace with list items holding links to hashed IDs
echo(preg_replace($patterns,$replacements,$value));
}
Whom to Follow
Update Twitter has once again rejiggered everything and I've gotten a little better with jQuery.
$('.flex-module-header h3:contains("Who to follow")').text("Whom to follow")
Whom to follow is a user script that changes the "Who to Follow" link on Twitter's top bar to "Whom to Follow." I wrote it because that thing was driving me up a wall.
I've only tested it in Chrome, but it's so simple that it's almost not worth testing in Greasemonkey. Kidding. I'll test it. Install it here. If you'd prefer a bookmarklet (tested in IE8, Firefox, Safari, and Chrome) then run the following in the URL bar of your browser tab that's open to Twitter:
javascript:(function(){document.getElementById("global-nav-whotofollow").firstChild.innerHTML="Whom to Follow";}())
You can also get the script from its Userscripts page.
3 Month Calendar
I like seeing a calendar for the previous, current, and next month. I also like seeing the current day highlighted. This (admittedly insane) one liner does all of those. I'll post the whole thing then break it down.
cal $(date '+"BEGIN{if(%m==1){print 12;print %Y-1}else{print %m-1;print %Y;}}"'|xargs awk);cal|sed "s/ $(date "+%d"|sed 's/^0/ /')/$(echo -e "\033[1;31m")&$(echo -e "\033[0m")/";date '+"BEGIN{if(%m==12){print 1;print %Y+1}else{print %m+1;print %Y;}}"'|xargs awk|xargs cal
The first part of this is the previous month's date. That's easy
enough, we just get the date from date and subtract 1.
But we have to handle the case of January, where we get 12 for the
month and the previous year. So our date string becomes an
awk command which handles that. We pass it using
xargs to turn the whole output into one string of
arguments, rather than passing them one at a time like backticks or
$(). We then pass the output of awk to
cal which just prints the previous month. Easy peasy.
The current month is fun. We first get the current day and, if it has
a leading zero, replace that with a space. that then becomes the
target of a regex in sed, which wraps the day in
ANSI escape
codes for, respectively, turning the text red and then clearing any
effect. That regex is then applied to the output of the current
month's calendar. We have to echo -e the color escape
codes because just printing them is not enough, apparently.
Finally we just do basically the same thing as the first command to
print out the next month. I used xargs to pass to
cal because I actually like that better. So do that.
Addendum: I use this in my Geektool to display it on the desktop. In
that case you have to leave off the -e option on each
echo inside the regex, but otherwise leave it the same.
Post addendum: I realize that the GNU date makes this easier than the
BSD date—all you have to do is specify -d "next month"
and you can skip the whole awk malarky. But BSD just doesn't have
that.
cal $(date -d "last month" '+%m %y'); cal; cal $(date -d "next month" '+%m %y')
Not Terrible Gallery
I recently worked on a portfolio site for my buddy James. He's a photographer who, among his other projects, went around the world on a Watson Fellowship, where he photographed the global shipping industry.
The challenge on the front end was making it not look like every other photo website. I wanted to implement his raster design concepts in CSS with decent animation in jQuery, but without alienating what few visitors wouldn't be using Javascript. To that end I did pretty OK. The everything but the landing page uses an invisible navigation ribbon at the top that shows itself when you hover it. The omnipresent logo at the top left hints that there is more up top in order to navigate. To be honest, it's not the design I would have chosen; I prefer users to know what their navigation options are at all times. But one renders unto the client that which is the client's, so I did what was asked. The navigation ribbon is always present if you don't have JS enabled. It does cover the photos somewhat—in the future I would make the default CSS push the photos down, then have the Javascript push them back up if it can hide the ribbon.
The other thing I'm not crazy about is the way the logo shows up on interior pages. Without it cached, it loads last. This is because it is the background to the title heading, whose text is off screen. Semantically, this makes sense: the image is not part of the content. Furthermore, the title text gets scraped first, by search engines, so you get less of the navigation ribbon and more of the title and subtitle in the search engine summary. However, background images get loaded last. To combat this, I would make the photos on the page the backgrounds of their list items, instead of images within them. However, this concern was obviated when he decided to go to a CMS.
On the backend, I ended up making a № 8 wire filesystem based CMS. The gist is that it scrapes directories corresponding to galleries for the photos in that gallery. Photos are named sequentially in order to be listed in order. To the user it appears that galleries are folders, but that's actually a URL rewrite to make it clean for linking and scraping. The end result was that the client—James—only had to edit one file and upload photos in order to make a new gallery.
I decided not to use the Flickr API to make his page because I thought their licensing terms would have made it a bit tacky. Specifically, all photos must reside in links to the original photo's page on Flickr. I figured that my "FTP and one file edit" design was sufficient.
Of course, a horse lead to water does not always drink; he's moving over to a new CMS with a new developer. I should probably mirror the work I did.
Heatmap
I like heatmaps. They're a pretty cool way of expressing 3D data in two dimensions. I've been working on a web tool to make quick little ones. Check it out. I've got a ton of features I want to add in the coming days and weeks and such, but I couldn't not give you a taste. Right now the only way to export the data is to hide the numbers and take a screenshot. It's what I've got right now. And obviously if you don't have Javascript please stay home.
