OnionOrNot

Guess whether the headline is real or from satirical newspaper The Onion. OnionOrNot is a collaboration between myself and Luiz Neves. We worked together remotely using Google Hangouts and Github.

Luiz worked primarily on the design, markup, and styling of the site. My primary role was in building the JavaScript that drives the game.

Desktop

The OnionOrNot project tested my knowledge of several JavaScript-related buzzwords. It's object-oriented and pulls it's data using AJAX calls.

Phone

It works just as nicely on the phone. Luiz devoted significant time to tuning the transitions to use GPU acceleration to get the performance we wanted on mobile.

HeadlineList object

The most complicated object in the game is the HeadlineList. Given a URL, it can fetch headlines without a page load using AJAX. As the headlines are attempted by a player, they are removed from the list. It knows how to reload the headlines when it's empty so the player can keep playing.

function HeadlineList(url) {
    // Object that retrieves a list of headlines from a JSON file
    this.url = url;
    this.loaded = $.Deferred();
    this.isEmpty = function() {
        return (this.quantity === 0 || this.quantity === undefined);
    };
    this.getRandom = function(remove) {
        // Selects and returns a random headline object
        var listObject = this;
        if (listObject.isEmpty()) {
            listObject.refreshContent();
        }
        return listObject.ajaxPromise.pipe(function() {
            var headlineNumber = Math.floor(Math.random() * listObject.quantity);
            var headlinePick = listObject.list[headlineNumber];
            if (remove) {
                listObject.deleteHeadline(headlineNumber);
            }
            return headlinePick;
        });
    };
    this.getHeadline = function(number, remove) {
        // Returns a headline specified by index
        var listObject = this;
        if (this.isEmpty()) {
            this.refreshContent();
        }
        return listObject.ajaxPromise.pipe(function() {
            var headlinePick = listObject.list[number];
            if (remove) {
                listObject.deleteHeadline(number);
            }
            return headlinePick;
        });
    };
    this.deleteHeadline = function(number) {
        // Deletes a headline specified by index
        this.list.splice(number, 1);
        this.quantity -= 1;
    };
    this.fillFromJSON = function(data) {
        // Sets object properties with results from the AJAX call
        this.list = [];
        for (var i = 0; i < data.headlines.length; i++) {
            var currentHeadline = data.headlines[i];
            this.list[i] = new Headline(currentHeadline.title, currentHeadline.url, currentHeadline.onion);
        }
        this.quantity = this.list.length;
        $(this).trigger('ajaxSuccess');
        this.loaded.resolve();
    };
    this.refreshContent = function() {
        // Reloads JSON file
        var listObject = this;
        listObject.ajaxPromise = $.ajax(listObject.url, {
            success: function(data) {
                listObject.fillFromJSON(data);
            },
            beforeSend: function() {
                $(listObject).trigger('ajaxLoading');
            },
            complete: function() {
                $(listObject).trigger('ajaxComplete');
            },
            error: function() {
                $(listObject).trigger('ajaxError');
            },
            type: 'GET',
            data: {},
            timeout: 4000,
            datatype: 'json'
        });
    };
}