/[webpac]/trunk2/out/js/search.js
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /trunk2/out/js/search.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 505 - (hide annotations)
Sun Oct 10 18:55:05 2004 UTC (19 years, 6 months ago) by dpavlin
File MIME type: application/javascript
File size: 9659 byte(s)
jsFind: fix warning in FireFox

1 dpavlin 391 /**
2     search.js searchs an XML index to HTML files.
3    
4     A part of the jsfind project (http://projects.elucidsoft.net/jsfind)
5     Copyright (C) 2003 Shawn Garbett
6    
7     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License
9     as published by the Free Software Foundation; either version 2
10     of the License, or (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20    
21     Contact Info:
22     Shawn Garbett <Shawn@eLucidSoft.net>
23     http://www.elucidsoft.net
24     4037 General Bate Drive
25     Nashville, TN 37204
26     */
27    
28     // Constants
29     var conversion = new String
30     ("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY");
31    
32     // State variables
33     var query_left = "";
34     var search_err = "";
35     var results = null;
36     var index_path = "";
37    
38     var watchdog_id = 0;
39     var watchdog_callback = null;
40    
41     // Object to hold search results
42     function Result(title, link, freq)
43     {
44     this.title=title;
45     this.link=link;
46     this.frequency=Number(freq);
47     }
48    
49     // Function to merge (intersect) two result sets
50     function intersect_results(data)
51     {
52     // If there are no stored results, then these are the results
53     if(!results)
54     {
55     results = data;
56     return;
57     }
58    
59     var output=new Array();
60    
61     // There are existing results, to do an intersect...
62     for(var i=0; i<results.length; i++)
63     {
64     for(var j=0; j<data.length; j++)
65     {
66     if(data[j].title == results[i].title)
67     {
68     results[i].frequency += data[j].frequency;
69     output.push(results[i]);
70     break;
71     }
72     }
73     }
74    
75     results = output;
76     }
77    
78     /*
79     From David Flanagan's, _Javascript:_The Definitive_Guide_, pg. 294-5,
80     published by O'Reilly, 4th edition, 2002
81     */
82 dpavlin 496
83     var debug_div = null;
84    
85 dpavlin 391 function debug(msg)
86     {
87 dpavlin 396 // return; // Disable debugging
88 dpavlin 391
89 dpavlin 496 if (! debug_div) debug_div = document.getElementById('debug');
90 dpavlin 391
91 dpavlin 496 // this will create debug div if it doesn't exist.
92     if (! debug_div) {
93     debug_div = document.createElement('div');
94 dpavlin 505 if (document.body) document.body.appendChild(debug_div);
95     else debug_div = null;
96 dpavlin 496 }
97     if (debug_div) {
98     debug_div.appendChild(document.createTextNode(msg));
99     debug_div.appendChild(document.createElement("br"));
100     }
101 dpavlin 391 }
102    
103     // Convert a number into a base 62 alphanumeric number string
104     function convert(num)
105     {
106     var base = conversion.length;
107     var pow = 1;
108     var pos = 0;
109     var out = "";
110    
111     if(num == 0)
112     {
113     return "0";
114     }
115    
116     while (num > 0)
117     {
118     pos = num % base;
119     out = conversion.charAt(pos) + out;
120     num = Math.floor(num/base);
121     pow *= base;
122     }
123    
124     return out;
125     }
126    
127     function watchdog()
128     {
129     debug ("TIMEOUT!");
130     watchdog_callback(new Array());
131     }
132    
133 dpavlin 469 var xmldoc;
134    
135 dpavlin 391 // This function loads the XML document from the specified URL, and when
136     // it is fully loaded, passes that document and the url to the specified
137     // handler function. This function works with any XML document
138     function loadXML(url, handler, data, result_handler)
139     {
140     debug("loadXML("+url+","+data+")");
141    
142     // Timeout operation in 10 seconds
143     watchdog_callback = result_handler;
144     watchdog_id=setTimeout("watchdog()", 20000);
145    
146     debug("setTimeout = "+watchdog_id);
147    
148     try
149     {
150     // Use the standard DOM Level 2 technique, if it is supported
151     if (document.implementation && document.implementation.createDocument)
152     {
153     // Create a new Document object
154 dpavlin 450 xmldoc = document.implementation.createDocument("", "", null);
155 dpavlin 391
156     // Specify what should happen when it finishes loading
157     xmldoc.onload = function() { handler(xmldoc, url, data, result_handler); }
158    
159     //xmldoc.onerror = docError;
160     //xmldoc.addEventListener("load",docError,false);
161    
162     // And tell it what URL to load
163     xmldoc.load(url);
164 dpavlin 496 return true;
165 dpavlin 391 }
166     // Otherwise use Microsoft's proprietary API for Internet Explorer
167     // Something about not following standards once again
168     else if (window.ActiveXObject)
169     {
170 dpavlin 450 xmldoc = new ActiveXObject("Microsoft.XMLDOM"); // Create doc.
171     if (! xmldoc) xmldoc = new ActiveXObject("MSXML2.DOMDocument"); // Create doc.
172 dpavlin 391 // Specify onload
173     xmldoc.onreadystatechange = function()
174     {
175     if (xmldoc.readyState == 4) handler(xmldoc, url, data, result_handler);
176     }
177     xmldoc.load(url); // Start loading!
178 dpavlin 496 return true;
179 dpavlin 391 }
180 dpavlin 496 // else fallback on usage of iframes to load xml (Opera 7.53 without Java and maybe old Mac browsers)
181     else {
182     debug("using iframe xml loader - experimental and slow");
183     if (! window.xml_iframe) {
184     debug("creating iframe");
185     window.xml_iframe = document.createElement('div');
186     window.xml_iframe.innerHTML = '<iframe src="'+url+'" name="xml_iframe" height="0" width="0" style="display: none;"></iframe>';
187     document.body.appendChild(window.xml_iframe);
188     } else {
189     debug("loading xml in existing iframe");
190     window.frames.xml_iframe.window.document.location.href = url;
191     }
192    
193     // set timeout to re-check if iframe is loaded
194     window.iframe_timeout = window.setInterval('iframe_xml_loaded();',100);
195    
196     // save some data for iframe_xml_loaded()
197     window.xml_handler = handler;
198     window.xml_url = url;
199     window.xml_data = data;
200     window.xml_result_handler = result_handler;
201     return true;
202     }
203     clearTimeout(watchdog_id);
204     debug("Browser incompatilibity: can't request XML document by one of supported methods");
205     return false;
206 dpavlin 391 }
207     catch(ex)
208     {
209     clearTimeout(watchdog_id);
210     debug("clearTimeout = "+watchdog_id);
211     debug ("CAUGHT EXCEPTION!");
212     result_handler(new Array());
213     return false;
214     }
215    
216     return true;
217     }
218    
219 dpavlin 496 function iframe_xml_loaded() {
220     debug("iframe_xmldoc_loaded");
221     if (! window.frames['xml_iframe']) return;
222     var xml = eval('window.frames.xml_iframe.window.document');
223     if (xml) {
224     clearTimeout(window.iframe_timeout);
225     debug("calling handler with ("+window.xml_url+","+window.xml_data+",...)");
226     window.xml_handler(window.frames.xml_iframe.window.document, window.xml_url, window.xml_data, window.xml_result_handler);
227     } else {
228     debug("can't eval iframe with xml");
229     }
230     }
231    
232 dpavlin 391 function loadData(xmldoc, url, pos, result_handler)
233     {
234     clearTimeout(watchdog_id);
235     debug("clearTimeout = "+watchdog_id);
236    
237     debug ("loadData("+url+","+pos+")");
238    
239     var data = new Array();
240    
241     // Get all entries
242     var entries = xmldoc.getElementsByTagName("e");
243    
244     if(entries.length > pos)
245     {
246     // Get the links associated with this query
247     var links = entries[pos].getElementsByTagName("l");
248    
249     // Dynamically append results to output
250     for(var i=0; i<links.length; i++)
251     {
252     data.push(new Result(links[i].getAttribute("t"),
253     links[i].firstChild.data,
254     links[i].getAttribute("f")));
255     }
256    
257     intersect_results(data);
258    
259     if(query_left.length > 0)
260     {
261     doSearch(index_path, query_left, result_handler);
262     }
263     else
264     {
265     results.sort(sortResults);
266     result_handler(results);
267     }
268     }
269     else
270     {
271     debug("INTERNAL ERROR, Inconsistent index");
272     search_err="INTERNAL ERROR, Inconsistent index";
273     }
274     }
275    
276     function sortResults(a, b)
277     {
278     return a.frequency - b.frequency;
279     }
280    
281     function traverseTree(xmldoc, url, query, result_handler)
282     {
283     clearTimeout(watchdog_id);
284     debug("clearTimeout = "+watchdog_id);
285    
286     debug("traverseTree("+xmldoc+","+url+","+query+")");
287    
288     var keys = xmldoc.getElementsByTagName("k");
289     var i;
290    
291     for(i = 0; i < keys.length; i++)
292     {
293     var key = keys[i].firstChild.data;
294     debug("traverseTree: key="+key+" query="+query);
295     if(key != '' && key != null)
296     {
297     // Case where current key is greater than query, descend
298     if(key > query)
299     {
300     if(key != '' && key != null)
301     {
302     if(!loadXML(url.replace(".xml","/"+convert(i)+".xml"),
303     traverseTree,query,result_handler))
304     {
305     debug("Unable to locate key "+query);
306     result_handler(new Array());
307     }
308     // make sure of garbage collection
309     xmldoc=null;
310     return;
311     }
312     }
313     // Found it!
314     else if(key==query)
315     {
316     if(!loadXML(url.replace(/(\w+\.xml)/, "_$1"),
317     loadData, i, result_handler))
318     {
319     debug("ERROR: Unable to locate data "+query);
320     result_handler(new Array());
321     }
322     // make sure of garbage collection
323     xmldoc=null;
324     return;
325     }
326     }
327     }
328     // Look past the end...
329     if(keys.length == 0 || !loadXML(url.replace(".xml","/"+convert(i)+".xml"),
330     traverseTree,query,result_handler))
331     {
332     debug("Unable to locate key "+query);
333     result_handler(new Array());
334     }
335     // make sure of garbage collection
336     xmldoc=null;
337     return;
338     }
339    
340     function doSearch(index_name,query, result_func)
341     {
342     //alert("doSearch("+index_name+","+query+")");
343     var pos=query.search(/[\s\+]/);
344     if (index_name) index_path = index_name+'/';
345    
346     if(pos < 0)
347     {
348     query_left = "";
349     }
350     else
351     {
352     query_left = query.slice(pos+1);
353     query = query.slice(0,pos);
354     }
355    
356     if(!loadXML(index_path+"0.xml", traverseTree, query.toLowerCase(), result_func))
357     {
358     debug("ERROR: Couldn't find main index 0.xml");
359     search_err = "INTERNAL ERROR: Unable to load main index 0.xml";
360     }
361     }

  ViewVC Help
Powered by ViewVC 1.1.26