component-search-facet-summary.js


/**
 * Facet summary component functionality
 * @module facetSummary
 * @param  {jQuery} $ Instance of jQuery
 * @param  {Document} document dom document object
 * @return {Object} list of methods for working with component facet summary
*/
XA.component.search.facet.summary = (function ($, document) {
    /**
    * This object stores all public api methods
    * @type {Object.<Methods>}
    * @memberOf module:facetSummary
    */
    var api = {},
        urlHelperModel = XA.component.search.url,
        queryModel = XA.component.search.query,
        apiModel = XA.component.search.ajax,
        initialized = false,
        facetName = "summary";

    /**
    * @name module:facetSummary.FacetSummaryModel
    * @constructor
    * @augments Backbone.Model
    */
    var FacetSummaryModel = Backbone.Model.extend(
        /** @lends module:facetSummary.FacetSummaryModel.prototype **/

        {
            /**
            * Default model options
            * @default
            * @param {Object} properties properties of ajax call and callback
            */
            defaults: {
                dataProperties: {},
                sig: [],
                hash: ''
            },
            /**
           * Listens to changes on facets and hash
            * @listens module:XA.component.search.vent~event:facet-data-loaded
            * @listens module:XA.component.search.vent~event:facet-data-filtered
            * @listens module:XA.component.search.vent~event:facet-data-partial-filtered
            * @listens module:XA.component.search.vent~event:hashChanged
            */
            initialize: function () {
                var that = this;
                this.set('resultData', {})
                //Event to get data at the begining or in case that there are no hash parameters in the url - one request for all controls
                XA.component.search.vent.on("facet-data-loaded", that.processData.bind(that));
                // //If the url hash contains this control facet name (someone clicked this control), then we have to listen for partial filtering
                XA.component.search.vent.on("facet-data-partial-filtered", that.processData.bind(that));
                // //When we are not filtering by this control (not clicked)
                XA.component.search.vent.on("facet-data-filtered", that.processData.bind(that));

            },
            /**
             * Finds all facets that have same name as facetName in Control Data and return them
             * @param {Object} facetData 
             * @param {*} controlData 
             * @returns {Array} Filtered facet data
             * @memberof module:facetSummary.FacetSummaryModel
             * @alias module:facetSummary.FacetSummaryModel.requestFacetData
             */
            requestFacetData: function (facetData, controlData) {
                return _.find(facetData, function (f) {
                    return f.Key.toLowerCase() === controlData.facetName.toLowerCase();
                });
            },
            /**
			 * Concatenates signature and facet name in order to build proper hash parameter name
			 * @param {*} rawSignature 
			 * @param {*} f 
			 */
            translateSignatures: function (rawSignature, f) {
                var signatures, i;

                f = f.toLowerCase();

                if (typeof rawSignature === "undefined" || rawSignature === null) {
                    return [f];
                }

                signatures = rawSignature.split(',');

                if (rawSignature === "") {
                    return [f];
                } else {
                    for (i = 0; i < signatures.length; i++) {
                        signatures[i] = signatures[i] + "_" + f;
                    }
                    return signatures;
                }
            },
            /**
            * Processes data that comes as parameter. Update
            * model and store all facets that are active and have
            * same signature
            * @param {Object} data Data from server with facet values
            * @memberof module:facetSummary.FacetSummaryModel
            * @alias module:facetSummary.FacetSummaryModel.processData
            */
            processData: function (data) {
                var hashObj = queryModel.parseHashParameters(window.location.hash),
                    requestFacedData,
                    that = this,
                    displayName,
                    facetData = [], requestData = {}, facetControl, control;
                var facets = XA.component.search.facet;

                for (facetControl in facets) {
                    control = XA.component.search.facet[facetControl];
                    if (typeof (control.getFacetDataRequestInfo) === "function") {
                        facetData = control.getFacetDataRequestInfo();
                        for (var facetIndex = 0; facetIndex < facetData.length; facetIndex++) {
                            var controlData = facetData[facetIndex];
                            var signaturesArray = controlData.signature.split(',');
                            for (var signatureIndex = 0; signatureIndex < signaturesArray.length; signatureIndex++) {
                                var signature = signaturesArray[signatureIndex];
                                if (data.Signature == signature && that.get('sig') == signature) {
                                    requestFacedData = that.requestFacetData(data.Facets, controlData);
                                    if (typeof requestFacedData !== "undefined") {
                                        displayName = requestFacedData.Name;
                                        var currResults = this.get('resultData');
                                        var facetHashNames = that.translateSignatures(signature, requestFacedData.Key.toLowerCase())
                                        for (var facetHashNameIndex = 0; facetHashNameIndex < facetHashNames.length; facetHashNameIndex++) {
                                            var facetHashName = facetHashNames[facetHashNameIndex];
                                            if (hashObj[facetHashName]) {
                                                currResults[displayName] = {
                                                    "value": hashObj[facetHashName],
                                                    "key": requestFacedData.Key,
                                                    "signature": data.Signature,
                                                    "facetHashName": facetHashName
                                                }
                                            } else {
                                                delete currResults[displayName];
                                            }
                                        }
                                        this.set('resultData', currResults);
                                        this.trigger('change', this)

                                    }
                                }
                            }

                        }
                    }
                }
            }
        });
    /**
    * @name module:facetSummary.FacetSummaryView
    * @constructor
    * @augments Backbone.View
    */
    var FacetSummaryView = XA.component.search.baseView.extend(
        /** @lends module:facetSummary.FacetSummaryView.prototype **/

        {
            tagName: "div",
            className: "facet-search-summary",
            template:
                "<% if(Object.keys(resultData).length){ %> <div class='facet-summary-wrapper clearfix'>" +
                "<% _.forEach(resultData, function(obj,key){ %>" +
                "<div class='active-facet-summary-element' data-hash='" + "<%=obj.facetHashName%>" + "' data-key='" + "<%=obj.key%>" + "' data-signature='" + "<%=obj.signature%>" + "'>" +
                "<%= key  %> " + "<span><%= obj.value  %></span>" +
                "<div class='removeFacet'>x</div>" +
                "</div>" +
                "<% }); %>" +
                "</div><% }%>",
            /**
            * Initially sets data to model and watches events on which
            * view should be updated
            * @listens module:facetSummary.FacetSummaryView~event:change
            * @memberof module:facetSummary.FacetSummaryView
            * @alias module:facetSummary.FacetSummaryView#initialize
            */
            clearButtons: function (event) {
                var $target = $(event.currentTarget),
                    $facetSummary = $target.closest(".facet-summary");
                $facetSummary.find('.clear-all-active-facets').trigger('click');

            },
            /**
            * Initializes the view by assigning events to the buttons and rendering component
            * @memberof module:facetSummary.FacetSummaryView
            * @alias module:facetSummary.FacetSummaryView#events
            */
            initialize: function () {
                var dataProperties = this.$el.data(),
                    that = this,
                    properties = dataProperties.properties,
                    signatures;
                Backbone.$('.facet-summary .clear-filter').on('click', function (event) {
                    that.clearButtons(event)

                })
                Backbone.$('.facet-summary .bottom-remove-filter').on('click', function (event) {
                    that.clearButtons(event)

                })
                signatures = this.translateSignatures(properties.searchResultsSignature, facetName);
                this.model.set("sig", properties.searchResultsSignature);
                dataProperties = this.$el.data("properties"),
                    this.model.on("change", this.render, this);
                this.render();
            },
            /**
             * list of events for Backbone View
            * @memberof module:facetSummary.FacetSummaryView
            * @alias module:facetSummary.FacetSummaryView#events
             */
            events: {
                'click .removeFacet': 'removeFacet',
                'click .clear-filter': 'clearAllActiveFacets',
                'click .bottom-remove-filter button': 'clearAllActiveFacets'
            },
            /**
             * Clears all active facets that are stored under summary component 
            * @memberof module:facetSummary.FacetSummaryView
            * @alias module:facetSummary.FacetSummaryView#clearAllActiveFacets
            */
            clearAllActiveFacets: function () {
                this.$el.find('.removeFacet').trigger('click');
            },
            /**
            * Prepares hash string based on hash object
            * @param {Object} hashObj Object created from hash parameters
            * @memberof module:facetSummary.FacetSummaryView
            * @alias module:facetSummary.FacetSummaryView#createHash
            * @returns {String} hash as a string
            */
            createHash: function (hashObj) {
                var result = "#";
                for (option in hashObj) {
                    result += option + "=" + hashObj[option] + "&";
                }
                return result;

            },
            /**
            * Removes selected facet and updates hash
            * @param {Event} event Event object where stored clicked element
            * @memberof module:facetSummary.FacetSummaryView
            * @alias module:facetSummary.FacetSummaryView#removeFacet
            */
            removeFacet: function (event) {
                var element = $(event.currentTarget).closest(".active-facet-summary-element"),
                    keyForRemoving = element.data('key'),
                    signature = element.data('signature'),
                    hashObj = queryModel.parseHashParameters(window.location.hash);
                facetHashNames = this.translateSignatures(signature, keyForRemoving)
                _.each(facetHashNames, function (facetHashName) {
                    delete hashObj[facetHashName];
                })

                window.location.hash = this.createHash(hashObj);
            },
            /**
            * Renders view
            * @memberof module:facetSummary.FacetSummaryView
            * @alias module:facetSummary.FacetSummaryView#render
            */
            render: function () {
                var inst = this,
                    resultData = this.model.get("resultData"),
                    template, templateResult;
                var dataProperties = this.$el.data();
                this.properties = dataProperties.properties;
                this.manageVisibilityByData(this.$el, resultData)
                if (this.model) {
                    this.model.set({ dataProperties: this.properties });
                    this.model.set("sig", this.properties.searchResultsSignature);
                }
                //checks whether page is opened from disc - if yes then we are in Creative Exchange mode
                if (window.location.href.startsWith("file://")) {
                    return;
                }

                if (resultData !== undefined) {
                    template = _.template(this.template);

                    templateResult = template({
                        "resultData": resultData
                    });
                }

                inst.$el.find(".facet-summary-placeholder").html(templateResult);
            }

        });
    /**
    * For each search dropdown component on a page creates instance of 
    * ["FacetSummaryModel"]{@link module:facetSummary.FacetSummaryModel} and 
    * ["FacetSummaryView"]{@link module:facetSummary.FacetSummaryView} 
    * @memberOf module:facetSummary
    * @alias module:facetSummary.init
    */
    api.init = function () {
        if ($("body").hasClass("on-page-editor") || initialized) {
            return;
        }

        queryModel = XA.component.search.query;
        apiModel = XA.component.search.ajax;
        urlHelperModel = XA.component.search.url;

        var facetSummary = $(".facet-summary");
        _.each(facetSummary, function (elem) {
            var model = new FacetSummaryModel(),
                view = new FacetSummaryView({ el: $(elem), model: model });
        });

        initialized = true;
    };

    return api;

}(jQuery, document));

XA.register('facetSummary', XA.component.search.facet.summary);