PageSourceSearch

https://www.harrywinston.com/-/media/base-themes/hw-search-theme/s…=-1&hash=FF8436BEF0B8C31DCE29A51D6AD24119

js harrywinston.com collected 2026-10-02 06:21:50 UTC 18,020 bytes, 397 lines download raw bytes

1
2/**
3 * Facet summary component functionality
4 * @module facetSummary
5 * @param  {jQuery} $ Instance of jQuery
6 * @param  {Document} document dom document object
7 * @return {Object} list of methods for working with component facet summary
8*/
9XA.component.search.facet.summary = (function ($, document) {
10    /**
11    * This object stores all public api methods
12    * @type {Object.<Methods>}
13    * @memberOf module:facetSummary
14    */
15    var api = {},
16        urlHelperModel = XA.component.search.url,
17        queryModel = XA.component.search.query,
18        apiModel = XA.component.search.ajax,
19        facetName = "summary";
20
21    /**
22    * @name module:facetSummary.FacetSummaryModel
23    * @constructor
24    * @augments Backbone.Model
25    */
26    var FacetSummaryModel = Backbone.Model.extend(
27        /** @lends module:facetSummary.FacetSummaryModel.prototype **/
28
29        {
30            /**
31            * Default model options
32            * @default
33            * @param {Object} properties properties of ajax call and callback
34            */
35            defaults: {
36                dataProperties: {},
37                sig: [],
38                hash: ''
39            },
40            /**
41           * Listens to changes on facets and hash
42            * @listens module:XA.component.search.vent~event:facet-data-loaded
43            * @listens module:XA.component.search.vent~event:facet-data-filtered
44            * @listens module:XA.component.search.vent~event:facet-data-partial-filtered
45            * @listens module:XA.component.search.vent~event:hashChanged
46            */
47            initialize: function () {
48                var that = this;
49                this.set('resultData', {})
50                //Event to get data at the begining or in case that there are no hash parameters in the url - one request for all controls
51                XA.component.search.vent.on("facet-data-loaded", that.processData.bind(that));
52                // //If the url hash contains this control facet name (someone clicked this control), then we have to listen for partial filtering
53                XA.component.search.vent.on("facet-data-partial-filtered", that.processData.bind(that));
54                // //When we are not filtering by this control (not clicked)
55                XA.component.search.vent.on("facet-data-filtered", that.processData.bind(that));
56
57            },
58            /**
59             * Finds all facets that have same name as facetName in Control Data and return them
60             * @param {Object} facetData 
61             * @param {*} controlData 
62             * @returns {Array} Filtered facet data
63             * @memberof module:facetSummary.FacetSummaryModel
64             * @alias module:facetSummary.FacetSummaryModel.requestFacetData
65             */
66            requestFacetData: function (facetData, controlData) {
67                return _.find(facetData, function (f) {
68                    return f.Key.toLowerCase() === controlData.facetName.toLowerCase();
69                });
70            },
71            /**
72             * Concatenates signature and facet name in order to build proper hash parameter name
73             * @param {*} rawSignature 
74             * @param {*} f 
75             */
76            translateSignatures: function (rawSignature, f) {
77                var signatures, i;
78
79                f = f.toLowerCase();
80
81                if (typeof rawSignature === "undefined" || rawSignature === null) {
82                    return [f];
83                }
84
85                signatures = rawSignature.split(',');
86
87                if (rawSignature === "") {
88                    return [f];
89                } else {
90                    for (i = 0; i < signatures.length; i++) {
91                        signatures[i] = signatures[i] + "_" + f;
92                    }
93                    return signatures;
94                }
95            },
96            /**
97            * Processes data that comes as parameter. Update
98            * model and store all facets that are active and have
99            * same signature
100            * @param {Object} data Data from server with facet values
101            * @memberof module:facetSummary.FacetSummaryModel
102            * @alias module:facetSummary.FacetSummaryModel.processData
103            */
104            processData: function (data) {
105                var hashObj = queryModel.parseHashParameters(window.location.hash),
106                    requestFacedData,
107                    that = this,
108                    displayName,
109                    facetData = [], requestData = {}, facetControl, control;
110                var facets = XA.component.search.facet;
111
112                for (facetControl in facets) {
113                    control = XA.component.search.facet[facetControl];
114                    if (typeof (control.getFacetDataRequestInfo) === "function") {
115                        facetData = control.getFacetDataRequestInfo();
116                        for (var facetIndex = 0; facetIndex < facetData.length; facetIndex++) {
117                            var controlData = facetData[facetIndex];
118                            var signaturesArray = controlData.signature.split(',');
119                            for (var signatureIndex = 0; signatureIndex < signaturesArray.length; signatureIndex++) {
120                                var signature = signaturesArray[signatureIndex];
121                                if (data.Signature == signature && that.get('sig') == signature) {
122                                    requestFacedData = that.requestFacetData(data.Facets, controlData);
123                                    if (typeof requestFacedData !== "undefined") {
124                                        displayName = requestFacedData.Name;
125                                        var currResults = this.get('resultData');
126                                        var facetHashNames = that.translateSignatures(signature, requestFacedData.Key.toLowerCase())
127                                        for (var facetHashNameIndex = 0; facetHashNameIndex < facetHashNames.length; facetHashNameIndex++) {
128                                            var facetHashName = facetHashNames[facetHashNameIndex];
129                                            if (hashObj[facetHashName]) {
130                                                currResults[displayName] = {
131                                                    "value": hashObj[facetHashName],
132                                                    "key": requestFacedData.Key,
133                                                    "signature": data.Signature,
134                                                    "facetHashName": facetHashName
135                                                }
136                                            } else {
137                                                delete currResults[displayName];
138                                            }
139                                        }
140                                        this.set('resultData', currResults);
141                                        this.trigger('change', this)
142
143                                    }
144                                }
145                            }
146
147                        }
148                    }
149                }
150            }
151        });
152    /**
153    * @name module:facetSummary.FacetSummaryView
154    * @constructor
155    * @augments Backbone.View
156    */
157    var FacetSummaryView = XA.component.search.baseView.extend(
158        /** @lends module:facetSummary.FacetSummaryView.prototype **/
159
160        {
161            tagName: "div",
162            className: "facet-search-summary",
163            template:
164                "<% if(Object.keys(resultData).length){ %> <div class='facet-summary-wrapper clearfix'>" +
165                "<% _.forEach(resultData, function(obj,key){ %>" +
166                "<div class='active-facet-summary-element' data-hash='" + "<%=obj.facetHashName%>" + "' data-key='" + "<%=obj.key%>" + "' data-signature='" + "<%=obj.signature%>" + "'>" +
167                "<span class='facet-summary-name'><%= key  %>:</span> " + "<%= renderFacetValues(obj.value) %>" +
168                "</div>" +
169                "<% }); %>" +
170                "</div><% }%>",
171
172            renderFacetValues: function (value) {
173                var params = value.split("||")
174
175                return params.map(function (p) {
176                    var template = '<div class=\'facet-summary-value\' data-value=' + encodeURIComponent(p) + '>'
177                        + '<p>' + p + '</p>'
178                        + '<span class=\'removeFacetValue\'>x</span>'
179                        + '</div>'
180
181                    return template;
182                }).join(' ')
183            },
184            /**
185            * Initially sets data to model and watches events on which
186            * view should be updated
187            * @listens module:facetSummary.FacetSummaryView~event:change
188            * @memberof module:facetSummary.FacetSummaryView
189            * @alias module:facetSummary.FacetSummaryView#initialize
190            */
191            clearButtons: function (event) {
192                var $target = $(event.currentTarget),
193                    $facetSummary = $target.closest(".facet-summary");
194                $facetSummary.find('.clear-all-active-facets').trigger('click');
195
196            },
197            /**
198            * Initializes the view by assigning events to the buttons and rendering component
199            * @memberof module:facetSummary.FacetSummaryView
200            * @alias module:facetSummary.FacetSummaryView#events
201            */
202            initialize: function () {
203                var dataProperties = this.$el.data(),
204                    that = this,
205                    properties = dataProperties.properties,
206                    signatures;
207                Backbone.$('.facet-summary .clear-filter').on('click', function (event) {
208                    that.clearButtons(event);
209                    that.updateUrlWithoutHash();
210
211                })
212                Backbone.$('.facet-summary .bottom-remove-filter').on('click', function (event) {
213                    that.clearButtons(event);
214                    that.updateUrlWithoutHash();
215
216                })
217                signatures = this.translateSignatures(properties.searchResultsSignature, facetName);
218                this.model.set("sig", properties.searchResultsSignature);
219                dataProperties = this.$el.data("properties"),
220                    this.model.on("change", this.render, this);
221                this.render();
222            },
223            /**
224             * list of events for Backbone View
225            * @memberof module:facetSummary.FacetSummaryView
226            * @alias module:facetSummary.FacetSummaryView#events
227             */
228            events: {
229                'click .removeFacetValue': 'removeFacetValue',
230                'click .clear-filter': 'clearAllActiveFacets',
231                'click .bottom-remove-filter button': 'clearAllActiveFacets'
232            },
233            updateUrlWithoutHash: function () {
234                // var currentUrl = window.location.href.split('#')[0];
235                // history.replaceState({}, document.title, currentUrl);
236                var currentUrl = window.location.href;
237                var hashIndex = currentUrl.indexOf('#');
238
239                if (hashIndex !== -1) {
240                    var hashPart = currentUrl.substring(hashIndex);
241
242                    if (hashPart === "#salon-locator_g=true") {
243                        return;
244                    } else if (hashPart.indexOf("#salon-locator_g=true") !== -1) {
245                        var newHashPart = "#salon-locator_g=true";
246                        history.replaceState({}, document.title, currentUrl.split('#')[0] + newHashPart);
247                    } else {
248                        history.replaceState({}, document.title, currentUrl.split('#')[0]);
249                    }
250                }
251            },
252            /**
253            * Prepares hash string based on hash object
254            * @param {Object} hashObj Object created from hash parameters
255            * @memberof module:facetSummary.FacetSummaryView
256            * @alias module:facetSummary.FacetSummaryView#createHash
257            * @returns {String}
257 hash as a string
258            */
259            createHash: function (hashObj) {
260                var result = "#";
261                for (option in hashObj) {
262                    result += option + "=" + hashObj[option] + "&";
263                }
264                return result;
265            },
266            /**
267             * Updates current location
268             * @param {Object} hashObj 
269             */
270            updateLocation: function (hashObj) {
271                XA.component.search.query.updateHash(hashObj);
272            },
273            /**
274             * Returns facet params
275             * @param {Jquery} el jquery event target element 
276             */
277            getFacetParams: function (el) {
278                var summaryEl = $(el).closest(".active-facet-summary-element");
279
280                return {
281                    key: summaryEl.data('key'),
282                    signature: summaryEl.data('signature')
283                }
284            },
285            /**
286             * Clears all active facets that are stored under summary component
287            * @memberof module:facetSummary.FacetSummaryView
288            * @alias module:facetSummary.FacetSummaryView#clearAllActiveFacets
289            */
290            clearAllActiveFacets: function () {
291                var self = this;
292                var hashObj = queryModel.parseHashParameters(window.location.hash);
293
294                this.$el.find('.active-facet-summary-element').each(function () {
295                    var facetParams = self.getFacetParams($(this));
296                    var facetHashNames = self.translateSignatures(facetParams.signature, facetParams.key)
297
298                    _.each(facetHashNames, function (facetHashName) {
299                        hashObj[facetHashName] = "";
300                    })
301                })
302
303                self.updateLocation(hashObj);
304            },
305            /**
306             * Removes selected facet value and updates hash
307             * @param {Event} event Event object where stored clicked element
308             */
309            removeFacetValue: function (event) {
310                var facetValueElem = $(event.currentTarget).closest(".facet-summary-value")
311
312                var selectedFacetValue = decodeURIComponent(facetValueElem.data('value'))
313                var facetParams = this.getFacetParams(event.currentTarget)
314
315                var hashObj = queryModel.parseHashParameters(window.location.hash);
316                var facetHashNames = this.translateSignatures(facetParams.signature, facetParams.key)
317
318                var removeSelectedValue = function (facetHashName) {
319                    hashObj[facetHashName] = hashObj[facetHashName]
320                        .split("||")
321                        .filter(function (val) {
322                            return val !== selectedFacetValue
323                        })
324                        .join("||");
325                }
326
327                _.each(facetHashNames, removeSelectedValue)
328
329                this.updateLocation(hashObj);
330            },
331            /**
332            * Renders view
333            * @memberof module:facetSummary.FacetSummaryView
334            * @alias module:facetSummary.FacetSummaryView#render
335            */
336            render: function () {
337                var inst = this,
338                    resultData = this.model.get("resultData"),
339                    template, templateResult;
340                var dataProperties = this.$el.data();
341                this.properties = dataProperties.properties;
342                this.manageVisibilityByData(this.$el, resultData)
343                if (this.model) {
344                    this.model.set({ dataProperties: this.properties });
345                    this.model.set("sig", this.properties.searchResultsSignature);
346                }
347                //checks whether page is opened from disc - if yes then we are in Creative Exchange mode
348                if (window.location.href.startsWith("file://")) {
349                    return;
350                }
351
352                if (resultData !== undefined) {
353                    template = _.template(this.template, {
354                        imports: { renderFacetValues: this.renderFacetValues }
355                    });
356
357                    templateResult = template({
358                        "resultData": resultData
359                    });
360                }
361
362                inst.$el.find(".facet-summary-placeholder").html(templateResult);
363            }
364
365        });
366    /**
367    * For each search dropdown component on a page creates instance of 
368    * ["FacetSummaryModel"]{@link module:facetSummary.FacetSummaryModel} and 
369    * ["FacetSummaryView"]{@link module:facetSummary.FacetSummaryView} 
370    * @memberOf module:facetSummary
371    * @alias module:facetSummary.init
372    */
373    api.init = function () {
374        if ($("body").hasClass("on-page-editor")) {
375            return;
376        }
377
378        queryModel = XA.component.search.query;
379        apiModel = XA.component.search.ajax;
380        urlHelperModel = XA.component.search.url;
381
382        var facetSummary = $(".facet-summary:not(.initialized)");
383
384        _.each(facetSummary, function (elem) {
385            var $el = $(elem),
386                model = new FacetSummaryModel(),
387                view = new FacetSummaryView({ el: $el, model: model });
388
389            $el.addClass("initialized");
390        });
391    };
392
393    return api;
394
395}(jQuery, document));
396
397XA.register('facetSummary', XA.component.search.facet.summary);

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.