/[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 25 - (show annotations)
Wed Sep 15 15:30:04 2004 UTC (19 years, 7 months ago) by dpavlin
File MIME type: application/javascript
File size: 4460 byte(s)
major refacture: 0 element is searched, all others can be used in result
function to generate html specific to one result. All that will be displayed
by calling display function which can add additional markup before or after
results.

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
13 // this function is called for each result
14 this.result = function (arr) {
15 return '<li><a href="'+arr[1]+'">'+
16 (this.hits % 2 == 0 ? '<span style="background: #e0e0e0;">' : '') +
17 arr[0] +
18 (this.hits % 2 == 0 ? '</span>' : '') +
19 '</a></li>';
20 }
21
22 // this function is called when updating innerHTML with results
23 this.display = function (html) {
24 return '<ul>'+html+'</ul>';
25 }
26
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;
94 } else {
95 results_div.innerHTML += this.display(html);
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][0].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.result(this.arr[part][i]);
188 this.hits++;
189 }
190 this.results(html);
191 } else {
192
193 var from = this.binarySearch(this.arr[part], find_lc);
194
195 if (from != null) {
196
197 this.debug("loop "+from+" ... "+this.arr[part].length);
198
199 html = '';
200
201 for(i = from ; i < this.arr[part].length ; i++) {
202 if (this.arr[part][i][0].substring(0,find.length).toLowerCase() != find_lc) {
203 this.debug("loop exit at "+i);
204 break;
205 }
206 html += this.result(this.arr[part][i]);
207 this.hits++;
208 }
209
210 this.results(html);
211 }
212
213 }
214
215 this.show_status(" for <em>"+find+"</em>");
216
217 }
218

  ViewVC Help
Powered by ViewVC 1.1.26