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-2015 X.commerce, Inc. (http://www.magento.com) 23 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) 24 */ 25function popWin(url,win,para) { 26 var win = window.open(url,win,para); 27 win.focus(); 28} 29 30function setLocation(url){ 31 window.location.href = url; 32} 33 34function setPLocation(url, setFocus){ 35 if( setFocus ) { 36 window.opener.focus(); 37 } 38 window.opener.location.href = url; 39} 40 41function setLanguageCode(code, fromCode){ 42 //TODO: javascript cookies have different domain and path than php cookies 43 var href = window.location.href; 44 var after = '', dash; 45 if (dash = href.match(/\#(.*)$/)) { 46 href = href.replace(/\#(.*)$/, ''); 47 after = dash[0]; 48 } 49 50 if (href.match(/[?]/)) { 51 var re = /([?&]store=)[a-z0-9_]*/; 52 if (href.match(re)) { 53 href = href.replace(re, '$1'+code); 54 } else { 55 href += '&store='+code; 56 } 57 58 var re = /([?&]from_store=)[a-z0-9_]*/; 59 if (href.match(re)) { 60 href = href.replace(re, ''); 61 } 62 } else { 63 href += '?store='+code; 64 } 65 if (typeof(fromCode) != 'undefined') { 66 href += '&from_store='+fromCode; 67 } 68 href += after; 69 70 setLocation(href); 71} 72 73/** 74 * Add classes to specified elements. 75 * Supported classes are: 'odd', 'even', 'first', 'last' 76 * 77 * @param elements - array of elements to be decorated 78 * [@param decorateParams] - array of classes to be set. If omitted, all available will be used 79 */ 80function decorateGeneric(elements, decorateParams) 81{ 82 var allSupportedParams = ['odd', 'even', 'first', 'last']; 83 var _decorateParams = {}; 84 var total = elements.length; 85 86 if (total) { 87 // determine params called 88 if (typeof(decorateParams) == 'undefined') { 89 decorateParams = allSupportedParams; 90 } 91 if (!decorateParams.length) { 92 return; 93 } 94 for (var k in allSupportedParams) { 95 _decorateParams[allSupportedParams[k]] = false; 96 } 97 for (var k in decorateParams) { 98 _decorateParams[decorateParams[k]] = true; 99 } 100 101 // decorate elements 102 // elements[0].addClassName('first'); // will cause bug in IE (#5587) 103 if (_decorateParams.first) { 104 Element.addClassName(elements[0], 'first'); 105 } 106 if (_decorateParams.last) { 107 Element.addClassName(elements[total-1], 'last'); 108 } 109 for (var i = 0; i < total; i++) { 110 if ((i + 1) % 2 == 0) { 111 if (_decorateParams.even) { 112 Element.addClassName(elements[i], 'even'); 113 } 114 } 115 else { 116 if (_decorateParams.odd) { 117 Element.addClassName(elements[i], 'odd'); 118 } 119 } 120 } 121 } 122} 123 124/** 125 * Decorate table rows and cells, tbody etc 126 * @see decorateGeneric() 127 */ 128function decorateTable(table, options) { 129 var table = $(table); 130 if (table) { 131 // set default options 132 var _options = { 133 'tbody' : false, 134 'tbody tr' : ['odd', 'even', 'first', 'last'], 135 'thead tr' : ['first', 'last'], 136 'tfoot tr' : ['first', 'last'], 137 'tr td' : ['last'] 138 }; 139 // overload options 140 if (typeof(options) != 'undefined') { 141 for (var k in options) { 142 _options[k] = options[k]; 143 } 144 } 145 // decorate 146 if (_options['tbody']) { 147 decorateGeneric(table.select('tbody'), _options['tbody']); 148 } 149 if (_options['tbody tr']) { 150 decorateGeneric(table.select('tbody tr'), _options['tbody tr']); 151 } 152 if (_options['thead tr']) { 153 decorateGeneric(table.select('thead tr'), _options['thead tr']); 154 } 155 if (_options['tfoot tr']) { 156 decorateGeneric(table.select('tfoot tr'), _options['tfoot tr']); 157 } 158 if (_options['tr td']) { 159 var allRows = table.select('tr'); 160 if (allRows.length) { 161 for (var i = 0; i < allRows.length; i++) { 162 decorateGeneric(allRows[i].getElementsByTagName('TD'), _options['tr td']); 163 } 164 } 165 } 166 } 167} 168 169/** 170 * Set "odd", "even" and "last" CSS classes for list items 171 * @see decorateGeneric() 172 */ 173function decorateList(list, nonRecursive) { 174 if ($(list)) { 175 if (typeof(nonRecursive) == 'undefined') { 176 var items = $(list).select('li') 177 } 178 else { 179 var items = $(list).childElements(); 180 } 181 decorateGeneric(items, ['odd', 'even', 'last']); 182 } 183} 184 185/** 186 * Set "odd", "even" and "last" CSS classes for list items 187 * @see decorateGeneric() 188 */ 189function decorateDataList(list) { 190 list = $(list); 191 if (list) { 192 decorateGeneric(list.select('dt'), ['odd', 'even', 'last']); 193 decorateGeneric(list.select('dd'), ['odd', 'even', 'last']); 194 } 195} 196 197/** 198 * Parse SID and produces the correct URL 199 */ 200function parseSidUrl(baseUrl, urlExt) { 201 var sidPos = baseUrl.indexOf('/?SID='); 202 var sid = ''; 203 urlExt = (urlExt != undefined) ? urlExt : ''; 204 205 if(sidPos > -1) { 206 sid = '?' + baseUrl.substring(sidPos + 2); 207 baseUrl = baseUrl.substring(0, sidPos + 1); 208 } 209 210 return baseUrl+urlExt+sid; 211} 212 213/** 214 * Formats currency using patern 215 * format - JSON (pattern, decimal, decimalsDelimeter, groupsDelimeter) 216 * showPlus - true (always show '+'or '-'), 217 * false (never show '-' even if number is negative) 218 * null (show '-' if number is negative) 219 */ 220 221function formatCurrency(price, format, showPlus){ 222 var precision = isNaN(format.precision = Math.abs(format.precision)) ? 2 : format.precision; 223 var requiredPrecision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision; 224 225 //precision = (precision > requiredPrecision) ? precision : requiredPrecision; 226 //for now we don't need this difference so precision is requiredPrecision 227 precision = requiredPrecision; 228 229 var integerRequired = isNaN(format.integerRequired = Math.abs(format.integerRequired)) ? 1 : format.integerRequired; 230 231 var decimalSymbol = format.decimalSymbol == undefined ? "," : format.decimalSymbol; 232 var groupSymbol = format.groupSymbol == undefined ? "." : format.groupSymbol; 233 var groupLength = format.groupLength == undefined ? 3 : format.groupLength; 234 235 var s = ''; 236 237 if (showPlus == undefined || showPlus == true) { 238 s = price < 0 ? "-" : ( showPlus ? "+" : ""); 239 } else if (showPlus == false) { 240 s = ''; 241 } 242 243 var i = parseInt(price = Math.abs(+price || 0).toFixed(precision)) + ""; 244 var pad = (i.length < integerRequired) ? (integerRequired - i.length) : 0; 245 while (pad) { i = '0' + i; pad--; } 246 j = (j = i.length) > groupLength ? j % groupLength : 0; 247 re = new RegExp("(\\d{" + groupLength + "})(?=\\d)", "g"); 248 249 /** 250 * replace(/-/, 0) is only for fixing Safari bug which appears 251 * when Math.abs(0).toFixed() executed on "0" number. 252 * Result is "0.-0" :( 253 */ 254 var r = (j ? i.substr(0, j) + groupSymbol : "") + i.substr(j).replace(re, "$1" + groupSymbol) + (precision ? decimalSymbol + Math.abs(price - i).toFixed(precision).replace(/-/, 0).slice(2) : "") 255 var pattern = ''; 256 if (format.pattern.indexOf('{sign}') == -1) { 257 pattern = s + format.pattern; 258 } else { 259 pattern = format.pattern.replace('{sign}', s); 260 } 261 262 return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); 263}; 264 265function expandDetails(el, childClass) {
266 if (Element.hasClassName(el,'show-details')) { 267 $$(childClass).each(function(item){item.hide()}); 268 Element.removeClassName(el,'show-details'); 269 } 270 else { 271 $$(childClass).each(function(item){item.show()}); 272 Element.addClassName(el,'show-details'); 273 } 274} 275 276// Version 1.0 277var isIE = navigator.appVersion.match(/MSIE/) == "MSIE"; 278 279if (!window.Varien) 280 var Varien = new Object(); 281 282Varien.showLoading = function(){ 283 var loader = $('loading-process'); 284 loader && loader.show(); 285} 286Varien.hideLoading = function(){ 287 var loader = $('loading-process'); 288 loader && loader.hide(); 289} 290Varien.GlobalHandlers = { 291 onCreate: function() { 292 Varien.showLoading(); 293 }, 294 295 onComplete: function() { 296 if(Ajax.activeRequestCount == 0) { 297 Varien.hideLoading(); 298 } 299 } 300}; 301 302Ajax.Responders.register(Varien.GlobalHandlers); 303 304/** 305 * Quick Search form client model 306 */ 307Varien.searchForm = Class.create(); 308Varien.searchForm.prototype = { 309 initialize : function(form, field, emptyText){ 310 this.form = $(form); 311 this.field = $(field); 312 this.emptyText = emptyText; 313 314 Event.observe(this.form, 'submit', this.submit.bind(this)); 315 Event.observe(this.field, 'focus', this.focus.bind(this)); 316 Event.observe(this.field, 'blur', this.blur.bind(this)); 317 this.blur(); 318 }, 319 320 submit : function(event){ 321 if (this.field.value == this.emptyText || this.field.value == ''){ 322 Event.stop(event); 323 return false; 324 } 325 return true; 326 }, 327 328 focus : function(event){ 329 if(this.field.value==this.emptyText){ 330 this.field.value=''; 331 } 332 333 }, 334 335 blur : function(event){ 336 if(this.field.value==''){ 337 this.field.value=this.emptyText; 338 } 339 }, 340 341 initAutocomplete : function(url, destinationElement){ 342 new Ajax.Autocompleter( 343 this.field, 344 destinationElement, 345 url, 346 { 347 paramName: this.field.name, 348 method: 'get', 349 minChars: 2, 350 updateElement: this._selectAutocompleteItem.bind(this), 351 onShow : function(element, update) { 352 if(!update.style.position || update.style.position=='absolute') { 353 update.style.position = 'absolute'; 354 Position.clone(element, update, { 355 setHeight: false, 356 offsetTop: element.offsetHeight 357 }); 358 }
359 Effect.Appear(update,{duration:0}); 360 } 361 362 } 363 ); 364 }, 365 366 _selectAutocompleteItem : function(element){ 367 if(element.title){ 368 this.field.value = element.title; 369 } 370 this.form.submit(); 371 } 372} 373 374Varien.Tabs = Class.create(); 375Varien.Tabs.prototype = { 376 initialize: function(selector) { 377 var self=this; 378 $$(selector+' a').each(this.initTab.bind(this)); 379 }, 380 381 initTab: function(el) { 382 el.href = 'javascript:void(0)'; 383 if ($(el.parentNode).hasClassName('active')) { 384 this.showContent(el); 385 } 386 el.observe('click', this.showContent.bind(this, el)); 387 }, 388 389 showContent: function(a) { 390 var li = $(a.parentNode), ul = $(li.parentNode); 391 ul.getElementsBySelector('li', 'ol').each(function(el){ 392 var contents = $(el.id+'_contents'); 393 if (el==li) { 394 el.addClassName('active'); 395 contents.show(); 396 } else { 397 el.removeClassName('active'); 398 contents.hide(); 399 } 400 }); 401 } 402} 403 404Varien.DateElement = Class.create(); 405Varien.DateElement.prototype = { 406 initialize: function(type, content, required, format) { 407 if (type == 'id') { 408 // id prefix 409 this.day = $(content + 'day'); 410 this.month = $(content + 'month'); 411 this.year = $(content + 'year'); 412 this.full = $(content + 'full'); 413 this.advice = $(content + 'date-advice'); 414 } else if (type == 'container') { 415 // content must be container with data 416 this.day = content.day; 417 this.month = content.month; 418 this.year = content.year; 419 this.full = content.full; 420 this.advice = content.advice; 421 } else { 422 return; 423 } 424 425 this.required = required; 426 this.format = format; 427 428 this.day.addClassName('validate-custom'); 429 this.day.validate = this.validate.bind(this); 430 this.month.addClassName('validate-custom'); 431 this.month.validate = this.validate.bind(this); 432 this.year.addClassName('validate-custom'); 433 this.year.validate = this.validate.bind(this); 434 435 this.setDateRange(false, false); 436 this.year.setAttribute('autocomplete','off'); 437 438 this.advice.hide(); 439 }, 440 validate: function() { 441 var error = false, 442 day = parseInt(this.day.value, 10) || 0, 443 month = parseInt(this.month.value, 10) || 0, 444 year = parseInt(this.year.value, 10) || 0; 445 if (this.day.value.strip().empty() 446 && this.month.value.strip().empty() 447 && this.year.value.strip().empty() 448 ) { 449 if (this.required) { 450 error = 'This date is a required value.'; 451 } else { 452 this.full.value = ''; 453 } 454 } else if (!day || !month || !year) { 455 error = 'Please enter a valid full date.'; 456 } else { 457 var date = new Date, countDaysInMonth = 0, errorType = null; 458 date.setYear(year);date.setMonth(month-1);date.setDate(32); 459 countDaysInMonth = 32 - date.getDate(); 460 if(!countDaysInMonth || countDaysInMonth>31) countDaysInMonth = 31; 461 462 if (day<1 || day>countDaysInMonth) { 463 errorType = 'day'; 464 error = 'Please enter a valid day (1-%d).'; 465 } else if (month<1 || month>12) { 466 errorType = 'month'; 467 error = 'Please enter a valid month (1-12).'; 468 } else { 469 if(day % 10 == day) this.day.value = '0'+day; 470 if(month % 10 == month) this.month.value = '0'+month; 471 this.full.value = this.format.replace(/%[mb]/i, this.month.value).replace(/%[de]/i, this.day.value).replace(/%y/i, this.year.value); 472 var testFull = this.month.value + '/' + this.day.value + '/'+ this.year.value; 473 var test = new Date(testFull); 474 if (isNaN(test)) { 475 error = 'Please enter a valid date.'; 476 } else { 477 this.setFullDate(test); 478 } 479 } 480 var valueError = false;
481 if (!error && !this.validateData()){//(year<1900 || year>curyear) { 482 errorType = this.validateDataErrorType;//'year'; 483 valueError = this.validateDataErrorText;//'Please enter a valid year (1900-%d).'; 484 error = valueError; 485 } 486 } 487 488 if (error !== false) { 489 try { 490 error = Translator.translate(error); 491 } 492 catch (e) {} 493 if (!valueError) { 494 this.advice.innerHTML = error.replace('%d', countDaysInMonth); 495 } else { 496 this.advice.innerHTML = this.errorTextModifier(error); 497 } 498 this.advice.show(); 499 return false; 500 } 501 502 // fixing elements class 503 this.day.removeClassName('validation-failed'); 504 this.month.removeClassName('validation-failed'); 505 this.year.removeClassName('validation-failed'); 506 507 this.advice.hide(); 508 return true; 509 }, 510 validateData: function() { 511 var year = this.fullDate.getFullYear(); 512 var date = new Date; 513 this.curyear = date.getFullYear(); 514 return (year>=1900 && year<=this.curyear); 515 }, 516 validateDataErrorType: 'year', 517 validateDataErrorText: 'Please enter a valid year (1900-%d).', 518 errorTextModifier: function(text) { 519 return text.replace('%d', this.curyear); 520 }, 521 setDateRange: function(minDate, maxDate) { 522 this.minDate = minDate; 523 this.maxDate = maxDate; 524 }, 525 setFullDate: function(date) { 526 this.fullDate = date; 527 } 528}; 529 530Varien.DOB = Class.create(); 531Varien.DOB.prototype = { 532 initialize: function(selector, required, format) { 533 var el = $$(selector)[0]; 534 var container = {}; 535 container.day = Element.select(el, '.dob-day input')[0]; 536 container.month = Element.select(el, '.dob-month input')[0]; 537 container.year = Element.select(el, '.dob-year input')[0]; 538 container.full = Element.select(el, '.dob-full input')[0]; 539 container.advice = Element.select(el, '.validation-advice')[0]; 540 541 new Varien.DateElement('container', container, required, format); 542 } 543}; 544 545Varien.dateRangeDate = Class.create(); 546Varien.dateRangeDate.prototype = Object.extend(new Varien.DateElement(), { 547 validateData: function() { 548 var validate = true; 549 if (this.minDate || this.maxValue) { 550 if (this.minDate) { 551 this.minDate = new Date(this.minDate); 552 this.minDate.setHours(0); 553 if (isNaN(this.minDate)) { 554 this.minDate = new Date('1/1/1900'); 555 } 556 validate = validate && (this.fullDate >= this.minDate) 557 } 558 if (this.maxDate) { 559 this.maxDate = new Date(this.maxDate) 560 this.minDate.setHours(0); 561 if (isNaN(this.maxDate)) { 562 this.maxDate = new Date(); 563 } 564 validate = validate && (this.fullDate <= this.maxDate) 565 } 566 if (this.maxDate && this.minDate) { 567 this.validateDataErrorText = 'Please enter a valid date between %s and %s'; 568 } else if (this.maxDate) { 569 this.validateDataErrorText = 'Please enter a valid date less than or equal to %s'; 570 } else if (this.minDate) { 571 this.validateDataErrorText = 'Please enter a valid date equal to or greater than %s'; 572 } else { 573 this.validateDataErrorText = ''; 574 } 575 } 576 return validate; 577 }, 578 validateDataErrorText: 'Date should be between %s and %s', 579 errorTextModifier: function(text) { 580 if (this.minDate) { 581 text = text.sub('%s', this.dateFormat(this.minDate)); 582 } 583 if (this.maxDate) { 584 text = text.sub('%s', this.dateFormat(this.maxDate)); 585 } 586 return text; 587 }, 588 dateFormat: function(date) { 589 return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear(); 590 } 591}); 592 593Varien.FileElement = Class.create(); 594Varien.FileElement.prototype = { 595 initialize: function (id) { 596 this.fileElement = $(id); 597 this.hiddenElement = $(id + '_value'); 598 599 this.fileElement.observe('change', this.selectFile.bind(this)); 600 }, 601 selectFile: function(event) { 602 this.hiddenElement.value = this.fileElement.getValue(); 603 } 604}; 605 606Validation.addAllThese([ 607 ['validate-custom', ' ', function(v,elm) { 608 return elm.validate(); 609 }] 610]); 611 612function truncateOptions() { 613 $$('.truncated').each(function(element){ 614 Event.observe(element, 'mouseover', function(){ 615 if (element.down('div.truncated_full_value')) { 616 element.down('div.truncated_full_value').addClassName('show') 617 } 618 }); 619 Event.observe(element, 'mouseout', function(){ 620 if (element.down('div.truncated_full_value')) { 621 element.down('div.truncated_full_value').removeClassName('show') 622 } 623 }); 624 625 }); 626} 627Event.observe(window, 'load', function(){ 628 truncateOptions(); 629}); 630 631Element.addMethods({ 632 getInnerText: function(element) 633 { 634 element = $(element); 635 if(element.innerText && !Prototype.Browser.Opera) { 636 return element.innerText 637 } 638 return element.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g, ' ').strip(); 639 } 640}); 641 642/* 643if (!("console" in window) || !("firebug" in console)) 644{ 645 var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", 646 "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; 647 648 window.console = {}; 649 for (var i = 0; i < names.length; ++i) 650 window.console[names[i]] = function() {} 651} 652*/ 653 654/** 655 * Executes event handler on the element. Works with event handlers attached by Prototype, 656 * in a browser-agnostic fashion. 657 * @param element The element object 658 * @param event Event name, like 'change' 659 * 660 * @example fireEvent($('my-input', 'click')); 661 */ 662function fireEvent(element, event) { 663 if (document.createEvent) { 664 // dispatch for all browsers except IE before version 9 665 var evt = document.createEvent("HTMLEvents"); 666 evt.initEvent(event, true, true ); // event type, bubbling, cancelable 667 return element.dispatchEvent(evt); 668 } else { 669 // dispatch for IE before version 9 670 var evt = document.createEventObject(); 671 return element.fireEvent('on' + event, evt) 672 } 673} 674 675/** 676 * Returns more accurate results of floating-point modulo division 677 * E.g.: 678 * 0.6 % 0.2 = 0.19999999999999996 679 * modulo(0.6, 0.2) = 0 680 * 681 * @param dividend 682 * @param divisor 683 */ 684function modulo(dividend, divisor) 685{ 686 var epsilon = divisor / 10000; 687 var remainder = dividend % divisor; 688 689 if (Math.abs(remainder - divisor) < epsilon || Math.abs(remainder) < epsilon) { 690 remainder = 0; 691 } 692 693 return remainder; 694} 695 696/** 697 * createContextualFragment is not supported in IE9. Adding its support. 698 */ 699if ((typeof Range != "undefined") && !Range.prototype.createContextualFragment) 700{ 701 Range.prototype.createContextualFragment = function(html) 702 { 703 var frag = document.createDocumentFragment(), 704 div = document.createElement("div"); 705 frag.appendChild(div); 706 div.outerHTML = html; 707 return frag; 708 }; 709} 710 711/** 712 * Create form element. Set parameters into it and send 713 * 714 * @param url 715 * @param parametersArray 716 * @param method 717 */ 718Varien.formCreator = Class.create(); 719Varien.formCreator.prototype = { 720 initialize : function(url, parametersArray, method) { 721 this.url = url; 722 this.parametersArray = JSON.parse(parametersArray); 723 this.method = method; 724 this.form = ''; 725 726 this.createForm(); 727 this.setFormData(); 728 }, 729 createForm : function() { 730 this.form = new Element('form', { 'method': this.method, action: this.url }); 731 }, 732 setFormData : function () { 733 for (var key in this.parametersArray) { 734 Element.insert( 735 this.form, 736 new Element('input', { name: key, value: this.parametersArray[key], type: 'hidden' }) 737 ); 738 } 739 } 740}; 741 742function customFormSubmit(url, parametersArray, method) { 743 var createdForm = new Varien.formCreator(url, parametersArray, method); 744 Element.insert($$('body')[0], createdForm.form); 745 createdForm.form.submit(); 746} 747 748function customFormSubmitToParent(url, parametersArray, method) { 749 new Ajax.Request(url, { 750 method: method, 751 parameters: JSON.parse(parametersArray), 752 onSuccess: function (response) { 753 var node = document.createElement('div'); 754 node.innerHTML = response.responseText; 755 var responseMessage = node.getElementsByClassName('messages')[0]; 756 var pageTitle = window.document.body.getElementsByClassName('page-title')[0]; 757 pageTitle.insertAdjacentHTML('afterend', responseMessage.outerHTML);
758 window.opener.focus(); 759 window.opener.location.href = response.transport.responseURL; 760 } 761 }); 762}
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.