Technical Blog

1 Post tagged with the dwr tag

Out of the box, Elastic Path is configured to serve pages for the storefront. Some customers, however, need more flexibility. For example, we have a customer with content in a Content Management System (CMS) that needed to include links to EP content. The approach taken was to make Elastic Path content available as widgets which could be loaded remotely using JavaScript. This approach has the limitation that if the end user has JavaScript turned off then they will not be able to access the shopping functionality. The jQuery JavaScript library was used.

 

Product Browsing

To enable product browsing, the ShoppingItemConfigController was customized to support two request parameters: type and  productWidgetId. When the type parameter was set to "widget", the  ShoppingItemConfigController returned the widget product view. This  product view was customised to fit in the small space allowed on the  page and a custom template was created for this. The productWidgetId parameter was used to identify the widget so that  multiple widgets could exist on one page.

 

The host page from the CMS included a div at the required location for the product widget:

<div class="blockElement" id="product-widget-1"></div>

 

A script element on the page included the following code:

$(document).ready(function() {
    $('#product-widget-1').load('storefront/category1/productCode.html?type=widget&productWidgetId=product-widget-1');
}

This code executes after the page loads but before all sub-content (e.g. images)  is loaded, sending an asynchronous request to EP for the product content and loading it in  the div with the id "product-widget-1".

 

Add to Cart

To add an item to the cart, an asynchronous call to DWR was made using the widget id to identify the SKU and quantity to add.

<form id="skuSelectForm" name="skuSelectForm" method="post" onsubmit="return addToCartSubmit('#$productWidgetId'); ">

 

function addToCartSubmit(widgetId) {      
    shoppingCartAjaxController.addSkuToCart(jQuery(widgetId + ' 
        .skuCodeParameter').val(), jQuery(widgetId +'-quantitySelect').val(), 
        function(data) {
            refreshShoppingCartSummary();
       
        });
   return false;
}


Shopping Cart Summary

When the addSkuToCart request returns, the refreshShoppingCartSummary() method is called. This is defined in a JavaScript file included in the hosted page. It makes another asynchronous call in order to determine the number of items in the cart. (Note: for greater network efficiency, the number of items in the cart could be returned from addSkuToCart.)

function refreshShoppingCartSummary() {
    shoppingCartAjaxController.getCartItemCount(function(data) { 
        jQuery('#cartSummaryText').text(data); 
    });            
};

 

Shopping Cart Summary Popup

The jQuery hover method was used  to detect when the mouse was over the icon and display a popup showing the contents of the cart. A DWR call was made to retrieve the cart data. To reduce the number of round trips, this call was designed to return all required information for the cart and its items. JavaScript was used to build the DOM tree for this data. (Note that, in production, a JS client side templating engine should be considered for this role.)

 

The next issue was making sure the popup remained open when the mouse moved to the checkout button. This was done using JavaScript timeouts; when the hover out function was called, the timeout would start. When a hover in function was called for the cart icon or for the popup, the timeout would be cancelled. If the timeout fired without being cancelled, the popup would be closed.

 

    $('#shoppingCartMenu').hover(function() {
        shoppingCartAjaxController.getCartSummary(function(cart) {
            var popupHtml = '<div class="cartTop">';           
            popupHtml += '</div>';
            popupHtml += '<div class="cartBottom transparent">';
            popupHtml +=    '<div class="yourCart">';
            popupHtml +=        '<p>YOUR CART</p>';
            popupHtml +=    '</div>'

            for (var i=0; i<cart.shoppingItems.length; i++) {
                popupHtml += '<div class="product">';
                shoppingItem = cart.shoppingItems[i];
                popupHtml +=    '<div class="items">';
                popupHtml +=        '<div class="itemsImg">';
                popupHtml +=            '<img width="35" height="41" border="0" alt="' + shoppingItem.localizedProductName;
                popupHtml += '" src="/storefront/renderImage.image?imageName=' + shoppingItem.imageFileName +'&width=35&height=41" id="productImage">';
                popupHtml +=        '</div>';
                popupHtml +=        '<div class="itemsText">';
                popupHtml +=            '<p><strong>' + shoppingItem.localizedProductName + '</strong></p>';
                popupHtml += '<p>';
                for (var j=0; j<shoppingItem.localizedSkuOptionDisplayNames.length; j++) {
                    if (j != 0) popupHtml += ',';
                    popupHtml += shoppingItem.localizedSkuOptionDisplayNames[j];
                }
                popupHtml += '</p>';
                popupHtml +=        '</div>';                                               
                popupHtml +=    '</div>';   
                popupHtml +=    '<div class="priceSubtotal">';
                popupHtml +=        '<p>Qty: ' + shoppingItem.quantity +'</p>';
                popupHtml +=    '</div>';
                popupHtml +=    '<div class="price">';
                popupHtml +=        '<h2><p>' + getCents(shoppingItem.total) + '</p><h2>' + getDollars(shoppingItem.total) + '</h2><p>$</p></h2>';
                popupHtml +=    '</div>';
                popupHtml += '</div>';
            }
            popupHtml += '<div class="subtotal">';
            popupHtml +=    '<div class="items">';
            popupHtml +=        '<p>ITEMS IN CART: ' + cart.numItems + '</p>';
            popupHtml +=    '</div>';   
            popupHtml +=    '<div class="priceSubtotal">';
            popupHtml +=        '<p>SUBTOTAL:</p>';
            popupHtml +=    '</div>';
            popupHtml +=    '<div class="price">';

            popupHtml +=        '<h2><p>' + getCents(cart.subTotal) + '</p><h2>' + getDollars(cart.subTotal) + '</h2><p>$</p></h2>';
            popupHtml +=    '</div>';                                               
            popupHtml += '</div>';                                   
            popupHtml += '<div class="checkout">';
            popupHtml +=    '<a href="/storefront/check-out.ep" title=""><img src="images/btn_checkout.gif" alt="" /></a>';
            popupHtml += '</div>';
            popupHtml += '</div>';
            $('#shoppingCartPopup').html(popupHtml);
            $('#shoppingCartPopup').css('display', 'block');
        });
    }, function() {
        shoppingCartPopupClose = setTimeout(closeShoppingCartPopup();, 500);
    });
   
    $('#shoppingCartPopup').hover(function() {
        clearTimeout(shoppingCartPopupClose);
    }, function() {
        shoppingCartPopupClose = setTimeout(closeShoppingCartPopup();, 500);
    })
1 Comments Permalink