1 // $Id$
  2 
  3 /**
  4  * @namespace A unique namespace for the AJAX Solr library.
  5  */
  6 AjaxSolr = function () {};
  7 
  8 /**
  9  * @namespace Baseclass for all classes
 10  */
 11 AjaxSolr.Class = function () {};
 12 
 13 /**
 14  * A class 'extends' itself into a subclass.
 15  *
 16  * @static
 17  * @param properties The properties of the subclass.
 18  * @returns A function that represents the subclass.
 19  */
 20 AjaxSolr.Class.extend = function (properties) {
 21   var klass = this; // Safari dislikes 'class'
 22   // The subclass is just a function that when called, instantiates itself.
 23   // Nothing is _actually_ shared between _instances_ of the same class.
 24   var subClass = function (options) {
 25     // 'this' refers to the subclass, which starts life as an empty object.
 26     // Add its parent's properties, its own properties, and any passed options.
 27     AjaxSolr.extend(this, new klass(options), properties, options);
 28   }
 29   // Allow the subclass to extend itself into further subclasses.
 30   subClass.extend = this.extend;
 31   return subClass;
 32 };
 33 
 34 /**
 35  * @static
 36  * @param {Object} obj Any object.
 37  * @returns {Number} the number of properties on an object.
 38  * @see http://stackoverflow.com/questions/5223/length-of-javascript-associative-array
 39  */
 40 AjaxSolr.size = function (obj) {
 41   var size = 0;
 42   for (var key in obj) {
 43     if (obj.hasOwnProperty(key)) {
 44       size++;
 45     }
 46   }
 47   return size;
 48 };
 49 
 50 /**
 51  * @static
 52  * @param foo A value.
 53  * @param bar A value.
 54  * @returns {Boolean} Whether the two given values are equal.
 55  */
 56 AjaxSolr.equals = function (foo, bar) {
 57   if (AjaxSolr.isArray(foo) && AjaxSolr.isArray(bar)) {
 58     if (foo.length !== bar.length) {
 59       return false;
 60     }
 61     for (var i = 0, l = foo.length; i < l; i++) {
 62       if (foo[i] !== bar[i]) {
 63         return false;
 64       }
 65     }
 66     return true;
 67   }
 68   else if (AjaxSolr.isRegExp(foo) && AjaxSolr.isString(bar)) {
 69     return bar.match(foo);
 70   }
 71   else if (AjaxSolr.isRegExp(bar) && AjaxSolr.isString(foo)) {
 72     return foo.match(bar);
 73   }
 74   else {
 75     return foo === bar;
 76   }
 77 };
 78 
 79 /**
 80  * @static
 81  * @param value A value.
 82  * @param array An array.
 83  * @returns {Boolean} Whether value exists in the array.
 84  */
 85 AjaxSolr.inArray = function (value, array) {
 86   if (array) {
 87     for (var i = 0, l = array.length; i < l; i++) {
 88       if (AjaxSolr.equals(array[i], value)) {
 89         return i;
 90       }
 91     }
 92   }
 93   return -1;
 94 };
 95 
 96 /**
 97  * A copy of MooTools' Array.flatten function.
 98  *
 99  * @static
100  * @see http://ajax.googleapis.com/ajax/libs/mootools/1.2.4/mootools.js
101  */
102 AjaxSolr.flatten = function(array) {
103   var ret = [];
104   for (var i = 0, l = array.length; i < l; i++) {
105     ret = ret.concat(AjaxSolr.isArray(array[i]) ? AjaxSolr.flatten(array[i]) : array[i]);
106   }
107   return ret;
108 };
109 
110 /**
111  * A copy of jQuery's jQuery.grep function.
112  *
113  * @static
114  * @see http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js
115  */
116 AjaxSolr.grep = function(array, callback) {
117   var ret = [];
118   for (var i = 0, l = array.length; i < l; i++) {
119     if (!callback(array[i], i) === false) {
120       ret.push(array[i]);
121     }
122   }
123   return ret;
124 }
125 
126 /**
127  * Equivalent to Ruby's Array#compact.
128  */
129 AjaxSolr.compact = function(array) {
130   return AjaxSolr.grep(array, function (item) {
131     return item.toString();
132   });
133 }
134 
135 /**
136  * Can't use toString.call(obj) === "[object Array]", as it may return
137  * "[xpconnect wrapped native prototype]", which is undesirable.
138  *
139  * @static
140  * @see http://thinkweb2.com/projects/prototype/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
141  * @see http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js
142  */
143 AjaxSolr.isArray = function (obj) {
144   return obj != null && typeof obj == 'object' && 'splice' in obj && 'join' in obj;
145 };
146 
147 /**
148  * @param obj Any object.
149  * @returns {Boolean} Whether the object is a RegExp object.
150  */
151 AjaxSolr.isRegExp = function (obj) {
152   return obj != null && (typeof obj == 'object' || typeof obj == 'function') && 'ignoreCase' in obj;
153 };
154 
155 /**
156  * @param obj Any object.
157  * @returns {Boolean} Whether the object is a String object.
158  */
159 AjaxSolr.isString = function (obj) {
160   return obj != null && typeof obj == 'string';
161 };
162 
163 /**
164  * Define theme functions to separate, as much as possible, your HTML from your
165  * JavaScript. Theme functions provided by AJAX Solr are defined in the
166  * AjaxSolr.theme.prototype namespace, e.g. AjaxSolr.theme.prototype.select_tag.
167  *
168  * To override a theme function provided by AJAX Solr, define a function of the
169  * same name in the AjaxSolr.theme namespace, e.g. AjaxSolr.theme.select_tag.
170  *
171  * To retrieve the HTML output by AjaxSolr.theme.prototype.select_tag(...), call
172  * AjaxSolr.theme('select_tag', ...).
173  *
174  * @param {String} func
175  *   The name of the theme function to call.
176  * @param ...
177  *   Additional arguments to pass along to the theme function.
178  * @returns
179  *   Any data the theme function returns. This could be a plain HTML string,
180  *   but also a complex object.
181  *
182  * @static
183  * @throws Exception if the theme function is not defined.
184  * @see http://cvs.drupal.org/viewvc.py/drupal/drupal/misc/drupal.js?revision=1.58
185  */
186 AjaxSolr.theme = function (func) {
187   if (AjaxSolr.theme[func] || AjaxSolr.theme.prototype[func] == undefined) {
188     console.log('Theme function "' + func + '" is not defined.');
189   }
190   else {
191     for (var i = 1, args = []; i < arguments.length; i++) {
192       args.push(arguments[i]);
193     }
194     return (AjaxSolr.theme[func] || AjaxSolr.theme.prototype[func]).apply(this, args);
195   }
196 };
197 
198 /**
199  * A simplified version of jQuery's extend function.
200  *
201  * @static
202  * @see http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.js
203  */
204 AjaxSolr.extend = function () {
205   var target = arguments[0] || {}, i = 1, length = arguments.length, options;
206   for (; i < length; i++) {
207     if ((options = arguments[i]) != null) {
208       for (var name in options) {
209         var src = target[name], copy = options[name];
210         if (target === copy) {
211           continue;
212         }
213         if (copy && typeof copy == 'object' && !copy.nodeType) {
214           target[name] = AjaxSolr.extend(src || (copy.length != null ? [] : {}), copy);
215         }
216         else if (copy && src && typeof copy == 'function' && typeof src == 'function') {
217           target[name] = (function(superfn, fn) {
218             return function () {
219               var tmp = this._super, ret;
220               this._super = superfn;
221               ret = fn.apply(this, arguments);
222               this._super = tmp;
223               return ret;
224             };
225           })(src, copy);
226         }
227         else if (copy !== undefined) {
228           target[name] = copy;
229         }
230       }
231     }
232   }
233   return target;
234 };
235