1// LIVEOPENCART: Related Options 2 3(function ($) { $.fn.liveopencart_RelatedOptions = function(p_params){ 4 5 $this = this; 6 7 var inst = { 8 9 each : function(collection, fn){ 10 for ( var i_item in collection ) { 11 if ( !collection.hasOwnProperty(i_item) ) continue; 12 if ( fn(collection[i_item], i_item) === false ) { 13 return; 14 } 15 } 16 }, 17 18 getSetting : function(p_setting_name, p_default) { 19 if ( typeof(inst.ro_settings[p_setting_name]) != 'undefined' ) { 20 if ( inst.ro_settings[p_setting_name] !== '0' ) { 21 return inst.ro_settings[p_setting_name]; 22 } else { 23 return 0; 24 } 25 } else { 26 return p_default; 27 } 28 }, 29 30 bind : function(trigger_name, event_function) { 31 inst.parentBlock.on(trigger_name, event_function); 32 }, 33 trigger : function(trigger_name, values) { 34 inst.getBlockOfOptions().trigger(trigger_name, values); 35 }, 36 37 initRO : function(ro_init_cnt) { 38 39 if ( !inst.ro_data || inst.ro_data == {} || inst.ro_data == [] ) { 40 return; // no related options 41 } 42 43 // add specifically displayed options (quantity input/select per option value) 44 inst.getOptionElement('[data-quantity-per-option][data-product-option-id]').each(function(){ 45 var product_option_id = $(this).attr('data-product-option-id'); 46 if ( $.inArray(product_option_id, inst.ro_product_options) !=-1 ) { 47 inst.input_quantity_per_options.push( product_option_id ); 48 } 49 }); 50 51 // assign for global variable 52 inst.options_step_by_step = inst.getOptionsAsSteps(); 53 54 if ( !inst.options_step_by_step.length && !ro_init_cnt ) { 55 // in some themes page options may be not available on this stage, so recall init on document.ready 56 $(document).ready( function() { 57 inst.initRO(1); 58 }); 59 return; 60 } 61 62 for (var i=0; i < inst.options_step_by_step.length; i++) { 63 inst.all_values_of_options[inst.options_step_by_step[i]] = inst.getAllValuesOfProductOption(inst.options_step_by_step[i]); 64 } 65 66 inst.getOptionElement('select[name^="'+inst.option_prefix+'"]').change(function(){ 67 inst.controlAccessToValuesOfAllOptions(); 68 }); 69 70 inst.getOptionElement('input[type=radio][name^="'+inst.option_prefix+'"]').change(function(){ 71 inst.controlAccessToValuesOfAllOptions(); 72 }); 73 74 inst.controlAccessToValuesOfAllOptions(); 75 76 $(document).ready( function() { 77 78 if ( typeof(inst.ros_to_select) != 'undefined' && inst.ros_to_select && inst.ros_to_select.length) { 79 var ro_id = false; 80 inst.each(inst.ros_to_select, function(current_ro_id){ 81 ro_id = current_ro_id; 82 inst.setSelectedCombination(ro_id, true); // without limitaions 83 }); 84 if (ro_id) { 85 inst.setSelectedCombination(ro_id); /// with limitations 86 } 87 } else { 88 89 // if there's filter and it's equal to related options model - this related options combination should be selected 90 if (!inst.setSelectedCombinationByModel(inst.filter_name)) { // if there's not filter relevant to related options 91 // if any value is selected - all values should be reselected (to be relevant to available related options) 92 if ( inst.poip_ov ) { 93 setTimeout(function () { 94 inst.makeFirstValuesSelected(); // ro_use_first_values(); 95 }, 1); // if any combination is selected (may be other extension), check it and change if it's not relevant to available related options 96 } 97 } 98 inst.controlAccessToValuesOfAllOptions(); 99 100 inst.initialAutoSelect(); 101 102 } 103 104 }); 105 106 inst.trigger('init_after.ro'); 107 108 }, 109 110 // correct auto selection for options some values already selected 111 makeFirstValuesSelected : function(set_anyway) { // ro_use_first_values 112 113 var options_values = inst.getOptionValues([]); 114 115 var selected_options = []; 116 var has_selected = false; 117 inst.each(options_values, function(pov_id, po_id){ 118 if (pov_id) { 119 has_selected = true; 120 selected_options.push(po_id); 121 } 122 }); 123 124 if (has_selected || set_anyway) { 125 126 inst.each(inst.options_step_by_step, function(product_option_id){ 127 128 if ( $.inArray(product_option_id, inst.ro_product_options) != -1 ) { 129 130 var product_option_value_id = false;
131 132 if ( inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"]').length) { 133 product_option_value_id = inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"] option[value][value!=""]:not(:disabled)').val(); 134 } else if ( inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+product_option_id+']"]').length > 0) { 135 product_option_value_id = inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+product_option_id+']"]:not(:disabled):first').val(); 136 } 137 138 if (product_option_value_id && ($.inArray(product_option_id, selected_options) == -1 || set_anyway) ) { 139 // if (product_option_value_id && ($.inArray(product_option_id, selected_options) != -1 || set_anyway) ) { 140 inst.setOptionValue(product_option_id, product_option_value_id); 141 inst.controlAccessToValuesOfAllOptions(); 142 } 143 } 144 }); 145 } 146 }, 147 148 setOptionValue : function(product_option_id, product_option_value_id) { 149 150 var $touched_elems = ''; 151 if ( inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"]').length > 0) { 152 $touched_elems = inst.getOptionElement('[name="'+inst.option_prefix+'['+product_option_id+']"]').val(product_option_value_id); 153 154 } else if ( inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+product_option_id+']"]').length > 0) { 155 var radio_elems = inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+product_option_id+']"]'); 156 radio_elems.prop('checked', false); 157 158 if ( product_option_value_id ) { 159 var radio_elem = inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+product_option_id+']"][value='+product_option_value_id+']'); 160 radio_elem.prop('checked', true); 161 } 162 163 $touched_elems = radio_elems; 164 } 165 166 inst.trigger('setOptionValue_after.ro', [product_option_id, product_option_value_id, $touched_elems]); 167 168 // Product Option Image PRO compatibility 169 if ( typeof(poipExternalOptionChange)=='function' ) { 170 poipExternalOptionChange(); 171 } 172 if ( typeof(poip_product)!='undefined' && typeof(poip_product.externalOptionChange) == 'function' ) { 173 poip_product.externalOptionChange(); 174 } 175 176 }, 177 178 getBlockOfOptions : function() { 179 return inst.parentBlock; 180 }, 181 182 getOptionElement : function(selector) { 183 return inst.getBlockOfOptions().find(selector); 184 }, 185 186 getProductOptionIdFromName : function(name) { 187 return name.substr(inst.option_prefix_length+1, name.lastIndexOf(']')-(inst.option_prefix_length+1) ); 188 }, 189 190 getElement : function(selector) { 191 return inst.parentBlock.find(selector); 192 }, 193 194 getQuantityInput : function(){ 195 let $quantity_input = inst.custom_getQuantityInput(); 196 if ( !$quantity_input ) { 197 $quantity_input = inst.getElement('input[type=text][name=quantity], input[type=number][name=quantity]'); 198 } 199 return $quantity_input; 200 }, 201 202 getQuantity : function(){ 203 return inst.getQuantityInput().val(); 204 }, 205 206 getValuesOfSelectOption : function(param_product_option_id) { 207 if ( $.isEmptyObject(inst.all_select_ov) ) { 208 inst.getOptionElement('select[name^="'+inst.option_prefix+'["]').each( function (si, sel_elem) { 209 var product_option_id = inst.getProductOptionIdFromName(sel_elem.name); 210 211 inst.all_select_ov[product_option_id] = []; 212 213 $.each(sel_elem.options, function (oi, op_elem) { 214 inst.all_select_ov[product_option_id].push(op_elem.value); 215 }); 216 217 } ); 218 } 219 return inst.all_select_ov[param_product_option_id]; 220 }, 221 222 getCurrentROIds : function(options_values) { 223 var ro_ids = []; 224 inst.each(inst.ro_data, function(ro_dt){ 225 226 var all_ok; 227 inst.each(ro_dt.ro, function(ro_comb, ro_id){ 228 229 all_ok = true; 230 inst.each(ro_comb.options, function(pov_id, po_id){ 231 if ( !(po_id in options_values && options_values[po_id]==pov_id) ) { 232 all_ok = false; 233 } 234 }); 235 if (all_ok) ro_ids.push(ro_id); 236 }); 237 }); 238 return ro_ids; 239 }, 240 241 arrayIntersection : function(arr1, arr2) { 242 var new_arr = []; 243 inst.each(arr1, function(val1){ 244 //for (var i in arr1) { 245 if ($.inArray(val1, arr2) != -1) { 246 new_arr.push(val1); 247 } 248 }); 249 return new_arr; 250 }, 251 252 arrayCopy : function(arr) { 253 var new_arr = []; 254 inst.each(arr, function(val, i){ 255 //for (var i in arr) { 256 if ( $.isArray(val) ) { 257 new_arr[i] = inst.arrayCopy(val); 258 } else { 259 new_arr[i] = val; 260 } 261 }); 262 return new_arr; 263 }, 264 265 getAllValuesOfProductOption : function(product_option_id) { 266 var values = []; 267 if ( inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"]').length) { 268 var select_options = inst.getValuesOfSelectOption(product_option_id); 269 for (var i=0;i<select_options.length;i++) { 270 if (select_options[i]) { 271 values.push(select_options[i]); 272 } 273 } 274 } else if ( inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+product_option_id+']"]').length) { 275 inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+product_option_id+']"]').each(function(){ 276 values.push($(this).val()); 277 }); 278 } 279 // add specifically displayed options (quantity input/select per option value) 280 if ( $.inArray(product_option_id, inst.input_quantity_per_options) != -1 ) { 281 $('[name^="quantity_per_option['+product_option_id+']["]').each(function(){ 282 var product_option_value_id = $(this).attr('data-value'); 283 if ( product_option_value_id ) { 284 values.push(product_option_value_id); 285 } 286 }); 287 } 288 return values; 289 }, 290 291 getOptionsWithDirectRelations : function(prodict_option_id) { 292 293 if ( inst.linked_options_cache[prodict_option_id] ) { 294 return inst.linked_options_cache[prodict_option_id]; 295 } else { 296 297 var linked_options = []; 298 inst.each(inst.ro_data, function(ro_dt){ 299 300 if ( $.inArray(prodict_option_id, ro_dt.options_ids)!=-1 ) { 301 inst.each(ro_dt.options_ids, function(current_po_id){ 302 if ( current_po_id != prodict_option_id && $.inArray(current_po_id, linked_options) ) { 303 linked_options.push(current_po_id); 304 } 305 }); 306 } 307 }); 308 inst.linked_options_cache[prodict_option_id] = linked_options; 309 return linked_options; 310 } 311 }, 312 313 // get available options values 314 // option_id - (product_option_id) 315 // param_options_values - current options values (selected) - only for related options 316 // param_skip_ropv_ids - don't make values addition for this related options combinations 317 getAccessibleOptionValues : function(option_id, param_options_values, param_skip_options) { 318 319 // make copies od arrays 320 var options_values = inst.arrayCopy(param_options_values); 321 var skip_options = inst.arrayCopy(param_skip_options); 322 skip_options.push(option_id); 323 324 var linked_options = inst.getOptionsWithDirectRelations(option_id); 325 326 inst.each(linked_options, function(current_option_id){ 327 if ( options_values[current_option_id] && !options_values[current_option_id].length && current_option_id != option_id) { 328 if ( $.inArray(current_option_id, skip_options) == -1 ) { 329 options_values[current_option_id] = inst.getAccessibleOptionValues(current_option_id, options_values, skip_options); 330 } 331 } 332 }); 333 334 var common_accessible_values = false;
335 336 var possible_current_option_values = inst.all_values_of_options[option_id]; 337 338 inst.each(inst.ro_data, function(ro_dt){ 339 340 if ($.inArray(option_id, ro_dt.options_ids)==-1) { 341 return; 342 } 343 344 var accessible_values = []; 345 346 var ro_combs = ro_dt.ro; 347 348 var options_for_check = []; // optimization 349 inst.each(options_values, function(current_pov_id, current_option_id){ 350 351 if (current_option_id != option_id && options_values[current_option_id].length && $.inArray(current_option_id, skip_options) == -1 && $.inArray(current_option_id, ro_dt.options_ids)!=-1) { 352 options_for_check.push(current_option_id); 353 } 354 }); 355 356 if (!options_for_check.length) { 357 if (ro_dt.options_ids.length == 1) { // combination contains only one option (this option) 358 inst.each(ro_combs, function(ro_comb){ 359 if ( ro_comb.options[option_id] && $.inArray(ro_comb.options[option_id], accessible_values) == -1 ) { 360 accessible_values.push(ro_comb.options[option_id]); 361 } 362 }); 363 } else { 364 accessible_values = inst.arrayCopy(possible_current_option_values); 365 } 366 } else { 367 inst.each(ro_combs, function(ro_comb){ 368 369 all_ok = true; 370 371 for (var j =0; j < options_for_check.length; j++) { 372 var current_option_id = options_for_check[j]; 373 if ( $.inArray(ro_comb.options[current_option_id], options_values[current_option_id]) == -1 ) { 374 all_ok = false; 375 } 376 if (!all_ok) { 377 break; 378 } 379 } 380 381 if (all_ok && ($.inArray(ro_comb.options[option_id], accessible_values) == -1 )) { 382 accessible_values.push(ro_comb.options[option_id]); 383 if (possible_current_option_values.length == accessible_values.length) { // optimization 384 return false; 385 } 386 } 387 }); 388 } 389 390 if (common_accessible_values === false) { 391 common_accessible_values = accessible_values; 392 } else { 393 common_accessible_values = inst.arrayIntersection(common_accessible_values, accessible_values); 394 } 395 }); 396 return common_accessible_values; 397 }, 398 399 // only for options with values 400 // returns array of accessible values 401 controlAccessToValuesOfOption : function(param_options_values, option_id) { 402 403 var options_values = []; 404 inst.each(param_options_values, function(pov_id, product_option_id){ 405 options_values[product_option_id] = []; 406 if (param_options_values[product_option_id]) { 407 options_values[product_option_id].push(param_options_values[product_option_id]); 408 } 409 }); 410 411 var skip_ropv_ids = []; 412 var accessible_values = inst.getAccessibleOptionValues(option_id, options_values, skip_ropv_ids); 413 414 inst.setAccessibleOptionValues(option_id, accessible_values); 415 416 return accessible_values; 417 }, 418 419 toggleOptionElement : function(option_id, toggle_flag) { 420 421 inst.getOptionElement('#input-option'+option_id).parent().toggle(toggle_flag); 422 if ( inst.getOptionElement('#input-option'+option_id).parent().is('div.select') && inst.getOptionElement('#input-option'+option_id).parent().parent().is('div.form-group') ) { // additional compatibility (fastor theme or custom modification) 423 inst.getOptionElement('#input-option'+option_id).parent().parent().toggle(toggle_flag); 424 } 425 inst.getOptionElement('label[for="input-option'+option_id+'"]').toggle(toggle_flag); 426 427 // magazin theme comp 428 if ( inst.getOptionElement('#input-option'+option_id).parent().is('.fancy-select') ) { 429 inst.getOptionElement('#input-option'+option_id).parent().parent().toggle(toggle_flag); 430 } 431 432 inst.trigger( 'toggleOptionElement_after.ro', [option_id, toggle_flag] ); 433 }, 434 435 optionIsAccessible : function(option_id) { 436 if ( inst.getOptionElement('select[name="'+inst.option_prefix+'['+option_id+']"]').length) { 437 return inst.getOptionElement('select[name="'+inst.option_prefix+'['+option_id+']"] option[value][value!=""]:not(:disabled)').length ? true : false; 438 } else if ( inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+option_id+']"]').length) { 439 return inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+option_id+']"]:not(:disabled)').length ? true : false;
440 } else if ( inst.getOptionElement('input[name^="quantity_per_option['+option_id+']["]').length) { 441 return inst.getOptionElement('input[name^="quantity_per_option['+option_id+']["]:not(:disabled)').length ? true : false; 442 } 443 }, 444 445 hideInaccessibleOptionIfNeeded : function(option_id) { 446 if (inst.ro_settings && inst.ro_settings.hide_option) { 447 inst.toggleOptionElement(option_id, inst.optionIsAccessible(option_id)); 448 } 449 }, 450 451 makeInaccessibleOptionsNotRequired : function(option_id) { 452 if (inst.ro_settings && inst.ro_settings.unavailable_not_required) { 453 var current_ids = []; 454 if ($('#ro_not_required').length) { 455 current_ids = $('#ro_not_required').val().split(','); 456 } else { 457 $('#product').append('<input type="hidden" name="ro_not_required" id="ro_not_required" value="">'); 458 } 459 var new_ids = []; 460 inst.each(current_ids, function(current_option_id){ 461 //for (var i in current_ids) { 462 if (current_option_id != option_id) { 463 new_ids.push(current_option_id); 464 } 465 }); 466 if (!inst.optionIsAccessible(option_id)) { 467 new_ids.push(option_id); 468 } 469 $('#ro_not_required').val( new_ids.toString()); 470 } 471 }, 472 473 setAccessibleOptionValues : function(option_id, accessible_values) { 474 475 var current_value = ( inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+option_id+']"]:checked').val() || inst.getOptionElement('select[name="'+inst.option_prefix+'['+option_id+']"]').val()); 476 477 if ( inst.getOptionElement('select[name="'+inst.option_prefix+'['+option_id+']"]').length) { 478 479 if (current_value && $.inArray(current_value, accessible_values)==-1) { 480 inst.getOptionElement('select[name="'+inst.option_prefix+'['+option_id+']"]').val(""); 481 } 482 483 if (inst.hide_inaccessible) { 484 485 let select_options = inst.getValuesOfSelectOption(option_id); 486 //select_options = inst.all_select_ov[inst.option_prefix+"["+option_id+"]"]; 487 for (let i=0;i<select_options.length;i++) { 488 if (select_options[i]) { 489 option_value_disabled = ($.inArray(select_options[i],accessible_values) == -1); 490 // hiding options for IE 491 inst.getOptionElement('select[name="'+inst.option_prefix+'['+option_id+']"]').toggleOption(select_options[i], !option_value_disabled); 492 } 493 } 494 495 } else { 496 497 let select_options = inst.getOptionElement('select[name="'+inst.option_prefix+'['+option_id+']"]')[0].options; 498 for (let i=0;i<select_options.length;i++) { 499 if (select_options[i].value) { 500 option_value_disabled = ($.inArray(select_options[i].value,accessible_values) == -1); 501 select_options[i].disabled = option_value_disabled; 502 if (option_value_disabled) { 503 $(select_options[i]).addClass('ro_option_disabled'); 504 } else { 505 $(select_options[i]).removeClass('ro_option_disabled'); 506 } 507 } 508 } 509 } 510 511 inst.trigger( 'setAccessibleOptionValues_select_after.ro', [option_id, accessible_values] ); 512 513 } else if ( inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+option_id+']"]').length) { 514 515 if (current_value && $.inArray(current_value, accessible_values)==-1) { 516 517 var elem_to_uncheck = inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+option_id+']"]:checked'); 518 519 if ( elem_to_uncheck.length ) { 520 elem_to_uncheck.prop('checked', false); 521 } 522 523 inst.trigger( 'setAccessibleOptionValues_radioUncheck_after.ro', [elem_to_uncheck] ); 524 } 525 526 radio_options = inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+option_id+']"]'); 527 for (var i=0;i<radio_options.length;i++) { 528 529 option_value_disabled = ($.inArray(radio_options[i].value,accessible_values) == -1); 530 531 $(radio_options[i]).prop('disabled', option_value_disabled); // hidden should be disabled too 532 533 if (inst.hide_inaccessible) { 534 535 if ( typeof(inst.custom_radioToggle) != 'undefined' && inst.custom_radioToggle( $(radio_options[i]), option_value_disabled ) ) { 536 // do nothing 537 } else { 538 $(radio_options[i]).parent().parent().toggle(!option_value_disabled); 539 $(radio_options[i]).toggle(!option_value_disabled); 540 } 541 542 // style change for padding change 543 if ( typeof(inst.custom_radioChangeClass) != 'undefined' && inst.custom_radioChangeClass() ) { 544 if (option_value_disabled) { 545 if ($(radio_options[i]).parent().parent().hasClass('radio')) { 546 $(radio_options[i]).parent().parent().removeClass('radio'); 547 $(radio_options[i]).parent().parent().addClass('_radio_ro'); 548 } 549 } else { 550 if ($(radio_options[i]).parent().parent().hasClass('_radio_ro')) { 551 $(radio_options[i]).parent().parent().removeClass('_radio_ro'); 552 $(radio_options[i]).parent().parent().addClass('radio'); 553 } 554 } 555 } 556 557 inst.trigger( 'setAccessibleOptionValues_radioToggle_after.ro', [ option_id, $(radio_options[i]) ] ); 558 559 } else { 560 561 if ( typeof(inst.custom_radioEnableDisable) != 'undefined' && inst.custom_radioEnableDisable( $(radio_options[i]), option_value_disabled ) ) { 562 // do nothing 563 } else { 564 565 if (option_value_disabled) { 566 $(radio_options[i]).parent().fadeTo("fast", 0.1); 567 } else { 568 $(radio_options[i]).parent().fadeTo("fast", 1); 569 } 570 571 } 572 573 inst.trigger( 'setAccessibleOptionValues_radioEnableDisable_after.ro', [ option_id, $(radio_options[i]) ] ); 574 575 } 576 } 577 578 } else if ( $.inArray(option_id, inst.input_quantity_per_options) != -1 ) { // for specifically displayed options (quantity input/select per option value) 579 580 inst.getOptionElement('[name^="quantity_per_option['+option_id+']["]').each(function(){ 581 var $qpo_input = $(this); 582 var product_option_value_id = qpo_getPOVIdByName( $qpo_input.attr('name') ); 583 //var product_option_value_id = $qpo_input.attr('data-value'); 584 if ( product_option_value_id ) { 585 option_value_disabled = ( $.inArray(product_option_value_id, accessible_values) == -1 ); 586 if ( option_value_disabled ) { 587 $qpo_input.val(''); 588 } else if ( $qpo_input.prop('disabled') ) { // re-enable the input - place default values 589 $qpo_input.val( $qpo_input.attr('data-default-value' || '0') ); 590 } 591 $qpo_input.prop('disabled', option_value_disabled); 592 var $option_value_container = $qpo_input.closest('tr'); 593 if ( !$option_value_container.length ) { 594 $option_value_container = $qpo_input.closest('div'); 595 } 596 if (inst.hide_inaccessible) { 597 $option_value_container.toggle(!option_value_disabled); 598 } else { 599 if ( option_value_disabled ) { 600 $option_value_container.fadeTo("fast", 0.1); 601 } else { 602 $option_value_container.fadeTo("fast", 1); 603 } 604 } 605 } 606 }); 607 608 } 609 610 inst.hideInaccessibleOptionIfNeeded(option_id); 611 inst.makeInaccessibleOptionsNotRequired(option_id); 612 }, 613 614 getOptionValues : function() { 615 616 var options_values = {}; 617 618 inst.getOptionElement('select[name^="'+inst.option_prefix+'["], input[type=radio][name^="'+inst.option_prefix+'["]').each(function(){ 619 option_id = inst.getProductOptionIdFromName( $(this).attr('name') ); 620 621 if ($.inArray(option_id, inst.ro_product_options) != -1) { 622 623 if ( typeof(options_values[option_id]) == 'undefined' ) { 624 options_values[option_id] = 0; 625 } 626 627 if ( $(this).find('option[value]').length ) { // select 628 options_values[option_id] = $(this).val(); 629 } else { // radio 630 if ( $(this).is(':checked') ) { 631 options_values[option_id] = $(this).val(); 632 } 633 } 634 635 } 636 }); 637 638 // add specifically displayed options (quantity input/select per option value) 639 inst.each(inst.input_quantity_per_options, function(qpo_product_option_id){ 640 //for (var i_input_quantity_per_options in inst.input_quantity_per_options) { 641 //if ( !inst.input_quantity_per_options.hasOwnProperty(i_input_quantity_per_options) ) continue; 642 //var product_option_id = qpo_product_option_id; 643 644 options_values[qpo_product_option_id] = 0; 645 //} 646 }); 647 648 return options_values; 649 }, 650
651 getSelectedOptionValues : function() { 652 let selected_options = {}; 653 inst.each(inst.getOptionValues(), function(pov_id, po_id){ 654 if ( pov_id ) { 655 selected_options[po_id] = pov_id; 656 } 657 }); 658 return selected_options; 659 }, 660 661 hasSelectedOptions : function() { 662 return Object.keys( inst.getSelectedOptionValues() ).length; 663 }, 664 665 setSelectedCombination : function(ro_id, skip_access) { 666 667 var selected_povs = []; 668 if (inst.ro_data) { 669 inst.each(inst.ro_data, function(ro_dt){ 670 let ro_combs = ro_dt.ro; 671 if ( ro_combs[ro_id] ) { 672 inst.each(ro_combs[ro_id].options, function(pov_id, product_option_id){ 673 inst.setOptionValue(product_option_id, ro_combs[ro_id].options[product_option_id]); 674 selected_povs.push(ro_combs[ro_id].options[product_option_id]); 675 }); 676 677 return false; 678 } 679 }); 680 } 681 682 // access should be checked also for step by step because there may be selects with removed options 683 if ( typeof(skip_access) == 'undefined' || !skip_access || (inst.step_by_step && inst.hide_inaccessible) ) { 684 685 inst.controlAccessToValuesOfAllOptions(); 686 687 inst.trigger('setSelectedCombination_withAccessControl_after.ro'); 688 689 } 690 691 /* 692 // poip compatibility 693 if ( selected_povs.length && typeof(poip_images_by_options) != 'undefined' && typeof(poip_option_value_selected) == 'function' ) { 694 for ( var i in selected_povs ) { 695 if ( !selected_povs.hasOwnProperty(i) ) continue; 696 697 if ( typeof(poip_images_by_options[selected_povs[i]]) != 'undefined' && poip_images_by_options[selected_povs[i]] && poip_images_by_options[selected_povs[i]].length ) { 698 699 var elem_to_run_poip = inst.getOptionElement('select[name^="'+inst.option_prefix+'["] option, input:radio[name^="'+inst.option_prefix+'["]').filter('[value="'+selected_povs[i]+'"]'); 700 if ( elem_to_run_poip.length ) { 701 poip_option_value_selected( elem_to_run_poip.is('option') ? elem_to_run_poip.parent()[0] : elem_to_run_poip[0]); 702 break; 703 } 704 } 705 } 706 } 707 708 // live price compatibility 709 if ( typeof(liveprice_recalc) == 'function' ) { 710 liveprice_recalc(100); 711 } 712 */ 713 inst.executeFunctionsFromOtherExtensionsOnOptionChange(); 714 715 }, 716 717 executeFunctionsFromOtherExtensionsOnOptionChange : function() { 718 719 // Parent-child options - compatibility 720 if ( typeof(pcop_check_visibility) == 'function' ) { 721 pcop_check_visibility(); 722 } 723 724 // old Product Option Image PRO compatibility 725 if ( typeof(poipExternalOptionChange)=='function' ) { 726 poipExternalOptionChange(); 727 } 728 // new Product Option Image PRO compatibility 729 if ( typeof(poip_product)!='undefined' && typeof(poip_product.externalOptionChange) == 'function' ) { 730 poip_product.externalOptionChange(); 731 } 732 733 // Live Price OLD 734 if ( typeof(liveprice_recalc) == 'function' ) { 735 liveprice_recalc(100); 736 } 737 738 // Live Price NEW 739 if ( window.liveopencart && window.liveopencart.live_price_instances ) { 740 var lp_instances = window.liveopencart.live_price_instances; 741 if ( Array.isArray(lp_instances) && lp_instances.length ) { 742 inst.each(lp_instances, function(lp_instance){ 743 //for ( var i_lp_instances in lp_instances ) { 744 //if ( !lp_instances.hasOwnProperty(i_lp_instances) ) continue; 745 //var lp_instance = lp_instances[i_lp_instances]; 746 lp_instance.updatePrice(100); 747 }); 748 } 749 } 750 751 }, 752 753 setSelectedCombinationByModel : function(model) { 754 if (model && inst.ro_data) { 755 inst.each(inst.ro_data, function(ro_dt){ 756 inst.each(ro_dt.ro, function(ro_comb){ 757 if (ro_comb.model && ro_comb.model.toLowerCase() == model.toLowerCase()) { 758 inst.setSelectedCombination(ro_id); 759 return true; 760 } 761 }); 762 }); 763 } 764 return false; 765 }, 766 767 // for step-by-step way 768 getOptionsAsSteps : function() { 769 var options_steps = []; 770 771 inst.getOptionElement('input[name^="'+inst.option_prefix+'["], select[name^="'+inst.option_prefix+'["]').each(function(){ 772 773 let product_option_id = inst.getProductOptionIdFromName( inst.getOptionElement(this).attr('name')); 774 775 if ($.inArray(product_option_id, inst.ro_product_options) != -1) { 776 if ($.inArray(product_option_id, options_steps) == -1) { 777 options_steps.push(product_option_id); 778 } 779 } 780 781 }); 782 783 // add specifically displayed options (quantity input/select per option value) 784 inst.each(inst.input_quantity_per_options, function(qpo_product_option_id){ 785 //for (var i_input_quantity_per_options in inst.input_quantity_per_options) { 786 // if ( !inst.input_quantity_per_options.hasOwnProperty(i_input_quantity_per_options) ) continue; 787 // let product_option_id = inst.input_quantity_per_options[i_input_quantity_per_options]; 788 options_steps.push(qpo_product_option_id); 789 }); 790 791 return options_steps; 792 }, 793 794 controlAccessToValuesOfAllOptions : function() { 795 796 if (!inst.ro_data || !Object.keys(inst.ro_data).length) return; 797 798 if (inst.step_by_step) { 799 800 var prev_options_values = {}; 801 var prev_options = []; 802 var option_accessible_values = []; 803 var one_prev_value_is_not_set = false;
804 805 for (let i=0;i<inst.options_step_by_step.length;i++) { 806 807 if (i == 0) { 808 // all values existent in combinations of related options should be available 809 inst.controlAccessToValuesOfOption([], inst.options_step_by_step[i]); 810 } else { 811 // if previous option value is selected or if previous option has no available values 812 if (!one_prev_value_is_not_set) { 813 // limitaion on previous 814 option_accessible_values = inst.controlAccessToValuesOfOption(prev_options_values, inst.options_step_by_step[i]); 815 816 } else { 817 // disable all 818 inst.setAccessibleOptionValues(inst.options_step_by_step[i], []); 819 option_accessible_values = []; 820 } 821 } 822 823 prev_options.push( ( inst.getOptionElement('input[type=radio][name="'+inst.option_prefix+'['+inst.options_step_by_step[i]+']"]:checked').val() || inst.getOptionElement('select[name="'+inst.option_prefix+'['+inst.options_step_by_step[i]+']"]').val()) ); 824 prev_options_values[inst.options_step_by_step[i]] = prev_options[prev_options.length-1]; 825 826 if ((option_accessible_values.length || i==0) && !prev_options[i] ) { // option has available values, but none of them is selected 827 one_prev_value_is_not_set = true; 828 } 829 830 } 831 832 } else { 833 834 //var options_keys = []; 835 var options_values = inst.getOptionValues(); 836 var options_keys = Object.keys(options_values); 837 838 for (let i=0;i<options_keys.length;i++) { 839 inst.controlAccessToValuesOfOption(options_values, options_keys[i]); 840 } 841 842 } 843 844 inst.checkAutoSelect(); 845 846 inst.trigger('controlAccessToValuesOfAllOptions_after.ro'); 847 848 }, 849 850 // autoselection for last available option value & first available always 851 checkAutoSelect : function() { 852 853 if (inst.auto_select_last || inst.auto_select_first_always) { 854 855 inst.each(inst.options_step_by_ste, function(product_option_id){ 856 857 if ( inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"]').length ) { 858 859 let options_elems = inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"]').find('option[value][value!=""]:not(:disabled)'); 860 861 if ( inst.auto_select_last && options_elems.length == 1 && !$(options_elems[0]).is(':selected') || ( inst.auto_select_first_always && options_elems.length && !options_elems.filter(':selected').length ) ) { 862 863 let product_option_value_id = $(options_elems[0]).val(); 864 865 inst.setOptionValue(product_option_id, product_option_value_id); 866 $(options_elems[0]).parent().change(); 867 return; 868 } 869 870 } else if ( inst.getOptionElement('input:radio[name="'+inst.option_prefix+'['+product_option_id+']"]').length ) { 871 872 //var radio_elems = inst.getOptionElement('input:radio[name="'+inst.option_prefix+'['+product_option_id+']"]:not(:disabled):visible'); 873 let radio_elems = inst.getOptionElement('input:radio[name="'+inst.option_prefix+'['+product_option_id+']"]:not(:disabled)'); 874 875 if ( inst.auto_select_last && radio_elems.length == 1 && !$(radio_elems[0]).is(':checked') || ( inst.auto_select_first_always && radio_elems.length && !radio_elems.filter(':checked').length ) ) { 876 877 let product_option_value_id = $(radio_elems[0]).val(); 878 inst.setOptionValue(product_option_id, product_option_value_id); 879 880 $(radio_elems[0]).change(); 881 return; 882 883 } 884 } 885 }); 886 } 887 }, 888 889 // autorelection for first values (initial) 890 initialAutoSelect : function() { 891 892 if (inst.ro_settings && inst.ro_settings.select_first && inst.ro_settings.select_first == 1) { 893 894 inst.each(inst.options_step_by_step, function(product_option_id){ 895 //for (var i in inst.options_step_by_step) { 896 897 if ( inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"]').length ) { 898 899 let elem = inst.getOptionElement('select[name="'+inst.option_prefix+'['+product_option_id+']"]'); 900 if ( !elem.val() ) { 901 902 let elem_option = elem.find('option[value][value!=""]:not(:disabled)'); 903 if (elem_option.length) { 904 905 inst.setOptionValue(product_option_id, elem_option.val() ); 906 907 elem.change(); 908 } 909 910 } 911 912 } else if ( inst.getOptionElement('input:radio[name="'+inst.option_prefix+'['+product_option_id+']"]').length ) { 913 914 if ( !inst.getOptionElement('input:radio[name="'+inst.option_prefix+'['+product_option_id+']"]:checked').length ) { 915 let elem = inst.getOptionElement('input:radio[name="'+inst.option_prefix+'['+product_option_id+']"]:not(:disabled):first'); 916 if (elem.length) { 917 918 inst.setOptionValue(product_option_id, elem.attr('value') ); 919 920 elem.change(); 921 922 } 923 } 924 } 925 }); 926 } 927 }, 928 929 930 }; 931 932 inst.parentBlock = this; 933 934 var params = $.extend( { 935 'ro_settings' : {}, 936 'ro_data' : false, 937 'ro_theme_name' : '', 938 'ros_to_select' : '', 939 'poip_ov' : '',
940 'filter_name' : '', 941 'option_prefix' : 'option', 942 }, p_params); 943 inst.ro_settings = params.ro_settings; 944 inst.ro_theme_name = params.ro_theme_name; 945 inst.ro_data = params.ro_data; 946 inst.ros_to_select = params.ros_to_select; 947 inst.poip_ov = params.poip_ov; 948 inst.filter_name = params.filter_name; 949 950 // settings 951 inst.hide_inaccessible = inst.getSetting('hide_inaccessible'); 952 inst.step_by_step = inst.getSetting('step_by_step'); 953 954 inst.auto_select_last = inst.getSetting('select_first') == 2; 955 inst.auto_select_first_always = inst.getSetting('select_first') == 3; 956 957 inst.option_prefix = params.option_prefix; 958 if ( inst.ro_data.length && !$('[name^="option["]').length && $('[name^="option_oc["]').length) { // 959 //if ($('#mijoshop').length && $('[name^="option_oc["]').length) { // 960 inst.option_prefix = "option_oc"; 961 } 962 inst.option_prefix_length = inst.option_prefix.length; 963 964 // data 965 inst.ro_product_options = []; 966 if ( inst.ro_data ) { 967 inst.each(inst.ro_data, function(ro_dt){ 968 //for ( var i_ro_data in inst.ro_data ) { 969 970 inst.each(ro_dt.options_ids, function(product_option_id){ 971 //for ( var i_option_ids in option_ids ) { 972 if ( $.inArray(product_option_id, inst.ro_product_options) == -1 ) { 973 inst.ro_product_options.push(product_option_id); 974 } 975 }); 976 }); 977 } 978 979 // variables 980 inst.linked_options_cache = {}; // cache 981 inst.all_select_ov = {}; // selects cache 982 inst.input_quantity_per_options = []; 983 inst.ro_stock_control_last_call = ''; 984 inst.options_types = []; 985 inst.options_step_by_step = []; 986 inst.all_values_of_options = []; 987 988 //inst.initRO(); // init should be started from outside, after assigning all additional functions/triggers 989 990 this.data('liveopencart_relatedOptions', inst); 991 992 if ( !window.liveopencart ) { 993 window.liveopencart = {}; 994 } 995 if ( !window.liveopencart.related_options_instances ) { 996 window.liveopencart.related_options_instances = []; 997 } 998 window.liveopencart.related_options_instances.push(inst); 999 1000 return inst; 1001 1002}; })(jQuery); 1003 1004 1005 1006 1007
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.