PageSourceSearch

https://www.juodatruoba.lt/wp-content/plugins/woocommerce-product-addon/js/ppom.inputs.js?ver=34.0.9

js juodatruoba.lt collected 2026-10-04 03:03:29 UTC 18,054 bytes, 658 lines download raw bytes

1/**
2 * Frontend field bootstrapper for PPOM inputs.
3 *
4 * PHP localizes each field definition into `ppom_input_vars.ppom_inputs`; this
5 * file hydrates those definitions into live widgets on the product page. It is
6 * the bridge between rendered markup and the other frontend subsystems such as
7 * pricing, conditional logic, and file uploads.
8 *
9 * @see ppom_update_option_prices in js/price/ppom-price.js
10 * @see ppom_update_option_prices in js/price/ppom-price-v2.js
11 * @see ppom_check_conditions in js/ppom-conditions-v2.js
12 * @see ppom_setup_file_upload_input in js/file-upload.js
13 */
14
15/**
16 * Minimal shape of a localized PPOM field as consumed by the frontend scripts.
17 *
18 * PHP sends richer metadata, but these are the keys repeatedly used across the
19 * field bootstrapper, price engines, and condition/upload helpers.
20 *
21 * @typedef {{
22 *   data_name: string,
23 *   type: string,
24 *   title?: string,
25 *   field_type?: string,
26 *   input_mask?: string,
27 *   discount_type?: string,
28 *   options?: Array<Object> | string,
29 *   images?: Array<Object>,
30 *   audio?: Array<Object>
31 * }} PPOMLocalizedFieldMeta
32 */
33
34'use strict';
35
36/* global ppom_input_vars */
37
38// Runtime caches shared by bulk quantity and price-matrix widgets.
39const ppom_bulkquantity_meta = [];
40let ppom_pricematrix_discount_type = '';
41
42jQuery( function ( $ ) {
43	// Boot the product-form behaviors once WooCommerce and PPOM markup exist.
44	// Tooltip Init
45	// $('.ppom-tooltip').powerTip({
46	//     placement: 'n',
47	//     smartPlacement: true,
48	//     mouseOnToPopup: true
49	// });
50
51	// Remove Emoji from text input
52	// $('.ppom-wrapper').on('input keyup', 'input[type="text"]', function(e) {
53
54	//     const input_val = $(this).val();
55	//     const new_val = input_val.replace(/([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g, '');
56	//     $(this).val(new_val);
57	// });
58
59	// $('[data-toggle="tooltip"]').tooltip({container:'body', trigger:'hover'});
60	const wc_cart_button = jQuery( 'form.cart' ).find(
61		'button[name="add-to-cart"]'
62	);
63	const wc_cart_form = jQuery( 'form.cart' );
64
65	// Measure
66	$( '.ppom-measure' )
67		.off( 'change.ppom' )
68		.on( 'change.ppom', '.ppom-measure-unit', function ( e ) {
69			e.preventDefault();
70			// console.log($(this).text());
71
72			$( this )
73				.closest( '.ppom-measure' )
74				.find( '.ppom-measure-input' )
75				.trigger( 'change' );
76		} );
77
78	// Disable ajax add to cart
79	wc_cart_button.removeClass( 'ajax_add_to_cart' );
80
81	// Range slider updated
82	$( document )
83		.off( 'ppom_range_slider_updated.ppom' )
84		.on( 'ppom_range_slider_updated.ppom', function ( e ) {
85			// console.log(wc_product_qty);
86			$( 'form.cart' ).find( 'input[name="quantity"]' ).val( e.qty );
87			// wc_product_qty.val(e.qty);
88			ppom_update_option_prices();
89		} );
90
91	// move modals to body bottom
92	if ( $( '.ppom-modals' ).length > 0 ) {
93		$( '.ppom-modals' ).appendTo( 'body' );
94	}
95
96	ppom_init_js_for_ppom_fields( ppom_input_vars.ppom_inputs );
97
98	// Re-init ppom fields.
99	$( document ).on( 'ppom_reinit', function ( e, product_id ) {
100		if ( typeof product_id !== 'undefined' ) {
101			ppom_input_vars = ppom_get_product_data( product_id );
102		}
103
104		if (
105			null !== ppom_input_vars &&
106			typeof 'undefined' !== ppom_input_vars &&
107			ppom_input_vars.ppom_inputs
108		) {
109			ppom_init_js_for_ppom_fields( ppom_input_vars.ppom_inputs );
110		}
111	} );
112} );
113
114/**
115 * Hydrate each localized field definition with the JS behavior its type needs.
116 *
117 * @param {PPOMLocalizedFieldMeta[]} ppom_fields
118 * @return {void}
119 */
120function ppom_init_js_for_ppom_fields( ppom_fields ) {
121	if ( ppom_input_vars.sp_force_display_block === 'on' ) {
122		// Fixed the form button issue
123		if ( ppom_fields && ppom_fields.length > 0 ) {
124			const css_type = jQuery( 'form.cart' ).css( 'display' );
125			if ( css_type === 'flex' ) {
126				jQuery( 'form.cart' ).addClass( 'ppom-flex-controller' );
127			}
128		}
129	}
130
131	jQuery.each( ppom_fields, function ( index, input ) {
132		const InputSelector = jQuery( '#' + input.data_name );
133		if ( InputSelector.data( 'ppom-initialized' ) === true ) {
134			return;
135		}
136
137		// Applying JS on inputs
138		switch ( input.type ) {
139			// masking
140			case 'text':
141				if ( input.input_mask == undefined || input.input_mask == '' ) {
142					break;
143				}
144				InputSelector.inputmask();
145				if (
146					input.type === 'text' &&
147					input.input_mask !== '' &&
148					input.use_regex !== 'on'
149				) {
150					InputSelector.inputmask( input.input_mask );
151				}
152				break;
153
154			// only allow numbers and periods in number fields
155			case 'number':
156				InputSelector.on( 'keydown keyup keypress', function ( event ) {
157					if (
158						event.key === 'Backspace' ||
159						event.key === 'Delete' ||
160						event.key === 'Tab' ||
161						( event.ctrlKey === true && event.key === 'a' ) ||
162						( event.ctrlKey === true && event.key === 'x' ) ||
163						( event.ctrlKey === true &&
164							event.key === 'Backspace' ) ||
165						( event.which >= 48 && event.which <= 57 ) ||
166						( event.which >= 96 && event.which <= 105 ) ||
167						( event.key === '.' &&
168							$( this ).val().indexOf( '.' ) <= 1 )
169					) {
170						// think happy thoughts :-)
171					} else {
172						event.preventDefault();
173					}
174				} )
175					.off( 'focus.ppom blur.ppom' )
176					.on( 'focus.ppom blur.ppom', function () {
177						if (
178							typeof InputSelector.attr( 'max' ) !== 'undefined'
179						) {
180							if (
181								parseFloat( InputSelector.val() ) >
182								parseFloat( InputSelector.attr( 'max' ) )
183							) {
184								InputSelector.val(
185									InputSelector.attr( 'max' )
186								);
187							}
188						}
189					} );
190				break;
191
192			case 'date':
193				if ( input.jquery_dp === 'on' ) {
194					InputSelector.datepicker( 'destroy' );
195					InputSelector.datepicker( {
196						changeMonth: true,
197						changeYear: true,
198						dateFormat: input.date_formats.ppom_js_stripSlashes(),
199						yearRange: input.year_range,
200					} );
201
202					if (
203						typeof input.min_date !== 'undefined' &&
204						input.min_date.trim().length > 0
205					) {
206						const min_date = input.min_date.trim();
207						InputSelector.datepicker(
208							'option',
209							'minDate',
210							min_date
211						);
212					}
213
214					if ( typeof input.past_dates !== 'undefined' ) {
215						if ( input.past_dates === 'on' ) {
216							InputSelector.datepicker( 'option', 'minDate', 0 );
217						}
218					}
219
220					if ( typeof input.max_date !== 'undefined' ) {
221						const max_date = input.max_date.trim();
222						InputSelector.datepicker(
223							'option',
224							'maxDate',
225							max_date
226						);
227					}
228
229					if (
230						typeof input.no_weekends !== 'undefined' &&
231						input.no_weekends === 'on'
232					) {
233						InputSelector.datepicker(
234							'option',
235							'beforeShowDay',
236							jQuery.datepicker.noWeekends
237						);
238					}
239
240					if (
241						typeof input.default_value !== 'undefined' &&
242						input.default_value.trim().length > 0
243					) {
244						const default_date = input.default_value.trim();
245						InputSelector.datepicker(
246							'option',
247							'defaultDate',
248							default_date
249						);
250						InputSelector.datepicker( 'setDate', default_date );
251					}
252
253					if (
254						typeof input.first_day_of_week !== 'undefined' &&
255						input.first_day_of_week.trim().length > 0
256					) {
257						const first_day_of_week =
258							input.first_day_of_week.trim();
259						InputSelector.datepicker(
260							'option',
261							'firstDay',
262							first_day_of_week
263						);
264					}
265				}
266				break;
267
268			case 'image':
269				var img_id = input.data_name;
270				// Image Tooltip
271				if (
272					input.show_popup === 'on' &&
273					! ppom_input_vars.is_mobile
274				) {
275					jQuery( '.ppom-zoom-' + img_id ).imageTooltip();
276				}
277
278				document
279					.querySelectorAll( '.ppom-image-select' )
280					.forEach( ( /** @type{HTMLDivElement} */ container ) => {
281						/**
282						 * @type {HTMLInputElement[]} Holds the selected images.
283						 */
284						const selectedImgs = [];
285
286						/**
287						 * @type {HTMLInputElement[]} The available images to select.
288						 */
289						const imgsInput = Array.from(
290							container.querySelectorAll(
291								'.ppom-input.pre_upload_image input'
292							)
293						);
294
295						for ( const imgInput of imgsInput ) {
296							const multiple =
297								imgInput.dataset.allowMultiple || false;
298							const maxImgSelection = parseInt(
299								imgInput.dataset?.maxSelection ?? '-1'
300							);
301
302							imgInput.addEventListener( 'click', ( e ) => {
303								if ( ! e.target.checked ) {
304									return;
305								}
306
307								if ( ! multiple ) {
308									// Uncheck other inputs.
309									imgsInput
310										.filter( ( i ) => i !== imgInput )
311										.forEach( ( i ) => {
312											i.checked = false;
313										} );
314								} else if ( 0 < maxImgSelection ) {
315									// Uncheck oldest checked image.
316									selectedImgs.push( imgInput );
317									while (
318										selectedImgs.length > maxImgSelection
319									) {
320										const oldestImgSelected =
321											selectedImgs.shift();
322										if ( oldestImgSelected ) {
323											oldestImgSelected.checked = false;
324										}
325									}
326								}
327							} );
328						}
329					} );
330
331				// Data Tooltip
332				// $(".pre_upload_image").tooltip({container: 'body'});
333				break;
334			// date_range
335			case 'daterange':
336				InputSelector.daterangepicker( {
337					autoApply: input.auto_apply == 'on' ? true : false,
338					locale: {
339						format:
340							input.date_formats !== ''
341								? input.date_formats
342								: 'YYYY-MM-DD',
343					},
344					showDropdowns: input.drop_down == 'on' ? true : false,
345					showWeekNumbers: input.show_weeks == 'on' ? true : false,
346					timePicker: input.time_picker == 'on' ? true : false,
347					timePickerIncrement:
348						input.tp_increment !== ''
349							? parseInt( input.tp_increment )
350							: '',
351					timePicker24Hour: input.tp_24hours == 'on' ? true : false,
352					timePickerSeconds: input.tp_seconds == 'on' ? true : false,
353					drops: input.open_style !== '' ? input.open_style : 'down',
354					startDate:
355						input.start_date == '' ? false : input.start_date,
356					endDate: input.end_date == '' ? false : input.end_date,
357					minDate: input.min_date == '' ? false : input.min_date,
358					maxDate: input.max_date == '' ? false : input.max_date,
359				} );
360				break;
361
362			// color: iris
363			case 'color':
364				InputSelector.css( 'background-color', input.default_color );
365				var iris_options = {
366					palettes: ppom_get_palette_setting( input ),
367					hide: input.show_onload == 'on' ? false : true,
368					color: input.default_color,
369					mode:
370						input.palettes_mode != '' ? input.palettes_mode : 'hsv',
371					width:
372						input.palettes_width != '' ? input.palettes_width : 200,
373					change( event, ui ) {
374						InputSelector.css(
375							'background-color',
376							ui.color.toString()
377						);
378						InputSelector.css( 'color', '#fff' );
379
380						// Getting Color Code for update price
381						InputSelector.val( ui.color.toString() );
382						if ( typeof ppomPrice !== 'undefined' ) {
383							ppomPrice.init();
384						}
385					},
386				};
387
388				InputSelector.iris( iris_options );
389
390				// Following script is added to close picker
391				// when color is picked
392				jQuery( document )
393					.off( 'click.ppomColor' )
394					.on( 'click.ppomColor', function ( e ) {
395						if (
396							! jQuery( e.target ).is(
397								'.ppom-input.color, .iris-picker, .iris-picker-inner'
398							)
399						) {
400							jQuery( '.ppom-input.color' ).iris( 'hide' );
401							return e;
402						}
403					} );
404
405				jQuery( '.ppom-input.color' )
406					.off( 'click.ppomColor' )
407					.on( 'click.ppomColor', function ( event ) {
408						jQuery( '.ppom-input.color' ).iris( 'hide' );
409						jQuery( this ).iris( 'show' );
410						return event;
411					} );
412				break;
413
414			// Palettes
415			case 'palettes':
416				const max_selected =
417					parseInt( input.max_selected ) || undefined;
418				if ( ! max_selected ) {
419					break;
420				}
421
422				jQuery( document )
423					.off(
424						'click.ppomPalettes' + input.data_name,
425						`.ppom-palettes-${ input.data_name } input.ppom-input`
426					)
427					.on(
428						'click.ppomPalettes' + input.data_name,
429						`.ppom-palettes-${ input.data_name } input.ppom-input`,
430						function ( e ) {
431							if (
432								jQuery(
433									`.ppom-palettes-${ input.data_name } input.ppom-input:checked`
434								).length > max_selected
435							) {
436								alert(
437									`You can only select a maximum of ${ max_selected } ${ input.title } colors`
438								);
439								e.preventDefault();
440								//   return false;
441							}
442						}
443					);
444				break;
445			// Bulk quantity
446			case 'bulkquantity':
447				setTimeout( function () {
448					jQuery( '.quantity.buttons_added' ).hide();
449				}, 50 );
450				jQuery( 'form.cart' ).find( '.quantity' ).hide();
451
452				// setting formatter
453				/*if ($('form.cart').closest('div').find('.price').length > 0){
454                	wc_price_DOM = $('form.cart').closest('div').find('.price');
455                }*/
456
457				ppom_bulkquantity_meta[ input.data_name ] = input.options;
458
459				var min_quantity_value = jQuery(
460					`.ppom-bulkquantity-qty.${ input.data_name }`
461				).val();
462
463				// Starting value
464				ppom_bulkquantity_price_manager(
465					min_quantity_value,
466					input.data_name
467				);
468				break;
469
470			case 'pricematrix':
471				ppom_pricematrix_discount_type = input.discount_type;
472
473				if (
474					input.show_slider === 'on' &&
475					jQuery( '.ppom-range-slide' ).length > 0
476				) {
477					const slider = new Slider( '.ppom-range-slide', {
478						formatter( value ) {
479							jQuery.event.trigger( {
480								type: 'ppom_range_slider_updated',
481								qty: value,
482								time: new Date(),
483							} );
484							return ppom_input_vars.text_quantity + ': ' + value;
485						},
486					} );
487				}
488
489				jQuery( '.ppom-range-bs-slider' )
490					.off( 'change.ppom' )
491					.on( 'change.ppom', function ( e ) {
492						jQuery.event.trigger( {
493							type: 'ppom_range_slider_updated',
494							qty: jQuery( this ).val(),
495							time: new Date(),
496						} );
497					} );
498				break;
499			case 'quantities':
500				var enable_plusminus = input.enable_plusminus;
501				var field_selectot = jQuery( '.ppom-input-' + input.data_name );
502				if ( enable_plusminus == 'on' ) {
503					jQuery( '.ppom-quantity', field_selectot ).niceNumber();
504				}
505				break;
506		}
507
508		// Mark this field as initialized to prevent duplicate bindings
509		InputSelector.data( 'ppom-initialized', true );
510	} );
511}
512
513function ppom_get_palette_setting( input ) {
514	let palettes_setting = false;
515	// first check if palettes is on
516	if ( input.show_palettes === 'on' ) {
517		palettes_setting = true;
518	}
519	if ( palettes_setting && input.palettes_colors !== '' ) {
520		palettes_setting = input.palettes_colors.split( ',' );
521	}
522
523	return palettes_setting;
524}
525
526/**
527 * Shared field lookup used by pricing, conditions, and file upload helpers.
528 *
529 * @param {string} field_id
530 * @return {string}
531 */
532function ppom_get_field_type_by_id( field_id ) {
533	let field_type = '';
534	jQuery.each( ppom_input_vars.ppom_inputs, function ( i, field ) {
535		if ( field.data_name === field_id ) {
536			field_type = field.field_type;
537		}
538	} );
539
540	return field_type;
541}
542
543/**
544 * Return the full localized field definition for a given data_name.
545 *
546 * @param {string} field_id
547 * @return {PPOMLocalizedFieldMeta|string}
548 */
549function ppom_get_field_meta_by_id( field_id ) {
550	let field_meta = '';
551	jQuery.each( ppom_input_vars.ppom_inputs, function ( i, field ) {
552		if ( field.data_name === field_id ) {
553			field_meta = field;
554		}
555	} );
556
557	return field_meta;
558}
559
560/**
561 * Some flows need all fields of a given type, for example cropper/file setup.
562 *
563 * @param {string} type
564 * @return {PPOMLocalizedFieldMeta[]}
565 */
566function ppom_get_field_meta_by_type( type ) {
567	const field_meta = Array();
568	jQuery.each( ppom_input_vars.ppom_inputs, function ( i, field ) {
569		if ( field.type === type ) {
570			field_meta.push( field );
571		}
572	} );
573
574	return field_meta;
575}
576
577// Keep the range and number UIs for bulkquantity in sync before recalculating.
578function ppom_bq_qty_changed( qty, data_name, context ) {
579	if ( context === 'range' ) {
580		// update the quantity too.
581		jQuery( `.ppom-bulkquantity-qty.${ data_name }` ).val( qty );
582	} else if ( context === 'number' ) {
583		// update slider too.
584		jQuery( `input[type=range].${ data_name }` ).val( qty );
585	}
586
587	ppom_bulkquantity_price_manager( qty, data_name );
588}
589
590// Resolve the active bulkquantity row into price/base-price attributes expected
591// by the legacy and modern price preview engines.
592function ppom_bulkquantity_price_manager( quantity, data_name ) {
593	let ppom_base_price = 0;
594	jQuery.each(
595		JSON.parse( ppom_bulkquantity_meta[ data_name ] ),
596		function ( idx, obj ) {
597			const qty_range = obj[ 'Quantity Range' ].split( '-' );
598			const qty_range_from = qty_range[ 0 ];
599			const qty_range_to = qty_range[ 1 ];
600
601			if (
602				quantity >= parseInt( qty_range_from ) &&
603				quantity <= parseInt( qty_range_to )
604			) {
605				// Setting Initial Price to 0 and taking base price
606				ppom_base_price =
607					obj[ 'Base Price' ] == undefined ||
608					obj[ 'Base Price' ] == ''
609						? 0
610						: obj[ 'Base Price' ];
611				jQuery(
612					`.ppom-bulkquantity-options.${ data_name } option:selected`
613				).attr( 'data-baseprice', ppom_base_price );
614
615				// Taking selected variation price
616				const variation = jQuery( '.ppom-bulkquantity-options' ).val();
617				const var_price = obj[ variation ];
618				jQuery(
619					`.ppom-bulkquantity-options.${ data_name } option:selected`
620				).attr( 'data-price', var_price );
621
622				return false;
623			}
624		}
625	);
626
627	ppom_update_option_prices();
628}
629
630String.prototype.ppom_js_stripSlashes = function () {
631	return this.replace( /\\(.)/gm, '$1' );
632};
633
634/**
635 * Get the localized data for a specific product.
636 * falling back to the single-product structure if needed.
637 *
638 * @param {number} productId
639 * @returns {object|null}
640 */
641function ppom_get_product_data( productId ) {
642	if (
643		typeof window[ 'ppom_input_vars_by_product' ] !== 'undefined' &&
644		window[ 'ppom_input_vars_by_product' ][ productId ]
645	) {
646		return window[ 'ppom_input_vars_by_product' ][ productId ];
647	}
648
649	// Fallback to single-product data for backward compatibility
650	if (
651		typeof window[ 'ppom_input_vars' ] !== 'undefined' &&
652		window[ 'ppom_input_vars' ].product_id == productId
653	) {
654		return window[ 'ppom_input_vars' ];
655	}
656
657	return null;
658}

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.