/*** /unisource/products.js **********************************/ Products = Class.create(); Products.Details = Class.create(); /** * Represents a Product Details pop-up */ Products.Details.prototype = { cart : null, productId : null, /** * Creates a new instance of the Product Details pop-up * * @param HTMLElement contentId the DOM ID of the pop-up container element */ initialize : function(contentId) { this.contentId = contentId; new DeepFreeze(this, ['addToCart']); }, /** * Returns the shopping cart object * * @return Object */ getCart : function() { var cartElement = $('mini-cart'); if (cartElement) { this.cart = cartElement.cart; } return this.cart; }, /** * Displays the product details pop-up in the current screen * * @param Integer productId the product ID to display * @param Boolean showAvailability whether or not to display product availability information * @param String alternativeProductsUrl the URL for the alternative product listing */ show : function(productId, showAvailability, alternativeProductsUrl) { // moves the detail container outside the listing var container = $(this.contentId); if (container.parentNode.tagName.toLowerCase() != 'body') { document.getElementsByTagName('body')[0].appendChild(container); } if(!showAvailability || showAvailability == 'undefined'){ showAvailability = ''; }else{ showAvailability = '/' + showAvailability; } if(!alternativeProductsUrl || alternativeProductsUrl == 'undefined'){ alternativeProductsUrl = ''; }else{ alternativeProductsUrl = '/' + alternativeProductsUrl; } var requestParameters = { alternativeProductsUrl: alternativeProductsUrl }; if (this.featuredProductId) { requestParameters.featuredProductId = this.featuredProductId; } new Ajax.Updater( this.contentId + '-content', Paths.www + '/uni_products/showDetails/' + productId + '/' + this.contentId + showAvailability, { parameters: requestParameters, onSuccess : function() { $(this.contentId).details = this; $(this.contentId).unipopup.show(); this.productId = productId; }.bindAsEventListener(this), evalScripts: true } ); }, /** * Hides this product details pop-up */ hide : function() { $(this.contentId).unipopup.hide(); }, /** * Adds the selected product to the mini-cart, if available */ addToCart : function() { var products = {}; products[this.productId] = $(this.contentId + '-quantity').value; this.getCart().observeOnce( MyUnisource.MiniCart.Event.PRODUCTS_SUBMITTED, function() { this.hide(); this.unfreeze(); }.bind(this) ); this.cart.submitProducts(products); } } Products.Listing = Class.create(); Products.Listing.quantities = {}; Products.Listing.listings = []; Products.Listing.Event = { /** * Invoked when the product listing is about to be * submitted in order to add products to the current * order */ SUBMITTING : 'submitting', /** * Invoked after the products have been added to the * order. */ SUBMITTED : 'submitted' } /** * Clears all retained quantities */ Products.Listing.clearAll = function() { Products.Listing.quantities = {}; } /** * Retains quantities in all product listings that are still * on the page at the moment this function * is called. */ Products.Listing.retainAll = function() { Products.Listing.forAll( function(listing) { listing.retain(); } ); } /** * Removes listings that are no longer part of the DOM */ Products.Listing.clearZombies = function() { if (Products.Listing.listings) { var clearedListings = $A(Products.Listing.listings).findAll( function(listingId) { var listingElement = $(listingId); return listingElement && listingElement.listing && listingElement.listing.getForm(); } ); Products.Listing.listings = clearedListings; } } /** * Restores quantities in all product listings that are still * on the page. */ Products.Listing.restoreAll = function() { Products.Listing.clearZombies(); Products.Listing.forAll( function(listing) { listing.restore(); } ); } Products.Listing.forgetAll = function(productIds) { Products.Listing.forAll ( function(listing) { listing.forgetQuantities(productIds); } ); } Products.Listing.forAll = function(lambda) { if (Products.Listing.listings) { $A(Products.Listing.listings).each( function(listingId){ var listingElement = $(listingId); if (listingElement && listingElement.listing && listingElement.listing instanceof Products.Listing) { lambda(listingElement.listing); } } ); } } /** * Function called whenever a listing is loaded. * * Overwrite with your favorite JS code. * e.g. * Products.Listing.onLoad = function (listing) { * alert('Listing contains ' + listing.productIds + ' product(s).'); * } * * @access public * @param Listing listing The loaded product listing * @return boolean False */ Products.Listing.onLoad = function (loaded) { /* overwrite */ return false; } /** * A Listing implementation for the Unisource product listing * that provides value retention for pagination */ Products.Listing.prototype = Object.extend(new Listing(), { /** * Retained product quantities for listings with an "Add to Cart" option */ quantities : {}, /** * The ID of the root element for the mini cart, to * which the actual cart object is attached * * @var string */ miniCartId : 'mini-cart', /** * Indicates whether or not this listing is "frozen", in * which case * * @var bool */ frozen: false, /** * The main constructor * * @param id the listing ID * @param productIds the products contained in this product listing * @param checkboxEnabled indicates whether checkboxes should be enabled * @param enditableQuantity indicates whether or not the quantities are editable */ initialize : function(id, productIds, checkboxEnabled, editableQuantity) { this.id = id; this.productIds = productIds; this.checkboxEnabled = checkboxEnabled || false; this.editableQuantity = editableQuantity || false; this.attach(); if (Products.Listing.listings && $A(Products.Listing.listings).indexOf(id) == -1) { Products.Listing.listings.push(id); } else { Products.Listing.listings = [this]; } this.refreshQuantities(); Products.Listing.onLoad(this); this.observeOnce( Listing.Event.PAGE_CHANGED, this.defaultPageChangedHandler.bind(this) ); this.observe( Products.Listing.Event.SUBMITTED, function() { this.unfreeze(); }.bind(this) ); new DeepFreeze(this, ['handleSubmit']); }, defaultPageChangedHandler : function() { window.setTimeout( function() { if( ! $(this.id) ) return; // Focus on the first quantity field var inputs = $(this.id).getElementsByTagName('input'); if (inputs) { for (var i = 0, c = inputs.length; i < c; i++) { if (inputs[i].id.match(/quantity/)) { var input = inputs[i]; $(this.id).scrollTo(); input.focus(); break; } } } }.bind(this), 200 ); }, /** * Returns the form data associated with this listing */ getForm : function() { return $(this.id).getForm(); }, /** * Attaches the event handlers required by this listing */ attach : function() { Listing.prototype.initialize.apply(this, [this.id, this.productIds]); this.listing = $(this.id); // Register pagination event handlers if (this.editableQuantity) { this.observeOnce( Listing.Event.PAGE_CHANGING, this.retain.bind(this) ); this.observeOnce( Listing.Event.PAGE_CHANGED, this.restore.bind(this) ); this.observeOnce( Listing.Event.SORTING, this.retain.bind(this) ); this.observeOnce( Listing.Event.SORTED, this.restore.bind(this) ); } var up = this; var exec = function(form) { var cart = up.getCart(); if (cart) { if (form && up.editableQuantity) { Event.observe( form, 'submit', function(e, form) { Event.stop(e); var form = $(up.id).getForm(); if (form) { up.handleSubmit(form); } }.bindAsEventListener(up) ); } cart.observe( MyUnisource.MiniCart.Event.PRODUCT_SUBMISSION_FAILED, function() { up.unfreeze(); }.bind(up) ); } }; if(document.loaded) { var form = $(this.id).getForm(); exec(form); } else { Event.observe( window, 'load', function() { var element = $(up.id); if (element.getForm) { var form = $(up.id).getForm(); exec(form); } } ); } }, clearOnSubmit : function() { var cart = this.getCart(); if (cart) { cart.observeOnce( MyUnisource.MiniCart.Event.PRODUCTS_SUBMITTED, function(products) { for(var i = 0, length = products.length;i