APIs

Show:
/**
 The class generates the UI for a template (a.k.a Screen Division) that is
 a selectable widget including the drawing of each viewer (division) within
 the screen, as well as firing related click events on action.
 @class ScreenTemplateFactory
 @constructor
 @param {object} i_screenTemplateData hold data as instructions for factory creation component
 @param {String} i_type the type of widget that we will create. This includes
 VIEWER_SELECTABLE as well as ENTIRE_SELECTABLE with respect to the ability to select the components viewers individually
 or the entire screen division
 @param {object} i_owner the owner of this class (parent) that we can query at the listening end, to examine if the event is
 of any interest to the listener.
 **/
define(['jquery', 'backbone'], function ($, Backbone) {

    /**
     This is a key event in the framework as many different instances subscribe to ON_VIEWER_SELECTED to reconfigure
     themselves. The event is fired when a viewer (i.e.: a screen division) is selected inside a Template (i.e. Screen).
     The key to remember is that the Factory instance (this) is always created with respect to it's owner (i_owner),
     so when ON_VIEWER_SELECTED is fired, the owner is carried with the event so listeners can act accordingly, and only if the owner
     is of interest to a subscribed listener.
     @event ON_VIEWER_SELECTED
     @param {this} caller
     @param {object} screenData event params
     @static
     @final
     @param {screenData} json encapsulated data of entire configuration of instance
     **/
    BB.EVENTS.ON_VIEWER_SELECTED = 'ON_VIEWER_SELECTED';

    var ScreenTemplateFactory = BB.Controller.extend({

        /**
         Constructor
         @method initialize
         **/
        initialize: function () {
            var self = this;
            this.m_owner = self.options.i_owner;
            this.m_myElementID = 'svgScreenLayout' + '_' + _.uniqueId();
            this.m_screenTemplateData = self.options.i_screenTemplateData;
            this.m_selfDestruct = self.options.i_selfDestruct;
            this.m_orientation = self.options.i_screenTemplateData['orientation'];
            this.m_resolution = self.options.i_screenTemplateData['resolution'];
            this.m_screenProps = self.options.i_screenTemplateData['screenProps'];
            this.m_scale = self.options.i_screenTemplateData['scale'];
            this.m_svgWidth = (this.m_resolution.split('x')[0]) / this.m_scale;
            this.m_svgHeight = (this.m_resolution.split('x')[1]) / this.m_scale;
            this.m_useLabels = false;
        },

        /**
         Get current selection color depnding on theme of light / daek
         @method _getColor
         @params {String} color
        _getColor: function(){
            if (BB.CONSTS['THEME']=='light')
                return '#428ac9 ';
            return '#eb7c66';
        },
         **/

        /**
         Method is called when an entire screen frame of the UI is clicked, in contrast to when a single viewer is selected.
         The difference in dispatch of the event depends on how the factory created this instance.
         @method _onViewSelected
         @param {Event} e
         @param {Object} i_caller
         @return {Boolean} false
         **/
        _onViewSelected: function (e, i_caller) {
            var self = i_caller;
            var element = e.target;

            var campaign_timeline_board_viewer_id = $(element).data('campaign_timeline_board_viewer_id');
            var campaign_timeline_id = $(element).data('campaign_timeline_id');

            var screenData = {
                sd: $(element).data('sd'),
                elementID: i_caller.m_myElementID,
                owner: i_caller.getOwner(),
                campaign_timeline_board_viewer_id: campaign_timeline_board_viewer_id,
                campaign_timeline_id: campaign_timeline_id,
                screenTemplateData: self.m_screenTemplateData
            };
            self._deselectViewers();
            BB.comBroker.fire(BB.EVENTS.ON_VIEWER_SELECTED, this, screenData);
        },

        /**
         Deselect all viewers, thus change their colors back to default.
         @method _deselectViewers
         @return none
         **/
        _deselectViewers: function () {
            var self = this;
            $(Elements.CLASS_SCREEN_DIVISION).each(function () {
                if ($(this).is('rect')) {
                    $(this).css({'fill': 'rgb(230,230,230)'});
                }
            });
        },

        /**
         When enabled, _mouseOverEffect will highlight viewers when mouse is hovered over them.
         @method _mouseOverEffect
         @return none
         **/
        _mouseOverEffect: function () {
            var self = this;
            var a = $('#' + self.m_myElementID);
            var b = $('#' + self.m_myElementID).find('rect');
            $('#' + self.m_myElementID).find('rect').each(function () {
                $(this).on('mouseover', function () {
                    $(this).css({'fill': 'rgb(190,190,190)'});
                }).mouseout(function () {
                    $(this).css({'fill': 'rgb(230,230,230)'});
                });
            });
        },

        /**
         Get the owner (parent) of this instance, i.e., the one who created this.
         We use the owner attribute as a way to distinguish what type of instance this was created as.
         @method getOwner
         @return {Object} m_owner
         **/
        getOwner: function () {
            var self = this;
            return self.m_owner;
        },

        /**
         Create all the screen divisions (aka viewers) as svg snippets and push them into an array
         @method getDivisions
         @return {array} f array of all svg divisions
         **/
        getDivisions: function () {
            var self = this;
            var svg = self.create();
            return $(svg).find('rect');

            var f = $(svg).find('rect').map(function (k, v) {
                return '<svg style="padding: 0px; margin: 15px" width="20px" height="20px" xmlns="http://www.w3.org/2000/svg">  ' +
                    '<g>' +
                    v.outerHTML +
                    '</g> ' +
                    '</svg>';
            });
            return f;
        },

        /**
         Create will produce the actual SVG based Template (screen) with inner viewers and return HTML snippet to the caller.
         @method create
         @return {Object} html element produced by this factory
         **/
        create: function () {
            var self = this;
            var screensDivisons = '';
            var screenLabels = '';

            // sort for proper z-order creating the viewers
            var orderedScreenValues = [], i = 0;
            for (var screenValues in self.m_screenProps) {
                var viewOrder = self.m_screenProps[screenValues]['view_order'];
                viewOrder = _.isUndefined(viewOrder) ? i : viewOrder;
                orderedScreenValues[viewOrder] = self.m_screenProps[screenValues];
                i++;
            }

            // create the viewers
            i = 0;
            for (var ordered in orderedScreenValues) {
                i++;
                var screenValue = orderedScreenValues[ordered];
                var x = screenValue['x'] == 0 ? 0 : screenValue['x'] / self.m_scale;
                var y = screenValue['y'] == 0 ? 0 : screenValue['y'] / self.m_scale;
                var w = screenValue['w'] == 0 ? 0 : screenValue['w'] / self.m_scale;
                var h = screenValue['h'] == 0 ? 0 : screenValue['h'] / self.m_scale;
                var campaign_timeline_board_viewer_id = screenValue['campaign_timeline_board_viewer_id'];
                var campaign_timeline_id = screenValue['campaign_timeline_id'];
                var sd = screenValues;

                var uniqueID = 'rectSD' + '_' + _.uniqueId();
                if (self.m_useLabels == true)
                    screenLabels += '<text class="screenDivisionClass"' + '" data-for="' + uniqueID + '" x="' + (x + (w / 2)) + '" y="' + (y + (h / 2)) + '" font-family="sans-serif" font-size="12px" text-anchor="middle" alignment-baseline="middle" fill="#666">' + i + '</text>';

                screensDivisons += '<rect id="' + uniqueID +
                    '" data-campaign_timeline_board_viewer_id="' + campaign_timeline_board_viewer_id +
                    '" data-campaign_timeline_id="' + campaign_timeline_id +
                    '" x="' + x +
                    '" y="' + y +
                    '" width="' + w +
                    '" height="' + h +
                    '" data-sd="' + sd +
                    '" class="screenDivisionClass"' +
                    '  style="fill:rgb(230,230,230);stroke-width:2;stroke:rgb(72,72,72)"/>';
            }
            return ($('<svg class="svgSD" id="' + self.m_myElementID + '" width="' + self.m_svgWidth + '" height="' + self.m_svgHeight + '" xmlns="http://www.w3.org/2000/svg">  ' +
                '<g>' +
                screensDivisons +
                screenLabels +
                '</g> ' +
                '</svg>'));
        },

        /**
         When enabled, selectableFrame will allow for UI mouse / click of the outer frame of the template (screen) and not
         individual viewers.
         @method selectableFrame
         @return none
         **/
        selectableFrame: function () {
            var self = this;
            var applyToSelected = function (e) {
                $('#' + self.m_myElementID).parent().parent().parent().find('rect').css({'stroke-width': '2', 'stroke': 'rgb(72,72,72)'});
                $('#' + self.m_myElementID).find('rect').css({'stroke-width': '2', 'stroke': BB.lib.getThemeColor()});
                self._onViewSelected(e, self);
            }
            // listen one
            if (self.m_selfDestruct) {
                $(Elements.CLASS_SCREEN_DIVISION, '#' + self.m_myElementID).one('mouseup contextmenu', function (e) {
                    applyToSelected(e);
                });

            } else {
                // listen on
                $(Elements.CLASS_SCREEN_DIVISION, '#' + self.m_myElementID).on('mouseup contextmenu', function (e) {
                    applyToSelected(e);
                });
            }
        },

        /**
         The public method version of _deselectViewers, which de-selects all viewers
         @method deselectDivisons
         **/
        deselectDivisons: function () {
            var self = this;
            self._deselectViewers();
        },

        /**
         Select a division (aka viewer) using it's viewer_id, only applicable when class represents an actual timelime > board > viewer_id
         @method selectDivison
         @param {Number} i_campaign_timeline_board_viewer_id
         **/
        selectDivison: function (i_campaign_timeline_board_viewer_id) {
            var self = this;
            self._deselectViewers();
            var selectedElement = $('#' + self.m_myElementID).find('[data-campaign_timeline_board_viewer_id="' + i_campaign_timeline_board_viewer_id + '"]');
            $(selectedElement).css({'fill': BB.lib.getThemeColor()});
        },

        /**
         Release all members to allow for garbage collection.
         @method destroy
         @return none
         **/
        destroy: function () {
            var self = this;
            $(Elements.CLASS_SCREEN_DIVISION).off('click contextmenu', function (e) {
                self._onViewSelected(e, self);
            });
            $(this).off('mouseover', function () {
                $(this).css({'fill': 'rgb(190,190,190)'});
            }).mouseout(function () {
                $(this).css({'fill': 'rgb(230,230,230)'});
            });
            $.each(self, function (k) {
                self[k] = undefined;
            });
        }
    });

    return ScreenTemplateFactory;

});