PageSourceSearch

https://www.commufa.jp/-/media/Base-Themes/SearchTheme/Scripts/component-search-page-selector.js

js commufa.jp collected 2026-09-24 18:11:18 UTC 18,266 bytes, 393 lines download raw bytes

1/**
2 * Facet page selector component functionality
3 * @module searchPageSelector
4 * @param  {jQuery} $ Instance of jQuery
5 * @param  {Document} document dom document object
6 * @return {Object} list of methods for working with component page selector
7*/
8XA.component.search.pageSelector = (function ($, document) {
9    /**
10    * This object stores all public api methods
11    * @type {Object.<Methods>}
12    * @memberOf module:searchPageSelector
13    */
14    var api = {},
15        queryModel;
16    facetName = "e";
17    /**
18    * @name module:searchPageSelector.SearchPageSelectorModel
19    * @constructor
20    * @augments Backbone.Model
21    */
22    var SearchPageSelectorModel = Backbone.Model.extend(
23        /** @lends module:searchPageSelector.SearchPageSelectorModel.prototype **/
24        {
25            /**
26            * Default model options
27            * @default
28            */
29            defaults: {
30                dataProperties: {},
31                resultsCount: 0,
32                offset: 0,
33                selectedValue: 1,
34                pageSize: 0,
35                repeatRequest: false,
36                template: "<ul class='page-selector-list'> " +
37                    "<li class='page-selector-item-first'><a href='#'><%= data.first %></a></li>" +
38                    "<li class='page-selector-item-previous'><a href='#'><%= data.previous %></a></li>" +
39                    "<% var beforePage = 0; %>" +
40                    "<% _.each(data.pages, function(page){ %>" +
41                    "<% if((beforePage+1) != page.number){ %>" +
42                    "<li><span class='page-selector-more'>...</span></li>" +
43                    "<% } %>" +
44                    "<% beforePage = page.number; %>" +
45                    "<% if(data.selectedValue === page.number){ %>" +
46                    "<% active = 'active'; %>" +
47                    "<% }else { active = '' } %>" +
48                    "<li><a class='page-selector-item-link <%= active %>' data-offset='<%= page.offset %>' data-itemNumber='<%= page.number %>' href='#'><%= page.number %></a></li>" +
49                    "<% }); %>" +
50                    "<li class='page-selector-item-next'><a href='#'><%= data.next %></a></li>" +
51                    "<li class='page-selector-item-last'><a href='#'><%= data.last %></a></li>" +
52                    "</ul>",
53                sig: [],
54                timeStamp: new Date().getTime()
55            }
56        });
57    /**
58     * @name module:searchPageSelector.SearchPageSelectorView
59     * @constructor
60     * @augments Backbone.View
61     */
62    var SearchPageSelectorView = XA.component.search.baseView.extend(
63        /** @lends module:searchPageSelector.SearchPageSelectorView **/
64        {
65            /**
66           * Initially sets data to model and watches events on which
67           * view should be updated
68           * @listens module:searchPageSelector.SearchPageSelectorView~event:change
69           * @listens module:XA.component.search.vent~event:results-loaded
70           * @memberof module:searchPageSelector.SearchPageSelectorView
71           * @alias module:searchPageSelector.SearchPageSelectorView#initialize
72           */
73            initialize: function () {
74                var dataProp = this.$el.data();
75
76                if (dataProp.properties.searchResultsSignature === null) {
77                    dataProp.properties.searchResultsSignature = "";
78                }
79
80                this.model.set("dataProperties", dataProp);
81                this.model.set("sig", this.translateSignatures(dataProp.properties.searchResultsSignature, facetName));
82                this.model.on("change", this.render, this);
83
84                XA.component.search.vent.on("results-loaded", this.handleLoadedData.bind(this));
85
86                //check whether page is opened from disc - if yes then we are in Creative Exchange mode and lets mock some content
87                if (window.location.href.startsWith("file://")) {
88                    this.model.set({
89                        "resultsCount": 10,
90                        "pageSize": 2,
91                        "selectedValue": 2
92                    });
93                }
94            },
95            /**
96             * list of events for Backbone View
97             * @memberof module:searchPageSelector.SearchPageSelectorView
98             * @alias module:searchPageSelector.SearchPageSelectorView#events
99             */
100            events: {
101                'click .page-selector-item-link': "updateSelectedValue",
102                'click .page-selector-item-first a': "showFirstPage",
103                'click .page-selector-item-last a': "showLastPage",
104                'click .page-selector-item-previous a': "showPrevPage",
105                'click .page-selector-item-next a': "showNextPage"
106            },
107            /**
108            * Updates model values with selectedValue
109            * and data object from server response
110            * @param {Object} data Data that contains component properties
111            * @param {Number} selectedValue number of selected page 
112            * @memberOf module:searchPageSelector.SearchPageSelectorView
113            * @alias module:searchPageSelector.SearchPageSelectorView#updateModelAfterSearch
114            */
115            updateModelAfterSearch: function (data, selectedValue) {
116                this.model.set({
117                    "pageSize": parseInt(data.pageSize),
118                    "resultsCount": parseInt(data.dataCount),
119                    "offset": parseInt(data.offset),
120                    "selectedValue": parseInt(selectedValue)
121                });
122                this.model.set("timeStamp", new Date().getTime());
123                this.updateElementCssClass(data);
124            },
125            /**
126            * Function that based on selected component values sets css class
127            * page-selector-empty or page-selector-single-page
128            * @param {Object} data Data that contains component properties
129            * @memberOf module:searchPageSelector.SearchPageSelectorView
130            * @alias module:searchPageSelector.SearchPageSelectorView#updateElementCssClass
131            */
132            updateElementCssClass: function (data) {
133                this.el.classList.remove("page-selector-empty")
134                this.el.classList.remove("page-selector-single-page")
135                if (data.dataCount === 0) {
136                    this.el.classList.add("page-selector-empty")
137                } else if (data.pageSize > data.dataCount || data.offset > data.dataCount) {
138                    this.el.classList.add("page-selector-single-page")
139                }
140            },
141            /**
142            * Updates hash according to changed component value
143            * @param {Event} event Event object that contains target with selected component value
144            * @memberOf module:searchPageSelector.SearchPageSelectorView
145            * @alias module:searchPageSelector.SearchPageSelectorView#updateSelectedValue
146            */
147            updateSelectedValue: function (event) {
148                event.preventDefault();
149
150                var sig = this.model.get("sig"),
151                    dataProp = $(event.target).data();
152
153                queryModel.updateHash(this.updateSignaturesHash(sig, dataProp.offset, {}));
154            },
155            /**
156            * Switches page selector to the first page and updates hash parameters
157            * @param {Event} event Event object that contains target with selected component value
158            * @memberOf module:searchPageSelector.SearchPageSelectorView
159            * @alias module:searchPageSelector.SearchPageSelectorView#showFirstPage
160            */
161            showFirstPage: function (event) {
162                event.preventDefault();
163
164                var sig = this.model.get("sig"),
165                    dataProp = $(event.target).data();
166
167                queryModel.updateHash(this.updateSignaturesHash(sig, 0, {}));
168            },
169            /**
170            * Switches page selector to the last page and updates hash parameters
171            * @param {Event} event Event object that contains target with selected component value
172            * @memberOf module:searchPageSelector.SearchPageSelectorView
173            * @alias module:searchPageSelector.SearchPageSelectorView#showLastPage
174            */
175            showLastPage: function (event) {
176                event.preventDefault();
177                var lastPageItems = this.model.get("resultsCount") % this.model.get("pageSize"),
178                    offset = this.model.get("resultsCount") - ((lastPageItems === 0) ? this.model.get("pageSize") : lastPageItems),
179                    sig = this.model.get("sig");
180
181                queryModel.updateHash(this.updateSignaturesHash(sig, offset, {}));
182            },
183            /**
184            * Switches page selector to the next page and updates hash parameters
185            * @param {Event} event Event object that contains target with selected component value
186            * @memberOf module:searchPageSelector.SearchPageSelectorView
187            * @alias module:searchPageSelector.SearchPageSelectorView#showNextPage
188            */
189            showNextPage: function (event) {
190                event.preventDefault();
191
192                var offset = this.model.get("offset"),
193                    sig = this.model.get("sig");
194
195                if ((offset + this.model.get("pageSize")) < this.model.get("resultsCount")) {
196                    offset += this.model.get("pageSize");
197                }
198
199                queryModel.updateHash(this.updateSignaturesHash(sig, offset, {}));
200            },
201            /**
202            * Switches page selector to the precious page and updates hash parameters
203            * @param {Event} event Event object that contains target with selected component value
204            * @memberOf module:searchPageSelector.SearchPageSelectorView
205            * @alias module:searchPageSelector.SearchPageSelectorView#showPrevPage
206            */
207            showPrevPage: function (event) {
208                event.preventDefault();
209
210                var offset = this.model.get("offset"),
211                    dataProp = $(event.target).data(),
212                    sig = this.model.get("sig");
213
214                if ((offset - this.model.get("pageSize")) >= 0) {
215                    offset -= this.model.get("pageSize");
216                }
217
218                queryModel.updateHash(this.updateSignaturesHash(sig, offset, {}));
219            },
220            /**
221            * Renders view
222            * @memberOf module:searchPageSelector.SearchPageSelectorView
223            * @alias module:searchPageSelector.SearchPageSelectorView#render
224            */
225            render: function () {
226                var inst = this,
227                    dataProp = this.model.get("dataProperties").properties,
228                    resultsCount = this.model.get("resultsCount"),
229                    pageSize = this.model.get("pageSize"),
230                    selectedValue = this.model.get("selectedValue"),
231                    pagesCount = Math.ceil(resultsCount / pageSize),
232                    pages = [],
233                    rangeStart = selectedValue - dataProp.treshold / 2,
234                    rangeEnd = selectedValue + dataProp.treshold / 2,
235                    templateObj;
236
237                if (rangeStart < 0) {
238                    rangeEnd += Math.abs(rangeStart);
239                }
240
241                if (rangeEnd > pagesCount) {
242                    rangeStart -= (rangeEnd - pagesCount);
243                }
244
245                if (dataProp.treshold >= pagesCount) {
246                    for (var i = 0; i < pagesCount; i++) {
247                        pages.push({ number: i + 1, offset: i * pageSize });
248                    }
249                }
250                else {
251                    for (var i = 1; i <= pagesCount; i++) {
252                        if ((i === 1) || (i === pagesCount)) {
253                            pages.push({ number: i, offset: (i - 1) * pageSize });
254                        }
255                        else if ((i >= rangeStart) && (i <= rangeEnd)) {
256                            pages.push({ number: i, offset: (i - 1) * pageSize });
257                        }
258                    }
259                }
260
261                templateObj = {
262                    previous: dataProp.previous,
263                    first: dataProp.first,
264                    next: dataProp.next,
265                    last: dataProp.last,
266                    pages: pages,
267                    selectedValue: selectedValue
268                };
269                var template = _.template(inst.model.get("template"));
270                var templateResult = template({ data: templateObj });
271                this.$el.html(templateResult);
272
273                this.handleButtonState(selectedValue, pagesCount);
274            },
275            /**
276            * Sets up page selectors buttons state depending on selected values
277            * @param {Number} selectedPage number of selected page
278            * @param {Number} pageCount number of pages
279            * @memberOf module:searchPageSelector.SearchPageSelectorView
280            * @alias module:searchPageSelector.SearchPageSelectorView#handleButtonState
281            */
282            handleButtonState: function (selectedPage, pageCount) {
283                this.$el.find(".page-selector-item-last, .page-selector-item-next").removeClass("inactive");
284                this.$el.find(".page-selector-item-first, .page-selector-item-previous").removeClass("inactive");
285
286
287                if (pageCount == 0) {
288                    this.$el.find(".page-selector-item-first, .page-selector-item-previous").addClass("inactive");
289                    this.$el.find(".page-selector-item-last, .page-selector-item-next").addClass("inactive");
290                }
291                else {
292                    if (selectedPage == 1) {
293                        this.$el.find(".page-selector-item-first, .page-selector-item-previous").addClass("inactive");
294                    }
295                    if (selectedPage == pageCount) {
296                        this.$el.find(".page-selector-item-last, .page-selector-item-next").addClass("inactive");
297                    }
298                }
299            },
300            /**
301            * Updates hash and model based on data object
302            * @param {Object} data Data that contains component properties
303            * @memberOf module:searchPageSelector.SearchPageSelectorView
304            * @alias module:searchPageSelector.SearchPageSelectorView#handleLoadedData
305            */
306            handleLoadedData: function (data) {
307                var that = this,
308                    sig = this.model.get("dataProperties").properties.searchResultsSignature.split(','),
309                    hash = queryModel.parseHashParameters(window.location.hash),
310                    newSelectedValue,
311                    param,
312                    hashObj,
313                    i;
314
315                if (typeof data.offset === 'undefined') {
316                    data.offset = 0;
317                }
318
319                for (i = 0; i < sig.length; i++) {
320                    if (encodeURIComponent(sig[i]) === data.searchResultsSignature) {
321                        if (data.pageSize > data.dataCount || data.offset > data.dataCount) {
322                            //When we have less results then page size then show first page
323                            this.updateModelAfterSearch(data, 1);
324                            //Wait till all requests are done and go to first page
325                            setTimeout(function () {
326                                //queryModel.updateHash({e: 0}); //- this will work, but doesn't give us proper browser history
327                                hashObj = queryModel.parseHashParameters(window.location.hash);
328                                param = data.searchResultsSignature !== "" ? data.searchResultsSignature + "_e" : "e";
329                                if (hash[param] !== "0") {
330                                    hashObj[param] = 0;
331                                    Backbone.history.navigate(that.createFirstPageUrlHash(hashObj), { trigger: true, replace: true });
332                                }
333                            }, 100);
334                        } else {
335                            newSelectedValue = Math.ceil(data.offset / data.pageSize) + 1;
336                            this.updateModelAfterSearch(data, newSelectedValue);
337                        }
338                    }
339                }
340            },
341            /**
342            * Calculates hash parameters for first page
343            * @param {Object} data Data that contains component properties
344            * @memberOf module:searchPageSelector.SearchPageSelectorView
345            * @alias module:searchPageSelector.SearchPageSelectorView#createFirstPageUrlHash
346            * @returns {String} hash parameter for first page
347            */
348            createFirstPageUrlHash: function (hashObj) {
349                var hashStr = "";
350
351                var i = 0;
352                _.each(hashObj, function (item, key) {
353                    if (i > 0) {
354                        hashStr += "&";
355                    }
356                    i++;
357                    hashStr += key + "=" + item;
358                });
359
360                return hashStr;
361            }
362        });
363
364    /**
365    * For each page selector on a page creates instance of 
366    * ["SearchPageSelectorModel"]{@link module:searchPageSelector.SearchPageSelectorModel} and 
367    * ["SearchPageSelectorView"]{@link module:searchPageSelector.SearchPageSelectorView} 
368    * @memberOf module:searchPageSelector
369    * @alias module:searchPageSelector.SearchPageSelectorView.init
370    */
371    api.init = function () {
372        if ($("body").hasClass("on-page-editor")) {
373            return;
374        }
375
376        queryModel = XA.component.search.query;
377
378        var searchPageSelector = $(".page-selector:not(.initialized)");
379
380        _.each(searchPageSelector, function (elem) {
381            var $el = $(elem);
382
383            new SearchPageSelectorView({ el: $el, model: new SearchPageSelectorModel });
384            
385            $el.addClass("initialized");
386        });
387    };
388
389    return api;
390
391}(jQuery, document));
392
393XA.register('searchPageSelector', XA.component.search.pageSelector);

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.