=== modified file 'shipping/uc_quote/uc_quote.js'
--- shipping/uc_quote/uc_quote.js	2008-12-05 15:55:40 +0000
+++ shipping/uc_quote/uc_quote.js	2009-02-11 16:04:16 +0000
@@ -42,13 +42,7 @@
     var i = $(this).val();
     if (window.set_line_item) {
       var label = $(this).parent().text();
-      set_line_item("shipping", label.substr(0, label.indexOf(":")), Math.round($(this).parent().prev().val() * 100) / 100, 1, 1, false);
-      if (window.getTax) {
-        getTax();
-      }
-      else if (window.render_line_items) {
-        render_line_items();
-      }
+      set_line_item("shipping", label.substr(0, label.indexOf(":")), Math.round($(this).parent().prev().val() * 100) / 100, 1, 1);
     }
   }).end();
 }
@@ -145,12 +139,6 @@
             if (label != "" && window.set_line_item) {
               set_line_item("shipping", label, Math.round(data[i].rate * 100) / 100, 1);
             }
-            if (window.getTax) {
-              getTax();
-            }
-            else if (window.render_line_items) {
-              render_line_items();
-            }
           }
         }
       }
@@ -172,13 +160,7 @@
         quoteDiv.find("input:radio[@value=" + i +"]").click(function() {
           var i = $(this).val();
           if (window.set_line_item) {
-            set_line_item("shipping", data[i].option_label, Math.round(data[i].rate * 100) / 100, 1, 1, false);
-          }
-          if (window.getTax) {
-            getTax();
-          }
-          else if (window.render_line_items) {
-            render_line_items();
+            set_line_item("shipping", data[i].option_label, Math.round(data[i].rate * 100) / 100, 1, 1);
           }
         }).end();
       }

=== modified file 'uc_cart/uc_cart.pages.inc'
--- uc_cart/uc_cart.pages.inc	2009-01-30 21:55:39 +0000
+++ uc_cart/uc_cart.pages.inc	2009-02-11 16:04:16 +0000
@@ -260,7 +260,7 @@
     }
   }
 
-  $order->line_items = uc_order_load_line_items($order->order_id, TRUE);
+  $order->line_items = uc_order_load_line_items($order, TRUE);
 
   uc_order_save($order);
 }

=== modified file 'uc_order/uc_order.ca.inc'
--- uc_order/uc_order.ca.inc	2009-02-05 22:32:34 +0000
+++ uc_order/uc_order.ca.inc	2009-02-11 16:04:16 +0000
@@ -22,6 +22,10 @@
     '#load' => 'uc_order_load',
     '#save' => 'uc_order_save',
   );
+  $entities['uc_line_item'] = array(
+    '#title' => t('Order line item'),
+    '#type' => 'object',
+  );
 
   return $entities;
 }

=== modified file 'uc_order/uc_order.module'
--- uc_order/uc_order.module	2009-02-10 21:51:13 +0000
+++ uc_order/uc_order.module	2009-02-11 16:04:16 +0000
@@ -1086,8 +1086,8 @@
   }
 
   // Load line items... has to be last after everything has been loaded.
-  $order->line_items = uc_order_load_line_items($order->order_id, TRUE);
-  usort($order->line_items, 'uc_weight_sort');
+  $order->line_items = uc_order_load_line_items($order, TRUE);
+
   // Merge it with the defaultish line items.
   $order->line_items = array_merge($order->line_items, uc_order_load_line_items($order, FALSE));
   usort($order->line_items, 'uc_weight_sort');
@@ -1165,17 +1165,30 @@
 
 /**
  * Return an array containing an order's line items ordered by weight.
- * if ($stored) { $order should be an order ID. }
+ *
+ * @param $order
+ *   An order object whose line items are to be loaded.
+ * @param $stored
+ *   Boolean flag. If TRUE, only line items stored in the database are loaded.
+ *   If FALSE, only line items not stored in the database are loaded.
+ *   This distinction is made because the non-stored line items may depend on
+ *   the amounts of all of the stored line items.
+ * @return
+ *   An array of line items, which are arrays containing the following keys:
+ *   - line_item_id
+ *   - type
+ *   - title
+ *   - amount
+ *   - weight
  */
 function uc_order_load_line_items($order, $stored) {
   $items = array();
 
   if ($stored) {
-    if (is_object($order)) {
-      $order = $order->order_id;
-    }
-    $result = db_query("SELECT * FROM {uc_order_line_items} WHERE order_id = %d", $order);
+    $result = db_query("SELECT * FROM {uc_order_line_items} WHERE order_id = %d", $order->order_id);
     while ($row = db_fetch_object($result)) {
+      drupal_alter('line_item', $row, $order);
+
       $items[] = array(
         'line_item_id' => $row->line_item_id,
         'type' => $row->type,

=== modified file 'uc_taxes/uc_taxes.js'
--- uc_taxes/uc_taxes.js	2009-01-23 19:27:54 +0000
+++ uc_taxes/uc_taxes.js	2009-02-11 16:04:16 +0000
@@ -34,6 +34,7 @@
     + "select[@name*=billing_zone], "
     + "input[@name*=billing_city], "
     + "input[@name*=billing_postal_code]").change(getTax);
+  $('#edit-panes-payment-current-total').click(getTax);
 });
 
 function getTax() {
@@ -98,24 +99,57 @@
       dataType: "json",
       success: function(taxes) {
         var key;
-        for (key in li_titles) {
-          if (key.substr(0, 4) == 'tax_') {
-            delete li_titles[key];
-            delete li_values[key];
-            delete li_weight[key];
-          }
-        }
+        var render;
+        var i;
         var j;
         for (j in taxes) {
-          if (taxes[j].id == 'subtotal') {
-            summed = 0;
-          }
-          else {
-            summed = 1;
-          }
-          set_line_item("tax_" + taxes[j].id, taxes[j].name, taxes[j].amount, Drupal.settings.ucTaxWeight + taxes[j].weight / 10, summed, false);
-        }
-        render_line_items();
+          key = 'tax_' + taxes[j].id;
+          // Check that this tax is a new line item, or updates its amount.
+          if (!li_values[key] || li_values[key] != taxes[j].amount) {
+            // The "Subtotal before taxes" line item is not added into the
+            // Total line item.
+            if (taxes[j].id == 'subtotal') {
+              summed = 0;
+            }
+            else {
+              summed = 1;
+            }
+
+            set_line_item(key, taxes[j].name, taxes[j].amount, Drupal.settings.ucTaxWeight + taxes[j].weight / 10, summed, false);
+
+            // Set flag to render all line items at once.
+            render = true;
+          }
+        }
+        var found;
+        // Search the existing tax line items and match them to a returned tax.
+        for (key in li_titles) {
+          // The tax id is the second part of the line item id if the first
+          // part is "tax".
+          i = key.split('_', 2);
+          if (i[0] == 'tax') {
+            found = false;
+            for (j in taxes) {
+              if (taxes[j].id == i[1]) {
+                found = true;
+                break;
+              }
+            }
+            // No tax was matched this time, so remove the line item.
+            if (!found) {
+              delete li_titles[key];
+              delete li_values[key];
+              delete li_weight[key];
+              delete li_summed[key];
+              // Even if no taxes were added earlier, the display must be
+              // updated.
+              render = true;
+            }
+          }
+        }
+        if (render) {
+          render_line_items();
+        }
       }
     });
   }

