codeslower.com Savor Your Code.

A Haskell Surprise!

My friend Joshua Siler, founder of HiringThing, recently wrote up an article about their homepage's "Buttons with a Surprise." It looked too cool, so I asked him to make a version for me. You can see the results on the homepage for my Haskell Cheatsheet. Move your mouse near some of the PDF links and watch the Haskell logo appear like magic!

Of course, I couldn't help tweaking his original implementation (available as a GitHub Gist). In particular, I didn't like how the mousemove function had to be attached to the document, meaning it ran a lot. You can see the complete source in my Gist (forked from Joshua's) at the bottom of this post.

Taking a page from 3D video games, I updated the initRobot function to create a bounding box around the target element. The mousemove function is then attached to that bounding box, rather than the document, meaning it runs a lot less often.

To ensure the bounding box did not mess up the layout of other elements, I made it span with absolute positioning. I sized and positioned the element such that it extended 90 pixels in all directions around the target element. Below, item_loc refers to the target item's location, item_dim holds the target's width and height, and detectDist is equal to 90 pixels:

itemDetect = $('<span></span>'); // Create the span.
itemDetect.css({
  "z-index": 100,
  "position": "absolute",
  "left": item_loc.left - detectDist,
  "top": item_loc.top - detectDist,
  "width": item_dim.w + detectDist * 2,
  "height": item_dim.h + detectDist * 2
});

Finally, to ensure the new item didn't mess up the existing DOM (which could make CSS selectors become invalid and change the page's appearance), I inserted the span at the end of body element:

$('body').append(itemDetect);

I didn't have to change Joshua's original mousemove implementation at all -- he'd parametrized it enough that it just worked when attached to itemDetect rather than document. I did need to add a mouseleave handler, which hides the surprise the when the mouse leaves the bounding box.

Finally, to attach the surprise to multiple elements, I just used jQuery to find all elements with class surprise:

$(document).ready(function() {
  $('.surprise').each(function (idx, item) { initHaskellButton($(item)); });
});

A drawback to my implementation is that overlapping bounding boxes do not play well together. The browser only fires the mousemove event for one of the overlapping rectangles -- not all of them. The logical step would be to iterate the overlapping bounding boxes and determine if any intersect with the mouse, but I'm not interested in going that far. Anyone is welcome to try!

In the meantime, enjoy your Haskell surprise!

Category: None

Please login to comment.