autocompletion ameliorations
authorx2001corpet <x2001corpet@839d8a87-29fc-0310-9880-83ba4fa771e5>
Sat, 31 Mar 2007 15:03:05 +0000 (15:03 +0000)
committerx2001corpet <x2001corpet@839d8a87-29fc-0310-9880-83ba4fa771e5>
Sat, 31 Mar 2007 15:03:05 +0000 (15:03 +0000)
git-svn-id: svn+ssh://murphy/home/svn/platal/trunk@1636 839d8a87-29fc-0310-9880-83ba4fa771e5

Makefile
htdocs/css/base.css
htdocs/javascript/jquery.autocomplete.js [new file with mode: 0644]
modules/search.php
templates/search/adv.form.tpl

index 047d482..3859605 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -109,8 +109,6 @@ htdocs/css/banana.css:
 jquery: htdocs/javascript/jquery.js htdocs/javascript/jquery.autocomplete.js
 htdocs/javascript/jquery.js:
        wget http://jquery.com/src/jquery-latest.pack.js -O htdocs/javascript/jquery.js -q
-htdocs/javascript/jquery.autocomplete.js:
-       wget http://www.dyve.net/jquery/js/jquery.autocomplete.js -O htdocs/javascript/jquery.autocomplete.js -q
 
 ################################################################################
 
index 1e7cc4c..c305aec 100644 (file)
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  ***************************************************************************/
 
+.ac_results {
+    background-color: window;
+    border: 1px solid;
+    overflow: hidden;
+    padding:0px;
+}
+
 .ac_results ul {
     padding:0px;
     margin:0px;
 .ac_results li {
     display:block;
     padding: 2px;
-    background: white;
-    color: black;
     cursor:pointer;
 }
 .ac_results .over {
-    background: yellow;
+    background: highlight;
+    color: highlighttext;
 }
 
+.ac_loading {
+       background:window url(images/wait.gif) no-repeat scroll right center;
+}
 /* vim: set et ts=4 sts=4 sw=4: */
diff --git a/htdocs/javascript/jquery.autocomplete.js b/htdocs/javascript/jquery.autocomplete.js
new file mode 100644 (file)
index 0000000..18d1fe5
--- /dev/null
@@ -0,0 +1,326 @@
+/* jQuery autocomplete Copyright Dylan Verheul <dylan@dyve.net>
+ * Licensed like jQuery, see http://docs.jquery.com/License
+ */
+
+$.autocomplete = function(input, options) {
+       // Create a link to self
+       var me = this;
+
+       // Create jQuery object for input element
+       var $input = $(input).attr("autocomplete", "off");;
+
+       // Apply inputClass if necessary
+       if (options.inputClass) $input.addClass(options.inputClass);
+
+       // Create results
+       var results = document.createElement("div");
+       // Create jQuery object for results
+       var $results = $(results);
+       // Set default values for results
+       var pos = findPos(input);
+       $results.hide().addClass(options.resultsClass).css({
+               position: "absolute",
+               top: (pos.y + input.offsetHeight) + "px",
+               left: pos.x + "px",
+       });
+       // Add to body element
+       $(input).parent().append(results);
+
+       input.autocompleter = me;
+       input.lastSelected = $input.val();
+
+       var timeout = null;
+       var prev = "";
+       var active = -1;
+       var cache = {};
+       var keyb = false;
+
+       $input
+       .keydown(function(e) {
+               switch(e.keyCode) {
+                       case 38: // up
+                               e.preventDefault();
+                               moveSelect(-1);
+                               break;
+                       case 40: // down
+                               e.preventDefault();
+                               moveSelect(1);
+                               break;
+                       case 9:  // tab
+                       case 13: // return
+                               if (selectCurrent()) {
+                                       e.preventDefault();
+                               }
+                               break;
+                       default:
+                               active = -1;
+                               if (timeout) clearTimeout(timeout);
+                               timeout = setTimeout(onChange, options.delay);
+                               break;
+               }
+       })
+       .blur(function() {
+               hideResults();
+       });
+
+       hideResultsNow();
+
+       function onChange() {
+               var v = $input.val();
+               if (v == prev) return;
+               prev = v;
+               if (v.length >= options.minChars) {
+                       $input.addClass(options.loadingClass);
+                       requestData(v);
+               } else {
+                       $input.removeClass(options.loadingClass);
+                       $results.hide();
+               }
+       };
+
+       function moveSelect(step) {
+
+               var lis = $("li", results);
+               if (!lis) return;
+
+               active += step;
+
+               if (active < 0) {
+                       active = 0;
+               } else if (active >= lis.size()) {
+                       active = lis.size() - 1;
+               }
+
+               lis.removeClass("over");
+
+               $(lis[active]).addClass("over");
+
+               // Weird behaviour in IE
+               // if (lis[active] && lis[active].scrollIntoView) {
+               //      lis[active].scrollIntoView(false);
+               // }
+
+       };
+
+       function selectCurrent() {
+               var li = $("li.over", results)[0];
+               if (!li) {
+                       var $li = $("li", results);
+                       if (options.selectOnly) {
+                               if ($li.length == 1) li = $li[0];
+                       } else if (options.selectFirst) {
+                               li = $li[0];
+                       }
+               }
+               if (li) {
+                       selectItem(li);
+                       return true;
+               } else {
+                       return false;
+               }
+       };
+
+       function selectItem(li) {
+               if (!li) {
+                       li = document.createElement("li");
+                       li.extra = [];
+                       li.selectValue = "";
+               }
+               var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML);
+               input.lastSelected = v;
+               prev = v;
+               $results.html("");
+               $input.val(v);
+               hideResultsNow();
+               if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1);
+       };
+
+       function hideResults() {
+               if (timeout) clearTimeout(timeout);
+               timeout = setTimeout(hideResultsNow, 200);
+       };
+
+       function hideResultsNow() {
+               if (timeout) clearTimeout(timeout);
+               $input.removeClass(options.loadingClass);
+               if ($results.is(":visible")) {
+                       $results.hide();
+               }
+               if (options.mustMatch) {
+                       var v = $input.val();
+                       if (v != input.lastSelected) {
+                               selectItem(null);
+                       }
+               }
+       };
+
+       function receiveData(q, data) {
+               if (data) {
+                       $input.removeClass(options.loadingClass);
+                       results.innerHTML = "";
+                       if ($.browser.msie) {
+                               // we put a styled iframe behind the calendar so HTML SELECT elements don't show through
+                               $results.append(document.createElement('iframe'));
+                       }
+                       results.appendChild(dataToDom(data));
+                       $results.show();
+               } else {
+                       hideResultsNow();
+               }
+       };
+
+       function parseData(data) {
+               if (!data) return null;
+               var parsed = [];
+               var rows = data.split(options.lineSeparator);
+               for (var i=0; i < rows.length; i++) {
+                       var row = $.trim(rows[i]);
+                       if (row) {
+                               parsed[parsed.length] = row.split(options.cellSeparator);
+                       }
+               }
+               return parsed;
+       };
+
+       function dataToDom(data) {
+               var ul = document.createElement("ul");
+               var num = data.length;
+               for (var i=0; i < num; i++) {
+                       var row = data[i];
+                       if (!row) continue;
+                       var li = document.createElement("li");
+                       if (options.formatItem) {
+                               li.innerHTML = options.formatItem(row, i, num);
+                               li.selectValue = row[0];
+                       } else {
+                               li.innerHTML = row[0];
+                       }
+                       var extra = null;
+                       if (row.length > 1) {
+                               extra = [];
+                               for (var j=1; j < row.length; j++) {
+                                       extra[extra.length] = row[j];
+                               }
+                       }
+                       li.extra = extra;
+                       ul.appendChild(li);
+                       $(li).hover(
+                               function() { $("li", ul).removeClass("over"); $(this).addClass("over"); },
+                               function() { $(this).removeClass("over"); }
+                       ).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) });
+               }
+               return ul;
+       };
+
+       function requestData(q) {
+               if (!options.matchCase) q = q.toLowerCase();
+               var data = options.cacheLength ? loadFromCache(q) : null;
+               if (data) {
+                       receiveData(q, data);
+               } else {
+                       $.get(makeUrl(q), function(data) {
+                               data = parseData(data)
+                               addToCache(q, data);
+                               receiveData(q, data);
+                       });
+               }
+       };
+
+       function makeUrl(q) {
+               var url = options.url + "?q=" + q;
+               for (var i in options.extraParams) {
+                       url += "&" + i + "=" + options.extraParams[i];
+               }
+               return url;
+       };
+
+       function loadFromCache(q) {
+               if (!q) return null;
+               if (cache[q]) return cache[q];
+               if (options.matchSubset) {
+                       for (var i = q.length - 1; i >= options.minChars; i--) {
+                               var qs = q.substr(0, i);
+                               var c = cache[qs];
+                               if (c) {
+                                       var csub = [];
+                                       for (var j = 0; j < c.length; j++) {
+                                               var x = c[j];
+                                               var x0 = x[0];
+                                               if (matchSubset(x0, q)) {
+                                                       csub[csub.length] = x;
+                                               }
+                                       }
+                                       return csub;
+                               }
+                       }
+               }
+               return null;
+       };
+
+       function matchSubset(s, sub) {
+               if (!options.matchCase) s = s.toLowerCase();
+               var i = s.indexOf(sub);
+               if (i == -1) return false;
+               return i == 0 || options.matchContains;
+       };
+
+       this.flushCache = function() {
+               cache = {};
+       };
+
+       this.setExtraParams = function(p) {
+               options.extraParams = p;
+       };
+
+       function addToCache(q, data) {
+               if (!data || !q || !options.cacheLength) return;
+               if (!cache.length || cache.length > options.cacheLength) {
+                       cache = {};
+                       cache.length = 1; // we know we're adding something
+               } else if (!cache[q]) {
+                       cache.length++;
+               }
+               cache[q] = data;
+       };
+
+       function findPos(obj) {
+               var curleft = obj.offsetLeft || 0;
+               var curtop = obj.offsetTop || 0;
+               while (obj = obj.offsetParent) {
+                       curleft += obj.offsetLeft
+                       curtop += obj.offsetTop
+               }
+               return {x:curleft,y:curtop};
+       }
+}
+
+$.fn.autocomplete = function(url, options) {
+       // Make sure options exists
+       options = options || {};
+       // Set url as option
+       options.url = url;
+       // Set default values for required options
+       options.inputClass = options.inputClass || "ac_input";
+       options.resultsClass = options.resultsClass || "ac_results";
+       options.lineSeparator = options.lineSeparator || "\n";
+       options.cellSeparator = options.cellSeparator || "|";
+       options.minChars = options.minChars || 1;
+       options.delay = options.delay || 400;
+       options.matchCase = options.matchCase || 0;
+       options.matchSubset = typeof(options.matchSubset) != 'undefined' ? options.matchSubset : 1;
+       options.matchContains = options.matchContains || 0;
+       options.cacheLength = options.cacheLength || 1;
+       options.mustMatch = options.mustMatch || 0;
+       options.extraParams = options.extraParams || {};
+       options.loadingClass = options.loadingClass || "ac_loading";
+       options.selectFirst = options.selectFirst || false;
+       options.selectOnly = options.selectOnly || false;
+
+       this.each(function() {
+               var input = this;
+               new $.autocomplete(input, options);
+       });
+
+       // Don't break the chain
+       return this;
+}
index 300b65b..89104be 100644 (file)
@@ -247,7 +247,7 @@ class SearchModule extends PLModule
 
             $page->assign('url_search_form', $search->make_url(Array('rechercher'=>0)));
             if (!Env::i('with_soundex')) {
-                $page->assign('with_soundex', $search->make_url(Array()) . "&with_soundex=1");
+                $page->assign('with_soundex', $search->make_url(Array()) . "&amp;with_soundex=1");
             }
             $nb_tot = $search->show();
 
@@ -295,7 +295,7 @@ class SearchModule extends PLModule
         switch ($type) {
         case 'firstname': $field = 'prenom'; break;
         case 'name': $field = 'nom'; break;
-        case 'nickname': $field = 'profile_nick'; break;
+        case 'nickname': $field = 'profile_nick'; $db = 'auth_user_quick'; break;
         case 'entreprise': $db = 'entreprises'; $field = 'entreprise'; $unique='uid'; break;
         default: exit();
         }
index 99ed048..6027b17 100644 (file)
@@ -39,7 +39,7 @@
     }
     $(document).ready(function() {
       $(".autocomplete").each(function() {
-        $(this).autocomplete("search/autocomplete/"+this.name,{selectOnly:1,formatItem:format_autocomplete});
+        $(this).autocomplete("search/autocomplete/"+this.name,{selectOnly:1,formatItem:format_autocomplete,matchSubset:0,width:$(this).width()});
       });
     });
   {/literal}</script>