PageSourceSearch

https://www.im-machinery-asia.com.sg/catalog/view/extension/relate…iveopencart.related_options.js?v=1648610674

js im-machinery-asia.com.sg collected 2026-10-05 06:23:16 UTC 36,377 bytes, 1,007 lines download raw bytes

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.