Source: views/nutritionView.js

/** Nutrition View
 * @namespace  nt.Views
 * @class nt.Views.Nutrition
 * @memberof! <global>
 * @extends Backbone.View */
nt.Views.Nutrition = Backbone.View.extend(/** @lends nt.Views.Nutrition# */{

    el: '#app',

    buttonsTemplate: Handlebars.Templates.buttons,

    events: {
        'click .item-nutrition': 'openNutrition',
        'click #nutrition-close': 'closeNutrition',
        'click #nutrition-add': 'addFood',
        'click #nutrition-remove': 'removeFood',
        'click #nutrition-track': 'openTrackerView'
    },

    /** Setup `this` context, DOM refs, variables, listeners and load google chart api */
    initialize: function() {
        _.bindAll(this, 'itemSuccess', 'itemError');

        this.$nutrition = $('#nutrition');
        this.$nutritionTop = $('#nutrition-top');
        this.$nutritionMenu = $('#nutrition-button-menu');
        this.$nutritionResults = $('#nutrition-results');
        this.$nLabel = $('#nlabel');
        this.trackedItem = null;
        this.gchart = null;
        this.gformat = null;

        // Load the Visualization API and the corechart package.
        google.charts.load('current', {'packages':['corechart']});

        // Close the Nutrition view when another search is run
        this.listenTo(nt.Plugin.Instance, 'selected', this.closeNutrition);

        // Update the Nutrition view model and tracking status when a food is saved
        this.listenTo(this.model, 'foodsaved', this.updateView);

    }, // initialize

    /** Display the button menu, pie chart, and nutrition label */
    render: function() {
        // Display button menu
        this.displayMenu();

        // Display pie chart
        this.displayChart();

        // Display nutrition label
        this.displayNutrition();

    }, // render

    /** Display the nutrition view */
    showColumn: function() {
        this.$nutrition.removeClass('hideColumn');
    }, // showColumn

    /** Hide the nutrition view */
    hideColumn: function() {
        this.$nutrition.addClass('hideColumn');
    }, // hideColumn

    /** Get the food item id and highlight it in the search view */
    openNutrition: function(e) {
        var elem = $(e.target);
        var id   = elem.data('item');

        e.preventDefault();

        // Close if already open
        this.closeNutrition();

        // Highlight selected item
        elem.closest('.item').css('background-color', '#b8dec0').addClass('highlight');

        // Show second column
        this.showColumn();

        // Get item data from localStorage or from the API
        this.checkItem(id);

    }, // openNutrition

    /** Check if the item selected is already in the tracker */
    checkItem: function(itemId) {
        // Check if this item is already being tracked
        this.trackedItem = nt.Collections.tracker.get(itemId);

        if(this.trackedItem) {
            // Copy the data from the tracker
            this.model.set( this.trackedItem.toJSON() );

            // Display the item
            this.itemSuccess();
        } else {
            // Get nutrition data from API using the item id
            this.getNutrition(itemId);
        }

    }, // checkItem

    /** Remove highlight, clear nutrition view, and hide the view */
    closeNutrition: function() {
        // Remove highlight from selected item
        $('.highlight').removeAttr('style').removeClass('highlight');

        // Clear chart and nutrition label
        this.$nutritionResults.find('figure').html('');

        // Hide second column
        this.hideColumn();

        // Restore hidden icons
        $('.tracked-delete').show();

    }, // closeNutrition

    /** AJAX success callback */
    itemSuccess: function(model, response) {
        // Render the nutrition info
        this.render();

        // Make the Search and Nutrition columns equal heights
        $('.row').eqHeights({child:'.eqHeights'});

    }, // itemSuccess

    /** AJAX error callback */
    itemError: function(model, errorResponse) {
        var status = errorResponse.status;
        var statusText = errorResponse.statusText;
        var msg = '<div class="alert alert-danger">Nutritionix item request failed: <br>' +
                   status + ' : ' + statusText + '</div>';
        this.$nutritionMenu.html(msg);

    }, // itemError

    /** Get food item details from Nutritionix */
    getNutrition: function(itemID) {
        var parameters = {
            'id': itemID,
            'appId': '53242d79',
            'appKey': '82289438a16ec7b92cdcf5ad054159c4'
        };

        // Display loading animation
        this.$nutritionMenu.html(nt.preloader);

        // Clear the model
        this.model.clear();

        // Make GET request to Nutritionix
        this.model.fetch({
            data: $.param(parameters),
            success: this.itemSuccess,
            error: this.itemError
        });

    }, // getNutrition

    /** Display pie chart using fat, carbs, and protein values */
    displayChart: function() {
        var fat = this.model.get('valueTotalFat');
        var carbs = this.model.get('valueTotalCarb');
        var protein = this.model.get('valueProteins');

        var data = google.visualization.arrayToDataTable([
            ['Nutrient', 'Value'],
            ['Fat', fat],
            ['Carbs', carbs],
            ['Protein', protein]
        ]);

        var options = {
            width: 280,
            height: 140,
            backgroundColor: '#b8dec0',
            sliceVisibilityThreshold: 0
        };

        var notZero = (parseFloat(fat + carbs + protein) !== 0);

        // Don't draw a chart if all the values are zero
        if(notZero) {
            // Add 'g' for grams unit to the values
            if(!this.gformat)
                this.gformat = new google.visualization.NumberFormat({suffix: 'g'});

            // Clear chart.
            if(this.gchart) this.gchart.clearChart();

            // Instantiate chart.
            this.gchart = new google.visualization.PieChart(
                    document.getElementById('gchart')
                );

            // Apply formatter to second column
            this.gformat.format(data, 1);

            // Draw chart.
            this.gchart.draw(data, options);
        }

    }, // displayChart

    /** Use label plugin to format and display nutritional values */
    displayNutrition: function() {
        // Reference Example #2
        // http://dev2.nutritionix.com/html/label-jquery-plugin/demo/demo.html

        // Reset the element and previous event handlers
        this.$nLabel.html('');
        this.$nLabel.undelegate();

        // Activate Nutrition Label jQuery Plugin by Nutritionix
        this.$nLabel.nutritionLabel(this.model.toJSON());

    }, // displayNutrition

    /** Display if food item is being tracked and button options */
    displayMenu: function() {
        var isTracked = false;

        // Clear button menu container
        this.$nutritionMenu.html('');

        // Set tracking flag
        if(this.trackedItem) isTracked = true;

        // Add the button menu html
        this.$nutritionMenu.append(this.buttonsTemplate({
            tracking: isTracked
        }));

    }, // displayMenu

    /** Open editor view for food */
    addFood: function() {
        // Create an editor view with the nutrition data model
        var editorView = new nt.Views.Editor({model: this.model});

        // Render the editor view and append its element to the nutrition view
        this.$nutrition.append( editorView.render().renderDatePicker().el );

    }, // addFood

    /** Destroy food model from the tracker collection using the id */
    removeFood: function() {
        var id = this.model.get('id');
        var food = nt.Collections.tracker.get(id);
        food.destroy();
        this.trackedItem = null;
        this.displayMenu();

    }, // removeFood

    /** When the 'foodsaved' event occurs, update the view's model and tracker status */
    updateView: function() {
        var itemId = this.model.get('id');
        var foodAttributes = nt.Collections.tracker.get(itemId).toJSON();
        this.model.set(foodAttributes);
        this.displayNutrition();
        this.trackedItem = true;
        this.displayMenu();

    }, // updateView

    /** If the item is being tracked, clicking the tracker status will open the tracker view */
    openTrackerView: function() {
        this.closeNutrition();
        $('#tab2').trigger('click');

    } // openTrackerView

});