/[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

Contents of /trunk/bfilter.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (show annotations)
Tue Sep 14 22:42:55 2004 UTC (19 years, 7 months ago) by dpavlin
File MIME type: application/javascript
File size: 5065 byte(s)
cleanup code a bit more to be general purpose

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

  ViewVC Help
Powered by ViewVC 1.1.26