/[bfilter]/trunk/bfilter.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 /trunk/bfilter.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28 - (hide annotations)
Thu Sep 23 18:22:50 2004 UTC (19 years, 7 months ago) by dpavlin
File MIME type: application/javascript
File size: 4550 byte(s)
somewhat incompatible change: now generated html is stored inside object (so
you can overrride result function with createElement or something like that
to get interactive performance)

1 dpavlin 1 /*
2     Fast filtering function using pre-sorted list elements
3     Dobrica Pavlinusic, dpavlin@rot13.org 2004-09-06
4 dpavlin 10 Matko Andjelinic, matko.andjelinic@gmail.com 2004-09-09 (contributed OO implementation)
5 dpavlin 1 */
6    
7 dpavlin 2
8 dpavlin 10 function BFilter(arr) {
9     this.id_cache = Array();
10     // total number of hits
11     this.hits = 0;
12 dpavlin 1
13 dpavlin 28 this.results_html = null;
14    
15 dpavlin 25 // this function is called for each result
16     this.result = function (arr) {
17 dpavlin 28 this.results_html += '<li><a href="'+arr[1]+'">'+
18 dpavlin 25 (this.hits % 2 == 0 ? '<span style="background: #e0e0e0;">' : '') +
19     arr[0] +
20     (this.hits % 2 == 0 ? '</span>' : '') +
21     '</a></li>';
22 dpavlin 28 return true;
23 dpavlin 25 }
24    
25     // this function is called when updating innerHTML with results
26 dpavlin 28 this.display = function () {
27     if (this.results_html) {
28     return '<ul>'+this.results_html+'</ul>';
29     } else {
30     return null;
31     }
32 dpavlin 25 }
33    
34    
35 dpavlin 10 if (! arr) {
36     this.debug("ERROR: can't search empty array");
37     return;
38     }
39 dpavlin 1
40 dpavlin 10 this.arr = arr;
41     this.debug("index has "+this.arr.length+" parts");
42    
43     if (! arr.min_len) {
44     this.results("ERROR: index structure problem");
45     return;
46 dpavlin 1 } else {
47 dpavlin 10 this.min_len = arr.min_len;
48     }
49    
50     this.debug("index part has "+this.min_len+" parts");
51    
52     this.show_status();
53    
54     }
55    
56     BFilter.prototype.element_id = function (id,no_alert) {
57     if (this.id_cache[id]) {
58     return this.id_cache[id];
59     } else {
60 dpavlin 1 var el = document.getElementById(id);
61     if (el) {
62 dpavlin 10 this.id_cache[id] = el;
63 dpavlin 1 return el;
64     } else {
65 dpavlin 10 if (! no_alert) {
66     alert("can't find element id: "+id);
67     } else {
68     // don't look it up again
69     this.id_cache[id] = null;
70     }
71 dpavlin 1 }
72     }
73 dpavlin 22 return null;
74 dpavlin 1 }
75    
76    
77 dpavlin 10 BFilter.prototype.show_status = function (status) {
78 dpavlin 1 var html;
79 dpavlin 10 if (this.hits > 0) {
80     html = "shown "+this.hits+" entries";
81 dpavlin 1 } else {
82     html = "no results";
83     }
84     if (! status) {
85 dpavlin 10 html = "Enter "+this.min_len+" letter"+(this.min_len == 1 ? '' : 's')+" to filter entries";
86 dpavlin 1 status = "";
87     }
88    
89 dpavlin 10 var el = this.element_id("status");
90 dpavlin 1 el.innerHTML = html+status+"\n";
91     }
92    
93 dpavlin 10 BFilter.prototype.results = function (html,clean) {
94 dpavlin 1
95     if (! html) { html = ""; }
96    
97     // results_div.style.cursor = 'wait'; // 'auto'
98 dpavlin 10 var results_div = this.element_id("results");
99 dpavlin 1 if (clean) {
100 dpavlin 25 results_div.innerHTML = html;
101 dpavlin 1 } else {
102 dpavlin 28 html = this.display();
103     if (html) results_div.innerHTML += html;
104 dpavlin 1 }
105     }
106    
107 dpavlin 10
108     BFilter.prototype.debug = function (html) {
109    
110     //return;
111    
112     // check if debugging is on
113     if (! html) { return 1; }
114    
115     var debug_div = this.element_id("debug",1);
116 dpavlin 22 if (! debug_div) { return null; }
117 dpavlin 10
118 dpavlin 12 debug_div.innerHTML += html + "<br>\n";
119 dpavlin 22
120     return null;
121 dpavlin 10 }
122    
123    
124 dpavlin 2 // modified binary search to find first element with substring
125 dpavlin 10 BFilter.prototype.binarySearch = function (arr, find) {
126 dpavlin 6 if (!arr || typeof (find) == "undefined" || !arr.length) {
127 dpavlin 2 return null;
128     }
129     var low = 0;
130     var high = arr.length - 1;
131     var middlearr = parseInt(arr.length / 2);
132     var lastTry;
133     while (low <= high) {
134     var mid = (low + high) / 2;
135     var aTry = (mid < 1) ? 0 : parseInt(mid);
136    
137 dpavlin 25 var curr = arr[aTry][0].substr(0,find.length).toLowerCase();
138 dpavlin 12 this.debug("low="+low+" high="+high+" lastTry="+lastTry+" "+aTry+": "+curr);
139 dpavlin 2 if (curr < find) {
140     low = aTry + 1;
141     continue;
142     }
143     if (curr > find) {
144     high = aTry - 1;
145     continue;
146     }
147     if (curr == find) {
148     high = aTry - 1;
149     lastTry = aTry;
150     continue;
151     }
152     return aTry;
153     }
154 dpavlin 12 this.debug("lastTry="+lastTry);
155 dpavlin 1
156 dpavlin 2 if (typeof (lastTry) != "undefined") {
157     return lastTry;
158     } else {
159     return null;
160     }
161     }
162    
163 dpavlin 10 BFilter.prototype.filter = function (document, find) {
164 dpavlin 1
165 dpavlin 10 this.results('',1);
166     this.hits = 0;
167 dpavlin 1
168 dpavlin 10 if (find.length < this.min_len) {
169     this.show_status();
170 dpavlin 1 return;
171     }
172    
173 dpavlin 12 this.debug("filter: '"+find+"'");
174 dpavlin 1
175     var find_lc = find.toLowerCase();
176    
177 dpavlin 10 var part = find_lc.substr(0,this.min_len);
178 dpavlin 1
179     // no part found
180 dpavlin 10 if (! this.arr[part]) {
181     this.show_status(" for <em>"+find+"</em><br>");
182     this.debug("no part "+part);
183 dpavlin 1 return;
184     }
185    
186     // start anim icon
187     //results("<img src=\"pie.gif\">&nbsp;Please wait, filtering...\n",1);
188    
189 dpavlin 22 var i;
190    
191 dpavlin 1 // full part? (optimization)
192 dpavlin 10 if (find.length == this.min_len) {
193 dpavlin 22 for (i = 0; i < this.arr[part].length; i++) {
194 dpavlin 28 this.result(this.arr[part][i]);
195 dpavlin 10 this.hits++;
196 dpavlin 1 }
197 dpavlin 28 this.results();
198 dpavlin 1 } else {
199    
200 dpavlin 10 var from = this.binarySearch(this.arr[part], find_lc);
201 dpavlin 1
202 dpavlin 2 if (from != null) {
203    
204 dpavlin 12 this.debug("loop "+from+" ... "+this.arr[part].length);
205 dpavlin 5
206 dpavlin 22 for(i = from ; i < this.arr[part].length ; i++) {
207 dpavlin 25 if (this.arr[part][i][0].substring(0,find.length).toLowerCase() != find_lc) {
208 dpavlin 10 this.debug("loop exit at "+i);
209 dpavlin 2 break;
210     }
211 dpavlin 28 this.result(this.arr[part][i]);
212 dpavlin 10 this.hits++;
213 dpavlin 1 }
214 dpavlin 5
215 dpavlin 28 this.results();
216 dpavlin 1 }
217    
218     }
219    
220 dpavlin 10 this.show_status(" for <em>"+find+"</em>");
221 dpavlin 1
222     }
223    

  ViewVC Help
Powered by ViewVC 1.1.26