1 // $Id$
  2 
  3 /**
  4  * Represents a Solr parameter.
  5  *
  6  * @param properties A map of fields to set. Refer to the list of public fields.
  7  * @class Parameter
  8  */
  9 AjaxSolr.Parameter = AjaxSolr.Class.extend(
 10   /** @lends AjaxSolr.Parameter.prototype */
 11   {
 12   /**
 13    * The parameter's name.
 14    *
 15    * @field
 16    * @private
 17    * @type String
 18    */
 19   name: null,
 20 
 21   /**
 22    * The parameter's value.
 23    *
 24    * @field
 25    * @private
 26    * @type String
 27    */
 28   value: null,
 29 
 30   /**
 31    * The parameter's local parameters.
 32    *
 33    * @field
 34    * @private
 35    * @type Object
 36    * @default {}
 37    */
 38   locals: {},
 39 
 40   /**
 41    * Returns the value. If called with an argument, sets the value.
 42    *
 43    * @param {String|Number|String[]|Number[]} [value] The value to set.
 44    * @returns The value.
 45    */
 46   val: function (value) {
 47     if (value === undefined) {
 48       return this.value;
 49     }
 50     else {
 51       this.value = value;
 52     }
 53   },
 54 
 55   /**
 56    * Returns the value of a local parameter. If called with a second argument,
 57    * sets the value of a local parameter.
 58    *
 59    * @param {String} name The name of the local parameter.
 60    * @param {String|Number|String[]|Number[]} [value] The value to set.
 61    * @returns The value.
 62    */
 63   local: function (name, value) {
 64     if (value === undefined) {
 65       return this.locals[name];
 66     }
 67     else {
 68       this.locals[name] = value;
 69     }
 70   },
 71 
 72   /**
 73    * Deletes a local parameter.
 74    *
 75    * @param {String} name The name of the local parameter.
 76    */
 77   remove: function (name) {
 78     delete this.locals[name];
 79   },
 80 
 81   /**
 82    * Returns the Solr parameter as a query string key-value pair.
 83    *
 84    * <p>IE6 calls the default toString() if you write <tt>store.toString()
 85    * </tt>. So, we need to choose another name for toString().</p>
 86    */
 87   string: function () {
 88     var pairs = [];
 89 
 90     for (var name in this.locals) {
 91       if (this.locals[name]) {
 92         pairs.push(name + '=' + encodeURIComponent(this.locals[name]));
 93       }
 94     }
 95 
 96     var prefix = pairs.length ? '{!' + pairs.join('%20') + '}' : '';
 97 
 98     if (this.value) {
 99       return this.name + '=' + prefix + this.valueString(this.value);
100     }
101     // For dismax request handlers, if the q parameter has local params, the
102     // q parameter must be set to a non-empty value. In case the q parameter
103     // is empty, use the q.alt parameter, which accepts wildcards.
104     else if (this.name == 'q') {
105       return 'q.alt=' + prefix + encodeURIComponent('*.*');
106     }
107     else {
108       return '';
109     }
110   },
111 
112   /**
113    * Parses a string formed by calling string().
114    *
115    * @param {String} str The string to parse.
116    */
117   parseString: function (str) {
118     var param = str.match(/^([^=]+)=(?:\{!([^\}]*)\})?(.*)$/);
119     if (param) {
120       var matches;
121 
122       while (matches = /([^\s=]+)=(\S*)/g.exec(decodeURIComponent(param[2]))) {
123         this.locals[matches[1]] = decodeURIComponent(matches[2]);
124         param[2] = param[2].replace(matches[0], ''); // Safari's exec seems not to do this on its own
125       }
126 
127       if (param[1] == 'q.alt') {
128         this.name = 'q';
129         // if q.alt is present, assume it is because q was empty, as above
130       }
131       else {
132         this.name = param[1];
133         this.value = this.parseValueString(param[3]);
134       }
135     }
136   },
137 
138   /**
139    * Returns the value as a URL-encoded string.
140    *
141    * @private
142    * @param {String|Number|String[]|Number[]} value The value.
143    * @returns {String} The URL-encoded string.
144    */
145   valueString: function (value) {
146     value = AjaxSolr.isArray(value) ? value.join(',') : value;
147     return encodeURIComponent(value);
148   },
149 
150   /**
151    * Parses a URL-encoded string to return the value.
152    *
153    * @private
154    * @param {String} str The URL-encoded string.
155    * @returns {Array} The value.
156    */
157   parseValueString: function (str) {
158     str = decodeURIComponent(str);
159     return str.indexOf(',') == -1 ? str : str.split(',');
160   }
161 });
162