/[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 10 - (show annotations)
Fri Sep 10 12:16:21 2004 UTC (19 years, 7 months ago) by dpavlin
File MIME type: application/javascript
File size: 4829 byte(s)
new object-oriented implementation contributed by Matko Adjelinic,
lot more debug output (which goes to debug div), configurable index
name which is argument to constructor

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

  ViewVC Help
Powered by ViewVC 1.1.26