Index: wp-includes/functions.php
===================================================================
--- wp-includes/functions.php	(revision 15001)
+++ wp-includes/functions.php	(working copy)
@@ -4130,6 +4130,12 @@
 			wp_delete_comment($comment_id);
 		}
 	}
+
+	// delete orphaned draft menu items
+	$menu_items_to_delete = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts AS p LEFT JOIN $wpdb->postmeta AS m ON p.ID = m.post_id WHERE post_type = 'nav_menu_item' AND post_status = 'draft' AND meta_key = '_menu_item_orphaned' AND meta_value < '%d'", $delete_timestamp ) );
+
+	foreach( (array) $menu_items_to_delete as $menu_item_id )
+		wp_delete_post( $menu_item_id, true );
 }
 
 /**
Index: wp-includes/nav-menu.php
===================================================================
--- wp-includes/nav-menu.php	(revision 15001)
+++ wp-includes/nav-menu.php	(working copy)
@@ -247,7 +247,7 @@
  *
  * @since 3.0.0
  *
- * @param int $menu_id The ID of the menu. Required.
+ * @param int $menu_id The ID of the menu. Required. If "0", makes the menu item a draft orphan.
  * @param int $menu_item_db_id The ID of the menu item. If "0", creates a new menu item.
  * @param array $menu_item_data The menu item's data.
  * @return int The menu item's database ID or WP_Error object on failure.
@@ -263,11 +263,11 @@
 
 	$menu = wp_get_nav_menu_object( $menu_id );
 
-	if ( ! $menu || is_wp_error( $menu ) ) {
+	if ( ( ! $menu && 0 != $menu_id ) || is_wp_error( $menu ) ) {
 		return $menu;
 	}
 
-	$menu_items = (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) );
+	$menu_items = 0 == $menu_id ? array() : (array) wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft' ) );
 
 	$count = count( $menu_items );
 
@@ -289,8 +289,10 @@
 	);
 
 	$args = wp_parse_args( $menu_item_data, $defaults );
-
-	if ( 0 == (int) $args['menu-item-position'] ) {
+	
+	if ( 0 == $menu_id ) {
+		$args['menu-item-position'] = 1;
+	} elseif ( 0 == (int) $args['menu-item-position'] ) {
 		$last_item = array_pop( $menu_items );
 		$args['menu-item-position'] = ( $last_item && isset( $last_item->menu_order ) ) ? 1 + $last_item->menu_order : $count;
 	}
@@ -339,9 +341,11 @@
 		'post_parent' => $original_parent,
 		'post_title' => $args['menu-item-title'],
 		'post_type' => 'nav_menu_item',
-		'tax_input' => array( 'nav_menu' => array( intval( $menu->term_id ) ) ),
 	);
 
+	if ( 0 != $menu_id )
+		$post['tax_input'] = array( 'nav_menu' => array( intval( $menu->term_id ) ) );
+
 	// New menu item. Default is draft status
 	if ( 0 == $menu_item_db_id ) {
 		$post['ID'] = 0;
@@ -374,9 +378,12 @@
 		$args['menu-item-xfn'] = implode( ' ', array_map( 'sanitize_html_class', explode( ' ', $args['menu-item-xfn'] ) ) );
 		update_post_meta( $menu_item_db_id, '_menu_item_classes', $args['menu-item-classes'] );
 		update_post_meta( $menu_item_db_id, '_menu_item_xfn', $args['menu-item-xfn'] );
-
-		// @todo: only save custom link urls.
 		update_post_meta( $menu_item_db_id, '_menu_item_url', esc_url_raw($args['menu-item-url']) );
+		
+		if ( 0 == $menu_id )
+			update_post_meta( $menu_item_db_id, '_menu_item_orphaned', time() );
+		else
+			delete_post_meta( $menu_item_db_id, '_menu_item_orphaned' );
 
 		do_action('wp_update_nav_menu_item', $menu_id, $menu_item_db_id, $args );
 	}
@@ -740,6 +747,17 @@
 	}
 }
 
+/**
+ * Automatically add newly published page objects to menus with that as an option.
+ *
+ * @since 3.0.0
+ * @access private
+ *
+ * @param string $new_status The new status of the post object.
+ * @param string $old_status The old status of the post object.
+ * @param object $post The post object being transitioned from one status to another.
+ * @return void
+ */
 function _wp_auto_add_pages_to_menu( $new_status, $old_status, $post ) {
 	if ( 'publish' != $new_status || 'publish' == $old_status || 'page' != $post->post_type )
 		return;
Index: wp-admin/admin-ajax.php
===================================================================
--- wp-admin/admin-ajax.php	(revision 15001)
+++ wp-admin/admin-ajax.php	(working copy)
@@ -816,14 +816,9 @@
 
 	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
 
-	$menu_id = (int) $_POST['menu'];
-	if ( isset( $_POST['menu-item'] ) ) {
-		$item_ids = wp_save_nav_menu_items( $menu_id, $_POST['menu-item'] );
-		if ( is_wp_error( $item_ids ) )
-			die('-1');
-	} else {
-		$item_ids = array();
-	}
+	$item_ids = wp_save_nav_menu_items( 0, $_POST['menu-item'] );
+	if ( is_wp_error( $item_ids ) )
+		die('-1');
 
 	foreach ( (array) $item_ids as $menu_item_id ) {
 		$menu_obj = get_post( $menu_item_id );
Index: wp-admin/includes/nav-menu.php
===================================================================
--- wp-admin/includes/nav-menu.php	(revision 15001)
+++ wp-admin/includes/nav-menu.php	(working copy)
@@ -58,11 +58,25 @@
 			$original_object = get_post( $item->object_id );
 			$original_title = $original_object->post_title;
 		}
+
+		$classes = array(
+			'menu-item menu-item-depth-' . $depth,
+			'menu-item-' . esc_attr( $item->object ),
+			'menu-item-edit-' . ( ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? 'active' : 'inactive'),
+		);
+
+		$title = $item->title;
+
+		if ( isset( $item->post_status ) && 'draft' == $item->post_status ) {
+			$classes[] = 'pending';
+			$title = sprintf( _x('%s (Pending)', 'menu item title with "pending" indicating its draft status'), $item->title );
+		}
+
 		?>
-		<li id="menu-item-<?php echo $item_id; ?>" class="menu-item menu-item-depth-<?php echo $depth; ?> menu-item-<?php echo esc_attr( $item->object ); ?> menu-item-edit-<?php echo ( isset( $_GET['edit-menu-item'] ) && $item_id == $_GET['edit-menu-item'] ) ? 'active' : 'inactive'; ?>">
+		<li id="menu-item-<?php echo $item_id; ?>" class="<?php echo implode(' ', $classes ); ?>">
 			<dl class="menu-item-bar">
 				<dt class="menu-item-handle">
-					<span class="item-title"><?php echo esc_html( $item->title ); ?></span>
+					<span class="item-title"><?php echo esc_html( $title ); ?></span>
 					<span class="item-controls">
 						<span class="item-type"><?php echo esc_html( $item->type_label ); ?></span>
 						<span class="item-order">
@@ -871,7 +885,7 @@
  *
  * @since 3.0.0
  *
- * @param int $menu_id The menu ID for which to save this item.
+ * @param int $menu_id The menu ID for which to save this item. $menu_id of 0 makes a draft, orphaned menu item.
  * @param array $menu_data The unsanitized posted menu item data.
  * @return array The database IDs of the items saved
  */
@@ -879,7 +893,7 @@
 	$menu_id = (int) $menu_id;
 	$items_saved = array();
 
-	if ( is_nav_menu( $menu_id ) ) {
+	if ( 0 == $menu_id || is_nav_menu( $menu_id ) ) {
 
 		// Loop through all the menu items' POST values
 		foreach( (array) $menu_data as $_possible_db_id => $_item_object_data ) {
@@ -888,7 +902,7 @@
 				(
 					! isset( $_item_object_data['menu-item-type'] ) || // and item type either isn't set
 					in_array( $_item_object_data['menu-item-url'], array( 'http://', '' ) ) || // or URL is the default
-					'custom' != $_item_object_data['menu-item-type'] ||  // or it's not a custom menu item
+					! ( 'custom' == $_item_object_data['menu-item-type'] && ! isset( $_item_object_data['menu-item-db-id'] ) ) ||  // or it's not a custom menu item (but not the custom home page)
 					! empty( $_item_object_data['menu-item-db-id'] ) // or it *is* a custom menu item that already exists
 				)
 			) {
@@ -1004,6 +1018,15 @@
 		else
 			return new WP_Error( 'menu_walker_not_exist', sprintf( __('The Walker class named <strong>%s</strong> does not exist.'), $walker_class_name ) );
 
+		$some_pending_menu_items = false;
+		foreach( (array) $menu_items as $menu_item ) {
+			if ( isset( $menu_item->post_status ) && 'draft' == $menu_item->post_status )
+				$some_pending_menu_items = true;
+		}
+
+		if ( $some_pending_menu_items )
+			$result .= '<div class="updated post-body-plain">' . __('Click <em>Save</em> to make pending menu items public.') . '</div>';
+
 		$result .= walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $menu_items), 0, (object) array('walker' => $walker ) );
 		return $result;
 	} elseif ( is_wp_error( $menu ) ) {
Index: wp-admin/nav-menus.php
===================================================================
--- wp-admin/nav-menus.php	(revision 15001)
+++ wp-admin/nav-menus.php	(working copy)
@@ -543,15 +543,15 @@
 								<br class="clear" />
 								<div class="publishing-action">
 									<input class="button-primary menu-save" name="save_menu" type="submit" value="<?php empty($nav_menu_selected_id) ? esc_attr_e('Create Menu') : esc_attr_e('Save Menu'); ?>" />
-								</div><!--END .publishing-action-->
+								</div><!-- END .publishing-action -->
 
 								<?php if ( ! empty( $nav_menu_selected_id ) ) : ?>
 								<div class="delete-action">
 									<a class="submitdelete deletion menu-delete" href="<?php echo esc_url( wp_nonce_url( admin_url('nav-menus.php?action=delete&amp;menu=' . $nav_menu_selected_id), 'delete-nav_menu-' . $nav_menu_selected_id ) ); ?>"><?php _e('Delete Menu'); ?></a>
-								</div><!--END .delete-action-->
+								</div><!-- END .delete-action -->
 								<?php endif; ?>
-							</div><!--END .major-publishing-actions-->
-						</div><!--END #submitpost .submitbox-->
+							</div><!-- END .major-publishing-actions -->
+						</div><!-- END #submitpost .submitbox -->
 						<?php
 						wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
 						wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
@@ -559,7 +559,7 @@
 						?>
 						<input type="hidden" name="action" value="update" />
 						<input type="hidden" name="menu" id="menu" value="<?php echo esc_attr( $nav_menu_selected_id ); ?>" />
-					</div><!--END #nav-menu-header-->
+					</div><!-- END #nav-menu-header -->
 					<div id="post-body">
 						<div id="post-body-content">
 							<?php if ( is_nav_menu( $nav_menu_selected_id ) ) : ?>
