APIs

Show:
/**
 Base class for all StackView components. StackView allows for dynamic changes of elements (show/hide) and it works
 with the Backbone framework, thus allowing for view control.
 @class StackView.ViewPort
 @constructor
 @return none instead instantiate derived classes
 **/
define(['jquery', 'backbone', 'StackView'], function ($, Backbone, StackView) {

    var StackView = BB.StackView = {};
    StackView.ViewPort = BB.View.extend({

        /**
         Constructor
         @method initialize
         **/
        initialize: function () {
            this.m_views = {};
            this.m_selectedView = {};
        },

        /**
         Add a backbone view so we can control its display mode via one of the derived classes
         @method addView
         @param {Object} i_view add a backbone view to control
         @return {String} stack view id added
         **/
        addView: function (i_view) {
            i_view.$el.hide();
            if (i_view.el==undefined)
                log('')
            var oid = i_view.el.id === '' ? i_view.cid : i_view.el.id;
            this.m_views[oid] = i_view;
            return oid;
        },

        /**
         Get all registered views
         @method getViews
         @return {Object} registered views
         **/
        getViews: function () {
            return this.m_views;
        },

        /**
         Find a registered backbone view by its id or cid
         @method getViewByID
         @param {String} i_id
         @return {Object} view object retrieved
         **/
        getViewByID: function (i_id) {
            var oid = i_id.replace(/#/g, '');
            if (this.m_views[oid])
                return this.m_views[oid];
            var f = _.find(this.m_views, function (v) {
                if (v.cid == oid)
                    return v;
            });
            return f;
        },

        /**
         Select a view to present in the DOM, implementation varies per derived class
         @method selectView
         @param {Object} i_view
         **/
        selectView: function (i_view) {
            this.m_selectedView = this._parseView(i_view);
            this._notifySubscribers(i_view);
        },

        /**
         If view was given as an ID string, find its matching Backbone > View
         @method _parseView
         @param {Object} i_view
         **/
        _parseView: function(i_view){
            if (_.isString(i_view)){
                i_view = this.getViewByID(i_view);
            }
            return i_view;
        },

        _notifySubscribers: function(i_view){
            var view = this._parseView(i_view);
            // log('view: '+ view.el.id);
            this.trigger(BB.EVENTS.SELECTED_STACK_VIEW, view);
            if (BB.comBroker)
                BB.comBroker.fire(BB.EVENTS.SELECTED_STACK_VIEW, view);
        }

    });

    /**
     An animated backbone view slider that supports unlimited number of separated views.
     Be sure to check CSS file for additional configuration via classes:
     .page.left  .page.center .page.right .page.transition
     Animation can be configured for GPU hardware acceleration as well as in vertical and horizontal modes (all via CSS).
     @class StackView.Slider
     @constructor
     @return {Object} instantiated StackView.Slider
     **/
    StackView.Slider = StackView.ViewPort.extend({

        /**
         Class init
         @method constructor
         @param {Object} options backbone (config done through CSS)
         **/
        constructor: function (options) {
            this._views = [];
            this._index = null;
            StackView.ViewPort.prototype.constructor.apply(this, arguments);
        },

        /**
         Select the initial default view
         @method selectView
         @param {Object} i_view backbone view
         **/
        selectView: function (i_view) {
            var self = this;
            i_view = self._parseView(i_view);
            StackView.ViewPort.prototype.selectView.apply(this, arguments);
            $.each(self.m_views, function (id, view) {
                view.$el.hide();
            });
            i_view.$el.fadeIn(this.m_duration);
        },

        /**
         The main functions which allows the animated sliding of one view to the next
         @method slideToPage
         @param {Object} i_toView backbone view
         @param {Object} i_direction provide 'left' or 'right'
         **/
        slideToPage: function (i_toView, i_direction) {
            var self = this;
            i_toView = self._parseView(i_toView);
            if (i_toView==self.m_selectedView)
                return;
            self._notifySubscribers(i_toView);
            i_toView.$el.show();
            // toView.el.offsetWidth;
            // Position the new page at the starting position of the animation
            i_toView.el.className = "page " + i_direction;
            // Position the new page and the current page at the ending position of their
            // animation with a transition class indicating the duration of the animation
            // and force reflow of page so it renders
            i_toView.$el.parent().parent()[0].offsetWidth;
            i_toView.el.className = "page transition center";
            self.m_selectedView.el.className = "page transition " + (i_direction === "left" ? "right" : "left");
            self.m_selectedView = i_toView;
        }
    });

    /**
     Select a view thus fading it in and hiding all other views managed by this class
     @class StackView.Fader
     @constructor
     @return {Object} instantiated StackView.Fader
     **/
    StackView.Fader = StackView.ViewPort.extend({

        /**
         Class init
         @method constructor
         @param {Object} options duration, default 300ms
         **/
        constructor: function (options) {
            options || (options = {});
            this.m_duration = options.duration || 300;
            this.transition = options.transition;
            if (options.views) this.setViews(options.views);
            // if (options.duration) this.m_duration = options.duration;
            StackView.ViewPort.prototype.constructor.apply(this, arguments);
        },

        /**
         Bring the selected view into display while hiding siblings
         @method selectView
         @param {Object} i_view backbone view
         **/
        selectView: function (i_view) {
            var self = this;
            var bb_view = self._parseView(i_view);
            if (self.m_selectedView==bb_view)
                return;

            // stop previous animation on previosuly selected view
            if (self.m_selectedView.el)
                self.m_selectedView.$el.stop();

            StackView.ViewPort.prototype.selectView.apply(this, arguments);
            $.each(self.m_views, function (id, view) {
                view.$el.hide();
            });
            bb_view.$el.fadeIn(this.m_duration);
        },

        /**
         Select a stack view using an offset index
         @method selectIndex
         @param {Number} i_index offset
         **/
        selectIndex: function (i_index) {
            var self = this;
            var foundView = undefined;
            var i = -1;
            $.each(this.m_views, function (view_id) {
                i++;
                if (i == i_index)
                    foundView = self.m_views[view_id];
            });
            return foundView;
        }
    });

    /**
     Load a backbone view inside a full page modal window while maintaining persistency between modals.
     @class StackView.Modal
     @constructor
     @return {Object} instantiated StackView.Modal
     **/
    StackView.Modal = StackView.ViewPort.extend({

        /**
         Class init
         @method constructor
         @param {Object} options include (slide_top | fade), (bgColor)
         **/
        constructor: function (options) {
            this.m_animation = 'slide_top';
            this.m_bgColor = 'white';
            options || (options = {});
            this.transition = options.transition;
            if (options.views) this.setViews(options.views);
            if (options.animation) this.m_animation = options.animation;
            if (options.bgColor) this.m_bgColor = options.bgColor;
            StackView.ViewPort.prototype.constructor.apply(this, arguments);
        },

        /**
         Load up selected backbone view into a full screen modal and present it (persistent)
         @method selectView
         @param {Object} i_view backbone
         **/
        selectView: function (i_view) {
            var self = this;
            i_view = self._parseView(i_view);
            StackView.ViewPort.prototype.selectView.apply(this, arguments);
            $.each(self.m_views, function (id, view) {
                view.$el.hide()
            });
            i_view.$el.show();
            self.$el.append(i_view.el);
            $('.modal_close').one('click', function (e) {
                self.closeModal(self.el);
                e.preventDefault();
            });

            var bh = $('body').get(0).scrollHeight + 'px';
            var bw = $('body').get(0).scrollWidth + 'px';
            self.$el.css({
                'display': 'block',
                'opacity': self.m_animation == 'fade' ? 0 : 1,
                'position': 'absolute',
                'z-index': 9999,
                'height': bh,
                'width': bw,
                'left': 0,
                'border-bottom': '3px solid gray',
                'background-color': self.m_bgColor,
                'top': self.m_animation == 'fade' ? 0 : '-' + bh,
                margin: 0
                // 'left': 50 + '%',
                // 'margin-left': -(modal_width / 2) + "px",
                // 'top': o.top + "px"
            });
            self.$el.animate({
                top: 0,
                opacity: 1}, 400);
        },

        /**
         Close via animation the currently opened modal window
         @method closelModal
         @param {String} modal_id
         **/
        closeModal: function (modal_id) {
            var self = this;
            $(modal_id).animate({
                    top: self.m_animation == 'fade' ? 0 : 0 - $('body').get(0).scrollHeight,
                    opacity: 0},
                400, function () {
                    $(this).css({display: 'none'})
                });
        }
    });

    return StackView;

});