text: /**
   * 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@magento.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.magento.com for more information.
   *
   * @category    Varien
   * @package     js
   * @copyright   Copyright (c) 2006-2020 Magento, Inc. (http://www.magento.com)
   * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
   */
  function popWin(url,win,para) {
      var win = window.open(url,win,para);
      win.focus();
  }
  
  function setLocation(url){
      window.location.href = encodeURI(url);
  }
  
  function setPLocation(url, setFocus){
      if( setFocus ) {
          window.opener.focus();
      }
      window.opener.location.href = encodeURI(url);
  }
  
  /**
   * @deprecated
   */
  function setLanguageCode(code, fromCode){
      //TODO: javascript cookies have different domain and path than php cookies
      var href = window.location.href;
      var after = '', dash;
      if (dash = href.match(/\#(.*)$/)) {
          href = href.replace(/\#(.*)$/, '');
          after = dash[0];
      }
  
      if (href.match(/[?]/)) {
          var re = /([?&]store=)[a-z0-9_]*/;
          if (href.match(re)) {
              href = href.replace(re, '$1'+code);
          } else {
              href += '&store='+code;
          }
  
          var re = /([?&]from_store=)[a-z0-9_]*/;
          if (href.match(re)) {
              href = href.replace(re, '');
          }
      } else {
          href += '?store='+code;
      }
      if (typeof(fromCode) != 'undefined') {
          href += '&from_store='+fromCode;
      }
      href += after;
  
      setLocation(href);
  }
  
  /**
   * Add classes to specified elements.
   * Supported classes are: 'odd', 'even', 'first', 'last'
   *
   * @param elements - array of elements to be decorated
   * [@param decorateParams] - array of classes to be set. If omitted, all available will be used
   */
  function decorateGeneric(elements, decorateParams)
  {
      var allSupportedParams = ['odd', 'even', 'first', 'last'];
      var _decorateParams = {};
      var total = elements.length;
  
      if (total) {
          // determine params called
          if (typeof(decorateParams) == 'undefined') {
              decorateParams = allSupportedParams;
          }
          if (!decorateParams.length) {
              return;
          }
          for (var k in allSupportedParams) {
              _decorateParams[allSupportedParams[k]] = false;
          }
          for (var k in decorateParams) {
              _decorateParams[decorateParams[k]] = true;
          }
  
          // decorate elements
          // elements[0].addClassName('first'); // will cause bug in IE (#5587)
          if (_decorateParams.first) {
              Element.addClassName(elements[0], 'first');
          }
          if (_decorateParams.last) {
              Element.addClassName(elements[total-1], 'last');
          }
          for (var i = 0; i < total; i++) {
              if ((i + 1) % 2 == 0) {
                  if (_decorateParams.even) {
                      Element.addClassName(elements[i], 'even');
                  }
              }
              else {
                  if (_decorateParams.odd) {
                      Element.addClassName(elements[i], 'odd');
                  }
              }
          }
      }
  }
  
  /**
   * Decorate table rows and cells, tbody etc
   * @see decorateGeneric()
   */
  function decorateTable(table, options) {
      var table = $(table);
      if (table) {
          // set default options
          var _options = {
              'tbody'    : false,
              'tbody tr' : ['odd', 'even', 'first', 'last'],
              'thead tr' : ['first', 'last'],
              'tfoot tr' : ['first', 'last'],
              'tr td'    : ['last']
          };
          // overload options
          if (typeof(options) != 'undefined') {
              for (var k in options) {
                  _options[k] = options[k];
              }
          }
          // decorate
          if (_options['tbody']) {
              decorateGeneric(table.select('tbody'), _options['tbody']);
          }
          if (_options['tbody tr']) {
              decorateGeneric(table.select('tbody tr'), _options['tbody tr']);
          }
          if (_options['thead tr']) {
              decorateGeneric(table.select('thead tr'), _options['thead tr']);
          }
          if (_options['tfoot tr']) {
              decorateGeneric(table.select('tfoot tr'), _options['tfoot tr']);
          }
          if (_options['tr td']) {
              var allRows = table.select('tr');
              if (allRows.length) {
                  for (var i = 0; i < allRows.length; i++) {
                      decorateGeneric(allRows[i].getElementsByTagName('TD'), _options['tr td']);
                  }
              }
          }
      }
  }
  
  /**
   * Set "odd", "even" and "last" CSS classes for list items
   * @see decorateGeneric()
   */
  function decorateList(list, nonRecursive) {
      if ($(list)) {
          if (typeof(nonRecursive) == 'undefined') {
              var items = $(list).select('li');
          }
          else {
              var items = $(list).childElements();
          }
          decorateGeneric(items, ['odd', 'even', 'last']);
      }
  }
  
  /**
   * Set "odd", "even" and "last" CSS classes for list items
   * @see decorateGeneric()
   */
  function decorateDataList(list) {
      list = $(list);
      if (list) {
          decorateGeneric(list.select('dt'), ['odd', 'even', 'last']);
          decorateGeneric(list.select('dd'), ['odd', 'even', 'last']);
      }
  }
  
  /**
   * Parse SID and produces the correct URL
   */
  function parseSidUrl(baseUrl, urlExt) {
      var sidPos = baseUrl.indexOf('/?SID=');
      var sid = '';
      urlExt = (urlExt != undefined) ? urlExt : '';
  
      if(sidPos > -1) {
          sid = '?' + baseUrl.substring(sidPos + 2);
          baseUrl = baseUrl.substring(0, sidPos + 1);
      }
  
      return baseUrl+urlExt+sid;
  }
  
  /**
   * Formats currency using patern
   * format - JSON (pattern, decimal, decimalsDelimeter, groupsDelimeter)
   * showPlus - true (always show '+'or '-'),
   *      false (never show '-' even if number is negative)
   *      null (show '-' if number is negative)
   */
  
  function formatCurrency(price, format, showPlus){
      var precision = isNaN(format.precision = Math.abs(format.precision)) ? 2 : format.precision;
      var requiredPrecision = isNaN(format.requiredPrecision = Math.abs(format.requiredPrecision)) ? 2 : format.requiredPrecision;
  
      //precision = (precision > requiredPrecision) ? precision : requiredPrecision;
      //for now we don't need this difference so precision is requiredPrecision
      precision = requiredPrecision;
  
      var integerRequired = isNaN(format.integerRequired = Math.abs(format.integerRequired)) ? 1 : format.integerRequired;
  
      var decimalSymbol = format.decimalSymbol == undefined ? "," : format.decimalSymbol;
      var groupSymbol = format.groupSymbol == undefined ? "." : format.groupSymbol;
      var groupLength = format.groupLength == undefined ? 3 : format.groupLength;
  
      var s = '';
  
      if (showPlus == undefined || showPlus == true) {
          s = price < 0 ? "-" : ( showPlus ? "+" : "");
      } else if (showPlus == false) {
          s = '';
      }
  
      var i = parseInt(price = Math.abs(+price || 0).toFixed(precision)) + "";
      var pad = (i.length < integerRequired) ? (integerRequired - i.length) : 0;
      while (pad) { i = '0' + i; pad--; }
      j = (j = i.length) > groupLength ? j % groupLength : 0;
      re = new RegExp("(\\d{" + groupLength + "})(?=\\d)", "g");
  
      /**
       * replace(/-/, 0) is only for fixing Safari bug which appears
       * when Math.abs(0).toFixed() executed on "0" number.
       * Result is "0.-0" :(
       */
      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) : "");
      var pattern = '';
      if (format.pattern.indexOf('{sign}') == -1) {
          pattern = s + format.pattern;
      } else {
          pattern = format.pattern.replace('{sign}', s);
      }
  
      return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  };
  
  function expandDetails(el, childClass) {
      if (Element.hasClassName(el,'show-details')) {
          $$(childClass).each(function(item){
              item.hide();
          });
          Element.removeClassName(el,'show-details');
      }
      else {
          $$(childClass).each(function(item){
              item.show();
          });
          Element.addClassName(el,'show-details');
      }
  }
  
  // Version 1.0
  var isIE = navigator.appVersion.match(/MSIE/) == "MSIE";
  
  if (!window.Varien)
      var Varien = new Object();
  
  Varien.showLoading = function(){
      var loader = $('loading-process');
      loader && loader.show();
  };
  Varien.hideLoading = function(){
      var loader = $('loading-process');
      loader && loader.hide();
  };
  Varien.GlobalHandlers = {
      onCreate: function() {
          Varien.showLoading();
      },
  
      onComplete: function() {
          if(Ajax.activeRequestCount == 0) {
              Varien.hideLoading();
          }
      }
  };
  
  Ajax.Responders.register(Varien.GlobalHandlers);
  
  /**
   * Quick Search form client model
   */
  Varien.searchForm = Class.create();
  Varien.searchForm.prototype = {
      initialize : function(form, field, emptyText){
          this.form   = $(form);
          this.field  = $(field);
          this.emptyText = emptyText;
  
          Event.observe(this.form,  'submit', this.submit.bind(this));
          Event.observe(this.field, 'focus', this.focus.bind(this));
          Event.observe(this.field, 'blur', this.blur.bind(this));
          this.blur();
      },
  
      submit : function(event){
          if (this.field.value == this.emptyText || this.field.value == ''){
              Event.stop(event);
              return false;
          }
          return true;
      },
  
      focus : function(event){
          if(this.field.value==this.emptyText){
              this.field.value='';
          }
  
      },
  
      blur : function(event){
          if(this.field.value==''){
              this.field.value=this.emptyText;
          }
      },
  
      initAutocomplete : function(url, destinationElement){
          new Ajax.Autocompleter(
              this.field,
              destinationElement,
              url,
              {
                  paramName: this.field.name,
                  method: 'get',
                  minChars: 2,
                  updateElement: this._selectAutocompleteItem.bind(this),
                  onShow : function(element, update) {
                      if(!update.style.position || update.style.position=='absolute') {
                          update.style.position = 'absolute';
                          Position.clone(element, update, {
                              setHeight: false,
                              offsetTop: element.offsetHeight
                          });
                      }
                      Effect.Appear(update,{duration:0});
                  }
  
              }
          );
      },
  
      _selectAutocompleteItem : function(element){
          if(element.title){
              this.field.value = element.title;
          }
          this.form.submit();
      }
  };
  
  Varien.Tabs = Class.create();
  Varien.Tabs.prototype = {
    initialize: function(selector) {
      var self=this;
      $$(selector+' a').each(this.initTab.bind(this));
    },
  
    initTab: function(el) {
        el.href = 'javascript:void(0)';
        if ($(el.parentNode).hasClassName('active')) {
          this.showContent(el);
        }
        el.observe('click', this.showContent.bind(this, el));
    },
  
    showContent: function(a) {
      var li = $(a.parentNode), ul = $(li.parentNode);
      ul.getElementsBySelector('li', 'ol').each(function(el){
        var contents = $(el.id+'_contents');
        if (el==li) {
          el.addClassName('active');
          contents.show();
        } else {
          el.removeClassName('active');
          contents.hide();
        }
      });
    }
  };
  
  Varien.DateElement = Class.create();
  Varien.DateElement.prototype = {
      initialize: function(type, content, required, format) {
          if (type == 'id') {
              // id prefix
              this.day    = $(content + 'day');
              this.month  = $(content + 'month');
              this.year   = $(content + 'year');
              this.full   = $(content + 'full');
              this.advice = $(content + 'date-advice');
          } else if (type == 'container') {
              // content must be container with data
              this.day    = content.day;
              this.month  = content.month;
              this.year   = content.year;
              this.full   = content.full;
              this.advice = content.advice;
          } else {
              return;
          }
  
          this.required = required;
          this.format   = format;
  
          this.day.addClassName('validate-custom');
          this.day.validate = this.validate.bind(this);
          this.month.addClassName('validate-custom');
          this.month.validate = this.validate.bind(this);
          this.year.addClassName('validate-custom');
          this.year.validate = this.validate.bind(this);
  
          this.setDateRange(false, false);
          this.year.setAttribute('autocomplete','off');
  
          this.advice.hide();
  
          var date = new Date;
          this.curyear = date.getFullYear();
      },
      validate: function() {
          var error = false,
              day   = parseInt(this.day.value, 10)   || 0,
              month = parseInt(this.month.value, 10) || 0,
              year  = parseInt(this.year.value, 10)  || 0;
          if (this.day.value.strip().empty()
              && this.month.value.strip().empty()
              && this.year.value.strip().empty()
          ) {
              if (this.required) {
                  error = 'This date is a required value.';
              } else {
                  this.full.value = '';
              }
          } else if (!day || !month || !year) {
              error = 'Please enter a valid full date';
          } else {
              var date = new Date, countDaysInMonth = 0, errorType = null;
              date.setYear(year);date.setMonth(month-1);date.setDate(32);
              countDaysInMonth = 32 - date.getDate();
              if(!countDaysInMonth || countDaysInMonth>31) countDaysInMonth = 31;
              if(year < 1900) error = this.errorTextModifier(this.validateDataErrorText);
  
              if (day<1 || day>countDaysInMonth) {
                  errorType = 'day';
                  error = 'Please enter a valid day (1-%d).';
              } else if (month<1 || month>12) {
                  errorType = 'month';
                  error = 'Please enter a valid month (1-12).';
              } else {
                  if(day % 10 == day) this.day.value = '0'+day;
                  if(month % 10 == month) this.month.value = '0'+month;
                  this.full.value = this.format.replace(/%[mb]/i, this.month.value).replace(/%[de]/i, this.day.value).replace(/%y/i, this.year.value);
                  var testFull = this.month.value + '/' + this.day.value + '/'+ this.year.value;
                  var test = new Date(testFull);
                  if (isNaN(test)) {
                      error = 'Please enter a valid date.';
                  } else {
                      this.setFullDate(test);
                  }
              }
              var valueError = false;
              if (!error && !this.validateData()){//(year<1900 || year>curyear) {
                  errorType = this.validateDataErrorType;//'year';
                  valueError = this.validateDataErrorText;//'Please enter a valid year (1900-%d).';
                  error = valueError;
              }
          }
  
          if (error !== false) {
              try {
                  error = Translator.translate(error);
              }
              catch (e) {}
              if (!valueError) {
                  this.advice.innerHTML = error.replace('%d', countDaysInMonth);
              } else {
                  this.advice.innerHTML = this.errorTextModifier(error);
              }
              this.advice.show();
              return false;
          }
  
          // fixing elements class
          this.day.removeClassName('validation-failed');
          this.month.removeClassName('validation-failed');
          this.year.removeClassName('validation-failed');
  
          this.advice.hide();
          return true;
      },
      validateData: function() {
          var year = this.fullDate.getFullYear();
          return (year>=1900 && year<=this.curyear);
      },
      validateDataErrorType: 'year',
      validateDataErrorText: 'Please enter a valid year (1900-%d).',
      errorTextModifier: function(text) {
          text = Translator.translate(text);
          return text.replace('%d', this.curyear);
      },
      setDateRange: function(minDate, maxDate) {
          this.minDate = minDate;
          this.maxDate = maxDate;
      },
      setFullDate: function(date) {
          this.fullDate = date;
      }
  };
  
  Varien.DOB = Class.create();
  Varien.DOB.prototype = {
      initialize: function(selector, required, format) {
          var el = $$(selector)[0];
          var container       = {};
          container.day       = Element.select(el, '.dob-day input')[0];
          container.month     = Element.select(el, '.dob-month input')[0];
          container.year      = Element.select(el, '.dob-year input')[0];
          container.full      = Element.select(el, '.dob-full input')[0];
          container.advice    = Element.select(el, '.validation-advice')[0];
  
          new Varien.DateElement('container', container, required, format);
      }
  };
  
  Varien.dateRangeDate = Class.create();
  Varien.dateRangeDate.prototype = Object.extend(new Varien.DateElement(), {
      validateData: function() {
          var validate = true;
          if (this.minDate || this.maxValue) {
              if (this.minDate) {
                  this.minDate = new Date(this.minDate);
                  this.minDate.setHours(0);
                  if (isNaN(this.minDate)) {
                      this.minDate = new Date('1/1/1900');
                  }
                  validate = validate && (this.fullDate >= this.minDate);
              }
              if (this.maxDate) {
                  this.maxDate = new Date(this.maxDate);
                  this.minDate.setHours(0);
                  if (isNaN(this.maxDate)) {
                      this.maxDate = new Date();
                  }
                  validate = validate && (this.fullDate <= this.maxDate);
              }
              if (this.maxDate && this.minDate) {
                  this.validateDataErrorText = 'Please enter a valid date between %s and %s';
              } else if (this.maxDate) {
                  this.validateDataErrorText = 'Please enter a valid date less than or equal to %s';
              } else if (this.minDate) {
                  this.validateDataErrorText = 'Please enter a valid date equal to or greater than %s';
              } else {
                  this.validateDataErrorText = '';
              }
          }
          return validate;
      },
      validateDataErrorText: 'Date should be between %s and %s',
      errorTextModifier: function(text) {
          if (this.minDate) {
              text = text.sub('%s', this.dateFormat(this.minDate));
          }
          if (this.maxDate) {
              text = text.sub('%s', this.dateFormat(this.maxDate));
          }
          return text;
      },
      dateFormat: function(date) {
          return (date.getMonth() + 1) + '/' + date.getDate() + '/' + date.getFullYear();
      }
  });
  
  Varien.FileElement = Class.create();
  Varien.FileElement.prototype = {
      initialize: function (id) {
          this.fileElement = $(id);
          this.hiddenElement = $(id + '_value');
  
          this.fileElement.observe('change', this.selectFile.bind(this));
      },
      selectFile: function(event) {
          this.hiddenElement.value = this.fileElement.getValue();
      }
  };
  
  Validation.addAllThese([
      ['validate-custom', ' ', function(v,elm) {
          return elm.validate();
      }]
  ]);
  
  function truncateOptions() {
      $$('.truncated').each(function(element){
          Event.observe(element, 'mouseover', function(){
              if (element.down('div.truncated_full_value')) {
                  element.down('div.truncated_full_value').addClassName('show');
              }
          });
          Event.observe(element, 'mouseout', function(){
              if (element.down('div.truncated_full_value')) {
                  element.down('div.truncated_full_value').removeClassName('show');
              }
          });
  
      });
  }
  Event.observe(window, 'load', function(){
     truncateOptions();
  });
  
  Element.addMethods({
      getInnerText: function(element)
      {
          element = $(element);
          if(element.innerText && !Prototype.Browser.Opera) {
              return element.innerText;
          }
          return element.innerHTML.stripScripts().unescapeHTML().replace(/[\n\r\s]+/g, ' ').strip();
      }
  });
  
  /*
  if (!("console" in window) || !("firebug" in console))
  {
      var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
      "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
  
      window.console = {};
      for (var i = 0; i < names.length; ++i)
          window.console[names[i]] = function() {}
  }
  */
  
  /**
   * Executes event handler on the element. Works with event handlers attached by Prototype,
   * in a browser-agnostic fashion.
   * @param element The element object
   * @param event Event name, like 'change'
   *
   * @example fireEvent($('my-input', 'click'));
   */
  function fireEvent(element, event) {
      if (document.createEvent) {
          // dispatch for all browsers except IE before version 9
          var evt = document.createEvent("HTMLEvents");
          evt.initEvent(event, true, true ); // event type, bubbling, cancelable
          return element.dispatchEvent(evt);
      } else {
          // dispatch for IE before version 9
          var evt = document.createEventObject();
          return element.fireEvent('on' + event, evt);
      }
  }
  
  /**
   * Returns more accurate results of floating-point modulo division
   * E.g.:
   * 0.6 % 0.2 = 0.19999999999999996
   * modulo(0.6, 0.2) = 0
   *
   * @param dividend
   * @param divisor
   */
  function modulo(dividend, divisor)
  {
      var epsilon = divisor / 10000;
      var remainder = dividend % divisor;
  
      if (Math.abs(remainder - divisor) < epsilon || Math.abs(remainder) < epsilon) {
          remainder = 0;
      }
  
      return remainder;
  }
  
  /**
   * createContextualFragment is not supported in IE9. Adding its support.
   */
  if ((typeof Range != "undefined") && !Range.prototype.createContextualFragment)
  {
      Range.prototype.createContextualFragment = function(html)
      {
          var frag = document.createDocumentFragment(),
          div = document.createElement("div");
          frag.appendChild(div);
          div.outerHTML = html;
          return frag;
      };
  }
  
  /**
   * Create form element. Set parameters into it and send
   *
   * @param url
   * @param parametersArray
   * @param method
   */
  Varien.formCreator = Class.create();
  Varien.formCreator.prototype = {
      initialize : function(url, parametersArray, method) {
          this.url = url;
          this.parametersArray = JSON.parse(parametersArray);
          this.method = method;
          this.form = '';
  
          this.createForm();
          this.setFormData();
      },
      createForm : function() {
          this.form = new Element('form', { 'method': this.method, action: this.url });
      },
      setFormData : function () {
          for (var key in this.parametersArray) {
              Element.insert(
                  this.form,
                  new Element('input', { name: key, value: this.parametersArray[key], type: 'hidden' })
              );
          }
      }
  };
  
  function customFormSubmit(url, parametersArray, method) {
      var createdForm = new Varien.formCreator(url, parametersArray, method);
      Element.insert($$('body')[0], createdForm.form);
      createdForm.form.submit();
  }
  
  function customFormSubmitToParent(url, parametersArray, method) {
      new Ajax.Request(url, {
          method: method,
          parameters: JSON.parse(parametersArray),
          onSuccess: function (response) {
              var node = document.createElement('div');
              node.innerHTML = response.responseText;
              var responseMessage = node.getElementsByClassName('messages')[0];
              var pageTitle = window.document.body.getElementsByClassName('page-title')[0];
              pageTitle.insertAdjacentHTML('afterend', responseMessage.outerHTML);
              window.opener.focus();
              window.opener.location.href = response.transport.responseURL;
          }
      });
  }
  
  function buttonDisabler() {
      var buttons = document.querySelectorAll('button.save');
      buttons.forEach(function(button) {
          button.disabled = true;
      });
  }
  