=== added file 'modules/menu/menu-rtl.css'
--- modules/menu/menu-rtl.css	1970-01-01 00:00:00 +0000
+++ modules/menu/menu-rtl.css	2007-11-18 08:32:01 +0000
@@ -0,0 +1,4 @@
+.menu-parent-select select,
+.menu-parent-select input {
+  float: right;
+}

=== added file 'modules/menu/menu.css'
--- modules/menu/menu.css	1970-01-01 00:00:00 +0000
+++ modules/menu/menu.css	2007-11-18 08:32:01 +0000
@@ -0,0 +1,4 @@
+.menu-parent-select select,
+.menu-parent-select input {
+  float: left; /* RTL */
+}

=== modified file 'modules/menu/menu.admin.inc'
--- modules/menu/menu.admin.inc	2007-11-17 14:25:23 +0000
+++ modules/menu/menu.admin.inc	2007-11-18 16:43:15 +0000
@@ -161,8 +161,7 @@ function theme_menu_overview_form($form)
 /**
  * Menu callback; Build the menu link editing form.
  */
-function menu_edit_item(&$form_state, $type, $item, $menu) {
-
+function _menu_edit_item(&$form_state, $type, $item, $menu) {
   $form['menu'] = array(
     '#type' => 'fieldset',
     '#title' => t('Menu settings'),
@@ -233,18 +232,13 @@ function menu_edit_item(&$form_state, $t
   );
 
   // Generate a list of possible parents (not including this item or descendants).
-  $options = menu_parent_options(menu_get_menus(), $item);
   $default = $item['menu_name'] .':'. $item['plid'];
   if (!isset($options[$default])) {
     $default = 'navigation:0';
   }
-  $form['menu']['parent'] = array(
-    '#type' => 'select',
-    '#title' => t('Parent item'),
-    '#default_value' => $default,
-    '#options' => $options,
-    '#description' => t('The maximum depth for an item and all its children is fixed at !maxdepth.  Some menu items may not be available as parents if selecting them would exceed this limit.', array('!maxdepth' => MENU_MAX_DEPTH)),
-    '#attributes' => array('class' => 'menu-title-select'),
+  $form['menu']['parents'] = array(
+    '#type' => 'menu_parent_select',
+    '#mlid' => $item['mlid'],
   );
   $form['menu']['weight'] = array(
     '#type' => 'weight',
@@ -293,11 +287,22 @@ function menu_item_delete_submit($form, 
 function menu_edit_item_submit($form, &$form_state) {
   $item = $form_state['values']['menu'];
   $item['options']['attributes']['title'] = $item['description'];
-  list($item['menu_name'], $item['plid']) = explode(':', $item['parent']);
+  $max_depth = 0;
+  $form = $form['menu']['parents']['wrapper']['parents'];
+  $item['plid'] = 0;
+  foreach (element_children($form) as $depth) {
+    $element = $form[$depth];
+    if (isset($element['select']) && $element['select']['#value'] && $depth > $max_depth) {
+      $item['plid'] = $element['select']['#value'];
+      $max_depth = $depth;
+    }
+  }
   if (!menu_link_save($item)) {
     drupal_set_message(t('There was an error saving the menu link.'), 'error');
   }
   $form_state['redirect'] = 'admin/build/menu-customize/'. $item['menu_name'];
+  // As long as the storage is not empty, Form API rebuilds the form.
+  unset($form_state['storage']['mlid']);
 }
 
 /**

=== modified file 'modules/menu/menu.module'
--- modules/menu/menu.module	2007-11-17 14:25:23 +0000
+++ modules/menu/menu.module	2007-11-18 16:42:47 +0000
@@ -99,7 +99,6 @@ function menu_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('menu_edit_item', 'add', NULL, 3),
     'type' => MENU_LOCAL_TASK,
-    'file' => 'menu.admin.inc',
   );
   $items['admin/build/menu-customize/%menu/edit'] = array(
     'title' => 'Edit menu',
@@ -136,6 +135,12 @@ function menu_menu() {
     'type' => MENU_CALLBACK,
     'file' => 'menu.admin.inc',
   );
+  $items['menu/js'] = array(
+    'title' => 'Menu JavaScript callback',
+    'page callback' => 'menu_form_js',
+    'access arguments' => array('administer menu'),
+    'type' => MENU_CALLBACK,
+  );
 
   return $items;
 }
@@ -149,10 +154,22 @@ function menu_theme() {
       'file' => 'menu.admin.inc',
       'arguments' => array('form' => NULL),
     ),
+    'menu_parent_select' => array(
+      'arguments' => array('form' => NULL),
+    ),
   );
 }
 
 /**
+ * Menu callback; Build the menu link editing form.
+ */
+function menu_edit_item(&$form_state, $type, $item, $menu) {
+  // The AHAH callback needs to find us.
+  require_once drupal_get_path('module', 'menu') .'/menu.admin.inc';
+  return _menu_edit_item($form_state, $type, $item, $menu);
+}
+
+/**
  * Implementation of hook_enable()
  *
  *  Add a link for each custom menu.
@@ -189,58 +206,159 @@ function menu_load($menu_name) {
   return db_fetch_array(db_query("SELECT * FROM {menu_custom} WHERE menu_name = '%s'", $menu_name));
 }
 
+function menu_elements() {
+  $types['menu_parent_select'] = array(
+    '#process' => array('menu_parent_select_process'),
+    '#input' => TRUE,
+    // Does not really matter but we set a #value just in case someone themes
+    // this element.
+    '#value' => '',
+    '#tree' => TRUE,
+  );
+  return $types;
+}
+
 /**
- * Return a list of menu items that are valid possible parents for the given menu item.
- *
- * @param $menus
- *   An array of menu names and titles, such as from menu_get_menus().
- * @param $item
- *   The menu item for which to generate a list of parents.
- *   If $item['mlid'] == 0 then the complete tree is returned.
- * @return
- *   An array of menu link titles keyed on the a string containing the menu name
- *   and mlid. The list excludes the given item and its children.
+ * Creates a parent selector fieldset for a given menu link.
  */
-function menu_parent_options($menus, $item) {
-
-  // If the item has children, there is an added limit to the depth of valid parents.
-  if (isset($item['parent_depth_limit'])) {
-    $limit = $item['parent_depth_limit'];
+function menu_parent_select_process($form, $edit, &$form_state) {
+  $original_mlid = $form['#mlid'];
+  if (isset($form_state['storage']['mlid'])) {
+    $mlid = $form_state['storage']['mlid'];
+    $collapsed = FALSE;
   }
   else {
-    $limit = _menu_parent_depth_limit($item);
+    $mlid = $original_mlid;
+    $collapsed = TRUE;
   }
-
-  foreach ($menus as $menu_name => $title) {
-    $tree = menu_tree_all_data($menu_name, NULL);
-    $options[$menu_name .':0'] = '<'. $title .'>';
-    _menu_parents_recurse($tree, $menu_name, '--', $options, $item['mlid'], $limit);
+  if (!$mlid) {
+    $mlid = db_result(db_query_range('SELECT mlid FROM {menu_links} WHERE plid = 0', 0, 1));
   }
-  return $options;
+  $item = menu_link_load($mlid);
+  $tree = menu_tree_all_data($item['menu_name'], $item);
+  $form = array_merge($form, array(
+    '#type' => 'fieldset',
+    '#title' => t('Parents'),
+    '#collapsible' => TRUE,
+    '#collapsed' => $collapsed,
+    '#theme' => 'menu_parent_select',
+  ));
+  $form['wrapper'] = array(
+    '#prefix' => '<div id="'. $form['#id'] .'-wrapper" class="menu-parent-select">',
+    '#suffix' => '</div>',
+  );
+  $form['wrapper']['parents'] = _menu_parent_select_recurse($tree, $original_mlid, TRUE);
+
+  $form['wrapper']['parent_submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Update'),
+    '#menu_parent_select' => &$form['wrapper']['parents'],
+    '#original_mlid' => $original_mlid,
+    '#submit' => array('_menu_parent_selector_update'),
+    '#ahah' => array(
+      'path' => 'menu/js',
+      'wrapper' => $form['#id'] .'-wrapper',
+      'selector' => '#'. $form['#id'] .'-wrapper select',
+      'event' => 'change',
+      'progress' => 'none',
+    ),
+  );
+  return $form;
 }
 
-/**
- * Recursive helper function for menu_parent_options().
- */
-function _menu_parents_recurse($tree, $menu_name, $indent, &$options, $exclude, $depth_limit) {
-  foreach ($tree as $data) {
-    if ($data['link']['depth'] > $depth_limit) {
-      // Don't iterate through any links on this level.
-      break;
-    }
-    if ($data['link']['mlid'] != $exclude && $data['link']['hidden'] >= 0) {
-      $title = $indent .' '. truncate_utf8($data['link']['title'], 30, TRUE, FALSE);
-      if ($data['link']['hidden']) {
-        $title .= ' ('. t('disabled') .')';
+function _menu_parent_select_recurse($tree, $original_mlid, $reset = FALSE) {
+  static $form;
+  if ($reset) {
+    $form = array();
+  }
+  foreach ($tree as $item) {
+    if (isset($item['link'])) {
+      $link = $item['link'];
+      // Skip the current element and all its children.
+      if ($link['mlid'] == $original_mlid) {
+        continue;
       }
-      $options[$menu_name .':'. $data['link']['mlid']] = $title;
-      if ($data['below']) {
-        _menu_parents_recurse($data['below'], $menu_name, $indent .'--', $options, $exclude, $depth_limit);
+      if (!$link['hidden']) {
+        $depth = $link['depth'];
+        $mlid = $link['mlid'];
+        if (!isset($form[$depth])) {
+          $form[$depth]['select'] = array(
+            '#type' => 'select',
+            '#default_value' => 0,
+            '#size' => 6,
+            '#multiple' => FALSE,
+            '#options' => array('-----'),
+          );
+        }
+        $form[$depth]['select']['#options'][$mlid] = $link['title'];
+        if ($link['in_active_trail']) {
+          $form[$depth]['select']['#default_value'] = $mlid;
+        }
       }
     }
+    if (!empty($item['below'])) {
+      _menu_parent_select_recurse($item['below'], $original_mlid);
+    }
+  }
+  return $form;
+}
+
+function _menu_parent_selector_update($form, &$form_state) {
+  $form_state['redirect'] = FALSE;
+  // We took care to make our selects easily findable.
+  $form = $form_state['clicked_button']['#menu_parent_select'];
+  $min_depth = MENU_MAX_DEPTH + 1;
+  // We need the first element that was changed.
+  foreach (element_children($form) as $depth) {
+    $element = $form[$depth];
+    if (isset($element['select']) && $element['select']['#default_value'] != $element['select']['#value'] && $depth < $min_depth) {
+      do {
+        $value = $form[$depth--]['select']['#value'];
+      } while ($depth && !$value);
+      $form_state['storage']['mlid'] = $value;
+      $min_depth = $depth + 1;
+    }
   }
 }
 
+function theme_menu_parent_select($form) {
+  drupal_add_css(drupal_get_path('module', 'menu') .'/menu.css');
+  // No need to show the button if we have javascript.
+  drupal_add_js('if (Drupal.jsEnabled) { $(document).ready(function() { $("#'. $form['wrapper']['parent_submit']['#id'] .'").css("display", "none"); }); }', 'inline');
+  return drupal_render($form);
+}
+
+function menu_form_js() {
+  $_POST['op'] = t('Update'); // Should AHAH provide this for me? I am unsure. I could know my own element, after all. But then agasin, what if someone renames the buttton? I think AHAH should pass to me the #value of the button it's tacked on.
+  $form_state = array('storage' => NULL, 'submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form = form_get_cache($form_build_id, &$form_state);
+  // #parameters has $form_id, $form_state and then whatever was passed to
+  // drupal_get_form.
+  $args = $form['#parameters'];
+  $form_id = array_shift($args);
+  $form['#post'] = $_POST;
+  $form['#redirect'] = FALSE;
+  // This will set up $form_state['clicked_button'] and
+  // $form_state['storage']['mlid'].
+  drupal_process_form($form_id, $form, $form_state);
+  // Recreate and re-cache the form.
+  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
+  // Pick up the parents of the pressed button.
+  $array_parents = $form_state['clicked_button']['#array_parents'];
+  // The last parent is the button itself, we need the wrapper instead.
+  array_pop($array_parents);
+  while ($array_parents) {
+    $parent = array_shift($array_parents);
+    $form = $form[$parent];
+  }
+  // Remove the button.
+  unset($form['parent_submit']);
+  // Render messages and selects.
+  $output = theme('status_messages') . drupal_render($form);
+  drupal_json(array('status' => TRUE, 'data' => $output));
+}
+
 /**
  * Reset a system-defined menu item.
  */

