/[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 1 by dpavlin, Tue Sep 7 08:33:53 2004 UTC revision 11 by dpavlin, Fri Sep 10 12:42:58 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    
 function bfilter_init() {  
         show_status();  
 }  
7    
8  var id_cache = Array();  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  function element_id(id) {          if (! arr.min_len) {
27          if (id_cache[id]) {                  this.results("ERROR: index structure problem");
28                  return id_cache[id];                  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 {          } else {
43                  var el = document.getElementById(id);                  var el = document.getElementById(id);
44                  if (el) {                  if (el) {
45                          id_cache[id] = el;                          this.id_cache[id] = el;
46                          return el;                          return el;
47                  } else {                  } else {
48                          alert("can't find element id: "+id);                          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    
 // total number of hits  
 var hits = 0;  
58    
59  function show_status(status) {  BFilter.prototype.show_status = function (status) {
60          var html;          var html;
61          if (hits > 0) {          if (this.hits > 0) {
62                  html = "shown "+hits+" entries";                  html = "shown "+this.hits+" entries";
63          } else {          } else {
64                  html = "no results";                  html = "no results";
65          }          }
66          if (! status) {          if (! status) {
67                  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";
68                  status = "";                  status = "";
69          }          }
70    
71          var el = element_id("status");          var el = this.element_id("status");
72          el.innerHTML = html+status+"\n";          el.innerHTML = html+status+"\n";
73  }  }
74    
75  var wait = 0;  BFilter.prototype.results = function (html,clean) {
   
 function results(html,clean) {  
76    
77          if (! html) { html = ""; }          if (! html) { html = ""; }
78    
79          // results_div.style.cursor = 'wait'; // 'auto'          // results_div.style.cursor = 'wait'; // 'auto'
80          var results_div = element_id("results");          var results_div = this.element_id("results");
81          if (clean) {          if (clean) {
82                  results_div.innerHTML = html+"\n";                  results_div.innerHTML = html + "\n";
83          } else {          } else {
84                  results_div.innerHTML += html+"\n";                  results_div.innerHTML += this.html_full_pre + html +"\n" + this.html_full_post;
85          }          }
86  }  }
87    
88    
89  function bfilter(document, id, find, arr) {  BFilter.prototype.debug = function (html) {
90    
91          var debug = 0;          //return;
92    
93          results('',1);          // check if debugging is on
94          hits = 0;          if (! html) { return 1; }
95    
96          if (find.length < min_len) {          var debug_div = this.element_id("debug",1);
97                  show_status();          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;                  return;
154          }          }
155    
156          if (debug) { results("filter: '"+find+"'<br>"); }          this.debug("filter: '"+find+"'<br>");
157    
158          var find_lc = find.toLowerCase();          var find_lc = find.toLowerCase();
159    
160          var part = find_lc.substr(0,min_len);          var part = find_lc.substr(0,this.min_len);
161    
162          // no part found          // no part found
163          if (! arr[part]) {          if (! this.arr[part]) {
164                  show_status(" for <em>"+find+"</em><br>");                  this.show_status(" for <em>"+find+"</em><br>");
165                    this.debug("no part "+part);
166                  return;                  return;
167          }          }
168    
# Line 86  function bfilter(document, id, find, arr Line 170  function bfilter(document, id, find, arr
170          //results("<img  src=\"pie.gif\">&nbsp;Please wait, filtering...\n",1);          //results("<img  src=\"pie.gif\">&nbsp;Please wait, filtering...\n",1);
171    
172          // full part? (optimization)          // full part? (optimization)
173          if (find.length == min_len) {          if (find.length == this.min_len) {
174                  var html = '';                  var html = '';
175                  for (var i = 0; i < arr[part].length; i++) {                  for (var i = 0; i < this.arr[part].length; i++) {
176                          html += "<li>"+arr[part][i]+"</li>\n";                          html += this.html_pre +
177                          hits++;                                  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                  results(html);                  this.results(html);
187          } else {          } else {
188    
189                  for (var i = 0; i < arr[part].length; i++) {                  var from = this.binarySearch(this.arr[part], find_lc);
   
                         var text = arr[part][i].toLowerCase();  
190    
191                          if (debug) { results(part+" "+i+": "+text); }                  if (from != null) {
192                    
193                          // get li element by ID                          this.debug("loop "+from+" ... "+this.arr[part].length)+"<br>\n";
194    
195                          if (debug) { results("cmp: "+text.substring(0,find.length)+" "+find+" ["+text+"]<br>\n"); }                          var html = '';
196    
197                          if (text.substring(0,find.length) == find_lc) {                          for(var i = from ; i < this.arr[part].length ; i++) {
198                                  results("<li>"+text+"</li>\n");                                  if (this.arr[part][i][1].substring(0,find.length).toLowerCase() != find_lc) {
199                                  hits++;                                          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          // clean clock if no results          this.show_status(" for <em>"+find+"</em>");
         if (hits == 0) { results("",1); }  
         show_status(" for <em>"+find+"</em>");  
219    
220  }  }
221    
222    

Legend:
Removed from v.1  
changed lines
  Added in v.11

  ViewVC Help
Powered by ViewVC 1.1.26