Index: uc_order.admin.inc
===================================================================
--- uc_order.admin.inc	(revision 242)
+++ uc_order.admin.inc	(working copy)
@@ -1056,9 +1056,9 @@
   }
 
   $output .= '<div class="order-pane abs-left">'. drupal_render($form['order_id'])
-           . drupal_render($form['form_id']) . drupal_render($form['form_token'])
-           . drupal_render($form['submit-changes']) . drupal_render($form['delete'])
-            .'</div>';
+           . drupal_render($form['form_id']) . drupal_render($form['form_build_id'])
+           . drupal_render($form['form_token']) . drupal_render($form['submit-changes'])
+           . drupal_render($form['delete']) .'</div>';
 
   return $output;
 }
@@ -1125,150 +1125,177 @@
 }
 
 /**
- * Populate the product add/edit div on the order edit screen.
+ * Product selection AHAH handler.
  */
-function uc_order_edit_products($order) {
-  if (is_array($_POST['products'])) {
-    foreach ($_POST['products'] as $key => $product) {
-      $product['data'] = unserialize($product['data']);
-      uc_order_product_save($order->order_id, (object) $product);
-    }
-  }
+function uc_order_ahah_product_select() {
+  $form_state = array('storage' => NULL, 'submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form = form_get_cache($form_build_id, $form_state);
+  $args = $form['#parameters'];
+  $form_id = $_POST['form_id'];
+  $form_state['post'] = $form['#post'] = $_POST;
+  $form['#programmed'] = $form['#redirect'] = FALSE;
 
-  switch ($_POST['action']) {
-    case 'add_blank':
-      db_query("INSERT INTO {uc_order_products} (order_id, qty) VALUES (%d, 1)", $order->order_id);
-      if (variable_get('uc_order_logging', TRUE)) {
-        uc_order_log_changes($order->order_id, array('add' => 'Added new product line to order.'));
+  drupal_process_form($form_id, $form, $form_state);
+  $errors = form_get_errors();
+  if (empty($errors)) {
+    if ($form_state['next_form_id']) {
+      if ($form_state['next_form_id'] == 'uc_order_product_select_form') {
+        $elements['selector'] = uc_order_product_select_form($form['#order_id'], $form_state['values']['product_search'], $form_state);
       }
-      break;
-    case 'add':
-      $product = node_load(intval($_POST['nid']));
-      $product->qty = intval($_POST['qty']);
-      $product->price = $product->sell_price;
-      if (module_exists('uc_manufacturer')) {
-        $product->manufacturer = uc_product_get_manufacturer($product->nid);
-        $product->manufacturer = $product->manufacturer->name;
+      else if ($form_state['next_form_id'] == 'uc_order_add_product_form') {
+        $elements['selector'] = uc_order_add_product_form($form['#order_id'], $form_state['values']['unid'], $form_state);
       }
-      if (module_exists('uc_attribute')) {
-        $form_state['values'] = array(
-          'nid' => intval($_POST['nid']),
-          'attributes' => $_POST['attributes'],
-        );
-        $product->data = module_invoke_all('add_to_cart_data', $form_state['values']);
-        $attributes = array();
-        $product->options = _uc_cart_product_get_options($product);
-        foreach ($product->options as $option) {
-          $product->cost += $option['cost'];
-          $product->price += $option['price'];
-          $product->weight += $option['weight'];
-          $attributes[$option['attribute']] = $option['name'];
-        }
-        $product->data['attributes'] = $attributes;
-        $product->module = $product->data['module'];
-        if ($product->data['model']) {
-          $product->model = $product->data['model'];
-        }
-      }
-      uc_order_product_save($order->order_id, $product);
-      if (variable_get('uc_order_logging', TRUE)) {
-        uc_order_log_changes($order->order_id, array('add' => 'Added ('. $product->qty .') '. $product->title .' to order.'));
-      }
-      break;
-    case 'remove':
-      db_query("DELETE FROM {uc_order_products} WHERE order_product_id = %d", intval($_POST['opid']));
-      break;
+    }
+    
+    // We should always append product list to the product pane content.
+    $elements['list'] = uc_order_edit_products_form($form['#order_id'], $form_state);
+
+    $form['products'] = $elements;
+    form_set_cache($form_build_id, $form, $form_state);
   }
+  else {
+    $elements = $form['products'];
+  }
+  $form = form_builder($form_id, $form, $form_state);
+  $output = drupal_render($form['products']);
 
-  $result = db_query("SELECT * FROM {uc_order_products} WHERE order_id = %d ORDER BY order_product_id", $order->order_id);
+  // If a newly inserted widget contains AHAH behaviors, they normally won't
+  // work because AHAH doesn't know about those - it just attaches to the exact
+  // form elements that were initially specified in the Drupal.settings object.
+  // The new ones didn't exist then, so we need to update Drupal.settings
+  // by ourselves in order to let AHAH know about those new form elements.
+  $javascript = drupal_add_js(NULL, NULL);
+  if (isset($javascript['setting'])) {
+    $output .= '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js(call_user_func_array('array_merge_recursive', $javascript['setting'])) .');</script>';
+  }
+
+  drupal_json(array(
+    'status'   => TRUE,
+    'data'     => theme('status_messages') . $output,
+  ));
+}
+
+
+/**
+ * Part of drupal_process_form() function.
+ * Allows altering sub-forms of order administration form. As these subforms are
+ * not forms itself, there are no other way to make alterations on them.
+ */
+function uc_alter_sub_form(&$form, &$form_state, $form_id) {
+  $data = &$form;
+  $data['__drupal_alter_by_ref'] = array(&$form_state);
+  drupal_alter('form_'. $form_id, $data);
+
+  // __drupal_alter_by_ref is unset in the drupal_alter() function, we need
+  // to repopulate it to ensure both calls get the data.
+  $data['__drupal_alter_by_ref'] = array(&$form_state);
+  drupal_alter('form', $data, $form_id);
+}
+
+
+function uc_order_load_products($order_id) {
+  $result = db_query("SELECT * FROM {uc_order_products} WHERE order_id = %d ORDER BY order_product_id", $order_id);
   while ($product = db_fetch_object($result)) {
     $products[] = $product;
   }
-
-  print uc_strip_form(drupal_get_form('uc_order_edit_products_form', $products));
-  exit();
+  return $products;
 }
 
-function uc_order_edit_products_form($form_state, $products) {
+/**
+ * List of order's products.
+ */
+function uc_order_edit_products_form($order_id, $form_state = NULL) {
+  $products = uc_order_load_products($order_id);
+
   if (($product_count = count($products)) > 0) {
     $form['products'] = tapir_get_table('op_products_edit_table');
     for ($i = 0; $i < $product_count; $i++) {
+      // we should use this to avoid bugs with image_button
+      $name = $products[$i]->order_product_id;
       $form['products'][$i]['remove'] = array(
-        '#type' => 'checkbox',
-        '#name' => "products[$i][remove]",
-        '#theme' => 'uc_order_remove_product',
-        '#parents' => array(),
-        '#img_id' => $products[$i]->order_product_id,
+        '#type' => 'image_button',
+        '#id' => $products[$i]->order_product_id,
+        '#name' => "products[$name][remove]",
+        '#src' => drupal_get_path('module', 'uc_store') .'/images/error.gif',
+        '#ahah' => array(
+          'path' => 'admin/store/orders/ahah/product_select',
+          'wrapper' => 'products-container',
+          'method' => 'replace',
+        ),
+        '#submit' => array('uc_order_edit_products_form_remove_submit'),
       );
       $form['products'][$i]['order_product_id'] = array(
-        '#type' => 'hidden',
-        '#value' => $products[$i]->order_product_id,
-        '#name' => "products[$i][order_product_id]",
-        '#parents' => array(),
-      );
+         '#type' => 'hidden',
+         '#value' => $products[$i]->order_product_id,
+         '#name' => "products[$name][order_product_id]",
+         '#parents' => array(),
+       );
       $form['products'][$i]['nid'] = array(
-        '#type' => 'hidden',
-        '#value' => $products[$i]->nid,
-        '#name' => "products[$i][nid]",
-        '#parents' => array(),
-      );
+         '#type' => 'hidden',
+         '#value' => $products[$i]->nid,
+         '#name' => "products[$name][nid]",
+         '#parents' => array(),
+       );
       $form['products'][$i]['qty'] = array(
-        '#type' => 'textfield',
-        '#value' => $products[$i]->qty,
-        '#name' => "products[$i][qty]",
-        '#parents' => array(),
-        '#size' => 2,
-        '#maxlength' => 6,
-      );
+         '#type' => 'textfield',
+         '#value' => $products[$i]->qty,
+         '#name' => "products[$name][qty]",
+         '#parents' => array(),
+         '#size' => 2,
+         '#maxlength' => 6,
+       );
       $form['products'][$i]['title'] = array(
-        '#type' => 'textfield',
-        '#value' => $products[$i]->title,
-        '#name' => "products[$i][title]",
-        '#parents' => array(),
-        '#size' => 30,
-      );
+         '#type' => 'textfield',
+         '#value' => $products[$i]->title,
+         '#name' => "products[$name][title]",
+         '#parents' => array(),
+         '#size' => 30,
+       );
       $form['products'][$i]['model'] = array(
-        '#type' => 'textfield',
-        '#value' => $products[$i]->model,
-        '#name' => "products[$i][model]",
-        '#parents' => array(),
-        '#size' => 6,
-      );
+         '#type' => 'textfield',
+         '#value' => $products[$i]->model,
+         '#name' => "products[$name][model]",
+         '#parents' => array(),
+         '#size' => 6,
+       );
       $form['products'][$i]['weight'] = array(
-        '#type' => 'textfield',
-        '#value' => $products[$i]->weight,
-        '#name' => "products[$i][weight]",
-        '#parents' => array(),
-        '#size' => 3,
-      );
+         '#type' => 'textfield',
+         '#value' => $products[$i]->weight,
+         '#name' => "products[$name][weight]",
+         '#parents' => array(),
+         '#size' => 3,
+       );
       $form['products'][$i]['cost'] = array(
-        '#type' => 'textfield',
-        '#value' => $products[$i]->cost,
-        '#name' => "products[$i][cost]",
-        '#parents' => array(),
-        '#size' => 5,
-      );
+         '#type' => 'textfield',
+         '#value' => $products[$i]->cost,
+         '#name' => "products[$name][cost]",
+         '#parents' => array(),
+         '#size' => 5,
+       );
       $form['products'][$i]['price'] = array(
-        '#type' => 'textfield',
-        '#value' => $products[$i]->price,
-        '#name' => "products[$i][price]",
-        '#parents' => array(),
-        '#size' => 5,
-      );
+         '#type' => 'textfield',
+         '#value' => $products[$i]->price,
+         '#name' => "products[$name][price]",
+         '#parents' => array(),
+         '#size' => 5,
+       );
       $form['products'][$i]['data'] = array(
-        '#type' => 'hidden',
-        '#value' => $products[$i]->data,
-        '#name' => "products[$i][data]",
-        '#parents' => array(),
-      );
-    }
-  }
-  else {
+         '#type' => 'hidden',
+         '#value' => $products[$i]->data,
+         '#name' => "products[$name][data]",
+         '#parents' => array(),
+       );
+     }
+   }
+   else {
     $form['products'][]['remove'] = array(
       '#value' => t('This order contains no products.'),
       '#cell_attributes' => array('colspan' => 'full'),
     );
   }
+
+  uc_alter_sub_form($form, $form_state, 'uc_order_edit_products_form');
   return $form;
 }
 
@@ -1276,17 +1303,264 @@
   return drupal_render($form);
 }
 
-function theme_uc_order_remove_product($form) {
-  return '<img id="'. $form['#img_id'] .'" src="'
-    .  base_path() . drupal_get_path('module', 'uc_store')
-    .'/images/error.gif" style="padding-top: 1px; padding-left: .8em; '
-    .'padding-right: 2px; float: left; cursor: pointer;" '
-    .'alt="'. t('Remove this product.') .'" onclick="'
-    .'remove_product_button(\''. t('Remove product from order?') .'\', this.id);" />'
-    . drupal_render($form);
+function uc_order_edit_products_form_remove_submit($form, &$form_state) {
+  $order_id = $form['#order_id'];
+  $order_product_id = $form_state['clicked_button']['#id'];
+  db_query("DELETE FROM {uc_order_products} WHERE order_product_id = %d", $order_product_id);
+  if (variable_get('uc_order_logging', TRUE)) {
+    uc_order_log_changes($order_id, array('add' => 'Product removed from order.'));
+  }
+  $form_state['rebuild'] = TRUE;
 }
 
 /**
+ * Products pane title subform.
+ */
+function product_pane_buttons($order_id) {
+  $form['add_product'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add product'),
+    '#ahah' => array(
+      'path' => 'admin/store/orders/ahah/product_select',
+      'wrapper' => 'products-container',
+      'method' => 'replace',
+    ),
+    '#submit' => array('product_pane_buttons_add_product_submit'),
+  );
+  $form['add_blank'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add blank line'),
+    '#ahah' => array(
+      'path' => 'admin/store/orders/ahah/product_select',
+      'wrapper' => 'products-container',
+      'method' => 'replace',
+    ),
+    '#submit' => array('product_pane_buttons_add_blank_submit'),
+  );
+  return $form;
+}
+
+function product_pane_buttons_add_product_submit($form, &$form_state) {
+  $form_state['next_form_id'] = 'uc_order_product_select_form';
+  $form_state['rebuid'] = TRUE;
+}
+
+function product_pane_buttons_add_blank_submit($form, &$form_state) {
+  $order_id = $form['#order_id'];
+  db_query("INSERT INTO {uc_order_products} (order_id, qty) VALUES (%d, 1)", $order_id);
+  if (variable_get('uc_order_logging', TRUE)) {
+    uc_order_log_changes($order_id, array('add' => 'Added new product line to order.'));
+  }
+  $form_state['rebuid'] = TRUE;
+}
+
+/**
+ * Form in which can be selected product to add or searched by.
+ */
+function uc_order_product_select_form($order_id, $search = NULL, $form_state = NULL) {
+  $options = get_avail_products($search);
+
+  $form['#weight'] = -5;
+  $form['unid'] = array(
+    '#type' => 'select',
+    '#title' => t('Select a product'),
+    '#options' => $options,
+    '#size' => 7,
+    '#weight' => 1,
+  );
+  $form['product_search'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $search,
+    '#title' => t('Search by name or model/SKU (* is the wildcard)'),
+    '#weight' => 2,
+  );
+  
+  $form['buttons']['#weight'] = 10;
+  $form['buttons']['select'] = array(
+    '#type' => 'button',
+    '#value' => t('Select'),
+    '#ahah' => array(
+      'path' => 'admin/store/orders/ahah/product_select',
+      'wrapper' => 'products-container',
+      'method' => 'replace',
+    ),
+    '#weight' => 1,
+    '#validate' => array('uc_order_product_select_form_select_validate'),
+  );
+  $form['buttons']['search'] = array(
+    '#type' => 'button',
+    '#value' => t('Search'),
+    '#ahah' => array(
+      'path' => 'admin/store/orders/ahah/product_select',
+      'wrapper' => 'products-container',
+      'method' => 'replace',
+    ),
+    '#weight' => 2,
+    '#validate' => array('uc_order_product_select_form_search_validate'),
+  );
+  $form['buttons']['cancel'] = array(
+    '#type' => 'button',
+    '#value' => t('Cancel'),
+    '#ahah' => array(
+      'path' => 'admin/store/orders/ahah/product_select',
+      'wrapper' => 'products-container',
+      'method' => 'replace',
+    ),
+    '#weight' => 10,
+    '#validate' => array('uc_order_product_select_rebuild'),
+  );
+  $form['#prefix'] = '<div id="products-selector" class="product-select-box2">';
+  $form['#suffix'] = '</div>';
+  
+  // This gives us a chance to alter subforms like usual, but in correct way.
+  uc_alter_sub_form($form, $form_state, 'uc_order_product_select_form');
+  return $form;
+}
+
+/**
+ * Get allowed products or search results for uc_order_product_select_form().
+ */
+function get_avail_products($search) {
+  $product_types = uc_product_types();
+  if ($search) {
+    $search = strtolower(str_replace('*', '%', check_plain($search)));
+
+    $product_types[] = $search;
+    $db_place = db_placeholders($product_types, 'varchar');
+
+    $args = array_merge($product_types, array($search, $search));
+    $result = db_query("SELECT n.nid, n.title FROM {node} AS n LEFT JOIN "
+                      ."{uc_products} AS p ON n.nid = p.nid WHERE n.type IN "
+                      ."(". $db_place .") AND (LOWER(n.title) LIKE '%s%%' OR LOWER(p.model) LIKE '%s%%')"
+                      ." ORDER BY n.title", $args);
+  }
+  else {
+  $result = db_query("SELECT nid, title FROM {node} WHERE type IN (". db_placeholders($product_types, 'varchar') .") "
+                      ."ORDER BY title", $product_types);
+  }
+  while ($row = db_fetch_object($result)) {
+    $options[$row->nid] = $row->title;
+  }
+
+  if (count($options) == 0) {
+    $options[0] = t('No products found.');
+  }
+  return $options;
+}
+
+function uc_order_product_select_form_select_validate($form, &$form_state) {
+  if (!isset($form_state['values']['unid']) || !$form_state['values']['unid']) {
+    form_set_error('unid', t('Please, select a product first.'));
+  }
+  $form_state['next_form_id'] = 'uc_order_add_product_form';
+  $form_state['rebuild'] = TRUE;
+}
+
+function uc_order_product_select_form_search_validate($form, &$form_state) {
+  $form_state['next_form_id'] = 'uc_order_product_select_form';
+  $form_state['rebuild'] = TRUE;
+}
+
+function uc_order_product_select_rebuild($form, &$form_state) {
+  $form_state['rebuild'] = TRUE;
+}
+
+
+/**
+ * Intermediate div that lets you set the qty and attributes for a product.
+ */
+function uc_order_add_product_form($order_id, $nid, $form_state = NULL) {
+  $form['#order_id'] = $order_id;
+  $form['nid'] = array('#type' => 'hidden', '#value' => $nid);
+  $form['qty'] = array('#type' => 'textfield', '#title' => 'Qty', '#default_value' => 1, '#size' => 2, '#maxlength' => 5);
+  
+  $form['buttons'] = array(
+    '#weight' => 10,
+  );
+  $form['buttons']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add to order'),
+    '#ahah' => array(
+      'path' => 'admin/store/orders/ahah/product_select',
+      'wrapper' => 'products-container',
+      'method' => 'replace',
+    ),
+    '#submit' => array('uc_order_add_product_form_submit'),
+  );
+  $form['buttons']['cancel'] = array(
+    '#type' => 'submit',
+    '#value' => t('Cancel'),
+    '#ahah' => array(
+      'path' => 'admin/store/orders/ahah/product_select',
+      'wrapper' => 'products-container',
+      'method' => 'replace',
+    ),
+    '#validate' => array('uc_order_product_select_rebuild'),
+  );
+  $form['#prefix'] = '<div id="products-selector" class="product-select-box2">';
+  $form['#suffix'] = '</div>';
+  
+  // This gives us a chance to alter subforms like usual, but in correct way.
+  uc_alter_sub_form($form, $form_state, 'uc_order_add_product_form');
+  return $form;
+}
+
+function uc_order_add_product_form_submit($form, &$form_state) {
+  $order_id = $form['#order_id'];
+  $product = node_load($form_state['values']['nid']);
+
+  if (is_null($data)) {
+    $data = array('module' => 'uc_product');
+  }
+  if (!isset($data['module'])) {
+    $data['module'] = 'uc_product';
+  }
+  $product->qty = $form_state['values']['qty'];
+  $product->price = $product->sell_price;
+  if (module_exists('uc_manufacturer')) {
+    $product->manufacturer = uc_product_get_manufacturer($product->nid);
+    $product->manufacturer = $product->manufacturer->name;
+  }
+  $product->data = module_invoke_all('add_to_cart_data', $form_state['values']);
+  if (module_exists('uc_attribute')) {
+    $attributes = array();
+    $product->options = _uc_cart_product_get_options($product);
+    foreach ($product->options as $option) {
+      $product->cost += $option['cost'];
+      $product->price += $option['price'];
+      $product->weight += $option['weight'];
+      $attributes[$option['attribute']] = $option['name'];
+    }
+    $product->data['attributes'] = $attributes;
+    $product->module = $product->data['module'];
+    if ($product->data['model']) {
+      $product->model = $product->data['model'];
+    }
+  }
+
+  $result = module_invoke_all('add_to_cart', $product->nid, $product->qty, $product->data);
+  if (is_array($result) && !empty($result)) {
+    foreach ($result as $row) {
+      if ($row['success'] === FALSE) {
+        if (isset($row['message']) && !empty($row['message'])) {
+          $message = $row['message'];
+        }
+        else {
+          $message = t('Sorry, that item is not available for purchase at this time.');
+        }
+        drupal_set_message($message, 'error');
+        return;
+      }
+    }
+  }
+  uc_order_product_save($order_id, $product);
+  if (variable_get('uc_order_logging', TRUE)) {
+    uc_order_log_changes($order_id, array('add' => 'Added ('. $product->qty .') '. $product->title .' to order.'));
+  }
+  $form_state['rebuild'] = TRUE;
+}
+
+/**
  * Form to add a line item to an order.
  */
 function uc_order_add_line_item_form($form_state, $order, $line_item_id) {
@@ -1353,109 +1627,6 @@
 }
 
 /**
- * When the Catalog module or uBrowser aren't enabled, use this product select.
- */
-function uc_order_load_product_select($order) {
-  $args = uc_product_types();
-
-  if (!empty($_POST['search'])) {
-    $search = strtolower(str_replace('*', '%', check_plain($_POST['search'])));
-
-    $args[] = $search;
-    $args[] = $search;
-    $result = db_query("SELECT n.nid, n.title FROM {node} AS n LEFT JOIN "
-                      ."{uc_products} AS p ON n.nid = p.nid WHERE n.type IN "
-                      ."(". db_placeholders($args, 'varchar') .") AND (LOWER(n.title) LIKE '%s' OR LOWER(p.model) LIKE '%s')"
-                      ." ORDER BY n.title", $args);
-  }
-  else {
-    $result = db_query("SELECT nid, title FROM {node} WHERE type IN (". db_placeholders($args, 'varchar') .") "
-                      ."ORDER BY title", $args);
-  }
-  while ($row = db_fetch_object($result)) {
-    $options[$row->nid] = $row->title;
-  }
-
-  $output = drupal_get_form('uc_order_product_select_form', $order->order_id, $options);
-
-  print $output;
-  exit();
-}
-
-function uc_order_product_select_form($form_state, $order_id, $options = array()) {
-  if (count($options) == 0) {
-    $options[0] = t('No products found.');
-  }
-
-  $form['unid'] = array(
-    '#type' => 'select',
-    '#title' => t('Select a product'),
-    '#options' => $options,
-    '#size' => 7,
-    '#attributes' => array('ondblclick' => 'return select_product();'),
-  );
-  $form['product_search'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Search by name or model/SKU (* is the wildcard)'),
-  );
-
-  $form['select'] = array(
-    '#type' => 'button',
-    '#value' => t('Select'),
-    '#attributes' => array('onclick' => 'return select_product();'),
-  );
-  $form['search'] = array(
-    '#type' => 'button',
-    '#value' => t('Search'),
-    '#attributes' => array('onclick' => 'return load_product_select('. $order_id .', true);'),
-  );
-  $form['close'] = array(
-    '#type' => 'button',
-    '#value' => t('Close'),
-    '#attributes' => array('onclick' => 'return close_product_select();'),
-  );
-
-  return $form;
-}
-
-/**
- * Intermediate div that lets you set the qty and attributes for a product.
- */
-function uc_order_add_product($order, $product) {
-  $output = '<div style="margin: 1em;"><strong>Add '. $product->title .'</strong>'
-          . drupal_get_form('uc_order_add_product_form', $order->order_id, $product->nid) .'</div>';
-
-  print $output;
-  exit();
-}
-
-function uc_order_add_product_form($form_state, $order_id, $nid) {
-  $form['nid'] = array(
-    '#type' => 'hidden',
-    '#value' => $nid,
-  );
-  $form['add-qty'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Qty'),
-    '#default_value' => '1',
-    '#size' => 2,
-    '#maxlength' => 5,
-  );
-  $form['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Add to order'),
-    '#attributes' => array('onclick' => 'return add_product_to_order('. $order_id .', '. $nid .');')
-  );
-  $form['cancel'] = array(
-    '#type' => 'submit',
-    '#value' => t('Cancel'),
-    '#attributes' => array('onclick' => "\$('#add-product-button').click(); return false;"),
-  );
-
-  return $form;
-}
-
-/**
  * Display an invoice in the browser, convert it to PDF, or e-mail it as HTML.
  */
 function uc_order_invoice($order, $op = 'view') {
Index: uc_order.css
===================================================================
--- uc_order.css	(revision 242)
+++ uc_order.css	(working copy)
@@ -64,6 +64,26 @@
   padding-bottom: .5em;
 }
 
+.order-pane-title div {
+  display:inline;
+}
+
+input {
+  vertical-align:middle;
+}
+
+.progress-disabled {
+  float:none;
+}
+.ahah-progress {
+  float:none;
+  display:inline;
+}
+.ahah-progress .throbber {
+  display:inline-block;
+  float:none;
+}
+
 .pos-left {
   float: left;
 }
Index: uc_order.js
===================================================================
--- uc_order.js	(revision 242)
+++ uc_order.js	(working copy)
@@ -234,158 +234,6 @@
   return false;
 }
 
-/**
- * Load the products div on the order edit screen.
- */
-function uc_order_load_product_edit_div(order_id) {
-  $(document).ready(
-    function() {
-      add_order_save_hold();
-
-      show_product_throbber();
-
-      $.post(Drupal.settings.basePath + '?q=admin/store/orders/' + order_id + '/products',
-             { action: 'view' },
-             function(contents) {
-               if (contents != '') {
-                 $('#products-container').empty().append(contents);
-               }
-               remove_order_save_hold();
-               hide_product_throbber();
-             });
-    }
-  );
-}
-
-function load_product_select(order_id, search) {
-  if (search == true) {
-    options = {'search' : $('#edit-product-search').val()};
-  }
-  else {
-    options = { };
-  }
-
-  show_product_throbber();
-
-  $.post(Drupal.settings.basePath + '?q=admin/store/orders/' + order_id + '/product_select', options,
-         function (contents) {
-           $('#products-selector').empty().addClass('product-select-box2').append(contents);
-           hide_product_throbber();
-         }
-  );
-
-  return false;
-}
-
-function select_product() {
-  add_product_form();
-  return false;
-}
-
-function close_product_select() {
-  $('#products-selector').empty().removeClass('product-select-box2');
-  return false;
-}
-
-function add_product_form() {
-  add_product_browser = $('#products-selector').html();
-
-  show_product_throbber();
-
-  if (parseInt($('#edit-unid').val()) > 0) {
-    $.post(Drupal.settings.basePath + '?q=admin/store/orders/' + $('#edit-order-id').val() + '/add_product/' + $('#edit-unid').val(), { },
-           function(contents) {
-             $('#products-selector').empty().append(contents);
-             hide_product_throbber();
-           }
-    );
-  }
-}
-
-function add_product_to_order(order_id, node_id) {
-  var post_vars = fetch_product_data();
-  post_vars['action'] = 'add';
-  post_vars['nid'] = node_id;
-  post_vars['qty'] = $('#edit-add-qty').val();
-
-  $('#uc-order-add-product-form :input').each(
-    function() {
-      if ($(this).attr('name').substr(0, 10) == 'attributes') {
-        post_vars[$(this).attr('name')] = $(this).val();
-      }
-    }
-  );
-
-  show_product_throbber();
-
-  $.post(Drupal.settings.basePath + '?q=admin/store/orders/' + order_id + '/products', post_vars,
-         function(contents) {
-           if (contents != '') {
-             $('#products-container').empty().append(contents);
-           }
-           hide_product_throbber();
-         }
-  );
-
-  $('#add-product-button').click();
-
-  return false;
-}
-
-function fetch_product_data() {
-  var pdata = { };
-
-  $('.order-pane-table :input').each(
-    function() {
-      pdata[$(this).attr('name')] = $(this).val();
-    }
-  );
-  $('.order-pane-table ~ :input').each(
-    function() {
-      pdata[$(this).attr('name')] = $(this).val();
-    }
-  );
-
-  return pdata;
-}
-
-function add_blank_line_button(order_id) {
-  var post_vars = fetch_product_data();
-  post_vars['action'] = 'add_blank';
-
-  show_product_throbber();
-
-  $.post(Drupal.settings.basePath + '?q=admin/store/orders/' + order_id + '/products',
-         post_vars,
-         function(contents) {
-           if (contents != '') {
-             $('#products-container').empty().append(contents);
-           }
-           hide_product_throbber();
-         }
-  );
-}
-
-function remove_product_button(message, opid) {
-  if (confirm(message)) {
-    var post_vars = fetch_product_data();
-    post_vars['action'] = 'remove';
-    post_vars['opid'] = opid;
-
-    show_product_throbber();
-
-    $.post(Drupal.settings.basePath + '?q=admin/store/orders/' + $('#edit-order-id').val() + '/products',
-           post_vars,
-           function(contents) {
-             if (contents != '') {
-               $('#products-container').empty().append(contents);
-             }
-             hide_product_throbber();
-           }
-    );
-  }
-}
-
 function confirm_line_item_delete(message, img_id) {
   if (confirm(message)) {
     var li_id = img_id.substring(3);
@@ -421,4 +269,3 @@
 function hide_product_throbber() {
   $('#product-div-throbber').removeAttr('style').empty();
 }
-
Index: uc_order.module
===================================================================
--- uc_order.module	(revision 242)
+++ uc_order.module	(working copy)
@@ -213,34 +213,17 @@
     'weight' => 1,
     'file' => 'uc_order.admin.inc',
   );
-  $items['admin/store/orders/%uc_order/add_line_item/%'] = array(
-    'title' => 'Add a line item',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('uc_order_add_line_item_form', 3, 5),
-    'access arguments' => array('edit orders'),
-    'type' => MENU_CALLBACK,
-    'file' => 'uc_order.admin.inc',
-  );
-  $items['admin/store/orders/%uc_order/products'] = array(
-    'title' => 'Products',
-    'page callback' => 'uc_order_edit_products',
-    'page arguments' => array(3),
-    'access arguments' => array('edit orders'),
-    'type' => MENU_CALLBACK,
-    'file' => 'uc_order.admin.inc',
-  );
-  $items['admin/store/orders/%uc_order/product_select'] = array(
+  $items['admin/store/orders/ahah/product_select'] = array(
     'title' => 'Product select',
-    'page callback' => 'uc_order_load_product_select',
-    'page arguments' => array(3),
+    'page callback' => 'uc_order_ahah_product_select',
     'access arguments' => array('edit orders'),
     'type' => MENU_CALLBACK,
     'file' => 'uc_order.admin.inc',
   );
-  $items['admin/store/orders/%uc_order/add_product/%node'] = array(
-    'title' => 'Add product',
-    'page callback' => 'uc_order_add_product',
-    'page arguments' => array(3, 5),
+  $items['admin/store/orders/%uc_order/add_line_item/%'] = array(
+    'title' => 'Add a line item',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('uc_order_add_line_item_form', 3, 5),
     'access arguments' => array('edit orders'),
     'type' => MENU_CALLBACK,
     'file' => 'uc_order.admin.inc',
@@ -332,10 +315,6 @@
       'arguments' => array('form' => NULL),
       'file' => 'uc_order.admin.inc',
     ),
-    'uc_order_remove_product' => array(
-      'arguments' => array('form' => NULL),
-      'file' => 'uc_order.admin.inc',
-    ),
     'uc_order_view_update_controls' => array(
       'arguments' => array('form' => NULL),
     ),
Index: uc_order.order_pane.inc
===================================================================
--- uc_order.order_pane.inc	(revision 242)
+++ uc_order.order_pane.inc	(working copy)
@@ -273,14 +273,23 @@
     case 'customer':
       return drupal_render(tapir_get_table('op_products_customer_table', $arg1->products));
 
+    case 'edit-form':
+      $order_id = $arg1->order_id;
+      return array(
+        '#order_id' => $order_id,
+        'products' => array(
+          'list' =>  uc_order_edit_products_form($order_id),
+        ),
+        'products_title' => product_pane_buttons($order_id),
+      );
+
     case 'edit-theme':
-      drupal_add_js('uc_order_load_product_edit_div('. $arg1['order_id']['#value'] .');', 'inline');
-
-      $output = '<div id="products-selector"></div>'
-               .'<div id="products-container">'. t('Loading product information... (<em>If nothing happens, make sure you have Javascript enabled.</em>)') .'</div>';
+      $order_id = $arg1['order_id']['#value'];
+      $output = '<div id="products-container">'. drupal_render($arg1['products']['list']).'</div>';
       return $output;
 
     case 'edit-title':
+      $order_id = $arg1['order_id']['#value'];
       $settings = array(
         'div' => '#products-selector',
         'class' => 'product-select-box',
@@ -294,14 +303,7 @@
         'select' => 'add_product_form();',
       );
 
-      $output = '<input type="button" value="'. t('Add product')
-               .'" onclick="load_product_select('. $arg1['order_id']['#value']
-               .', false);" id="add-product-button" />';
-
-      $output .= '<input type="button" value="'. t('Add blank line')
-                .'" onclick="add_blank_line_button('. $arg1['order_id']['#value']
-                .');" />';
-      $output .= ' <span id="product-div-throbber"></span>';
+      $output = drupal_render($arg1['products_title']);
       return $output;
   }
 }
