Fandom

xkcd Time Wiki

Javascript

1,338pages on
this wiki
Add New Page
Comments0 Share

About 10-20 newpix in to the comic, readers noticed a small piece of mysterious, minified JavaScript below the image that had not been there at the time of the comic's creation. Theories abounded as to what it did until people realized it primarily just autoloaded the next image.  It seems to have been created on the fly by Randall in order to reduce the number of people hammering the refresh button every few millipix.  As of the time of this writing, the script appears to be on its seventh revision.

The Code:Edit

This was formatted and annotated by ternarybit, a Watcher of Time, and posted on Pastebin .

function () {
    function t(e) {
        (new Image).src = "http://xkcd.com/events/" + e
    }
    function n() {
        location.hash == "#verbose" && console.log.apply(console, arguments)
    }
// This spreads requests over 8 subdomains
    var e = ["http://c0.xkcd.com", "http://c1.xkcd.com", "http://c2.xkcd.com", "http://c3.xkcd.com", "http://c4.xkcd.com", "http://c5.xkcd.com", "http://c6.xkcd.com", "http://c7.xkcd.com"];
    try {
// This selects randomly between the subdomains above
        var r = e[Math.floor(Math.random() * e.length)],
// These create a new event source to listen for a new comic
            i = r + "/stream/comic/time?method=EventSource",
            s = new EventSource(i);
// This starts a connection to the event source
        n("connecting to event source:", i), s.addEventListener("open", function (e) {
            t("connect_start")
        }, !1), s.addEventListener("error", function (e) {
            n("connection error", e), t("connect_error")
        }, !1), s.addEventListener("comic/time/ping", n, !1), s.addEventListener("comic/time", n, !1);
        var o = !0;
// If the event source spits out a response, parse it.
// The event source is just a JSON file that includes what looks like a SHA1 hash that is used to construct the image's file name
        s.addEventListener("comic/time", function (e) {
            var t = JSON.parse(e.data),
                r = document.getElementById("comic").getElementsByTagName("img")[0],
                i = o ? 0 : Math.round(Math.random() * t.spread);

            n("waiting", i, "seconds before displaying comic", t.image), setTimeout(function () {

// This changes the image on the web page
                r.src = "http://imgs.xkcd.com/comics/time/" + t.image
            }, i * 1e3), o = !1
// This basically just keeps checking for a new image, and if it finds one, loads it.
// The timing of new images is entirely server-side, controlled by what JSON response the servers give.
// As far as I can see, there is no way to speed things up, since the event responses are sent from the server.
        }, !1), s.addEventListener("comic/time/reload", function (e) {
            var r = Math.round(Math.random() * 55);
            n("reloading in", r + 5, "seconds"), setTimeout(function () {
                t("reloading"), setTimeout(function () {
                    location.reload()
                }, 5e3)
            }, r * 1e3)
        }, !1)
    } catch (u) {
        t("js_error")
    }
}();

fiveofoh also made an annotated version and put it up on GitHub:

//This event appears to ping xkcd's servers when various things happen
//Probably for serverside logging/analytics/debugging/statistics
function ping_event(evt_name) {
    (new Image).src = "http://xkcd.com/events/" + evt_name
}
//This function ouputs debug info into the javascript console if the URL has a "#verbose" anchor appended
function log() {
    location.hash == "#verbose" && console.log.apply(console, arguments)
}
//A list of event streams to choose from at random, for load balancing
var loadbalance_urls = ["http://c0.xkcd.com", "http://c1.xkcd.com", "http://c2.xkcd.com", "http://c3.xkcd.com", "http://c4.xkcd.com", "http://c5.xkcd.com", "http://c6.xkcd.com", "http://c7.xkcd.com"];
try {
    //Choose a stream and initialize and EventSource watching it
    var baseurl = loadbalance_urls[Math.floor(Math.random() * loadbalance_urls.length)],
        evturl = baseurl + "/stream/comic/time?method=EventSource",
        s = new EventSource(evturl);
    log("connecting to event source:", evturl);
 
    //Connect functions to listen for certain events, mostly diagnostic
    //Ping xkcd's server when the stream is opened
    s.addEventListener("open", function (msg) { ping_event("connect_start") }, false);
    //Ping xkcd's server and log to the console on an error
    s.addEventListener("error", function (msg) { log("connection error", msg); ping_event("connect_error") }, false); 
    //Log pings and events from xkcd's server in the console
    s.addEventListener("comic/time/ping", log, false);
    s.addEventListener("comic/time", log, false);
 
    //This is the meat of the function - responds to "comic/time" events from xckd's event streams
    var first_event = true;
    s.addEventListener("comic/time", function (msg) {
        //Parse the message from the stream
        var data = JSON.parse(msg.data);
        //Grab the image so we can change it
        var img = document.getElementById("comic").getElementsByTagName("img")[0];
        //If it's the first ping, display the image immediately
        //otherwise delay it by a random number of seconds
        //Between zero and the maximum spread defined in the event
        //This is presumably another load-balancing mechanism
        var delay = first_event ? 0 : Math.round(Math.random() * data.spread);
 
        //Change the image and log as such
        log("waiting", delay, "seconds before displaying comic", data.image);
        setTimeout(function () { img.src = "http://imgs.xkcd.com/comics/time/" + data.image }, delay * 1e3);
 
        //It's not the first event any more
        first_event = false
    }, false);
 
    //Also respond to requests for page reloads
    //Presumably this is in case Randall needs to update the javascript, which he did several times (this is version 7)
    s.addEventListener("comic/time/reload", function (msg) {
        //Also introduce a random delay here, again likely for load-balancing
        //So not everyone reloads the page at once
        var delay = Math.round(Math.random() * 55);
 
        //Reload the page, whee!
        log("reloading in", delay + 5, "seconds");
        setTimeout(function () {
            ping_event("reloading");
            setTimeout(function () { location.reload() }, 5e3)
        }, delay * 1e3)
    }, false)
} catch (err) {
    //If we have javascript errors, send them back to xkcd's servers
    ping_event("js_error")
}

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.