StudioForty9 | Search Engine Marketing, E-Commerce, Web Design, Web Development, Magento, ExpressionEngine

  • Home
  • Products
  • Our Work
  • Our Team
  • Blog
  • Contact Us

jQuery in Magento made easy

(or sophisticated depending on your point of vew)

  • Date 14th February, 2011
  • Author Alan Morkan
  • Category Magento

First of all I'd like to credit my colleague Eoghan. He's the Javascript guru in the company, and really this blog post is based on a library he developed for use on our projects, adapted for Magento. I'm still feeling my way around Javascript, in terms of taking advantage of the existing frameworks (jQuery, Prototype, MooTools) to write modular code that is loosely coupled with the underlying HTML/CSS.

For those of you who have used Magento, you will know that it comes packaged with Prototype and Scriptaculous. The entire functionality both frontend and backend is dependent on the 10 or so Javascript classes written on top of Prototype. While technically it is possible to strip back this Javascript to allow orders to be placed for users without Javascript enabled, it really depends on your setup and is a reasonable amount of work for a questionable pay-off.

But of course, Prototype is somewhat limited as a framework. Not only does it not have the same amount of 3rd party modules written for it, in comparison with jQuery, but it also tends to be a bit more verbose in terms of getting it to do what you want. So it's not surprising that Magento Connect is littered with modules that provide functionality (e.g., slideshows) that are written in jQuery.

Of course, you can't just throw the jQuery library and some custom code into a Magento template and expect it to work. There will be conflicts between Prototype and jQuery as both use the '$' sign notation. Fortunately, jQuery has the noConflict() method that you can use to allow Prototype and jQuery to function happily together.

But as online shops become more sophisticated in terms of the user experience, there can be an increase in the number of jQuery modules being used on the store. For example, on a store I am building at the moment you have a sliding panel and a lightbox on every page, as well as an image zoom, a colour picker and another sliding panel on the product page. If we start putting <script> tags into the Magento template files where each particular functionality is needed, we soon end up with code that is difficult to maintain. Not only that, but including Javascript inline like that, slows down page loads.

So rather than having each piece of jQuery in the appropriate template, remembering to wrap it with noConflict() each time, let's put it in one file for the entire site. Here's the example I'll be using:

(function($){

     $.studioforty9= {
          version: '0.1',
          website: 'http://dev.studioforty9.com/',
          sections: {
               'cms-index-index' : 'this.initHome()',
               'cms-page-view' : 'this.initCMS()',
               'catalog-category-view' : 'this.initCategory()',
               'catalog-product-view' : 'this.initProduct()',
               'checkout-cart-index' : 'this.initCart()',
               'checkout-onepage-index' : 'this.initCheckout()'
          },
          init: function()
          {
               this.TopPanel();
               this.LightBox();
          },
          initSiteSection: function(section){
               var section = $('body').attr('class').split(' ')[1];
               eval(this.sections[section]);
          },
          initHome: function(){},
          initCMS: function(){},
          initCategory: function(){},
          initProduct: function(){
               this.ProductOptions();
               this.ProductZoom();
               this.ColourPicker()
          },
          initCart: function(){},
          initCheckout: function(){},
          Utilities:
          {
               external: function() {
                    $('A[rel*="external"]').click(function(e) {
                         var url = $(this).attr('href');
                         window.open(url);
                         e.preventDefault();
                    });
               }
          },
          Forms:
          {
               focus: function() {
                    var prevLabel = '';
                    $('.focus').focus(function() {
                         if ( $.trim($(this).val()) == $(this).attr('title') ) {
                              prevLabel = $(this).val();
                              $(this).val('');
                         }
                    });
                    $('.focus').blur(function() {
                         if ( $(this).val() == '' ) {
                              $(this).val(prevLabel);
                         }
                    });
               }
          },
          TopPanel: function() {
               $('#lightbox-link').bind('click', function(event){
                    event.preventDefault();
                    $('.lightbox').slideDown('slow');
                    $('#close-link').show();
               });
              
               $('#login-link').bind('click', function(event){
                    event.preventDefault();
                    $('.login').slideDown('slow');
                    $('#close-link').show();
               });
              
               $('#close-link').bind('click', function(event){
                    event.preventDefault();
                    $('.login').slideUp('slow');
                    $('.lightbox').slideUp('slow');
                    $('#close-link').fadeOut('slow');
               });
          },
          LightBox: function(){
               $('.lightbox-img').lightBox({
                    containerResizeSpeed: 800,
                    imageLoading: 'http://dev.studioforty9.com/skin/frontend/default/modern/img/lightbox-ico-loading.gif',
                    imageBtnClose: 'http://dev.studioforty9.com/skin/frontend/default/modern/img/lightbox-btn-close.gif',
                    imageBtnPrev: 'http://dev.studioforty9.com/skin/frontend/default/modern/img/lightbox-btn-prev.gif',
                    imageBtnNext: 'http://dev.studioforty9.com/skin/frontend/default/modern/img/lightbox-btn-next.gif',
               });
          },    
          ProductOptions: function(){
               if($('#choose-options').length > 0){
                    $('#choose-options').bind('click', function(event){
                         event.preventDefault();
                         $('.options').slideToggle('slow');
                    });
               }
          },
          ProductZoom: function(){    
               var options = {
                             zoomWidth: 300,
                             zoomHeight: 260,
                           xOffset: 122,
                           yOffset: -82,
                           position: "right",
                           title: false
               };

               $('.product-image-zoom a').jqzoom(options);
          },
          ColourPicker: function(){    
               $('#picker-link a').bind('click', function(event){
                    event.preventDefault();
                    $('#colour-picker').fadeToggle();
               });                    
              
               $('#colour-picker').farbtastic({callback : '.product-essential', width: 150});
          }
     }

     $(function() {
          $.studioforty9.init();
          $.studioforty9.initSiteSection();
     });

})(jQuery.noConflict());

There's a few things I'd like to point out about this code.

First of all, there's only one call to noConflict(). The entire code is wrapped as an anonymous function, and noConflict() applied to this. Easy!

Second, also at the bottom of the code is the equivalent of the onDomReady function. This is the code that is run when the page is finished loading. 2 lines. Easy to see what's going on. There's the init() function that calls other functions that we want to run on every page on the site. So in our case this is the TopPanel that slides down when particular links are clicked and the LightBox for particular images.

The other function is initSiteSection(). As we've said already, we want certain code to only be run on certain pages. Rather than introduce a raft of if...else statements, we can leverage Magento to figure this out in a more seamless manner. Each Magento page has particular classes on the

tag. The main ones are listed in the sections object. We associate these classes with a particular function to run (e.g., when the

tag has a class of 'catalog-product-view' we want to run the initProduct() function). This way it's very easy to find out exactly what code from the class is running on any given page.*

* I should point out that it's also necessary to include the relevant libraries in the appropriate layout XML file. So for example, we would want to add the following lines of code to catalog.xml file of our theme to add the jqZoom library to

of the page:

<catalog_product_view translate="label">
          ...
        <reference name="head">
          ...  
          <action method="addItem"><type>skin_js</type><name>js/jquery.jqzoom1.0.1.js</name></action>
          <action method="addItem"><type>skin_css</type><name>css/jqzoom.css</name></action>
          ...
        </reference>

        ...
</catalog_product_view>

Subscribe to Our Blog
Recent Posts Toggle
  • An Irish Module for Magento
  • Taking Control of Product Options in Magento
  • jQuery in Magento made easy
  • Restricting Product Purchase to Authorised Users in Magento
  • West Cork Homeless
  • Fota Wildlife wins Best Tourism & Travel Website… and also takes the Eircom Spiders Grand Prix
  • Realex Redirect with PHP
  • Blinds & Magento
  • Fota Wildlife shortlisted for Golden Spider Award
  • Curtains & Magento
Categories Toggle
  • Expression Engine (2)
  • General (6)
  • Magento (7)
  • PHP (1)
  • Portfolio (2)
  • Realex (1)
  • SEO (1)
  • We are now getting twice as many hits as we were in the past and the numbers are growing by the week. StudioForty9 are innovative, well organised, knowledgeable, flexible and very easy to deal with.
    Stephen RyanFotawildlife.ie
  • I have been working closely with StudioForty9 for over a year now. They are a key part of my online strategy and I can recommend them without hesitation.
    Brendan O'SullivanMyBlinds.ie
  • I have no hesitation in recommending StudioForty9. I now regard them as critical partners in my business.
    Fred CroweSpeech-Writers.com
  • As a business development consultant I understand what it takes to build and expand a business and when it comes to the online business sector, this company has what it takes to deliver.
    Billy O'ConnorThe Discovery Partnership

MyMailCampaign Client Login StudioForty9 Lite

Copyright © 2006 - 2012 StudioForty9. 2nd Floor, 34 Grand Parade, Cork City, Ireland. Phone: +353 87 225 1250