1/** 2 * Model for search services 3 * @module SearchServiceModel 4 * @param {jQuery} $ Instance of jQuery 5 * @param {Document} document dom document object 6 * @return {SearchServiceModel} instance of search service model 7*/ 8XA.component.search.service = (function ($, document) { 9 10 'use strict'; 11 12 var searchResultsModels = XA.component.search.results.searchResultModels, 13 urlHelperModel = XA.component.search.url, 14 queryModel = XA.component.search.query, 15 queryParameters = XA.component.search.parameters, 16 apiModel = XA.component.search.ajax, 17 SearchServiceModel; 18 /** 19 * @name module:SearchServiceModel.SearchServiceModel 20 * @constructor 21 * @augments Backbone.Model 22 */ 23 SearchServiceModel = Backbone.Model.extend( 24 /** @lends module:SearchServiceModel.SearchServiceModel.prototype **/ 25 { 26 /** 27 * Default model options 28 * @default 29 */ 30 defaults: { 31 }, 32 /** 33 * Watches for event 'orderChanged' and trigger 34 * ['getData']{@link module:SearchServiceModel.SearchServiceModel#getData} 35 * @listens module:XA.component.search.vent~event:orderChanged 36 * @memberof module:SearchServiceModel.SearchServiceModel 37 */ 38 initialize: function () { 39 var that = this; 40 XA.component.search.vent.on('orderChanged', function (data) { 41 that.getData(data); 42 }); 43 }, 44 /** 45 * If search result model created call 46 * ['getSearchResultsData']{@link module:SearchServiceModel.SearchServiceModel#getSearchResultsData} 47 * in other case call 48 * ['getEndpointAndSearch']{@link module:SearchServiceModel.SearchServiceModel#getEndpointAndSearch} 49 * @param {Object} overrideProps new properties fro overriding 50 * @memberof module:SearchServiceModel.SearchServiceModel 51 * @alias module:SearchServiceModel.SearchServiceModel#getData 52 */ 53 getData: function (overrideProps) { 54 if (searchResultsModels.length > 0) {
55 this.getSearchResultsData(overrideProps); 56 } else { 57 this.getEndpointAndSearch(overrideProps); 58 } 59 }, 60 /** 61 * Processes search result data 62 * @param {Object} overrideProps properties for overriding 63 * @memberof module:SearchServiceModel.SearchServiceModel 64 * @alias module:SearchServiceModel.SearchServiceModel#getSearchResultsData 65 */ 66 getSearchResultsData: function (overrideProps) { 67 var hash = queryModel.parseHashParameters(window.location.hash), 68 that = this, 69 defaultSortOrder, 70 offsetSignature, 71 searchResultsDefaultPageSize, 72 searchResultsDefaultVariant, 73 signature, 74 mergedProps, 75 url; 76 77 _.each(searchResultsModels, function (searchModel) { 78 signature = searchModel.get('dataProperties').sig !== null 79 ? encodeURIComponent(searchModel.get('dataProperties').sig) 80 : ""; 81 offsetSignature = signature !== '' ? signature + "_e" : "e"; 82 83 if (!searchModel.get('dataProperties').autoFireSearch) { 84 //If hash is not present or no criteria with search model signature is present in hash, then do not fire search 85 if (!hash || !queryModel.isSignaturePresentInHash(hash, signature)) { 86 return; 87 } 88 } 89 90 defaultSortOrder = searchModel.get('dataProperties').defaultSortOrder; 91 searchResultsDefaultPageSize = searchModel.get('dataProperties').p; 92 searchResultsDefaultVariant = searchModel.get('dataProperties').v; 93 94 //if we have singleRequestMode with signature, then we are getting data just for that signature 95 if (typeof overrideProps !== "undefined" && 96 overrideProps.hasOwnProperty("singleRequestMode") && 97 overrideProps["singleRequestMode"] != signature) { 98 return; 99 } 100 101 //if there is no page size param in the query, but we have page size component on the page, then take 102 //default page size or first (if default isn't set) 103 hash = that.getDefaultDefaultPageSize(signature, searchResultsDefaultPageSize, hash); 104 105 //in case of facet that filters items by language 106 //when someone is filtering by certain language, and removes that filter, then without 107 //this if statement, search results language parameter would not be considered - because l="" from hash object 108 //will override default language from dataProperties 109 if (hash.hasOwnProperty('l') && hash.l === '') { 110 hash.l = searchModel.get('dataProperties').l; 111 } 112 113 mergedProps = $.extend({}, searchModel.get('dataProperties'), hash); 114 mergedProps = $.extend(mergedProps, overrideProps); 115 116 if (mergedProps.hasOwnProperty('loadMore')) { 117 searchModel.set('loadMore', true); 118 delete mergedProps.loadMore; 119 120 var newOffset = searchModel.get('loadMoreOffset') + mergedProps.p; 121 searchModel.set('loadMoreOffset', newOffset); 122 mergedProps[offsetSignature] = newOffset; 123 } 124 else if (searchModel.get('loadMoreOffset')) { //if results reload is caused by variant change, loadMoreOffset should be considered in request, so after changing variant, the same number of results will be visible 125 if (mergedProps.p !== 0) { 126 mergedProps.p = mergedProps.p * (1 + searchModel.get('loadMoreOffset') / mergedProps.p); 127 mergedProps[offsetSignature] = 0; 128 searchModel.set('loadMoreOffset', 0); 129 } 130 delete mergedProps.variantChanged; 131 } 132 133 mergedProps = that.getSortOrder(signature, mergedProps, defaultSortOrder); 134 mergedProps = that.setVariant(signature, mergedProps, searchResultsDefaultVariant); 135 136 url = urlHelperModel.createSearchUrl(mergedProps, signature); 137 if (!url) { 138 return; 139 } 140 141 if (!searchModel.checkBlockingRequest()) { 142 searchModel.blockRequests(true); 143 XA.component.search.vent.trigger('results-loading', searchModel.cid); 144 apiModel.getData({ 145 callback: function (data) { 146 data.Signature = data.Signature !== null ? data.Signature : ''; 147 XA.component.search.vent.trigger('results-loaded', { 148 dataCount: data.Count, 149 data: data.Results, 150 pageSize: data.Signature !== '' && mergedProps.hasOwnProperty(data.Signature + '_p') ? mergedProps[data.Signature + '_p'] : mergedProps.p, 151 offset: data.Signature !== '' && mergedProps.hasOwnProperty(data.Signature + '_e') ? mergedProps[data.Signature + '_e'] : mergedProps.e, 152 searchResultsSignature: data.Signature,
153 loadMore: searchModel.get('loadMore') 154 }); 155 }, 156 url: url 157 }); 158 } 159 }); 160 }, 161 /** 162 * Processes search result data. Call for apiModel.getData 163 * @param {Object} overrideProps properties for overriding 164 * @fires XA.component.search.vent#results-loaded 165 * @listens module:XA.component.search.vent~event:orderChanged 166 * @memberof module:SearchServiceModel.SearchServiceModel 167 * @alias module:SearchServiceModel.SearchServiceModel#getSearchData 168 */ 169 getSearchData: function (overrideProps) { 170 var hash = queryModel.parseHashParameters(window.location.hash), 171 mergedProps = $.extend({}, hash, mergedProps, overrideProps), 172 signatures = [], 173 firstSortingOption, 174 url, 175 i; 176 177 178 mergedProps = this.getDefaultDefaultPageSize("", 0, mergedProps); 179 180 181 //if there is no sort param in the query, but we have sort results component on the page, then take first sorting option 182 if (!mergedProps.hasOwnProperty('o') && typeof XA.component.search.sort !== 'undefined') { 183 firstSortingOption = XA.component.search.sort.getFirstSortingOption(); 184 if (firstSortingOption !== -1) { 185 mergedProps.o = firstSortingOption; 186 } 187 } 188 189 //currently we are taking endpoint from Map component (atm it's only which can handle showing of search results) 190 mergedProps.endpoint = XA.component.map.getSearchEndpoint(); 191 //the same with signature 192 signatures = XA.component.map.getSignatures(); 193 194 for (i = 0; i < signatures.length; i++) { 195 mergedProps.sig = signatures[i]; 196 url = urlHelperModel.createSearchUrl(mergedProps, signatures[i]); 197 198 if (!url) { 199 return; 200 } 201 202 apiModel.getData({ 203 callback: function (data) { 204 data.Signature = data.Signature !== null ? data.Signature : ''; 205 XA.component.search.vent.trigger('results-loaded', { 206 dataCount: data.Count, 207 data: data.Results, 208 pageSize: mergedProps.p, 209 offset: 0, 210 searchResultsSignature: data.Signature 211 }); 212 }, 213 url: url 214 }); 215 } 216 }, 217 /** 218 * Checks if map component exists and getSearchEndpoint returns not undefined value. If yes 219 * call ["getSearchData"]{@link module:SearchServiceModel.SearchServiceModel#getSearchData} 220 * @memberof module:SearchServiceModel.SearchServiceModel 221 * @alias module:SearchServiceModel.SearchServiceModel#getEndpointAndSearch 222 */ 223 getEndpointAndSearch: function () { 224 if (XA.component.map && typeof (XA.component.map.getSearchEndpoint()) !== 'undefined') {
225 this.getSearchData(); 226 } else { 227 setTimeout(this.getEndpointAndSearch.bind(this), 100); 228 } 229 }, 230 /** 231 * Sorts search result due to selected properties 232 * @param {String} signature component signature 233 * @param {Object} mergedProps 234 * @param {String} searchResultsDefaultSortOrder default sorting order 235 * @memberof module:SearchServiceModel.SearchServiceModel 236 * @alias module:SearchServiceModel.SearchServiceModel#getSortOrder 237 * @returns {Object} merged properties 238 */ 239 getSortOrder: function (signature, mergedProps, searchResultsDefaultSortOrder) { 240 var firstSortingOption = XA.component.search.sort.getFirstSortingOption(signature), 241 paramName = signature !== '' ? signature + '_o' : 'o', 242 obj = {}, 243 defaultSortOrder = "", 244 defaultSigned = {}; 245 246 247 if (firstSortingOption !== -1) { 248 defaultSortOrder = firstSortingOption; 249 } else if (searchResultsDefaultSortOrder !== "") { 250 defaultSortOrder = searchResultsDefaultSortOrder; 251 } 252 253 if (!mergedProps.hasOwnProperty(paramName) && defaultSortOrder !== "") { 254 delete mergedProps.defaultSortOrder; 255 delete mergedProps.o; 256 257 mergedProps[paramName] = defaultSortOrder; 258 obj[paramName] = defaultSortOrder; 259 } 260 defaultSigned[paramName] = defaultSortOrder; 261 queryParameters.registerDefault(defaultSigned); 262 263 return mergedProps; 264 }, 265 266 /** 267 * Sets default page size into hash 268 * @param {String} signature component signature 269 * @param {Number} searchResultsDefaultPageSize default page size 270 * @param {Object} hash hash represented as an object 271 * @memberof module:SearchServiceModel.SearchServiceModel 272 * @alias module:SearchServiceModel.SearchServiceModel#getDefaultDefaultPageSize 273 * @returns {Object} hash object 274 */ 275 getDefaultDefaultPageSize: function (signature, searchResultsDefaultPageSize, hash) { 276 var defaultPageSizes = XA.component.search.pageSize.getDefaultPageSizes(), 277 paramName = signature !== "" ? signature + "_p" : "p", 278 pageSizes; 279 280 if (!hash.hasOwnProperty(paramName) && typeof XA.component.search.pageSize !== 'undefined') { 281 if (defaultPageSizes !== -1) { 282 pageSizes = defaultPageSizes.filter(function (x) { 283 return x.signatures.indexOf(signature) !== -1; 284 }); 285 if (pageSizes.length > 0) { 286 hash[paramName] = pageSizes[0].defaultPageSize; 287 } 288 } 289 } 290 291 if (!hash.hasOwnProperty(paramName) && searchResultsDefaultPageSize != 0) { 292 hash[paramName] = searchResultsDefaultPageSize; 293 } 294 295 var defaultParam = {}; 296 defaultParam[paramName] = searchResultsDefaultPageSize; 297 queryParameters.registerDefault(defaultParam); 298 return hash; 299 }, 300 /** 301 * Sets variant of view search result based on variant selector component 302 * @param {String} signature component signature 303 * @param {Number} searchResultsDefaultPageSize default page size 304 * @param {Object} hash hash represented as an object 305 * @memberof module:SearchServiceModel.SearchServiceModel 306 * @alias module:SearchServiceModel.SearchServiceModel#setVariant 307 * @returns {Object} hash object 308 */ 309 setVariant: function (signature, mergedProps, searchResultsDefaultVariant) { 310 var variantMappings = XA.component.search.variantFilter.getVariantMappings(signature), 311 paramName = signature !== "" ? signature + "_v" : "v", 312 variantIndex; 313 314 if (signature === "" && $.isEmptyObject(variantMappings)
314) { 315 //there is no signature, and no variant selector on the page, therefore, do nothing - mergedPropes should have v param 316 } else if (signature === "" && mergedProps.hasOwnProperty(paramName) && variantMappings.hasOwnProperty(mergedProps[paramName])) { 317 //there is no signature, but there is variant selector on the page, and it was clicked 318 mergedProps[paramName] = variantMappings[mergedProps[paramName]].id; 319 } else if (signature === "" && variantMappings.hasOwnProperty(0)) { 320 //there is no signature, but there is variant selector on the page, therefore take its first variant 321 mergedProps[paramName] = variantMappings[0].id; 322 } else { 323 delete mergedProps.v; 324 if (mergedProps.hasOwnProperty(paramName)) { 325 //variant switcher was clicked 326 mergedProps[paramName] = variantMappings[mergedProps[paramName]].id; 327 } else { 328 //if there is variant selector on the page, take first variant form the component, otherwise use search results default variant 329 if (variantMappings.hasOwnProperty(0)) { 330 mergedProps[paramName] = variantMappings[0].id; 331 } else { 332 mergedProps[paramName] = searchResultsDefaultVariant; 333 } 334 } 335 } 336 337 var defaultVariant = {}; 338 defaultVariant[paramName] = 0; 339 queryParameters.registerDefault(defaultVariant); 340 341 return mergedProps; 342 } 343 }); 344 345 return new SearchServiceModel(); 346 347}(jQuery, document));
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.