Source: views/exams/examsView.js

/*global require, define, console, $ */
/*jslint nomen: true, debug: true */

/**
 * @module examsView
 * @extends module:defaultView
 */


define([
    "framework",
    "views/defaultView",
    "text!templates/exams/examsTpl.hbs",
    "models/examsModel",
    "underscore",
    "utils",
    "views/exams/examsAvgChartView",
    "views/exams/examsSubjectChartView",
    "views/exams/examsSubjectYearChartView",
    "views/exams/examsAvgYearView"

], function ($, defaultView, tpl, Model, _, utils, avgChartView, subjectChartView, subjectYearChartView, avgYearView) {
    "use strict";
    /**
     * @name module:examsView
     * @description Exams widget class
     * @class Backbone.View
     *
     * @requires module:defaultView
     * @requires module:examsModel
     * @requires text!templates/examsTpl {String} Exams hbs template
     * @requires underscore
     * @requires module:utils
     * @requires module:examsAvgChartView
     * @requires module:examsSubjectChartView
     * @requires module:examsSubjectYearChartView
     * @requires module:examsAvgYearView
     *
     * @see module:defaultView
     * @see module:utils
     * @see module:examsModel
     * @see module:examsAvgChartView
     * @see module:examsSubjectChartView
     * @see module:examsSubjectYearChartView
     * @see module:examsAvgYearView
     *
     * @constructor
     * @returns {Function} Backbone.View constructor
     */

    var MENU_PRIMARY_CLASS = ".enw__menu--primary",
        MENU_SECONDARY_CLASS = ".enw__menu--secondary";

    return defaultView.extend({
        /**
         * @name module:examsView#template
         * @description Raw handlebars template
         * @type {String}
         */
        template: tpl,

        /**
         * @name module:examsView#name
         * @description Exams template id (need for caching)
         * @type {String}
         */
        name: "examsTpl",

        /**
         * @name module:examsView#title
         * @description Default exams widget title
         * @type {String}
         */
        title: "egeTitle",

        /**
         * @name module:examsView#ModelConstructor
         * @see module:defaultView#ModelConstructor
         * @see module:examsModel
         * @description Exams (EGE) model class
         */
        ModelConstructor: Model,

        /**
         * @name module:examsView#mode
         * @description Current widget mode
         * @type {Object}
         * @example
         * {
         *   subject: "avg",
         *   year: "yearSlice"
         * }
         */
        mode: {
            subject: "avg",
            year: "yearSlice"
        },

        /**
         * @name module:examsView#renderData
         * @description Exams charts update & widget menu render
         * @function
         */
        renderData: function () {
            var collection = this.model.get("collection"),
                relatedView = this.getRelatedView();

            /* istanbul ignore else */
            if (this.renderMenu) {
                // Getting unique subjects and years from model
                this.renderMenu(
                    ["avg"].concat(_.uniq(_.pluck(collection, 'name'))),
                    MENU_PRIMARY_CLASS
                );
                this.renderMenu(
                    ["yearSlice"].concat(_.uniq(_.map(collection, function (value) {
                        return (new Date(value.date)).getFullYear().toString();
                    }))),
                    MENU_SECONDARY_CLASS
                );

                // There's no need to render another one;
                this.renderMenu = undefined;
            }

            //this.switchModeDelayed();
            this.showMsg();

            // Foolproof
            /* istanbul ignore else */
            if (relatedView) {

                relatedView.render(
                    collection || this.model.attributes,
                    this.model.get("subtype") || this.model.get("name")
                );
                this.switchRelatedView(relatedView.$el);
            }
            return this.model.attributes;
        },
        /**
         * @name module:examsView#afterRender
         * @description Menu event bindings
         * @see module:defaultView#afterRender
         * @function
         */
        afterRender: function () {
            var MENU_LINK_SELECTOR = ".enw__menu__link";

            this.$el.on(
                "click",
                MENU_LINK_SELECTOR,
                $.proxy(this.onMenuClick, this)
            );
        },
        /**
         * @name module:examsView#getRelatedView
         * @description Gets related view by widget mode
         * @function
         */
        getRelatedView: function () {
            var mode = this.mode,
                SELECTOR,
                hash,
            // Related view constructor
                View;

            // true alias
            switch (!!mode) {
            case mode.subject === "avg" && mode.year === "yearSlice":
                hash = "avgChart";
                SELECTOR = ".avgChart";
                View = avgChartView;
                break;
            case mode.year === "yearSlice":
                hash = "subjectChart";
                SELECTOR = ".subjectChart";
                View = subjectChartView;
                break;
            case (typeof mode.year === "number") && mode.subject !== "avg":
                hash = "subjectYearChart";
                SELECTOR = ".subjectYearChart";
                View = subjectYearChartView;
                break;
            default:
                //case typeof mode.year === "number" && mode.subject === "avg":
                hash = "avgYearTable";
                SELECTOR = ".avgYearTable";
                View = avgYearView;
            }
            // Delayed chart initialization
            return this.initRelatedView(hash, View, SELECTOR);

        },
        /**
         * @name module:examsView#onMenuClick
         * @description Primary and secondary menu click handler.
         * Switches widget mode by click
         * @function
         */
        onMenuClick: function (e) {
            var $target = $(e.target),
                mode = $target.data("href");

            // "Throttling": suspends handler while previous data request is being proceed
            /* istanbul ignore else */
            if (this.status === 2) {
                // Part of switchMode logic
                // this.selectMenuItem($target);

                // Looks weird
                if ($target.parent().is(MENU_PRIMARY_CLASS)) {
                    this.switchMode(mode);
                } else {
                    this.switchMode(undefined, mode);
                }
            }
            return mode;
        },
        /**
         * @name module:examsView#switchMode
         * @description Updates model state by selected mode
         * @function
         * @param [subject] {String|Object} Subject or {subject:"subject", year: 2000}
         * @param [year] {String|Number} Year in xxxx format
         */
        switchMode: function (subject, year) {
            var mode = this.setMode(subject, year),
                model = this.model,
                url = model.host + "/" + model.path;

            /* istanbul ignore else */
            if (mode) {

                // Menu class switch
                this.selectMenuItem(mode.subject, this.$el.find(MENU_PRIMARY_CLASS));
                this.selectMenuItem(mode.year, this.$el.find(MENU_SECONDARY_CLASS));

                // NB: As far as we have no pre-initialized related views
                // DOM state may be switched in renderData callback only
                // So we just form the request and wait. DDP as is.

                // "avg" mode has empty subtype
                /* istanbul ignore else */
                if (mode.subject !== "avg") {
                    url += "/" + mode.subject;
                }
                /* istanbul ignore else */
                if (mode.year && mode.year !== "yearSlice") {
                    url += "/" + mode.year;
                }

                this.fetch(url);
            }
            return mode;
        }
    });
});