Hacker News new | past | comments | ask | show | jobs | submit login
Lemmings 404 page (romainbrasier.fr)
320 points by thibaut_barrere on Jan 23, 2013 | hide | past | favorite | 73 comments



I've said it before, but: What's the deal with 404 pages?

If the content has moved, I should get a 30x redirect. If the server has a way of guessing what I wanted, I should get 300 Multiple Choices. If the server knows that what I'm looking for isn't anywhere, I should get 410 Gone. 404 is supposed to mean that the server has no idea what I'm looking for, no idea how to find it, no idea where to look.

In that case, I don't want a page to load. I don't want a tab to open. I definitely don't want to download a Flash game, or a 500kb JPEG, or infinity many Lemming images. I just want my browser to mark that link as dead and let me know in as unobtrusive a way as possible, "Hey, you clicked on some bullshit!" Let me either search the domain or click something else.

Not to rag on creative 404s, and I know it's a bit of a pipe dream. Just a peeve of mine.


Well I do think that "404" should be more visible but everything else is just part of design. It's like complaining that blogs should be just text or that CSS3 is pointless. It's design, it's interesting, I like it.


if you feel the point of "design" is simply to make something look pretty, or interesting, then you missed the point.


You're heartless, those poor lemmings were plummeting to their deaths!


Don't you worry my friend, I saved them all: http://i.imgur.com/EbvgPyT.png


I didn't have a choice, according to CFAA I was probably breaking the law just viewing the page!


I use Cloudflare's 404 pages feature, which incorporates possible intended destinations. I haven't had a chance to make a custom 404 page (e.g. with Google's 404 widget), so this gets the job done.

e.g. http://www.philipithomas.com/does_not_exist


Is that page customizable in any way? My first impression is that it looks like a parked domain landing page, which I instinctively ignore and close immediately.


What it boils down to is that 403, 404, 500, etc. pages are there to identify a problem loading the resource you're after. In the case of a 500, I might agree, but with the 404, you're getting what it's supposed to give you, and that's a heads up that the url you were shooting for was not found. Some companies get creative while others create useful links and guesses, but either way, you got the intended message, "not found".


As much as I love the 404, even more so I adore the immediate response of the hacker news community to find the best way to save all the lemmings. Bravo!


Followed by the inevitable snark denouncing what a waste of time and function it is.


Personally I got so sick and tired of Lemmings back when it was released that I find a feeling of peace by letting them all fall to their death.


Save them all! (firefox only)

    MutationObserver(function(event) {
      $(event[0].addedNodes[0]).mouseover();
    }).observe($('body')[0], {childList: true});
    $('img').mouseover();


I just resized my browser to be about an inch wide, and then they all fall in a straight line past the cursor.

I guess you could call that a workaround :-)


hmm... i was planning to run out and buy a taller monitor, but your workaround just saved me hours!


pretty awesome, this works in chrome

  new WebKitMutationObserver(function(event) {
    $(event[0].addedNodes[0]).mouseover();
  }).observe(document.body, {childList: true});


Much cooler than mine. I just ran

    $('img').each(function() { $(this).mouseover(); });
every few seconds. Something cool should have happened.


I just did:

    setInterval( function() {$('img').trigger('mouseenter'); }, 100 );
(probably burning up my cpu)


Nice, didn't think of this one


aha did that too, jquery style :

$('img').trigger('mouseenter')


One of my favourite 404 pages was this: http://www.homestarrunner.com/systemisdown.html


That's not not a 404 page (missing page). It seems like it's supposed to be a 500 page (server error) or 503 page (unavailable) but it incorrectly returns a 200 status which means everything is OK.

Edit: Corrected the 50X error information thanks to the responses below.


It is correct for a request for a page named "error" to result in a 200 OK status meaning that the page named "error" was successfully retrieved.

It would not be correct for a request for a page named "error" to return 404 Not Found if the page named "error" was retrieved successfully.

It would also not be correct for a request for a page that does not exist to return the page named "error" with a 200 OK status.


1) This page in no way is related to page missing (404). My response that it is not a 404 page is correct. This page has nothing to do with 404 error.

2) I made an assumption, based on the context, that this page was serving a role that is used when the server is overloaded or otherwise unavailable. In that case, this page should not be serving a 200 status, it should be serving a 50X response.

Now, it's possible that this page is just a demonstration of the error that would normally be produced when the website is unavailable. In that case, sure, 200 status is proper since it's not meant to actually be the literal error page which is served when the site has gone down. It's also possible the page has logic in it to serve 200 error when requested directly and 50X when the server is down.

In really, I bet this page is served as-is when the website is unavailable and sends a 200 error. It's difficult to know whether or not this is true until we see a real problem with the server.


It's probably technically incorrect, but the page title is "404 Doodoo error".


Didn't notice the title. That page is all over the place. The discussion the two characters were having was something like "Don't worry, the page will come back soon." Meaning, it's just a temporary error.

It's a fun page but horribly executed. The customer has no idea what's actually happening. Is this a server problem or is the page actually missing?


500 isn't server busy, it's server error.


I'd say being busy can be considered as an error.

503 (Unavailable) is more suitable for that I guess.


Yeah, IIRC 5-8 years ago Apache used to return 500 when PHP scripts timed out... hence association with "busy."


This is actually Homestar Runner's 404 page. Still a good one (warning - has sound)

http://homestarrunner.com/lkjsdflkjsdlkjklfjsdf.html


"Last Updated 12-22-10"

Wow. I guess the income from the swag (and their 15 minutes) ran out.


    var ims = document.getElementsByTagName('img');
    var event = document.createEvent("MouseEvent");
    event.initMouseEvent("mouseover", true, true, window);
    for(var i=0;i<ims.length; i++){
        ims[i].dispatchEvent(event);
    }
:(


    $("img").mouseover()


    window.setInterval(function() { 
      $('img').mouseover(); 
    }, 500);
So you can catch the ones that haven't been created yet.


Looks like a use case for MutationObserver:

    var evt = document.createEvent("MouseEvent");
    evt.initMouseEvent("mouseover", true, true, window,
      0, 0, 0, 0, 0, false, false, false, false, 0, null);

    function isALemming(node) {
      return node.nodeName === 'IMG';
    }
    function fakeMouseover(node) {
      node.dispatchEvent(evt);
    }
    
    function saveLemmings(possibleLemmings) {
      possibleLemmings.filter(isALemming).forEach(fakeMouseover);
    }
    
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(record) {
        saveLemmings(Array.prototype.slice.call(record.addedNodes || []));
      });
    });
    saveLemmings(Array.prototype.slice.call(document.getElementsByTagName('img')));
    observer.observe(document.body, { childList: true });


$('img').live('mouseover', function() {});

Same, but nicer, listens to mouseover events on img elements that may not exist yet. Then again, this will - if I understand correctly - cause the event to bubble up in the DOM until it reaches the root element, where jquery's live callback handler will check what element the event took place on and invoke that callback.


You're spot on that's the cleanest conceptual way to do it in jQuery. In more recent versions of jQuery, though, $.live is technically deprecated (1.7+). The equivalent new syntax is:

$(document).on('mouseover', 'img', function() {});


That creates a event handler for all images on mouseover, even images that haven't been created yet.

You want to trigger the mouseover event, not bind to it. And you want to trigger it after the image has been inserted. Unfortunately there's no jquery event for dom insertions. But on firefox you can use a MutationObserver:

    MutationObserver(function(event) {
      $(event[0].addedNodes[0]).mouseover();
    }).observe($('body')[0], {childList: true});


Whoops, you're 100% correct.


the 5 previous posts in this thread are so perfectly stepwise, it's making my head explode.


That registers a mouseover event listener. Mine triggers a mouseover event. They are completely different.


aww man...

    var event = document.createEvent("MouseEvent");
    event.initMouseEvent("mouseover", true, true, window);

    function save_them_prontos(){
        var ims = document.getElementsByTagName('img');

        for(var i=0;i<ims.length; i++){
            if(ims[i].id == ''){
               ims[i].id = i;
               ims[i].dispatchEvent(event);
            }
        }
        time_dem();
    }


    function time_dem(){
        window.setTimeout(function(){
            save_them_prontos();
        },100)
    }

    save_them_prontos();
triple :(


Wait...jQuery is available??

double :(


Was this double :( a response to the fact that jQuery is available and shouldn't have needed to be? Or because you just wrote 6 lines of javascript when you could have written 1?

I read it as the first, and had this immediate reaction:

- I'd rather write the 1 line of jQuery over the 6 in vanilla javascript

- I'd rather read the 1 line of jQuery to understand what is going on instead of the 6 in vanilla javascript

- jQuery didn't actually impact your experience much... as you didn't realize it might even be available.


I'd take the 6 lines of vanilla javascript any day over loading the full jQuery library to get away with writing only a single line. If jQuery isn't use anywhere else on the page, that is.


setInterval( function() { var ims = document.getElementsByTagName('img'); var event = document.createEvent("MouseEvent"); event.initMouseEvent("mouseover", true, true, window); for(var i=0;i<ims.length; i++){ ims[i].dispatchEvent(event); }}, 2000 )


It's much easier if you resize the tab - they all fall in a nice little column (and it doesn't change if you resize it after the load).


This is better than any of the solutions using JavaScript!


Obviously this is taken to a fun extreme, but it reminds me of a good practice: error pages should be treated as yet another way to engage with your visitor. Too many times I see people relying on the ugly default error pages provided by a web framework.


best 404 page i've seen ! I ended up playing.

Code is pretty neat. I thought you'd need more lines than this. http://www.romainbrasier.fr/js/lemmings.js


`this.img=eval($('.last'));`

Why is he using eval here?


I have no clue, and it's bothering me.

MDN says: >> If the argument of eval() is not a string, eval() returns the argument unchanged.

I copied the code and tried it both ways, saw no apparent difference. I don't think it does anything.. I could be wrong...


Half on-topic, half off-topic: WebGL Lemmings port: http://webglgaming.com/lemmings/index.php


Actually, that is a copy of DHTML lemmings from before the age of WebGL, Ajax, CSS sprites (alistapart only came up with an article about CSS sprites a year later), html5, or any of that fancy modern stuff kids these days play with. The original is at http://www.elizium.nu/scripts/lemmings/.

And background info / blogpost, written seven years later by the author: http://crisp.tweakblogs.net/blog/3881/dhtml-lemmings-primer....


Here's a more up-to-date version which uses HTML5 and AJAX - http://bombsite.org/jslems/


DHTML lemmings? DHTML? is this from 1998? :D - Oh, sorry... it says 2004. I don't think this is WebGL.

[edit] format


Tested in Chrome Version 24.0.1312.52 m

  var savedCount = 0;
  var saveFromDeathInterval = setInterval(function(){
  	for(var i=0;i<tabLemmings.length;i++){
            var lem = tabLemmings[i];
            if(lem.etat == 'tombe'){
               lem.etat = 'para';
               lem.paraOpen();
               savedCount++;
            }
  	}
        if(savedCount == 404)
        {
           clearInterval(saveFromDeathInterval);
        }
  },2000);


Not sure if I'd count it as "best ever" but it was amusing. Definitely a subtle way to just have fun.


well, that's the longest amount of time I've spent on a 404 page...


Great page, only thing that its missing is the nuke button!


What would you say if I told you I saved 396 - manually?


I'd say you used a tablet.


I feel bad the lemmings splat and die :/


You could write a script to save them all!


I wrote that prior to realizing it was a game :) I can now save a lot of them. I feel much better.


None died on my watch:

var saveTheirSouls = function() { $('img').trigger('mouseover'); setTimeout( function() { if ($('img').length > 1) { return saveTheirSouls() } else { return false; } }, 1000); }; saveTheirSouls();


This is really hard on an iPad. You can trigger a mouse over with a light touch, but it's not reliable.


Way better than a simple "Oops, page not found, blah, blah, blah"


DUDE, do you mind me taking this page? :D


So many lemmings. Gotta catch 'em all!


in chrome console:

winCount = count = 404; while ($('img').length > 0) { $('img').remove(); }


You can't save them all! :|


Solid 6 FPS in Chrome :(




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: