component-search-facet-range-slider.js

/**
 * Range Slider component functionality
 * @module searchFacetRangeSlider
 * @param  {jQuery} $ Instance of jQuery
 * @param  {Document} document dom document object
 * @return {Object} list of methods for working with range slider
*/
XA.component.search.facet.rangeslider = (function ($, document) {
    /**
    * This object stores all public api methods
    * @type {Object.<Methods>}
    * @memberOf module:searchFacetRangeSlider
    */
    var api = {},
        urlHelperModel,
        queryModel,
        initialized = false;

    /**
    * @name module:searchFacetRangeSlider.SearchFacetRangeSliderModel
    * @constructor
    * @augments Backbone.Model
    */
    var SearchFacetRangeSliderModel = Backbone.Model.extend(
        /** @lends module:searchFacetRangeSlider.SearchFacetRangeSliderModel.prototype **/
        {
            /**
           * Default model options
           * @default
           */
            defaults: {
                dataProperties: {},
                sig: [],
                timeStamp: ''
            }
        });
    /**
    * @name module:searchFacetRangeSlider.SearchFacetRangeSliderView
    * @constructor
    * @augments Backbone.View
    */
    var SearchFacetRangeSliderView = XA.component.search.baseView.extend(
        /** @lends module:searchFacetRangeSlider.SearchFacetRangeSliderView.prototype **/
        {
            /**
            * Initially sets data to model and watches events on which
            * view should be updated
            * @listens module:searchFacetRangeSlider.SearchFacetRangeSliderView~event:change
            * @listens module:XA.component.search.vent~event:hashChanged
            * @memberof module:searchFacetRangeSlider.SearchFacetRangeSliderView
            */
            initialize: function () {
                var dataProperties = this.$el.data();
                this.properties = dataProperties.properties;

                if (this.model) {
                    this.model.set({ dataProperties: this.properties });
                    this.model.set("sig", this.translateSignatures(this.properties.searchResultsSignature, this.properties.f));
                }
                this.model.on("change", this.updateSelectedValue, this);

                XA.component.search.vent.on("hashChanged", this.updateModel.bind(this));

                this.render();
            },
            /**
            * list of events for Backbone View
            * @memberof module:searchFacetRangeSlider.SearchFacetRangeSliderView
            * @alias module:searchFacetRangeSlider.SearchFacetRangeSliderView#events
            */
            events: {
                'click .bottom-remove-filter, .clear-filter': 'removeFacet',
                'mouseup .ui-slider-handle': 'updateModel'
            },
            /**
             * Renders view. Use jQueryUI slider with set up from searchFacetRangeSlider
             * properties
             * @memberof module:searchFacetRangeSlider.SearchFacetRangeSliderView
             * @alias module:searchFacetRangeSlider.SearchFacetRangeSliderView#render
             */
            render: function () {
                var self = this,
                    sig = this.model.get('sig'),
                    queryModel = XA.component.search.query,
                    hashObj = queryModel.parseHashParameters(window.location.hash),
                    minRangeValue = parseFloat(this.model.get('dataProperties').minRangeValue),
                    maxRangeValue = parseFloat(this.model.get('dataProperties').maxRangeValue),
                    changeStep = parseFloat(this.model.get('dataProperties').changeStep),
                    $sliderValue = $('<div />').addClass('slider-value'),
                    facetClose = this.$el.find('.facet-heading > span'),
                    $slider = this.$el.find('.slider'),
                    selectedMinValue,
                    selectedMaxValue,
                    i;

                for (i = 0; i < sig.length; i++) {
                    if (!jQuery.isEmptyObject(_.pick(hashObj, sig[i]))) {
                        var values = _.values(_.pick(hashObj, sig[i]))[0];
                        if (values) {
                            selectedMinValue = values.split("|")[0];
                            selectedMaxValue = values.split("|")[1];
                            //Adds active class to group close button
                            facetClose.addClass('has-active-facet');
                        }
                    } else {
                        selectedMinValue = parseFloat(this.model.get('dataProperties').selectedMinValue);
                        selectedMaxValue = parseFloat(this.model.get('dataProperties').selectedMaxValue);
                        facetClose.removeClass('has-active-facet');
                    }
                }

                if (isNaN(minRangeValue)) {
                    minRangeValue = 0;
                }
                if (isNaN(maxRangeValue)) {
                    maxRangeValue = 0;
                }
                if (isNaN(changeStep) || changeStep === 0) {
                    changeStep = 1;
                }
                if (isNaN(selectedMinValue)) {
                    selectedMinValue = 0;
                }
                if (isNaN(selectedMaxValue)) {
                    selectedMaxValue = 0;
                }

                $slider.slider({
                    range: true,
                    min: minRangeValue,
                    max: maxRangeValue,
                    step: changeStep,
                    values: [selectedMinValue, selectedMaxValue],
                    create: function (event, ui) {
                        $(".slider-value").remove();
                        $slider.after($sliderValue);
                        if (selectedMinValue !== 0 || selectedMaxValue !== 0) {
                            self.updateText(selectedMinValue, selectedMaxValue);
                        }
                    },
                    slide: function (event, ui) {
                        self.updateModel(self.updateSignaturesHash(sig, ui.values[0] + "|" + ui.values[1], {}));
                    }
                });

            },
            /**
             * Sets default values for Range Slider and updates hash according to them
             * @memberof module:searchFacetRangeSlider.SearchFacetRangeSliderView
             * @alias module:searchFacetRangeSlider.SearchFacetRangeSliderView#removeFacet
             */
            removeFacet: function () {
                var facet = this.$el,
                    sig = this.model.get('sig'),
                    $slider = this.$el.find('.slider'),
                    $facetClose = facet.find('.facet-heading > span'),
                    properties = this.model.get('dataProperties'),
                    hash = queryModel.parseHashParameters(window.location.hash);

                $facetClose.removeClass('has-active-facet');

                properties.selectedMinValue = properties.minRangeValue;
                properties.selectedMaxValue = properties.maxRangeValue;

                //Updates slider text to default min and max range values
                this.updateText(properties.minRangeValue, properties.maxRangeValue);

                //Sets slider valued to default min and max range values
                $slider.slider("values", [properties.minRangeValue, properties.maxRangeValue]);

                this.model.set({ dataProperties: properties });

                if (hash.hasOwnProperty(this.model.get('sig'))) {
                    queryModel.updateHash(this.updateSignaturesHash(sig, "", hash));
                }
            },
            /**
             * Updates model based on hash parameters
             * @param {Object} hash Object that contains hash parameters
             * @memberof module:searchFacetRangeSlider.SearchFacetRangeSliderView
             * @alias module:searchFacetRangeSlider.SearchFacetRangeSliderView#updateModel
             */
            updateModel: function (hash) {
                var sig = this.model.get('sig'),
                    facetPart,
                    dataProperties,
                    values,
                    selectedMinValue,
                    selectedMaxValue,
                    i;

                if (!hash) {
                    hash = queryModel.parseHashParameters(window.location.hash);
                }

                for (i = 0; i < sig.length; i++) {
                    facetPart = sig[i].toLocaleString();
                    if (hash.hasOwnProperty(facetPart)) {
                        values = _.values(_.pick(hash, facetPart))[0];
                        if (values !== '') {
                            selectedMinValue = values.split("|")[0];
                            selectedMaxValue = values.split("|")[1];

                            if (typeof selectedMaxValue === "undefined" ||
                                typeof selectedMinValue === "undefined") {
                                continue;
                            }

                            dataProperties = this.model.get('dataProperties');
                            dataProperties.selectedMinValue = selectedMinValue;
                            dataProperties.selectedMaxValue = selectedMaxValue;
                            this.model.set('dataProperties', dataProperties);
                            this.model.set("timeStamp", (new Date()).getTime());
                        } else {
                            this.removeFacet();
                        }
                    }
                }
            },
            /**
             * Updates selected text values
             * @memberof module:searchFacetRangeSlider.SearchFacetRangeSliderView
             * @alias module:searchFacetRangeSlider.SearchFacetRangeSliderView#updateSelectedValue
             */
            updateSelectedValue: function () {
                var dataProperties = this.model.get('dataProperties'),
                    facetMinValue = dataProperties.selectedMinValue,
                    facetMaxValue = dataProperties.selectedMaxValue,
                    $slider = this.$el.find('.slider'),
                    sig = this.model.get('sig');

                $slider.slider("values", [facetMinValue, facetMaxValue]);
                this.updateText(facetMinValue, facetMaxValue);
                this.$el.find('.facet-heading > span').addClass('has-active-facet');

                queryModel.updateHash(this.updateSignaturesHash(sig, facetMinValue + "|" + facetMaxValue, {}));
            },
            /**
             * Updates slider text values text
             * @param {String} facetMinValue Minimal value of facet
             * @param {String} facetMaxValue Maximal value of facet
             * @memberof module:searchFacetRangeSlider.SearchFacetRangeSliderView
             * @alias module:searchFacetRangeSlider.SearchFacetRangeSliderView#updateSelectedValue
             */
            updateText: function (facetMinValue, facetMaxValue) {
                var $sliderValueField = this.$el.find('.slider-value'),
                    sliderText = this.model.get('dataProperties').formatingString;

                sliderText = sliderText.replace('{from}', facetMinValue).replace('{to}', facetMaxValue);
                $sliderValueField.html(sliderText);
            }
        });
    /**
    * For each search facet range slider component on a page creates instance of 
    * ["SearchFacetRangeSliderModel"]{@link module:searchFacetRangeSlider.SearchFacetRangeSliderModel} and 
    * ["SearchFacetRangeSliderView"]{@link module:searchFacetRangeSlider.SearchFacetRangeSliderView} 
    * @memberOf module:searchFacetRangeSlider
    * @alias module:searchFacetRangeSlider.init
    */
    api.init = function () {
        queryModel = XA.component.search.query;
        urlHelperModel = XA.component.search.url;

        var searchFacetRangeSlider = $(".facet-range-selector");
        _.each(searchFacetRangeSlider, function (elem) {
            var searchFacetRangeSliderModel = new SearchFacetRangeSliderModel(),
                searchFacetRangeSliderView = new SearchFacetRangeSliderView({ el: $(elem), model: searchFacetRangeSliderModel });
        });

        initialized = true;
    };

    return api;

}(jQuery, document));

XA.register('searchFacetRangeSlider', XA.component.search.facet.rangeslider);