r3393 committed - menu: some refactoring; somewhat closer to paging

r3393 committed - menu: some refactoring; somewhat closer to paging


Revision: 3393
Author: joern.zaefferer
Date: Sun Oct 25 05:08:59 2009
Log: menu: some refactoring; somewhat closer to paging
http://code.google.com/p/jquery-ui/source/detail?r=3393
Modified:
/branches/dev/ui/jquery.ui.menu.js
=======================================
--- /branches/dev/ui/jquery.ui.menu.js    Sun Oct 25 03:34:06 2009
+++ /branches/dev/ui/jquery.ui.menu.js    Sun Oct 25 05:08:59 2009
@@ -14,36 +14,45 @@
$.widget("ui.menu", {
    _init: function() {
-        
this.element.attr("role", "menu").attr("aria-activedescendant", "ui-active-menuitem").addClass("ui-menu
ui-widget ui-widget-content ui-corner-bottom");
-        var items = this.element.children("li");
        var self = this;
-        items.addClass("ui-menu-item").attr("role", "menuitem")
-        .children("a").attr("tabindex", "-1").addClass("ui-corner-all")
-        // replace with event delegation
+        this.element.attr("role", "menu")
+        .attr("aria-activedescendant", "ui-active-menuitem")
+        .addClass("ui-menu ui-widget ui-widget-content ui-corner-bottom")
        .click(function(e) {
            // temporary
            e.preventDefault();
-            self._trigger("selected", null, { item: $(this).parent() });
-        })
+            self.select();
+        });
+        var items = this.element.children("li");
+        items.addClass("ui-menu-item").attr("role", "menuitem")
+        .children("a").attr("tabindex", "-1").addClass("ui-corner-all")
+        // mouseenter doesn't work with event delegation
        .mouseenter(function() {
-            self.activeitem && self.deactivate(self.activeitem);
-            self.activate($(this));
+            self.activate($(this).parent());
        });
-
    },
    activate: function(item) {
-        this.activeitem =
item.addClass("ui-state-hover").attr("id", "ui-active-menuitem");
-        this._trigger("focus", null, { item: item.parent() });
+        this.deactivate();
+        this.active =
item.children("a").addClass("ui-state-hover").attr("id", "ui-active-menuitem").end();
+        this._trigger("focus", null, { item: item });
+        if (this.hasScroll()) {
+            var offset = item.offset().top - this.element.offset().top,
+                scroll = this.element.attr("scrollTop"),
+                elementHeight = this.element.height();
+            if (offset < 0) {
+                this.element.attr("scrollTop", scroll + offset);
+            } else if (offset > elementHeight) {
+                this.element.attr("scrollTop", scroll + offset - elementHeight +
item.height());
+            }
+        }
    },
-    deactivate: function(item) {
-        if (!item && this.activeitem) {
-            this.deactivate(this.activeitem);
-            this.activeitem = null;
+    deactivate: function() {
+        if (!this.active)
            return;
-        }
-        
item.removeClass("ui-state-hover").removeAttr("id", "ui-active-menuitem");
+        
this.active.children("a").removeClass("ui-state-hover").removeAttr("id", "ui-active-menuitem");
+        this.active = null;
    },
    next: function() {
@@ -55,60 +64,60 @@
    },
    first: function() {
-        return this.activeitem && !this.activeitem.parent().prev().length;
+        return this.active && !this.active.prev().length;
    },
    last: function() {
-        return this.activeitem && !this.activeitem.parent().next().length;
+        return this.active && !this.active.next().length;
    },
    move: function(direction, edge) {
-        if (!this.activeitem) {
-            this.activate(this.element.children(edge).children("a"));
+        if (!this.active) {
+            this.activate(this.element.children(edge));
            return;
        }
-        this.deactivate(this.activeitem);
-        var next = this.activeitem.parent()[direction]();
+        var next = this.active[direction]();
        if (next.length) {
-            this.activate(next.children("a"));
+            this.activate(next);
        } else {
-            this.activate(this.element.children(edge).children("a"));
-        }
-
-        /* scroll when necessary; need to adapt this code...
-        var offset = 0;
-        listItems.slice(0, active).each(function() {
-            offset += this.offsetHeight;
-        });
-        if ((offset + activeItem[0].offsetHeight - list.scrollTop()) >
list[0].clientHeight) {
-            list.scrollTop(offset + activeItem[0].offsetHeight -
list.innerHeight());
-        } else if (offset < list.scrollTop()) {
-            list.scrollTop(offset);
-        }
-        */
+            this.activate(this.element.children(edge));
+        }
    },
    nextPage: function() {
-        // TODO calculate pagesize
-        var pagesize = 8;
-        for (var i = 0; i < pagesize; i++) {
-            // TODO prevent triggering a focus event multiple times
-            this.move("next", "li:first");
+        if (this.hasScroll()) {
+            // TODO last item on page, then scroll one page down, otherwise select
last item on page
+            if (this.active && this.active.offset().top - this.element.offset().top
+ this.active.height() > this.element.height()) {
+                console.log("last");
+            } else {
+                console.log("not last");
+            }
+        } else {
+            // TODO when no active, select first
+            this.activate(this.element.children(this.last() ? ":first" : ":last"));
        }
    },
    previousPage: function() {
-        // TODO calculate pagesize
-        var pagesize = 8;
-        for (var i = 0; i < pagesize; i++) {
-            // TODO prevent triggering a focus event multiple times
-            this.move("prev", "li:last");
+        if (this.hasScroll()) {
+            // TODO first item on page, then scroll one page up, otherwise select
first item on page
+            if (this.active && this.active.offset().top - this.element.offset().top
<= 1) {
+                console.log("first");
+            } else {
+                console.log("not first");
+            }
+        } else {
+            // TODO when no active, select last
+            this.activate(this.element.children(this.first() ? ":last" : ":first"));
        }
    },
+    hasScroll: function() {
+        return this.element.height() < this.element.attr("scrollHeight");
+    },
+
    select: function() {
-        // merge with click handler
-        this._trigger("selected", null, { item: $(this.activeitem).parent() });
+        this._trigger("selected", null, { item: this.active });
    }
});