PageSourceSearch

https://www.stlouisfed.org/-/media/themes/frbstl/stlouisfed/stloui…/component-search-facet-daterange-frbstl.js

js stlouisfed.org collected 2026-09-24 06:40:20 UTC 12,561 bytes, 287 lines download raw bytes

1/**
2 * Includes functionality for daterange component
3 * @module facetDateRange
4 * @param  {jQuery} $ Instance of jQuery
5 * @param  {Document} document dom document object
6 * @return {Object} list of methods for working with date range component
7*/
8XA.component.search.facet.daterange = (function ($, document) {
9    /**
10    * This object stores all public api methods
11    * @type {Object.<Methods>}
12    * @memberOf module:facetDateRange
13    * */
14    var api = {}, queryModel, urlHelperModel, initialized = false, toUrlDate, fromUrlDate;
15    /**
16     * format date
17     * @param {String} date date that should be formatted
18     * @private
19     * @memberof module:facetDateRange
20     * @alias module:facetDateRange.toUrlDate
21     * @returns {String} date in format 'yymmdd'
22     */
23    toUrlDate = function (date) {
24        return date !== null && date !== "" ? $.datepicker.formatDate('yymmdd', date) : "";
25    };
26    /**
27     * format date from url
28     * @private
29     * @param {String} dateString date that should be formatted
30     * @memberof module:facetDateRange
31     * @alias module:facetDateRange.fromUrlDate
32     * @returns {Date} date
33     */
34    fromUrlDate = function (dateString) {
35        var y = dateString.substr(0, 4),
36            m = dateString.substr(4, 2) - 1,
37            d = dateString.substr(6, 2),
38            D = new Date(y, m, d);
39
40        if (dateString === "") {
41            return;
42        }
43
44        if (D.getFullYear() == y && D.getMonth() == m && D.getDate() == d)
45            return D;
46        else
47            throw "Invalid date: " + dateString;
48    };
49    /**
50    * @name module:facetDateRange.FacetDateRangeModel
51    * @constructor
52    * @augments Backbone.Model
53    */
54    var FacetDateRangeModel = Backbone.Model.extend(
55        /** @lends module:facetDateRange.FacetDateRangeModel.prototype **/
56        {
57            /**
58           * Default model options
59           * @default
60           */
61            defaults: {
62                dataProperties: {},
63                sig: []
64            }
65        });
66    /**
67      * @name module:facetDateRange.FacetDateRangeView
68      * @constructor
69      * @augments Backbone.View
70      */
71    var FacetDateRangeView = XA.component.search.baseView.extend(
72        /** @lends module:facetDateRange.FacetDateRangeView.prototype **/
73        {
74            /**
75            * Initially sets data to model and watches events on which
76            * view should be updated
77            * @listens module:facetDateRange.FacetDateRangeView~event:change
78            * @listens module:XA.component.search.vent~event:hashChanged
79            * @memberof module:facetDateRange.FacetDateRangeView
80            */
81            initialize: function () {
82                this.properties = this.$el.data().properties;
83                if (this.model) {
84                    this.model.set({ dataProperties: this.properties });
85                    this.model.set("sig", this.translateSignatures(this.properties.searchResultsSignature, this.properties.f));
86                }
87                this.model.on("change", this.render, this);
88                
89                XA.component.search.vent.on("hashChanged", this.updateComponent.bind(this));
90            },
91            /**
92             * list of events for Backbone View
93             * @memberof module:facetDateRange.FacetDateRangeView
94             * @alias module:facetDateRange.FacetDateRangeView#events
95             */
96            events: {
97                'change .startDate': 'updateFacet',
98                'change .endDate': 'updateFacet',
99                'click .bottom-remove-filter, .clear-filter': 'clearFilter'
100            },
101            /**
102             * Renders view. Use jquery ui datepicker
103             * @memberof module:facetDateRange.FacetDateRangeView
104             * @alias module:facetDateRange.FacetDateRangeView#render
105             */
106            render: function () {
107                var fromDateDefaultOffset = parseInt(this.model.get('dataProperties').fromDateDefaultOffset),
108                    toDateDefaultOffset = parseInt(this.model.get('dataProperties').toDateDefaultOffset),
109                    fromDateFormat = this.model.get('dataProperties').fromDateDisplayFormat,
110                    toDateFormat = this.model.get('dataProperties').toDateDisplayFormat,
111                    fromDateMonthsShown = this.model.get('dataProperties').fromDateMonthsShown,
112                    toDateMonthsShown = this.model.get('dataProperties').toDateMonthsShown,
113                    fromDatePastDays = this.model.get('dataProperties').fromDatePastDays,
114                    toDateFutureDays = this.model.get('dataProperties').toDateFutureDays,
115                    fromDateVisible = this.model.get('dataProperties').fromDateVisible,
116                    toDateVisible = this.model.get('dataProperties').toDateVisible,
117                    $fromDate = this.$el.find('.startDate'),
118                    $toDate = this.$el.find('.endDate'),
119                    hashObj = queryModel.parseHashParameters(window.location.hash),
120                    sig = this.model.get('sig'),
121                    lang = $("html").attr("lang") ? $("html").attr("lang") : "",
122                    dates, i;
123
124                if (toDateFormat) {
125                    toDateFormat = toDateFormat.replace(/yy/g, "y");
126                }
127                if (fromDateFormat) {
128                    fromDateFormat = fromDateFormat.replace(/yy/g, "y");
129                }
130
131                if (fromDateVisible) {
132                    $fromDate.datepicker({
133                        dateFormat: fromDateFormat,
134                        changeMonth: fromDateMonthsShown,
135                        changeYear: fromDateMonthsShown,
136						yearRange: "1967:c",
137                        minDate: fromDatePastDays ? (fromDateDefaultOffset != '' ? -1 * fromDateDefaultOffset : new Date(1900, 1, 1)) : new Date()
138                    });
139                }
140
141                if (toDateVisible) {
142                    $toDate.datepicker({
143                        dateFormat: toDateFormat,
144                        changeMonth: toDateMonthsShown,
145                        changeYear: toDateMonthsShown,
146						yearRange: "1967:c",
147                        maxDate: toDateFutureDays ? (toDateDefaultOffset != '' ? toDateDefaultOffset : new Date(2100, 1, 1)) : new Date()
148                    });
149                }
150                $xa.datepicker.setDefaults($xa.datepicker.regional[lang]);
151                for (i = 0; i < sig.length; i++) {
152                    if (hashObj.hasOwnProperty(sig[i]) && hashObj[sig[i]] != '') {
153                        dates = hashObj[sig[i]].split("|");
154                        $fromDate.datepicker("setDate", fromUrlDate(dates[0]));
155                        $toDate.datepicker("setDate", fromUrlDate(dates[1]));
156                    }
157                }
158            },
159            /**
160            * Updates hash by calling ["updateHash"]{@link module:searchQuery.updateHash}
161            * @memberof module:facetDateRange.FacetDateRangeView
162            * @alias module:facetDateRange.FacetDateRangeView#updateFacet
163            */
164            updateFacet: function (param) {
165                var $facetClose = this.$el.find('.facet-heading > span'),
166                    $fromDate = this.$el.find('.startDate'),
167                    $toDate = this.$el.find('.endDate'),
168                    fromDate = $fromDate.length > 0 ? $fromDate.datepicker("getDate") : null,
169                    toDate = $toDate.length > 0 ? $toDate.datepicker("getDate") : null,
170                    sig = this.model.get('sig');
171
172                queryModel.updateHash(this.updateSignaturesHash(sig, toUrlDate(fromDate) + "|" + toUrlDate(toDate), {}));
173                $facetClose.addClass('has-active-facet');
174            },
175            /**
176            * Clears selected filter in component
177            * @param {Object} param
178            * @memberof module:facetDateRange.FacetDateRangeView
179            * @alias module:facetDateRange.FacetDateRangeView#clearFilter
180            */
181            clearFilter: function (param) {
182                var properties = this.model.get('dataProperties'),
183                    $facetClose = this.$el.find('.facet-heading > span'),
184                    hash = queryModel.parseHashParameters(window.location.hash),
185                    sig = this.model.get('sig'),
186                    shouldClear = false,
187                    facetData,
188                    i;
189
190                $facetClose.removeClass('has-active-facet');
191
192                for (i = 0; i < sig.length; i++) {  
193                    facetData = sig[i];
194                    if (typeof hash[facetData] !== "undefined" && hash[facetData] !== "") {                                      
195                        delete properties[facetData];
196                        shouldClear = true;
197                    }
198                }
199
200                if (!shouldClear) {
201                    return;
202                }
203
204                queryModel.updateHash(this.updateSignaturesHash(sig, "", hash));
205
206                this.model.set({ dataProperties: properties });
207
208                this.$el.find('.startDate').val("");
209                this.$el.find('.endDate').val("");
210            },
211            /**
212            * Updates component after changes in hash
213            * @param {Object} hash object that stores hash values
214            * @memberof module:facetDateRange.FacetDateRangeView
215            * @alias module:facetDateRange.FacetDateRangeView#updateComponent
216            */
217            updateComponent: function (hash) {
218                var $fromDate = this.$el.find('.startDate'),
219                    $toDate = this.$el.find('.endDate'),
220                    sig = this.model.get('sig'),
221                    facetPart,
222                    dates,
223                    i;
224
225                for (i = 0; i < sig.length; i++) {
226                    facetPart = sig[i].toLowerCase();
227                    if (hash.hasOwnProperty(facetPart) && hash[facetPart] !== '') {
228                        dates = hash[facetPart].split("|");
229                        if (dates[0] !== "") {
230                            this.handleDate($fromDate, dates[0]);
231                        }
232                        if (dates[1] !== "") {
233                            this.handleDate($toDate, dates[1]);
234                        }
235                    } else {
236                        this.clearFilter();
237                    }
238                }
239            },
240            /**
241            * Updates datepicker date
242            * @param {jQuery<DomElement>} control element where start date specified
243            * @param {String} value date that should be set  
244            * @memberof module:facetDateRange.FacetDateRangeView
245            * @alias module:facetDateRange.FacetDateRangeView#handleDate
246            */
247            handleDate: function (control, value) {
248                var $facetClose = this.$el.find('.facet-heading > span');
249                if (control.length !== 0 && toUrlDate(control.datepicker('getDate')) !== value) {
250                    control.datepicker("setDate", fromUrlDate(value));
251                    $facetClose.addClass('has-active-facet');
252                } else if (value === "") {
253                    control.datepicker('setDate', null);
254                }
255            }
256        });
257
258    /**
259    * For each search date range on a page creates instance of 
260    * ["FacetDateRangeModel"]{@link module:facetDateRange.FacetDateRangeModel} and 
261    * ["FacetDateRangeView"]{@link module:facetDateRange.FacetDateRangeView} 
262    * @memberOf module:facetDateRange
263    * @alias module:facetDateRange.init
264    */
265    api.init = function () {
266        if ($("body").hasClass("on-page-editor") || initialized) {
267            return;
268        }
269
270        queryModel = XA.component.search.query;
271        urlHelperModel = XA.component.search.url;
272
273        var facetDateRangesList = $(".facet-date-range");
274        _.each(facetDateRangesList, function (elem) {
275            var model = new FacetDateRangeModel(),
276                view = new FacetDateRangeView({ el: $(elem), model: model });
277            view.render();
278        });
279
280        initialzied = true;
281    };
282
283    return api;
284
285}(jQuery, document));
286
287XA.register('facetDateRange', XA.component.search.facet.daterange);

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.