r3388 committed - autocomplete: implemented focus behaviour (update input when moving th...

r3388 committed - autocomplete: implemented focus behaviour (update input when moving th...


Revision: 3388
Author: joern.zaefferer
Date: Fri Oct 23 09:20:42 2009
Log: autocomplete: implemented focus behaviour (update input when moving
the menu focus, put back the entered value when moving "back")
http://code.google.com/p/jquery-ui/source/detail?r=3388
Modified:
/branches/dev/ui/jquery.ui.autocomplete.js
/branches/dev/ui/jquery.ui.menu.js
=======================================
--- /branches/dev/ui/jquery.ui.autocomplete.js    Fri Oct 23 08:18:50 2009
+++ /branches/dev/ui/jquery.ui.autocomplete.js    Fri Oct 23 09:20:42 2009
@@ -28,9 +28,11 @@
                break;
            case $.ui.keyCode.UP:
                self.move("previous");
+                event.preventDefault();
                break;
            case $.ui.keyCode.DOWN:
                self.move("next");
+                event.preventDefault();
                break;
            case $.ui.keyCode.ENTER:
                self.select();
@@ -68,8 +70,8 @@
        if ($.isArray(this.options.source)) {
            var array = this.options.source;
            this.source = function(request, response) {
-                // TODO escape regex characters
-                var matcher = new RegExp(request.term, "i");
+                // escape regex characters
+                var matcher = new
RegExp(request.term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|
\\])/gi, "\\$1"), "i");
                return $.grep(array, function(value) {
                return matcher.test(value)
                });
@@ -92,6 +94,7 @@
            if (this._trigger("search") === false)
                return;
            self.element.addClass("ui-autocomplete-loading");
+            self.term = value;
            function response(content) {
                if (content.length) {
                    self._trigger("open");
@@ -115,7 +118,7 @@
        clearTimeout(this.closing);
        if (this.menu) {
            this._trigger("close");
-            this.menu.remove();
+            this.menu.element.remove();
            this.menu = null;
        }
        if (this.previous != this.element.val()) {
@@ -141,9 +144,9 @@
    suggest: function(items) {
        items = this.normalize(items);
-        this.menu && this.menu.remove();
+        this.menu && this.menu.element.remove();
        var self = this;
-        var ul = this.menu = $("<ul/>");
+        var ul = $("<ul/>");
        $.each(items, function(index, item) {
            $("<li/>").data("item.autocomplete", item).append("<a>" + item.label
+ "</a>").appendTo(ul);
        });
@@ -152,7 +155,8 @@
        }).appendTo(document.body).menu({
            focus: function(event, ui) {
                self._trigger("focus", null, { item: ui.item.data("item.autocomplete")
});
-                // TODO update input value and revert back to the input when
focus "moves back" to the input
+                // use label or result?
+                self.element.val(ui.item.data("item.autocomplete").result);
            },
            selected: function(event, ui) {
                var data = ui.item.data("item.autocomplete");
@@ -168,6 +172,7 @@
            at: "left bottom",
            of: this.element
        });
+        this.menu = ul.data("menu");
        if (ul.width() <= this.element.width()) {
            ul.width(this.element.width());
        }
@@ -178,18 +183,23 @@
            this.search();
            return;
        }
-        this.menu.menu(direction);
+        if (this.menu.first() && direction == "previous" || this.menu.last() &&
direction == "next") {
+            this.element.val(this.term);
+            this.menu.deactivate();
+            return;
+        }
+        this.menu[direction]();
    },
    select: function() {
        if (!this.menu)
            return;
-        this.menu.menu("select");
+        this.menu.select();
    },
    widget: function() {
        // return empty jQuery object when menu isn't initialized yet
-        return this.menu || $([]);
+        return this.menu && this.menu.element || $([]);
    }
});
=======================================
--- /branches/dev/ui/jquery.ui.menu.js    Sat Oct 17 05:04:47 2009
+++ /branches/dev/ui/jquery.ui.menu.js    Fri Oct 23 09:20:42 2009
@@ -38,6 +38,11 @@
    },
    deactivate: function(item) {
+        if (!item && this.activeitem) {
+            this.deactivate(this.activeitem);
+            this.activeitem = null;
+            return;
+        }
        
item.removeClass("ui-state-hover").removeAttr("id", "ui-active-menuitem");
    },
@@ -49,6 +54,14 @@
        this.move("prev", "li:last");
    },
+    first: function() {
+        return this.activeitem && !this.activeitem.parent().prev().length;
+    },
+
+    last: function() {
+        return this.activeitem && !this.activeitem.parent().next().length;
+    },
+
    move: function(direction, edge) {
        if (!this.activeitem) {
            this.activate(this.element.children(edge).children("a"));