This blog post was originally posted in the ATG Developer Community by Spark::red’s co-founding partner Russell Moore in 2008.

I know a lot of stuff in ATG uses Dojo for javascript, but I have had good luck with JQuery as well.

Step 1: Download JQuery and put it in your war

I put it under scripts/jquery-1.2.3.js for the purposes of this example.

Step 2: Create a header and a cart page fragment

I created a frags directory, with a header.jsp & minicart.jsp.
The header.jsp holds 2 things: the connecting javascript (which there is little of) and the hidden div to hold the cart.

frags/header.jsp
<%@ taglib uri="dsp" prefix="dsp"%>
<dsp:page>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<%-- accepts param from include for title, keywords, and description --%>   
<title><dsp:valueof param="pageTitle">petsovernight.com - any pet, anywhere, overnight!</dsp:valueof></title>
<meta name="keywords" content="<dsp:valueof param="metaKeywords" />" />
<meta name="description" content="<dsp:valueof param="metaDescription" />" />
<meta http-equiv="Content-Language" content="en-us" />
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<script src="scripts/jquery-1.2.3.js" type="text/javascript"></script>   
</head>
<body>
<script type="text/javascript">
function addtocart() {
    var selObject = returnObjById("selectSKU");
    var selIndex = selObject.selectedIndex;
    var selQuantity = returnObjById("quantity");
    if(selObject.value == "") {
        alert("please select a size");
        return false;
    }
    if(selQuantity.value == "") {
        alert("please select a quantity");
        return false;
    }
    updateCartURL = "frags/minicart.jsp?dcs_action=additemtocart&url_catalog_ref_id=" + selObject.options
[selIndex].value + "&url_product_id=<dsp:valueof param="productId"/>&url_quantity=" + selQuantity.value;
    cartsummaryURL = "frags/cartsummary.jsp";
    $('#minicart').load(updateCartURL,function(){$('#cartsummary').load(cartsummaryURL);});
    $('#minicart').slideDown('slow');
}
function returnObjById(id) {
    if (document.getElementById) {
        var returnVar = document.getElementById(id);
    else {
        if (document.all) {
            var returnVar = document.all[id];
        else {
            if (document.layers) {
                var returnVar = document.layers[id];
            }
        }
    }
    return returnVar;
}
</script>
<div id="minicart" style="width: 300px;z-index: 150;position: absolute;top: 30px;left: 200px;color: #fff;display: none;">
    .
</div>
...

The minicart.jsp contains – you guessed it, the cart contents.

frags/minicart.jsp
<%@ taglib uri="dsp" prefix="dsp"%>
<%@ taglib uri="c" prefix="c"%>
<dsp:page>
<dsp:importbean bean="/atg/commerce/order/formhandler/ShoppingCartFormHandler" />
<dsp:importbean bean="/atg/commerce/ShoppingCart" />
<dsp:importbean bean="/atg/commerce/order/purchase/RepriceOrderDroplet" />
<dsp:importbean bean="/atg/dynamo/droplet/ForEach" />
<dsp:importbean bean="/atg/dynamo/droplet/Switch" />
<dsp:importbean bean="/atg/dynamo/droplet/IsNull" />
<dsp:droplet name="RepriceOrderDroplet">
    <dsp:param value="ORDER_SUBTOTAL" name="pricingOp" />
</dsp:droplet>
<script type="text/javascript">              
$('a#continueshop').click(function() {
    $('#minicart').slideUp(400);
    return false;
});
</script>
<div id="cartmain" class="cart">
    <dsp:droplet name="Switch">
    <dsp:param name="value" bean="ShoppingCart.currentEmpty" />
        <dsp:oparam name="true">
          <div class="cartshippad">Your cart is currently empty.</div>
        </dsp:oparam>
        <dsp:oparam name="default">
          <div class="cartwrapper">
        <dsp:droplet name="ForEach">
        <dsp:param bean="ShoppingCartFormHandler.Order.ShippingGroups" name="array"/>
        <dsp:param name="elementName" value="ShippingGroup"/>
        <dsp:param name="indexName" value="shippingGroupIndex"/>
        <dsp:oparam name="output">
          <dsp:droplet name="ForEach">
            <dsp:param name="array" param="ShippingGroup.CommerceItemRelationships" />
            <dsp:param name="elementName" value="CiRelationship" />
            <dsp:param name="indexName" value="index" />
            <dsp:oparam name="output">
            <div class="cartdetailwrapper">
                  <div class="cartdetailsection">
                     <div class="cartdetailtitle"><dsp:valueof param="CiRelationship.commerceItem.auxiliaryData.catalogRef.displayName" /></div>
                     <p><dsp:valueof param="CiRelationship.commerceItem.priceInfo.amount" converter="currency" /></p>
                        <p>Color: <b><dsp:valueof param="CiRelationship.commerceItem.auxiliaryData.catalogRef.color.colorName" /></b></p>
                        <p>Size: <b><dsp:valueof param="CiRelationship.commerceItem.auxiliaryData.catalogRef.size" /></b></p>
                        <p>Quantity: <b><dsp:valueof param="CiRelationship.commerceItem.quantity" /></b></p>
                    </div>
                   </p>                 
                        </div>           
            </dsp:oparam>
          </dsp:droplet>
        </dsp:oparam>
        </dsp:droplet>   
    </div>
        <p>total items = <dsp:valueof bean="ShoppingCart.current.totalCommerceItemCount" /><br />
           grand total = <dsp:valueof bean="ShoppingCart.current.priceInfo.amount" converter="currency" />
        </p>
    <p><a href="#" id="continueshop">continue</a> | <dsp:a page="/checkout/">checkout</dsp:a></p>
      </dsp:oparam>
    </dsp:droplet>
    
</div>
</dsp:page>

Step 3: Create the form in your product page

For this example, you have to have a select with the sku in it (called “selectSku”), a select with the quantity (called “quantity”) and a javascript submit button that calls addItemToCart.

product.jsp
<%@ taglib uri="dsp" prefix="dsp"%>
<dsp:page>
<dsp:importbean bean="/atg/commerce/catalog/ProductLookup" />
<dsp:importbean bean="/atg/commerce/catalog/CategoryLookup" />
<dsp:importbean bean="/atg/commerce/catalog/ProductLookup" />
<dsp:importbean bean="/atg/commerce/pricing/PriceItem" />
<dsp:importbean bean="/atg/dynamo/droplet/Switch" />
<dsp:importbean bean="/atg/targeting/TargetingForEach" />
<dsp:importbean bean="/atg/commerce/catalog/ProductBrowsed" />
<dsp:importbean bean="/atg/dynamo/droplet/IsNull" />
<dsp:include page="/frags/header.jsp" />
<dsp:droplet name="ProductBrowsed">
  <dsp:param param="product" name="eventobject"/>
</dsp:droplet>
<h1><dsp:valueof param="product.displayName" /></h1>
<!-- display images, related content, etc... -->
...
<dsp:form action="." method="post" id="addtocart">
  <input name="id" type="hidden" value='<dsp:valueof param="product.repositoryId"/>' />
  <select id="selectSKU">
    <dsp:droplet name="ForEach">
        <dsp:param name="array" param="product.childSKUs"/>
        <dsp:oparam name="output">
            <option value="<dsp:valueof param="element.id" />" ><dsp:valueof param="element.size" /> </option>
        </dsp:oparam>
    </dsp:droplet>
  </select>
  <select id="quantity">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
  </select>
  <a href="#"><img src="images/add2cart.jpg" onclick="addtocart()" alt="Add To Cart" border="0" /></a>
</dsp:form>

How it works?

jQuery makes it really easy to fill divs with the content of external pages. It also has some nice functions for transitions.
This allows us to treat the page fragments as individual objects to some extent.

The AddITemToCartServlet is mapped in the pipeline to look for any page request with specific parameters. parameters are actually caught and forwarded to it by the CommerceCommandServlet. For more information, look up “Adding an Item to an Order via a URL” in the ATGCommerceProgrammingGuide.

The Servlet takes the following params that we are interested in:

  • dcs_action – in this case it is “addItemToCart” – tells CommerceCommandServlet to pass to the AddITemToCartServlet
  • url_catalog_ref_id – the sku ID
  • url_product_id – the product ID
  • url_quantity – the quantity to add

There are other params that this servlet takes as well – you could even create a form to update/edit items in the cart.

So, basically, the form sets the sku and the quantity, and the javascript on the button calls addtocart() javascript function.
The addtocart() function inspects the form values, creates the URL to call (the minicart page, plus the URL paramaters to invoke the AddITemToCartServlet). It then fills a hidden div with the content of the ajax response, and slides the cart open for the user to see.