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

Diff of /trunk/bfilter.js

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 5 by dpavlin, Tue Sep 7 09:16:24 2004 UTC revision 22 by dpavlin, Tue Sep 14 22:42:55 2004 UTC
# Line 1  Line 1 
1  /*  /*
2     Fast filtering function using pre-sorted list elements     Fast filtering function using pre-sorted list elements
3     Dobrica Pavlinusic, dpavlin@rot13.org 2004-09-06     Dobrica Pavlinusic, dpavlin@rot13.org 2004-09-06
4       Matko Andjelinic, matko.andjelinic@gmail.com 2004-09-09 (contributed OO implementation)
5  */  */
6    
 var debug = 0;  
7    
8  function bfilter_init() {  function BFilter(arr) {
9          show_status();          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  var id_cache = Array();          this.arr = arr;
34            this.debug("index has "+this.arr.length+" parts");
35    
36  function element_id(id) {          if (! arr.min_len) {
37          if (id_cache[id]) {                  this.results("ERROR: index structure problem");
38                  return id_cache[id];                  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 {          } else {
53                  var el = document.getElementById(id);                  var el = document.getElementById(id);
54                  if (el) {                  if (el) {
55                          id_cache[id] = el;                          this.id_cache[id] = el;
56                          return el;                          return el;
57                  } else {                  } else {
58                          alert("can't find element id: "+id);                          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    
 // total number of hits  
 var hits = 0;  
69    
70  function show_status(status) {  BFilter.prototype.show_status = function (status) {
71          var html;          var html;
72          if (hits > 0) {          if (this.hits > 0) {
73                  html = "shown "+hits+" entries";                  html = "shown "+this.hits+" entries";
74          } else {          } else {
75                  html = "no results";                  html = "no results";
76          }          }
77          if (! status) {          if (! status) {
78                  html = "Enter "+min_len+" letter"+(min_len == 1 ? '' : 's')+" to filter entries";                  html = "Enter "+this.min_len+" letter"+(this.min_len == 1 ? '' : 's')+" to filter entries";
79                  status = "";                  status = "";
80          }          }
81    
82          var el = element_id("status");          var el = this.element_id("status");
83          el.innerHTML = html+status+"\n";          el.innerHTML = html+status+"\n";
84  }  }
85    
86  var wait = 0;  BFilter.prototype.results = function (html,clean) {
   
 function results(html,clean) {  
87    
88          if (! html) { html = ""; }          if (! html) { html = ""; }
89    
90          // results_div.style.cursor = 'wait'; // 'auto'          // results_div.style.cursor = 'wait'; // 'auto'
91          var results_div = element_id("results");          var results_div = this.element_id("results");
92          if (clean) {          if (clean) {
93                  results_div.innerHTML = html+"\n";                  results_div.innerHTML = html + "\n";
94          } else {          } else {
95                  results_div.innerHTML += html+"\n";                  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  // modified binary search to find first element with substring
117  function binarySearch(arr, find) {  BFilter.prototype.binarySearch = function (arr, find) {
118          if (!arr ||          if (!arr || typeof (find) == "undefined" || !arr.length) {
                 typeof (arr) != "object" ||  
                 typeof (find) == "undefined" || !arr.length) {  
119                  return null;                  return null;
120          }          }
121          var low = 0;          var low = 0;
# Line 74  function binarySearch(arr, find) { Line 126  function binarySearch(arr, find) {
126                  var mid = (low + high) / 2;                  var mid = (low + high) / 2;
127                  var aTry = (mid < 1) ? 0 : parseInt(mid);                  var aTry = (mid < 1) ? 0 : parseInt(mid);
128                    
129                  var curr = arr[aTry].substr(0,find.length).toLowerCase();                  var curr = arr[aTry][1].substr(0,find.length).toLowerCase();
130                  if (debug) { results("low="+low+" high="+high+" lastTry="+lastTry+" "+aTry+": "+curr+"<br>"); }                  this.debug("low="+low+" high="+high+" lastTry="+lastTry+" "+aTry+": "+curr);
131                  if (curr < find) {                  if (curr < find) {
132                          low = aTry + 1;                          low = aTry + 1;
133                          continue;                          continue;
# Line 91  function binarySearch(arr, find) { Line 143  function binarySearch(arr, find) {
143                  }                  }
144                  return aTry;                  return aTry;
145          }          }
146          if (debug) { results("lastTry="+lastTry+"<br>"); }          this.debug("lastTry="+lastTry);
147    
148          if (typeof (lastTry) != "undefined") {          if (typeof (lastTry) != "undefined") {
149                  return lastTry;                  return lastTry;
# Line 100  function binarySearch(arr, find) { Line 152  function binarySearch(arr, find) {
152          }          }
153  }  }
154    
155  function bfilter(document, id, find, arr) {  BFilter.prototype.filter = function (document, find) {
156    
157          results('',1);          this.results('',1);
158          hits = 0;          this.hits = 0;
159    
160          if (find.length < min_len) {          if (find.length < this.min_len) {
161                  show_status();                  this.show_status();
162                  return;                  return;
163          }          }
164    
165          if (debug) { results("filter: '"+find+"'<br>"); }          this.debug("filter: '"+find+"'");
166    
167          var find_lc = find.toLowerCase();          var find_lc = find.toLowerCase();
168    
169          var part = find_lc.substr(0,min_len);          var part = find_lc.substr(0,this.min_len);
170    
171          // no part found          // no part found
172          if (! arr[part]) {          if (! this.arr[part]) {
173                  show_status(" for <em>"+find+"</em><br>");                  this.show_status(" for <em>"+find+"</em><br>");
174                    this.debug("no part "+part);
175                  return;                  return;
176          }          }
177    
178          // start anim icon          // start anim icon
179          //results("<img  src=\"pie.gif\">&nbsp;Please wait, filtering...\n",1);          //results("<img  src=\"pie.gif\">&nbsp;Please wait, filtering...\n",1);
180    
181            var i;
182    
183          // full part? (optimization)          // full part? (optimization)
184          if (find.length == min_len) {          if (find.length == this.min_len) {
185                  var html = '';                  var html = '';
186                  for (var i = 0; i < arr[part].length; i++) {                  for (i = 0; i < this.arr[part].length; i++) {
187                          html += "<li>";                          html += this.html_pre +
188                          if (debug) { $html += i+": "; }                                  this.arr[part][i][0] +
189                          html += arr[part][i]+"</li>\n";                                  this.html_mid +
190                          hits++;                                  (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                  results(html);                  this.results(html);
198          } else {          } else {
199    
200                  var from = binarySearch(arr[part], find_lc);                  var from = this.binarySearch(this.arr[part], find_lc);
201    
202                  if (from != null) {                  if (from != null) {
203                                    
204                          if (debug) { results("loop "+from+" ... "+arr[part].length)+"<br>\n"; }                          this.debug("loop "+from+" ... "+this.arr[part].length);
205    
206                          var html = '';                          html = '';
207    
208                          for(var i = from ; i < arr[part].length ; i++) {                          for(i = from ; i < this.arr[part].length ; i++) {
209                                  if (arr[part][i].substring(0,find.length).toLowerCase() != find_lc) {                                  if (this.arr[part][i][1].substring(0,find.length).toLowerCase() != find_lc) {
210                                            this.debug("loop exit at "+i);
211                                          break;                                          break;
212                                  }                                  }
213                                  if (debug) { html += i+": "; }                                  html += this.html_pre +
214                                  html += arr[part][i]+"<br>\n";                                          this.arr[part][i][0] +
215                                  hits++;                                          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                          results(html);                          this.results(html);
                 } else {  
                         // clean results list  
 //                      results("",1);  
225                  }                  }
226    
227          }          }
228    
229          show_status(" for <em>"+find+"</em>");          this.show_status(" for <em>"+find+"</em>");
230    
231  }  }
232    
233    

Legend:
Removed from v.5  
changed lines
  Added in v.22

  ViewVC Help
Powered by ViewVC 1.1.26