1// Miva Merchant 2// 3// This file and the source codes contained herein are the property of 4// Miva, Inc. Use of this file is restricted to the specific terms and 5// conditions in the License Agreement associated with this file. Distribution 6// of this file or portions of this file for uses not covered by the License 7// Agreement is not allowed without a written agreement signed by an officer of 8// Miva, Inc. 9// 10// Copyright 1998-2026 Miva, Inc. All rights reserved. 11// http://www.miva.com 12// 13 14function DeriveFrom( base_class, child_class ) 15{ 16 var placeholder; 17 18 placeholder = function() { ; } 19 placeholder.prototype = base_class.prototype; 20 child_class.prototype = new placeholder(); 21 child_class.prototype.constructor = child_class; 22} 23 24function newElement( type, attributes, styles, parent ) 25{ 26 var element; 27 28 element = document.createElement( type ); 29 30 setElementAttributes( element, attributes ); 31 setElementStyles( element, styles ); 32 33 if ( parent ) 34 { 35 parent.appendChild( element ); 36 } 37 38 return element; 39} 40 41function newTextNode( text, parent ) 42{ 43 var element; 44 45 element = document.createTextNode( text ); 46 47 if ( parent ) 48 { 49 parent.appendChild( element ); 50 } 51 52 return element; 53} 54 55function newTextNode_EmptyParent( text, parent ) 56{ 57 if ( parent ) 58 { 59 parent.innerHTML = ''; 60 } 61 62 return newTextNode( text, parent ); 63} 64 65function setElementAttributes( element, attributes ) 66{ 67 var attribute; 68 69 for ( attribute in attributes ) 70 { 71 if ( !attributes.hasOwnProperty( attribute ) ) 72 { 73 continue; 74 } 75 76 if ( attribute == 'name' ) element.name = attributes[ attribute ]; 77 else if ( attribute == 'class' ) element.className = attributes[ attribute ]; 78 else element.setAttribute( attribute, attributes[ attribute ] ); 79 } 80} 81 82function setElementStyles( element, styles ) 83{ 84 var style; 85 86 for ( style in styles ) 87 { 88 if ( styles.hasOwnProperty( style ) ) 89 { 90 element.style[ style ] = styles[ style ]; 91 } 92 } 93} 94 95function classNameContains( element, classname, allow_regex_in_classname ) 96{ 97 var i, i_len, classlist; 98 99 classlist = element.className.split( /\s/ ); 100 101 for ( i = 0, i_len = classlist.length; i < i_len; i++ ) 102 { 103 if ( classlist[ i ] == '' ) continue; 104 else if ( !allow_regex_in_classname && classlist[ i ] == classname ) return true; 105 else if ( allow_regex_in_classname && classlist[ i ].match( new RegExp( '(?:^)' + classname + '(?:$)' ) ) ) return true; 106 } 107 108 return false; 109} 110 111function classNameReplace( element, classname, replacement_classname, allow_regex_in_classname ) 112{ 113 var i, i_len, classlist, new_classlist; 114 115 new_classlist = new Array(); 116 classlist = element.className.split( /\s/ ); 117 118 for ( i = 0, i_len = classlist.length; i < i_len; i++ ) 119 { 120 if ( classlist[ i ] == '' ) continue; 121 else if ( !allow_regex_in_classname && classlist[ i ] == classname ) continue; 122 else if ( allow_regex_in_classname && classlist[ i ].match( new RegExp( '(?:^)' + classname + '(?:$)' ) ) ) continue; 123 124 new_classlist.push( classlist[ i ] ); 125 } 126 127 new_classlist.push( replacement_classname ); 128 129 return new_classlist.join( ' ' ); 130} 131 132function classNameReplaceIfAltered( element, classname, replacement_classname, allow_regex_in_classname ) 133{ 134 var new_classlist, original_classlist; 135 136 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 137 original_classlist = original_classlist.filter( function( filter_classname ) { return filter_classname !== ''; } ); 138 new_classlist = original_classlist.filter( function( filter_classname ) 139 { 140 if ( filter_classname === replacement_classname ) 141 { 142 return false; 143 } 144 145 if ( !allow_regex_in_classname ) 146 { 147 return filter_classname !== classname; 148 } 149 150 return !filter_classname.match( new RegExp( '(?:^)' + classname + '(?:$)' ) ); 151 } ); 152 153 new_classlist.push( replacement_classname ); 154 155 new_classlist.sort(); 156 original_classlist.sort(); 157 158 if ( !compareObjects( original_classlist, new_classlist ) ) 159 { 160 element.className = new_classlist.join( ' ' ); 161 } 162} 163 164function classNameAdd( element, classname ) 165{ 166 var new_classlist, original_classlist; 167 168 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 169 new_classlist = original_classlist.filter( function( filter_classname ) { return ( filter_classname !== '' && filter_classname !== classname ); } ); 170
171 new_classlist.push( classname ); 172 173 return new_classlist.join( ' ' ); 174} 175 176function classNameAddIfMissing( element, classname ) 177{ 178 var new_classlist, original_classlist; 179 180 if ( Array.isArray( classname ) ) 181 { 182 return classNameAddListIfMissing( element, classname ); 183 } 184 185 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 186 original_classlist = original_classlist.filter( function( filter_classname ) { return filter_classname !== ''; } ); 187 new_classlist = original_classlist.filter( function( filter_classname ) { return filter_classname !== classname; } ); 188 189 new_classlist.push( classname ); 190 191 new_classlist.sort(); 192 original_classlist.sort(); 193 194 if ( !compareObjects( original_classlist, new_classlist ) ) 195 { 196 element.className = new_classlist.join( ' ' ); 197 } 198} 199 200function classNameAddList( element, classnamelist ) 201{ 202 var new_classlist, original_classlist; 203 204 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 205 new_classlist = original_classlist.filter( function( filter_classname ) { return filter_classname !== '' && classnamelist.indexOf( filter_classname ) === -1; } ); 206 new_classlist = new_classlist.concat( classnamelist ); 207 208 return new_classlist.join( ' ' ); 209} 210 211function classNameAddListIfMissing( element, classnamelist ) 212{ 213 var new_classlist, original_classlist; 214 215 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 216 original_classlist = original_classlist.filter( function( filter_classname ) { return filter_classname !== ''; } ); 217 new_classlist = original_classlist.filter( function( filter_classname ) { return classnamelist.indexOf( filter_classname ) === -1; } ); 218 new_classlist = new_classlist.concat( classnamelist ); 219 220 new_classlist.sort(); 221 original_classlist.sort(); 222 223 if ( !compareObjects( original_classlist, new_classlist ) ) 224 { 225 element.className = new_classlist.join( ' ' ); 226 } 227} 228 229function classNameRemove( element, classname, allow_regex_in_classname ) 230{ 231 var new_classlist, original_classlist; 232 233 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 234 new_classlist = original_classlist.filter( function( filter_classname ) 235 { 236 if ( filter_classname === '' ) return false; 237 else if ( !allow_regex_in_classname ) return filter_classname !== classname; 238 239 return !filter_classname.match( new RegExp( '(?:^)' + classname + '(?:$)' ) ); 240 } ); 241 242 return new_classlist.join( ' ' ); 243} 244 245function classNameRemoveIfPresent( element, classname, allow_regex_in_classname ) 246{ 247 var new_classlist, original_classlist; 248 249 if ( Array.isArray( classname ) ) 250 { 251 return classNameRemoveListIfPresent( element, classname, allow_regex_in_classname ); 252 } 253 254 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 255 original_classlist = original_classlist.filter( function( filter_classname ) { return filter_classname !== ''; } ); 256 new_classlist = original_classlist.filter( function( filter_classname ) 257 { 258 if ( !allow_regex_in_classname ) 259 { 260 return filter_classname !== classname; 261 } 262 263 return !filter_classname.match( new RegExp( '(?:^)' + classname + '(?:$)' ) ); 264 } ); 265 266 new_classlist.sort(); 267 original_classlist.sort(); 268 269 if ( !compareObjects( original_classlist, new_classlist ) ) 270 { 271 element.className = new_classlist.join( ' ' ); 272 } 273} 274 275function classNameRemoveList( element, classnamelist, allow_regex_in_classname ) 276{ 277 var new_classlist, original_classlist; 278 279 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 280 new_classlist = original_classlist.filter( function( filter_classname ) 281 { 282 var i, i_len; 283 284 if ( filter_classname === '' ) return false; 285 else if ( !allow_regex_in_classname ) return classnamelist.indexOf( filter_classname ) === -1; 286 287 for ( i = 0, i_len = classnamelist.length; i < i_len; i++ ) 288 { 289 if ( filter_classname.match( new RegExp( '(?:^)' + classnamelist[ i ] + '(?:$)' ) ) ) 290 { 291 return false;
292 } 293 } 294 295 return true; 296 } ); 297 298 return new_classlist.join( ' ' ); 299} 300 301function classNameRemoveListIfPresent( element, classnamelist, allow_regex_in_classname ) 302{ 303 var new_classlist, original_classlist; 304 305 original_classlist = element.className.split( /\s/ ).map( function( filter_classname ) { return trim( filter_classname ); } ); 306 original_classlist = original_classlist.filter( function( filter_classname ) { return filter_classname !== ''; } ); 307 new_classlist = original_classlist.filter( function( filter_classname ) 308 { 309 var i, i_len; 310 311 if ( !allow_regex_in_classname ) 312 { 313 return classnamelist.indexOf( filter_classname ) === -1; 314 } 315 316 for ( i = 0, i_len = classnamelist.length; i < i_len; i++ ) 317 { 318 if ( filter_classname.match( new RegExp( '(?:^)' + classnamelist[ i ] + '(?:$)' ) ) ) 319 { 320 return false; 321 } 322 } 323 324 return true; 325 } ); 326 327 new_classlist.sort(); 328 original_classlist.sort(); 329 330 if ( !compareObjects( original_classlist, new_classlist ) ) 331 { 332 element.className = new_classlist.join( ' ' ); 333 } 334} 335 336function computedStyleValue( element, property ) 337{ 338 if ( element instanceof Element ) 339 { 340 return window.getComputedStyle( element, null ).getPropertyValue( property ) 341 } 342 else if ( element.ownerDocument && element.ownerDocument.defaultView && element instanceof element.ownerDocument.defaultView.Element ) 343 { 344 return element.ownerDocument.defaultView.getComputedStyle( element, null ).getPropertyValue( property ); 345 } 346 347 return returnUndefined() 348} 349 350function elementExistsInNodeType( element, type ) 351{ 352 while ( element ) 353 { 354 if ( element.nodeName.toLowerCase() == type.toLowerCase() ) 355 { 356 return true; 357 } 358 359 element = element.parentNode; 360 } 361 362 return false; 363} 364 365function getNearestElementAncestorNodeTypeOrNull( element, type /* can be comma separated string */ ) 366{ 367 var typelist = type.toLowerCase().split( ',' ); 368 369 while ( element ) 370 { 371 if ( typelist.indexOf( element.nodeName.toLowerCase() ) != -1 ) 372 { 373 return element; 374 } 375 376 element = element.parentNode; 377 } 378 379 return null; 380} 381 382function getNearestElementAncestorWithStyleValue( element, property, value /* can be comma separated string */ ) 383{ 384 var style, valuelist; 385 386 valuelist = value.toLowerCase().split( ',' ); 387 388 while ( element ) 389 { 390 style = computedStyleValue( element, property ); 391 392 if ( typeof style === 'string' && valuelist.indexOf( style.toLowerCase() ) !== -1 ) 393 { 394 return element; 395 } 396 397 element = element.parentNode; 398 } 399 400 return null; 401} 402 403function getPreviousTreeNode( start_node, root_node ) 404{ 405 if ( start_node === root_node ) 406 { 407 return null; 408 } 409 else if ( start_node.previousSibling ) 410 { 411 if ( start_node.previousSibling.hasChildNodes() ) 412 { 413 return start_node.previousSibling.childNodes[ start_node.previousSibling.childNodes.length - 1 ]; 414 } 415 416 return start_node.previousSibling; 417 } 418 else if ( start_node.parentNode && start_node.parentNode !== root_node ) 419 { 420 return start_node.parentNode; 421 } 422 423 return null; 424} 425 426function getNextTreeNode( start_node, root_node ) 427{ 428 var current_node; 429 430 if ( start_node.hasChildNodes() ) 431 { 432 return start_node.childNodes[ 0 ]; 433 } 434 else if ( start_node !== root_node ) 435 { 436 if ( start_node.nextSibling ) 437 { 438 return start_node.nextSibling; 439 } 440 else 441 { 442 current_node = start_node; 443 444 while ( current_node = current_node.parentNode ) 445 { 446 if ( current_node === root_node ) 447 { 448 return null; 449 } 450 else if ( current_node.nextSibling ) 451 { 452 return current_node.nextSibling; 453 } 454 } 455 } 456 } 457 458 return null; 459} 460 461function getScopedElementsByClassName( className, scope ) 462{ 463 var regex_match, all_elements, results, i; 464 465 regex_match = new RegExp( "(?:^|\\s)" + className + "(?:$|\\s)" ); 466 all_elements = scope.getElementsByTagName( '*' ); 467 results = []; 468 469 for ( i = 0; all_elements[ i ] != null; i++ ) 470 { 471 if ( typeof all_elements[ i ].className === 'string' && ( all_elements[ i ].className.indexOf( className ) != -1 ) && regex_match.test( all_elements[ i ].className ) ) 472 { 473 results.push( all_elements[ i ] ); 474 } 475 } 476 477 return results; 478} 479 480function getScopedElementByName( name, parent_element ) 481{ 482 var i, i_len, children; 483 484 children = parent_element.getElementsByTagName( '*' ); 485 486 if ( children ) 487 { 488 for ( i = 0, i_len = children.length; i < i_len; i++ ) 489 { 490 if ( children[ i ].name == name ) 491 { 492 return children[ i ]; 493 } 494 } 495 } 496 497 return null; 498} 499 500function containsChild( parent_elem, element ) 501{ 502 if ( element ) 503 { 504 while ( ( element = element.parentNode ) != null ) 505 { 506 if ( element === parent_elem ) 507 { 508 return true; 509 } 510 } 511 } 512 513 return false;
514} 515 516function getScrollOffset( e ) 517{ 518 if ( e.type == 'wheel' ) return { x: -e.deltaX, y: -e.deltaY }; 519 else if ( ( e.deltaX || e.deltaY ) && e.deltaMode == 0 ) return { x: ( e.deltaX ? -e.deltaX : 0 ), y: ( e.deltaY ? -e.deltaY : 0 ) }; 520 else if ( ( e.deltaX || e.deltaY ) && e.deltaMode != 0 ) return { x: ( e.deltaX ? -e.deltaX * 18 : 0 ), y: ( e.deltaY ? -e.deltaY * 18 : 0 ) }; 521 else if ( e.wheelDeltaX || e.wheelDeltaY ) return { x: ( originalEvent.wheelDeltaX ? ( originalEvent.wheelDeltaX / 2 ) : 0 ), y: ( originalEvent.wheelDeltaY ? ( originalEvent.wheelDeltaY / 2 ) : ( -originalEvent.wheelDelta / 2 ) ) }; 522 else if ( e.detail ) return { x: 0, y: -originalEvent.detail * 18 }; 523 else return { x: 0, y: ( e.wheelDelta ? e.wheelDelta / 2 : 0 ) }; 524} 525 526function offsetLeft( element ) 527{ 528 var offset = 0; 529 530 while ( element ) 531 { 532 offset += element.offsetLeft; 533 element = element.offsetParent; 534 } 535 536 return offset; 537} 538 539function offsetTop( element ) 540{ 541 var offset = 0; 542 543 while ( element ) 544 { 545 offset += element.offsetTop; 546 element = element.offsetParent; 547 } 548 549 return offset; 550} 551 552function testBoxModel() 553{ 554 var div; 555 556 div = document.createElement( 'div' ); 557 div.style.width = '1px'; 558 div.style.paddingLeft = '1px'; 559 560 document.body.appendChild( div ); 561 562 window.boxModelSupported = div.offsetWidth === 2; 563 window.boxModelTested = true; 564 565 document.body.removeChild( div ).style.display = 'none'; 566} 567 568function getScrollTop() 569{ 570 if ( !window.boxModelTested ) // box model support must be done after document.body loads 571 { 572 testBoxModel(); 573 } 574 575 if ( 'pageYOffset' in window ) return window.pageYOffset; 576 else if ( window.boxModelSupported ) return document.documentElement.scrollTop; 577 else return document.body.scrollTop; 578} 579 580function getScrollLeft() 581{ 582 if ( !window.boxModelTested ) // box model support must be done after document.body loads 583 { 584 testBoxModel(); 585 } 586 587 if ( 'pageXOffset' in window ) return window.pageXOffset; 588 else if ( window.boxModelSupported ) return document.documentElement.scrollLeft; 589 else return document.body.scrollLeft; 590} 591 592function cursorToEnd( element ) 593{ 594 var range; 595 596 element.focus(); 597 598 if ( typeof element.selectionStart == 'number' ) 599 { 600 element.selectionStart = element.value.length; 601 element.selectionEnd = element.value.length; 602 } 603 else if ( typeof element.createTextRange != 'undefined' ) 604 { 605 range = element.createTextRange(); 606 607 range.collapse( false ); 608 range.select(); 609 } 610} 611 612function clearTextSelection() 613{ 614 var range; 615 616 if ( window.getSelection ) 617 { 618 range = window.getSelection(); 619 range.removeAllRanges(); 620 } 621 else if ( document.selection && document.body.createTextRange ) 622 { 623 range = document.body.createTextRange(); 624 range.collapse( true ); 625 range.select(); 626 } 627} 628 629function keySupportsMultiSelect( e ) 630{ 631 if ( e.ctrlKey || e.metaKey ) // In general, e.metaKey is the Command key on Mac and the Windows key on Windows. 632 { 633 return true; 634 } 635 636 return false; 637} 638 639function eventStopPropagation( event ) 640{ 641 if ( event.stopPropagation ) 642 { 643 return event.stopPropagation(); 644 } 645 646 event.cancelBubble = true; 647} 648 649function eventPreventDefault( event ) 650{ 651 if ( event.preventDefault ) 652 { 653 return event.preventDefault(); 654 } 655 656 event.returnValue = false; 657 658 return false; 659} 660 661function returnUndefined() 662{ 663 return; 664} 665 666function AddEvent( obj, eventType, fn ) 667{ 668 try 669 { 670 obj.addEventListener( eventType, fn, false ); 671 return true; 672 } 673 catch ( e ) 674 { 675 try 676 { 677 return obj.attachEvent( 'on' + eventType, fn ); 678 } 679 catch ( e ) 680 { 681 return false; 682 } 683 } 684} 685 686function RemoveEvent( obj, eventType, fn ) 687{ 688 try 689 { 690 obj.removeEventListener( eventType, fn, false ); 691 return true; 692 } 693 catch ( e ) 694 { 695 try 696 { 697 return obj.detachEvent( 'on' + eventType, fn ); 698 } 699 catch ( e ) 700 { 701 return false; 702 } 703 } 704} 705 706function AddScrollEvent( element, original_callback ) 707{ 708 var event_type, callback; 709 710 if ( 'onwheel' in document.createElement( 'div' ) ) event_type = 'wheel'; // IE 9+, FF 17+ 711 else if ( document.onmousewheel !== undefined ) event_type = 'mousewheel'; // IE 8-, Chrome, Safari 712 else event_type = 'DOMMouseScroll'; // FF 16- 713 714 callback = function( originalEvent ) 715 { 716 var event, mousepos; 717 718 mousepos = captureMousePosition( originalEvent ); 719 event = new Object(); 720 event.target = originalEvent.target || originalEvent.srcElement; 721 event.timeStamp = originalEvent.timeStamp ? originalEvent.timeStamp : new Date(); 722 event.eventPhase = originalEvent.eventPhase; 723 event.defaultPrevented = originalEvent.defaultPrevented; 724 event.currentTarget = originalEvent.currentTarget; 725 event.cancelable = originalEvent.cancelable; 726 event.bubbles = originalEvent.bubbles; 727 event.type = 'wheel'; 728 event.pageX = mousepos.x; 729 event.pageY = mousepos.y; 730 event.screenX = originalEvent.screenX; 731 event.screenY = originalEvent.screenY; 732 event.clientX = originalEvent.clientX; 733 event.clientY = originalEvent.clientY; 734 event.ctrlKey = originalEvent.ctrlKey; 735 event.altKey = originalEvent.altKey; 736 event.shiftKey = originalEvent.shiftKey; 737 event.metaKey = originalEvent.metaKey; 738 event.button = originalEvent.button; 739 event.relatedTarget = originalEvent.relatedTarget; 740 event.deltaMode = 0; 741 event.deltaZ = originalEvent.deltaZ || 0; 742 event.preventDefault = function() { originalEvent.preventDefault ? originalEvent.preventDefault() : originalEvent.returnValue = false; }; 743 event.stopPropagation = function() { originalEvent.stopPropagation ? originalEvent.stopPropagation() : originalEvent.cancelBubble = true; }; 744 event.stopImmediatePropagation = originalEvent.stopImmediatePropagation; 745 746 // calculate deltaY (and deltaX) according to the event 747 if ( event_type == 'wheel' ) 748 { 749 event.deltaY = ( originalEvent.deltaMode == 0 ? originalEvent.deltaY : ( originalEvent.deltaMode == 1 ? originalEvent.deltaY * 18 : 0 ) ); 750 event.deltaX = ( originalEvent.deltaMode == 0 ? originalEvent.deltaX : ( originalEvent.deltaMode == 1 ? originalEvent.deltaX * 18 : 0 ) ); 751 } 752 else if ( event_type == 'mousewheel' ) 753 { 754 event.deltaY = ( originalEvent.wheelDeltaY ? ( -originalEvent.wheelDeltaY / 2 ) : ( -originalEvent.wheelDelta / 2 ) ); 755 event.deltaX = ( originalEvent.wheelDeltaX ? ( -originalEvent.wheelDeltaX / 2 ) : 0 ); 756 } 757 else 758 { 759 event.deltaY = originalEvent.detail * 18; 760 event.deltaX = 0; 761 } 762 763 return original_callback( event ); 764 }; 765 original_callback.callback = callback; 766 767 AddEvent( element, event_type, callback ); 768} 769 770function RemoveScrollEvent( element, original_callback ) 771{ 772 var event_type; 773 774 if ( 'onwheel' in document.createElement( 'div' ) ) event_type = 'wheel'; // IE 9+, FF 17+ 775 else if ( document.onmousewheel !== undefined ) event_type = 'mousewheel'; // IE 8-, Chrome, Safari 776 else event_type = 'DOMMouseScroll'; // FF 16- 777 778 RemoveEvent( element, event_type, original_callback.callback ); 779 original_callback.callback = null; 780} 781 782function AddClickEvent( element, onclick ) 783{ 784 element.mm_event_mousedown = function( event ) { return element.Event_OnMouseDown( event ? event : window.event ); }; 785 element.mm_event_mouseup = function( event ) { return element.Event_OnMouseUp( event ? event : window.event ); }; 786 787 element.Event_OnMouseDown = function( e ) 788 { 789 AddEvent( document, 'mouseup', element.mm_event_mouseup ); 790 AddEvent( window, 'blur', element.mm_event_mouseup ); 791 792 eventStopPropagation( e ); 793 return true; 794 } 795 796 element.Event_OnMouseUp = function( e ) 797 { 798 var target = e.target; 799 800 RemoveEvent( document, 'mouseup', element.mm_event_mouseup ); 801 RemoveEvent( window, 'blur', element.mm_event_mouseup ); 802 803 if ( mouseClickType( e ) == 'RIGHT' ) 804 { 805 return true; 806 } 807 808 if ( target !== element && !containsChild( element, target ) ) 809 { 810 return true; 811 } 812 813 if ( typeof onclick === 'function' ) 814 { 815 onclick( e ); 816 } 817 818 eventStopPropagation( e ); 819 return eventPreventDefault( e ); 820 } 821 822 AddEvent( element, 'mousedown', element.mm_event_mousedown ); 823} 824 825function RemoveClickEvent( element, onclick ) 826{ 827 RemoveEvent( element, 'mousedown', element.mm_event_mousedown ); 828 RemoveEvent( document, 'mouseup', element.mm_event_mouseup ); 829 RemoveEvent( window, 'blur', element.mm_event_mouseup ); 830} 831 832function regexEscape( text ) 833{ 834 return text.replace( new RegExp( '[.\\\\+*?\\[\\^\\]$(){}=!<>|:\\-]', 'g' ), '\\$&' ); // Compare to PHP's preg_quote function 835} 836 837function sortAlphaNumeric( a, b, sort_asc ) 838{ 839 var regex_alpha, regex_numeric, replaced_a_alpha, replaced_b_alpha, replaced_a_numeric, replaced_b_numeric; 840 841 regex_alpha = new RegExp( '[^a-zA-Z]', 'g' ); 842 regex_numeric = new RegExp( '[^0-9]', 'g' ); 843 844 replaced_a_alpha = a.replace( regex_alpha, '' ); 845 replaced_b_alpha = b.replace( regex_alpha, '' ); 846 847 if ( replaced_a_alpha === replaced_b_alpha ) 848 { 849 replaced_a_numeric = stoi( a.replace( regex_numeric, '' ) ); 850 replaced_b_numeric = stoi( b.replace( regex_numeric, '' ) ); 851 852 return ( replaced_a_numeric === replaced_b_numeric ) ? 0 : ( ( replaced_a_numeric > replaced_b_numeric ) ? ( sort_asc ? 1 : -1 ) : ( sort_asc ? -1 : 1 ) ); 853 } 854 855 return ( replaced_a_alpha > replaced_b_alpha ) ? ( sort_asc ? 1 : -1 ) : ( sort_asc ? -1 : 1 ); 856} 857 858function stringIntersect( string_a, string_b ) 859{ 860 var i, j, i_len, j_len, grid, match, temp_string, longest_common_substring; 861 862 match = ''; 863 longest_common_substring = 0; 864 865 if ( string_b.length > string_a.length ) 866 {
867 temp_string = string_b; 868 string_b = string_a; 869 string_a = temp_string; 870 } 871 872 grid = new Array( string_a.length ); 873 874 for ( i = 0, i_len = string_a.length; i < i_len; i++ ) 875 { 876 grid[ i ] = new Array( string_b.length ); 877 878 for ( j = 0, j_len = string_b.length; j < j_len; j++ ) 879 { 880 grid[ i ][ j ] = 0; 881 } 882 } 883 884 for ( i = 0, i_len = string_a.length; i < i_len; i++ ) 885 { 886 for ( j = 0, j_len = string_b.length; j < j_len; j++ ) 887 { 888 if ( string_a.charAt( i ) == string_b.charAt( j ) ) 889 { 890 if ( i == 0 || j == 0 ) grid[ i ][ j ] = 1; 891 else grid[ i ][ j ] = grid[ i - 1 ][ j - 1 ] + 1; 892 893 if ( grid[ i ][ j ] > longest_common_substring ) 894 { 895 longest_common_substring = grid[ i ][ j ]; 896 match = ''; 897 } 898 899 if ( grid[ i ][ j ] == longest_common_substring ) 900 { 901 match = string_a.substring( i - longest_common_substring + 1, i + 1 ); 902 } 903 } 904 } 905 } 906 907 if ( ( ( string_b.indexOf( match ) == 0 ) && ( string_a.indexOf( match ) == ( string_a.length - match.length ) ) ) || 908 ( ( string_a.indexOf( match ) == 0 ) && ( string_b.indexOf( match ) == ( string_b.length - match.length ) ) ) ) 909 { 910 return match; 911 } 912 913 return ''; 914} 915 916function textContent( element ) 917{ 918 if ( typeof( element.textContent ) != 'undefined' ) return element.textContent; 919 if ( typeof( element.innerText ) != 'undefined' ) return element.innerText; 920 921 return ''; 922} 923 924function captureMousePosition( e ) 925{ 926 var x, y; 927 928 if ( e.pageX || e.pageY ) 929 { 930 x = e.pageX; 931 y = e.pageY; 932 } 933 else if ( e.clientX || e.clientY ) 934 { 935 x = e.clientX + getScrollLeft(); 936 y = e.clientY + getScrollTop(); 937 } 938 939 return { x: x, y: y }; 940} 941 942function getQueryStringAsArray() 943{ 944 var result, results 945 var querystring, regex, element; 946 947 results = new Array(); 948 querystring = document.location.search.substring( 1 ); 949 regex = /([^&=]+)=([^&]*)/g; 950 951 while ( ( element = regex.exec( querystring ) ) != null ) 952 { 953 result = new Object(); 954 result.name = element[ 1 ]; 955 result.value = element[ 2 ]; 956 957 results.push( result ); 958 } 959 960 return results; 961} 962 963function arrayIndexOf( array, element ) 964{ 965 var i; 966 967 if ( array.indexOf ) 968 { 969 return array.indexOf( element ); 970 } 971 972 for ( i = 0; i < array.length; i++ ) 973 { 974 if ( array[ i ] === element ) 975 { 976 return i; 977 } 978 } 979 980 return -1; 981} 982 983function arrayMove( arr, old_index, new_index ) 984{ 985 var k; 986 987 while ( old_index < 0 ) old_index += arr.length; 988 while ( new_index < 0 ) new_index += arr.length; 989 990 if ( new_index >= arr.length ) 991 { 992 k = new_index - arr.length; 993 while ( ( k-- ) + 1 ) 994 { 995 arr.push( undefined ); 996 } 997 } 998 999 arr.splice( new_index, 0, arr.splice( old_index, 1 )[ 0 ] ); 1000} 1001 1002function arrayFilter( array, func, passed_this ) 1003{ 1004 var i, i_len, value, result; 1005 1006 if ( array.filter ) 1007 { 1008 return array.filter( func, passed_this ); 1009 } 1010 1011 if ( array == null ) throw new TypeError(); 1012 else if ( typeof func !== 'function' ) throw new TypeError(); 1013 1014 result = new Array(); 1015 1016 for ( i = 0, i_len = array.length; i < i_len; i++ ) 1017 { 1018 value = array[ i ]; 1019 if ( func.call( passed_this, value, i, array ) ) 1020 { 1021 result.push( value ); 1022 } 1023 } 1024 1025 return result; 1026} 1027 1028function arrayFind( array, func, passed_this ) 1029{ 1030 var i, i_len, value; 1031 1032 if ( array.find ) 1033 { 1034 return array.find( func, passed_this ); 1035 } 1036 1037 if ( array == null ) throw new TypeError(); 1038 else if ( typeof func !== 'function' ) throw new TypeError(); 1039 1040 for ( i = 0, i_len = array.length; i < i_len; i++ ) 1041 { 1042 value = array[ i ]; 1043 if ( func.call( passed_this, value, i, array ) ) 1044 { 1045 return value; 1046 } 1047 } 1048 1049 return returnUndefined(); 1050} 1051 1052function arrayUniquify( array ) 1053{ 1054 return [ ...new Set( [ ...array ] ) ]; 1055} 1056 1057function compareObjects( obj1, obj2 ) 1058{ 1059 var i, i_len, attribute, obj1_attribute_count, obj2_attribute_count; 1060 1061 if ( obj1 === obj2 ) 1062 { 1063 return true; 1064 } 1065 1066 if ( obj1 instanceof Array && obj2 instanceof Array ) 1067 { 1068 if ( obj1.length != obj2.length ) 1069 { 1070 return false; 1071 } 1072 1073 for ( i = 0, i_len = obj1.length; i < i_len; i++ ) 1074 { 1075 if ( !compareObjects( obj1[ i ], obj2[ i ] ) ) 1076 { 1077 return false; 1078 } 1079 } 1080 1081 return true; 1082 } 1083 else if ( obj1 instanceof Object && obj2 instanceof Object ) 1084 { 1085 obj1_attribute_count = 0; 1086 obj2_attribute_count = 0; 1087 1088 for ( attribute in obj1 ) 1089 { 1090 if ( obj1.hasOwnProperty( attribute ) ) 1091 { 1092 if ( !obj2.hasOwnProperty( attribute ) ) 1093 { 1094 return false;
1095 } 1096 1097 obj1_attribute_count++; 1098 } 1099 } 1100 1101 for ( attribute in obj2 ) 1102 { 1103 if ( obj2.hasOwnProperty( attribute ) ) 1104 { 1105 if ( !obj1.hasOwnProperty( attribute ) ) 1106 { 1107 return false; 1108 } 1109 1110 obj2_attribute_count++; 1111 } 1112 } 1113 1114 if ( obj1_attribute_count != obj2_attribute_count ) 1115 { 1116 return false; 1117 } 1118 1119 for ( attribute in obj1 ) 1120 { 1121 if ( obj1.hasOwnProperty( attribute ) ) 1122 { 1123 if ( !compareObjects( obj1[ attribute ], obj2[ attribute ] ) ) 1124 { 1125 return false; 1126 } 1127 } 1128 } 1129 1130 return true; 1131 } 1132 1133 return false; 1134} 1135 1136function cloneObject( obj ) 1137{ 1138 var obj_copy; 1139 var i, i_len, attribute; 1140 1141 if ( ( obj == null ) || 1142 ( typeof obj != 'object' ) ) 1143 { 1144 return obj; 1145 } 1146 1147 if ( obj instanceof Array ) 1148 { 1149 obj_copy = new Array(); 1150 1151 for ( i = 0, i_len = obj.length; i < i_len; i++ ) 1152 { 1153 obj_copy[ i ] = cloneObject( obj[ i ] ); 1154 } 1155 1156 return obj_copy; 1157 } 1158 else if ( obj instanceof Object ) 1159 { 1160 obj_copy = new Object(); 1161 1162 for ( attribute in obj ) 1163 { 1164 if ( obj.hasOwnProperty( attribute ) ) 1165 { 1166 obj_copy[ attribute ] = cloneObject( obj[ attribute ] ); 1167 } 1168 } 1169 1170 return obj_copy; 1171 } 1172 1173 return obj; 1174} 1175 1176function objectDeepAssign( target, ...sources ) 1177{ 1178 if ( typeof target !== 'object' ) 1179 { 1180 target = new Object(); 1181 } 1182 1183 for ( const source of sources ) 1184 { 1185 for ( const key in source ) 1186 { 1187 if ( typeof source[ key ] !== 'object' || Array.isArray( source[ key ] ) || !target.hasOwnProperty( key ) ) Object.assign( target, { [ key ]: source[ key ] } ); 1188 else target[ key ] = objectDeepAssign( target[ key ], source[ key ] ); 1189 } 1190 } 1191 1192 return target; 1193} 1194 1195function encodeentities( input ) 1196{ 1197 var result; 1198 1199 result = new String( input ); 1200 result = result.replace( /&/g, '&' ); 1201 result = result.replace( /"/g, '"' ); 1202 result = result.replace( /</g, '<' ); 1203 result = result.replace( />/g, '>' ); 1204 result = result.replace( /\(/g, '(' ); 1205 result = result.replace( /\)/g, ')' ); 1206 1207 return result; 1208} 1209 1210function encodeattribute( text ) 1211{ 1212 var i, i_len, character, character_code, data; 1213 1214 if ( typeof text !== 'string' ) 1215 { 1216 return text; 1217 } 1218 1219 data = ''; 1220 1221 for ( i = 0, i_len = text.length; i < i_len; i++ ) 1222 { 1223 character = text.charAt( i ); 1224 character_code = text.charCodeAt( i ); 1225 1226 switch ( character ) 1227 { 1228 case ' ' : 1229 { 1230 data += '+'; 1231 1232 break; 1233 } 1234 case '~' : 1235 case '`' : 1236 case '!' : 1237 case '#' : 1238 case '$' : 1239 case '%' : 1240 case '^' : 1241 case '&' : 1242 case '(' : 1243 case ')' : 1244 case '+' : 1245 case '=' : 1246 case '{' : 1247 case '}' : 1248 case '[' : 1249 case ']' : 1250 case '|' : 1251 case '\\' : 1252 case ':' : 1253 case ';' : 1254 case '"' : 1255 case '\'' : 1256 case '<' : 1257 case '>' : 1258 case ',' : 1259 case '?' : 1260 case '/' : 1261 { 1262 data += '%' + padl( character_code.toString( 16 ).toUpperCase(), 2, '0' ); 1263 1264 break; 1265 } 1266 default : 1267 { 1268 if ( character_code > 0x20 && character_code < 0x7F ) data += character; 1269 else data += '%' + padl( character_code.toString( 16 ).toUpperCase(), 2, '0' ); 1270 1271 break; 1272 } 1273 } 1274 } 1275 1276 return data; 1277} 1278 1279function decodeattribute( text ) 1280{ 1281 if ( typeof text !== 'string' ) 1282 { 1283 return text; 1284 } 1285 1286 return decodeURIComponent( text.replace( new RegExp( regexEscape( '+' ), 'g' ), ' ' ) ); 1287} 1288 1289function trim( value ) 1290{ 1291 if ( typeof value !== 'string' ) return value; 1292 else return value.replace( /^\s+|\s+$/g, '' ); 1293} 1294 1295function GetNormalizedValue( value ) 1296{ 1297 // Normalize line breaks in value string 1298 1299 if ( typeof value !== 'string' ) 1300 { 1301 return ''; 1302 } 1303 1304 value = value.replace( /\r\n/gm, '\n' ); 1305 value = value.replace( /\r/gm, '\n' ); 1306 value = value.replace( /\n/gm, '\r\n' ); 1307 1308 return value; 1309} 1310 1311function RFC3339DateString( date, timezone ) 1312{ 1313 var fixed_timezone, rfc3339_timezone; 1314 1315 timezone = stod( timezone ); 1316 1317 if ( timezone === 0 ) 1318 { 1319 rfc3339_timezone = 'Z'; 1320 } 1321 else 1322 { 1323 fixed_timezone = Math.abs( timezone ).toFixed( 2 ); 1324 rfc3339_timezone = ( ( timezone > 0 ) ? '+' : '-' ) + padl( fixed_timezone.split( '.' )[ 0 ], 2, '0' ) + ':' + padl( Math.floor( ( fixed_timezone.split( '.' )[ 1 ] * 60 ) / 100 ), 2, '0' ); 1325 } 1326 1327 return ( date.getFullYear() + '-' + padl( date.getMonth() + 1, 2, '0' ) + '-' + padl( date.getDate(), 2, '0' ) + 'T' + padl( date.getHours(), 2, '0' ) + ':' + padl( date.getMinutes(), 2, '0' ) + ':' + padl( date.getSeconds(), 2, '0' ) + rfc3339_timezone ); 1328} 1329 1330function RFC3339DateStringNoTimeZone( date ) 1331{ 1332 return ( date.getFullYear() + '-' + padl( date.getMonth() + 1, 2, '0' ) + '-' + padl( date.getDate(), 2, '0' ) + 'T' + padl( date.getHours(), 2, '0' ) + ':' + padl( date.getMinutes(), 2, '0' ) + ':' + padl( date.getSeconds(), 2, '0' ) + '-00:00' ); 1333} 1334 1335function padl( string, length, character ) 1336{ 1337 var pad; 1338 1339 length = stoi_def( length, 0 ); 1340 pad = new Array( Math.ceil( length / character.length ) + 1 ).join( character ); // More efficient for longer strings than a while loop 1341 1342 if ( typeof string !== 'string' ) 1343 { 1344 string = "" + string; 1345 } 1346 1347 if ( string.length >= length ) 1348 { 1349 return string; 1350 } 1351 1352 return pad.substring( 0, length - string.length ) + string; 1353} 1354 1355function padr( string, length, character ) 1356{ 1357 var pad; 1358 1359 length = stoi_def( length, 0 ); 1360 pad = new Array( Math.ceil( length / character.length ) + 1 ).join( character ); // More efficient for longer strings than a while loop 1361 1362 if ( typeof string !== 'string' ) 1363 { 1364 string = "" + string; 1365 } 1366 1367 if ( string.length >= length ) 1368 { 1369 return string; 1370 } 1371 1372 return string + pad.substring( 0, length - string.length ); 1373} 1374 1375function stob( value ) 1376{ 1377 if ( typeof value !== 'string' ) 1378 { 1379 return value ? true : false;
1380 } 1381 1382 value = value.toLowerCase(); 1383 1384 return ( value === '' || value === '0' || value === 'no' || value === 'false' ) ? false : true; 1385} 1386 1387function stoi( value ) 1388{ 1389 return parseInt( value, 10 ); 1390} 1391 1392function stoi_def( value, default_value ) 1393{ 1394 value = stoi( value ); 1395 1396 return ( ( isNaN( value ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? default_value : value ); 1397} 1398 1399function stoi_def_nonneg( value, default_value ) 1400{ 1401 value = stoi( value ); 1402 1403 return ( ( isNaN( value ) || ( value < 0 ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? default_value : value ); 1404} 1405 1406function stoi_min( value, min_value ) 1407{ 1408 value = stoi( value ); 1409 1410 return ( ( isNaN( value ) || ( value < min_value ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? min_value : value ); 1411} 1412 1413function stoi_max( value, max_value ) 1414{ 1415 value = stoi( value ); 1416 1417 return ( ( isNaN( value ) || ( value > max_value ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? max_value : value ); 1418} 1419 1420function stoi_range( value, min_value, max_value, default_value ) 1421{ 1422 return stoi_min( stoi_max( stoi_def( value, default_value ), max_value ), min_value ); 1423} 1424 1425function stod( value ) 1426{ 1427 return parseFloat( value ); 1428} 1429 1430function stod_def( value, default_value ) 1431{ 1432 value = stod( value ); 1433 1434 return ( ( isNaN( value ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? default_value : value ); 1435} 1436 1437function stod_def_nonneg( value, default_value ) 1438{ 1439 value = stod( value ); 1440 1441 return ( ( isNaN( value ) || ( value < 0 ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? default_value : value ); 1442} 1443 1444function stod_min( value, min_value ) 1445{ 1446 value = stod( value ); 1447 1448 return ( ( isNaN( value ) || ( value < min_value ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? min_value : value ); 1449} 1450 1451function stod_max( value, max_value ) 1452{ 1453 value = stod( value ); 1454 1455 return ( ( isNaN( value ) || ( value > max_value ) || value == Number.POSITIVE_INFINITY || value == Number.NEGATIVE_INFINITY ) ? max_value : value ); 1456} 1457 1458function stod_range( value, min_value, max_value, default_value ) 1459{ 1460 return stod_min( stod_max( stod_def( value, default_value ), max_value ), min_value ); 1461} 1462 1463function ValueIsEmpty( value ) 1464{ 1465 if ( value === null ) return true; 1466 else if ( typeof value === 'object' ) return Object.keys( value ).length === 0 && value.constructor === Object; 1467 else if ( typeof value === 'undefined' ) return true; 1468 else if ( typeof value === 'string' && value.length == 0 ) return true; 1469 1470 // type is boolean, number, function, non-zero length string, etc 1471 return false; 1472} 1473 1474function ValueIsNonEmptyString( value ) 1475{ 1476 if ( typeof value !== 'string' ) return false; 1477 else if ( value.trim().length === 0 ) return false; 1478 1479 return true; 1480} 1481 1482function ValueIsNonEmptyArray( value ) 1483{ 1484 if ( !Array.isArray( value ) ) return false; 1485 else if ( value.length === 0 ) return false; 1486 1487 return true; 1488} 1489 1490function getMonthName_Abbreviated( date ) 1491{ 1492 switch ( date.getMonth() ) 1493 { 1494 case 0: return 'Jan'; 1495 case 1: return 'Feb'; 1496 case 2: return 'Mar'; 1497 case 3: return 'Apr'; 1498 case 4: return 'May'; 1499 case 5: return 'Jun'; 1500 case 6: return 'Jul'; 1501 case 7: return 'Aug'; 1502 case 8: return 'Sep'; 1503 case 9: return 'Oct'; 1504 case 10: return 'Nov'; 1505 case 11: return 'Dec'; 1506 } 1507} 1508 1509/* 1510 * Note: This function is also present (with a different name) in ajax.js and v55_ui.js. 1511 * Modifications here should be made in those other locations as well. 1512 */ 1513 1514function isUnicode() 1515{ 1516 return ( document.characterSet || document.charset || '' ).search( 'UTF' ) == 0 ? true : false; 1517} 1518 1519/* 1520 * Note: This function is also present (with a different name) in ajax.js and v55_ui.js. 1521 * Modifications here should be made in those other locations as well. 1522 */ 1523 1524function CharsetEncodeAttribute( instring ) 1525{ 1526 var encoded; 1527 1528 if ( isUnicode() ) 1529 { 1530 return encodeURIComponent( instring ); 1531 } 1532 else 1533 { 1534 if ( typeof escape === 'function' ) 1535 { 1536 encoded = escape( instring ); 1537 encoded = encoded.replace( '+', '%2B' ); 1538 encoded = encoded.replace( '/', '%2F' ); 1539 encoded = encoded.replace( '@', '%40' ); 1540 1541 return encoded; 1542 } 1543 else 1544 { 1545 return instring; 1546 } 1547 } 1548} 1549 1550function CharsetDecodeAttribute( instring ) 1551{ 1552 if ( isUnicode() ) 1553 { 1554 return decodeattribute( instring ); 1555 } 1556 else 1557 { 1558 if ( typeof unescape === 'function' ) return unescape( instring ); 1559 else return instring; 1560 } 1561} 1562 1563function MMStripHTML( string ) 1564{
1565 var html_stripper = new DOMParser().parseFromString( string, 'text/html' ); 1566 1567 return html_stripper.body.textContent; 1568} 1569 1570function Price_Pad( price ) 1571{ 1572 return Decimal_Pad( price, 2 ); 1573} 1574 1575function Decimal_Pad( value, digits ) 1576{ 1577 return stod_def( value, 0.0 ).toLocaleString( 'en-US', { minimumFractionDigits: digits, maximumFractionDigits: 8, useGrouping: false } ); 1578} 1579 1580( function( global ) 1581{ 1582 global.getVariableType = function( variable ) 1583 { 1584 // Return a more accurate representation of a variable's type based on the 1585 // passed in [[Class]], when possible. If variable is null, return 'null'. 1586 // If variable is undefined, return 'undefined'. If variable is global (such 1587 // as the window), pass back global, otherwise, pass back the parsed toString 1588 // value from Object.prototype.toString, which gives us a more detailed 1589 // object type [object Array], [object Date], etc. While not a perfect solution 1590 // for every case, this will give us a much more accurate value than 1591 // JavaScript's builtin "typeof" operator. The anonymous wrapper function 1592 // ensures we receive the "global" context for later comparison 1593 1594 if ( variable === null ) return 'null'; // true null 1595 else if ( variable == null ) return 'undefined'; // Undefined variable 1596 else if ( variable === global ) return 'global'; // global object, such as window 1597 else return Object.prototype.toString.call( variable ).match( /\s([a-zA-Z]+)/)[ 1 ].toLowerCase(); 1598 } 1599}( this ) ); 1600// Miva Merchant 1601// 1602// This file and the source codes contained herein are the property of 1603// Miva, Inc. Use of this file is restricted to the specific terms and 1604// conditions in the License Agreement associated with this file. Distribution 1605// of this file or portions of this file for uses not covered by the License 1606// Agreement is not allowed without a written agreement signed by an officer of 1607// Miva, Inc. 1608// 1609// Copyright 1998-2024 Miva, Inc. All rights reserved. 1610// http://www.miva.com 1611// 1612 1613// Misc HTML/JavaScript functions 1614//////////////////////////////////////////////////// 1615 1616function MMProdList_FormElement_Value( element ) 1617{ 1618 var node, type; 1619 1620 if ( element && element.nodeType === 1 ) 1621 { 1622 node = element.nodeName.toLowerCase(); 1623 1624 if ( node == 'textarea' ) 1625 { 1626 return element.value; 1627 } 1628 else if ( node == 'select' ) 1629 { 1630 return ( element.selectedIndex != -1 && element.options[ element.selectedIndex ] ? element.options[ element.selectedIndex ].value : '' ); 1631 } 1632 else if ( node == 'input' ) 1633 { 1634 type = element.type.toLowerCase(); 1635 1636 if ( type == 'text' || type == 'hidden' ) 1637 { 1638 return element.value; 1639 } 1640 else if ( type == 'radio' && element.checked ) 1641 { 1642 return element.value; 1643 } 1644 else if ( type == 'checkbox' ) 1645 { 1646 return element.checked ? element.value : ''; 1647 } 1648 } 1649 } 1650 1651 return ''; 1652} 1653 1654function MMProdList_AddNestedFacetValue( element, code, value, submit_delay ) 1655{ 1656 var form, entry; 1657 1658 if ( element.form ) form = element.form; 1659 else if ( !( form = getNearestElementAncestorNodeTypeOrNull( element, 'FORM' ) ) ) return; 1660 1661 if ( !form.mmprodlist_updatequery_form_data ) 1662 { 1663 form.mmprodlist_updatequery_form_data = new Array(); 1664 } 1665 1666 entry = new Object(); 1667 entry.element = element; 1668 entry.onParametersGenerated = function( form_params_struct, url_params_struct ) 1669 { 1670 if ( form_params_struct[ code ] ) 1671 { 1672 form_params_struct[ code ].values.push( value ); 1673 } 1674 else if ( url_params_struct[ code ] ) 1675 { 1676 url_params_struct[ code ].values.push( value ); 1677 } 1678 else 1679 { 1680 form_params_struct[ code ] = new Object(); 1681 form_params_struct[ code ].name = code; 1682 form_params_struct[ code ].values = new Array(); 1683 form_params_struct[ code ].values.push( value ); 1684 } 1685 }; 1686 1687 form.mmprodlist_updatequery_form_data.push( entry ); 1688 MMProdList_UpdateQuery_SubmitParameters_Timeout( form, submit_delay ); 1689} 1690 1691function MMProdList_RemoveNestedFacetValue( element, code, value, submit_delay ) 1692{ 1693 var form, entry; 1694 1695 if ( element.form ) form = element.form; 1696 else if ( !( form = getNearestElementAncestorNodeTypeOrNull( element, 'FORM' ) ) ) return; 1697 1698 if ( !form.mmprodlist_updatequery_form_data ) 1699 { 1700 form.mmprodlist_updatequery_form_data = new Array(); 1701 } 1702 1703 entry = new Object(); 1704 entry.element = element; 1705 entry.onParametersGenerated = function( form_params_struct, url_params_struct ) 1706 { 1707 var i, i_len; 1708 1709 if ( form_params_struct[ code ] ) 1710 { 1711 for ( i = 0, i_len = form_params_struct[ code ].values.length; i < i_len; i++ ) 1712 { 1713 if ( form_params_struct[ code ].values[ i ] == value ) 1714 { 1715 form_params_struct[ code ].values.splice( i, form_params_struct[ code ].values.length - i ); 1716 1717 if ( form_params_struct[ code ].values.length == 0 ) 1718 { 1719 if ( form_params_struct[ code + '_reset' ] ) 1720 { 1721 form_params_struct[ code + '_reset' ].values = [ '1' ]; 1722 } 1723 else 1724 { 1725 form_params_struct[ code + '_reset' ] = new Object(); 1726 form_params_struct[ code + '_reset' ].name = code + '_reset'; 1727 form_params_struct[ code + '_reset' ].values = [ '1' ]; 1728 } 1729 } 1730 1731 break; 1732 } 1733 } 1734 } 1735 1736 if ( url_params_struct[ code ] ) 1737 { 1738 for ( i = 0, i_len = url_params_struct[ code ].values.length; i < i_len; i++ ) 1739 { 1740 if ( url_params_struct[ code ].values[ i ] == value ) 1741 { 1742 url_params_struct[ code ].values.splice( i, url_params_struct[ code ].values.length - i ); 1743 1744 if ( url_params_struct[ code ].values.length == 0 ) 1745 { 1746 if ( url_params_struct[ code + '_reset' ] ) 1747 { 1748 url_params_struct[ code + '_reset' ].values = [ '1' ]; 1749 } 1750 else 1751 { 1752 url_params_struct[ code + '_reset' ] = new Object(); 1753 url_params_struct[ code + '_reset' ].name = code + '_reset'; 1754 url_params_struct[ code + '_reset' ].values = [ '1' ]; 1755 } 1756 } 1757 1758 break; 1759 } 1760 } 1761 } 1762 }; 1763 1764 form.mmprodlist_updatequery_form_data.push( entry ); 1765 MMProdList_UpdateQuery_SubmitParameters_Timeout( form, submit_delay ); 1766} 1767 1768function MMProdList_UpdateQuery( element, submit_delay ) 1769{ 1770 var form, entry; 1771 1772 if ( element.form ) form = element.form; 1773 else if ( !( form = getNearestElementAncestorNodeTypeOrNull( element, 'FORM' ) ) ) return; 1774 1775 if ( !form.mmprodlist_updatequery_form_data ) 1776 { 1777 form.mmprodlist_updatequery_form_data = new Array(); 1778 } 1779 1780 entry = new Object(); 1781 entry.element = element; 1782 entry.onParametersGenerated = null; 1783 1784 form.mmprodlist_updatequery_form_data.push( entry ); 1785 MMProdList_UpdateQuery_SubmitParameters_Timeout( form, submit_delay ); 1786} 1787 1788function MMProdList_UpdateQueryBuildParameters( form ) 1789{ 1790 var i, j, name, query, regex, match, value, i_len, j_len, params, member; 1791 var element, url_param, url_params_struct, form_params_struct, merged_params_struct; 1792 1793 params = new Array(); 1794 url_params_struct = new Object(); 1795 form_params_struct = new Object(); 1796 1797 query = window.location.search.substring( 1 ); 1798 regex = /([^=&?]+)=([^&]+)/g; 1799 1800 while ( ( match = regex.exec( query ) ) !== null ) 1801 { 1802 name = CharsetDecodeAttribute( match[ 1 ] ); 1803 value = CharsetDecodeAttribute( match[ 2 ] ); 1804 1805 if ( name == 'Offset' || 1806 name == 'SearchOffset' || 1807 name == 'RelatedOffset' || 1808 name == 'CatListingOffset' || 1809 name == 'AllOffset' ) 1810 {
1811 continue; 1812 } 1813 1814 // Handle single-value inputs that are disabled by excluding them from url_params. Handles rangesliders that 1815 // wouldn't be covered in the code below because the values don't match. 1816 1817 if ( !form.elements[ name ] || ( typeof form.elements[ name ] !== 'object' ) || !form.elements[ name ].disabled ) 1818 { 1819 if ( !url_params_struct[ name ] ) 1820 { 1821 url_params_struct[ name ] = new Object(); 1822 url_params_struct[ name ].name = name; 1823 url_params_struct[ name ].values = new Array(); 1824 } 1825 1826 url_params_struct[ name ].values.push( value ); 1827 } 1828 } 1829 1830 for ( i = 0, i_len = form.elements.length; i < i_len; i++ ) 1831 { 1832 if ( form.elements[ i ].disabled ) 1833 { 1834 // Remove this particular value from the url_params, if it is present, and do 1835 // not add this value to the form_params. 1836 1837 url_param = url_params_struct[ form.elements[ i ].name ]; 1838 if ( url_param ) 1839 { 1840 for ( j = 0, j_len = url_param.values.length; j < j_len; j++ ) 1841 { 1842 if ( url_param.values[ j ] == form.elements[ i ].value ) 1843 { 1844 url_param.values.splice( j, 1 ); 1845 break; 1846 } 1847 } 1848 } 1849 1850 continue; 1851 } 1852 1853 if ( ( typeof form.elements[ i ].name === 'string' ) && form.elements[ i ].name.length ) 1854 { 1855 if ( !form_params_struct[ form.elements[ i ].name ] ) 1856 { 1857 form_params_struct[ form.elements[ i ].name ] = new Object(); 1858 form_params_struct[ form.elements[ i ].name ].name = form.elements[ i ].name; 1859 form_params_struct[ form.elements[ i ].name ].values = new Array(); 1860 } 1861 1862 form_params_struct[ form.elements[ i ].name ].values.push( MMProdList_FormElement_Value( form.elements[ i ] ) ); 1863 } 1864 } 1865 1866 if ( form.mmprodlist_updatequery_form_data ) 1867 { 1868 for ( i = 0, i_len = form.mmprodlist_updatequery_form_data.length; i < i_len; i++ ) 1869 { 1870 element = form.mmprodlist_updatequery_form_data[ i ].element; 1871 1872 if ( !element.disabled && ( typeof element.name === 'string' ) && element.name.length && !form_params_struct[ element.name ] ) 1873 { 1874 form_params_struct[ element.name ] = new Object(); 1875 form_params_struct[ element.name ].name = element.name; 1876 form_params_struct[ element.name ].values = new Array(); 1877 1878 form_params_struct[ element.name ].values.push( MMProdList_FormElement_Value( element ) ); 1879 } 1880 1881 if ( typeof form.mmprodlist_updatequery_form_data[ i ].onParametersGenerated === 'function' ) 1882 { 1883 form.mmprodlist_updatequery_form_data[ i ].onParametersGenerated( form_params_struct, url_params_struct ) 1884 } 1885 } 1886 } 1887 1888 merged_params_struct = url_params_struct; 1889 1890 for ( member in form_params_struct ) 1891 { 1892 if ( form_params_struct.hasOwnProperty( member ) ) 1893 { 1894 merged_params_struct[ member ] = form_params_struct[ member ]; 1895 } 1896 } 1897 1898 for ( member in merged_params_struct ) 1899 { 1900 if ( merged_params_struct.hasOwnProperty( member ) ) 1901 { 1902 params.push( merged_params_struct[ member ] ); 1903 } 1904 } 1905 1906 return params; 1907} 1908 1909function MMProdList_UpdateQuery_SubmitParameters( form, params ) 1910{ 1911 var i, j, i_len, j_len, elements, params_output_array; 1912 1913 if ( window.mmprodlist_updatequery_submitparameters_submitted ) 1914 { 1915 return; 1916 } 1917 1918 window.mmprodlist_updatequery_submitparameters_submitted = true; 1919 params_output_array = new Array(); 1920 1921 params.sort( function( a, b ) { return sortAlphaNumeric( a.name, b.name, true ); } ); 1922 1923 for ( i = 0, i_len = params.length; i < i_len; i++ ) 1924 { 1925 for ( j = 0, j_len = params[ i ].values.length; j < j_len; j++ ) 1926 { 1927 if ( params[ i ].values[ j ].length ) 1928 { 1929 params_output_array.push( encodeURIComponent( params[ i ].name ) + '=' + encodeURIComponent( params[ i ].values[ j ] ) ); 1930 } 1931 } 1932 } 1933 1934 if ( window.mmprodlist_updatequery_submitparameters_timeout ) 1935 { 1936 clearTimeout( window.mmprodlist_updatequery_submitparameters_timeout ); 1937 delete window.mmprodlist_updatequery_submitparameters_timeout; 1938 } 1939 1940 if ( window.mmprodlist_updatequery_submitparameters_timeout_event_attached ) 1941 { 1942 elements = form.getElementsByTagName( '*' ); 1943 1944 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1945 { 1946 RemoveEvent( elements[ i ], 'mousedown', window.mmprodlist_updatequery_submitparameters_timeout_event_function ); 1947 RemoveEvent( elements[ i ], 'mousemove', window.mmprodlist_updatequery_submitparameters_timeout_event_function ); 1948 RemoveEvent( elements[ i ], 'mouseup', window.mmprodlist_updatequery_submitparameters_timeout_event_function ); 1949 } 1950 } 1951 1952 window.location.href = [ window.location.protocol, '//', window.location.host, window.location.pathname ].join( '' ) + ( params_output_array.length ? ( '?' + params_output_array.join( '&' ) ) : '' ); 1953} 1954 1955// Overridable: If different timeout functionality is desired, override 1956// the following function "MMProdList_UpdateQuery_SubmitParameters_Timeout" 1957 1958function MMProdList_UpdateQuery_SubmitParameters_Timeout( form, submit_delay ) 1959{ 1960 var i, i_len, elements; 1961
1962 submit_delay = stoi_def_nonneg( submit_delay, 0 ) 1963 1964 if ( window.mmprodlist_updatequery_submitparameters_timeout ) 1965 { 1966 clearTimeout( window.mmprodlist_updatequery_submitparameters_timeout ); 1967 delete window.mmprodlist_updatequery_submitparameters_timeout; 1968 } 1969 1970 if ( submit_delay === 0 ) 1971 { 1972 return MMProdList_UpdateQuery_SubmitParameters_LowLevel( form ); 1973 } 1974 1975 window.mmprodlist_updatequery_submitparameters_timeout = setTimeout( function() { MMProdList_UpdateQuery_SubmitParameters_LowLevel( form ); }, submit_delay ); 1976 1977 if ( !window.mmprodlist_updatequery_submitparameters_timeout_event_attached ) 1978 { 1979 window.mmprodlist_updatequery_submitparameters_timeout_event_attached = true; 1980 window.mmprodlist_updatequery_submitparameters_timeout_event_function = function( event ) { MMProdList_UpdateQuery_SubmitParameters_Timeout( form, submit_delay ); }; 1981 1982 elements = form.getElementsByTagName( '*' ); 1983 1984 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1985 { 1986 AddEvent( elements[ i ], 'mousedown', window.mmprodlist_updatequery_submitparameters_timeout_event_function ); 1987 AddEvent( elements[ i ], 'mousemove', window.mmprodlist_updatequery_submitparameters_timeout_event_function ); 1988 AddEvent( elements[ i ], 'mouseup', window.mmprodlist_updatequery_submitparameters_timeout_event_function ); 1989 } 1990 } 1991} 1992 1993function MMProdList_UpdateQuery_SubmitParameters_LowLevel( form ) 1994{ 1995 var params = MMProdList_UpdateQueryBuildParameters( form ); 1996 1997 MMProdList_UpdateQuery_Notify_Updating( form ); 1998 MMProdList_UpdateQuery_SubmitParameters( form, params ); 1999 MMProdList_UpdateQuery_Notify_Updated( form ); 2000} 2001 2002// Overridable: If different notification functionality is desired, override 2003// the following function "MMProdList_UpdateQuery_Notify_Updating" 2004 2005function MMProdList_UpdateQuery_Notify_Updating( form ) 2006{ 2007 var i, i_len; 2008 2009 /** 2010 * Disable all inputs while keeping track of what is already disabled 2011 */ 2012 2013 for ( i = 0, i_len = form.elements.length; i < i_len; i++ ) 2014 { 2015 form.elements[ i ].mm_original_disabled = form.elements[ i ].disabled; 2016 form.elements[ i ].setAttribute( 'disabled', 'disabled' ); 2017 } 2018} 2019 2020// Overridable: If different updated functionality is desired, override 2021// the following function "MMProdList_UpdateQuery_Notify_Updated" 2022 2023function MMProdList_UpdateQuery_Notify_Updated( form ) 2024{ 2025 var i, i_len; 2026 2027 /** 2028 * Enable any inputs which were not already disabled and setup the form for resubmission 2029 */ 2030 2031 for ( i = 0, i_len = form.elements.length; i < i_len; i++ ) 2032 { 2033 if ( form.elements[ i ].hasOwnProperty( 'mm_original_disabled' ) ) 2034 { 2035 if ( !form.elements[ i ].mm_original_disabled ) 2036 { 2037 form.elements[ i ].removeAttribute( 'disabled' ); 2038 } 2039 2040 delete form.elements[ i ].mm_original_disabled; 2041 } 2042 } 2043 2044 window.mmprodlist_updatequery_submitparameters_submitted = false; 2045} 2046 2047function MMFacet_RangeSlider_Initialize() 2048{ 2049 var i, name, i_len, module_code, facet_code, elementlist, range_low, range_high, allow_value_input, selected_range_low, selected_range_high; 2050 2051 elementlist = document.querySelectorAll( '[data-mm-facet-rangeslider-name]' ); 2052 2053 for ( i = 0, i_len = elementlist.length; i < i_len; i++ ) 2054 { 2055 module_code = elementlist[ i ].getAttribute( 'data-mm-facet-module-code' ); 2056 facet_code = elementlist[ i ].getAttribute( 'data-mm-facet-code' ); 2057 name = elementlist[ i ].getAttribute( 'data-mm-facet-rangeslider-name' ); 2058 range_low = stod_def( elementlist[ i ].getAttribute( 'data-mm-facet-rangeslider-range-low' ), 0 ); 2059 range_high = stod_def( elementlist[ i ].getAttribute( 'data-mm-facet-rangeslider-range-high' ), 0 ); 2060 selected_range_low = stod_def( elementlist[ i ].getAttribute( 'data-mm-facet-rangeslider-selected-range-low' ), 0 ); 2061 selected_range_high = stod_def( elementlist[ i ].getAttribute( 'data-mm-facet-rangeslider-selected-range-high' ), range_high ); 2062 2063 if ( elementlist[ i ].hasAttribute( 'data-mm-facet-rangeslider-allow-value-input' ) ) allow_value_input = elementlist[ i ].getAttribute( 'data-mm-facet-rangeslider-allow-value-input' ).toLowerCase(); 2064 else allow_value_input = 'No'; 2065 2066 elementlist[ i ].mm_facet_rangeslider = new MMFacet_RangeSlider( elementlist[ i ], module_code, facet_code, name, range_low, range_high, selected_range_low, selected_range_high, allow_value_input === 'yes' || allow_value_input === '1' || allow_value_input === 'true' ); 2067 } 2068} 2069 2070// MMFacet_RangeSlider 2071//////////////////////////////////////////////////// 2072 2073function MMFacet_RangeSlider( element_parent, module_code, facet_code, name, range_low, range_high, selected_range_low, selected_range_high, allow_value_input ) 2074{ 2075 var self = this; 2076 2077 this.element_parent = element_parent; 2078 this.module_code = module_code; 2079 this.facet_code = facet_code;
2080 this.name = name; 2081 this.range_low = range_low; 2082 this.range_high = range_high; 2083 this.range_span = range_high - range_low; 2084 this.selected_range_low = selected_range_low; 2085 this.selected_range_high = selected_range_high; 2086 this.allow_value_input = allow_value_input; 2087 2088 this.shouldrender = false; 2089 this.slider_position_low = 0; 2090 this.slider_position_high = 0; 2091 this.original_value = this.selected_range_low + '-' + this.selected_range_high; 2092 2093 this.element_parent.innerHTML = ''; 2094 2095 this.element_value = newElement( 'input', { 'type': 'hidden', 'name': name }, null, this.element_parent ); 2096 this.element_input_container_low = newElement( 'span', { 'class': 'mm_facet_rangeslider_input_container_low' }, null, this.element_parent ); 2097 this.element_track_container = newElement( 'span', { 'class': 'mm_facet_rangeslider_track_container' }, null, this.element_parent ); 2098 this.element_track = newElement( 'span', { 'class': 'mm_facet_rangeslider_track' }, null, this.element_track_container ); 2099 this.element_track_background = newElement( 'span', { 'class': 'mm_facet_rangeslider_track_background' }, null, this.element_track ); 2100 this.element_track_selection = newElement( 'span', { 'class': 'mm_facet_rangeslider_track_selection' }, null, this.element_track ); 2101 this.element_track_handle_low = newElement( 'span', { 'class': 'mm_facet_rangeslider_track_handle_low' }, null, this.element_track ); 2102 this.element_track_handle_high = newElement( 'span', { 'class': 'mm_facet_rangeslider_track_handle_high' }, null, this.element_track ); 2103 this.element_input_container_high = newElement( 'span', { 'class': 'mm_facet_rangeslider_input_container_high' }, null, this.element_parent ); 2104 2105 if ( !this.allow_value_input ) 2106 { 2107 this.element_label_low = newElement( 'span', { 'class': 'mm_facet_rangeslider_input' }, null, this.element_input_container_low ); 2108 this.element_label_high = newElement( 'span', { 'class': 'mm_facet_rangeslider_input' }, null, this.element_input_container_high ); 2109 } 2110 else 2111 { 2112 this.element_input_low = newElement( 'input', { 'type': 'text', 'class': 'mm_facet_rangeslider_input' }, null, this.element_input_container_low ); 2113 this.element_input_high = newElement( 'input', { 'type': 'text', 'class': 'mm_facet_rangeslider_input' }, null, this.element_input_container_high ); 2114 2115 this.event_keydown_input = function( event ) { return self.Event_KeyDown_Input( event ? event : window.event ); }; 2116 this.event_focus_input_low = function( event ) { return self.Event_Focus_Input_Low( event ? event : window.event ); }; 2117 this.event_blur_input_low = function( event ) { return self.Event_Blur_Input_Low( event ? event : window.event ); }; 2118 this.event_focus_input_high = function( event ) { return self.Event_Focus_Input_High( event ? event : window.event ); }; 2119 this.event_blur_input_high = function( event ) { return self.Event_Blur_Input_High( event ? event : window.event ); }; 2120 this.event_click_input_container_low = function( event ) { return self.Event_Click_Input_Container_Low( event ? event : window.event ); }; 2121 this.event_click_input_container_high = function( event ) { return self.Event_Click_Input_Container_High( event ? event : window.event ); }; 2122 2123 AddEvent( this.element_input_low, 'keydown', this.event_keydown_input ); 2124 AddEvent( this.element_input_low, 'focus', this.event_focus_input_low ); 2125 AddEvent( this.element_input_low, 'blur', this.event_blur_input_low ); 2126 AddEvent( this.element_input_high, 'keydown', this.event_keydown_input ); 2127 AddEvent( this.element_input_high, 'focus', this.event_focus_input_high ); 2128 AddEvent( this.element_input_high, 'blur', this.event_blur_input_high ); 2129 AddEvent( this.element_input_container_low, 'click', this.event_click_input_container_low ); 2130 AddEvent( this.element_input_container_high, 'click', this.event_click_input_container_high ); 2131 } 2132 2133 this.event_render = function() { self.Render(); }; 2134 this.event_returnfalse = function() { return false; }; 2135 2136 this.event_mousedown_handle_low = function( event ) { return self.Event_MouseDown_Handle_Low( event ? event : window.event ); }; 2137 this.event_mousedown_handle_high = function( event ) { return self.Event_MouseDown_Handle_High( event ? event : window.event ); }; 2138 this.event_mousemove_handle_low = function( event ) { return self.Event_MouseMove_Handle_Low( event ? event : window.event ); }; 2139 this.event_mousemove_handle_high = function( event ) { return self.Event_MouseMove_Handle_High( event ? event : window.event ); }; 2140 this.event_mouseup_handle_low = function( event ) { return self.Event_MouseUp_Handle_Low( event ? event : window.event ); }; 2141 this.event_mouseup_handle_high = function( event ) { return self.Event_MouseUp_Handle_High( event ? event : window.event ); }; 2142 2143 this.event_touchstart_handle_low = function( event ) { return self.Event_TouchStart_Handle_Low( event ? event : window.event ); }; 2144 this.event_touchstart_handle_high = function( event ) { return self.Event_TouchStart_Handle_High( event ? event : window.event ); }; 2145 this.event_touchmove_handle_low = function( event ) { return self.Event_TouchMove_Handle_Low( event ? event : window.event ); }; 2146 this.event_touchmove_handle_high = function( event ) { return self.Event_TouchMove_Handle_High( event ? event : window.event ); }; 2147 this.event_touchend_handle_low = function( event ) { return self.Event_TouchEnd_Handle_Low( event ? event : window.event ); }; 2148 this.event_touchend_handle_high = function( event ) { return self.Event_TouchEnd_Handle_High( event ? event : window.event ); }; 2149 2150 AddEvent( this.element_track_handle_low, 'mousedown', this.event_mousedown_handle_low ); 2151 AddEvent( this.element_track_handle_high, 'mousedown', this.event_mousedown_handle_high ); 2152 2153 AddEvent( this.element_track_handle_low, 'touchstart', this.event_touchstart_handle_low ); 2154 AddEvent( this.element_track_handle_high, 'touchstart', this.event_touchstart_handle_high ); 2155 2156 this.SetSelectedRange( this.selected_range_low, this.selected_range_high ); 2157 this.RequestRender(); 2158} 2159 2160MMFacet_RangeSlider.prototype.FormatValues = function( low, high ) 2161{ 2162 var value_low, value_high, slider_rect, handle_rect, slider_length, available_handle_length; 2163 2164 slider_rect = this.element_track.getBoundingClientRect(); 2165 handle_rect = this.element_track_handle_low.getBoundingClientRect(); 2166 slider_length = ( slider_rect.right - slider_rect.left ); 2167 available_handle_length = slider_length - ( handle_rect.right - handle_rect.left + 2 ); 2168 2169 value_low = stoi_def( Math.round( this.range_low + stod_def( stod_range( ( ( low / available_handle_length ) * slider_length ) / slider_length, 0, 1 ) * this.range_span, 0 ) ), 0 ); 2170 value_high = stoi_def( Math.round( this.range_low + stod_def( stod_range( ( ( high / available_handle_length ) * slider_length ) / slider_length, 0, 1 ) * this.range_span, 0 ) ), 0 ); 2171 2172 this.FormatValues_LowLevel( value_low, value_high ); 2173} 2174 2175MMFacet_RangeSlider.prototype.FormatValues_LowLevel = function( value_low, value_high ) 2176{ 2177 var tmp_low; 2178 2179 if ( value_low > value_high ) 2180 { 2181 tmp_low = value_low; 2182 value_low = value_high; 2183 value_high = tmp_low; 2184 } 2185 2186 this.element_value.value = value_low + '-' + value_high; 2187 this.element_value.disabled = ( value_low == this.range_low && value_high == this.range_high ) ? true : false;
2188 2189 if ( this.allow_value_input ) 2190 { 2191 this.element_input_low.value = MMFacet_RangeSlider_FormatValue( this.module_code, this.facet_code, value_low ); 2192 this.element_input_high.value = MMFacet_RangeSlider_FormatValue( this.module_code, this.facet_code, value_high ); 2193 } 2194 else 2195 { 2196 this.element_label_low.innerHTML = MMFacet_RangeSlider_FormatValue( this.module_code, this.facet_code, value_low ); 2197 this.element_label_high.innerHTML = MMFacet_RangeSlider_FormatValue( this.module_code, this.facet_code, value_high ); 2198 } 2199} 2200 2201MMFacet_RangeSlider.prototype.SetSelectedRange = function( low, high ) 2202{ 2203 var slider_rect, handle_rect, slider_length, available_handle_length; 2204 2205 slider_rect = this.element_track.getBoundingClientRect(); 2206 handle_rect = this.element_track_handle_low.getBoundingClientRect(); 2207 slider_length = ( slider_rect.right - slider_rect.left ); 2208 available_handle_length = slider_length - ( handle_rect.right - handle_rect.left + 2 ); 2209 2210 this.slider_position_low = stod_def( ( ( ( ( low - this.range_low ) / this.range_span ) * slider_length ) / slider_length ) * available_handle_length, 0 ); 2211 this.slider_position_high = stod_def( ( ( ( ( high - this.range_low ) / this.range_span ) * slider_length ) / slider_length ) * available_handle_length, 0 ); 2212 2213 this.FormatValues_LowLevel( low, high ); 2214} 2215 2216MMFacet_RangeSlider.prototype.Event_Click_Input_Container_Low = function( e ) 2217{ 2218 var rect, mousepos, scrollfromtop, scrollfromleft; 2219 2220 rect = this.element_input_low.getBoundingClientRect(); 2221 mousepos = captureMousePosition( e ); 2222 scrollfromtop = getScrollTop(); 2223 scrollfromleft = getScrollLeft(); 2224 2225 if ( mousepos.y < ( rect.top + scrollfromtop ) || 2226 mousepos.y > ( rect.top + ( rect.bottom - rect.top ) + scrollfromtop ) || 2227 mousepos.x < ( rect.left + scrollfromleft ) || 2228 mousepos.x > ( rect.left + ( rect.right - rect.left ) + scrollfromleft ) ) 2229 { 2230 this.element_input_low.focus(); 2231 } 2232} 2233 2234MMFacet_RangeSlider.prototype.Event_Click_Input_Container_High = function( e ) 2235{ 2236 var rect, mousepos, scrollfromtop, scrollfromleft; 2237 2238 rect = this.element_input_high.getBoundingClientRect(); 2239 mousepos = captureMousePosition( e ); 2240 scrollfromtop = getScrollTop(); 2241 scrollfromleft = getScrollLeft(); 2242 2243 if ( mousepos.y < ( rect.top + scrollfromtop ) || 2244 mousepos.y > ( rect.top + ( rect.bottom - rect.top ) + scrollfromtop ) || 2245 mousepos.x < ( rect.left + scrollfromleft ) || 2246 mousepos.x > ( rect.left + ( rect.right - rect.left ) + scrollfromleft ) ) 2247 { 2248 this.element_input_high.focus(); 2249 } 2250} 2251 2252MMFacet_RangeSlider.prototype.Event_Focus_Input_Low = function( e ) 2253{ 2254 this.element_input_container_low.className = classNameAdd( this.element_input_container_low, 'mm_facet_rangeslider_input_active' ); 2255} 2256 2257MMFacet_RangeSlider.prototype.Event_Blur_Input_Low = function( e ) 2258{ 2259 this.element_input_container_low.className = classNameRemove( this.element_input_container_low, 'mm_facet_rangeslider_input_active' ); 2260 this.SetSelectedRange( stod_def( this.element_input_low.value.replace( /[^\d.-]/g, '' ), 0 ), stod_def( this.element_input_high.value.replace( /[^\d.-]/g, '' ), 0 ) ); 2261 this.RequestRender(); 2262 this.Submit(); 2263} 2264 2265MMFacet_RangeSlider.prototype.Event_Focus_Input_High = function( e ) 2266{ 2267 this.element_input_container_high.className = classNameAdd( this.element_input_container_high, 'mm_facet_rangeslider_input_active' ); 2268} 2269 2270MMFacet_RangeSlider.prototype.Event_Blur_Input_High = function( e ) 2271{ 2272 this.element_input_container_high.className = classNameRemove( this.element_input_container_high, 'mm_facet_rangeslider_input_active' ); 2273 this.SetSelectedRange( stod_def( this.element_input_low.value.replace( /[^\d.-]/g, '' ), 0 ), stod_def( this.element_input_high.value.replace( /[^\d.-]/g, '' ), 0 ) ); 2274 this.RequestRender(); 2275 this.Submit(); 2276} 2277 2278MMFacet_RangeSlider.prototype.Event_KeyDown_Input = function( e ) 2279{ 2280 var keycode = e.keyCode || e.which; 2281 2282 if ( keycode == 13 ) 2283 { 2284 this.SetSelectedRange( stod_def( this.element_input_low.value.replace( /[^\d.-]/g, '' ), 0 ), stod_def( this.element_input_high.value.replace( /[^\d.-]/g, '' ), 0 ) ); 2285 this.RequestRender(); 2286 this.Submit(); 2287 } 2288 2289 return true; 2290} 2291 2292MMFacet_RangeSlider.prototype.Event_MouseDown_Handle_Low = function( e ) 2293{ 2294 var mousepos; 2295 2296 AddEvent( window, 'mousemove', this.event_mousemove_handle_low ); 2297 AddEvent( window, 'mouseup', this.event_mouseup_handle_low ); 2298 AddEvent( window, 'blur', this.event_mouseup_handle_low ); 2299 2300 mousepos = captureMousePosition( e ); 2301 this.slider_started = true; 2302 this.slider_target = e.target ? e.target : e.srcElement; 2303 this.slider_startpos_low = mousepos.x; 2304 this.slider_originalposition_low = this.element_track_handle_low.getBoundingClientRect().left - this.element_track.getBoundingClientRect().left; 2305 2306 clearTextSelection(); 2307 document.body.focus(); 2308 document.body.unselectable = 'on'; 2309 document.onselectstart = this.event_returnfalse; 2310 this.slider_target.ondragstart = this.event_returnfalse; 2311 2312 if ( this.slider_target.setCapture ) 2313 { 2314 this.slider_target.setCapture(); 2315 } 2316 2317 eventStopPropagation( e ); 2318 return eventPreventDefault( e ); 2319} 2320 2321MMFacet_RangeSlider.prototype.Event_MouseMove_Handle_Low = function( e ) 2322{ 2323 var mousepos, slider_rect, handle_rect, slider_length, available_handle_length; 2324 2325 if ( this.slider_started ) 2326 { 2327 eventPreventDefault( e ); 2328 this.slider_started = false;
2329 } 2330 2331 mousepos = captureMousePosition( e ); 2332 slider_rect = this.element_track.getBoundingClientRect(); 2333 handle_rect = this.element_track_handle_low.getBoundingClientRect(); 2334 slider_length = ( slider_rect.right - slider_rect.left ); 2335 available_handle_length = slider_length - ( handle_rect.right - handle_rect.left + 2 ); 2336 this.slider_position_low = stod_range( this.slider_originalposition_low + ( mousepos.x - this.slider_startpos_low ), 0, available_handle_length ); 2337 2338 clearTextSelection(); 2339 this.RequestRender(); 2340 2341 eventStopPropagation( e ); 2342 return eventPreventDefault( e ); 2343} 2344 2345MMFacet_RangeSlider.prototype.Event_MouseUp_Handle_Low = function( e ) 2346{ 2347 RemoveEvent( window, 'mousemove', this.event_mousemove_handle_low ); 2348 RemoveEvent( window, 'mouseup', this.event_mouseup_handle_low ); 2349 RemoveEvent( window, 'blur', this.event_mouseup_handle_low ); 2350 2351 this.slider_started = false; 2352 document.body.unselectable = null; 2353 document.onselectstart = null; 2354 this.slider_target.ondragstart = null; 2355 2356 if ( this.slider_target.releaseCapture ) 2357 { 2358 this.slider_target.releaseCapture(); 2359 } 2360 2361 this.RequestRender(); 2362 this.Submit(); 2363 2364 eventStopPropagation( e ); 2365 return eventPreventDefault( e ); 2366} 2367 2368MMFacet_RangeSlider.prototype.Event_MouseDown_Handle_High = function( e ) 2369{ 2370 var mousepos; 2371 2372 AddEvent( window, 'mousemove', this.event_mousemove_handle_high ); 2373 AddEvent( window, 'mouseup', this.event_mouseup_handle_high ); 2374 AddEvent( window, 'blur', this.event_mouseup_handle_high ); 2375 2376 mousepos = captureMousePosition( e ); 2377 this.slider_started = true; 2378 this.slider_target = e.target ? e.target : e.srcElement; 2379 this.slider_startpos_high = mousepos.x; 2380 this.slider_originalposition_high = this.element_track_handle_high.getBoundingClientRect().left - this.element_track.getBoundingClientRect().left; 2381 2382 clearTextSelection(); 2383 document.body.focus(); 2384 document.body.unselectable = 'on'; 2385 document.onselectstart = this.event_returnfalse; 2386 this.slider_target.ondragstart = this.event_returnfalse; 2387 2388 if ( this.slider_target.setCapture ) 2389 { 2390 this.slider_target.setCapture(); 2391 } 2392 2393 eventStopPropagation( e ); 2394 return eventPreventDefault( e ); 2395} 2396 2397MMFacet_RangeSlider.prototype.Event_MouseMove_Handle_High = function( e ) 2398{ 2399 var mousepos, slider_rect, handle_rect, slider_length, available_handle_length; 2400 2401 if ( this.slider_started ) 2402 { 2403 eventPreventDefault( e ); 2404 this.slider_started = false; 2405 } 2406 2407 mousepos = captureMousePosition( e ); 2408 slider_rect = this.element_track.getBoundingClientRect(); 2409 handle_rect = this.element_track_handle_high.getBoundingClientRect(); 2410 slider_length = ( slider_rect.right - slider_rect.left ); 2411 available_handle_length = slider_length - ( handle_rect.right - handle_rect.left + 2 ); 2412 this.slider_position_high = stod_range( this.slider_originalposition_high + ( mousepos.x - this.slider_startpos_high ), 0, available_handle_length ); 2413 2414 clearTextSelection(); 2415 this.RequestRender(); 2416 2417 eventStopPropagation( e ); 2418 return eventPreventDefault( e ); 2419} 2420 2421MMFacet_RangeSlider.prototype.Event_MouseUp_Handle_High = function( e ) 2422{ 2423 RemoveEvent( window, 'mousemove', this.event_mousemove_handle_high ); 2424 RemoveEvent( window, 'mouseup', this.event_mouseup_handle_high ); 2425 RemoveEvent( window, 'blur', this.event_mouseup_handle_high ); 2426 2427 this.slider_started = false; 2428 document.body.unselectable = null; 2429 document.onselectstart = null; 2430 this.slider_target.ondragstart = null; 2431 2432 if ( this.slider_target.releaseCapture ) 2433 { 2434 this.slider_target.releaseCapture(); 2435 } 2436 2437 this.RequestRender(); 2438 this.Submit(); 2439 2440 eventStopPropagation( e ); 2441 return eventPreventDefault( e ); 2442} 2443 2444MMFacet_RangeSlider.prototype.Event_TouchStart_Handle_Low = function( e ) 2445{ 2446 if ( e.touches && e.touches.length > 1 ) 2447 { 2448 if ( this.touchevents_applied ) 2449 { 2450 RemoveEvent( this.touch_target, 'touchmove', this.event_touchmove_handle_low ); 2451 RemoveEvent( this.touch_target, 'touchend', this.event_touchend_handle_low ); 2452 RemoveEvent( this.touch_target, 'touchcancel', this.event_touchend_handle_low ); 2453 2454 this.touchevents_applied = false; 2455 } 2456 2457 return; 2458 } 2459 2460 this.touches = e.touches; 2461 this.touch_target = e.target; 2462 2463 this.slider_started = true; 2464 this.slider_startpos_low = this.touches[ 0 ].pageX; 2465 this.slider_originalposition_low = this.element_track_handle_low.getBoundingClientRect().left - this.element_track.getBoundingClientRect().left; 2466 2467 if ( !this.touchevents_applied ) 2468 { 2469 this.touchevents_applied = true; 2470 2471 AddEvent( e.target, 'touchmove', this.event_touchmove_handle_low ); 2472 AddEvent( e.target, 'touchend', this.event_touchend_handle_low ); 2473 AddEvent( e.target, 'touchcancel', this.event_touchend_handle_low ); 2474 } 2475 2476 eventStopPropagation( e ); 2477 return eventPreventDefault( e ); 2478} 2479 2480MMFacet_RangeSlider.prototype.Event_TouchMove_Handle_Low = function( e ) 2481{ 2482 var slider_rect, handle_rect, slider_length, available_handle_length; 2483 2484 if ( this.slider_started ) 2485 { 2486 eventPreventDefault( e ); 2487 this.slider_started = false;
2488 } 2489 2490 this.touches = e.touches; 2491 2492 slider_rect = this.element_track.getBoundingClientRect(); 2493 handle_rect = this.element_track_handle_low.getBoundingClientRect(); 2494 slider_length = ( slider_rect.right - slider_rect.left ); 2495 available_handle_length = slider_length - ( handle_rect.right - handle_rect.left + 2 ); 2496 this.slider_position_low = stod_range( this.slider_originalposition_low + ( this.touches[ 0 ].pageX - this.slider_startpos_low ), 0, available_handle_length ); 2497 2498 this.RequestRender(); 2499} 2500 2501MMFacet_RangeSlider.prototype.Event_TouchEnd_Handle_Low = function( e ) 2502{ 2503 RemoveEvent( this.touch_target, 'touchmove', this.event_touchmove_handle_low ); 2504 RemoveEvent( this.touch_target, 'touchend', this.event_touchend_handle_low ); 2505 RemoveEvent( this.touch_target, 'touchcancel', this.event_touchend_handle_low ); 2506 2507 this.touchevents_applied = false; 2508 this.slider_started = false; 2509 2510 this.RequestRender(); 2511 this.Submit(); 2512 2513 eventStopPropagation( e ); 2514 return eventPreventDefault( e ); 2515} 2516 2517MMFacet_RangeSlider.prototype.Event_TouchStart_Handle_High = function( e ) 2518{ 2519 if ( e.touches && e.touches.length > 1 ) 2520 { 2521 if ( this.touchevents_applied ) 2522 { 2523 RemoveEvent( this.touch_target, 'touchmove', this.event_touchmove_handle_high ); 2524 RemoveEvent( this.touch_target, 'touchend', this.event_touchend_handle_high ); 2525 RemoveEvent( this.touch_target, 'touchcancel', this.event_touchend_handle_high ); 2526 2527 this.touchevents_applied = false; 2528 } 2529 2530 return; 2531 } 2532 2533 this.touches = e.touches; 2534 this.touch_target = e.target; 2535 2536 this.slider_started = true; 2537 this.slider_startpos_high = this.touches[ 0 ].pageX; 2538 this.slider_originalposition_high = this.element_track_handle_high.getBoundingClientRect().left - this.element_track.getBoundingClientRect().left; 2539 2540 if ( !this.touchevents_applied ) 2541 { 2542 this.touchevents_applied = true; 2543 2544 AddEvent( e.target, 'touchmove', this.event_touchmove_handle_high ); 2545 AddEvent( e.target, 'touchend', this.event_touchend_handle_high ); 2546 AddEvent( e.target, 'touchcancel', this.event_touchend_handle_high ); 2547 } 2548 2549 eventStopPropagation( e ); 2550 return eventPreventDefault( e ); 2551} 2552 2553MMFacet_RangeSlider.prototype.Event_TouchMove_Handle_High = function( e ) 2554{ 2555 var slider_rect, handle_rect, slider_length, available_handle_length; 2556 2557 if ( this.slider_started ) 2558 { 2559 eventPreventDefault( e ); 2560 this.slider_started = false; 2561 } 2562 2563 this.touches = e.touches; 2564 2565 slider_rect = this.element_track.getBoundingClientRect(); 2566 handle_rect = this.element_track_handle_high.getBoundingClientRect(); 2567 slider_length = ( slider_rect.right - slider_rect.left ); 2568 available_handle_length = slider_length - ( handle_rect.right - handle_rect.left + 2 ); 2569 this.slider_position_high = stod_range( this.slider_originalposition_high + ( this.touches[ 0 ].pageX - this.slider_startpos_high ), 0, available_handle_length ); 2570 2571 this.RequestRender(); 2572} 2573 2574MMFacet_RangeSlider.prototype.Event_TouchEnd_Handle_High = function( e ) 2575{ 2576 RemoveEvent( this.touch_target, 'touchmove', this.event_touchmove_handle_high ); 2577 RemoveEvent( this.touch_target, 'touchend', this.event_touchend_handle_high ); 2578 RemoveEvent( this.touch_target, 'touchcancel', this.event_touchend_handle_high ); 2579 2580 this.touchevents_applied = false; 2581 this.slider_started = false; 2582 2583 this.RequestRender(); 2584 this.Submit(); 2585 2586 eventStopPropagation( e ); 2587 return eventPreventDefault( e ); 2588} 2589 2590MMFacet_RangeSlider.prototype.Submit = function() 2591{ 2592 if ( this.original_value !== this.element_value.value ) 2593 { 2594 MMProdList_UpdateQuery( this.element_value ); 2595 } 2596} 2597 2598// Rendering 2599 2600MMFacet_RangeSlider.prototype.RequestRender = function() 2601{ 2602 if ( !this.shouldrender ) 2603 { 2604 this.shouldrender = true; 2605 window.requestAnimationFrame( this.event_render ); 2606 } 2607} 2608 2609MMFacet_RangeSlider.prototype.Render = function() 2610{ 2611 if ( this.shouldrender ) 2612 { 2613 this.shouldrender = false;
2614 this.Redraw(); 2615 } 2616} 2617 2618MMFacet_RangeSlider.prototype.Redraw = function() 2619{ 2620 var low, high, tmp_low, slider_rect, handle_rect, slider_length, available_handle_length; 2621 2622 slider_rect = this.element_track.getBoundingClientRect(); 2623 handle_rect = this.element_track_handle_high.getBoundingClientRect(); 2624 slider_length = ( slider_rect.right - slider_rect.left ); 2625 available_handle_length = slider_length - ( handle_rect.right - handle_rect.left + 2 ); 2626 2627 this.slider_position_low = stod_range( this.slider_position_low, 0, available_handle_length ); 2628 this.slider_position_high = stod_range( this.slider_position_high, 0, available_handle_length ); 2629 2630 low = this.slider_position_low; 2631 high = this.slider_position_high; 2632 2633 if ( low > high ) 2634 { 2635 tmp_low = low; 2636 low = high; 2637 high = tmp_low; 2638 } 2639 2640 this.element_track_handle_low.style.left = this.slider_position_low + 'px'; 2641 this.element_track_handle_high.style.left = this.slider_position_high + 'px'; 2642 this.element_track_selection.style.left = ( low + ( this.element_track_handle_low.offsetWidth / 2 ) ) + 'px'; 2643 this.element_track_selection.style.right = ( this.element_track.offsetWidth - ( high + ( this.element_track_handle_low.offsetWidth / 2 ) ) ) + 'px'; 2644 2645 this.FormatValues( low, high ); 2646} 2647 2648// Miscellaneous 2649//////////////////////////////////////////////////// 2650 2651function MMDynamic_Form_Submit( action, hidden_input_fields, form_attributes ) 2652{ 2653 var key, form; 2654 2655 form = newElement( 'form', { 'action': action, 'method': 'POST', 'taget': '_self' }, null, null ); 2656 2657 if ( form_attributes && ( typeof form_attributes === 'object' ) ) 2658 { 2659 for ( key in form_attributes ) 2660 { 2661 form.setAttribute( key, form_attributes[ key ] ); 2662 } 2663 } 2664 2665 for ( key in hidden_input_fields ) 2666 { 2667 newElement( 'input', { 'type': 'hidden', 'name': key, 'value': hidden_input_fields[ key ] }, null, form ); 2668 } 2669 2670 document.body.appendChild( form ); 2671 form.submit(); 2672 document.body.removeChild( form ); 2673}
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.