PageSourceSearch

https://www.xanax.com/-/media/Base-Themes/SearchTheme/Scripts/component-search-facet-managed-range.js

js xanax.com collected 2026-09-24 22:54:50 UTC 17,032 bytes, 370 lines download raw bytes

1/**
2 * Managed Range Facet component functionality
3 * @module managedrange
4 * @param  {jQuery} $ Instance of jQuery
5 * @param  {Document} document dom document object
6 * @return {Object} list of methods for working with managed range component
7*/
8XA.component.search.facet.managedrange = (function ($, document) {
9    /**
10    * This object stores all public api methods
11    * @type {Object.<Methods>}
12    * @memberOf module:managedrange
13    */
14    var api = {},
15        urlHelperModel,
16        queryModel,
17        apiModel,
18        initialized = false;
19    /**
20     * @name module:managedrange.FacetManagedRangeModel
21     * @constructor
22     * @augments Backbone.Model
23     */
24    var FacetManagedRangeModel = Backbone.Model.extend(
25        /** @lends module:managedrange.FacetManagedRangeModel.prototype **/
26
27        {
28            /**
29            * Default model options
30            * @default
31            */
32            defaults: {
33                dataProperties: {},
34                sig: []
35            }
36        });
37    /**
38    * @name module:managedrange.FacetManagedRangeView
39    * @constructor
40    * @augments Backbone.View
41    */
42    var FacetManagedRangeView = XA.component.search.baseView.extend(
43        /** @lends module:managedrange.FacetManagedRangeView.prototype **/
44
45        {
46            /**
47            * Initially sets data to model and watches events on which
48            * view should be updated
49            * @listens module:managedrange.FacetManagedRangeView~event:change
50            * @listens module:XA.component.search.vent~event:hashChanged
51            * @memberof module:managedrange.FacetManagedRangeView
52            */
53            initialize: function () {
54                this.properties = this.$el.data().properties;
55
56                if (this.model) {
57                    this.model.set({ dataProperties: this.properties });
58                    this.model.set("sig", this.translateSignatures(this.properties.searchResultsSignature, this.properties.f));
59                }
60
61                if (this.$el.find(".filterButton").length === 0) {
62                    //If there is no filter button, we still have to have the possibility to use manual ranges
63                    this.$el.find('.manualRangeMin').on('blur', this.textBoxChange.bind(this, []));
64                    this.$el.find('.manualRangeMax').on('blur', this.textBoxChange.bind(this, []));
65                }
66                this.model.on("change", this.render, this);
67
68                XA.component.search.vent.on("hashChanged", this.updateComponent.bind(this));
69            },
70            /**
71           * list of events for Backbone View
72           * @memberof module:managedrange.FacetManagedRangeView
73           * @alias module:managedrange.FacetManagedRangeView#events
74           */
75            events: {
76                'click .faceLink': 'linkClick',
77                'click .facetRadio': 'radioClick',
78                'click .facetCheckbox': 'checkBoxClick',
79                'click .filterButton': 'filter',
80                'click .bottom-remove-filter, .clear-filter': 'clearFilter',
81                'keyup .manualRangeMin, .manualRangeMax': 'configureKeyCodes'
82            },
83            /**
84             * On enter click calls 
85             * ["filter"]{@link module:managedrange.FacetManagedRangeView.filter} method
86             * @param {Event} e Event object
87             * @memberof module:managedrange.FacetManagedRangeView
88             * @alias module:managedrange.FacetManagedRangeView#configureKeyCodes
89             */
90            configureKeyCodes: function (e) {
91                if (e.keyCode == 13) {
92                    this.filter();
93                }
94            },
95            /**
96            * Helper function that will take all ranges selected on a page and 
97            * update hash parameters according to this value
98            * @param {Array<DomElement>} foundRangeControls List of range controls on a page
99            * @memberof module:managedrange.FacetManagedRangeView
100            * @alias module:managedrange.FacetManagedRangeView#updateHash
101            */
102            updateHash: function (foundRangeControls) {
103                var sig = this.model.get('sig'),
104                    ranges = [];
105
106                _.each(foundRangeControls, function (range) {
107                    var $range = $(range);
108                    ranges.push($range.data().minvalue + "|" + $range.data().maxvalue);
109                });
110
111                this.$el.find('.manualRangeMin').val('');
112                this.$el.find('.manualRangeMax').val('');
113
114                queryModel.updateHash(this.updateSignaturesHash(sig, ranges.join(','), {}));
115            },
116            /**
117             * Render view
118             * @memberof module:managedrange.FacetManagedRangeView
119             * @alias module:managedrange.FacetManagedRangeView#render
120             */
121            render: function () {
122                var hashObj = queryModel.parseHashParameters(window.location.hash),
123                    facetClose = this.$el.find(".facet-heading > span"),
124                    sig = this.model.get('sig'),
125                    inst = this,
126                    ranges,
127                    i;
128
129                for (i = 0; i < sig.length; i++) {
130                    if (hashObj.hasOwnProperty(sig[i]) && hashObj[sig[i]] !== '') {
131                        ranges = hashObj[sig[i]].split(",");
132
133                        facetClose.addClass('has-active-facet');
134                        _.each(ranges, function (range) {
135                            var r = range.split('|'),
136                                minValue = r[0],
137                                maxValue = r[1],
138                                selector,
139                                $component;
140
141                            if (minValue === "" && maxValue === "") {
142                                return;
143                            } else if (minValue !== "" && maxValue !== "") {
144                                selector = ".facetCheckbox[data-minvalue='" + minValue + "'][data-maxvalue='" + maxValue + "'], .facetRadio[data-minvalue='" + minValue + "'][data-maxvalue='" + maxValue + "']";
145                            } else if (minValue !== "" && maxValue === "") {
146                                selector = ".facetCheckbox[data-minvalue='" + minValue + "'], .facetRadio[data-minvalue='" + minValue + "']";
147                            } else if (minValue === "" && maxValue !== "") {
148                                selector = ".facetCheckbox[data-maxvalue='" + maxValue + "'], .facetRadio[data-maxvalue='" + maxValue + "']";
149                            }
150
151                            $component = $(selector);
152
153                            if ($component.length > 0) {
154                                $component.attr("checked", "checked");
155                            } else {
156                                inst.$el.find('.manualRangeMin').val(r[0]);
157                                inst.$el.find('.manualRangeMax').val(r[1]);
158                            }
159                        });
160                    }
161                }
162            },
163            /**
164             * Updates Hash base on selected element by calling 
165             * ["updateHash"]{@link module:managedrange.FacetManagedRangeView.updateHash}
166             * @param {Event} param Event that contains
167             * currentTarget element
168             * @memberof module:managedrange.FacetManagedRangeView
169             * @alias module:managedrange.FacetManagedRangeView#radioClick
170             */
171            radioClick: function (param) {
172                //fix for radio buttons groups in the ASP.NET repeater control
173                var radio = $(param.currentTarget);
174                $('.facetRadio').attr("name", radio.attr("name"));
175                this.updateHash(radio);
176            },
177            /**
178             * Clears values for manualRangeMin and manualRangeMax elements
179             * @param {Event} param Event that contains
180             * currentTarget element
181             * @memberof module:managedrange.FacetManagedRangeView
182             * @alias module:managedrange.FacetManagedRangeView#checkBoxClick
183             */
184            checkBoxClick: function (param) {
185                var checkbox = $(param.currentTarget);
186                if (checkbox.is(":checked")) {
187                    this.$el.find('.manualRangeMin').val("");
188                    this.$el.find('.manualRangeMax').val("");
189                }
190            },
191            /**
192             * Manages checked status for facetCheckbox 
193             * Clears values for manualRangeMin and manualRangeMax elements
194             * and updates hash value
195             * @param {Event} param Event that contains
196             * currentTarget element
197             * @memberof module:managedrange.FacetManagedRangeView
198             * @alias module:managedrange.FacetManagedRangeView#linkClick
199             */
200            linkClick: function (param) {
201                var $link = $(param.currentTarget),
202                    hashValue = $link.data().minvalue + "|" + $link.data().maxvalue;
203
204                this.$el.find(".facetCheckbox[data-shortid!=" + $link.data().shortid + "]").removeAttr("checked");
205                this.$el.find(".facetCheckbox[data-shortid=" + $link.data().shortid + "]").attr("checked", "checked");
206                this.$el.find('.manualRangeMin').val("");
207                this.$el.find('.manualRangeMax').val("");
208
209                queryModel.updateHash(this.updateSignaturesHash(sig, hashValue, {}));
210            },
211            /**
212             * If minRange or maxRange value set 
213             * ["queryModel updateHash"]{@link module:searchQuery.updateHash} method
214             * If checked CheckBox or RadioButton called
215             * ["managedrange updateHash"]{@link module:managedrange.FacetManagedRangeView.updateHash}
216             * If multiply selection disabled call 
217             * ["radioClick"]{@link module:managedrange.FacetManagedRangeView.radioClick}
218             * @memberof module:managedrange.FacetManagedRangeView
219             * @alias module:managedrange.FacetManagedRangeView.filter
220             */
221            filter: function () {
222                var multipleSelection = this.model.get('dataProperties').multipleSelection,
223                    checkedCheckBoxes = this.$el.find('.facetCheckbox:checked'),
224                    checkedRadioButton = this.$el.find('.facetRadio:checked'),
225                    minRange = this.$el.find('.manualRangeMin'),
226                    maxRange = this.$el.find('.manualRangeMax'),
227                    sig = this.model.get('sig'),
228                    maxRange, minRange, minValue, maxValue;
229
230                //Gets values from text boxes
231                minValue = minRange.length > 0 && minRange.val() !== "" ? minRange.val() : "";
232                maxValue = maxRange.length > 0 && maxRange.val() !== "" ? maxRange.val() : "";
233
234                if (minValue !== "" || maxValue !== "") {
235                    //Clears all selected radio buttons and checkboxes
236                    this.$el.find(".facetRadio").removeAttr("checked");
237                    this.$el.find(".facetCheckbox").removeAttr("checked");
238
239                    //Auto update hash after text box change when there is no filter button
240                    queryModel.updateHash(this.updateSignaturesHash(sig, minValue + "|" + maxValue, {}));
241                } else if (checkedCheckBoxes.length > 0 || checkedRadioButton.length > 0) {
242                    if (multipleSelection) {
243                        this.updateHash(checkedCheckBoxes);
244                    } else {
245                        this.radioClick({ currentTarget: checkedRadioButton });
246                    }
247                }
248            },
249            /**
250            * Clears selected filter and updates hash
251            * @memberof module:managedrange.FacetManagedRangeView
252            * @alias module:managedrange.FacetManagedRangeView#clearFilter
253            * 
254            */
255            clearFilter: function () {
256                var minRange = this.$el.find('.manualRangeMin'),
257                    maxRange = this.$el.find('.manualRangeMax'),
258                    properties = this.model.get('dataProperties'),
259                    facetClose = this.$el.find('.facet-heading > span'),
260                    hash = queryModel.parseHashParameters(window.location.hash),
261                    sig = this.model.get('sig'),
262                    shouldClear = false,
263                    facetData,
264                    i;
265
266                for (i = 0; i < sig.length; i++) {
267                    facetData = sig[i];
268                    if (typeof hash[facetData] !== "undefined" && hash[facetData] !== "") {
269                        delete properties[facetData];
270                        hash[facetData] = "";
271                        shouldClear = true;
272                    }
273                }
274
275                if (!shouldClear) {
276                    return;
277                }
278
279                queryModel.updateHash(hash);
280
281                this.model.set({ dataProperties: properties });
282
283                this.$el.find('.facetCheckbox').removeAttr("checked");
284                this.$el.find('.facetRadio').removeAttr("checked");
285
286                facetClose.removeClass('has-active-facet');
287
288                if (minRange.length > 0) {
289                    minRange.val(minRange.data().defaultvalue);
290                }
291                if (maxRange.length > 0) {
292                    maxRange.val(maxRange.data().defaultvalue);
293                }
294            },
295            /**
296             * Updates hash on checkbox or radio button changes
297             * @memberof module:managedrange.FacetManagedRangeView
298             * @alias module:managedrange.FacetManagedRangeView#clearFilter
299             * 
300             */
301            textBoxChange: function () {
302                var minRange = this.$el.find('.manualRangeMin'),
303                    maxRange = this.$el.find('.manualRangeMax'),
304                    minValue = minRange.length > 0 && minRange.val() !== "" ? minRange.val() : "",
305                    maxValue = maxRange.length > 0 && maxRange.val() !== "" ? maxRange.val() : "",
306                    sig = this.model.get('sig');
307
308                //Clears all selected radio buttons and checkboxes
309                this.$el.find(".facetRadio").removeAttr("checked");
310                this.$el.find(".facetCheckbox").removeAttr("checked");
311
312                if (minValue !== "" || maxValue !== "") {
313                    //Auto updates hash after text box change when there is no filter button
314                    queryModel.updateHash(this.updateSignaturesHash(sig, minValue + "|" + maxValue, {}));
315                } else {
316                    //Clears all radio buttons and checkbox hash parameters
317                    queryModel.updateHash(this.updateSignaturesHash(sig, "", {}));
318                }
319            },
320            /**
321             * Updates component
322             * @memberof module:managedrange.FacetManagedRangeView
323             * @alias module:managedrange.FacetManagedRangeView#clearFilter
324             * 
325             */
326            updateComponent: function (hash) {
327                var sig = this.model.get('sig'),
328                    facetPart,
329                    i;
330                for (i = 0; i < sig.length; i++) {
331                    facetPart = sig[i].toLowerCase();
332                    if (hash.hasOwnProperty(facetPart)) {
333                        this.render();
334                    } else {
335                        this.clearFilter();
336                    }
337                }
338            }
339        });
340    /**
341    * For each search managed range component on a page creates instance of 
342    * ["FacetManagedRangeModel"]{@link module:managedrange.FacetManagedRangeModel} and 
343    * ["FacetManagedRangeView"]{@link module:managedrange.FacetManagedRangeView} 
344    * @memberOf module:managedrange
345    * @alias module:managedrange.init
346    */
347    api.init = function () {
348        if ($("body").hasClass("on-page-editor") || initialized) {
349            return;
350        }
351
352        queryModel = XA.component.search.query;
353        apiModel = XA.component.search.ajax;
354        urlHelperModel = XA.component.search.url;
355
356        var facetManagedRangesList = $(".facet-managed-range");
357        _.each(facetManagedRangesList, function (elem) {
358            var model = new FacetManagedRangeModel(),
359                view = new FacetManagedRangeView({ el: $(elem), model: model });
360            view.render();
361        });
362
363        initialzied = true;
364    };
365
366    return api;
367
368}(jQuery, document));
369
370XA.register('managedrange', XA.component.search.facet.managedrange);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.