Index: admin_menu.js
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/admin_menu/admin_menu.js,v
retrieving revision 1.7.2.7.2.18
diff -u -p -r1.7.2.7.2.18 admin_menu.js
--- admin_menu.js	20 Feb 2010 23:44:04 -0000	1.7.2.7.2.18
+++ admin_menu.js	12 Mar 2010 19:20:12 -0000
@@ -198,22 +198,63 @@ Drupal.admin.behaviors.hover = function 
     );
   }
 
+  var maxHeight = $(window).height() - $adminMenu.height();
+  $('li.expandable > ul', $adminMenu).mousemove(function (e) {
+    // Don't move if the hovered link does not belong to this list.
+    // @todo Better way? Heavily hard-codes current theme markup.
+    if (e.target.parentNode.parentNode != this) {
+      return;
+    }
+    // Stop moving when hovering expandable parent items.
+    // @todo Adjust relativeY based on amount of (direct) preceding expandable items.
+    if ($(e.target.parentNode).is('.expandable')) {
+      return;
+    }
+    var $ul = $(this);
+    var $li = $ul.parent();
+    var liOffset = $li.offset().top;
+    var liHeight = $li.height();
+    // No animation if the tree fits into the visible viewport.
+    if (liOffset + $ul.height() > maxHeight) {
+      // @todo Child trees overlay parent trees.
+      // $ul.css('zIndex', -10);
+      // Based on the current cursor position, subtract vertical offset of the
+      // list item, and subtract...
+      var relativeY = e.pageY - liOffset - liHeight;
+      // Child trees below a top-level item are positioned below the item, not
+      // next to it. We therefore have to subtract the list item height.
+      if (!$li.parents('li.expandable').length) {
+        relativeY -= liHeight;
+      }
+      if (e.pageY > liOffset + liHeight) {
+        $ul.css('top', liOffset - relativeY);
+      }
+      // When reaching the bottom offset of the list item, unset the custom
+      // positioning.
+      else {
+        $ul.css('top', '');
+      }
+    }
+  });
+  // @todo Delayed mouseout needs to be put back in, resp. see hoverIntent issue.
+  return;
+
   // Delayed mouseout.
   $('li.expandable', $adminMenu).hover(
     function () {
       // Stop the timer.
       clearTimeout(this.sfTimer);
       // Display child lists.
-      $('> ul', this)
-        .css({left: 'auto', display: 'block'})
+      $ul = $('> ul', this);
+      $ul.css({left: 'auto', display: 'block'})
         // Immediately hide nephew lists.
         .parent().siblings('li').children('ul').css({left: '-999em', display: 'none'});
     },
     function () {
       // Start the timer.
-      var uls = $('> ul', this);
+      var $ul = $('> ul', this);
       this.sfTimer = setTimeout(function () {
-        uls.css({left: '-999em', display: 'none'});
+        $ul.css({left: '-999em', display: 'none'});
       }, 400);
     }
   );
Index: admin_menu.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/admin_menu/admin_menu.module,v
retrieving revision 1.43.2.17.2.30
diff -u -p -r1.43.2.17.2.30 admin_menu.module
--- admin_menu.module	20 Feb 2010 01:02:58 -0000	1.43.2.17.2.30
+++ admin_menu.module	12 Mar 2010 21:33:44 -0000
@@ -82,6 +82,51 @@ function admin_menu_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'admin_menu.inc',
   );
+
+  $items['admin/test'] = array(
+    'title' => 'Dropdown test',
+    'access arguments' => array('administer site configuration'),
+  );
+  $factor = 100;
+  foreach (range(1, 40) as $l1) {
+    $items["admin/test/$l1"] = array(
+      'title' => "{$l1}th-level item",
+      'access callback' => TRUE,
+    );
+    if (rand(0, 200) >= $factor) {
+      foreach (range(1, 6) as $l2) {
+        $items["admin/test/$l1/$l2"] = array(
+          'title' => "{$l2}th-level item",
+          'access callback' => TRUE,
+        );
+        if (rand(0, 150) >= $factor) {
+          foreach (range(1, 6) as $l3) {
+            $items["admin/test/$l1/$l2/$l3"] = array(
+              'title' => "{$l3}th-level item",
+              'access callback' => TRUE,
+            );
+            if (rand(0, 130) >= $factor) {
+              foreach (range(1, 6) as $l4) {
+                $items["admin/test/$l1/$l2/$l3/$l4"] = array(
+                  'title' => "{$l4}th-level item",
+                  'access callback' => TRUE,
+                );
+                if (rand(0, 110) >= $factor) {
+                  foreach (range(1, 10) as $l5) {
+                    $items["admin/test/$l1/$l2/$l3/$l4/$l5"] = array(
+                      'title' => "{$l5}th-level item",
+                      'access callback' => TRUE,
+                    );
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
   return $items;
 }
 
