Hello, I’m Joe Vennix, and this is where I blog.

I am a twenty year-old CS student at the University of Texas. I work as a developer and a designer. I am currently interning at Metasploit, where I get to work with awesome tools like Rails, Coffeescript, and SASS to develop the user interface to the Metasploit Pro product. My past work includes writing iPhone apps, designing and coding websites, and creating custom software. My products have been featured on national commercials, billboards, and magazines.

I am currently busy with school and contracting, but from time to time I will post a personal project up here.

Twitter / Facebook / Github

Add a spotlight “sheen” to your backgrounds with CSS3

Posted on 29 Jun 2011

Recently when building an admin panel for a client, I decided to add a spotlight sheen effect to the background for a sleeker look. Here's a snap of the completed design:

Here's the CSS(3) that I used to do it. The "sheen" is really just a radial gradient that tapers from a transparent white to full transparency:

background:-webkit-gradient(radial, 250 50,0,250 50,800,
            from(rgba(255,255,255,.4)),to(transparent)) transparent;
background: -moz-radial-gradient(250px 50px, 
            rgba(255,255,255,.4), transparent) transparent;

The effect is applied to a #wrap div, which lies directly on top of the body.

How I implement static-site search

Posted on 25 May 2011

A few weeks ago I read about Tapir, a Javascript static-site search API: add a few lines of Javascript to your static blog or site (RSS feed required), and thanks to AJAX magic you can have your own built-in search functionality! No more clunky embedded Google search (the previous “best solution”). Really a very good idea, and nicely implemented as well.

However, my blog isn’t that big, since I am constantly changing servers and losing years worth of blog posts. My RSS feed weighs in at a whopping 4kb. All my posts fit on a single page. Because of my relatively small RSS footprint, Tapir seemed to be overkill.

So I wrote my own solution. Check it out by typing something into the search bar at the top right. RSS feeds are just XML, which is very easy to parse with Javascript. Even easier (kinda) with jQuery’s $.ajax() calls. Here’s what my code looks like:

function findEntries(q) {
  var matches = [];
  var rq = new RegExp(q, 'im');
  for (var i = 0; i < entries.length; i++) {
    var entry = entries[i];
    var title = $(entry.getElementsByTagName('title')[0]).text();
    var link = $(entry.getElementsByTagName('link')[0]).attr('href');
    var content = $(entry.getElementsByTagName('content')[0]).text();          
    if (rq.test(title) || rq.test(link) || rq.test(content)) {
      var updated = prettyDate(xmlDateToJavascriptDate($(entry.getElementsByTagName('updated')[0]).text()));
      matches.push({'title':title, 'link':link, 'date':updated});
    }
  }
  var html = '<h3 style="text-align:center; margin-bottom:40px;"><a href="#" onclick="window.location.hash=\'\'; return false;"><img style="height:8px; margin:3px 3px;" src="/images/closelabel.png" /></a> Search Results for "'+htmlEscape(q)+'"</h3><div id="results">';
  for (var i = 0; i < matches.length; i++) {
    var match = matches[i];
    html += '<div class="results_row"><div class="results_row_left"><a href="'+match.link+'"*gt;'+htmlEscape(match.title);
    html += '</a></div><div class="results_row_right">'+match.date+'</div><div style="clear:both;"></div></div>';
  }
  html += '</div>';
  $('#content').html(html);
}

$('#search_form').submit(function(e) {
  var query = $('#query').val();            
  window.location.hash = 'search='+escape(query.replace(/\s/g, '+'));
  e.preventDefault();
});

$(window).bind('hashchange', function(e) {
  var query = $.param.fragment().replace('+', ' ').replace('search=', '');
  $('#query').val(query);
  console.log('Changing state: '+query);
  if (query == '') {
    if (oldhtml == null) {
      oldhtml = $('#content').html(); 
    }
    $('#content').html(oldhtml);
    $('#footer').show();
    $('#query').blur();
  } else {
    $('#content').html('<div id="loader"></div>');
    $('#footer').hide();
    $('#query').blur().attr('disabled', true);
    if (entries == null) {
      $.ajax({url:'/atom.xml?r='+(Math.random()*99999999999), dataType:'xml', success: function(data) {
        entries = data.getElementsByTagName('entry');
        findEntries(query);
      } });
    } else {
      findEntries(query);
    }
    $('#query').blur().attr('disabled', false);
  }
});
$(window).trigger( 'hashchange' );

I use Ben Alman’s jQuery BBQ plugin to manage the page state. As you can see, the actual searching is done with regular expressions for the moment. This won’t scale as well as something like a Boyer-moore search, but I think it’s neat to be able to grep through my posts. Because the RSS feed is cached, every search after the initial one is almost instantaneous.

Although this is not an optimal solution for sites with a huge amount of posts, it does work very well to small- to medium-sized sites. The main barrier in my solution is that the script has to process the entire text of every post, which can be very slow. I figure this could be improved by having a pre-generated dictionary (preferably something like a trie structure for easier partial-matching) that holds all the words in a post, and points to an array of post IDs. Can anyone think of how this could be further optimized?

Finally, a complete Node.JS IP geolocation library

Posted on 10 May 2011

I received a message from the user kuno on Github today:

Hi: My name is kuno, the maintainer of geoip module on nodejs. Your project GeoIP-js inspired my re-write my module from sketch, appreciate that. Do you mind I added your name into the contributor list? If so, may I have your email address? --kuno

After looking over his geoip module, his project looks to be more in-depth and versatile compared to my rather limited module, which I wrote about here. So, hats off to kuno, I’ve updated my repo to redirect users to his project. To install kuno’s geoip, simply use npm:

$ npm install geoip

Hacking Safari’s Reader

Posted on 09 May 2011

I often use Safari’s Reader function when I come across articles that have tiny print, are contrained along a very narrow column, or are broken up by enormous ads. For those of you unfamiliar with Safari’s Reader, it basically performs the same function as the Readable bookmarklet: it extracts the body of an article and presents it in an easy-to-read format. Here’s an example:

The problem is, of course, what determines how the article is extracted? And, in that case, how the title is extracted? I ran into this problem when designing my blog, resulting in the title of every article appearing as “[between extremes]” – my blog title, not the article title – in the Reader.

Weird. I searched a bit for “Safari Reader documentation” and found nothing, so I futzed around with the HTML and eventually got it to work by adding the “title” class to the <h3> tag holding the title. Problem solved, pack it up and move on.

Hang on a second, though. I started to wonder what algorithm Safari uses for extracting articles. Then I realized the easiest way to write something like Safari Reader would be in plain JS, with the HTML already parsed into a DOM and whatnot. So I decided to see if Safari injects the code for Reader into the page, for the sole sake of science. A minute later I found the code and came to the conclusion that Safari Reader is just a glorified Safari extension, consisting of an injected script, style, and toolbar button.

For legal reasons I don’t think I can just post the code, but here’s how to access it:

  1. Open Hacker News in Safari (no sense in wasting a tab)
  2. Open Web Inspector (cmd-option-I)
  3. Open the Scripts tab, click Enable Debugging
  4. Pause the Javascript interpreter (above "Watch Expressions")
  5. Refresh the page
  6. Step through the code line-by-line. Eventually you'll get to the Safari Reader code

The JS code that you now see in the Web Inspector is the article extraction algorithm for Safari Reader. Incredibly, the code is not packed or minified, so by throwing it through jsbeautifier, you can end up with some nice, readable code. A couple of interesting things I noticed by glancing through the code:

  • The script uses a Levenshtein distance calculation sometimes to check if a certain string of text agrees enough with the article to be the title.
  • ~1200 lines of Javascript, hundreds of arrays, and not a single splice() call
  • The algorithm works by slowly trimming irrelevant DOM nodes, ending up with just the article content
  • For a certain body of text to be the primary article candidate, it must have at least 10 commas
  • The "#disqus_thread" identifier is one of the few, hardcoded, values the parser automatically skips
  • The algorithm also parses next page URL by looking for the link with the best "score"
  • You can copy and paste this script into the console of any browser. To run it, you would type:
var ReaderArticleFinderJS = new ReaderArticleFinder(document);
var article = ReaderArticleFinderJS.findArticle();

This code might be valuable to anyone looking to scrape text content from HTML. If anyone has better pointers into the script’s inner workings, feel free to comment!

GeoIP.JS - An IP Geolocation Library for Node.JS

Posted on 25 Apr 2011
/*=========    GeoIP.JS Sample Code    ==========*/
var geo = require('./GeoIP-js/geoip.js');
geo.open({ cache: true, filename: './geoip/GeoLiteCity.dat'});
var coord = geo.lookup('74.125.227.16');
console.log(coord);
geo.close();
geo.open({ cache: true, filename: './geoip/GeoLiteCity.dat'});

Last week I needed a way to geocode IP addresses to GPS coordinates using Node.JS. I needed the geocoding done fast (locally) as I wanted to serve the coordinates within the page. I eventually found the (free) MaxMind GeoIP API which is a C library that parses their (also free) database of cities, GeoLite City, which is accurate “over 99.5% on a country level and 79% on a city level for the US within a 25 mile radius.” Good enough for me.

Unfortunately, while wrapper libraries had been written over the C API in a few different languages, Javascript was not among them. Luckily, Node.JS supports writing native extensions in C++, so with the help of a few walkthroughs and examples, I was able to hack together a native binding around the MaxMind C API.

I pushed the result to GitHub here; it might be helpful for anyone trying to figure out how to write native extensions for Node.JS. The library is far from complete: the C API allows you to pull data such as city, state, and zip code, whereas my implementation simply takes an IP and returns an array of coordinates. However, following the same model set up in my code, it would be trivial to code up similar functions that return other data.

One other thing: this library is synchronous. I thought this might cause some trouble, so I ran a few benchmarks. I found that the API often responded in less than 1ms - amazing! The API by default caches the database in memory, leading to some very fast lookups.

JScrollie, and Why Javascript Scrollbars Suck

Posted on 12 Apr 2011

Scrollbars are an essential part of just about every website. Any div that overflows (and is not set to overflow:hidden) requires one, along with the <body> tag. And yet, with the exception of IE*, they are hardly customizable in most browsers. To get around this, various projects have been written that recreate scrollbars in Javascript to make them highly configurable.

The problem with most Javascript (and Flash, for that matter) scrollbar solutions today is that they essentially reinvent the wheel by reimplementing all of the native scrolling logic in Javascript, which has a very disconcerting effect on the user. I am used to one scroll setting. When I spin my scrollwheel and the scrollable area flies by too fast, or takes an hour to move down an inch, or, shudder, continues scrolling long after I’ve stopped thanks to some fancy inertia effect, I get a little pissed off. I immediately reach for the scrollbar, as dragging the scrollbar around is generally easier than recalibrating my brain to a new scroll setting. If dragging the scrollbar still produces an inertia effect, well, you better watch your back.

Note: I’m not trying to say faster, slower, or inertia settings for scrolling are inherently bad, they just aren’t what I’m used to. I’m thrown out of my comfort zone. And I have at least one reason to not return to your site. What I am trying to say here is that users are used to the native scroll settings, i.e. whatever they have set in System Preferences / Control Panel. It makes no sense to force them to use anything different.

Anyways, while working on a project of mine last weekend, I ran into the need for a small, transparent scrollbar to maximize screen space. After looking around at the currently available options, I eventually ran into this Google Groups thread, which talks about Scrollbar Paper, a jQuery scrollbar solution written by Henri Medot that works by essentially creating a div that “covers” your actual scrollbar using absolute positioning and a high z-index. Dragging this div around would fire jQuery callbacks that moved the scrollbar, and scrolling up and down the page would fire callbacks that moved the div. Additionally, a 200ms timer callback was setup that repeatedly checked the content size and adjusted the size of the div to match, or hide the div altogether if possible. That way, the actual scrolling logic remained native, while the old scrollbar was hidden out of sight and replaced with a div that you can customize through CSS.

I thought this was an interesting idea, so I grabbed the source code and started messing around. I came up with a slightly different solution, here is a picture that compares both methods:

Basically, my solution works by creating a wrapper div that has overflow:hidden. Inside of this div is the actual scrollpane, whose width is set to width of the wrapper div + 20px. This pushes the y-scrollbar out of sight. I then use Henri’s code for creating a fake scrollbar and binding it to follow scroll events. This yields a couple advantages over the original implementation:

  1. You can create a truly transparent scrollbar. This is important when you’re scrolling over the table and you want the separator lines to continue all the way to the end.
  2. The original solution would sometimes “flicker”, and I would catch a glimpse of the native scrollbar underneath the “scrollbar paper.” With the new solution, the scrollbar is completely hidden, not just covered with a div with a higher z-index.

I turned my solution into a separate project called jScrollie, which you can get on github here. Right now its sole purpose is to wrap an entire page with a custom scrollbar, however with a little hacking you can get this method working for embedded content (I had to do this for my project). jScrollie also degrades nicely, since all the “wrapper” divs are created when (scrollpane).jScrollie() is called. Forgoing this call leaves you with a stock scrollpane.

For a demo, look at your scrollbar :)

* Although, I can’t give them too much credit: they only allow tint changes to certain parts.