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 14(function( obj, eventType, fn ) 15{ 16 if ( obj.addEventListener ) 17 { 18 obj.addEventListener( eventType, fn, false ); 19 } 20 else if ( obj.attachEvent ) 21 { 22 obj.attachEvent( 'on' + eventType, fn ); 23 } 24})( window, 'load', function() { AttributeMachine_Initialize(); } ); 25 26function AttributeMachine_Initialize() 27{ 28 FireEvent( window, 'attributemachine_override' ); 29 FireEvent( window, 'attributemachine_initialize' ); 30} 31 32function AttributeMachine( product_code, dependency_resolution, inventory_element_id, inv_long, price_element_id, swatch_element_id, invalid_msg, missing_text_msg, missing_radio_msg, attribute_swatch_id ) 33{ 34 this.purchase_disabled = false; 35 36 this.inv_div = null; 37 this.price_div = null; 38 this.additional_price_div = null; 39 this.weight_div = null; 40 this.discount_div = null; 41 this.swatches = null; 42 this.master_attributes = null; 43 this.attributes = null; 44 this.have_inventory_attributes = false; 45 this.purchase_buttons = null; 46 this.buttons = new Array(); 47 this.possible_req = null; 48 49 this.form = null; 50 this.form_action = null; 51 this.element_product_code = null; 52 this.element_product_quantity = null; 53 this.elementlist_product_attributes = new Array(); 54 this.elementlist_product_subscription = new Array(); 55 56 /* 57 * Provide backwards compatibility with old parameters 58 */ 59 60 if ( typeof product_code === 'object' ) 61 { 62 this.settings = product_code; 63 64 if ( typeof this.settings.getElementById === 'function' ) this.getElementById = this.settings.getElementById; 65 if ( typeof this.settings.getElementsByTagName === 'function' ) this.getElementsByTagName = this.settings.getElementsByTagName; 66 } 67 else 68 { 69 this.settings = new Object(); 70 this.settings.product_code = product_code; 71 this.settings.dependency_resolution = dependency_resolution; 72 this.settings.inventory_element_id = inventory_element_id; 73 this.settings.inv_long = inv_long; 74 this.settings.price_element_id = price_element_id; 75 this.settings.swatch_element_id = swatch_element_id; 76 this.settings.attribute_swatch_id = attribute_swatch_id; 77 this.settings.invalid_msg = invalid_msg ? invalid_msg : ''; 78 this.settings.missing_text_msg = missing_text_msg ? missing_text_msg : ''; 79 this.settings.missing_radio_msg = missing_radio_msg ? missing_radio_msg : ''; 80 } 81 82 if ( this.settings.inventory_element_id ) this.inv_div = this.getElementById( this.settings.inventory_element_id ); 83 if ( this.settings.price_element_id ) this.price_div = this.getElementById( this.settings.price_element_id ); 84 if ( this.settings.additional_price_element_id ) this.additional_price_div = this.getElementById( this.settings.additional_price_element_id ); 85 if ( this.settings.weight_element_id ) this.weight_div = this.getElementById( this.settings.weight_element_id ); 86 if ( this.settings.discount_element_id ) this.discount_div = this.getElementById( this.settings.discount_element_id ); 87 if ( this.settings.swatch_element_id ) this.swatches = this.getElementById( this.settings.swatch_element_id ); 88 89 if ( this.price_div ) this.initial_price_value = this.price_div.innerHTML; 90 if ( this.additional_price_div ) this.initial_additional_price_value = this.additional_price_div.innerHTML; 91 if ( this.weight_div ) this.initial_weight_value = this.weight_div.innerHTML; 92 if ( this.discount_div ) this.initial_discount_value = this.discount_div.innerHTML; 93} 94 95AttributeMachine.prototype.Initialize = function( attributes, possible ) 96{ 97 var self = this; 98 99 if ( attributes ) return this.AttributeAndOptionList_Load_Callback( attributes, possible ); 100 else Runtime_AttributeAndOptionList_Load_Product( this.settings.product_code, function( response ) { self.AttributeAndOptionList_Load_Callback( response, possible ); } ); 101} 102 103AttributeMachine.prototype.Find_Purchase_Buttons = function() 104{ 105 var i, i_len, type, node_name; 106 107 if ( !this.form ) 108 { 109 return; 110 } 111 112 for ( i = 0, i_len = this.form.elements.length; i < i_len; i++ ) 113 { 114 node_name = this.form.elements[ i ].nodeName.toLowerCase(); 115 116 if ( this.form.elements[ i ].hasAttribute( 'type' ) && 117 typeof this.form.elements[ i ].type === 'string' ) type = this.form.elements[ i ].type.toLowerCase(); 118 else if ( node_name === 'button' ) type = 'submit'; // Default type for HTMLButtonElement 119 else if ( node_name === 'input' ) type = 'text'; // Default type for HTMLInputElement 120 else type = null; 121 122 if ( type === 'button' || type === 'submit' ) 123 { 124 // 125 // Button, input, or custom element that wants to be treated as a button 126 // 127 128 this.buttons.push( this.form.elements[ i ] ); 129 } 130 } 131} 132 133AttributeMachine.prototype.Disable_Purchase_Buttons = function() 134{ 135 var i, i_len; 136 137 if ( this.form_action === 'ATWL' || this.form_action == 'AFWL' ) 138 { 139 return; 140 } 141 else if ( this.form_action === 'ADPM' ) 142 { 143 if ( this.Purchase_FormElement_CanEnableDisable( this.element_product_quantity ) ) 144 { 145 this.element_product_quantity.disabled = true; 146 } 147 } 148 else if ( this.form_action === 'AUPM' ) 149 { 150 for ( i = 0, i_len = this.buttons.length; i < i_len; i++ ) 151 { 152 if ( this.Purchase_FormElement_CanEnableDisable( this.buttons[ i ] ) ) 153 { 154 this.Purchase_FormElement_IncrementInvalidCount( this.buttons[ i ] ); 155 this.buttons[ i ].disabled = true; 156 } 157 } 158 } 159 else 160 { 161 for ( i = 0, i_len = this.buttons.length; i < i_len; i++ ) 162 { 163 if ( this.Purchase_FormElement_CanEnableDisable( this.buttons[ i ] ) ) 164 { 165 this.buttons[ i ].disabled = true; 166 } 167 } 168 } 169 170 this.purchase_disabled = true; 171} 172 173AttributeMachine.prototype.Enable_Purchase_Buttons = function() 174{ 175 var i, i_len; 176 177 if ( this.form_action === 'ATWL' || this.form_action == 'AFWL' ) 178 { 179 return; 180 } 181 else if ( this.form_action === 'ADPM' ) 182 { 183 if ( this.Purchase_FormElement_CanEnableDisable( this.element_product_quantity ) ) 184 { 185 this.element_product_quantity.disabled = false;
186 } 187 } 188 else if ( this.form_action === 'AUPM' ) 189 { 190 for ( i = 0, i_len = this.buttons.length; i < i_len; i++ ) 191 { 192 if ( this.Purchase_FormElement_CanEnableDisable( this.buttons[ i ] ) && 193 this.Purchase_FormElement_DecrementInvalidCount( this.buttons[ i ] ) == 0 ) 194 { 195 this.buttons[ i ].disabled = false; 196 } 197 } 198 } 199 else 200 { 201 for ( i = 0, i_len = this.buttons.length; i < i_len; i++ ) 202 { 203 if ( this.Purchase_FormElement_CanEnableDisable( this.buttons[ i ] ) ) 204 { 205 this.buttons[ i ].disabled = false; 206 } 207 } 208 } 209 210 this.purchase_disabled = false; 211} 212 213AttributeMachine.prototype.Purchase_Button_CanEnableDisable = function( button ) 214{ 215 return this.Purchase_FormElement_CanEnableDisable( button ); 216} 217 218AttributeMachine.prototype.Purchase_FormElement_CanEnableDisable = function( element ) 219{ 220 if ( element ) 221 { 222 while ( ( element = element.parentNode ) != null ) 223 { 224 if ( ( typeof element.getAttribute === 'function' ) && 225 ( element.getAttribute( 'data-mmnodisable' ) !== null ) ) 226 { 227 return false; 228 } 229 } 230 231 return true; 232 } 233 234 return false; 235} 236 237AttributeMachine.prototype.Purchase_FormElement_IncrementInvalidCount = function( element ) 238{ 239 var invalid_count; 240 241 invalid_count = parseInt( element.getAttribute( 'data-mminvalidcount' ) ) || 0; 242 243 if ( !this.purchase_disabled ) 244 { 245 invalid_count++; 246 } 247 248 element.setAttribute( 'data-mminvalidcount', invalid_count ); 249 return invalid_count; 250} 251 252AttributeMachine.prototype.Purchase_FormElement_DecrementInvalidCount = function( element ) 253{ 254 var invalid_count; 255 256 invalid_count = parseInt( element.getAttribute( 'data-mminvalidcount' ) ) || 0; 257 258 if ( this.purchase_disabled && invalid_count > 0 ) 259 { 260 invalid_count--; 261 } 262 263 element.setAttribute( 'data-mminvalidcount', invalid_count ); 264 return invalid_count; 265} 266 267AttributeMachine.prototype.Gather_Form_ProductAttributeElements = function( attribute, template_attribute ) 268{ 269 var i, i_len, index, match, regex, elements; 270 271 elements = new Array(); 272 273 if ( ( index = this.Lookup_Attribute_Form_Index( this.form, attribute.code, template_attribute ? template_attribute.code : null ) ) !== null ) 274 { 275 if ( this.form_action === 'ADPM' ) 276 { 277 regex = new RegExp( '^products\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[\\s{0,}' + index + '\\s{0,}\\]:value$', 'i' ); 278 279 for ( i = 0, i_len = this.elementlist_product_attributes.length; i < i_len; i++ ) 280 { 281 if ( !this.elementlist_product_attributes[ i ].hasAttribute( 'name' ) ) continue; 282 if ( ( match = this.elementlist_product_attributes[ i ].name.match( regex ) ) === null ) continue; 283 284 elements.push( this.elementlist_product_attributes[ i ] ); 285 } 286 } 287 else if ( this.form_action === 'AUPM' ) 288 { 289 regex = new RegExp( '^product\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[\\s{0,}' + index + '\\s{0,}\\]:value$', 'i' ); 290 291 for ( i = 0, i_len = this.elementlist_product_attributes.length; i < i_len; i++ ) 292 { 293 if ( !this.elementlist_product_attributes[ i ].hasAttribute( 'name' ) ) continue; 294 if ( ( match = this.elementlist_product_attributes[ i ].name.match( regex ) ) === null ) continue; 295 296 elements.push( this.elementlist_product_attributes[ i ] ); 297 } 298 } 299 else 300 { 301 regex = new RegExp( '^product_attributes\\[\\s{0,}' + index + '\\s{0,}\\]:value$', 'i' ); 302 303 for ( i = 0, i_len = this.elementlist_product_attributes.length; i < i_len; i++ ) 304 { 305 if ( !this.elementlist_product_attributes[ i ].hasAttribute( 'name' ) ) continue; 306 if ( ( match = this.elementlist_product_attributes[ i ].name.match( regex ) ) === null ) continue; 307 308 elements.push( this.elementlist_product_attributes[ i ] ); 309 } 310 } 311 } 312 313 return elements; 314} 315 316AttributeMachine.prototype.AttributeAndOptionList_Load_Callback = function( response, possible ) 317{ 318 var self = this; 319 var i, j, i_len, j_len, data, input, attribute, selection, last_attr_id, last_option_id, last_attmpat_id, template_attribute; 320 321 if ( !response.success ) 322 { 323 this.onerror( response.error_message ); 324 } 325 326 this.master_attributes = response.data; 327 this.attributes = new Array(); 328 this.have_inventory_attributes = false; 329 330 if ( !this.Lookup_Attribute_Form() ) 331 { 332 return; 333 } 334 335 this.Find_Purchase_Buttons(); 336 337 if ( this.settings.displaydiscounts ) 338 { 339 this.subscription_term = new AttributeMachine_SubscriptionTerm( this, this.form, this.elementlist_product_subscription.slice() ); 340 this.subscription_term.onchange = function( event ) { self.ProductSubscriptionTerm_Changed(); }; 341 } 342 343 for ( i = 0, i_len = this.master_attributes.length; i < i_len; i++ ) 344 { 345 attribute = this.master_attributes[ i ]; 346 347 if ( attribute.type != 'template' ) 348 { 349 if ( attribute.inventory ) 350 { 351 this.have_inventory_attributes = true; 352 } 353 354 if ( attribute.type == 'checkbox' ) input = new AttributeMachine_Checkbox( this, attribute, null ); 355 else if ( attribute.type == 'text' ) input = new AttributeMachine_Text( this, attribute, null ); 356 else if ( attribute.type == 'memo' ) input = new AttributeMachine_Memo( this, attribute, null ); 357 else if ( attribute.type == 'radio' ) input = new AttributeMachine_Radio( this, attribute, null ); 358 else if ( attribute.type == 'select' ) input = new AttributeMachine_Select( this, attribute, null ); 359 else if ( attribute.type == 'swatch-select' ) input = new AttributeMachine_Select( this, attribute, null ); 360 else continue; 361 362 if ( !input.Initialize( this.form, this.Gather_Form_ProductAttributeElements( attribute, null ) ) ) 363 {
364 this.onerror( 'Unable to locate form element(s) for attribute ' + attribute.code ); 365 continue; 366 } 367 368 this.attributes.push( input ); 369 } 370 else 371 { 372 for ( j = 0, j_len = attribute.attributes.length; j < j_len; j++ ) 373 { 374 template_attribute = attribute.attributes[ j ]; 375 376 if ( template_attribute.inventory ) 377 { 378 this.have_inventory_attributes = true; 379 } 380 381 if ( template_attribute.type == 'checkbox' ) input = new AttributeMachine_Checkbox( this, attribute, template_attribute ); 382 else if ( template_attribute.type == 'text' ) input = new AttributeMachine_Text( this, attribute, template_attribute ); 383 else if ( template_attribute.type == 'memo' ) input = new AttributeMachine_Memo( this, attribute, template_attribute ); 384 else if ( template_attribute.type == 'radio' ) input = new AttributeMachine_Radio( this, attribute, template_attribute ); 385 else if ( template_attribute.type == 'select' ) input = new AttributeMachine_Select( this, attribute, template_attribute ); 386 else if ( template_attribute.type == 'swatch-select' ) input = new AttributeMachine_Select( this, attribute, template_attribute ); 387 else continue; 388 389 if ( !input.Initialize( this.form, this.Gather_Form_ProductAttributeElements( attribute, template_attribute ) ) ) 390 { 391 this.onerror( 'Unable to locate form element(s) for template attribute ' + attribute.code + ':' + template_attribute.code ); 392 continue; 393 } 394 395 this.attributes.push( input ); 396 } 397 } 398 } 399 400 if ( this.attributes.length == 0 ) 401 { 402 this.oninitializeswatches( this.master_attributes, null ); 403 return; 404 } 405 406 selection = this.Build_Selection(); 407 408 if ( !selection.Has_Selected() ) 409 { 410 last_attr_id = 0; 411 last_attmpat_id = 0; 412 last_option_id = 0; 413 } 414 else 415 { 416 last_attr_id = selection.selected_attr_ids[ 0 ]; 417 last_attmpat_id = selection.selected_attmpat_ids[ 0 ]; 418 last_option_id = selection.selected_option_ids[ 0 ]; 419 } 420 421 if ( possible ) 422 { 423 this.AttributeList_Load_Possible_Callback( possible ); 424 } 425 else 426 { 427 data = new Object(); 428 data.product_code = this.settings.product_code; 429 data.dependency_resolution = this.settings.dependency_resolution; 430 data.predictdiscounts = this.settings.displaydiscounts; 431 data.calculate_sale_price = this.settings.price === 'sale' ? true : false; 432 data.last_selected_attr_id = last_attr_id; 433 data.last_selected_attmpat_id = last_attmpat_id; 434 data.last_selected_option_id = last_option_id; 435 data.selected_term_id = selection.selected_term_id; 436 data.selected_attr_ids = selection.selected_attr_ids; 437 data.selected_attmpat_ids = selection.selected_attmpat_ids; 438 data.selected_option_ids = selection.selected_option_ids; 439 data.selected_attr_types = selection.selected_attr_types; 440 data.unselected_attr_ids = selection.unselected_attr_ids; 441 data.unselected_attmpat_ids = selection.unselected_attmpat_ids; 442 443 this.possible_req = v96_Runtime_AttributeList_Load_ProductVariant_Possible_PredictDiscounts( data, function( possible_response ) { self.AttributeList_Load_Possible_Callback( possible_response ); } ); 444 } 445} 446 447AttributeMachine.prototype.ProductSubscriptionTerm_Changed = function() 448{ 449 var self = this; 450 var data, selection; 451 452 selection = this.Build_Selection(); 453 454 data = new Object(); 455 data.product_code = this.settings.product_code; 456 data.dependency_resolution = this.settings.dependency_resolution; 457 data.predictdiscounts = this.settings.displaydiscounts; 458 data.calculate_sale_price = this.settings.price === 'sale' ? true : false; 459 data.last_selected_attr_id = 0; 460 data.last_selected_attmpat_id = 0; 461 data.last_selected_option_id = 0; 462 data.selected_term_id = selection.selected_term_id; 463 data.selected_attr_ids = selection.selected_attr_ids; 464 data.selected_attmpat_ids = selection.selected_attmpat_ids; 465 data.selected_option_ids = selection.selected_option_ids; 466 data.selected_attr_types = selection.selected_attr_types; 467 data.unselected_attr_ids = selection.unselected_attr_ids; 468 data.unselected_attmpat_ids = selection.unselected_attmpat_ids; 469 470 this.possible_req = v96_Runtime_AttributeList_Load_ProductVariant_Possible_PredictDiscounts( data, function( possible_response ) { self.AttributeList_Load_Possible_Callback( possible_response ); } ); 471} 472 473AttributeMachine.prototype.AttributeList_Load_Possible_Callback = function( response ) 474{ 475 var i, i_len, variant, message, attribute, cull_failures, possible_lookup, template_attribute, possible_sublookup; 476 477 cull_failures = new Array(); 478 this.possible_req = null; 479 480 if ( !response.success ) 481 {
482 this.onerror( response.error_message ); 483 } 484 485 this.oninitializeswatches( this.master_attributes, response ); 486 487 possible_lookup = ( response.data ) ? this.Build_Possible_Lookup( response.data.attributes ) : null; 488 489 // Iterate through the attributes we've created and disable any that are not possible 490 for ( i = 0, i_len = this.attributes.length; i < i_len; i++ ) 491 { 492 attribute = this.attributes[ i ].attribute; 493 template_attribute = this.attributes[ i ].template_attribute; 494 495 if ( !attribute.inventory && ( !template_attribute || !template_attribute.inventory ) ) 496 { 497 continue; 498 } 499 500 possible_sublookup = ( possible_lookup ) ? possible_lookup[ attribute.id ] : null; 501 502 if ( possible_sublookup ) 503 { 504 if ( template_attribute ) possible_sublookup = possible_sublookup[ template_attribute.id ]; 505 else possible_sublookup = possible_sublookup[ 0 ]; 506 } 507 508 if ( possible_sublookup == null ) this.attributes[ i ].Disable(); 509 else 510 { 511 if ( !this.attributes[ i ].Cull( possible_sublookup.options, possible_sublookup.selected_id, message ) ) 512 { 513 cull_failures.push( template_attribute ? template_attribute : attribute ); 514 } 515 } 516 } 517 518 variant = ( response.data ) ? response.data.variant : null; 519 520 if ( response.data && response.data.have_price ) 521 { 522 this.Pricing_Update( response.data ); 523 this.Weight_Update( response.data ); 524 } 525 else 526 { 527 this.Pricing_Reset(); 528 this.Weight_Reset(); 529 } 530 531 if ( !this.have_inventory_attributes ) 532 { 533 return; 534 } 535 536 // Handle the purchase buttons and inventory message 537 if ( !variant || cull_failures.length ) 538 { 539 this.Disable_Purchase_Buttons(); 540 541 if ( this.inv_div ) 542 { 543 this.inv_div.innerHTML = this.settings.invalid_msg; 544 545 for ( i = 0, i_len = cull_failures.length; i < i_len; i++ ) 546 { 547 if ( cull_failures[ i ].type == 'radio' ) message = this.settings.missing_radio_msg; 548 else if ( ( cull_failures[ i ].type == 'text' ) || ( cull_failures[ i ].type == 'memo' ) ) message = this.settings.missing_text_msg; 549 else message = ''; 550 551 message = message.replace( '%attribute_code%', cull_failures[ i ].code ); 552 message = message.replace( '%attribute_prompt%', cull_failures[ i ].prompt ); 553 554 this.inv_div.innerHTML += message; 555 } 556 } 557 } 558 else 559 { 560 if ( variant.inv_active && 561 variant.inv_level == 'out' ) this.Disable_Purchase_Buttons(); 562 else this.Enable_Purchase_Buttons(); 563 564 if ( this.inv_div ) this.inv_div.innerHTML = this.settings.inv_long ? variant.inv_long : variant.inv_short; 565 566 const product_data = 567 { 568 product_code: this.settings.product_code, 569 variant_id: variant.variant_id 570 }; 571 572 this.onVariantChanged( product_data ); 573 574 if ( typeof MivaEvents !== 'undefined' ) 575 { 576 MivaEvents.ThrowEvent( 'variant_changed', product_data ); 577 } 578 } 579} 580 581AttributeMachine.prototype.Pricing_Update = function( data ) 582{ 583 var i, i_len, price, additional_price, formatted_price, formatted_additional_price; 584 585 if ( this.settings.price === 'retail' ) 586 { 587 price = data.retail; 588 formatted_price = data.formatted_retail; 589 } 590 else if ( this.settings.price === 'base' ) 591 { 592 price = data.base_price; 593 formatted_price = data.formatted_base_price; 594 } 595 else 596 { 597 price = data.price; 598 formatted_price = data.formatted_price; 599 } 600 601 if ( ( this.settings.additionalprice === 'retail' ) && ( price < data.retail ) ) 602 { 603 additional_price = data.retail; 604 formatted_additional_price = data.formatted_retail; 605 } 606 else if ( ( this.settings.additionalprice === 'base' ) && ( price < data.base_price ) ) 607 { 608 additional_price = data.base_price; 609 formatted_additional_price = data.formatted_base_price; 610 } 611 else 612 { 613 additional_price = null; 614 formatted_additional_price = ''; 615 } 616 617 if ( this.price_div ) this.price_div.innerHTML = formatted_price; 618 if ( this.additional_price_div ) this.additional_price_div.innerHTML = formatted_additional_price; 619 620 if ( this.discount_div && this.settings.displaydiscounts ) 621 { 622 this.discount_div.innerHTML = ''; 623 624 for ( i = 0, i_len = data.discounts.length; i < i_len; i++ ) 625 { 626 this.discount_div.appendChild( this.Generate_Discount( data.discounts[ i ] ) ); 627 } 628 } 629 630 const product_data = 631 { 632 product_code: this.settings.product_code, 633 price: price, 634 additional_price: additional_price, 635 formatted_price: formatted_price, 636 formatted_additional_price: formatted_additional_price 637 }; 638 639 this.onPriceChanged( product_data ); 640 641 if ( typeof MivaEvents !== 'undefined' ) 642 { 643 MivaEvents.ThrowEvent( 'price_changed', product_data ); 644 } 645} 646 647AttributeMachine.prototype.Pricing_Reset = function() 648{ 649 if ( this.price_div ) this.price_div.innerHTML = this.initial_price_value; 650 if ( this.additional_price_div ) this.additional_price_div.innerHTML = this.initial_additional_price_value; 651 652 if ( this.discount_div && this.settings.displaydiscounts ) 653 { 654 this.discount_div.innerHTML = this.initial_discount_value; 655 } 656} 657 658AttributeMachine.prototype.Weight_Update = function( data ) 659{ 660 if ( this.weight_div ) 661 { 662 this.weight_div.textContent = this.weight_div.hasAttribute( 'data-mm-formatted' ) ? data.formatted_weight : data.padded_weight; 663 } 664} 665 666AttributeMachine.prototype.Weight_Reset = function() 667{ 668 if ( this.weight_div ) 669 { 670 this.weight_div.innerHTML = this.initial_weight_value; 671 } 672} 673 674AttributeMachine.prototype.Attribute_Changed = function( attribute ) 675{ 676 var self = this; 677 var data, selection; 678 679 if ( this.possible_req ) 680 { 681 this.possible_req.onreadystatechange = function() {}; 682 this.possible_req.abort(); 683 } 684 685 selection = this.Build_Selection(); 686 687 data = new Object(); 688 data.product_code = this.settings.product_code; 689 data.dependency_resolution = this.settings.dependency_resolution; 690 data.predictdiscounts = this.settings.displaydiscounts; 691 data.calculate_sale_price = this.settings.price === 'sale' ? true : false;
692 data.last_selected_attr_id = attribute.attribute.id; 693 data.last_selected_attmpat_id = attribute.template_attribute ? attribute.template_attribute.id : 0; 694 data.last_selected_option_id = attribute.Selected_Option_ID(); 695 data.selected_term_id = selection.selected_term_id; 696 data.selected_attr_ids = selection.selected_attr_ids; 697 data.selected_attmpat_ids = selection.selected_attmpat_ids; 698 data.selected_option_ids = selection.selected_option_ids; 699 data.selected_attr_types = selection.selected_attr_types; 700 data.unselected_attr_ids = selection.unselected_attr_ids; 701 data.unselected_attmpat_ids = selection.unselected_attmpat_ids; 702 703 this.possible_req = v96_Runtime_AttributeList_Load_ProductVariant_Possible_PredictDiscounts( data, function( possible_response ) { self.AttributeList_Load_Possible_Callback( possible_response ); } ); 704} 705 706AttributeMachine.prototype.Build_Selection = function() 707{ 708 var i, type, i_len, attr_id, selection, option_id, attmpat_id; 709 710 selection = new AttributeMachine_Selection(); 711 712 if ( this.subscription_term ) 713 { 714 selection.selected_term_id = this.subscription_term.GetValue(); 715 } 716 717 for ( i = 0, i_len = this.attributes.length; i < i_len; i++ ) 718 { 719 attr_id = this.attributes[ i ].attribute.id; 720 attmpat_id = this.attributes[ i ].template_attribute == null ? 0 : this.attributes[ i ].template_attribute.id; 721 option_id = this.attributes[ i ].Selected_Option_ID(); 722 723 if ( option_id === null ) 724 { 725 selection.unselected_attr_ids.push( attr_id ); 726 selection.unselected_attmpat_ids.push( attmpat_id ); 727 } 728 else 729 { 730 type = this.attributes[ i ].template_attribute == null ? this.attributes[ i ].attribute.type : this.attributes[ i ].template_attribute.type; 731 732 selection.selected_attr_ids.push( attr_id ); 733 selection.selected_attmpat_ids.push( attmpat_id ); 734 selection.selected_option_ids.push( option_id ); 735 selection.selected_attr_types.push( type ); 736 } 737 } 738 739 return selection; 740} 741 742AttributeMachine.prototype.Build_Possible_Lookup = function( data ) 743{ 744 var i, j, i_len, j_len, lookup, attr_id, option_id, attmpat_id; 745 746 lookup = new Array(); 747 748 for ( i = 0, i_len = data.length; i < i_len; i++ ) 749 { 750 attr_id = data[ i ].id; 751 attmpat_id = data[ i ].attmpat_id; 752 753 if ( lookup[ attr_id ] == null ) 754 { 755 lookup[ attr_id ] = new Array(); 756 } 757 758 if ( lookup[ attr_id ][ attmpat_id ] == null ) 759 { 760 lookup[ attr_id ][ attmpat_id ] = new Object; 761 lookup[ attr_id ][ attmpat_id ].options = new Array(); 762 } 763 764 lookup[ attr_id ][ attmpat_id ].selected_id = data[ i ].selected_id; 765 766 for ( j = 0, j_len = data[ i ].options.length; j < j_len; j++ ) 767 { 768 option_id = data[ i ].options[ j ]; 769 lookup[ attr_id ][ attmpat_id ].options[ option_id ] = 1; 770 } 771 } 772 773 return lookup; 774} 775 776AttributeMachine.prototype.Lookup_Form_Data = function() 777{ 778 var i, j, data, forms, i_len, j_len, action, action_value; 779 780 forms = this.getElementsByTagName( 'form' ); 781 782 for ( i = 0, i_len = forms.length; i < i_len; i++ ) 783 { 784 for ( j = 0, j_len = forms[ i ].elements.length; j < j_len; j++ ) 785 { 786 if ( !forms[ i ].elements[ j ].hasAttribute( 'name' ) ) 787 { 788 continue; 789 } 790 else if ( forms[ i ].elements[ j ].name.toLowerCase() === 'action' ) 791 { 792 action = forms[ i ].elements[ j ]; 793 break; 794 } 795 } 796 797 if ( !action ) 798 { 799 continue; 800 } 801 802 action_value = action.value.toUpperCase(); 803 804 if ( action_value !== 'ADPR' && 805 action_value !== 'ADPM' && 806 action_value !== 'AUPR' && 807 action_value !== 'AUPM' && 808 action_value !== 'AFWL' ) 809 { 810 continue; 811 } 812 813 if ( action_value === 'ADPM' || action_value === 'AUPM' ) 814 { 815 if ( ( data = this.Lookup_Form_Data_LowLevel_MultiAddForm( forms[ i ], action_value ) ) !== null ) 816 { 817 return data; 818 } 819 } 820 else 821 { 822 if ( ( data = this.Lookup_Form_Data_LowLevel_SingleAddForm( forms[ i ], action_value ) ) !== null ) 823 { 824 return data; 825 } 826 } 827 } 828 829 return null; 830} 831 832AttributeMachine.prototype.Lookup_Form_Data_LowLevel_MultiAddForm = function( form, action_value ) 833{ 834 var i, data, i_len, name, product_id, match_code, match_quantity, match_attributes, regex_product_code, match_subscription, regex_product_quantity; 835 var elementmap_product_code, regex_product_attributes, regex_product_subscription, elementmap_product_quantity, elementmap_product_attributes, elementmap_product_subscription; 836 837 product_id = -1; 838 elementmap_product_code = new Object(); 839 elementmap_product_quantity = new Object(); 840 elementmap_product_attributes = new Object(); 841 elementmap_product_subscription = new Object(); 842 843 if ( action_value === 'AUPM' ) 844 { 845 regex_product_code = new RegExp( '^product\\[\\s{0,}(\\d{1,})\\s{0,}\\]:code', 'i' ); 846 regex_product_quantity = null; 847 regex_product_attributes = new RegExp( '^product\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[', 'i' ); 848 regex_product_subscription = new RegExp( '^product\\[\\s{0,}(\\d{1,})\\s{0,}\\]:subterm_id', 'i' ); 849 } 850 else 851 { 852 regex_product_code = new RegExp( '^products\\[\\s{0,}(\\d{1,})\\s{0,}\\]:code', 'i' ); 853 regex_product_quantity = new RegExp( '^products\\[\\s{0,}(\\d{1,})\\s{0,}\\]:quantity', 'i' ); 854 regex_product_attributes = new RegExp( '^products\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[', 'i' ); 855 regex_product_subscription = new RegExp( '^products\\[\\s{0,}(\\d{1,})\\s{0,}\\]:subterm_id', 'i' ); 856 } 857 858 for ( i = 0, i_len = form.elements.length; i < i_len; i++ ) 859 {
860 if ( !form.elements[ i ].hasAttribute( 'name' ) ) 861 { 862 continue; 863 } 864 865 name = form.elements[ i ].name.toLowerCase(); 866 867 if ( ( ( match_code = name.match( regex_product_code ) ) !== null ) && ( typeof match_code[ 1 ] === 'string' ) && ( match_code[ 1 ].length ) ) 868 { 869 if ( form.elements[ i ].value.toLowerCase() === this.settings.product_code.toLowerCase() ) 870 { 871 product_id = match_code[ 1 ]; 872 } 873 874 elementmap_product_code[ match_code[ 1 ] ] = form.elements[ i ]; 875 } 876 else if ( regex_product_quantity && ( ( match_quantity = name.match( regex_product_quantity ) ) !== null ) && ( typeof match_quantity[ 1 ] === 'string' ) && ( match_quantity[ 1 ].length ) ) 877 { 878 elementmap_product_quantity[ match_quantity[ 1 ] ] = form.elements[ i ]; 879 } 880 else if ( ( ( match_attributes = name.match( regex_product_attributes ) ) !== null ) && ( typeof match_attributes[ 1 ] === 'string' ) && ( match_attributes[ 1 ].length ) ) 881 { 882 if ( !Array.isArray( elementmap_product_attributes[ match_attributes[ 1 ] ] ) ) 883 { 884 elementmap_product_attributes[ match_attributes[ 1 ] ] = new Array(); 885 } 886 887 elementmap_product_attributes[ match_attributes[ 1 ] ].push( form.elements[ i ] ); 888 } 889 else if ( ( ( match_subscription = name.match( regex_product_subscription ) ) !== null ) && ( typeof match_subscription[ 1 ] === 'string' ) && ( match_subscription[ 1 ].length ) ) 890 { 891 if ( !Array.isArray( elementmap_product_subscription[ match_subscription[ 1 ] ] ) ) 892 { 893 elementmap_product_subscription[ match_subscription[ 1 ] ] = new Array(); 894 } 895 896 elementmap_product_subscription[ match_subscription[ 1 ] ].push( form.elements[ i ] ); 897 } 898 } 899 900 if ( product_id === -1 ) return null; 901 if ( !elementmap_product_code.hasOwnProperty( product_id ) ) return null; 902 if ( action_value === 'ADPM' && !elementmap_product_quantity.hasOwnProperty( product_id ) ) return null; 903 if ( ( !elementmap_product_attributes.hasOwnProperty( product_id ) || elementmap_product_attributes[ product_id ].length === 0 ) && 904 ( !elementmap_product_subscription.hasOwnProperty( product_id ) || elementmap_product_subscription[ product_id ].length === 0 ) ) return null; 905 906 data = new Object(); 907 data.form = form; 908 data.form_action = action_value; 909 data.element_product_code = elementmap_product_code[ product_id ]; 910 data.element_product_quantity = elementmap_product_quantity.hasOwnProperty( product_id ) ? elementmap_product_quantity[ product_id ] : null; 911 data.elementlist_product_attributes = elementmap_product_attributes[ product_id ]; 912 data.elementlist_product_subscription = elementmap_product_subscription.hasOwnProperty( product_id ) ? elementmap_product_subscription[ product_id ] : []; 913 914 return data; 915} 916 917AttributeMachine.prototype.Lookup_Form_Data_LowLevel_SingleAddForm = function( form, action_value ) 918{ 919 var i, name, data, i_len, element_product_code, element_product_quantity, elementlist_product_attributes, elementlist_product_subscription; 920 921 element_product_code = null; 922 element_product_quantity = null; 923 elementlist_product_attributes = new Array(); 924 elementlist_product_subscription = new Array(); 925 926 for ( i = 0, i_len = form.elements.length; i < i_len; i++ ) 927 { 928 if ( !form.elements[ i ].hasAttribute( 'name' ) ) 929 { 930 continue; 931 } 932 933 name = form.elements[ i ].name.toLowerCase(); 934 935 if ( name === 'product_code' ) element_product_code = form.elements[ i ]; 936 else if ( name === 'quantity' ) element_product_quantity = form.elements[ i ]; 937 else if ( name === 'product_subscription_term_id' ) elementlist_product_subscription.push( form.elements[ i ] ); 938 else if ( name.indexOf( 'product_attributes[' ) === 0 ) elementlist_product_attributes.push( form.elements[ i ] ); 939 } 940 941 if ( !element_product_code ) return null; 942 if ( action_value === 'ADPM' && !element_product_quantity ) return null; 943 if ( element_product_code.value.toLowerCase() != this.settings.product_code.toLowerCase() ) return null; 944 if ( elementlist_product_attributes.length === 0 && elementlist_product_subscription.length === 0 ) return null; 945 946 data = new Object(); 947 data.form = form; 948 data.form_action = action_value; 949 data.element_product_code = element_product_code; 950 data.element_product_quantity = element_product_quantity; 951 data.elementlist_product_attributes = elementlist_product_attributes; 952 data.elementlist_product_subscription = elementlist_product_subscription; 953 954 return data; 955} 956 957AttributeMachine.prototype.Lookup_Attribute_Form = function() 958{ 959 var i, j, forms, i_len, j_len, action, form_data, ignore_error; 960 961 if ( ( form_data = this.Lookup_Form_Data() ) !== null ) 962 { 963 this.form = form_data.form; 964 this.form_action = form_data.form_action; 965 this.element_product_code = form_data.element_product_code; 966 this.element_product_quantity = form_data.element_product_quantity; 967 this.elementlist_product_attributes = form_data.elementlist_product_attributes; 968 this.elementlist_product_subscription = form_data.elementlist_product_subscription; 969 970 return form_data.form; 971 } 972 973 // 974 // Iterate over each of the forms on screen. If the ATWL 975 // form exists, then we ignore the error alert 976 // 977 978 forms = this.getElementsByTagName( 'form' ); 979 980 for ( i = 0, i_len = forms.length; i < i_len; i++ ) 981 { 982 for ( j = 0, j_len = forms[ i ].elements.length; j < j_len; j++ ) 983 {
984 if ( !forms[ i ].elements[ j ].hasAttribute( 'name' ) ) 985 { 986 continue; 987 } 988 else if ( forms[ i ].elements[ j ].name.toLowerCase() === 'action' ) 989 { 990 action = forms[ i ].elements[ j ]; 991 break; 992 } 993 } 994 995 if ( !action ) 996 { 997 continue; 998 } 999 else if ( action.value.toUpperCase() === 'ATWL' ) 1000 { 1001 ignore_error = true; 1002 break; 1003 } 1004 } 1005 1006 if ( !ignore_error ) 1007 { 1008 this.onerror( 'Unable to locate form for inventory attributes' ); 1009 } 1010 1011 return null; 1012} 1013 1014AttributeMachine.prototype.Lookup_Attribute_Form_Index = function( form, attribute_code, template_code ) 1015{ 1016 var i, j, i_len, j_len, regex, match, index, regex_template, match_template; 1017 1018 if ( form !== this.form ) 1019 { 1020 return null; 1021 } 1022 1023 if ( this.form_action === 'ADPM' ) 1024 { 1025 regex = new RegExp( '^products\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[\\s{0,}(\\d{1,})\\s{0,}\\]:code$', 'i' ); 1026 1027 for ( i = 0, i_len = this.elementlist_product_attributes.length; i < i_len; i++ ) 1028 { 1029 if ( !this.elementlist_product_attributes[ i ].hasAttribute( 'name' ) ) continue; 1030 if ( ( match = this.elementlist_product_attributes[ i ].name.match( regex ) ) === null ) continue; 1031 if ( this.elementlist_product_attributes[ i ].value !== attribute_code ) continue; 1032 1033 index = parseInt( match[ 2 ], 10 ); 1034 1035 if ( template_code === null ) 1036 { 1037 return index; 1038 } 1039 1040 regex_template = new RegExp( '^products\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[\\s{0,}(\\d{1,})\\s{0,}\\]:template_code$', 'i' ); 1041 1042 for ( j = 0, j_len = this.elementlist_product_attributes.length; j < j_len; j++ ) 1043 { 1044 if ( !this.elementlist_product_attributes[ j ].hasAttribute( 'name' ) ) continue; 1045 if ( ( match_template = this.elementlist_product_attributes[ j ].name.match( regex_template ) ) === null ) continue; 1046 if ( this.elementlist_product_attributes[ j ].value !== template_code ) continue; 1047 1048 if ( parseInt( match_template[ 2 ], 10 ) === index ) 1049 { 1050 return index; 1051 } 1052 } 1053 } 1054 } 1055 else if ( this.form_action == 'AUPM' ) 1056 { 1057 regex = new RegExp( '^product\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[\\s{0,}(\\d{1,})\\s{0,}\\]:code$', 'i' ); 1058 1059 for ( i = 0, i_len = this.elementlist_product_attributes.length; i < i_len; i++ ) 1060 { 1061 if ( !this.elementlist_product_attributes[ i ].hasAttribute( 'name' ) ) continue; 1062 if ( ( match = this.elementlist_product_attributes[ i ].name.match( regex ) ) === null ) continue; 1063 if ( this.elementlist_product_attributes[ i ].value !== attribute_code ) continue; 1064 1065 index = parseInt( match[ 2 ], 10 ); 1066 1067 if ( template_code === null ) 1068 { 1069 return index; 1070 } 1071 1072 regex_template = new RegExp( '^product\\[\\s{0,}(\\d{1,})\\s{0,}\\]:attributes\\[\\s{0,}(\\d{1,})\\s{0,}\\]:template_code$', 'i' ); 1073 1074 for ( j = 0, j_len = this.elementlist_product_attributes.length; j < j_len; j++ ) 1075 { 1076 if ( !this.elementlist_product_attributes[ j ].hasAttribute( 'name' ) ) continue; 1077 if ( ( match_template = this.elementlist_product_attributes[ j ].name.match( regex_template ) ) === null ) continue; 1078 if ( this.elementlist_product_attributes[ j ].value !== template_code ) continue; 1079 1080 if ( parseInt( match_template[ 2 ], 10 ) === index ) 1081 { 1082 return index; 1083 } 1084 } 1085 } 1086 } 1087 else 1088 { 1089 regex = new RegExp( '^product_attributes\\[\\s{0,}(\\d{1,})\\s{0,}\\]:code$', 'i' ); 1090 1091 for ( i = 0, i_len = this.elementlist_product_attributes.length; i < i_len; i++ ) 1092 { 1093 if ( !this.elementlist_product_attributes[ i ].hasAttribute( 'name' ) ) continue; 1094 if ( ( match = this.elementlist_product_attributes[ i ].name.match( regex ) ) === null ) continue; 1095 if ( this.elementlist_product_attributes[ i ].value !== attribute_code ) continue; 1096 1097 index = parseInt( match[ 1 ], 10 ); 1098 1099 if ( template_code === null ) 1100 { 1101 return index; 1102 } 1103 1104 regex_template = new RegExp( '^product_attributes\\[\\s{0,}(\\d{1,})\\s{0,}\\]:template_code$', 'i' ); 1105 1106 for ( j = 0, j_len = this.elementlist_product_attributes.length; j < j_len; j++ ) 1107 { 1108 if ( !this.elementlist_product_attributes[ j ].hasAttribute( 'name' ) ) continue; 1109 if ( ( match_template = this.elementlist_product_attributes[ j ].name.match( regex_template ) ) === null ) continue; 1110 if ( this.elementlist_product_attributes[ j ].value !== template_code ) continue; 1111 1112 if ( parseInt( match_template[ 1 ], 10 ) === index ) 1113 { 1114 return index; 1115 } 1116 } 1117 } 1118 } 1119 1120 return null; 1121} 1122 1123AttributeMachine.prototype.onerror = function( error_message ) { console.log( error_message ); } 1124AttributeMachine.prototype.getElementById = function( id ) { return document.getElementById( id ); } 1125AttributeMachine.prototype.getElementsByTagName = function( tagName ) { return document.getElementsByTagName( tagName ); } 1126AttributeMachine.prototype.onPriceChanged = function( product_data ) { ; } 1127AttributeMachine.prototype.onVariantChanged = function( product_data ) { ; } 1128 1129// AttributeMachine_SubscriptionTerm
1130/////////////////////////////////////////////////////////////////// 1131 1132function AttributeMachine_SubscriptionTerm( machine, form, elements ) 1133{ 1134 var self = this; 1135 var i, i_len; 1136 1137 this.machine = machine; 1138 this.elements = new Array(); 1139 1140 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1141 { 1142 if ( elements[ i ].nodeName.toLowerCase() === 'input' && 1143 elements[ i ].type.toLowerCase() === 'radio' ) 1144 { 1145 this.elements.push( elements[ i ] ); 1146 AddEvent( elements[ i ], 'click', function( event ) { self.onchange( event ); } ); 1147 } 1148 else 1149 { 1150 this.elements.push( elements[ i ] ); 1151 AddEvent( elements[ i ], 'change', function( event ) { self.onchange( event ); } ); 1152 } 1153 } 1154} 1155 1156AttributeMachine_SubscriptionTerm.prototype.GetValue = function() 1157{ 1158 var i, i_len; 1159 1160 if ( this.elements.length == 0 ) 1161 { 1162 return 0; 1163 } 1164 1165 for ( i = 0, i_len = this.elements.length; i < i_len; i++ ) 1166 { 1167 if ( ( this.elements[ i ].nodeName.toLowerCase() == 'input' ) && 1168 ( this.elements[ i ].type.toLowerCase() == 'radio' ) ) 1169 { 1170 if ( this.elements[ i ].checked ) 1171 { 1172 return this.elements[ i ].value; 1173 } 1174 } 1175 else 1176 { 1177 return this.elements[ i ].value; 1178 } 1179 } 1180} 1181 1182AttributeMachine_SubscriptionTerm.prototype.onchange = function( event ) { ; } 1183 1184// AttributeMachine_Selection 1185/////////////////////////////////////////////////////////////////// 1186 1187function AttributeMachine_Selection() 1188{ 1189 this.selected_term_id = 0; 1190 this.selected_attr_ids = new Array(); 1191 this.selected_attmpat_ids = new Array(); 1192 this.selected_option_ids = new Array(); 1193 this.selected_attr_types = new Array(); 1194 1195 this.unselected_attr_ids = new Array(); 1196 this.unselected_attmpat_ids = new Array(); 1197} 1198 1199AttributeMachine_Selection.prototype.Has_Selected = function() 1200{ 1201 return this.selected_attr_ids.length ? true : false; 1202} 1203 1204// AttributeMachine_Checkbox 1205/////////////////////////////////////////////////////////////////// 1206 1207function AttributeMachine_Checkbox( machine, attribute, template_attribute ) 1208{ 1209 this.machine = machine; 1210 this.attribute = attribute; 1211 this.template_attribute = template_attribute; 1212 this.checkbox = null; 1213 this.hidden = null; 1214} 1215 1216AttributeMachine_Checkbox.prototype.Initialize = function( form, elements ) 1217{ 1218 var self = this; 1219 var i, i_len; 1220 1221 this.checkbox = null; 1222 1223 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1224 { 1225 if ( !elements[ i ].hasAttribute( 'type' ) ) continue; 1226 if ( elements[ i ].type.toLowerCase() !== 'checkbox' ) continue; 1227 1228 this.checkbox = elements[ i ]; 1229 break; 1230 } 1231 1232 if ( this.checkbox == null ) 1233 { 1234 return false; 1235 } 1236 1237 this.hidden = document.createElement( 'input' ); 1238 this.hidden.type = 'hidden'; 1239 this.hidden.name = this.checkbox.name; 1240 this.hidden.value = this.checkbox.checked ? 'Yes' : ''; 1241 this.hidden.disabled = this.checkbox.disabled ? false : true; 1242 1243 this.checkbox.form.appendChild( this.hidden ); 1244 1245 AddEvent( this.checkbox, 'click', function() 1246 { 1247 self.machine.Attribute_Changed( self ); 1248 return true; 1249 } ); 1250 1251 return true; 1252} 1253 1254AttributeMachine_Checkbox.prototype.Disable = function() 1255{ 1256 this.checkbox.disabled = true; 1257 this.hidden.disabled = false; 1258} 1259 1260AttributeMachine_Checkbox.prototype.Enable = function() 1261{ 1262 this.checkbox.disabled = false; 1263 this.hidden.disabled = true; 1264} 1265 1266AttributeMachine_Checkbox.prototype.Cull = function( possible_option_lookup, selected_id ) 1267{ 1268 if ( selected_id == 0 ) 1269 { 1270 this.checkbox.checked = false; 1271 this.hidden.value = ''; 1272 } 1273 else if ( selected_id == 1 ) 1274 { 1275 this.checkbox.checked = true; 1276 this.hidden.value = 'Yes'; 1277 } 1278 1279 if ( possible_option_lookup[ 0 ] == null || 1280 possible_option_lookup[ 1 ] == null ) this.Disable(); 1281 else this.Enable(); 1282 1283 return true; 1284} 1285 1286AttributeMachine_Checkbox.prototype.Selected_Option_ID = function() 1287{ 1288 if ( this.checkbox.checked ) return 1; 1289 else return 0; 1290} 1291 1292// AttributeMachine_Text 1293/////////////////////////////////////////////////////////////////// 1294 1295function AttributeMachine_Text( machine, attribute, template_attribute ) 1296{ 1297 this.machine = machine; 1298 this.attribute = attribute; 1299 this.template_attribute = template_attribute; 1300 this.input = null; 1301 this.last_value = null; 1302} 1303 1304AttributeMachine_Text.prototype.Initialize = function( form, elements ) 1305{ 1306 var self = this; 1307 var i, i_len; 1308 1309 this.input = null; 1310 1311 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1312 { 1313 if ( !elements[ i ].hasAttribute( 'type' ) ) continue; 1314 if ( elements[ i ].type.toLowerCase() !== 'text' ) continue; 1315 1316 this.input = elements[ i ]; 1317 break; 1318 } 1319 1320 if ( this.input == null ) 1321 { 1322 return false;
1323 } 1324 1325 this.last_value = this.input.value; 1326 1327 AddEvent( this.input, 'change', function( event ) { return self.Event_OnChange( event ? event : window.event ); } ); 1328 AddEvent( this.input, 'keyup', function( event ) { return self.Event_OnChange( event ? event : window.event ); } ); 1329 1330 return true; 1331} 1332 1333AttributeMachine_Text.prototype.Event_OnChange = function( e ) 1334{ 1335 if ( ( this.last_value.length == 0 ) != ( this.input.value.length == 0 ) ) 1336 { 1337 this.machine.Attribute_Changed( this ); 1338 } 1339 1340 this.last_value = this.input.value; 1341 1342 return true; 1343} 1344 1345AttributeMachine_Text.prototype.Disable = function() 1346{ 1347 this.input.disabled = true; 1348} 1349 1350AttributeMachine_Text.prototype.Enable = function() 1351{ 1352 this.input.disabled = false; 1353} 1354 1355AttributeMachine_Text.prototype.Cull = function( possible_option_lookup, selected_id ) 1356{ 1357 if ( possible_option_lookup[ 1 ] == null ) 1358 { 1359 this.Disable(); 1360 return true; 1361 } 1362 1363 this.Enable(); 1364 1365 switch ( selected_id ) 1366 { 1367 case 0 : 1368 { 1369 this.last_value = ''; 1370 this.input.value = ''; 1371 1372 break; 1373 } 1374 case 1 : 1375 { 1376 if ( this.input.value.length == 0 ) 1377 { 1378 return false; 1379 } 1380 1381 break; 1382 } 1383 } 1384 1385 return true; 1386} 1387 1388AttributeMachine_Text.prototype.Selected_Option_ID = function() 1389{ 1390 if ( this.input.disabled ) return 0; 1391 if ( this.input.value.length ) return 1; 1392 else return 0; 1393} 1394 1395// AttributeMachine_Memo 1396/////////////////////////////////////////////////////////////////// 1397 1398function AttributeMachine_Memo( machine, attribute, template_attribute ) 1399{ 1400 this.machine = machine; 1401 this.attribute = attribute; 1402 this.template_attribute = template_attribute; 1403 this.textarea = null; 1404 this.last_value = null; 1405} 1406 1407AttributeMachine_Memo.prototype.Initialize = function( form, elements ) 1408{ 1409 var self = this; 1410 var i, i_len; 1411 1412 this.textarea = null; 1413 1414 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1415 { 1416 if ( elements[ i ].nodeName.toLowerCase() !== 'textarea' ) 1417 { 1418 continue; 1419 } 1420 1421 this.textarea = elements[ i ]; 1422 break; 1423 } 1424 1425 if ( this.textarea == null ) 1426 { 1427 return false; 1428 } 1429 1430 this.last_value = this.textarea.value; 1431 1432 AddEvent( this.textarea, 'change', function( event ) { return self.Event_OnChange( event ? event : window.event ); } ); 1433 AddEvent( this.textarea, 'keyup', function( event ) { return self.Event_OnChange( event ? event : window.event ); } ); 1434 1435 return true; 1436} 1437 1438AttributeMachine_Memo.prototype.Event_OnChange = function( e ) 1439{ 1440 if ( ( this.last_value.length == 0 ) != ( this.textarea.value.length == 0 ) ) 1441 { 1442 this.machine.Attribute_Changed( this ); 1443 } 1444 1445 this.last_value = this.textarea.value; 1446 1447 return true; 1448} 1449 1450AttributeMachine_Memo.prototype.Disable = function() 1451{ 1452 this.textarea.disabled = true; 1453} 1454 1455AttributeMachine_Memo.prototype.Enable = function() 1456{ 1457 this.textarea.disabled = false; 1458} 1459 1460AttributeMachine_Memo.prototype.Cull = function( possible_option_lookup, selected_id ) 1461{ 1462 if ( possible_option_lookup[ 1 ] == null ) 1463 { 1464 this.Disable(); 1465 return true; 1466 } 1467 1468 this.Enable(); 1469 1470 switch ( selected_id ) 1471 { 1472 case 0 : 1473 { 1474 this.last_value = ''; 1475 this.textarea.value = ''; 1476 1477 break; 1478 } 1479 case 1 : 1480 { 1481 if ( this.textarea.value.length == 0 ) 1482 { 1483 return false; 1484 } 1485 1486 break; 1487 } 1488 } 1489 1490 return true; 1491} 1492 1493AttributeMachine_Memo.prototype.Selected_Option_ID = function() 1494{ 1495 if ( this.textarea.disabled ) return 0; 1496 if ( this.textarea.value.length ) return 1; 1497 else return 0; 1498} 1499 1500// AttributeMachine_Radio 1501/////////////////////////////////////////////////////////////////// 1502 1503function AttributeMachine_Radio( machine, attribute, template_attribute ) 1504{ 1505 this.machine = machine; 1506 this.attribute = attribute; 1507 this.template_attribute = template_attribute; 1508 this.options = template_attribute ? template_attribute.options : attribute.options; 1509 this.radios = new Array(); 1510 this.empty_radio = null; 1511 this.option_lookup = null; 1512} 1513 1514AttributeMachine_Radio.prototype.Initialize = function( form, elements ) 1515{ 1516 var self = this; 1517 var i, i_len, j, j_len; 1518 1519 this.radios = new Array(); 1520 1521 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1522 { 1523 if ( !elements[ i ].hasAttribute( 'type' ) ) continue; 1524 if ( elements[ i ].type.toLowerCase() !== 'radio' ) continue; 1525 1526 this.radios.push( elements[ i ] ); 1527 } 1528 1529 if ( this.radios.length === 0 ) 1530 { 1531 return false;
1532 } 1533 1534 // Build an option lookup by ID that correlates to the specific radio <input> element for that option 1535 this.option_lookup = new Array(); 1536 1537 for ( i = 0, i_len = this.radios.length; i < i_len; i++ ) 1538 { 1539 if ( ( this.radios[ i ].value.length === 0 ) && ( this.empty_radio === null ) ) 1540 { 1541 this.empty_radio = this.radios[ i ]; 1542 } 1543 else 1544 { 1545 for ( j = 0, j_len = this.options.length; j < j_len; j++ ) 1546 { 1547 if ( this.radios[ i ].value == this.options[ j ].code ) 1548 { 1549 this.option_lookup[ this.options[ j ].id ] = this.radios[ i ]; 1550 } 1551 } 1552 } 1553 } 1554 1555 for ( i = 0, i_len = this.radios.length; i < i_len; i++ ) 1556 { 1557 AddEvent( this.radios[ i ], 'click', function() 1558 { 1559 self.machine.Attribute_Changed( self ); 1560 return true; 1561 } ); 1562 } 1563 1564 return true; 1565} 1566 1567AttributeMachine_Radio.prototype.Disable = function() 1568{ 1569 var i; 1570 1571 for ( i = 0; i < this.radios.length; i++ ) 1572 { 1573 this.radios[ i ].disabled = true; 1574 this.radios[ i ].checked = false; 1575 } 1576 1577 if ( this.empty_radio ) 1578 { 1579 this.empty_radio.disabled = false; 1580 this.empty_radio.checked = true; 1581 } 1582} 1583 1584AttributeMachine_Radio.prototype.Enable = function() 1585{ 1586 var i; 1587 1588 for ( i = 0; i < this.radios.length; i++ ) 1589 { 1590 this.radios[ i ].disabled = false; 1591 } 1592} 1593 1594AttributeMachine_Radio.prototype.Cull = function( possible_option_lookup, selected_id ) 1595{ 1596 var i; 1597 1598 this.Enable(); 1599 1600 for ( i = 0; i < this.options.length; i++ ) 1601 { 1602 if ( !possible_option_lookup[ this.options[ i ].id ] ) 1603 { 1604 this.option_lookup[ this.options[ i ].id ].disabled = true; 1605 } 1606 } 1607 1608 if ( selected_id ) this.option_lookup[ selected_id ].checked = true; 1609 else if ( this.empty_radio ) this.empty_radio.checked = true; 1610 else 1611 { 1612 for ( i in this.option_lookup ) 1613 { 1614 this.option_lookup[ i ].checked = false; 1615 } 1616 1617 if ( this.template_attribute ) 1618 { 1619 if ( this.template_attribute.required ) return false; 1620 } 1621 else if ( this.attribute.required ) return false; 1622 } 1623 1624 return true; 1625} 1626 1627AttributeMachine_Radio.prototype.Selected_Option_ID = function() 1628{ 1629 var i, j; 1630 1631 for ( i = 0; i < this.radios.length; i++ ) 1632 { 1633 if ( this.radios[ i ].checked && !this.radios[ i ].disabled ) 1634 { 1635 for ( j = 0; j < this.options.length; j++ ) 1636 { 1637 if ( this.options[ j ].code == this.radios[ i ].value ) 1638 { 1639 return this.options[ j ].id; 1640 } 1641 } 1642 } 1643 } 1644 1645 return null; 1646} 1647 1648// AttributeMachine_Select 1649/////////////////////////////////////////////////////////////////// 1650 1651function AttributeMachine_Select( machine, attribute, template_attribute ) 1652{ 1653 this.machine = machine; 1654 this.attribute = attribute; 1655 this.template_attribute = template_attribute; 1656 this.options = template_attribute ? template_attribute.options : attribute.options; 1657 this.select = null; 1658 this.option_lookup = null; 1659 this.empty_option = null; 1660} 1661 1662AttributeMachine_Select.prototype.Initialize = function( form, elements ) 1663{ 1664 var self = this; 1665 var i, j, i_len, j_len; 1666 1667 this.select = null; 1668 1669 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1670 { 1671 if ( elements[ i ].nodeName.toLowerCase() !== 'select' ) continue; 1672 if ( elements[ i ].type.toLowerCase() !== 'select-one' ) continue; 1673 1674 this.select = elements[ i ]; 1675 break; 1676 } 1677 1678 if ( this.select == null ) 1679 { 1680 return false; 1681 } 1682 1683 // Build an option lookup by ID that correlates to the specific <option> element for that option 1684 this.option_lookup = new Array(); 1685 1686 for ( i = 0, i_len = this.select.options.length; i < i_len; i++ ) 1687 { 1688 if ( this.select.options[ i ].value == '' ) 1689 { 1690 this.empty_option = this.select.options[ i ]; 1691 continue; 1692 } 1693 1694 for ( j = 0, j_len = this.options.length; j < j_len; j++ ) 1695 { 1696 if ( this.select.options[ i ].value == this.options[ j ].code ) 1697 { 1698 this.option_lookup[ this.options[ j ].id ] = this.select.options[ i ]; 1699 } 1700 } 1701 } 1702 1703 AddEvent( this.select, 'change', function() 1704 { 1705 self.machine.Attribute_Changed( self ); 1706 return true; 1707 } ); 1708 1709 return true; 1710} 1711 1712AttributeMachine_Select.prototype.Initialize_NonInventory = function( form, elements ) 1713{ 1714 var i, i_len; 1715 1716 for ( i = 0, i_len = elements.length; i < i_len; i++ ) 1717 { 1718 if ( elements[ i ].nodeName.toLowerCase() !== 'select' ) continue; 1719 if ( elements[ i ].type.toLowerCase() !== 'select-one' ) continue; 1720 1721 this.select = elements[ i ]; 1722 break; 1723 } 1724} 1725 1726AttributeMachine_Select.prototype.Disable = function() 1727{ 1728 this.select.disabled = true; 1729} 1730 1731AttributeMachine_Select.prototype.Enable = function() 1732{ 1733 this.select.disabled = false;
1734} 1735 1736AttributeMachine_Select.prototype.Cull = function( possible_option_lookup, selected_id ) 1737{ 1738 var i, option_count, selected_index; 1739 1740 this.select.options.length = 0; 1741 option_count = 0; 1742 selected_index = 0; 1743 1744 if ( this.empty_option ) 1745 { 1746 this.select.options[ option_count++ ] = this.empty_option; 1747 } 1748 1749 for ( i = 0; i < this.options.length; i++ ) 1750 { 1751 if ( possible_option_lookup[ this.options[ i ].id ] ) 1752 { 1753 if ( this.options[ i ].id == selected_id ) 1754 { 1755 selected_index = option_count; 1756 } 1757 1758 this.select.options[ option_count++ ] = this.option_lookup[ this.options[ i ].id ]; 1759 } 1760 } 1761 1762 this.select.selectedIndex = selected_index; 1763 1764 if ( this.select.options.length ) this.Enable(); 1765 else this.Disable(); 1766 1767 return true; 1768} 1769 1770AttributeMachine_Select.prototype.Selected_Option_ID = function() 1771{ 1772 var i; 1773 var selected_code; 1774 1775 if ( this.select.disabled || 1776 this.select.selectedIndex < 0 ) 1777 { 1778 return null; 1779 } 1780 1781 selected_code = this.select.options[ this.select.selectedIndex ].value; 1782 1783 for ( i = 0; i < this.options.length; i++ ) 1784 { 1785 if ( this.options[ i ].code == selected_code ) 1786 { 1787 return this.options[ i ].id; 1788 } 1789 } 1790 1791 return null; 1792} 1793 1794// AttributeMachine Swatches 1795/////////////////////////////////////////////////////////////////// 1796 1797AttributeMachine.prototype.oninitializeswatches = function( attributes, possible ) 1798{ 1799 this.Initialize_Swatches( attributes, possible ); 1800} 1801 1802AttributeMachine.prototype.onswatchclick = function( input, attribute, option ) 1803{ 1804 this.Swatch_Click( input, attribute, option ); 1805} 1806 1807AttributeMachine.prototype.Initialize_Swatches = function( attributes, possible ) 1808{ 1809 var self = this; 1810 var i, j; 1811 var possible_lookup; 1812 var attribute, template_attribute, current, swatch, attr_ul, attr_swatch; 1813 1814 if ( !this.Lookup_Attribute_Form() ) 1815 { 1816 return; 1817 } 1818 1819 this.swatch_attributes = [] 1820 1821 for ( i = 0; i < attributes.length; i++ ) 1822 { 1823 if ( attributes[ i ].type === 'template' ) 1824 { 1825 for ( j = 0; j < attributes[ i ].attributes.length; j++ ) 1826 { 1827 if ( attributes[ i ].attributes[ j ].type === 'swatch-select' ) 1828 { 1829 this.swatch_attributes.push( new AttributeMachine_Select( this, attributes[ i ], attributes[ i ].attributes[ j ] ) ); 1830 this.swatch_attributes[ this.swatch_attributes.length - 1 ].Initialize_NonInventory( this.form, this.Gather_Form_ProductAttributeElements( attributes[ i ], attributes[ i ].attributes[ j ] ) ); 1831 } 1832 } 1833 } 1834 else if ( attributes[ i ].type === 'swatch-select' ) 1835 { 1836 this.swatch_attributes.push( new AttributeMachine_Select( this, attributes[ i ], null ) ); 1837 this.swatch_attributes[ this.swatch_attributes.length - 1 ].Initialize_NonInventory( this.form, this.Gather_Form_ProductAttributeElements( attributes[ i ], null ) ); 1838 } 1839 } 1840 1841 if ( this.swatch_attributes.length === 0 ) return; 1842 1843 if ( this.swatches ) this.Empty_Element( this.swatches ); 1844 1845 possible_lookup = ( possible ) ? this.Build_Possible_Lookup( possible.data.attributes ) : null; 1846 1847 for ( i = 0; i < this.swatch_attributes.length; i++ ) 1848 { 1849 attribute = this.swatch_attributes[ i ].attribute; 1850 template_attribute = this.swatch_attributes[ i ].template_attribute; 1851 1852 current = template_attribute ? template_attribute : attribute; 1853 1854 attr_swatch = this.Find_Attribute_Swatch( current ); 1855 if ( attr_swatch ) this.Empty_Element( attr_swatch ); 1856 1857 possible_sublookup = ( possible_lookup ) ? possible_lookup[ attribute.id ] : null; 1858 1859 if ( possible_sublookup ) 1860 { 1861 if ( template_attribute ) possible_sublookup = possible_sublookup[ template_attribute.id ]; 1862 else possible_sublookup = possible_sublookup[ 0 ]; 1863 } 1864 1865 attr_ul = document.createElement( 'ul' ); 1866 attr_ul.style.clear = 'both'; 1867 1868 for ( j = 0; j < current.options.length; j++ ) 1869 { 1870 if ( current.inventory && possible_sublookup ) 1871 { 1872 if ( !possible_sublookup.options[ current.options[ j ].id ] ) continue; 1873 } 1874 1875 swatch = this.Generate_Swatch( this.settings.product_code, current, current.options[ j ] ); 1876 1877 swatch.mm5_input = this.swatch_attributes[ i ]; 1878 swatch.mm5_attribute = current; 1879 swatch.mm5_option = current.options[ j ]; 1880 1881 AddEvent( swatch, 'click', function() 1882 { 1883 var node; 1884 1885 if ( this.mm5_input ) node = this; 1886 else if ( window.event ) node = window.event.srcElement; 1887 else node = null; 1888 1889 while ( node && !node.mm5_input ) 1890 { 1891 node = node.parentNode; 1892 } 1893 1894 if ( node ) self.onswatchclick( node.mm5_input, node.mm5_attribute, node.mm5_option ); 1895 } ); 1896 1897 if ( attr_swatch ) attr_ul.appendChild( swatch ); 1898 else if ( this.swatches ) attr_ul.appendChild( swatch ); 1899 } 1900 1901 if ( attr_swatch ) attr_swatch.appendChild( attr_ul ); 1902 else if ( this.swatches ) this.swatches.appendChild( attr_ul ); 1903 } 1904} 1905 1906AttributeMachine.prototype.Swatch_Click = function( input, attribute, option ) 1907{ 1908 var i 1909 1910 for ( i = 0; i < input.select.options.length; i++ ) 1911 { 1912 if ( input.select.options[ i ].value == option.code ) 1913 { 1914 input.select.selectedIndex = i; 1915 } 1916 } 1917 1918 this.Attribute_Changed( input ); 1919} 1920 1921AttributeMachine.prototype.Empty_Element = function( container ) 1922{ 1923 while( container.hasChildNodes() ) 1924 { 1925 container.removeChild( container.lastChild ); 1926 } 1927} 1928 1929AttributeMachine.prototype.Find_Attribute_Swatch = function( attribute ) 1930{ 1931 var selector = this.settings.attribute_swatch_id; 1932 1933 if ( !selector ) 1934 { 1935 return null; 1936 } 1937 1938 selector = selector.replace( '%attribute_id%', attribute.id ); 1939 1940 return this.getElementById( selector ); 1941}
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.