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