--- trunk/bfilter.js 2004/09/10 12:16:21 10 +++ trunk/bfilter.js 2004/09/25 22:13:13 32 @@ -4,16 +4,24 @@ Matko Andjelinic, matko.andjelinic@gmail.com 2004-09-09 (contributed OO implementation) */ +top.__bfilter_obj = new Array(); + function BFilter(arr) { this.id_cache = Array(); // total number of hits this.hits = 0; - this.html_pre = ''; - this.html_post = '
'; - this.html_full_pre = ''; - this.html_full_post = ''; + + // store reference to this object for later (YAK) + this.obj_count = top.__bfilter_obj.length; + top.__bfilter_obj[this.obj_count] = this; + + // clear results html + this.results_html = null; + + // show results after 0.2s + this.timeout = 200; + this.timeout_handle = null; if (! arr) { this.debug("ERROR: can't search empty array"); @@ -24,7 +32,7 @@ this.debug("index has "+this.arr.length+" parts"); if (! arr.min_len) { - this.results("ERROR: index structure problem"); + alert("ERROR: index structure problem"); return; } else { this.min_len = arr.min_len; @@ -34,58 +42,79 @@ this.show_status(); + // show alert for non-existent elements? + this.show_alert = 1; + } BFilter.prototype.element_id = function (id,no_alert) { if (this.id_cache[id]) { return this.id_cache[id]; } else { - var el = document.getElementById(id); + var el = self.document.getElementById(id); if (el) { this.id_cache[id] = el; return el; } else { - if (! no_alert) { - alert("can't find element id: "+id); + if (! no_alert && this.show_alert) { + this.show_alert = confirm("can't find element id: "+id); } else { // don't look it up again this.id_cache[id] = null; } } } + return null; } -BFilter.prototype.show_status = function (status) { - var html; - if (this.hits > 0) { - html = "shown "+this.hits+" entries"; - } else { - html = "no results"; - } - if (! status) { - html = "Enter "+this.min_len+" letter"+(this.min_len == 1 ? '' : 's')+" to filter entries"; - status = ""; +BFilter.prototype.show_status = function (status,no_hits) { + var html = ""; + if (! no_hits) { + if (this.hits > 0) { + html = "shown "+this.hits+" entries"; + } else { + html = "no results"; + } + if (! status) { + html = "Enter "+this.min_len+" letter"+(this.min_len == 1 ? '' : 's')+" to filter entries"; + status = ""; + } } var el = this.element_id("status"); el.innerHTML = html+status+"\n"; -} -BFilter.prototype.results = function (html,clean) { + return true; +} - if (! html) { html = ""; } +// this function is called to clean old results list +BFilter.prototype.clear_results = function () { + var results_div = this.element_id("results"); + results_div.innerHTML = ''; + this.results_html = ''; + return true; +} + +// this function is called for each result +BFilter.prototype.result = function (arr) { + this.results_html += '
  • '+ + (this.hits % 2 == 0 ? '' : '') + + arr[0] + + (this.hits % 2 == 0 ? '' : '') + + '
  • '; + return true; +} - // results_div.style.cursor = 'wait'; // 'auto' +// this function is called when updating innerHTML with results +BFilter.prototype.show_results = function () { var results_div = this.element_id("results"); - if (clean) { - results_div.innerHTML = html + "\n"; - } else { - results_div.innerHTML += this.html_full_pre + html +"\n" + this.html_full_post; + if (this.results_html) { + results_div.innerHTML = ''; } + return true; } - BFilter.prototype.debug = function (html) { //return; @@ -94,47 +123,46 @@ if (! html) { return 1; } var debug_div = this.element_id("debug",1); - if (! debug_div) { return; } + if (! debug_div) { return null; } - if (debug_div.innerHTML) { - debug_div.innerHTML =+ html + "x
    \n"; - } else { - debug_div.innerHTML = html + "y
    \n"; - } + debug_div.innerHTML += html + "
    \n"; + + return null; } // modified binary search to find first element with substring -BFilter.prototype.binarySearch = function (arr, find) { - if (!arr || typeof (find) == "undefined" || !arr.length) { +BFilter.prototype.binarySearch = function (arr, user_filter) { + if (!arr || typeof (user_filter) == "undefined" || !arr.length) { return null; } var low = 0; var high = arr.length - 1; var middlearr = parseInt(arr.length / 2); + this.debug("binarySearch: "+low+"-("+middlearr+")-"+high+" for "+user_filter); var lastTry; while (low <= high) { var mid = (low + high) / 2; var aTry = (mid < 1) ? 0 : parseInt(mid); - var curr = arr[aTry][1].substr(0,find.length).toLowerCase(); - this.debug("low="+low+" high="+high+" lastTry="+lastTry+" "+aTry+": "+curr+"
    "); - if (curr < find) { + var curr = arr[aTry][0].substr(0,user_filter.length).toLowerCase(); + this.debug(low+"-"+high+", "+aTry+"="+curr+" last="+lastTry); + if (curr < user_filter) { low = aTry + 1; continue; } - if (curr > find) { + if (curr > user_filter) { high = aTry - 1; continue; } - if (curr == find) { + if (curr == user_filter) { high = aTry - 1; lastTry = aTry; continue; } return aTry; } - this.debug("lastTry="+lastTry+"
    "); + this.debug("lastTry="+lastTry); if (typeof (lastTry) != "undefined") { return lastTry; @@ -143,80 +171,82 @@ } } -BFilter.prototype.filter = function (document, find) { +BFilter.prototype.filter = function (user_filter) { + this.debug("set timeout for "+this.obj_count+" to "+this.timeout); + if (this.timeout_handle) { + clearTimeout(this.timeout_handle); + this.timeout_handle = null; + } + this.timeout_handle=setTimeout("top.__bfilter_obj["+this.obj_count+"].show_filter('"+user_filter.replace(/'/,"\\'")+"');", this.timeout); + return true; +} + +BFilter.prototype.show_filter = function (user_filter) { + + this.show_status("Showing entries with "+user_filter+"\n"); - this.results('',1); + if (this.timeout_handle) { + clearTimeout(this.timeout_handle); + this.timeout_handle = null; + this.debug("timeout cleared"); + } + + this.clear_results(); this.hits = 0; - if (find.length < this.min_len) { + if (user_filter.length < this.min_len) { this.show_status(); return; } - this.debug("filter: '"+find+"'
    "); - - var find_lc = find.toLowerCase(); + var user_filter_lc = user_filter.toLowerCase(); + + this.debug("filter: '"+user_filter_lc+"'"); - var part = find_lc.substr(0,this.min_len); + var part = user_filter_lc.substr(0,this.min_len); // no part found if (! this.arr[part]) { - this.show_status(" for "+find+"
    "); + this.show_status(" for "+user_filter+"
    "); this.debug("no part "+part); return; } // start anim icon - //results(" Please wait, filtering...\n",1); + // Please wait, filtering... + + var i; // full part? (optimization) - if (find.length == this.min_len) { - var html = ''; - for (var i = 0; i < this.arr[part].length; i++) { - html += this.html_pre + - this.arr[part][i][0] + - this.html_mid + - (this.hits % 2 == 0 ? '' : ''); - if (this.debug()) { html += i+": "; } - html += this.arr[part][i][1] + - (this.hits % 2 == 0 ? '' : '') + - this.html_post + "\n"; + if (user_filter.length == this.min_len) { + for (i = 0; i < this.arr[part].length; i++) { + this.result(this.arr[part][i]); this.hits++; } - this.results(html); + this.show_results(); } else { - var from = this.binarySearch(this.arr[part], find_lc); + var from = this.binarySearch(this.arr[part], user_filter_lc); if (from != null) { - this.debug("loop "+from+" ... "+this.arr[part].length)+"
    \n"; - - var html = ''; + this.debug("loop "+from+" ... "+this.arr[part].length); - for(var i = from ; i < this.arr[part].length ; i++) { - if (this.arr[part][i][1].substring(0,find.length).toLowerCase() != find_lc) { + for(i = from ; i < this.arr[part].length ; i++) { + if (this.arr[part][i][0].substring(0,user_filter.length).toLowerCase() != user_filter_lc) { this.debug("loop exit at "+i); break; } - html += this.html_pre + - this.arr[part][i][0] + - this.html_mid + - (this.hits % 2 == 0 ? '' : ''); - if (this.debug()) { html += i+": "; } - html += this.arr[part][i][1] + - (this.hits % 2 == 0 ? '' : '') + - this.html_post + "\n"; + this.result(this.arr[part][i]); this.hits++; } - this.results(html); + this.show_results(); } } - this.show_status(" for "+find+""); + this.show_status(" for "+user_filter+""); } -