Ajax Based Add Product to Wishlist and Compare Products

In this blog post we will see how to make “Add to Wishlist” and “Add to Compare” operations ajax based.

In both product page and category page we will make the required changes for this. This is in continuation of the previous blog written for magento ajax based operations. Again we will use jquery for all ajax operations.
Attached are screenshots of the final result of this module

Ajax Wishlist and Compare Category Page

Ajax Wishlist and Compare Category Page

Ajax Wishlist and Compare Product Page

Ajax Wishlist and Compare Product Page

Also attached is the module created for this blog, it contains detailed source for each of the files.
[dm]19[/dm]
Now let see the steps to do this.

Product Page

The phtml file from where the Wishlist and Compare links come are catalog/product/view/addto.phtml. So first we will override this file so that we can put in our of javascript functions. To do this in our layout file we will put in this code

<catalog_product_view>
	   	<reference name='product.info.addto'>
	   		<action method='setTemplate'><template>ajaxwishlist/catalog/product/view/addto.phtml</template></action>
	   	</reference>
   </catalog_product_view>

So here we have set the template of the block ‘product.info.addto’ to ajaxwishlist/catalog/product/view/addto.phtml. In the new addtophtml we will place our new html code.
Wishlist
Now first let us see the html and javascript changes for the ‘Add To Wishlist’ link.
The default html of ‘Add to Wishlist’ is

<li><a href="<?php echo $_wishlistSubmitUrl ?>" onclick="productAddToCartForm.submitLight(this, '<?php echo $_wishlistSubmitUrl ?>'); return false;" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>

we will change this to

<li><a href="#" onclick="wishlistForm.submitAjaxWishlist(this, '<?php echo $_wishlistSubmitUrl ?>','<?php echo $_product->getId()?>'); return false;" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>

Next we will create the javascript of the wishlistForm used above.

<script type="text/javascript">
var wishlistForm = new VarienForm('product_addtocart_form');
wishlistForm.submitAjaxWishlist = function(button, url,id){
    if(this.validator) {
        var nv = Validation.methods;
        delete Validation.methods['required-entry'];
        delete Validation.methods['validate-one-required'];
        delete Validation.methods['validate-one-required-by-name'];
        if (this.validator.validate()) {
        	url = url.replace("wishlist/index","ajaxwishlist/index");
        	var data = jQuery('#product_addtocart_form').serialize();
			data += '&isAjax=1';
			jQuery('#ajax_loading'+id).show();
			jQuery.ajax( {
				url : url,
				dataType : 'json',
				type : 'post',
				data : data,
				success : function(data) {
					jQuery('#ajax_loading'+id).hide();
					if(data.status == 'ERROR'){
						alert(data.message);
					}else{
						alert(data.message);
						if(jQuery('.block-wishlist').length){
                            jQuery('.block-wishlist').replaceWith(data.sidebar);
                        }else{
                            if(jQuery('.col-right').length){
                            	jQuery('.col-right').prepend(data.sidebar);
                            }
                        }
                        if(jQuery('.header .links').length){
                            jQuery('.header .links').replaceWith(data.toplink);
                        }
					}
				}
			});
        }
        Object.extend(Validation.methods, nv);
    }
}.bind(wishlistForm);
</script>

The main code to note here is this

url = url.replace("wishlist/index","ajaxwishlist/index");
var data = jQuery('#product_addtocart_form').serialize();

we change the default wishlist url to our module’s url and in data variable serialize the forms fields. then ajax call is made to the URL and html is returned in appended to the right column.
Next we need to add code to the IndexController for this ajax action.

protected function _getWishlist()
	{
		$wishlist = Mage::registry('wishlist');
		if ($wishlist) {
			return $wishlist;
		}

		try {
			$wishlist = Mage::getModel('wishlist/wishlist')
			->loadByCustomer(Mage::getSingleton('customer/session')->getCustomer(), true);
			Mage::register('wishlist', $wishlist);
		} catch (Mage_Core_Exception $e) {
			Mage::getSingleton('wishlist/session')->addError($e->getMessage());
		} catch (Exception $e) {
			Mage::getSingleton('wishlist/session')->addException($e,
			Mage::helper('wishlist')->__('Cannot create wishlist.')
			);
			return false;
		}

		return $wishlist;
	}
	public function addAction()
	{

		$response = array();
		if (!Mage::getStoreConfigFlag('wishlist/general/active')) {
			$response['status'] = 'ERROR';
			$response['message'] = $this->__('Wishlist Has Been Disabled By Admin');
		}
		if(!Mage::getSingleton('customer/session')->isLoggedIn()){
			$response['status'] = 'ERROR';
			$response['message'] = $this->__('Please Login First');
		}

		if(empty($response)){
			$session = Mage::getSingleton('customer/session');
			$wishlist = $this->_getWishlist();
			if (!$wishlist) {
				$response['status'] = 'ERROR';
				$response['message'] = $this->__('Unable to Create Wishlist');
			}else{

				$productId = (int) $this->getRequest()->getParam('product');
				if (!$productId) {
					$response['status'] = 'ERROR';
					$response['message'] = $this->__('Product Not Found');
				}else{

					$product = Mage::getModel('catalog/product')->load($productId);
					if (!$product->getId() || !$product->isVisibleInCatalog()) {
						$response['status'] = 'ERROR';
						$response['message'] = $this->__('Cannot specify product.');
					}else{

						try {
							$requestParams = $this->getRequest()->getParams();
							$buyRequest = new Varien_Object($requestParams);

							$result = $wishlist->addNewItem($product, $buyRequest);
							if (is_string($result)) {
								Mage::throwException($result);
							}
							$wishlist->save();

							Mage::dispatchEvent(
                				'wishlist_add_product',
							array(
			                    'wishlist'  => $wishlist,
			                    'product'   => $product,
			                    'item'      => $result
							)
							);

							Mage::helper('wishlist')->calculate();

							$message = $this->__('%1$s has been added to your wishlist.', $product->getName(), $referer);
							$response['status'] = 'SUCCESS';
							$response['message'] = $message;

							Mage::unregister('wishlist');

							$this->loadLayout();
							$toplink = $this->getLayout()->getBlock('top.links')->toHtml();
							$sidebar_block = $this->getLayout()->getBlock('wishlist_sidebar');
							$sidebar = $sidebar_block->toHtml();
							$response['toplink'] = $toplink;
							$response['sidebar'] = $sidebar;
						}
						catch (Mage_Core_Exception $e) {
							$response['status'] = 'ERROR';
							$response['message'] = $this->__('An error occurred while adding item to wishlist: %s', $e->getMessage());
						}
						catch (Exception $e) {
							mage::log($e->getMessage());
							$response['status'] = 'ERROR';
							$response['message'] = $this->__('An error occurred while adding item to wishlist.');
						}
					}
				}
			}

		}
		$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
		return;
	}

This is the code required to make the ajax wishlist work.
Compare Link
This is the default code for the compare links

<li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>

we will change this to

<li><span class="separator">|</span> <a href="#" onclick="ajaxCompare('<?php echo $_compareUrl?>','<?php echo $_product->getId()?>'); return false;" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>

Here we have created a function called ajaxCompare() for the ajax operations. The code of ajax compare function is

function ajaxCompare(url,id){
	url = url.replace("catalog/product_compare/add","ajaxwishlist/index/compare");
	url += 'isAjax/1/';
	jQuery('#ajax_loading'+id).show();
	jQuery.ajax( {
		url : url,
		dataType : 'json',
		success : function(data) {
			jQuery('#ajax_loading'+id).hide();
			if(data.status == 'ERROR'){
				alert(data.message);
			}else{
				alert(data.message);
				if(jQuery('.block-compare').length){
                    jQuery('.block-compare').replaceWith(data.sidebar);
                }else{
                    if(jQuery('.col-right').length){
                    	jQuery('.col-right').prepend(data.sidebar);
                    }
                }
			}
		}
	});
}

Here also we have replaced the default compare url to our modules url. So here the implantation of the compareAction()

public function compareAction(){
		$response = array();

		if ($productId = (int) $this->getRequest()->getParam('product')) {
			$product = Mage::getModel('catalog/product')
			->setStoreId(Mage::app()->getStore()->getId())
			->load($productId);

			if ($product->getId()/* && !$product->isSuper()*/) {
				Mage::getSingleton('catalog/product_compare_list')->addProduct($product);
				$response['status'] = 'SUCCESS';
				$response['message'] = $this->__('The product %s has been added to comparison list.', Mage::helper('core')->escapeHtml($product->getName()));
				Mage::register('referrer_url', $this->_getRefererUrl());
				Mage::helper('catalog/product_compare')->calculate();
				Mage::dispatchEvent('catalog_product_compare_add_product', array('product'=>$product));
				$this->loadLayout();
				$sidebar_block = $this->getLayout()->getBlock('catalog.compare.sidebar');
				$sidebar_block->setTemplate('ajaxwishlist/catalog/product/compare/sidebar.phtml');
				$sidebar = $sidebar_block->toHtml();
				$response['sidebar'] = $sidebar;
			}
		}
		$this->getResponse()->setBody(Mage::helper('core')->jsonEncode($response));
		return;
	}

This is all that is required to make the compare link work.

Category Page

To make changes to the catagory page, we need to override the list.phtml file. To do this in the modules layout file put in this code

<catalog_category_default>
   		<reference name="head">
            <action method="addItem"><type>js</type><name>jquery/jquery-1.6.4.min.js</name></action>
            <action method="addItem"><type>js</type><name>jquery/noconflict.js</name></action>
            <action method="addItem"><type>skin_js</type><name>js/ajaxwishlist/ajaxwishlist.js</name></action>
        </reference>
    	<reference name='product_list'>
    		<action method='setTemplate'><template>ajaxwishlist/catalog/product/list.phtml</template></action>
    	</reference>
    </catalog_category_default>
    <catalog_category_layered>
    	<reference name="head">
            <action method="addItem"><type>js</type><name>jquery/jquery-1.6.4.min.js</name></action>
            <action method="addItem"><type>js</type><name>jquery/noconflict.js</name></action>
            <action method="addItem"><type>skin_js</type><name>js/ajaxwishlist/ajaxwishlist.js</name></action>
        </reference>
    	<reference name='product_list'>
    		<action method='setTemplate'><template>ajaxwishlist/catalog/product/list.phtml</template></action>
    	</reference>
    </catalog_category_layered>

Next in our layout file we need to change the code of ‘Add to wishlist’ and ‘Add to compare’. Default code is

<?php if ($this->helper('wishlist')->isAllow()) : ?>
                            <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
                        <?php endif; ?>
                        <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
                            <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
                        <?php endif; ?>

this needs to be changed to

<ul class="add-to-links">
                        <?php if ($this->helper('wishlist')->isAllow()) : ?>
                            <li><a href="#" onclick='ajaxWishlist("<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>","<?php echo $_product->getId()?>");return false;' class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
                        <?php endif; ?>
                        <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
                            <li><span class="separator">|</span> <a href="#" onclick='ajaxCompare("<?php echo $_compareUrl ?>","<?php echo $_product->getId()?>");return false;' class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
                        <?php endif; ?>
                    </ul>
                    <span id='ajax_loading<?php echo $_product->getId()?>' style='display:none'><img src='<?php echo $this->getSkinUrl('images/opc-ajax-loader.gif')?>'/></span>

The ajaxCompare is the same function used previously. The new function created is ajaxWishlist. the code for which is

function ajaxWishlist(url,id){
	url = url.replace("wishlist/index","ajaxwishlist/index");
	url += 'isAjax/1/';
	jQuery('#ajax_loading'+id).show();
	jQuery.ajax( {
		url : url,
		dataType : 'json',
		success : function(data) {
			jQuery('#ajax_loading'+id).hide();
			if(data.status == 'ERROR'){
				alert(data.message);
			}else{
				alert(data.message);
				if(jQuery('.block-wishlist').length){
                    jQuery('.block-wishlist').replaceWith(data.sidebar);
                }else{
                    if(jQuery('.col-right').length){
                    	jQuery('.col-right').prepend(data.sidebar);
                    }
                }
			}
		}
	});
}
The detailed source code for making this work is attached in the zip file. Please upload it to your magento and checkout all files. Some files have not been explained this blog because of complexity, which are these in the module source code.