1(function($) { 2 AjaxSolr.RiotSolrFacetWidget = AjaxSolr.AbstractFacetWidget.extend({ 3 activeFacets: [], 4 5 initStore: function() { 6 /* http://wiki.apache.org/solr/SimpleFacetParameters */ 7 var parameters = [ 8 'facet.prefix', 9 'facet.sort', 10 'facet.limit', 11 'facet.offset', 12 'facet.mincount', 13 'facet.missing', 14 'facet.method', 15 'facet.enum.cache.minDf', 16 ]; 17 18 this.manager.store.addByValue('facet', true); 19 20 // Set facet.field, facet.date or facet.range to truthy values to add 21 // related per-field parameters to the parameter store. 22 if (this['facet.field'] !== undefined) { 23 var f; 24 if (this.operator === 'or') { 25 f = '{!ex=' + this.id + '}' + this.field; 26 } else { 27 f = this.field; 28 } 29 this.manager.store.addByValue('facet.field', f); 30 } else if (this['facet.date'] !== undefined) { 31 this.manager.store.addByValue('facet.date', this.field); 32 parameters = parameters.concat([ 33 'facet.date.start', 34 'facet.date.end', 35 'facet.date.gap', 36 'facet.date.hardend', 37 'facet.date.other', 38 'facet.date.include', 39 ]); 40 } else if (this['facet.range'] !== undefined) { 41 this.manager.store.addByValue('facet.range', this.field); 42 parameters = parameters.concat([ 43 'facet.range.start', 44 'facet.range.end', 45 'facet.range.gap', 46 'facet.range.hardend', 47 'facet.range.other', 48 'facet.range.include', 49 ]); 50 } 51 52 for (var i = 0, l = parameters.length; i < l; i++) { 53 if (this[parameters[i]] !== undefined) { 54 this.manager.store.addByValue('f.' + this.field + '.' + parameters[i], this[parameters[i]]); 55 } 56 } 57 }, 58 59 /** 60 * Set the current query param for this widget. 61 * @param value 62 * @returns {*|Boolean} 63 */ 64 set: function(value) { 65 return this.changeSelection(function() { 66 var a = this.manager.store.removeByValue( 67 'fq', 68 new RegExp('^-?' + this.manager.regexEscape(this.getTag()) + this.manager.regexEscape(this.field) + ':') 69 ), 70 b = this.manager.store.addByValue('fq', this.fq(value)); 71 console.log(value); 72 return a || b; 73 }); 74 }, 75 76 /** 77 * Adds one or more filter queries. 78 * 79 * @returns {Boolean} Whether a filter query was added. 80 */ 81 addMulti:function(value) { 82 if (RiotSolrAppTracker) { 83 RiotSolrAppTracker.trackEvent({ 84 category: 'Search - ' + this.getLabel(), 85 action: 'Facet Set', 86 label: value, 87 entityInfo: this.manager.bundles 88 ? this.manager.entityType + ' - ' + this.manager.bundles.join(', ') 89 : this.manager.entityType, 90 }); 91 } 92 93 var self = this, 94 fq, 95 or = [], 96 rgx = new RegExp('.*' + self.manager.regexEscape(self.field)); 97 98 return this.changeSelection(function() { 99 if (self.operator !== 'or' || (!this.activeFacets.length && !Array.isArray(value))) { 100 return this.manager.store.addByValue('fq', this.fq(value)); 101 } 102 103 fq = self.activeFacets.map(function(i) { 104 return i.facet; 105 }); 106 107 if(Array.isArray(value)) { 108 fq = fq.concat(value); 109 } 110 else { 111 fq.push(value); 112 } 113 114 this.manager.store.removeByValue('fq', rgx); 115 116 for (var f in fq) { 117 or.push(AjaxSolr.Parameter.escapeValue(fq[f])); 118 } 119 120 return this.manager.store.addByValue('fq', self.getTag() + self.field + ':( ' + or.join(' OR ') + ')'); 121 }); 122 }, 123 124 /** 125 * Adds a filter query. 126 * 127 * @returns {Boolean} Whether a filter query was added. 128 */ 129 add: function(value) { 130 if (RiotSolrAppTracker) { 131 RiotSolrAppTracker.trackEvent({ 132 category: 'Search - ' + this.getLabel(), 133 action: 'Facet Set', 134 label: value, 135 entityInfo: this.manager.bundles 136 ? this.manager.entityType + ' - ' + this.manager.bundles.join(', ') 137 : this.manager.entityType, 138 }); 139 } 140 141 var self = this, 142 fq, 143 or = [], 144 rgx = new RegExp('.*' + self.manager.regexEscape(self.field)); 145 146 return this.changeSelection(function() { 147 if (self.operator !== 'or' || !this.activeFacets.length) { 148 return this.manager.store.addByValue('fq', this.fq(value)); 149 } 150 151 fq = self.activeFacets.map(function(i) { 152 return i.facet; 153 }); 154 155 fq.push(value); 156 157 this.manager.store.removeByValue('fq', rgx); 158 159 for (var f in fq) { 160 or.push(AjaxSolr.Parameter.escapeValue(fq[f])); 161 } 162 163 return this.manager.store.addByValue('fq', self.getTag() + self.field + ':( ' + or.join(' OR ') + ')'); 164 }); 165 }, 166 167 /** 168 * Removes all filter queries. 169 * 170 * @returns {Boolean} Whether all filter queries have been removed. 171 */ 172 removeAll: function() { 173 return this.changeSelection(function() { 174 var rgx = new RegExp('.*' + this.manager.regexEscape(this.field) + ':'); 175 return this.manager.store.removeByValue('fq', rgx); 176 }); 177 }, 178 179 /** 180 * Removes a filter query. 181 * 182 * @returns {Boolean} Whether a filter query was removed. 183 */ 184 remove: function(value) { 185 if (RiotSolrAppTracker) { 186 RiotSolrAppTracker.trackEvent({ 187 category: 'Search - ' + this.getLabel(), 188 action: 'Facet Unset', 189 label: value, 190 entityInfo: this.manager.bundles 191 ? this.manager.entityType + ' - ' + this.manager.bundles.join(', ') 192 : this.manager.entityType, 193 }); 194 } 195 196 return this.changeSelection(function() { 197 var rgx = new RegExp('.*' + this.manager.regexEscape(this.field) + ':'), 198 or = [], 199 cond; 200 201 for (var f in this.activeFacets) { 202 if (value === this.activeFacets[f].facet) { 203 this.activeFacets.splice(f, 1); 204 if (!this.activeFacets.length) { 205 return this.manager.store.removeByValue('fq', rgx); 206 } 207 } 208 } 209 210 if (this.operator === 'or' && this.activeFacets.length) { 211 this.manager.store.removeByValue('fq', rgx); 212 or = this.activeFacets.map(function(f, i) { 213 return AjaxSolr.Parameter.escapeValue(f.facet); 214 }); 215 cond = or.length > 1 ? '( ' + or.join(' OR ') + ')' : or.join(''); 216 return this.manager.store.addByValue('fq', this.fq(cond)); 217 } 218 return this.manager.store.removeByValue('fq', this.fq(value)); 219 }); 220 }, 221 222 /** 223 * Removes all filter queries using the widget's facet field. 224 * 225 * @returns {Boolean} Whether a filter query was removed. 226 */ 227 clear: function() { 228 return this.changeSelection(function() { 229 return this.manager.store.removeByValue( 230 'fq', 231 new RegExp('^-?' + AjaxSolr.Parameter.escapeValue(this.field) + ':') 232 ); 233 }); 234 }, 235 236 /** 237 * Callback function executed after any request made by this widget's manager. 238 */ 239 afterRequest: function() { 240 if ( 241 this.manager.response.facet_counts === undefined || 242 this.manager.response.facet_counts.facet_fields[this.field] === undefined 243 ) { 244 return; 245 } 246 var maxCount = 0; 247 var objectedItems = []; 248 var self = this; 249 250 for (var facet in this.manager.response.facet_counts.facet_fields[this.field]) { 251 var count = parseInt(this.manager.response.facet_counts.facet_fields[this.field][facet]); 252 if (count > maxCount) { 253 maxCount = count; 254 } 255 objectedItems.push({ facet: facet, count: count }); 256 } 257 258 objectedItems.sort(function(a, b) { 259 return a.facet < b.facet ? -1 : 1; 260 }); 261
262 var eventParams = { 263 observable: this.observable, 264 instance: this, 265 field: this.field, 266 widget: this.observable.opts.widget, 267 items: objectedItems, 268 }; 269 270 this.activeFacets = objectedItems.filter(function(i) { 271 return self.isActive(i.facet); 272 }); 273 274 this.observable.trigger(this.observable.opts.widget + 'Update', eventParams); 275 }, 276 277 /** 278 * Properly format a string for use in a FQ query. 279 * @param value 280 * @param exclude 281 * @returns {string} 282 */ 283 fq: function(value, exclude) { 284 return (exclude ? '-' : '') + this.getTag() + this.field + ':' + AjaxSolr.Parameter.escapeValue(value); 285 }, 286 287 /** 288 * Get the {!tag} for this widget. 289 * @returns {string} 290 */ 291 getTag: function() { 292 return '{!tag=RiotSolrWidget,' + this.id + '}'; 293 }, 294 295 /** 296 * Whether this widget is active in the current query. 297 * @param facetValue 298 * @returns {boolean} 299 */ 300 isActive: function(facetValue) { 301 var v, r, fq; 302 v = AjaxSolr.Parameter.escapeValue(facetValue); 303 r = new RegExp(this.manager.regexEscape(this.getTag()) + '.*:(\\( |\\(.* OR )?' + this.manager.regexEscape(v)); 304 fq = this.manager.store.find('fq', r); 305 return !!fq; 306 }, 307 308 /** 309 * Get this widgets label 310 */ 311 getLabel: function() { 312 if (this.observable && this.observable.opts.label) { 313 return this.observable.opts.label; 314 } 315 return this.label; 316 }, 317 318 /** 319 * Static function for extracting values from a query string 320 * @param str 321 * @returns {*} 322 */ 323 getValues: function(str) { 324 var val = str.split(':').pop().replace(/"|'|\(|\)/g, ''); 325 if (this.operator === 'or') { 326 return val.split('OR').map(function(val) { 327 return val.trim(); 328 }); 329 } 330 return [val]; 331 }, 332 333 /** 334 * Get the current list of values for ths widget instance 335 * @returns {Array} 336 */ 337 getCurrent: function(getValue) { 338 var self = this, 339 vals = this.getFQ(), 340 fq = this.manager.store.get('fq'); 341 342 if (!vals.length) { 343 return []; 344 } 345 346 return vals.map(function getValues(valIndex) { 347 return getValue ? self.getValues(fq[valIndex].value) : fq[valIndex].value; 348 }); 349 }, 350 351 /** 352 * Formats the current search label for this widget 353 * @returns {Array} 354 */ 355 formatCurrentSearchLabel: function() { 356 var self = this, 357 vals = this.getCurrent(true); 358 359 if (!vals.length) { 360 return []; 361 } 362 363 return vals 364 .reduce(function flatten(a, b) { 365 return a.concat(b); 366 }, []) 367 .map(function transformValues(val) { 368 return { 369 facet: self.fq(val), 370 label: val, 371 remove: function() { 372 var facet = self.getValues(this.facet).shift(); 373 self.remove(facet); 374 self.doRequest(); 375 }, 376 }; 377 }); 378 }, 379 380 /** 381 * Get the current FQ parameter for this widget 382 */ 383 getFQ: function() { 384 if (this.field) { 385 return this.manager.store.find('fq', new RegExp('^.*' + this.manager.regexEscape(this.field) + ':')); 386 } 387 }, 388 }); 389})(jQuery);
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.