DIY Magento: Create a Quick View for Your Magento Theme

by on October 6, 2011

DIY Magento

If you browse around Magento Connect you’ll quickly find dozens of Quick View extensions, which make it easier for your customers to quickly glance at a product while viewing the catalog and search pages. Quick View popups typically show some brief details about the selected product and an order form, but you can make them as simple or advanced as you want.

You can always buy an extension, but you’ll end up having to customize it for your store’s design anyway. Our premium Magento theme Avalanche comes with a Quick View popup right out of the box and it’s custom designed for the theme. I recommend purchasing a theme that comes with Quick View or learning how to build your own from scratch. In this tutorial, we’ll walk through all the steps it takes to build a popup with jQuery and create the necessary template files.

In order to build a Quick View popup for Magento, we need to do the following:

  1. Create an AJAX product controller.
  2. Update our frontend layout (local.xml) to populate the Quick View popup with data.
  3. Create the structural block template for <catalog_ajax_product_view>.
  4. Create the Quick View block template.
  5. Add a link to our product listings/catalog page to trigger the popup.
  6. Install jQuery and a jQuery Lightbox to display the Quick View. Use CSS to style the popup.

Create the AJAX Product Controller

The first thing we need to do is create an empty controller to receive AJAX requests that inherit the existing Mage_Catalog_ProductController methods. This way we can use the same controller actions used on the product page. Create an “Ajax” folder and ProductController.php file based on the path listed below:

/app/code/core/Mage/Catalog/controllers/Ajax/ProductController.php

1
2
3
4
5
6
<?php
require_once('app/code/core/Mage/Catalog/controllers/ProductController.php');
 
class Mage_Catalog_Ajax_ProductController extends Mage_Catalog_ProductController
{
}

Update Your Magento Theme’s Local.xml

Now that we have our AJAX product controller set up we need to make it appear in the frontend. Edit your theme’s local.xml file inside /layout. If you don’t have a local.xml yet, learn more about local.xml files here.

/app/design/frontend/YOUR_THEME/layout/local.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?xml version="1.0"?>
<layout version="0.1.0">
<catalog_ajax_product_view>
    <reference name="root">
        <action method="setTemplate"><template>page/quickview.phtml</template></action>
    </reference>
    <reference name="head">
        <action method="addJs"><script>varien/product.js</script></action>
        <action method="addJs"><script>varien/configurable.js</script></action>
    </reference>
    <reference name="content">
		<block type="catalog/product_view" name="product.info" template="catalog/ajax/product/view.phtml">
			<!-- Media: To use, create new template with code located at bottom of blog post -->
            <!--<block type="catalog/product_view_media" name="product.info.media" as="media" template="catalog/product/view/media-quickview.phtml"/>-->
 
		    <block type="core/text_list" name="alert.urls" as="alert_urls" translate="label">
                <label>Alert Urls</label>
            </block>
 
	        <action method="setTierPriceTemplate"><template>catalog/product/view/tierprices.phtml</template></action>
 
            <block type="core/text_list" name="product.info.extrahint" as="extrahint" translate="label">
                <label>Product View Extra Hint</label>
            </block>
 
            <block type="catalog/product_view" name="product.info.options.wrapper" as="product_options_wrapper" template="catalog/product/view/options/wrapper.phtml" translate="label">
                <label>Info Column Options Wrapper</label>
                <block type="core/template" name="options_js" template="catalog/product/view/options/js.phtml"/>
                <block type="catalog/product_view_options" name="product.info.options" as="product_options" template="catalog/product/view/options.phtml">
                    <action method="addOptionRenderer"><type>text</type><block>catalog/product_view_options_type_text</block><template>catalog/product/view/options/type/text.phtml</template></action>
                    <action method="addOptionRenderer"><type>file</type><block>catalog/product_view_options_type_file</block><template>catalog/product/view/options/type/file.phtml</template></action>
                    <action method="addOptionRenderer"><type>select</type><block>catalog/product_view_options_type_select</block><template>catalog/product/view/options/type/select.phtml</template></action>
                    <action method="addOptionRenderer"><type>date</type><block>catalog/product_view_options_type_date</block><template>catalog/product/view/options/type/date.phtml</template></action>
                </block>
 
				<block type="core/html_calendar" name="html_calendar" as="html_calendar" template="page/js/calendar.phtml"/>
            </block>
 
            <block type="catalog/product_view" name="product.info.options.wrapper.bottom" as="product_options_wrapper_bottom" template="catalog/product/view/options/wrapper/bottom.phtml" translate="label">
                <label>Bottom Block Options Wrapper</label>
                <action method="insert"><block>product.tierprices</block></action>
                <block type="catalog/product_view" name="product.clone_prices" as="prices" template="catalog/product/view/price_clone.phtml"/>
                <action method="append"><block>product.info.addtocart</block></action>
                <action method="append"><block>product.info.addto</block></action>
            </block>
 
            <block type="core/template_facade" name="product.info.container1" as="container1">
                <action method="setDataByKey"><key>alias_in_layout</key><value>container1</value></action>
                <action method="setDataByKeyFromRegistry"><key>options_container</key><key_in_registry>product</key_in_registry></action>
                <action method="append"><block>product.info.options.wrapper</block></action>
                <action method="append"><block>product.info.options.wrapper.bottom</block></action>
            </block>
 
			<block type="core/template_facade" name="product.info.container2" as="container2">
			    <action method="setDataByKey"><key>alias_in_layout</key><value>container2</value></action>
			    <action method="setDataByKeyFromRegistry"><key>options_container</key><key_in_registry>product</key_in_registry></action>
			    <action method="append"><block>product.info.options.wrapper</block></action>
			    <action method="append"><block>product.info.options.wrapper.bottom</block></action>
			</block>
 
            <action method="unsetCallChild"><child>container1</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
	        <action method="unsetCallChild"><child>container2</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
 
			<!-- Rating (Use Black BG) -->
			<action method="addReviewSummaryTemplate"><type>default</type><template>review/helper/fd_summary-black.phtml</template></action>
 
			<!-- Add to Cart -->
           	<block type="catalog/product_view" name="product.info.addtocart" as="addtocart" template="catalog/product/view/addtocart.phtml"/>
 
			<!-- Additional Data -->
			<block type="catalog/product_view_additional" name="product.info.additional" as="product_additional_data" />
		</block>
    </reference>
</catalog_ajax_product_view>
</layout>

Create the Structural Block

Catalog_Ajax_Product_View includes the same blocks used on the product page. The next thing we need to do is create the structural block that will render all of the blocks in <reference name="content">. Our structural block is set via the following XML in local.xml:

<reference name="root">
<action method="setTemplate"><template>page/quickview.phtml</template></action>
</reference>

And here’s the structural block code:

/app/design/frontend/YOUR_THEME/template/page/quickview.phtml

1
<?php echo $this->getChildHtml('content'); ?>

This will render all of the content blocks in the Quick View popup, including catalog/ajax/product/view.phtml.

Create the Quick View Block

Here’s a barebones template for your Quick View popup. It includes a variety of product data using the content blocks from local.xml. Feel free to add extra markup and modify as you see fit:

/app/design/frontend/YOUR_THEME/template/catalog/ajax/product/view.phtml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
    $_helper = $this->helper('catalog/output');
    $_product = $this->getProduct();
?>
<script type="text/javascript">
    var optionsPrice = new Product.OptionsPrice(<?php echo $this->getJsonConfig() ?>);
</script>
<div class="quick-view">
	<?php echo $this->getChildHtml('media') ?>
 
 	<a href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->__('View Full Details') ?></a>
 
	<?php echo $this->getReviewsSummaryHtml($_product) ?>
 
	<h1><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></h1>
 
	<?php echo $this->getPriceHtml($_product) ?>
 
	<?php if(!$_product->isSaleable()): ?>
	    <div id="availability"><?php echo $this->__('Out Of Stock') ?></div>
	<?php endif; ?>
 
	<?php echo $this->getChildHtml('alert_urls') ?>
	<div class="product-type-data">
    	<?php echo $this->getChildHtml('product_type_data') ?>
	</div>
    <?php echo $this->getTierPriceHtml() ?>
    <?php echo $this->getChildHtml('extrahint') ?>
    <?php echo $this->getChildHtml('other') ?>
 
	<form action="<?php echo $this->getSubmitUrl($_product) ?>" method="post" id="order-form" <?php if($_product->getOptions()): ?>enctype="multipart/form-data"<?php endif; ?>>
		<?php if($_product->isSaleable()): ?>
			<?php if($this->hasOptions()): ?>
				<?php echo $this->getChildChildHtml('container1', '', true, true) ?>
				<?php echo $this->getChildChildHtml('container2', '', true, true) ?>
			<?php endif; ?>
			<?php echo $this->getChildHtml('addtocart') ?>
		<?php endif; ?>
	</form>
</div>
<script type="text/javascript">
    var productAddToCartForm = new VarienForm('order-form');
    productAddToCartForm.submit = function(button, url) {
        if (this.validator.validate()) {
            var form = this.form;
            var oldUrl = form.action;
 
            if (url) {
               form.action = url;
            }
 
            var e = null;
            this.form.action = oldUrl;
	    form.submit();
 
            if (e) {
                throw e;
            }
 
            if (button && button != 'undefined') {
                button.disabled = true;
            }
 
	    return false;
        }
    }.bind(productAddToCartForm);
</script>

Show Quick View Links in Catalog

Now that we have a way to render the Quick View popup, we need to create a link or button that allows the customer to toggle the Quick View when browsing products. Add the following HTML to your catalog list template:

Add to /app/design/frontend/YOUR_THEME/template/catalog/product/list.phtml. Add it twice for list and grid mode, e.g. under lines 78 and 115.

1
<a href="#" class="quick-view-link" data-url="<?php echo Mage::getBaseUrl(), 'catalog/ajax_product/view/id/', $_product->getId() ?>/"><?php echo $this->__('Quick View') ?></a>

Each product shown in your catalog listings will have a Quick View link. We’re going to write an AJAX call to our new AJAX product controller (catalog/ajax_product) to get the product’s data and render the popup. The URL is pulled from the link’s “data-url” attribute.

Write the JavaScript

In order to tie everything together we need to handle the onclick event for each Quick View link. Upon clicking the link we need to make an AJAX request, get the returned template HTML, and then show that HTML in a lightbox popup. For this example we’ll be using jQuery and Lightbox_Me.

You’ll need to include a copy of jQuery and Lightbox_Me in your local.xml file. I also included some JavaScript files used on the product details page to show the configurable product options in the Quick View. I included it in the default layout handle so your Quick Views will work anywhere. If you’d like you can limit it to catalog_category_default, catalog_category_layered and catalogsearch_result_index.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0"?>
<layout>
    <default>
        <reference name="head">
            <action method="addJs"><script>my_theme/jquery-1.6.4.js</script></action>
            <action method="addJs"><script>my_theme/jquery.lightbox_me.js</script></action>
 
	    <!-- Add these files to show configurable product options in the Quick View -->
            <action method="addJs"><script>varien/product.js</script></action>
            <action method="addJs"><script>varien/configurable.js</script></action>
	    <action method="addJs"><script>calendar/calendar.js</script></action>
	    <action method="addJs"><script>calendar/calendar-setup.js</script></action>
	   <action method="addItem"><type>skin_js</type><name>js/bundle.js</name></action>
        </reference>
   </default>
</layout>

These files are expected in /js/my_theme. If you’ve never used jQuery with Magento before, make sure you add this line to the bottom of your jQuery file:

var $jQ = jQuery.noConflict();

This moves jQuery over to a new namespace, $jQ, and avoids using $ since it’s reserved by Prototype. Now we can write our event handler for the quick view links:

/app/design/frontend/YOUR_THEME/template/catalog/product/list.phtml under line 128

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script type="text/javascript">
$jQ('.quick-view-link').one('click', function(e) {
	showQuickView(this, e);
	$jQ(this).click(function() { return false; });
	e.preventDefault();
});
 
function showQuickView(link, e) {
	var quickUrl = $jQ(link).data('url');
 
	$jQ.get(quickUrl, function(data) {
		$jQ('body').append(data);
		$jQ('.quick-view').lightbox_me({
			centered: true,
			destroyOnClose: true,
			overlaySpeed: 10,
			onClose: function() {
				$jQ(link).one('click', function(e) {
					showQuickView(link, e);
					$jQ(this).click(function() { return false; });
				});
			}
		});
	});
}
</script>

Upon clicking a quick review link, we append the HTML to the catalog page and call lightbox_me(). Finally, we can style the lightbox. Edit your theme’s CSS:

1
2
/* Quick View */
.quick-view { display: none; width: 780px; padding: 20px; background: #fff; border: 4px solid #000; }

Update 10/17 – Create A Quick View Media Template

If you’d like to include product photos in your Quick View, refer to the code below (thanks for the reminder Mick):

/app/design/frontend/YOUR_THEME/template/catalog/product/view/media-quickview.phtml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
    $_product = $this->getProduct();
    $_helper = $this->helper('catalog/output');
?>
 
<div id="quickview-image-browser">
	<div id="product-image">
		<?php if ($_product->getImage() != 'no_selection' && $_product->getImage()): ?>
		    <?php
				$_img = '<img src="'.$this->helper('catalog/image')->init($_product, 'image').'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" width="300" height="300" />';
		        echo $_helper->productAttribute($_product, $_img, 'image');
		    ?>
		<?php else: ?>
		    <?php
		        $_img = '<img src="'.$this->helper('catalog/image')->init($_product, 'image')->resize(300).'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" width="300" height="300" />';
		        echo $_helper->productAttribute($_product, $_img, 'image');
		    ?>
		<?php endif; ?>
	</div>
</div>
  • Mooshi

    thank you very much!…this is great :)

  • Neha Ce15

    its not working for me…

  • Mick_mailman

    doesn’t work for me
    http://www.mysite/catalog/ajax/Product/view/id/301

    page not available error

  • Mick_mailman

    i dont have the media-quickview.phtml is this a problem?

    template=”catalog/product/view/media-quickview.phtml”/>

  • Anonymous

    Oops, yeah that could be the issue. I was using some additional custom templates in my Quick View. Does removing that block fix your problem?

  • Anonymous

    Hi, there was an issue with the local.xml code. Let me know if there’s anything in particular I can address for you.

  • Anonymous

    I added media-quickview.phtml to the bottom of this post.

  • Anonymous

    No problem! Let me know if you have any issues :)

  • Slapushere

    Hey, great article!

    For best practice, can this: /app/code/core/Mage/Catalog/controllers/Ajax/ProductController.php
    be replaced by: /app/code/local/Mage/Catalog/controllers/Ajax/ProductController.php
    to prevent it from being overwritten after an update?

  • Anonymous

    Since Mage_Catalog_Ajax_ProductController is not instantiated by the Mage class, you either have to include it in /app/code/core or create a custom extension that allows you to create the /catalog/ajax_product route. The most forward compatible way would be to create a custom extension, but for the sake of this tutorial it’s much easier and faster to do it in /app/code/core. It’s one file that can easily be included after an update. For more extensive functionality and best practice, I would definitely create an extension.

  • Mick_mailman

    I love this solution as shown in the Avalanche Theme but I can’t get the quickview to work on my store. Has anyone got this to work following the instructions above.

  • Mayank5oct

    Hi,

    i have follow the instructions and I have issue with the pop up. The ajax response is not appent in the body.

    $jQ(‘body’).append(data.html);

    This cde is not wrking with me. Any idea ?

    Thanks,
    Mayank

  • Mick_mailman

    yes that is where I seem to run into problems as well

  • Mick_mailman

    ok $100 bucks hard cold cash to show me how to get this working!!!!!

  • 计成 赵

    hope i can help you.my skype id is himagentochina

  • Anonymous

    Hi Mick, sorry for the hassle. I went through the tutorial again, made some changes, and everything should work fine now.

  • Anonymous

    Hi Mayank, please go through the tutorial again. There were a few bugs.

  • Mick_mailman

    I’m getting the following internal server error:

    ERR (3): Warning: require_once(app/code/core/Mage/Catalog/controllers/ProductController.php): failed to open stream: No such file or directory in /var/data/magento/app/code/core/Mage/Catalog/controllers/Ajax/ProductController.php on line 3

    but the folder and file does exist.

  • Anonymous

    Hi Mick, I haven’t been able to duplicate this issue. Could you use the contact form at the top of this site? I’d like to help you one-on-one personally through email. Thank you!

  • Mick_mailman

    Hey Fast,

    I got it working :) I am using multiple stores so the path add to be.

    require_once(‘/var/data/magento/app/code/core/Mage/Catalog/controllers/ProductController.php’);

    Thanks
    Mick

  • http://fastdivision.com/2011/11/23/diy-magento-create-an-ajax-quick-cart-for-your-magento-theme/ DIY Magento: Create an AJAX Quick Cart for Your Magento Theme — Fast Division

    [...] Note: This tutorial requires the Quick View popup from our previous DIY Magento article – Create a Quick View for Your Magento Theme [...]

  • djpaoloc

    i have the same problem now… any resolution??

  • R2D2

    Like the idea but couldn’t get it to work properly (or better said.. couldn’t get it to work at all). Arent there any sample files for let’s say the blank theme to see how things are done properly?

    Regards

  • R2D2

    Ok i havce some results but still can’t get it to work properly. I made it ready to cut&paste on an fresh Magento install using the blank theme.

    I’m stuck with an strange jQuery error at this moment… Maybe someone else can help me out with this. When it’s fixed it should work on all Magento installs i think.

    The whole package i made can be found here, http://extern.vout.nl/quickview.zip

  • Reind

    Ok i found the problem, when commenting out the following code from ‘view.phtml’ it works,

    var optionsPrice = new Product.OptionsPrice(getJsonConfig() ?>);

    Thing is… wat does the code above does?

  • Anonymous

    Hi Reind,

    The optionsPrice code allows you to calculate the price based on the configurable product options. I’m not sure why it would be causing problems for you unless you’re missing varien/product.js or varien/configurable.js — it’s on a variety of pages including the product page. Please double-check your local.xml. Thank you!

  • Anonymous

    Good idea, I’ll append this post with sample files in the near future.

  • Reind

    I removed them from the local.xml and added them to the catalog.xml and then it seem to work properly however, when trying to open up an configurable product i’m getting the error message ‘Calendar is not defined’.

    Besides above i also spotted an bug on the lightbox effect. Open up the same product several times and close it with the ‘esc’ key. After opening it up an few times you wil see that the lightbox starts ‘blinking’ and won’t stop at all unless you refresh the page. When trying the same thing but closing it with the ‘close link’ this strange behaviour doesn’t appear at all.

  • Roxanai

    Hello Jake,
    When I am debugging the js in /app/design/frontend/YOUR_THEME/template/catalog/product/list.phtml , and I get to the showQuickView() function at line 11 <> it gets out … so the function is not completed and the quickView is not shown.
    Could you give me a clue?

    Thank you for the article.

  • http://fastdivision.com/ Jake Johnson

    Hi Roxanai, is your store online? I can take a look if you need more help. Use the contact form and email me your store URL.

  • Zeeshan Shahid

    I followed it to the end, issue i came up with, light-box don’t show the attributes of configurable products in drop down. I’m trying to figure it out but ended up with no success, any suggestion, from where to start tracing it….A lot of thanks in advance

  • http://twitter.com/pharmokan Pharmokan

    very nice walk-through, thank you for sharing this, I was able to get it to work fine. the only thing i would do is take the media-quickview.phtml and put it in to catalog/ajax/product/view/ for organization purposes.

  • http://fastdivision.com/ Jake Johnson

    Sounds like an issue with loading varien/product.js and varien/configurable.js. Make sure you load the scripts on all pages (or catalog/category pages) using the local.xml file:

    varien/product.js
    varien/configurable.js

  • http://fastdivision.com/ Jake Johnson

    You’re welcome! That’s a great idea, thanks for sharing.

  • http://fastdivision.com/2012/03/29/diy-magento-create-ajax-login-registration-forms-for-your-magento-theme/ DIY Magento: Create AJAX Login & Registration Forms for Your Magento Theme — Fast Division

    [...] [...]

  • http://webmuch.com Aayush

    That’s an amazing tut. Thanks a lot for sharing. Though I am having a problem with configurable products. I have read all the comments and have added all the required JS files. The error is with the following code:

    var optionsPrice = new Product.OptionsPrice(getJsonConfig() ?>);

    as soon as I comment this line, the non configurable products start showing up in the lightbox, configurable products have the error: “Product is not defined”.

    and when this line is uncommented the same error comes for all products.

    I am not using local.xml, instead I am using page.xml and catalog.xml. Could you please help me with that. Really appreciate your help.

    Thanks!

  • http://taur.in/ Lawrence

    Hello Jake,
    I’ve followed every bit of it.

    When i tried to test, nothing to happen, firebug console says

    “onClose: function() {” is not a function

    im using jquery 1.7.2.

    bit of a js noob here. help?

  • http://taur.in/ Lawrence

    *nothing seems to happen.

  • http://taur.in/ Lawrence

    my bad, i put the plugin in plugin.js and forgot to uncomment it from before.

    no errors. firebug console shows the get request, but its blank. 28bytes.

  • http://taur.in/ Lawrence

    i ignored this line ‘/app/design/frontend/YOUR_THEME/template/catalog/ajax/product/view.phtml’

    its fixed now, please delete my comments, thanks for that.

  • http://fastdivision.com/ Jake Johnson

    Hi Aayush,

    It sounds like you need to make sure product.js and configurable.js are added to your catalog views. Make sure the following are in <catalog_category_default> and <catalog_category_layered> under reference name “head” in your catalog.xml file:

    varien/product.js
    varien/configurable.js

  • http://fastdivision.com/ Jake Johnson

    Let me know if you have any other issues! Thanks Lawrence.

  • Neo JL

    Hi thanks for sharing:
    Tuto I followed the step by step, and revised several times, but I am always with the same problem:
    By clicking on the link, it does nothing (goes to the top of the page). Both Chrome and Firefox I have the same message: “$ jQ is not defined”.

    I have several jquerys loaded and run, anyway, following your advice I added in the bottom of jquery-1.7.1.min.js (in my case) and jquery.lightbox_me.js:
    var $ jQ = jQuery.noConflict (), just in case, but still not working.

    I would appreciate any help

  • http://taur.in/ Lawrence

    Thanks Jake,
    I was wondering how you showed the loading icon to show progress.

    On my localhost, it takes about 2-3 seconds for the popup, but i’d like to show the user some progress, like a loading icon just like the avalanche theme or any other modal.

    I managed to use the Twitter Bootstrap modal with this, looks neat.

Previous post:

Next post: