1/** 2 * Facet dropdown component functionality 3 * @module dropdown 4 * @param {jQuery} $ Instance of jQuery 5 * @param {Document} document dom document object 6 * @return {Object} list of methods for working with component dropdown 7*/ 8XA.component.search.facet.dropdown = (function ($, document) { 9 10 "use strict"; 11 /** 12 * This object stores all public api methods 13 * @type {Object.<Methods>} 14 * @memberOf module:dropdown 15 */ 16 var api = {}, 17 urlHelperModel, 18 queryModel, 19 initialized = false; 20 /** 21 * @name module:dropdown.FacetDropdownModel 22 * @constructor 23 * @augments Backbone.Model 24 */ 25 var FacetDropdownModel = XA.component.search.baseModel.extend( 26 /** @lends module:dropdown.FacetDropdownModel.prototype **/ 27 { 28 /** 29 * Default model options 30 * @default 31 */ 32 defaults: { 33 template: "<% _.forEach(results, function(result){" + 34 "%><option data-facetName=\"<%= result.Name !== '' ? encodeURIComponent(result.Name) : '_empty_' %>\" <%= result.Selected !== undefined ? 'selected' : '' %> ><%= result.Name !== '' ? result.Name.replaceAll('zPast-Participant', 'Past-Participant').replaceAll('--', '(HYPHEN)').replaceAll('-', ' ').replaceAll('_','/').replaceAll('~','&').replaceAll('(HYPHEN)','-') : emptyText %> (<%= result.Count %>)</option><%" + 35 "}); %>", 36 dataProperties: {}, 37 blockNextRequest: false, 38 resultData: {}, 39 optionSelected: false, 40 sig: [] 41 }, 42 /** 43 * Listens to changes on facets and hash 44 * @listens module:XA.component.search.vent~event:facet-data-loaded 45 * @listens module:XA.component.search.vent~event:facet-data-filtered 46 * @listens module:XA.component.search.vent~event:facet-data-partial-filtered 47 * @listens module:XA.component.search.vent~event:hashChanged 48 */ 49 initialize: function () { 50 //Event to get data at the begining or when there are no hash parameters in the url - one request for all controls 51 XA.component.search.vent.on("facet-data-loaded", this.processData.bind(this)); 52 53 //Event to get filtered data 54 XA.component.search.vent.on("facet-data-filtered", this.processData.bind(this)); 55 56 //If the url contains a hash, and facet name control is clicked, then we have to listen for partial filtering 57 XA.component.search.vent.on("facet-data-partial-filtered", this.processData.bind(this)); 58 59 //Event after change of hash 60 XA.component.search.vent.on("hashChanged", this.updateComponent.bind(this)); 61 }, 62 /** 63 * Toggle value of blockNextRequest variable 64 * @memberof module:dropdown.FacetDropdownModel 65 * @alias module:dropdown.FacetDropdownModel#toggleBlockRequests 66 */ 67 toggleBlockRequests: function () { 68 var state = this.get("blockNextRequest"); 69 this.set(this.get("blockNextRequest"), !state); 70 }, 71 /** 72 * Processes data that comes as parameter update 73 * model and sorts facets 74 * @param {Object} data Data from server with facet values 75 * @memberof module:dropdown.FacetDropdownModel 76 * @alias module:dropdown.FacetDropdownModel#processData 77 */ 78 processData: function (data) { 79 var inst = this, 80 hashObj = queryModel.parseHashParameters(window.location.hash), 81 sig = inst.get("sig"), 82 dataProperties = this.get("dataProperties"), 83 searchResultsSignature = dataProperties.searchResultsSignature.split(','), 84 sortOrder = dataProperties.sortOrder, 85 facet = dataProperties.f, 86 facetItem, 87 facedData, 88 i, j; 89 90 for (j = 0; j < searchResultsSignature.length; j++) { 91 if (data.Facets.length > 0 && (data.Signature === searchResultsSignature[j]) || data.Signature === "" || data.Signature === null) { 92 facedData = _.find(data.Facets, function (f) { 93 return f.Key.toLowerCase() === facet.toLowerCase(); 94 }); 95 96 if (facedData === undefined) { 97 return; 98 } 99 100 for (i = 0; i < sig.length; i++) { 101 if (!jQuery.isEmptyObject(_.pick(hashObj, sig[i]))) { 102 if (hashObj[sig[i]] !== "") { 103 facetItem = _.where(facedData.Values, { Name: hashObj[sig[i]] }); 104 if (facetItem.length === 0) { 105 facetItem = _.where(facedData.Values, { Name: "" }); 106 } 107 if (facetItem.length > 0) { 108 facetItem[0].Selected = true; 109 inst.optionSelected = true; 110 } 111 } 112 } 113 } 114 115 this.sortFacetArray(sortOrder, facedData.Values); 116 inst.set({ resultData: facedData.Values }); 117 } 118 } 119 }, 120 /** 121 * Sets option selected value to model based on hash 122 * @param {Object} hash Hash stored as an object 123 * @memberof module:dropdown.FacetDropdownModel 124 * @alias module:dropdown.FacetDropdownModel#updateComponent 125 */
126 updateComponent: function (hash) { 127 var sig = this.get("sig"), i, facetPart; 128 129 for (i = 0; i < sig.length; i++) { 130 facetPart = sig[i].toLowerCase(); 131 if (hash.hasOwnProperty(facetPart) && hash[facetPart] !== "") { 132 this.set({ optionSelected: true }); 133 } else { 134 this.set({ optionSelected: false }); 135 } 136 } 137 } 138 }); 139 /** 140 * @name module:dropdown.FacetDropdownView 141 * @constructor 142 * @augments Backbone.View 143 */ 144 var FacetDropdownView = XA.component.search.baseView.extend( 145 /** @lends module:dropdown.FacetDropdownView.prototype **/ 146 147 { 148 /** 149 * Initially sets data to model and watches events on which 150 * view should be updated 151 * @listens module:dropdown.FacetDropdownModel~event:change 152 * @memberof module:dropdown.FacetDropdownView 153 * @alias module:dropdown.FacetDropdownView#initialize 154 */ 155 initialize: function () { 156 var dataProperties = this.$el.data(); 157 this.properties = dataProperties.properties; 158 159 if (this.model) { 160 this.model.set({ dataProperties: this.properties }); 161 this.model.set("sig", this.translateSignatures(this.properties.searchResultsSignature, this.properties.f)); 162 } 163 164 this.model.on("change", this.render, this); 165 }, 166 /** 167 * list of events for Backbone View 168 * @memberof module:dropdown.FacetDropdownView 169 * @alias module:dropdown.FacetDropdownView#events 170 */ 171 events: { 172 "change .facet-dropdown-select": "updateFacet", 173 "click .bottom-remove-filter, .clear-filter": "clearFilter" 174 }, 175 /** 176 * Calculates value of optionSelected value in model and calls 177 * ["updateSignaturesHash"]{@link module dropdown.FacetDropdownView#updateSignaturesHash} 178 * inside of ["updateHash"]{@link module:searchQuery.updateHash} 179 * @memberof module:dropdown.FacetDropdownView 180 * @alias module:dropdown.FacetDropdownView#updateFacet 181 */ 182 updateFacet: function (param) { 183 var $selectedOption = this.$el.find(".facet-dropdown-select").find("option:selected"), 184 facetName = decodeURIComponent($selectedOption.data("facetname")), 185 sig = this.model.get("sig"); 186 187 if (facetName === "") { 188 this.model.set({ optionSelected: false }); 189 } else { 190 this.model.set({ optionSelected: true }); 191 } 192 queryModel.updateHash(this.updateSignaturesHash(sig, facetName, {})); 193 }, 194 /** 195 * Renders view 196 * @memberof module:dropdown.FacetDropdownView 197 * @alias module:dropdown.FacetDropdownView#render 198 */ 199 render: function () { 200 var inst = this, 201 resultData = inst.model.get("resultData"), 202 dropdown = this.$el.find(".facet-dropdown-select"), 203 emptyValueText = inst.model.get('dataProperties').emptyValueText, 204 facetClose = this.$el.find(".facet-heading > span"), 205 notSelectedOption = dropdown.find("option:first"), 206 notSelectedOptionEntry = $("<option />"), 207 template = _.template(inst.model.get("template")), 208 templateResult = template({ results: resultData, emptyText: emptyValueText }); 209 210 this.manageVisibilityByData(this.$el, resultData) 211 notSelectedOptionEntry.text(notSelectedOption.text()); 212 notSelectedOptionEntry.data("facetname", ""); 213 214 if (this.model.get("optionSelected")) { 215 facetClose.addClass("has-active-facet"); 216 } else if (notSelectedOption.data("facetname") === "") { 217 facetClose.removeClass("has-active-facet"); 218 } 219 220 dropdown.empty().append(notSelectedOptionEntry).append(templateResult); 221 }, 222 /** 223 * Clears selected filters and updates hash by calling 224 * ["updateHash"]{@link module:searchQuery.updateHash} 225 * @memberof module:dropdown.FacetDropdownView 226 * @alias module:dropdown.FacetDropdownView#clearFilter 227 */ 228 clearFilter: function () { 229 var dropdown = this.$el.find(".facet-dropdown-select"), 230 facetClose = this.$el.find(".facet-heading > span"), 231 sig = this.model.get("sig"); 232
233 queryModel.updateHash(this.updateSignaturesHash(sig, "", {})); 234 this.model.set({ optionSelected: false }); 235 facetClose.removeClass("has-active-facet"); 236 dropdown.val(dropdown.find("option:first").val()); 237 } 238 }); 239 /** 240 * For each search dropdown component on a page creates instance of 241 * ["FacetDropdownModel"]{@link module:dropdown.FacetDropdownModel} and 242 * ["FacetDropdownView"]{@link module:dropdown.FacetDropdownView} 243 * @memberOf module:dropdown 244 * @alias module:dropdown.init 245 */ 246 247 api.init = function () { 248 if ($("body").hasClass("on-page-editor") || initialized) { 249 return; 250 } 251 252 queryModel = XA.component.search.query; 253 urlHelperModel = XA.component.search.url; 254 255 var facetDropdownList = $(".facet-dropdown"); 256 _.each(facetDropdownList, function (elem) { 257 var view = new FacetDropdownView({ el: $(elem), model: new FacetDropdownModel() }); 258 }); 259 260 initialized = true; 261 }; 262 /** 263 * 264 * @memberOf module:dropdown 265 * @alias module:dropdown.getFacetDataRequestInfo 266 * @returns {Array<FacetDataRequestInfo>} facet data needed for request 267 */ 268 api.getFacetDataRequestInfo = function () { 269 var facetDropdownList = $(".facet-dropdown"), 270 result = []; 271 272 _.each(facetDropdownList, function (elem) { 273 var properties = $(elem).data().properties, 274 signatures = properties.searchResultsSignature.split(','), 275 i; 276 277 for (i = 0; i < signatures.length; i++) { 278 result.push({ 279 signature: signatures[i] === null ? "" : signatures[i], 280 facetName: properties.f, 281 endpoint: properties.endpoint, 282 filterWithoutMe: true 283 }); 284 } 285 }); 286 287 return result; 288 }; 289 290 return api; 291 292}(jQuery, document)); 293 294XA.register("facetDropdown", XA.component.search.facet.dropdown);
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.