]> scripts.mit.edu Git - autoinstalls/wordpress.git/blob - wp-includes/js/jquery/suggest.js
Wordpress 2.5.1-scripts
[autoinstalls/wordpress.git] / wp-includes / js / jquery / suggest.js
1 /*
2  *      jquery.suggest 1.1 - 2007-08-06
3  *      
4  *      Uses code and techniques from following libraries:
5  *      1. http://www.dyve.net/jquery/?autocomplete
6  *      2. http://dev.jquery.com/browser/trunk/plugins/interface/iautocompleter.js      
7  *
8  *      All the new stuff written by Peter Vulgaris (www.vulgarisoip.com)       
9  *      Feel free to do whatever you want with this file
10  *
11  */
12
13 (function($) {
14
15         $.suggest = function(input, options) {
16
17                 var $input = $(input).attr("autocomplete", "off");
18                 var $results = $(document.createElement("ul"));
19
20                 var timeout = false;            // hold timeout ID for suggestion results to appear     
21                 var prevLength = 0;                     // last recorded length of $input.val()
22                 var cache = [];                         // cache MRU list
23                 var cacheSize = 0;                      // size of cache in chars (bytes?)
24                 
25                 $results.addClass(options.resultsClass).appendTo('body');
26                         
27
28                 resetPosition();
29                 $(window)
30                         .load(resetPosition)            // just in case user is changing size of page while loading
31                         .resize(resetPosition);
32
33                 $input.blur(function() {
34                         setTimeout(function() { $results.hide() }, 200);
35                 });
36                 
37                 
38                 // help IE users if possible
39                 try {
40                         $results.bgiframe();
41                 } catch(e) { }
42
43
44                 // I really hate browser detection, but I don't see any other way
45                 if ($.browser.mozilla)
46                         $input.keypress(processKey);    // onkeypress repeats arrow keys in Mozilla/Opera
47                 else
48                         $input.keydown(processKey);             // onkeydown repeats arrow keys in IE/Safari
49                 
50
51
52
53                 function resetPosition() {
54                         // requires jquery.dimension plugin
55                         var offset = $input.offset();
56                         $results.css({
57                                 top: (offset.top + input.offsetHeight) + 'px',
58                                 left: offset.left + 'px'
59                         });
60                 }
61                 
62                 
63                 function processKey(e) {
64                         
65                         // handling up/down/escape requires results to be visible
66                         // handling enter/tab requires that AND a result to be selected
67                         if ((/27$|38$|40$/.test(e.keyCode) && $results.is(':visible')) ||
68                                 (/^13$|^9$/.test(e.keyCode) && getCurrentResult())) {
69                                 
70                                 if (e.preventDefault)
71                                         e.preventDefault();
72                                 if (e.stopPropagation)
73                                         e.stopPropagation();
74
75                                 e.cancelBubble = true;
76                                 e.returnValue = false;
77                         
78                                 switch(e.keyCode) {
79
80                                         case 38: // up
81                                                 prevResult();
82                                                 break;
83                         
84                                         case 40: // down
85                                                 nextResult();
86                                                 break;
87
88                                         case 9:  // tab
89                                         case 13: // return
90                                                 selectCurrentResult();
91                                                 break;
92                                                 
93                                         case 27: //     escape
94                                                 $results.hide();
95                                                 break;
96
97                                 }
98                                 
99                         } else if ($input.val().length != prevLength) {
100
101                                 if (timeout) 
102                                         clearTimeout(timeout);
103                                 timeout = setTimeout(suggest, options.delay);
104                                 prevLength = $input.val().length;
105                                 
106                         }                       
107                                 
108                         
109                 }
110                 
111                 
112                 function suggest() {
113                 
114                         var q = $.trim($input.val());
115
116                         if (q.length >= options.minchars) {
117                                 
118                                 cached = checkCache(q);
119                                 
120                                 if (cached) {
121                                 
122                                         displayItems(cached['items']);
123                                         
124                                 } else {
125                                 
126                                         $.get(options.source, {q: q}, function(txt) {
127
128                                                 $results.hide();
129                                                 
130                                                 var items = parseTxt(txt, q);
131                                                 
132                                                 displayItems(items);
133                                                 addToCache(q, items, txt.length);
134                                                 
135                                         });
136                                         
137                                 }
138                                 
139                         } else {
140                         
141                                 $results.hide();
142                                 
143                         }
144                                 
145                 }
146                 
147                 
148                 function checkCache(q) {
149
150                         for (var i = 0; i < cache.length; i++)
151                                 if (cache[i]['q'] == q) {
152                                         cache.unshift(cache.splice(i, 1)[0]);
153                                         return cache[0];
154                                 }
155                         
156                         return false;
157                 
158                 }
159                 
160                 function addToCache(q, items, size) {
161
162                         while (cache.length && (cacheSize + size > options.maxCacheSize)) {
163                                 var cached = cache.pop();
164                                 cacheSize -= cached['size'];
165                         }
166                         
167                         cache.push({
168                                 q: q,
169                                 size: size,
170                                 items: items
171                                 });
172                                 
173                         cacheSize += size;
174                 
175                 }
176                 
177                 function displayItems(items) {
178                         
179                         if (!items)
180                                 return;
181                                 
182                         if (!items.length) {
183                                 $results.hide();
184                                 return;
185                         }
186
187                         resetPosition(); // when the form moves after the page has loaded
188
189                         var html = '';
190                         for (var i = 0; i < items.length; i++)
191                                 html += '<li>' + items[i] + '</li>';
192
193                         $results.html(html).show();
194                         
195                         $results
196                                 .children('li')
197                                 .mouseover(function() {
198                                         $results.children('li').removeClass(options.selectClass);
199                                         $(this).addClass(options.selectClass);
200                                 })
201                                 .click(function(e) {
202                                         e.preventDefault(); 
203                                         e.stopPropagation();
204                                         selectCurrentResult();
205                                 });
206                                                 
207                 }
208                 
209                 function parseTxt(txt, q) {
210                         
211                         var items = [];
212                         var tokens = txt.split(options.delimiter);
213                         
214                         // parse returned data for non-empty items
215                         for (var i = 0; i < tokens.length; i++) {
216                                 var token = $.trim(tokens[i]);
217                                 if (token) {
218                                         token = token.replace(
219                                                 new RegExp(q, 'ig'), 
220                                                 function(q) { return '<span class="' + options.matchClass + '">' + q + '</span>' }
221                                                 );
222                                         items[items.length] = token;
223                                 }
224                         }
225                         
226                         return items;
227                 }
228                 
229                 function getCurrentResult() {
230                 
231                         if (!$results.is(':visible'))
232                                 return false;
233                 
234                         var $currentResult = $results.children('li.' + options.selectClass);
235                         
236                         if (!$currentResult.length)
237                                 $currentResult = false;
238                                 
239                         return $currentResult;
240
241                 }
242                 
243                 function selectCurrentResult() {
244                 
245                         $currentResult = getCurrentResult();
246                 
247                         if ($currentResult) {
248                                 $input.val($currentResult.text());
249                                 $results.hide();
250                                 
251                                 if (options.onSelect)
252                                         options.onSelect.apply($input[0]);
253                                         
254                         }
255                 
256                 }
257                 
258                 function nextResult() {
259                 
260                         $currentResult = getCurrentResult();
261                 
262                         if ($currentResult)
263                                 $currentResult
264                                         .removeClass(options.selectClass)
265                                         .next()
266                                                 .addClass(options.selectClass);
267                         else
268                                 $results.children('li:first-child').addClass(options.selectClass);
269                 
270                 }
271                 
272                 function prevResult() {
273                 
274                         $currentResult = getCurrentResult();
275                 
276                         if ($currentResult)
277                                 $currentResult
278                                         .removeClass(options.selectClass)
279                                         .prev()
280                                                 .addClass(options.selectClass);
281                         else
282                                 $results.children('li:last-child').addClass(options.selectClass);
283                 
284                 }
285
286         }
287         
288         $.fn.suggest = function(source, options) {
289         
290                 if (!source)
291                         return;
292         
293                 options = options || {};
294                 options.source = source;
295                 options.delay = options.delay || 100;
296                 options.resultsClass = options.resultsClass || 'ac_results';
297                 options.selectClass = options.selectClass || 'ac_over';
298                 options.matchClass = options.matchClass || 'ac_match';
299                 options.minchars = options.minchars || 2;
300                 options.delimiter = options.delimiter || '\n';
301                 options.onSelect = options.onSelect || false;
302                 options.maxCacheSize = options.maxCacheSize || 65536;
303
304                 this.each(function() {
305                         new $.suggest(this, options);
306                 });
307
308                 return this;
309                 
310         };
311         
312 })(jQuery);