Create a gist now

Instantly share code, notes, and snippets.

Magento product image vertical align middle /js/varien/product.js
/**
* Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE_AFL.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@magentocommerce.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Magento to newer
* versions in the future. If you wish to customize Magento for your
* needs please refer to http://www.magentocommerce.com for more information.
*
* @category Varien
* @package js
* @copyright Copyright (c) 2011 Magento Inc. (http://www.magentocommerce.com)
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
*/
if(typeof Product=='undefined') {
var Product = {};
}
/********************* IMAGE ZOOMER ***********************/
Product.Zoom = Class.create();
/**
* Image zoom control
*
* @author Magento Core Team <core@magentocommerce.com>
*/
Product.Zoom.prototype = {
initialize: function(imageEl, trackEl, handleEl, zoomInEl, zoomOutEl, hintEl){
this.containerEl = $(imageEl).parentNode;
this.imageEl = $(imageEl);
this.handleEl = $(handleEl);
this.trackEl = $(trackEl);
this.hintEl = $(hintEl);
this.containerDim = Element.getDimensions(this.containerEl);
this.imageDim = Element.getDimensions(this.imageEl);
this.imageDim.ratio = this.imageDim.width/this.imageDim.height;
this.floorZoom = 1;
if (this.imageDim.width > this.imageDim.height) {
this.ceilingZoom = this.imageDim.width / this.containerDim.width;
} else {
this.ceilingZoom = this.imageDim.height / this.containerDim.height;
}
if (this.imageDim.width <= this.containerDim.width
&& this.imageDim.height <= this.containerDim.height) {
this.trackEl.up().hide();
this.hintEl.hide();
this.containerEl.removeClassName('product-image-zoom');
return;
}
this.imageX = 0;
if (this.imageDim.width > this.containerDim.width) {
myY = ((this.containerDim.width/this.imageDim.width)*this.imageDim.height)/2 - this.containerDim.height/2;
} else { myY = 0; }
this.imageY = '-' + myY;
this.imageZoom = 1;
this.sliderSpeed = 0;
this.sliderAccel = 0;
this.zoomBtnPressed = false;
this.showFull = false;
this.selects = document.getElementsByTagName('select');
this.draggable = new Draggable(imageEl, {
starteffect:false,
reverteffect:false,
endeffect:false,
snap:this.contain.bind(this)
});
this.slider = new Control.Slider(handleEl, trackEl, {
axis:'horizontal',
minimum:0,
maximum:Element.getDimensions(this.trackEl).width,
alignX:0,
increment:1,
sliderValue:0,
onSlide:this.scale.bind(this),
onChange:this.scale.bind(this)
});
this.scale(0);
Event.observe(this.imageEl, 'dblclick', this.toggleFull.bind(this));
Event.observe($(zoomInEl), 'mousedown', this.startZoomIn.bind(this));
Event.observe($(zoomInEl), 'mouseup', this.stopZooming.bind(this));
Event.observe($(zoomInEl), 'mouseout', this.stopZooming.bind(this));
Event.observe($(zoomOutEl), 'mousedown', this.startZoomOut.bind(this));
Event.observe($(zoomOutEl), 'mouseup', this.stopZooming.bind(this));
Event.observe($(zoomOutEl), 'mouseout', this.stopZooming.bind(this));
},
toggleFull: function () {
this.showFull = !this.showFull;
//Hide selects for IE6 only
if (typeof document.body.style.maxHeight == "undefined") {
for (i=0; i<this.selects.length; i++) {
this.selects[i].style.visibility = this.showFull ? 'hidden' : 'visible';
}
}
val_scale = !this.showFull ? this.slider.value : 1;
this.scale(val_scale);
this.trackEl.style.visibility = this.showFull ? 'hidden' : 'visible';
this.containerEl.style.overflow = this.showFull ? 'visible' : 'hidden';
this.containerEl.style.zIndex = this.showFull ? '1000' : '9';
return this;
},
scale: function (v) {
var centerX = (this.containerDim.width*(1-this.imageZoom)/2-this.imageX)/this.imageZoom;
var centerY = (this.containerDim.height*(1-this.imageZoom)/2-this.imageY)/this.imageZoom;
var overSize = (this.imageDim.width > this.containerDim.width || this.imageDim.height > this.containerDim.height);
this.imageZoom = this.floorZoom+(v*(this.ceilingZoom-this.floorZoom));
if (overSize) {
if (this.imageDim.width > this.containerDim.width) {
this.imageEl.style.width = (this.imageZoom*this.containerDim.width)+'px';
} else if (this.imageDim.height > this.containerDim.height) {
this.imageEl.style.height = (this.imageZoom*this.containerDim.height)+'px';
}
if(this.containerDim.ratio){
this.imageEl.style.height = (this.imageZoom*this.containerDim.width*this.containerDim.ratio)+'px'; // for safari
}
} else {
this.slider.setDisabled();
}
this.imageX = this.containerDim.width*(1-this.imageZoom)/2-centerX*this.imageZoom;
this.imageY = this.containerDim.height*(1-this.imageZoom)/2-centerY*this.imageZoom;
this.contain(this.imageX, this.imageY, this.draggable);
return true;
},
startZoomIn: function()
{
if (!this.slider.disabled) {
this.zoomBtnPressed = true;
this.sliderAccel = .002;
this.periodicalZoom();
this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05);
}
return this;
},
startZoomOut: function()
{
if (!this.slider.disabled) {
this.zoomBtnPressed = true;
this.sliderAccel = -.002;
this.periodicalZoom();
this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05);
}
return this;
},
stopZooming: function()
{
if (!this.zoomer || this.sliderSpeed==0) {
return;
}
this.zoomBtnPressed = false;
this.sliderAccel = 0;
},
periodicalZoom: function()
{
if (!this.zoomer) {
return this;
}
if (this.zoomBtnPressed) {
this.sliderSpeed += this.sliderAccel;
} else {
this.sliderSpeed /= 1.5;
if (Math.abs(this.sliderSpeed)<.001) {
this.sliderSpeed = 0;
this.zoomer.stop();
this.zoomer = null;
}
}
this.slider.value += this.sliderSpeed;
this.slider.setValue(this.slider.value);
this.scale(this.slider.value);
return this;
},
contain: function (x,y,draggable) {
var dim = Element.getDimensions(draggable.element);
var xMin = 0, xMax = this.containerDim.width-dim.width;
var yMin = 0, yMax = this.containerDim.height-dim.height;
x = x>xMin ? xMin : x;
x = x<xMax ? xMax : x;
y = y>yMin ? yMin : y;
y = y<yMax ? yMax : y;
if (this.containerDim.width > dim.width) {
x = (this.containerDim.width/2) - (dim.width/2);
}
if (this.containerDim.height > dim.height) {
y = (this.containerDim.height/2) - (dim.height/2);
}
this.imageX = x;
this.imageY = y;
this.imageEl.style.left = this.imageX+'px';
this.imageEl.style.top = this.imageY+'px';
return [x,y];
}
}
/**************************** CONFIGURABLE PRODUCT **************************/
Product.Config = Class.create();
Product.Config.prototype = {
initialize: function(config){
this.config = config;
this.taxConfig = this.config.taxConfig;
this.settings = $$('.super-attribute-select');
this.state = new Hash();
this.priceTemplate = new Template(this.config.template);
this.prices = config.prices;
this.settings.each(function(element){
Event.observe(element, 'change', this.configure.bind(this))
}.bind(this));
// fill state
this.settings.each(function(element){
var attributeId = element.id.replace(/[a-z]*/, '');
if(attributeId && this.config.attributes[attributeId]) {
element.config = this.config.attributes[attributeId];
element.attributeId = attributeId;
this.state[attributeId] = false;
}
}.bind(this))
// Init settings dropdown
var childSettings = [];
for(var i=this.settings.length-1;i>=0;i--){
var prevSetting = this.settings[i-1] ? this.settings[i-1] : false;
var nextSetting = this.settings[i+1] ? this.settings[i+1] : false;
if(i==0){
this.fillSelect(this.settings[i])
}
else {
this.settings[i].disabled=true;
}
$(this.settings[i]).childSettings = childSettings.clone();
$(this.settings[i]).prevSetting = prevSetting;
$(this.settings[i]).nextSetting = nextSetting;
childSettings.push(this.settings[i]);
}
// Set default values - from config and overwrite them by url values
if (config.defaultValues) {
this.values = config.defaultValues;
}
var separatorIndex = window.location.href.indexOf('#');
if (separatorIndex != -1) {
var paramsStr = window.location.href.substr(separatorIndex+1);
var urlValues = paramsStr.toQueryParams();
if (!this.values) {
this.values = {};
}
for (var i in urlValues) {
this.values[i] = urlValues[i];
}
}
this.configureForValues();
document.observe("dom:loaded", this.configureForValues.bind(this));
},
configureForValues: function () {
if (this.values) {
this.settings.each(function(element){
var attributeId = element.attributeId;
element.value = (typeof(this.values[attributeId]) == 'undefined')? '' : this.values[attributeId];
this.configureElement(element);
}.bind(this));
}
},
configure: function(event){
var element = Event.element(event);
this.configureElement(element);
},
configureElement : function(element) {
this.reloadOptionLabels(element);
if(element.value){
this.state[element.config.id] = element.value;
if(element.nextSetting){
element.nextSetting.disabled = false;
this.fillSelect(element.nextSetting);
this.resetChildren(element.nextSetting);
}
}
else {
this.resetChildren(element);
}
this.reloadPrice();
// Calculator.updatePrice();
},
reloadOptionLabels: function(element){
var selectedPrice;
if(element.options[element.selectedIndex].config){
selectedPrice = parseFloat(element.options[element.selectedIndex].config.price)
}
else{
selectedPrice = 0;
}
for(var i=0;i<element.options.length;i++){
if(element.options[i].config){
element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price-selectedPrice);
}
}
},
resetChildren : function(element){
if(element.childSettings) {
for(var i=0;i<element.childSettings.length;i++){
element.childSettings[i].selectedIndex = 0;
element.childSettings[i].disabled = true;
if(element.config){
this.state[element.config.id] = false;
}
}
}
},
fillSelect: function(element){
var attributeId = element.id.replace(/[a-z]*/, '');
var options = this.getAttributeOptions(attributeId);
this.clearSelect(element);
element.options[0] = new Option(this.config.chooseText, '');
var prevConfig = false;
if(element.prevSetting){
prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];
}
if(options) {
var index = 1;
for(var i=0;i<options.length;i++){
var allowedProducts = [];
if(prevConfig) {
for(var j=0;j<options[i].products.length;j++){
if(prevConfig.config.allowedProducts
&& prevConfig.config.allowedProducts.indexOf(options[i].products[j])>-1){
allowedProducts.push(options[i].products[j]);
}
}
} else {
allowedProducts = options[i].products.clone();
}
if(allowedProducts.size()>0){
options[i].allowedProducts = allowedProducts;
element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id);
element.options[index].config = options[i];
index++;
}
}
}
},
getOptionLabel: function(option, price){
var price = parseFloat(price);
if (this.taxConfig.includeTax) {
var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax;
var excl = price - tax;
var incl = excl*(1+(this.taxConfig.currentTax/100));
} else {
var tax = price * (this.taxConfig.currentTax / 100);
var excl = price;
var incl = excl + tax;
}
if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) {
price = incl;
} else {
price = excl;
}
var str = option.label;
if(price){
if (this.taxConfig.showBothPrices) {
str+= ' ' + this.formatPrice(excl, true) + ' (' + this.formatPrice(price, true) + ' ' + this.taxConfig.inclTaxTitle + ')';
} else {
str+= ' ' + this.formatPrice(price, true);
}
}
return str;
},
formatPrice: function(price, showSign){
var str = '';
price = parseFloat(price);
if(showSign){
if(price<0){
str+= '-';
price = -price;
}
else{
str+= '+';
}
}
var roundedPrice = (Math.round(price*100)/100).toString();
if (this.prices && this.prices[roundedPrice]) {
str+= this.prices[roundedPrice];
}
else {
str+= this.priceTemplate.evaluate({price:price.toFixed(2)});
}
return str;
},
clearSelect: function(element){
for(var i=element.options.length-1;i>=0;i--){
element.remove(i);
}
},
getAttributeOptions: function(attributeId){
if(this.config.attributes[attributeId]){
return this.config.attributes[attributeId].options;
}
},
reloadPrice: function(){
var price = 0;
var oldPrice = 0;
for(var i=this.settings.length-1;i>=0;i--){
var selected = this.settings[i].options[this.settings[i].selectedIndex];
if(selected.config){
price += parseFloat(selected.config.price);
oldPrice += parseFloat(selected.config.oldPrice);
}
}
optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice});
optionsPrice.reload();
return price;
if($('product-price-'+this.config.productId)){
$('product-price-'+this.config.productId).innerHTML = price;
}
this.reloadOldPrice();
},
reloadOldPrice: function(){
if ($('old-price-'+this.config.productId)) {
var price = parseFloat(this.config.oldPrice);
for(var i=this.settings.length-1;i>=0;i--){
var selected = this.settings[i].options[this.settings[i].selectedIndex];
if(selected.config){
price+= parseFloat(selected.config.price);
}
}
if (price < 0)
price = 0;
price = this.formatPrice(price);
if($('old-price-'+this.config.productId)){
$('old-price-'+this.config.productId).innerHTML = price;
}
}
}
}
/**************************** SUPER PRODUCTS ********************************/
Product.Super = {};
Product.Super.Configurable = Class.create();
Product.Super.Configurable.prototype = {
initialize: function(container, observeCss, updateUrl, updatePriceUrl, priceContainerId) {
this.container = $(container);
this.observeCss = observeCss;
this.updateUrl = updateUrl;
this.updatePriceUrl = updatePriceUrl;
this.priceContainerId = priceContainerId;
this.registerObservers();
},
registerObservers: function() {
var elements = this.container.getElementsByClassName(this.observeCss);
elements.each(function(element){
Event.observe(element, 'change', this.update.bindAsEventListener(this));
}.bind(this));
return this;
},
update: function(event) {
var elements = this.container.getElementsByClassName(this.observeCss);
var parameters = Form.serializeElements(elements, true);
new Ajax.Updater(this.container, this.updateUrl + '?ajax=1', {
parameters:parameters,
onComplete:this.registerObservers.bind(this)
});
var priceContainer = $(this.priceContainerId);
if(priceContainer) {
new Ajax.Updater(priceContainer, this.updatePriceUrl + '?ajax=1', {
parameters:parameters
});
}
}
}
/**************************** PRICE RELOADER ********************************/
Product.OptionsPrice = Class.create();
Product.OptionsPrice.prototype = {
initialize: function(config) {
this.productId = config.productId;
this.priceFormat = config.priceFormat;
this.includeTax = config.includeTax;
this.defaultTax = config.defaultTax;
this.currentTax = config.currentTax;
this.productPrice = config.productPrice;
this.showIncludeTax = config.showIncludeTax;
this.showBothPrices = config.showBothPrices;
this.productOldPrice = config.productOldPrice;
this.priceInclTax = config.priceInclTax;
this.priceExclTax = config.priceExclTax;
this.skipCalculate = config.skipCalculate;//@deprecated after 1.5.1.0
this.duplicateIdSuffix = config.idSuffix;
this.specialTaxPrice = config.specialTaxPrice;
this.oldPlusDisposition = config.oldPlusDisposition;
this.plusDisposition = config.plusDisposition;
this.oldMinusDisposition = config.oldMinusDisposition;
this.minusDisposition = config.minusDisposition;
this.optionPrices = {};
this.containers = {};
this.displayZeroPrice = true;
this.initPrices();
},
setDuplicateIdSuffix: function(idSuffix) {
this.duplicateIdSuffix = idSuffix;
},
initPrices: function() {
this.containers[0] = 'product-price-' + this.productId;
this.containers[1] = 'bundle-price-' + this.productId;
this.containers[2] = 'price-including-tax-' + this.productId;
this.containers[3] = 'price-excluding-tax-' + this.productId;
this.containers[4] = 'old-price-' + this.productId;
},
changePrice: function(key, price) {
this.optionPrices[key] = price;
},
getOptionPrices: function() {
var price = 0;
var nonTaxable = 0;
var oldPrice = 0;
var priceInclTax = 0;
var currentTax = this.currentTax;
$H(this.optionPrices).each(function(pair) {
if ('undefined' != typeof(pair.value.price) && 'undefined' != typeof(pair.value.oldPrice)) {
price += parseFloat(pair.value.price);
oldPrice += parseFloat(pair.value.oldPrice);
} else if (pair.key == 'nontaxable') {
nonTaxable = pair.value;
} else if (pair.key == 'priceInclTax') {
priceInclTax += pair.value;
} else if (pair.key == 'optionsPriceInclTax') {
priceInclTax += pair.value * (100 + currentTax) / 100;
} else {
price += parseFloat(pair.value);
oldPrice += parseFloat(pair.value);
}
});
var result = [price, nonTaxable, oldPrice, priceInclTax];
return result;
},
reload: function() {
var price;
var formattedPrice;
var optionPrices = this.getOptionPrices();
var nonTaxable = optionPrices[1];
var optionOldPrice = optionPrices[2];
var priceInclTax = optionPrices[3];
optionPrices = optionPrices[0];
$H(this.containers).each(function(pair) {
var _productPrice;
var _plusDisposition;
var _minusDisposition;
if ($(pair.value)) {
if (pair.value == 'old-price-'+this.productId && this.productOldPrice != this.productPrice) {
_productPrice = this.productOldPrice;
_plusDisposition = this.oldPlusDisposition;
_minusDisposition = this.oldMinusDisposition;
} else {
_productPrice = this.productPrice;
_plusDisposition = this.plusDisposition;
_minusDisposition = this.minusDisposition;
}
if (pair.value == 'old-price-'+this.productId && optionOldPrice !== undefined) {
price = optionOldPrice+parseFloat(_productPrice);
} else if (this.specialTaxPrice == 'true' && this.priceInclTax !== undefined && this.priceExclTax !== undefined) {
price = optionPrices+parseFloat(this.priceExclTax);
priceInclTax += this.priceInclTax;
} else {
price = optionPrices+parseFloat(_productPrice);
priceInclTax += parseFloat(_productPrice) * (100 + this.currentTax) / 100;
}
if (this.specialTaxPrice == 'true') {
var excl = price;
var incl = priceInclTax;
} else if (this.includeTax == 'true') {
// tax = tax included into product price by admin
var tax = price / (100 + this.defaultTax) * this.defaultTax;
var excl = price - tax;
var incl = excl*(1+(this.currentTax/100));
} else {
var tax = price * (this.currentTax / 100);
var excl = price;
var incl = excl + tax;
}
excl += parseFloat(_plusDisposition);
incl += parseFloat(_plusDisposition);
excl -= parseFloat(_minusDisposition);
incl -= parseFloat(_minusDisposition);
//adding nontaxlable part of options
excl += parseFloat(nonTaxable);
incl += parseFloat(nonTaxable);
if (pair.value == 'price-including-tax-'+this.productId) {
price = incl;
} else if (pair.value == 'price-excluding-tax-'+this.productId) {
price = excl;
} else if (pair.value == 'old-price-'+this.productId) {
if (this.showIncludeTax || this.showBothPrices) {
price = incl;
} else {
price = excl;
}
} else {
if (this.showIncludeTax) {
price = incl;
} else {
price = excl;
}
}
if (price < 0) price = 0;
if (price > 0 || this.displayZeroPrice) {
formattedPrice = this.formatPrice(price);
} else {
formattedPrice = '';
}
if ($(pair.value).select('.price')[0]) {
$(pair.value).select('.price')[0].innerHTML = formattedPrice;
if ($(pair.value+this.duplicateIdSuffix) && $(pair.value+this.duplicateIdSuffix).select('.price')[0]) {
$(pair.value+this.duplicateIdSuffix).select('.price')[0].innerHTML = formattedPrice;
}
} else {
$(pair.value).innerHTML = formattedPrice;
if ($(pair.value+this.duplicateIdSuffix)) {
$(pair.value+this.duplicateIdSuffix).innerHTML = formattedPrice;
}
}
};
}.bind(this));
},
formatPrice: function(price) {
return formatCurrency(price, this.priceFormat);
}
}
@creativetags

I added lines 67 - 70 to start the image centered vertically instead of at the top.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment