Commerce Reference Store has two pages that render the gift selection options for each gift item: the store.war/cart/gadgets/giftSelection.jsp page is used when JavaScript is enabled, while store.war/cart/gadgets/noJsGiftSelection.jsp is used when it is not. Both pages use the atg.commerce.promotion.GiftWithPurchaseSelectionChoicesDroplet to obtain a list of GiftWithPurchaseSelectionChoice beans associated with the current gift. Each GiftWithPurchaseSelectionChoice bean contains a product, and its associated SKUs, that is available for selection for the current gift.

Depending on how a gift is configured in the Business Control Center, it may have a giftType that consists of a single product or multiple products. The sku and product gift types include a single product, hence one GiftWithPurchaseSelectionChoice bean is returned for this gift type. The category, skuContentGroup, and productContentGroup gift types include multiple products, so multiple GiftWithPurchaseSelectionChoice beans are returned.

The list of GiftWithPurchaseSelectionChoice beans is passed to the /atg/commerce/collections/filter/droplet/InventoryFilterDroplet. This droplet iterates over each bean, using the Commerce Reference Store-specific filter /atg/registry/CollectionFilters/GWPSelectionInventoryFilter, and checks if the SKUs are available in inventory. Any GiftWithPurchaseSelectionChoice bean that has no SKUs available in inventory is filtered out.

The gift selection page iterates over the filtered GiftWithPurchaseSelectionChoice beans and renders a row for each bean that displays the product and SKU choices for that bean. The giftSelection.jsp gadget renders a JavaScript-based picker similar to what is used on the product detail pages, while the noJsGiftSelection.jsp gadget renders a drop-down list with each SKU combination. If there is more than one row (that is, more than one GiftWithPurchaseSelectionChoice bean), a radio button is rendered next to each row so that the customer can pick a SKU and then click the radio button to indicate that this is the SKU she wants to choose. If the customer is making a change to a previous selection, the previous selection is pre-selected on the form. If there is only one row to render, the radio button is omitted.

Note about Selecting Gifts When JavaScript Is Not Enabled

To make gift selection, both the product ID and SKU ID must be submitted within the form. When JavaScript is not enabled, however, selecting the radio button next to the selected product or SKU allows us to only specify one parameter, either the product ID or the SKU ID. The noJsGiftSelection.jsp gadget includes logic to resolve the unspecified parameter.

When the giftType of the gift is a SKU content group, the noJsGiftSelection.jsp gadget renders one SKU per row on the page. Selecting the radio button next to a SKU specifies the SKU ID for the gift. To pass the corresponding product ID, noJsGiftSelection.jsp specifies an additional parameter of the form promoId_skuId=productId. The atg.projects.store.promotion.StoreGiftWithPurchaseFormHandler.preMakeGiftSelection() method checks whether the promoId_skuId request parameter is specified and, if so, it assigns the parameter’s value to the productId property.

For all other gift types, the storefront displays one product on each row, so selecting the radio button next to the product specifies the product ID. Similarly to the previous case, noJsGiftSelection.jsp specifies an additional parameter of the form promoId_productId=skuId. The preMakeGiftSelection() method checks whether the promoId_productId request parameter is specified and, if so, it assigns the parameter’s value to the skuId property.

Note: In the JavaScript-enabled case, this additional logic is not necessary because when a user clicks a color, size, wood finish, or radio button control in the pop up page, the clickGiftSku() or clickGiftProduct() JavaScript functions are called. These functions ensure that all the necessary form parameters are specified.

Error Messages on the Gift Selection Page

The handling of error messages on the gift selection page varies depending on whether JavaScript is enabled or not.

When JavaScript is enabled, an AJAX request is sent to the server when the customer chooses a gift in the popup page. If an error occurs during the request processing, JavaScript retrieves the error messages from a JSON response and injects them into the HTML structure of the popup. To implement this solution, the store.war/cart/gadgets/giftSelection.jsp gadget specifies the store.war/cart/json/giftErrors.jsp JSP page as the error URL to use when the gift selection has been made via an AJAX request:

<dsp:input bean="GiftWithPurchaseFormHandler.ajaxMakeGiftSelectionErrorURL"
           type="hidden" value="${contextroot}/cart/json/giftErrors.jsp"/>

The giftErrors.jsp page extracts the errors from the /atg/commerce/promotion/GiftWithPurchaseFormHandler.formExceptions property using the /atg/dynamo/droplet/ErrorMessageForEach droplet and then creates a JSON object that contains an array of the errors that occurred during request processing. The handleJSON() JavaScript function from store.war/javascript/picker.js processes the received JSON object and checks whether it contains any errors. If so, the errors are injected into a special reserved <div> container inside the gift selection popup. Using this method to render error messages improves the performance of the gift popup page because only a portion of the page is re-rendered when errors occur, not the entire page.

For the case when JavaScript is not enabled, the noJsGiftSelection.jsp gadget includes the store.war/global/gadgets/errorMessage.jsp gadget. This gadget renders all of the specified form handler exceptions, wrapped into a single <div> tag. errorMessage.jsp uses the ErrorMessageForEach droplet to retrieve the error messages from the GiftWithPurchaseFormHandler.formExceptions array.