1/** 2 * Magento 3 * 4 * NOTICE OF LICENSE 5 * 6 * This source file is subject to the Academic Free License (AFL 3.0) 7 * that is bundled with this package in the file LICENSE_AFL.txt. 8 * It is also available through the world-wide-web at this URL: 9 * http://opensource.org/licenses/afl-3.0.php 10 * If you did not receive a copy of the license and are unable to 11 * obtain it through the world-wide-web, please send an email 12 * to [email protected] so we can send you a copy immediately. 13 * 14 * DISCLAIMER 15 * 16 * Do not edit or add to this file if you wish to upgrade Magento to newer 17 * versions in the future. If you wish to customize Magento for your 18 * needs please refer to http://www.magento.com for more information. 19 * 20 * @category Varien 21 * @package js 22 * @copyright Copyright (c) 2006-2020 Magento, Inc. (http://www.magento.com) 23 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) 24 */ 25if(typeof Product=='undefined') { 26 var Product = {}; 27} 28 29/********************* IMAGE ZOOMER ***********************/ 30 31Product.Zoom = Class.create(); 32/** 33 * Image zoom control 34 * 35 * @author Magento Core Team <[email protected]> 36 */ 37Product.Zoom.prototype = { 38 initialize: function(imageEl, trackEl, handleEl, zoomInEl, zoomOutEl, hintEl){ 39 this.containerEl = $(imageEl).parentNode; 40 this.imageEl = $(imageEl); 41 this.handleEl = $(handleEl); 42 this.trackEl = $(trackEl); 43 this.hintEl = $(hintEl); 44 45 this.containerDim = Element.getDimensions(this.containerEl); 46 this.imageDim = Element.getDimensions(this.imageEl); 47 48 this.imageDim.ratio = this.imageDim.width/this.imageDim.height; 49 50 this.floorZoom = 1; 51 52 if (this.imageDim.width > this.imageDim.height) { 53 this.ceilingZoom = this.imageDim.width / this.containerDim.width; 54 } else { 55 this.ceilingZoom = this.imageDim.height / this.containerDim.height; 56 } 57 58 if (this.imageDim.width <= this.containerDim.width 59 && this.imageDim.height <= this.containerDim.height) { 60 this.trackEl.up().hide(); 61 this.hintEl.hide(); 62 this.containerEl.removeClassName('product-image-zoom'); 63 return; 64 } 65 66 this.imageX = 0; 67 this.imageY = 0; 68 this.imageZoom = 1; 69 70 this.sliderSpeed = 0; 71 this.sliderAccel = 0; 72 this.zoomBtnPressed = false; 73 74 this.showFull = false; 75 76 this.selects = document.getElementsByTagName('select'); 77 78 this.draggable = new Draggable(imageEl, { 79 starteffect:false, 80 reverteffect:false, 81 endeffect:false, 82 snap:this.contain.bind(this) 83 }); 84 85 this.slider = new Control.Slider(handleEl, trackEl, { 86 axis:'horizontal', 87 minimum:0, 88 maximum:Element.getDimensions(this.trackEl).width, 89 alignX:0, 90 increment:1, 91 sliderValue:0, 92 onSlide:this.scale.bind(this), 93 onChange:this.scale.bind(this) 94 }); 95 96 this.scale(0); 97 98 Event.observe(this.imageEl, 'dblclick', this.toggleFull.bind(this)); 99 100 Event.observe($(zoomInEl), 'mousedown', this.startZoomIn.bind(this)); 101 Event.observe($(zoomInEl), 'mouseup', this.stopZooming.bind(this)); 102 Event.observe($(zoomInEl), 'mouseout', this.stopZooming.bind(this)); 103 104 Event.observe($(zoomOutEl), 'mousedown', this.startZoomOut.bind(this)); 105 Event.observe($(zoomOutEl), 'mouseup', this.stopZooming.bind(this)); 106 Event.observe($(zoomOutEl), 'mouseout', this.stopZooming.bind(this)); 107 }, 108 109 toggleFull: function () { 110 this.showFull = !this.showFull; 111 112 //Hide selects for IE6 only 113 if (typeof document.body.style.maxHeight == "undefined") { 114 for (i=0; i<this.selects.length; i++) { 115 this.selects[i].style.visibility = this.showFull ? 'hidden' : 'visible'; 116 } 117 } 118 val_scale = !this.showFull ? this.slider.value : 1; 119 this.scale(val_scale); 120
121 this.trackEl.style.visibility = this.showFull ? 'hidden' : 'visible'; 122 this.containerEl.style.overflow = this.showFull ? 'visible' : 'hidden'; 123 this.containerEl.style.zIndex = this.showFull ? '1000' : '9'; 124 125 return this; 126 }, 127 128 scale: function (v) { 129 var centerX = (this.containerDim.width*(1-this.imageZoom)/2-this.imageX)/this.imageZoom; 130 var centerY = (this.containerDim.height*(1-this.imageZoom)/2-this.imageY)/this.imageZoom; 131 var overSize = (this.imageDim.width > this.containerDim.width || this.imageDim.height > this.containerDim.height); 132 133 this.imageZoom = this.floorZoom+(v*(this.ceilingZoom-this.floorZoom)); 134 135 if (overSize) { 136 if (this.imageDim.width > this.imageDim.height) { 137 this.imageEl.style.width = (this.imageZoom*this.containerDim.width)+'px'; 138 } else { 139 this.imageEl.style.height = (this.imageZoom*this.containerDim.height)+'px'; 140 } 141 if (this.containerDim.ratio) { 142 if (this.imageDim.width > this.imageDim.height) { 143 this.imageEl.style.height = (this.imageZoom*this.containerDim.width*this.containerDim.ratio)+'px'; // for safari 144 } else { 145 this.imageEl.style.width = (this.imageZoom*this.containerDim.height*this.containerDim.ratio)+'px'; // for safari 146 } 147 } 148 } else { 149 this.slider.setDisabled(); 150 } 151 152 this.imageX = this.containerDim.width*(1-this.imageZoom)/2-centerX*this.imageZoom; 153 this.imageY = this.containerDim.height*(1-this.imageZoom)/2-centerY*this.imageZoom; 154 155 this.contain(this.imageX, this.imageY, this.draggable); 156 157 return true; 158 }, 159 160 startZoomIn: function() 161 { 162 if (!this.slider.disabled) { 163 this.zoomBtnPressed = true; 164 this.sliderAccel = .002; 165 this.periodicalZoom(); 166 this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05); 167 } 168 return this; 169 }, 170 171 startZoomOut: function() 172 { 173 if (!this.slider.disabled) { 174 this.zoomBtnPressed = true; 175 this.sliderAccel = -.002; 176 this.periodicalZoom(); 177 this.zoomer = new PeriodicalExecuter(this.periodicalZoom.bind(this), .05); 178 } 179 return this; 180 }, 181 182 stopZooming: function() 183 { 184 if (!this.zoomer || this.sliderSpeed==0) { 185 return; 186 } 187 this.zoomBtnPressed = false; 188 this.sliderAccel = 0; 189 }, 190 191 periodicalZoom: function() 192 { 193 if (!this.zoomer) { 194 return this; 195 } 196 197 if (this.zoomBtnPressed) { 198 this.sliderSpeed += this.sliderAccel; 199 } else { 200 this.sliderSpeed /= 1.5; 201 if (Math.abs(this.sliderSpeed)<.001) { 202 this.sliderSpeed = 0; 203 this.zoomer.stop(); 204 this.zoomer = null; 205 } 206 } 207 this.slider.value += this.sliderSpeed; 208 209 this.slider.setValue(this.slider.value); 210 this.scale(this.slider.value); 211 212 return this; 213 }, 214 215 contain: function (x,y,draggable) { 216 217 var dim = Element.getDimensions(draggable.element); 218 219 var xMin = 0, xMax = this.containerDim.width-dim.width; 220 var yMin = 0, yMax = this.containerDim.height-dim.height; 221 222 x = x>xMin ? xMin : x; 223 x = x<xMax ? xMax : x; 224 y = y>yMin ? yMin : y; 225 y = y<yMax ? yMax : y; 226 227 if (this.containerDim.width > dim.width) { 228 x = (this.containerDim.width/2) - (dim.width/2); 229 } 230 231 if (this.containerDim.height > dim.height) { 232 y = (this.containerDim.height/2) - (dim.height/2); 233 } 234 235 this.imageX = x; 236 this.imageY = y; 237 238 this.imageEl.style.left = this.imageX+'px'; 239 this.imageEl.style.top = this.imageY+'px'; 240 241 return [x,y]; 242 } 243}; 244 245/**************************** CONFIGURABLE PRODUCT **************************/ 246Product.Config = Class.create(); 247Product.Config.prototype = { 248 initialize: function(config){ 249 this.config = config; 250 this.taxConfig = this.config.taxConfig; 251 this.settings = $$('.super-attribute-select'); 252 this.state = new Hash(); 253 this.priceTemplate = new Template(this.config.template); 254 this.prices = config.prices; 255 256 this.settings.each(function(element){ 257 Event.observe(element, 'change', this.configure.bind(this)); 258 }.bind(this)); 259 260 // fill state 261 this.settings.each(function(element){
262 var attributeId = element.id.replace(/[a-z]*/, ''); 263 if(attributeId && this.config.attributes[attributeId]) { 264 element.config = this.config.attributes[attributeId]; 265 element.attributeId = attributeId; 266 this.state[attributeId] = false; 267 } 268 }.bind(this)); 269 270 // Init settings dropdown 271 var childSettings = []; 272 for(var i=this.settings.length-1;i>=0;i--){ 273 var prevSetting = this.settings[i-1] ? this.settings[i-1] : false; 274 var nextSetting = this.settings[i+1] ? this.settings[i+1] : false; 275 if(i==0){ 276 this.fillSelect(this.settings[i]); 277 } 278 else { 279 this.settings[i].disabled=true; 280 } 281 $(this.settings[i]).childSettings = childSettings.clone(); 282 $(this.settings[i]).prevSetting = prevSetting; 283 $(this.settings[i]).nextSetting = nextSetting; 284 childSettings.push(this.settings[i]); 285 } 286 287 // Set default values - from config and overwrite them by url values 288 if (config.defaultValues) { 289 this.values = config.defaultValues; 290 } 291 292 var separatorIndex = window.location.href.indexOf('#'); 293 if (separatorIndex != -1) { 294 var paramsStr = window.location.href.substr(separatorIndex+1); 295 var urlValues = paramsStr.toQueryParams(); 296 if (!this.values) { 297 this.values = {}; 298 } 299 for (var i in urlValues) { 300 this.values[i] = urlValues[i]; 301 } 302 } 303 304 this.configureForValues(); 305 document.observe("dom:loaded", this.configureForValues.bind(this)); 306 }, 307 308 configureForValues: function () { 309 if (this.values) { 310 this.settings.each(function(element){ 311 var attributeId = element.attributeId; 312 element.value = (typeof(this.values[attributeId]) == 'undefined')? '' : this.values[attributeId]; 313 this.configureElement(element); 314 }.bind(this)); 315 } 316 }, 317 318 configure: function(event){ 319 var element = Event.element(event); 320 this.configureElement(element); 321 }, 322 323 configureElement : function(element) { 324 this.reloadOptionLabels(element); 325 if(element.value){ 326 this.state[element.config.id] = element.value; 327 if(element.nextSetting){ 328 element.nextSetting.disabled = false; 329 this.fillSelect(element.nextSetting); 330 this.resetChildren(element.nextSetting); 331 } 332 } 333 else { 334 this.resetChildren(element); 335 } 336 this.reloadPrice(); 337// Calculator.updatePrice(); 338 }, 339 340 reloadOptionLabels: function(element){ 341 var selectedPrice; 342 if(element.options[element.selectedIndex].config){ 343 selectedPrice = parseFloat(element.options[element.selectedIndex].config.price); 344 } 345 else{ 346 selectedPrice = 0; 347 } 348 for(var i=0;i<element.options.length;i++){ 349 if(element.options[i].config){ 350 element.options[i].text = this.getOptionLabel(element.options[i].config, element.options[i].config.price-selectedPrice); 351 } 352 } 353 }, 354 355 resetChildren : function(element){ 356 if(element.childSettings) { 357 for(var i=0;i<element.childSettings.length;i++){ 358 element.childSettings[i].selectedIndex = 0; 359 element.childSettings[i].disabled = true; 360 if(element.config){ 361 this.state[element.config.id] = false; 362 } 363 } 364 } 365 }, 366 367 fillSelect: function(element){ 368 var attributeId = element.id.replace(/[a-z]*/, ''); 369 var options = this.getAttributeOptions(attributeId); 370 this.clearSelect(element); 371 element.options[0] = new Option('', ''); 372 element.options[0].innerHTML = this.config.chooseText; 373 374 var prevConfig = false; 375 if(element.prevSetting){ 376 prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex]; 377 } 378 379 if(options) { 380 var index = 1; 381 for(var i=0;i<options.length;i++){ 382 var allowedProducts = []; 383 if(prevConfig) { 384 for(var j=0;j<options[i].products.length;j++){ 385 if(prevConfig.config.allowedProducts 386 && prevConfig.config.allowedProducts.indexOf(options[i].products[j])>-1){ 387 allowedProducts.push(options[i].products[j]); 388 } 389 } 390 } else { 391 allowedProducts = options[i].products.clone(); 392 } 393 394 if(allowedProducts.size()>0){ 395 options[i].allowedProducts = allowedProducts; 396 element.options[index] = new Option(this.getOptionLabel(options[i], options[i].price), options[i].id); 397 element.options[index].config = options[i]; 398 index++; 399 } 400 } 401 } 402 }, 403 404 getOptionLabel: function(option, price){ 405 var price = parseFloat(price); 406 if (this.taxConfig.includeTax) { 407 var tax = price / (100 + this.taxConfig.defaultTax) * this.taxConfig.defaultTax; 408 var excl = price - tax; 409 var incl = excl*(1+(this.taxConfig.currentTax/100)); 410 } else { 411 var tax = price * (this.taxConfig.currentTax / 100); 412 var excl = price; 413 var incl = excl + tax; 414 } 415 416 if (this.taxConfig.showIncludeTax || this.taxConfig.showBothPrices) { 417 price = incl; 418 } else { 419 price = excl; 420 } 421 422 var str = option.label; 423 if(price){ 424 if (this.taxConfig.showBothPrices) { 425 str+= ' ' + this.formatPrice(excl, true) + ' (' + this.formatPrice(price, true) + ' ' + this.taxConfig.inclTaxTitle + ')'; 426 } else { 427 str+= ' ' + this.formatPrice(price, true); 428 } 429 } 430 return str; 431 }, 432 433 formatPrice: function(price, showSign){ 434 var str = ''; 435 price = parseFloat(price); 436 if(showSign){ 437 if(price<0){ 438 str+= '-'; 439 price = -price; 440 } 441 else{ 442 str+= '+'; 443 } 444 } 445 446 var roundedPrice = (Math.round(price*100)/100).toString(); 447 448 if (this.prices && this.prices[roundedPrice]) { 449 str+= this.prices[roundedPrice]; 450 } 451 else { 452 str+= this.priceTemplate.evaluate({price:price.toFixed(2)}); 453 } 454 return str; 455 }, 456 457 clearSelect: function(element){ 458 for(var i=element.options.length-1;i>=0;i--){ 459 element.remove(i); 460 } 461 }, 462 463 getAttributeOptions: function(attributeId){ 464 if(this.config.attributes[attributeId]){ 465 return this.config.attributes[attributeId].options; 466 } 467 }, 468 469 reloadPrice: function(){ 470 var price = 0; 471 var oldPrice = 0; 472 for(var i=this.settings.length-1;i>=0;i--){ 473 var selected = this.settings[i].options[this.settings[i].selectedIndex]; 474 if(selected.config){ 475 price += parseFloat(selected.config.price); 476 oldPrice += parseFloat(selected.config.oldPrice); 477 } 478 } 479 480 optionsPrice.changePrice('config', {'price': price, 'oldPrice': oldPrice}); 481 optionsPrice.reload(); 482 483 return price; 484 }, 485 486 reloadOldPrice: function(){ 487 if ($('old-price-'+this.config.productId)) { 488 489 var price = parseFloat(this.config.oldPrice); 490 for(var i=this.settings.length-1;i>=0;i--){ 491 var selected = this.settings[i].options[this.settings[i].selectedIndex]; 492 if(selected.config){ 493 var parsedOldPrice = parseFloat(selected.config.oldPrice); 494 price += isNaN(parsedOldPrice) ? 0 : parsedOldPrice; 495 } 496 } 497 if (price < 0) 498 price = 0; 499 price = this.formatPrice(price); 500 501 if($('old-price-'+this.config.productId)){ 502 $('old-price-'+this.config.productId).innerHTML = price; 503 } 504 505 } 506 } 507}; 508 509 510/**************************** SUPER PRODUCTS ********************************/ 511 512Product.Super = {}; 513Product.Super.Configurable = Class.create(); 514 515Product.Super.Configurable.prototype = { 516 initialize: function(container, observeCss, updateUrl, updatePriceUrl, priceContainerId) { 517 this.container = $(container); 518 this.observeCss = observeCss; 519 this.updateUrl = updateUrl; 520 this.updatePriceUrl = updatePriceUrl; 521 this.priceContainerId = priceContainerId; 522 this.registerObservers(); 523 }, 524 registerObservers: function() { 525 var elements = this.container.getElementsByClassName(this.observeCss); 526 elements.each(function(element){ 527 Event.observe(element, 'change', this.update.bindAsEventListener(this)); 528 }.bind(this)); 529 return this; 530 }, 531 update: function(event) { 532 var elements = this.container.getElementsByClassName(this.observeCss); 533 var parameters = Form.serializeElements(elements, true); 534 535 new Ajax.Updater(this.container, this.updateUrl + '?ajax=1', { 536 parameters:parameters, 537 onComplete:this.registerObservers.bind(this) 538 }); 539 var priceContainer = $(this.priceContainerId); 540 if(priceContainer) { 541 new Ajax.Updater(priceContainer, this.updatePriceUrl + '?ajax=1', { 542 parameters:parameters 543 }); 544 } 545 } 546};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.