1 // $Id$
  2 
  3 /**
  4  * Baseclass for all facet widgets.
  5  *
  6  * @class AbstractFacetWidget
  7  * @augments AjaxSolr.AbstractWidget
  8  */
  9 AjaxSolr.AbstractFacetWidget = AjaxSolr.AbstractWidget.extend(
 10   /** @lends AjaxSolr.AbstractFacetWidget.prototype */
 11   {
 12   /**
 13    * The field to facet on.
 14    *
 15    * @field
 16    * @public
 17    * @type String
 18    */
 19   field: null,
 20 
 21   /**
 22    * @returns {Boolean} Whether any filter queries have been set using this
 23    *   widget's facet field.
 24    */
 25   isEmpty: function () {
 26     return !this.manager.store.find('fq', new RegExp('^-?' + this.field + ':'));
 27   },
 28 
 29   /**
 30    * Adds a filter query.
 31    *
 32    * @returns {Boolean} Whether a filter query was added.
 33    */
 34   add: function (value) {
 35     return this.changeSelection(function () {
 36       return this.manager.store.addByValue('fq', this.fq(value));
 37     });
 38   },
 39 
 40   /**
 41    * Removes a filter query.
 42    *
 43    * @returns {Boolean} Whether a filter query was removed.
 44    */
 45   remove: function (value) {
 46     return this.changeSelection(function () {
 47       return this.manager.store.removeByValue('fq', this.fq(value));
 48     });
 49   },
 50 
 51   /**
 52    * Removes all filter queries using the widget's facet field.
 53    *
 54    * @returns {Boolean} Whether a filter query was removed.
 55    */
 56   clear: function () {
 57     return this.changeSelection(function () {
 58       return this.manager.store.removeByValue('fq', new RegExp('^-?' + this.field + ':'));
 59     });
 60   },
 61 
 62   /**
 63    * Helper for selection functions.
 64    *
 65    * @param {Function} Selection function to call.
 66    * @returns {Boolean} Whether the selection changed.
 67    */
 68   changeSelection: function (func) {
 69     changed = func.apply(this);
 70     if (changed) {
 71       this.afterChangeSelection();
 72     }
 73     return changed;
 74   },
 75 
 76   /**
 77    * An abstract hook for child implementations.
 78    *
 79    * <p>This method is executed after the filter queries change.</p>
 80    */
 81   afterChangeSelection: function () {},
 82 
 83   /**
 84    * @param {String} value The value.
 85    * @returns {Function} Sends a request to Solr if it successfully adds a
 86    *   filter query with the given value.
 87    */
 88   clickHandler: function (value) {
 89     var self = this;
 90     return function () {
 91       if (self.add(value)) {
 92         self.manager.doRequest(0);
 93       }
 94       return false;
 95     }
 96   },
 97 
 98   /**
 99    * @param {String} value The value.
100    * @returns {Function} Sends a request to Solr if it successfully removes a
101    *   filter query with the given value.
102    */
103   unclickHandler: function (value) {
104     var self = this;
105     return function () {
106       if (self.remove(value)) {
107         self.manager.doRequest(0);
108       }
109       return false;
110     }
111   },
112 
113   /**
114    * @param {String} value The facet value.
115    * @param {Boolean} exclude Whether to exclude this fq parameter value.
116    * @returns {String} An fq parameter value.
117    */
118   fq: function (value, exclude) {
119     // If the field value has a space or a colon in it, wrap it in quotes,
120     // unless it is a range query.
121     if (value.match(/[ :]/) && !value.match(/[\[\{]\S+ TO \S+[\]\}]/)) {
122       value = '"' + value + '"';
123     }
124     return (exclude ? '-' : '') + this.field + ':' + value;
125   }
126 });
127