PageSourceSearch

https://metaphordogs.org/Dogs/search.js

js metaphordogs.org collected 2026-10-02 13:47:46 UTC 38,615 bytes, 1,008 lines download raw bytes

1// ----------------------------------------------------------------------------
2// Zoom Search Engine 5.1 (13/11/2007)
3//
4// This file (search.js) is the JavaScript search front-end for client side
5// searches using index files created by the Zoom Search Engine Indexer.
6//
7// email: [email protected]
8// www: http://www.wrensoft.com
9//
10// Copyright (C) Wrensoft 2000-2007
11//
12// This script performs client-side searching with the index data file
13// (zoom_index.js) generated by the Zoom Search Engine Indexer. It allows you
14// to run searches on mediums such as CD-ROMs, or other local data, where a
15// web server is not available.
16//
17// We recommend against using client-side searches for online websites because
18// it requires the entire index data file to be downloaded onto the user's
19// local machine. This can be very slow for large websites, and our server-side
20// search scripts (available for PHP, ASP and CGI) are far better suited for this.
21// However, JavaScript is still an option for smaller websites in a limited
22// hosting situation (eg: your web host does not support PHP, ASP or CGI).
23// ----------------------------------------------------------------------------
24
25// Include required files for index data, settings, etc.
26document.write("<script language=\"JavaScript\" src=\"zoom_index.js\" charset=\"" + Charset + "\"><\/script>");
27document.write("<script language=\"JavaScript\" src=\"zoom_pageinfo.js\" charset=\"" + Charset + "\"><\/script>");
28
29document.write("<meta http-equiv=\"content-type\" content=\"text/html; charset=" + Charset + "\">");
30
31// ----------------------------------------------------------------------------
32// Settings (change if necessary)
33// ----------------------------------------------------------------------------
34
35// The options available in the dropdown menu for number of results
36// per page
37var PerPageOptions = new Array(10, 20, 50, 100);
38
39// Globals
40var SkippedWords = 0;
41var searchWords = new Array();
42var RegExpSearchWords = new Array();
43var SkippedOutputStr = "";
44
45var months = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
46
47// Index format
48var PAGEDATA_URL = 0;
49var PAGEDATA_TITLE = 1;
50var PAGEDATA_DESC = 2;
51var PAGEDATA_IMG = 3;
52var PAGEINFO_DATETIME = 0;
53var PAGEINFO_FILESIZE = 1;
54var PAGEINFO_CAT = 2;
55
56// ----------------------------------------------------------------------------
57// Helper Functions
58// ----------------------------------------------------------------------------
59
60// This function will return the value of a GET parameter
61function getParam(paramName)
62{
63    paramStr = document.location.search;
64    if (paramStr == "")
65        return "";
66
67    // remove '?' in front of paramStr
68    if (paramStr.charAt(0) == "?")
69        paramStr = paramStr.substr(1);
70
71    arg = (paramStr.split("&"));
72    for (i=0; i < arg.length; i++) {
73        arg_values = arg[i].split("=")
74        if (unescape(arg_values[0]) == paramName) 
75        {
76        	if (paramName == "zoom_query")
77        		arg_values[1] = arg_values[1].replace(/[\+]/g, " ");  // replace the '+' with spaces
78        		        		
79            if (UseUTF8 == 1 && self.decodeURIComponent) // check if decodeURIComponent() is defined
80                ret = decodeURIComponent(arg_values[1]);
81            else
82                ret = unescape(arg_values[1]);  // IE 5.0 and older does not have decodeURI
83            return ret;
84        }
85    }
86    return "";
87}
88
89function getParamArrayInt(paramName)
90{
91    paramStr = document.location.search;
92
93    var retArray = new Array();
94    var retCount = 0;
95
96    if (paramStr == "")
97        return retArray;
98
99    // remove '?' in front of paramStr
100    if (paramStr.charAt(0) == "?")
101        paramStr = paramStr.substr(1);
102
103    arg = (paramStr.split("&"));
104    for (i=0; i < arg.length; i++) 
105    {
106        arg_values = arg[i].split("=")
107        if (unescape(arg_values[0]) == paramName) 
108        {
109            if (UseUTF8 == 1 && self.decodeURIComponent) // check if decodeURIComponent() is defined
110                ret = decodeURIComponent(arg_values[1]);
111            else
112                ret = unescape(arg_values[1]);  // IE 5.0 and older does not have decodeURI            
113                
114            if (isNaN(ret) == false)
115            {
116            	retArray[retCount] = ret;
117            	retCount++;            
118            }
119        }
120    }
121    return retArray;    
122}
123
124// Compares the two values, used for sorting output results
125// Results that match all search terms are put first, highest score
126function SortCompare (a, b)
127{
128    if (a[2] < b[2]) return 1;
129    else if (a[2] > b[2]) return -1;
130    else if (a[1] < b[1]) return 1;
131    else if (a[1] > b[1]) return -1;
132    else return 0;
133}
134
135function SortByDate(a, b)
136{   
137    if (pageinfo[a[0]][PAGEINFO_DATETIME] < pageinfo[b[0]][PAGEINFO_DATETIME]) return 1;
138    else if (pageinfo[a[0]][PAGEINFO_DATETIME] > pageinfo[b[0]][PAGEINFO_DATETIME]) return -1;
139    else return SortCompare(a, b);
140}
141
142function sw_compare(a, b)
143{
144    if (a.charAt(0) == '-') 
145        return 1;
146    
147    if (b.charAt(0) == '-') 
148        return -1;
149    
150    return 0;
151}
152
153function pattern2regexp(pattern)
154{
155    pattern = pattern.replace(/\#/g, "\\#");
156    pattern = pattern.replace(/\$/g, "\\$");
157    pattern = pattern.replace(/\./g, "\\.");
158    pattern = pattern.replace(/\*/g, "[\\d\\S]*");
159    pattern = pattern.replace(/\?/g, ".?");
160    return pattern;
161}
162
163function PrintHighlightDescription(line) 
164{
165    if (Highlighting == 0)
166    {
167        document.writeln(line);
168        return;
169    }
170        
171    res = " " + line + " ";
172    for (i = 0; i < numwords; i++) {
173        if (RegExpSearchWords[i] == "")
174            continue;
175
176        if (SearchAsSubstring == 1)
177            res = res.replace(new RegExp("("+RegExpSearchWords[i]+")", "gi"), "[;:]$1[:;]");
178        else
179            res = res.replace(new RegExp("(\\W|^|\\b)("+RegExpSearchWords[i]+")(\\W|$|\\b)", "gi"), "$1[;:]$2[:;]$3");
180    }
181    // replace the marker text with the html text
182    // this is to avoid finding previous <span>'ed text.
183    res = res.replace(/\[;:\]/g, "<span class=\"highlight\">");
184    res = res.replace(/\[:;
184\]/g, "</span>");
185    document.writeln(res);
186}
187
188function PrintNumResults(num)
189{
190    if (num == 0)
191        return STR_NO_RESULTS;
192    else if (num == 1)
193        return num + " " + STR_RESULT;
194    else
195        return num + " " + STR_RESULTS;
196}
197
198function AddParamToURL(url, paramStr)
199{
200    // add GET parameters to URL depending on 
201    // whether there are any existing parameters
202    if (url.indexOf("?") > -1)  
203        return url + "&amp;" + paramStr;
204    else        
205        return url + "?" + paramStr;            
206}
207
208function SkipSearchWord(sw) {
209    if (searchWords[sw] != "") {
210        if (SkippedWords > 0)
211            SkippedOutputStr += ", ";
212        SkippedOutputStr += "\"<b>" + searchWords[sw] + "</b>\"";
213        searchWords[sw] = "";
214    }
215}
216
217function wordcasecmp(word1, word2) {
218    if (word1 == word2)
219        return 0;
220    else
221        return -1;  
222}
223
224function htmlspecialchars(query) {
225    query = query.replace(/\&/g, "&#38;");
226    query = query.replace(/\</g, "&#60;");
227    query = query.replace(/\>/g, "&#62;");  
228    query = query.replace(/\"/g, "&#34;");
229    query = query.replace(/\'/g, "&#39;");
230    return query;
231}
232
233function QueryEntities(query) { 
234    query = query.replace(/\&/g, "&#38;");  
235    query = query.replace(/\</g, "&#60;");
236    query = query.replace(/\>/g, "&#62;");
237    query = query.replace(/\'/g, "&#39;");  
238    return query;
239}
240
241function FixQueryForAsianWords(query) {
242    currCharType = 0;
243    lastCharType = 0;   // 0 is normal, 1 is hiragana, 2 is katakana, 3 is "han"
244    
245    // check for hiragana/katakana splitting required
246    newquery = "";
247    for (i = 0; i < query.length; i++)
248    {
249        ch = query.charAt(i);
250        chVal = query.charCodeAt(i);
251        
252        if (chVal >= 12352 && chVal <= 12447)
253            currCharType = 1;
254        else if (chVal >= 12448 && chVal <= 12543)
255            currCharType = 2;
256        else if (chVal >= 13312 && chVal <= 44031)
257            currCharType = 3;
258        else
259            currCharType = 0;
260                        
261        if (lastCharType != currCharType && ch != " ")
262            newquery += " ";            
263        lastCharType = currCharType;                
264        newquery += ch;
265    }
266    return newquery;
267}
268
269// ----------------------------------------------------------------------------
270// Parameters initialisation (globals)
271// ----------------------------------------------------------------------------
272
273var query = getParam("zoom_query");
274query = query.replace(/[\"]/g, " ");
275
276var per_page = parseInt(getParam("zoom_per_page"));
277if (isNaN(per_page)) per_page = 10;
278if (per_page < 1) per_page = 1;
279
280var page = parseInt(getParam("zoom_page"));
281if (isNaN(page)) page = 1;
282
283var andq = parseInt(getParam("zoom_and"));
284if (isNaN(andq))
285{
286    if (typeof(DefaultToAnd) != "undefined" && DefaultToAnd == 1)
287        andq = 1;
288    else
289        andq = 0;
290}
291
292var cat = getParamArrayInt("zoom_cat[]");
293if (cat.length == 0)
294{
295    cat[0] = parseInt(getParam("zoom_cat"));
296    if (isNaN(cat))
297        cat[0] = -1;    // search all categories
298}
299var num_zoom_cats = cat.length; 
300
301
302// for sorting options. zero is default (relevance)
303// 1 is sort by date (if date/time is available)
304var sort = parseInt(getParam("zoom_sort"));
305if (isNaN(sort)) sort = 0;
306
307var SelfURL = "";
308if (typeof(LinkBackURL) == "undefined")
309{
310    SelfURL = document.location.href;
311    // strip off parameters and anchors
312    var paramIndex;
313    paramIndex = SelfURL.indexOf("?");    
314    if (paramIndex > -1)
315        SelfURL = SelfURL.substr(0, paramIndex);
316    paramIndex = SelfURL.indexOf("#");
317    if (paramIndex > -1)
318        SelfURL = SelfURL.substr(0, paramIndex);        
319}
320else
321    SelfURL = LinkBackURL;
322// encode invalid URL characters
323SelfURL = SelfURL.replace(/\</g, "&lt;");
324SelfURL = SelfURL.replace(/\"/g, "&quot;");
325
326var data = new Array();
327var output = new Array();
328
329target = "";
330if (UseLinkTarget == 1)
331    target = " target=\"" + LinkTarget + "\" ";
332
333// ----------------------------------------------------------------------------
334// Main search function starts here
335// ----------------------------------------------------------------------------
336
337function ZoomSearch() 
338{
339    if (UseCats)
340        NumCats = catnames.length;
341
342    if (Timing == 1) {
343        timeStart = new Date();
344    }        
345        
346    // Display the form
347    if (FormFormat > 0) {
348        document.writeln("<form method=\"get\" action=\"" + SelfURL + "\" class=\"zoom_searchform\">");
349        document.writeln("<input type=\"text\" name=\"zoom_query\" size=\"20\" value=\"" + htmlspecialchars(query) + "\" class=\"zoom_searchbox\" />");
350        document.writeln("<input type=\"submit\" value=\"" + STR_FORM_
350SUBMIT_BUTTON + "\" class=\"zoom_button\" />");
351        if (FormFormat == 2) {
352            document.writeln("<span class=\"zoom_results_per_page\">" + STR_FORM_RESULTS_PER_PAGE + "\n");
353            document.writeln("<select name=\"zoom_per_page\">");
354            for (i = 0; i < PerPageOptions.length; i++) {
355                document.write("<option");
356                if (PerPageOptions[i] == per_page)
357                    document.write(" selected=\"selected\"");
358                document.writeln(">" + PerPageOptions[i] + "</option>");
359            }
360            document.writeln("</select><br /><br /></span>");
361            if (UseCats) {
362                document.writeln("<span class=\"zoom_categories\">");
363                document.write(STR_FORM_CATEGORY + " ");
364                if (SearchMultiCats)
365                {                                                   
366                    document.writeln("<ul>");
367                    document.write("<li><input type=\"checkbox\" name=\"zoom_cat[]\" value=\"-1\"");
368                    if (cat[0] == -1)
369                        document.write(" checked=\"checked\"");
370                    document.writeln(">" + STR_FORM_CATEGORY_ALL + "</input></li>");                                
371                    for (i = 0; i < NumCats; i++)  
372                    {           
373                        document.write("<li><input type=\"checkbox\" name=\"zoom_cat[]\" value=\"" +i+ "\"");
374                        if (cat[0] != -1)
375                        {
376                            for (catit = 0; catit < num_zoom_cats; catit++)
377                            {
378                                if (i == cat[catit])
379                                {
380                                    document.write(" checked=\"checked\"");
381                                    break;
382                                }
383                            }
384                        }
385                        document.writeln(">"+catnames[i]+"</input></li>");
386                    }
387                    document.writeln("</ul><br /><br />");
388                }
389                else
390                {                       
391                    document.write("<select name='zoom_cat[]'>");
392                    // 'all cats option
393                    document.write("<option value=\"-1\">" + STR_FORM_CATEGORY_ALL + "</option>");
394                    for (i = 0; i < NumCats; i++) {
395                        document.write("<option value=\"" + i + "\"");
396                        if (i == cat[0])
397                            document.write(" selected=\"selected\"");
398                        document.writeln(">" + catnames[i] + "</option>");
399                    }
400                    document.writeln("</select>&nbsp;&nbsp;");
401                }
402                document.writeln("</span>");
403            }
404            document.writeln("<span class=\"zoom_match\">" + STR_FORM_MATCH + " ");
405            if (andq == 0) {
406                document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"0\" checked=\"checked\" />" + STR_FORM_ANY_SEARCH_WORDS);
407                document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"1\" />" + STR_FORM_ALL_SEARCH_WORDS);                                
408            } else {
409                document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"0\" />" + STR_FORM_ANY_SEARCH_WORDS);
410                document.writeln("<input type=\"radio\" name=\"zoom_and\" value=\"1\" checked=\"checked\" />" + STR_FORM_ALL_SEARCH_WORDS);                
411            }
412            document.writeln("<input type=\"hidden\" name=\"zoom_sort\" value=\"" + sort + "\" />");
413            document.writeln("<br /><br /></span>");
414        }
415        else
416        {
417            document.writeln("<input type=\"hidden\" name=\"zoom_per_page\" value=\"" + per_page + "\" />");
418            document.writeln("<input type=\"hidden\" name=\"zoom_and\" value=\"" + andq + "\" />");
419            document.writeln("<input type=\"hidden\" name=\"zoom_sort\" value=\"" + sort + "\" />");
420        }
421        
422        document.writeln("</form>");
423    }
424
425    // give up early if no search words provided
426    if (query.length == 0) {
427        //document.writeln("No search query entered.<br />");        
428        if (ZoomInfo == 1)
429            document.writeln("<center><p><small>
429" + STR_POWEREDBY + " <a href=\"http://www.wrensoft.com/zoom/\" target=\"_blank\"><b>Zoom Search Engine</b></a></small></p></center>");
430        return;
431    }
432
433    if (MapAccents == 1) 
434    {
435        for (i = 0; i < NormalChars.length; i++)
436            query = query.replace(new RegExp(AccentChars[i], "g"), NormalChars[i]);                
437    }
438
439    // Special query processing required when SearchAsSubstring is enabled
440    if (SearchAsSubstring == 1 && UseUTF8 == 1)
441        query = FixQueryForAsianWords(query);
442
443    // prepare search query, strip quotes, trim whitespace
444    if (WordJoinChars.indexOf(".") == -1)
445        query = query.replace(/[\.]/g, " ");
446
447    if (WordJoinChars.indexOf("-") == -1)
448        query = query.replace(/(\S)\-/g, "$1 ");
449
450    if (WordJoinChars.indexOf("#") == -1)
451        query = query.replace(/\#(\S)/g, " $1");
452
453    if (WordJoinChars.indexOf("+") == -1)
454    {
455        query = query.replace(/[\+]+([^\+\s])/g, " $1");
456		query = query.replace(/([^\+\s])\+\s/g, "$1 ");
457    }
458
459    if (WordJoinChars.indexOf("_") == -1)
460        query = query.replace(/[\_]/g, " ");
461
462    if (WordJoinChars.indexOf("'") == -1)
463        query = query.replace(/[\']/g, " ");
464
465    if (WordJoinChars.indexOf("$") == -1)
466        query = query.replace(/[\$]/g, " ");
467
468    if (WordJoinChars.indexOf("&") == -1)
469        query = query.replace(/[\&]/g, " ");
470
471    if (WordJoinChars.indexOf(":") == -1)
472        query = query.replace(/[\:]/g, " ");
473
474    if (WordJoinChars.indexOf(",") == -1)
475        query = query.replace(/[\,]/g, " ");
476
477    if (WordJoinChars.indexOf("/") == -1)
478        query = query.replace(/[\/]/g, " ");
479
480    if (WordJoinChars.indexOf("\\") == -1)
481        query = query.replace(/[\\]/g, " ");
482        
483    // substitute multiple whitespace chars to single character
484    // also strip any of the wordjoinchars if followed immediately by a space
485    query = query.replace(/[\s\(\)\^\[\]\|\{\}\%]+|[\-._',:&\/\\\\](\s|$)/g, " ");   
486    
487    // trim trailing/leading whitespace
488    query = query.replace(/^\s*|\s*$/g,""); 
489    
490    var queryForHTML = htmlspecialchars(query);
491    var queryForSearch;
492    if (ToLowerSearchWords == 1)
493        queryForSearch = query.toLowerCase();
494    else
495        queryForSearch = query;    
496    queryForSearch = htmlspecialchars(queryForSearch);    
497
498    // split search phrase into words
499    searchWords = queryForSearch.split(" "); // split by spaces.
500    
501    // Sort search words if there are negative signs
502    if (queryForSearch.indexOf("-") != -1)
503        searchWords.sort(sw_compare);      
504
505    var query_zoom_cats = "";
506
507    document.write("<div class=\"searchheading\">" + STR_RESULTS_FOR + " " + queryForHTML);
508    if (UseCats) {
509        if (cat[0] == -1)
510        {
511            document.writeln(" " + STR_RESULTS_IN_ALL_CATEGORIES);
512            query_zoom_cats = "&amp;zoom_cat%5B%5D=-1";
513        }
514        else
515        {
516            document.writeln(" " + STR_RESULTS_IN_CATEGORY + " ");
517            for (catit = 0; catit < num_zoom_cats; catit++)
518            {
519                if (catit > 0)
520                    document.write(", ");
521                document.write("\"" + catnames[cat[catit]] + "\"");
522                query_zoom_cats += "&amp;zoom_cat%5B%5D="+cat[catit];
523            }
524        }
525    }
526    document.writeln("<br /><br /></div>");
527
528    document.writeln("<div class=\"results\">");
529
530    numwords = searchWords.length;
531    kw_ptr = 0;
532    outputline = 0;    
533    ipage = 0;
534    matches = 0;
535    var SWord;
536    pagesCount = NumPages;
537    
538    exclude_count = 0;
539    ExcludeTerm = 0;
540    
541    // Initialise a result table the size of all pages
542    res_table = new Array(pagesCount);
543    for (i = 0; i < pagesCount; i++)
544    {
545        res_table[i] = new Array(3);
546        res_table[i][0] = 0;
547        res_table[i][1] = 0;
548        res_table[i][2] = 0;
549    }
550    
551    var UseWildCards = new Array(numwords);    
552        
553    for (sw = 0; sw < numwords; sw++) {
554
555        UseWildCards[sw] = 0;
556
557        if (skipwords) {
558            // check min length
559            if (searchWords[sw].length < MinWordLen) {
560                SkipSearchWord(sw);
561                continue;
562            }
563            // check skip word list
564            for (i = 0;
564 i < skipwords.length; i++) {
565                if (searchWords[sw] == skipwords[i]) {
566                    SkipSearchWord(sw);
567                    break;
568                }
569            }
570        }
571
572        if (searchWords[sw].indexOf("*") == -1 && searchWords[sw].indexOf("?") == -1) {
573            UseWildCards[sw] = 0;
574        } else {
575            UseWildCards[sw] = 1;
576            RegExpSearchWords[sw] = pattern2regexp(searchWords[sw]);
577        }
578        
579        if (Highlighting == 1 && UseWildCards[sw] == 0)
580            RegExpSearchWords[sw] = searchWords[sw];                    
581    }
582                   
583    // Begin searching...
584    for (sw = 0; sw < numwords; sw++) {
585
586        if (searchWords[sw] == "") {
587            SkippedWords++;
588            continue;
589        }
590
591        if (searchWords[sw].charAt(0) == '-')
592        {           
593            searchWords[sw] = searchWords[sw].substr(1);            
594            ExcludeTerm = 1;
595            exclude_count++;            
596        }
597        
598        if (UseWildCards[sw] == 1) {            
599            if (SearchAsSubstring == 0)
600                pattern = "^" + RegExpSearchWords[sw] + "$";
601            else
602                pattern = RegExpSearchWords[sw];
603            re = new RegExp(pattern, "g");
604        }
605
606        for (kw_ptr = 0; kw_ptr < dictwords.length; kw_ptr++) {
607
608            data = dictwords[kw_ptr].split(" ");
609
610            if (UseWildCards[sw] == 0) {            	
611                if (SearchAsSubstring == 0)
612                    match_result = wordcasecmp(data[0], searchWords[sw]);
613                else
614                    match_result = data[0].indexOf(searchWords[sw]);
615            } else
616                match_result = data[0].search(re);
617
618
619            if (match_result != -1) {
620                // keyword found, include it in the output list
621                for (kw = 1; kw < data.length; kw += 2) {
622                    // check if page is already in output list
623                    pageexists = 0;
624                    ipage = data[kw];
625                    
626                    if (ExcludeTerm == 1)
627                    {
628                        // we clear out the score entry so that it'll be excluded in the filter stage
629                        res_table[ipage][0] = 0;
630                    }                    
631                    else if (res_table[ipage][0] == 0) {
632                        matches++;
633                        res_table[ipage][0] += parseInt(data[kw+1]);
634                    }
635                    else {
636
637                        if (res_table[ipage][0] > 10000) {
638                            // take it easy if its too big to prevent gigantic scores
639                            res_table[ipage][0] += 1;
640                        } else {
641                            res_table[ipage][0] += parseInt(data[kw+1]); // add in score
642                            res_table[ipage][0] *= 2;           // double score as we have two words matching
643                        }
644                    }
645                    res_table[ipage][1] += 1;
646                    // store the 'and' user search terms matched' value
647                    if (res_table[ipage][2] == sw || res_table[ipage][2] == sw-SkippedWords-exclude_count)
648                        res_table[ipage][2] += 1;
649
650                }
651                if (UseWildCards[sw] == 0 && SearchAsSubstring == 0)
652                    break;    // this search word was found, so skip to next
653            }
654        }
655    }
656    
657    if (SkippedWords > 0)
658        document.writeln("<div class=\"summary\">" + STR_SKIPPED_FOLLOWING_WORDS + " " + SkippedOutputStr + ".<br /><br /></div>");
659
660    // Count number of output lines that match ALL search terms
661    oline = 0;
662    fullmatches = 0;    
663    output = new Array();
664    var full_numwords = numwords - SkippedWords - exclude_count;
665    for (i = 0; i < pagesCount; i++) {
666        IsFiltered = false;
667        if (res_table[i][0] > 0) {
668            if (UseCats && cat[0] != -1) {
669                // using cats and not doing an "all cats" search
670                if (SearchMultiCats) {
671                    for (cati = 0; cati < num_zoom_cats; cati++) {                      
672                        if (pageinfo[i][PAGEINFO_CAT].charAt(cat[cati]) == "1")
673                            break;
674                    }
675                    if (cati == num_zoom_cats)
676                        IsFiltered = true;
677                }
678                else {                                      
679                    if (pageinfo[i][PAGEINFO_CAT].charAt(cat[0]) == "0") {
680                        IsFiltered = true;
681                    }
682                }
683            }
684            if (IsFiltered == false) {
685                if (res_table[i][2] >= full_numwords) {
686                    fullmatches++;
687                } else {
688                    if (andq == 1)
689                        IsFiltered = true;
690                }
691            }
692            if (IsFiltered == false) {
693                // copy if not filtered out
694                output[oline] = new Array(3);
695                output[oline][0] = i;
696                output[oline][1] = res_table[i][0];
697                output[oline][2] = res_table[i][1];
698                oline++;
699            }
700        }
701    }
702    matches = oline;    
703
704    // Sort results in order of score, use "SortCompare" function
705    if (matches > 1)    
706    {
707        if (sort == 1 && UseDateTime == 1)
708            output.sort(SortByDate);    // sort by date
709        else
710            output.sort(SortCompare);   // sort by relevance
711    }
712    
713    // prepare queryForURL
714    var queryForURL = query.replace(/\s/g, "+");
715    if (UseUTF8 == 1 && self.encodeURIComponent)
716        queryForURL = encodeURIComponent(queryForURL);
717    else
718        queryForURL = escape(queryForURL);    
719
720    //Display search result information
721    document.writeln("<div class=\"summary\">");
722    if (matches == 0)
723        document.writeln(STR_SUMMARY_NO_RESULTS_FOUND + "<br />");
724    else if (numwords > 1 && andq == 0) {
725        //OR
726        SomeTermMatches = matches - fullmatches;
727        document.writeln(PrintNumResults(fullmatches) + " " + STR_SUMMARY_FOUND_CONTAINING_ALL_TERMS + " ");
728        if (SomeTermMatches > 0)
729            document.writeln(PrintNumResults(SomeTermMatches) + " " + STR_SUMMARY_FOUND_CONTAINING_SOME_TERMS);
730        document.writeln("<br />");
731    }
732    else if (numwords > 1 && andq == 1) //AND
733        document.writeln(PrintNumResults(fullmatches) + " " + STR_SUMMARY_FOUND_CONTAINING_ALL_TERMS + "<br />");
734    else
735        document.writeln(PrintNumResults(matches) + " " + STR_SUMMARY_FOUND + "<br />");
736
737    document.writeln("</div>\n");
738
739    // number of pages of results
740    num_pages = Math.ceil(matches / per_page);
741    if (num_pages > 1)
742        document.writeln("<div class=\"result_pagescount\"><br />" + num_pages + " " + STR_PAGES_OF_RESULTS + "</div>\n");
743        
744    // Show recommended links if any
745    if (Recommended == 1)
746    {
747        num_recs_found = 0;
748        rec_count = recommended.length;
749        for (rl = 0; rl < rec_count && num_recs_found < RecommendedMax; rl++)
750        {
751            sep = recommended[rl].lastIndexOf(" ");
752            if (sep > -1)
753            {
754                rec_word = recommended[rl].slice(0, sep);
755                rec_idx = parseInt(recommended[rl].slice(sep));
756                for (sw = 0; sw <= numwords; sw++)  
757                {
758                    if (sw == numwords)
759                    {
760                        match_result = wordcasecmp(rec_word, queryForSearch);
761                    }
762                    else
763                    {
764                        if (UseWildCards[sw] == 1)
765                        {
766                            if (SearchAsSubstring == 0)
767                                pattern = "^" + RegExpSearchWords[sw] + "$";
768                            else
769                                pattern = RegExpSearchWords[sw];
770                            re = new RegExp(pattern, "g");
771                            match_result = rec_word.search(re);                         
772                        }
773                        else if (SearchAsSubstring == 0)
774                        {
775                            match_result = wordcasecmp(rec_word, searchWords[sw]);
776                        }
777                        else
778                            match_result = rec_word.indexOf(searchWords[sw]);
779                    }
780                    if (match_result != -1)
781                    {
782                        if (num_recs_found == 0)
783                        {
784                            document.writeln("<div class=\"recommended\">");
785                            document.writeln("<div class=\"recommended_heading\">" + STR_RECOMMENDED + "</div>");
786                        }
787                        pgurl = pagedata[rec_idx][PAGEDATA_URL];
788                        pgtitle = pagedata[rec_idx][PAGEDATA_TITLE];
789                        pgdesc = pagedata[rec_idx][PAGEDATA_DESC];
790                        urlLink = pgurl;                        
791                        if (GotoHighlight == 1)             
792                        {
793                            if (SearchAsSubstring == 1)
794                                urlLink = AddParamToURL(urlLink, "zoom_highlightsub=" + queryForURL);
795                            else
796                                urlLink = AddParamToURL(urlLink, "zoom_highlight=" + queryForURL);
797                        }           
798                        if (PdfHighlight == 1)
799                        {
800                            if (urlLink.indexOf(".pdf") != -1)
801                                urlLink = urlLink+"#search=&quot;"+query+"&quot;";
802                        }                       
803                        document.writeln("<div class=\"recommend_block\">");
804                        document.writeln("<div class=\"recommend_title\">");
805                        document.writeln("<a href=\"" + urlLink + "\"" + target + ">");
806                        if (pgtitle.length > 1)
807                            PrintHighlightDescription(pgtitle);
808                        else
809                            PrintHighlightDescription(pgurl);
810                        document.writeln("</a></div>");                             
811                        document.writeln("<div class=\"recommend_description\">")
812                        PrintHighlightDescription(pgdesc);
813                        document.writeln("</div>");                     
814                        document.writeln("<div class=\"recommend_infoline\">" + pgurl + "</div>");
815                        document.writeln("</div>");
816                        num_recs_found++;                       
817                        break;              
818                    }
819                }               
820            }
821        }
822        if (num_recs_found > 0)
823            document.writeln("</div");
824    }
825    
826    // Show sorting options
827    if (matches > 1)
828    {
829        if (UseDateTime == 1)
830        {
831            document.writeln("<div class=\"sorting\">");
832            if (sort == 1)
833                document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + queryForURL + "&amp;zoom_page=" + page + "&amp;zoom_per_page=" + per_page + query_zoom_cats + "&amp;zoom_and=" + andq + "&amp;zoom_sort=0\">" + STR_SORTBY_RELEVANCE + "</a> / <b>" + STR_SORTEDBY_DATE + "</b>");
834            else
835                document.writeln("<b>" + STR_SORTEDBY_RELEVANCE + "</b> / <a href=\"" + SelfURL + "?zoom_query=" + queryForURL + "&amp;zoom_page=" + page + "&amp;zoom_per_page=" + per_page + query_zoom_cats + "&amp;zoom_and=" + andq + "&amp;zoom_sort=1\">" + STR_SORTBY_DATE + "</a>");
836            document.writeln("</div>");
837        }       
838    }    
839
840    // determine current line of result from the output array
841    if (page == 1) {
842        arrayline = 0;
843    } else {
844        arrayline = ((page - 1) * per_page);
845    }
846
847    // the last result to show on this page
848    result_limit = arrayline + per_page;
849
850    // display the results
851    while (arrayline < matches && arrayline < result_limit) {
852        ipage = output[arrayline][0];
853        score = output[arrayline][1];
854        
855        pgurl = pagedata[ipage][PAGEDATA_URL];
856        pgtitle = pagedata[ipage][PAGEDATA_TITLE];
857        pgdesc = pagedata[ipage][PAGEDATA_DESC];
858        pgimage = pagedata[ipage][PAGEDATA_IMG];                
859                
860        urlLink = pgurl;                                        
861        if (GotoHighlight == 1)             
862        {
863            if (SearchAsSubstring == 1)
864                urlLink = AddParamToURL(urlLink, "zoom_highlightsub=" + queryForURL);
865            else
866                urlLink = AddParamToURL(urlLink, "zoom_highlight=" + queryForURL);
867        }       
868        if (PdfHighlight == 1)
869        {
870            if (urlLink.indexOf(".pdf") != -1)
871                urlLink = urlLink+"#search=&quot;"+query+"&quot;";
872        } 
873                
874        if (arrayline % 2 == 0)
875            document.writeln("<div class=\"result_block\">");
876        else
877            document.writeln("<div class=\"result_altblock\">");
878        
879        if (UseZoomImage == 1)
880        {           
881            if (pgimage.length > 1)
882            {
883                document.writeln("<div class=\"result_image\">");           
884                document.writeln("<a href=\"" + urlLink + "\"" + target + "><img src=\"" + pgimage + "\" alt=\"\" class=\"result_image\"></a>");
885                document.writeln("</div>");
886            }
887        }
888                            
889        document.writeln("<div class=\"result_title\">");
890        if (DisplayNumber == 1)
891            document.writeln("<b>" + (arrayline+1) + ".</b>&nbsp;");
892            
893        if (DisplayTitle == 1)
894        {
895            document.writeln("<a href=\"" + urlLink + "\"" + target + ">");
896            PrintHighlightDescription(pgtitle);
897            document.writeln("</a>");
898        }        
899        else
900            document.writeln("<a href=\"" + urlLink + "\"" + target + ">" + pgurl + "</a>");
901                   
902        if (UseCats) 
903        {           
904        	catpage = pageinfo[ipage][PAGEINFO_CAT];        	
905            document.write("<span class=\"category\">");
906            for (cati = 0; cati < NumCats; cati++)
907            {
908                if (catpage.charAt(cati) == "1")
909                    document.write(" ["+catnames[cati]+"]");
910            }             
911            document.writeln("</span>");
912        }
913        document.writeln("</div>");
914        
915        if (DisplayMetaDesc == 1)
916        {
917            // print meta description
918            document.writeln("<div class=\"description\">");            
919            PrintHighlightDescription(pgdesc);
920            document.writeln("</div>\n");
921        }
922        
923        info_str = "";
924        
925        if (DisplayTerms == 1)
926            info_str += STR_RESULT_TERMS_MATCHED + " " + output[arrayline][2];
927            
928        if (DisplayScore == 1) {
929            if (info_str.length > 0)
930                info_str += "&nbsp; - &nbsp;";
931            info_str += STR_RESULT_SCORE + " " + score;
932        }
933        
934        if (DisplayDate == 1) 
935        {
936        	pgdate = pageinfo[ipage][PAGEINFO_DATETIME];
937        	if (pgdate > 0)
938        	{        	
939	            datetime = new Date(pgdate*1000);
940	            if (info_str.length > 0)
941	                info_str += "&nbsp; - &nbsp;";
942	            info_str += datetime.getDate() + " " + months[datetime.getMonth()] + " " + datetime.getFullYear();
943	        }
944        }
945        
946        if (DisplayFilesize == 1) 
947        {
948			filesize = pageinfo[ipage][PAGEINFO_FILESIZE];
949        	filesize = Math.ceil(filesize / 1024);
950        	if (filesize < 1)
951            	filesize = 1;
952            	        	
953            if (info_str.length > 0)
954                info_str += "&nbsp; - &nbsp;";
955            info_str += filesize + "k";
956        }        
957             
958        if (DisplayURL == 1) {
959            if (info_str.length > 0)
960                info_str += "&nbsp; - &nbsp;";
961            info_str += STR_RESULT_URL + " " + pgurl;
962        }
963                   
964        document.writeln("<div class=\"infoline\">");
965        document.writeln(info_str);                        
966        document.writeln("</div></div>\n");
967        arrayline++;
968    }
969
970    // Show links to other result pages
971    if (num_pages > 1) {
972        // 10 results to the left of the current page
973        start_range = page - 10;
974        if (start_range < 1)
975            start_range = 1;
976
977        // 10 to the right
978        end_range = page + 10;
979        if (end_range > num_pages)
980            end_range = num_pages;
981
982        document.writeln("<div class=\"result_pages\">" + STR_RESULT_PAGES + " ");
983        if (page > 1)
984            document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + queryForURL + "&amp;zoom_page=" + (page-1) + "&amp;zoom_per_page=" + per_page + query_zoom_cats + "&amp;zoom_and=" + andq + "&amp;zoom_sort=" + sort + "\">&lt;&lt; " + STR_RESULT_PAGES_PREVIOUS + "</a> ");
985        for (i = start_range; i <= end_range; i++) 
986        {
987            if (i == page)
988                document.writeln(page + " ");
989            else
990                document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + queryForURL + "&amp;zoom_page=" + i + "&amp;zoom_per_page=" + per_page + query_zoom_cats + "&amp;zoom_and=" + andq + "&amp;zoom_sort=" + sort + "\">" + i + "</a> ");            
991        }
992        if (page != num_pages)
993            document.writeln("<a href=\"" + SelfURL + "?zoom_query=" + queryForURL + "&amp;zoom_page=" + (page+1) + "&amp;zoom_per_page=" + per_page + query_zoom_cats + "&amp;zoom_and=" + andq + "&amp;zoom_sort=" + sort + "\">" + STR_RESULT_PAGES_NEXT + " &gt;&gt;</a> ");
994        document.writeln("</div>");
995    }
996
997    document.writeln("</div>"); // end results style tag
998
999    if (Timing == 1) {
1000        timeEnd = new Date();
1001        timeDifference = timeEnd - timeStart;
1002        document.writeln("<div class=\"searchtime\"><br /><br />" + STR_SEARCH_TOOK + " " + (timeDifference/1000) + " " + STR_SECONDS + ".</div>\n");
1003    }
1004
1005    if (ZoomInfo == 1)
1006        document.writeln("<center><p><small>" + STR_POWEREDBY + " <a href=\"http://www.wrensoft.com/zoom/\" target=\"_blank\"><b>Zoom Search Engine</b></a></small></p></center>");
1007}
1008

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.