Easy responsive cart for Ubercart

By default, Drupal's Ubercart module renders its cart display as a table, which means it displays terribly on small screens. There aren't a lot of easy ways around it (and they don't conveniently use a view, like Drupal Commerce does).

I recently came up with a very simple way to rearrange the display so that it works well on both desktop and mobile devices. It relies on the fact that Ubercart themes the cart display using the tapir table API, and offers an alter hook.

So I rearrange the table data, combining data and altering columns like so:

function YOURMODULE_tapir_table_alter(&$data, $table_id) {
  if ($table_id == 'uc_cart_view_table') {
    // Loop through table data.
    foreach ($data as $idx => $item) {
      // Only operate on products.
      if (is_numeric($idx) && isset($item['nid'])) {
        // Render the image and prepend it to the description
        $data[$idx]['desc']['#markup'] = '<div>' . drupal_render($item['image']) . </div>' . $item['desc']['#markup'];
        unset($data[$idx]['image']);  
      }
    }
    
    // Re-order columns, remove some titles.
    $data['#columns']['desc']['weight'] = 0;
    $data['#columns']['qty']['weight'] = 1;
    $data['#columns']['qty']['cell'] = '';
    $data['#columns']['remove']['weight'] = 2;
    $data['#columns']['remove']['cell'] = '';
    
    // Remove image column.
    unset($data['#columns']['image']);
  }
}

This puts the image and the description together in the first column, moves the remove button between the qty and the total, and removes some titles. This already looks much better, but make it even more compact, I tweak the display for mobile using some jQuery, as follows, replacing the "Remove" text with "X" and shrinking the qty field size. You'll note that there's also an onclick handler in there because Ubercart's form handling gets confused by a value of "X" on submission. That means a flash of the full-sized button, but i can live with that.

(function($) {

Drupal.behaviors.YOURMODULE = {
  attach: function (context, settings) {

    function doResize() {
      var pWidth = $(window).width();
      
      // Small screens
      if (pWidth <= 400) {
        // Tweaks for UC cart
        if ($('#uc-cart-view-form').length) {
          $('.form-type-uc-quantity input[type=text]').attr('size', 2).css('max-width', '50%');
          $('input[value=Remove]').click(function(){
            $(this).attr('value', 'Remove');
          }).attr('value', 'X');
        }
      }
    }
    
    doResize();
    $(window).on("resize", doResize);
    
  }
}

})(jQuery);

And there you are: a very simple couple of changes that make Ubercart a whole lot better on mobile.