PageSourceSearch

https://www.sparkil.org/wp-content/themes/elessi-theme-child/digi_…?ref=1.50&ctv=2.4.3&dev=6339&&ver=7.1.2

js sparkil.org collected 2026-09-26 07:52:29 UTC 89,279 bytes, 2,092 lines download raw bytes

1// NEW WC 2024 VERSION
2
3// push data to GTM
4window.dataLayer = window.dataLayer || [];
5window.dataLayer.push({
6    'fb_pixel_lang': digi_e_vars.lang, // digi_e_vars.pixel_lang
7});
8
9;(w => {
10    w.addEventListener('DOMContentLoaded', ()=>{
11        const $ = jQuery;
12		
13		// Boolean - enable/disable notice popup before redirecting to lender external website
14		const _notice_popup = true;
15        
16        let vv = 37;
17        
18        console.log('V-'+vv);
19		
20		function spark_v3_find_variation_id_by_lend_amount($form, lend_amount) {
21			if (!$form || !$form.length || typeof lend_amount === 'undefined' || lend_amount === '') {
22				return '';
23			}
24			
25			var raw_variations = $form.attr('data-product_variations');
26			if (!raw_variations) {
27				return '';
28			}
29			
30			var variations = raw_variations;
31			if (typeof raw_variations === 'string') {
32				try {
33					variations = JSON.parse(raw_variations);
34				} catch (e) {
35					return '';
36				}
37			}
38			
39			if (!Array.isArray(variations)) {
40				return '';
41			}
42			
43			for (var i = 0; i < variations.length; i++) {
44				var v = variations[i];
45				if (!v || !v.attributes) {
46					continue;
47				}
48				if (v.attributes['attribute_pa_lend-amount'] === lend_amount && v.variation_id) {
49					return String(v.variation_id);
50				}
51			}
52			
53			return '';
54		}
55
56		/**
57		 * V3 custom amount option value for lend dropdown
58		 * @since 2.4.0
59		 * @returns {string}
60		 */
61		function spark_get_v3_custom_amount_option_value() {
62			return 'spark-custom-amount';
63		}
64
65		/**
66		 * Resolve open price min/max from input with language defaults fallback
67		 * @since 2.4.0
68		 * @param {jQuery} $input
69		 * @returns {{min_amount:number,max_amount:number}}
70		 */
71		function spark_get_open_price_range_from_input($input) {
72			var defaults = {
73				min_amount: 36,
74				max_amount: 720
75			};
76
77			if (typeof digi_e_vars !== 'undefined' && digi_e_vars.lang == 'he') {
78				defaults.min_amount = 50;
79				defaults.max_amount = 2400;
80			}
81
82			if (!$input || !$input.length) {
83				return defaults;
84			}
85
86			var min_attr = parseInt($input.attr('min'), 10);
87			var max_attr = parseInt($input.attr('max'), 10);
88
89			if (!isNaN(min_attr)) {
90				defaults.min_amount = min_attr;
91			}
92
93			if (!isNaN(max_attr)) {
94				defaults.max_amount = max_attr;
95			}
96
97			return defaults;
98		}
99
100		/**
101		 * Default labels and values for V3 custom amount UI
102		 * @since 2.4.0
103		 * @returns {{placeholder_text:string,currency_symbol:string,custom_option_text:string,min_amount:number,max_amount:number}}
104		 */
105		function spark_get_v3_open_price_defaults() {
106			var defaults = {
107				placeholder_text: 'Type Amount',
108				currency_symbol: '$',
109				custom_option_text: 'Other Amount',
110				min_amount: 36,
111				max_amount: 720
112			};
113
114			if (typeof digi_e_vars !== 'undefined' && digi_e_vars.lang == 'he') {
115				defaults.placeholder_text = 'הכניסו סכום';
116				defaults.currency_symbol = '₪';
117				defaults.custom_option_text = 'סכום אחר';
118				defaults.min_amount = 50;
119				defaults.max_amount = 2400;
120			}
121
122			return defaults;
123		}
124
125		/**
126		 * Build V3 custom amount input markup
127		 * @since 2.4.0
128		 * @returns {string}
129		 */
130		function spark_get_v3_custom_open_price_input_html() {
131			var defaults = spark_get_v3_open_price_defaults();
132			var input_html = '';
133
134			input_html += '<div class="spark-v3-open-price-wrap product-single-open-price">';
135			input_html += '<div class="open-price-input-wrapper">';
136			input_html += '<input type="number" name="open_price" class="open-price-input" placeholder="' + defaults.placeholder_text + '" min="' + defaults.min_amount + '" max="' + defaults.max_amount + '" step="1" pattern="[0-9]+" />';
137			input_html += '<span class="currency-symbol">' + defaults.currency_symbol + '</span>';
138			input_html += '</div>';
139			input_html += '<span class="validation-message" style="display:none; color: #e74c3c; font-size: 12px;"></span>';
140			input_html += '</div>';
141
142			return input_html;
143		}
144
145		/**
146		 * Toggle V3 custom amount input based on dropdown selection
147		 * @since 2.4.0
148		 * @param {jQuery} $form
149		 */
150		function spark_toggle_v3_custom_amount_input($form) {
151			if (!$form || !$form.length) {
152				return;
153			}
154
155			var custom_option_value = spark_get_v3_custom_amount_option_value();
156			var $select = $form.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount").first();
157			var $open_price_wrap = $form.find('.spark-v3-open-price-wrap').first();
158
159			if (!$select.length || !$open_price_wrap.length) {
160				return;
161			}
162
163			var is_custom_selected = ($select.val() === custom_option_value);
164			var $open_price_input = $open_price_wrap.find('.open-price-input').first();
165			var $validation_message = $open_price_wrap.find('.validation-message').first();
166
167			if (is_custom_selected) {
168				$open_price_wrap.addClass('spark-v3-open-price-visible');
169
170				var $variation_id_input = $form.find("input[name='variation_id']");
171				if ($variation_id_input.length) {
172					$variation_id_input.val('0');
173				}
174
175				var $buy_buttons = $form.find('button.nasa-buy-now, button.single_add_to_cart_button');
176				if ($buy_buttons.length) {
177					$buy_buttons.prop('disabled', false);
178					$buy_buttons.removeClass('disabled wc-variation-selection-needed');
179				}
180
181				return;
182			}
183
184			$open_price_wrap.removeClass('spark-v3-open-price-visible');
185			if ($open_price_input.length) {
186				$open_price_input.val('');
187				$open_price_input.removeClass('error valid');
188			}
189
190			if ($validation_message.length) {
191				$validation_message.hide().text('');
192			}
193		}
194
195		function spark_is_quickview_scope(_scope) {
196			if (!_scope || !_scope.length) {
197				return false;
198			}
199
200			return _scope.is('#nasa-quickview-sidebar-content, #nasa-quickview-popup, .product-lightbox') || _scope.closest('#nasa-quickview-sidebar-content, #nasa-quickview-popup, .product-lightbox').length > 0;
201		}
202
203		function spark_ensure_v3_custom_amount_ui($form) {
204			if (!$form || !$form.length) {
205				return;
206			}
207
208			var $select = $form.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount").first();
209			if (!$select.length) {
210				return;
211			}
212
213			var custom_option_value = spark_get_v3_custom_amount_option_value();
214			var open_price_defaults = spark_get_v3_open_price_defaults();
215
216			if (!$select.find('option[value="' + custom_option_value + '"]').length) {
217				$select.append('<option value="' + custom_option_value + '" data-spark-custom-amount="1">' + open_price_defaults.custom_option_text + '</option>');
218			}
219
220			var $actions = $form.find('.spark-v3-lend-actions').first();
221			var $btn = $form.find('button.nasa-buy-now, button.single_add_to_cart_button').first();
222
223			if ($actions.length && $btn.length && !$actions.find('.spark-v3-open-price-wrap').length) {
224				$btn.before(spark_get_v3_custom_open_price_input_html());
225			}
226		}
227		
228		function spark_init_v3_lend_actions(_scope) {
229			var is_v3 = $('body').hasClass('spark-grid-v3');
230			var is_quickview_scope = spark_is_quickview_scope(_scope);
231			if (!is_v3 && !is_quickview_scope) {
232				return;
233			}
234			
235			var $scope = _scope && _scope.length ? _scope : $(document);
236			var $forms = $scope.find('form.cart');
237			if ($scope.is('form.cart')) {
238				$forms = $forms.add($scope);
239			}
240			$forms = $forms.filter(function() {
241				var $f = $(this);
242				return spark_is_quickview_scope($f) || $f.closest('body.single-product').length > 0;
243			});
244			
245			$forms.each(function() {
246				var $form = $(this);
247				if ($form.data('spark_v3_lend_init') === 1) {
248					if (is_v3 || spark_is_quickview_scope($form)) {
249						spark_ensure_v3_custom_amount_ui($form);
250						spark_toggle_v3_custom_amount_input($form);
251					}
252					return;
253				}
254				
255				var $select = $form.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount").first();
256				if (!$select.length) {
257					return;
258				}
259				
260				var $select_row = $select.closest('tr');
261				var $select_label = $form.find('label[for="pa_lend-amount"], label[for="attribute_pa_lend-amount"]');
262				
263				$form.data('spark_v3_lend_init', 1);
264				$form.addClass('spark-v3-lend-form');
265				
266				var $btn = $form.find('button.nasa-buy-now').first();
267				if (!$btn.length) {
268					$btn = $form.find('button.single_add_to_cart_button').first();
269				}
270				if (!$btn.length) {
271					return;
272				}
273				
274				var $actions = $form.find('.spark-v3-lend-actions');
275				if (!$actions.length) {
276					$actions = $('<div class="spark-v3-lend-actions" />');
277				}
278				
279				var $btn_wrap = $btn.closest('.woocommerce-variation-add-to-cart, .single_variation_wrap, .variations_button');
280				if (!$btn_wrap.length) {
281					$btn_wrap = $form;
282				}
283				
284				$btn_wrap.prepend($actions);
285				$select.appendTo($actions);
286				$btn.appendTo($actions);
287
288				if (is_v3 || spark_is_quickview_scope($form)) {
289					spark_ensure_v3_custom_amount_ui($form);
290				}
291				
292				var giftcard_url = '/giftcard/';
293				var giftcard_text = 'Buy as a Giftcard';
294				if (typeof digi_e_vars !== 'undefined' && digi_e_vars.lang == 'he') {
295					giftcard_url = '/gifcardhe/';
296					giftcard_text = 'קנה כגיפטקארד';
297				}
298				
299				var $giftcard_btn = $actions.find('.spark-giftcard-inline');
300				if (!$giftcard_btn.length) {
301					$actions.append('<a href="' + giftcard_url + '" class="button nasa-button giftcard-button spark-giftcard-inline">' + giftcard_text + '</a>');
302					$giftcard_btn = $actions.find('.spark-giftcard-inline');
303				}
304				
305				// Ensure order: Select -> Lend Now -> GiftCard
306				$giftcard_btn.insertAfter($btn);
307				
308				if ($select_row.length) {
309					$select_row.addClass('spark-v3-variation-row-hidden');
310				}
311				
312				if ($select_label.length) {
313					$select_label.addClass('spark-v3-lend-label-hidden');
314				}
315				
316				var $placeholder_opt = $select.find('option[value=""]');
317				if ($placeholder_opt.length) {
318					$placeholder_opt.remove();
319				}
320				
321				if (!$select.val()) {
322					$select.prop('selectedIndex', 0);
323				}
324				
325				setTimeout(function() {
326					$select.trigger('change');
327					$form.trigger('check_variations');
328					spark_toggle_v3_custom_amount_input($form);
329				}, 10);
330			});
331		}
332		
333		function spark_v3_mark_reached_icon(_scope) {
334			var $scope = _scope && _scope.length ? _scope : $(document);
335			var $items = $scope.find('.spark-v3-progress-wrap.spark-v3-detailed .spark-v3-detail-item');
336			if (!$items.length) {
337				return;
338			}
339			
340			$items.each(function() {
341				var $item = $(this);
342				var label_text = String($item.find('.spark-v3-detail-label').text() || '').trim();
343				if (!label_text) {
344					return;
345				}
346				
347				var is_reached = (label_text.indexOf('גויס עד כה') !== -1) || (label_text.toLowerCase().indexOf("i've reached") !== -1);
348				if (!is_reached) {
349					return;
350				}
351				
352				var $icon = $item.find('.spark-v3-detail-icon').first();
353				if ($icon.length) {
354					$icon.addClass('spark-v3-detail-icon-reached');
355				}
356			});
357		}
358		
359		spark_init_v3_lend_actions($(document));
360		spark_v3_mark_reached_icon($(document));
361		
362		var _spark_qv_observer = null;
363		
364		function spark_bind_quickview_observer() {
365			var _spark_qv_selector = '#nasa-quickview-sidebar-content';
366			var _spark_qv_node = document.getElementById('nasa-quickview-sidebar-content');
367			if (!_spark_qv_node) {
368				_spark_qv_selector = '#nasa-quickview-popup';
369				_spark_qv_node = document.getElementById('nasa-quickview-popup');
370			}
371			if (!_spark_qv_node) {
372				return false;
373			}
374			
375			if (_spark_qv_observer) {
376				return true;
377			}
378			
379			var $qv = $(_spark_qv_selector);
380			spark_init_v3_lend_actions($qv);
381			spark_v3_mark_reached_icon($qv);
382			
383			_spark_qv_observer = new MutationObserver(function() {
384				var $qv_inner = $(_spark_qv_selector);
385				spark_init_v3_lend_actions($qv_inner);
386				spark_v3_mark_reached_icon($qv_inner);
387			});
388			_spark_qv_observer.observe(_spark_qv_node, { childList: true, subtree: true });
389			
390			return true;
391		}
392		
393		// Quickview container is created dynamically; watch for it.
394		if (!spark_bind_quickview_observer() && document.body) {
395			var _spark_body_observer = new MutationObserver(function() {
396				if (spark_bind_quickview_observer()) {
397					_spark_body_observer.disconnect();
398				}
399			});
400			_spark_body_observer.observe(document.body, { childList: true, subtree: true });
401		}
402
403		$('body').on('init_quickview_variations_form nasa_after_quickview', function(e, formLightBox) {
404			var $qv_scope = formLightBox && $(formLightBox).length ? $(formLightBox) : $('#nasa-quickview-sidebar-content, #nasa-quickview-popup');
405			if (!$qv_scope.length) {
406				return;
407			}
408
409			spark_init_v3_lend_actions($qv_scope);
410			spark_v3_mark_reached_icon($qv_scope);
411		});
412
413		$(document).on('change', '.spark-v3-lend-form select[name="attribute_pa_lend-amount"], .spark-v3-lend-form #pa_lend-amount', function() {
414			var $form = $(this).closest('form.cart');
415			spark_toggle_v3_custom_amount_input($form);
416		});
417		
418		//et slider_campaign_id   = 0;
419		//let slider_campaign_name = null;
420		
421        /**
422         *  Single product Page - Add campaign ID to Body & send GA event
423         */
424         if($("body").hasClass("single-product")) {
425            if(typeof _this_product_campaign_id !== 'undefined') {
426                $("body").attr("data-campaign_id", _this_product_campaign_id);        
427            }
428            
429            if($("body.single-product FORM BUTTON.nasa-buy-now").length) {
430                $("body.single-product FORM BUTTON.nasa-buy-now").addClass('buy-lender');    
431            }
432            
433            // PUSH View GA event
434            if(typeof _this_product_campaign_id !== 'undefined' && typeof _this_product_campaign_name !== 'undefined') {
435                push_ga_view_item_event(_this_product_campaign_id, _this_product_campaign_name);    
436            }
437            
438            
439         }
440         
441        // Nasa Buy now BUTTON 	
442        $('body.single-product').on('click', 'form.cart .nasa-buy-now.buy-lender', function(e) {
443            e.preventDefault();
444            e.stopImmediatePropagation();
445			
446			var $form = $(this).closest('form.cart');
447            
448			variation_selected = $form.find("INPUT[name=variation_id]").val();
449			lend_amount = $form.find("#pa_lend-amount option:selected").val();
450			var custom_option_value = spark_get_v3_custom_amount_option_value();
451			var is_custom_amount_option = (lend_amount === custom_option_value);
452			
453			if (!is_custom_amount_option && (typeof variation_selected === 'undefined' || variation_selected === '0') && typeof lend_amount !== 'undefined' && lend_amount !== '') {
454				var _found_variation_id = spark_v3_find_variation_id_by_lend_amount($form, lend_amount);
455				if (_found_variation_id) {
456					variation_selected = _found_variation_id;
457					$form.find("INPUT[name=variation_id]").val(variation_selected);
458				}
459			}
460            
461            // No variation Selected - check for custom open price input
462            if(typeof variation_selected == 'undefined' || variation_selected == '0' || typeof lend_amount == 'undefined' || lend_amount == '' || is_custom_amount_option) {
463                
464                // Check if there's a valid custom open price input
465                var customOpenPriceInput = $( this ).closest( "form.cart" ).find(".open-price-input");
466                var customInputValue = null;
467                var hasValidCustomInput = false;
468                
469                if (customOpenPriceInput.length > 0 && customOpenPriceInput.val() !== '') {
470					var open_price_range = spark_get_open_price_range_from_input(customOpenPriceInput);
471					customInputValue = parseInt(customOpenPriceInput.val(), 10);
472					hasValidCustomInput = !isNaN(customInputValue) && customInputValue >= open_price_range.min_amount && customInputValue <= open_price_range.max_amount;
473                }
474                
475                if (hasValidCustomInput) {
476                    // Use the custom input value as the lend amount
477                    lend_amount = 'lend-' + customInputValue;
478                    variation_selected = '1'; // Set variation as selected
479                    
480                    // Also set the form data for consistency
481                    $( this ).closest( "form.cart" ).find("INPUT[name=variation_id]").val('custom-' + customInputValue);
482                    $( this ).closest( "form.cart" ).find("select[name='attribute_pa_lend-amount']").val(lend_amount);
483                    
484                } else {
485                    // No valid variation or custom input
486                    _alertTxt = 'Please select some product options before adding this product to your cart.';
487					
488					if(digi_e_vars.lang == 'he') {
489						_alertTxt = 'נא לבחור סכום הלוואה';	
490					} 
491					
492					alert(_alertTxt);
493                    return false;
494                }
495            }
496            
497            lend_amount = lend_amount.replace('lend-', '');
498            
499            // Get current raised amount
500            raised = $( this ).closest(".nasa-product-info-wrap").find(".progress-container-v2 .progress-raised-number").text(); 
501            raised = raised.replace(/[$,]/g, ""); // removes $ and commas
502            raised = parseInt(raised, 10);
503                
504            updated_raised = raised + parseInt(lend_amount, 10);
505            
506            //console.log(raised);
507            //console.log(updated_raised);
508            
509            // Deprecated Aug 2025
510            //call_ajax_update_campaign_raised(_this_product_campaign_id, updated_raised, parseInt(lend_amount, 10));
511
512            // variation select - redirect to lender
513            redirect_to_lender(_this_product_campaign_id, lend_amount);
514			//window.location.assign("https://lender.sparkil.org/"+digi_e_vars.lang+"/projects/"+_this_product_campaign_id+"/checkout?amount="+lend_amount+"&currency="+digi_e_vars.currency+"&anonymouns=true");
515            
516            return false;
517        });
518        
519        // Buy Now on Loop Grid Button
520        $('body.digi-no-checkout').on('click','.add-to-cart-grid.buy-lender', function(e){
521            if($(this).hasClass('nasa-active')) {
522                e.preventDefault();
523                e.stopImmediatePropagation();
524                
525                variation_selected = $( this ).attr('data-product_id');
526                variation_data     = $( this ).attr('data-variation');
527                campaign_id        = $( this ).attr('data-campaign_id');
528                
529                if(typeof variation_data == 'undefined' || variation_data == '' || typeof campaign_id == 'undefined' || campaign_id == '') return false;
530                
531                variation_data_json = JSON.parse(variation_data);
532                
533                lend_amount = variation_data_json["attribute_pa_lend-amount"];
534
535                lend_amount = lend_amount.replace('lend-', '');
536                
537                // Get current raised amount
538                raised = $( this ).closest(".product-info-wrap").find(".progress-container-v2 .progress-raised-number").text(); 
539                raised = raised.replace(/[$,]/g, ""); // removes $ and commas
540                raised = parseInt(raised, 10);
541                
542                updated_raised = raised + parseInt(lend_amount, 10);
543                
544                // Deprecated Aug 2025
545                //call_ajax_update_campaign_raised(campaign_id, updated_raised, parseInt(lend_amount, 10));
546                
547                //console.log(raised);
548                //console.log(updated_raised);
549                
550                // variation select - redirect to lender
551                redirect_to_lender(campaign_id, lend_amount);
552                //window.location.assign("https://lender.sparkil.org/"+digi_e_vars.lang+"/projects/"+campaign_id+"/checkout?amount="+lend_amount+"&currency="+digi_e_vars.currency+"&anonymouns=true");
553                
554                    
555            } else {
556                return false;
557            }
558            
559        });
560        
561        document.addEventListener('click', function(e) {
562			var btn = e.target && e.target.closest ? e.target.closest('#nasa-quickview-sidebar-content form.cart button.nasa-buy-now, #nasa-quickview-popup form.cart button.nasa-buy-now') : null;
563			if (!btn) {
564				return;
565			}
566			
567			if (!$('body').hasClass('digi-no-checkout')) {
568				return;
569			}
570			
571			// Capture phase: stop WooCommerce's variation validation alert from firing first.
572			e.preventDefault();
573			e.stopPropagation();
574			e.stopImmediatePropagation();
575			
576			var $btn = $(btn);
577			var $form = $btn.closest('form.cart');
578			
579			var variation_selected = $form.find("input[name='variation_id']").val();
580			var lend_amount = $form.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount").val();
581			var custom_option_value = spark_get_v3_custom_amount_option_value();
582			var is_custom_amount_option = (lend_amount === custom_option_value);
583
584			if (!is_custom_amount_option && (typeof variation_selected === 'undefined' || variation_selected === '0') && typeof lend_amount !== 'undefined' && lend_amount !== '') {
585				var _found_variation_id = spark_v3_find_variation_id_by_lend_amount($form, lend_amount);
586				if (_found_variation_id) {
587					variation_selected = _found_variation_id;
588					$form.find("input[name='variation_id']").val(variation_selected);
589				}
590			}
591			if ((typeof lend_amount === 'undefined' || lend_amount === '') && !is_custom_amount_option) {
592				lend_amount = $form.find('.nasa-attr-ux_wrap .selected').attr('data-value');
593			}
594			
595			var campaign_id = $form.find("input[name='spark_campaign_id'], #spark_campaign_id").val();
596			
597			if (typeof lend_amount === 'undefined' || lend_amount === '' || typeof variation_selected === 'undefined' || variation_selected === '0' || is_custom_amount_option) {
598				var customOpenPriceInput = $form.find('.open-price-input').first();
599				var customInputValue = null;
600				var hasValidCustomInput = false;
601
602				if (customOpenPriceInput.length > 0 && customOpenPriceInput.val() !== '') {
603					var open_price_range = spark_get_open_price_range_from_input(customOpenPriceInput);
604					customInputValue = parseInt(customOpenPriceInput.val(), 10);
605					hasValidCustomInput = !isNaN(customInputValue) && customInputValue >= open_price_range.min_amount && customInputValue <= open_price_range.max_amount;
606				}
607
608				if (hasValidCustomInput) {
609					lend_amount = 'lend-' + customInputValue;
610					variation_selected = '1';
611					$form.find("input[name='variation_id']").val('custom-' + customInputValue);
612					$form.find("select[name='attribute_pa_lend-amount']").val(lend_amount);
613				} else {
614				var _alertTxt = 'Please select some product options before adding this product to your cart.';
615				if (digi_e_vars.lang == 'he') {
616					_alertTxt = 'נא לבחור סכום הלוואה';
617				}
618				alert(_alertTxt);
619				return;
620				}
621			}
622			
623			lend_amount = lend_amount.replace('lend-', '');
624			redirect_to_lender(campaign_id, lend_amount);
625		}, true);
626        
627        // Checkout Button Click
628        /*
629        $(document).on('click', ['.button.checkout', '.wp-block-woocommerce-cart .wc-block-cart__submit-button'], function(e) {
630            e.preventDefault();
631            e.stopImmediatePropagation();
632            
633            // run ajax function 
634            $.ajax({
635                type: "post",
636                dataType: "json",
637                url: "/wp-admin/admin-ajax.php", 
638                data: {
639                    action:'spark_checkout_order', 
640                },
641                success: function(data){
642                    var json = JSON.parse(data);
643                    
644                    if(json.status == 1) {
645                        alert('new order success');
646                        return false;
647                    } else {
648                        // error
649                        alert('new order error');
650                        return false;
651                    }
652                }
653            });
654            
655            return false;
656        });
657        */
658		
659		/**
660		 * Redirec to lender
661		 * @param string campaign_id
662		 * @param int lend_amount
663		 */
664		function redirect_to_lender(campaign_id, lend_amount) {
665			popup_en_id  = 2587;
666			popup_heb_id = 1862;
667			popup_id     = 0;
668			
669			debug_redirect = false;
670
671      /* ===== Maintenance Mode ===== */
672      if (window.__SPARKIL_MAINTENANCE__ === true) {
673        let maintenanceUrl = null;
674        
675        if(digi_e_vars.lang == 'he') {
676          maintenanceUrl = 'https://www.sparkil.org/he/%d7%aa%d7%97%d7%96%d7%95%d7%a7%d7%94-200/';
677        } else {
678          maintenanceUrl = 'https://www.sparkil.org/maintenance-200/';
679        }
680        
681        window.location.assign(maintenanceUrl);
682        return;
683                
684      }
685      /* ===== END Maintenance Mode ===== */
686			
687			if(digi_e_vars.lang == 'he') {
688				popup_id = popup_heb_id;	
689			} else {
690				popup_id = popup_en_id;		
691			}
692			
693			/*
694			 * Push Tag Manager Evenet 
695			*/
696			window.dataLayer = window.dataLayer || [];
697			window.dataLayer.push({
698			 	'event': 'popup_to_lender_'+digi_e_vars.lang,
699				'lender_amount' : lend_amount ,
700				'lender_currency': digi_e_vars.currency
701		    });
702		    
703		    if(debug_redirect) {
704		        console.log("https://lender.sparkil.org/"+digi_e_vars.lang+"/projects/"+campaign_id+"/checkout?amount="+lend_amount+"&currency="+digi_e_vars.currency+"&anonymouns=true");
705		    }
706			
707			if(_notice_popup) {
708				elementorProFrontend.modules.popup.showPopup( { id: popup_id } );
709				
710				// wait X seconds before redirecting 1000 = 1 second
711				setTimeout(() => {
712  					window.location.assign("https://lender.sparkil.org/"+digi_e_vars.lang+"/projects/"+campaign_id+"/checkout?amount="+lend_amount+"&currency="+digi_e_vars.currency+"&anonymouns=true");
713				}, 4000);
714
715				
716			} else{
717				// redirect
718				window.location.assign("https://lender.sparkil.org/"+digi_e_vars.lang+"/projects/"+campaign_id+"/checkout?amount="+lend_amount+"&currency="+digi_e_vars.currency+"&anonymouns=true");
719			}
720			
721				
722		}
723		
724		/**
725		 * PUSH  View GA Tag Manager Evenet 
726		 * @param string campaign_id
727		 * @param string campaign_name
728		 */
729		function push_ga_view_item_event(campaign_id, campaign_name) {
730			window.dataLayer = window.dataLayer || [];
731			window.dataLayer.push({
732			 	'event': 'view_item',
733				'items': [
734					{
735						item_id: ""+campaign_id+"",
736					  	item_name: ""+campaign_name+"",
737						quantity: 1
738					}
739				 ]
740			});
741				
742		}
743		
744		/**
745		 * Send to ajax function to update a campaign  updatees raised amount - the current raised amount + the new loan
746         * Deprecated Aug 2025 !!
747		 */
748		function call_ajax_update_campaign_raised(campaignId, updatedRaised, loan_amount) {
749            $.ajax({
750                url: digi_e_vars.ajaxurl, // AJAX URL from localized script
751                type: 'POST',
752                dataType: 'json',
753                data: {
754                    action         : 'spark_campaign_raised_update', // Action name
755                    //security       : digi_e_vars.nonce, // Nonce for validation
756                    campaign_id    : campaignId, 
757                    updated_raised : updatedRaised, 
758                    loan_value     : loan_amount
759                },
760                success: function (response) {
761                    if (response.success) {
762                        //console.log('success1'); // Success message
763                    } else {
764                        //console.log('ajax error'); // Error message
765                    }
766                },
767                error: function (xhr, status, error) {
768                    //console.error('AJAX error:', status, error);
769                },
770            });
771        
772        }
773        
774        // Grid Overlay - Porim Advertisment
775        $(".product-item.grid .spark-grid-overlay.porim").on('click',function() {
776           alert('PORIMMMMM');
777           console.log(digi_e_vars.ad_overlay_url);
778           
779           //window.location.assign(digi_e_vars.ad_overlay_url);
780        });
781        
782        
783        // On grid page, find an item that has an overlay div and disable the  after hover event
784        $('ul.products.grid li.product-warp-item div.product-item ').each(function() {
785            if ($(this).find('div.spark-grid-overlay').length > 0) {
786                //console.log('FFF');
787                $(this).addClass('disable-after');
788            }
789        });
790
791        /**
792         * -------------------------------------------------------------------------------------------
793         * Open Price Input - NO CART
794         * @since 1.2.0
795         * -------------------------------------------------------------------------------------------
796        */
797
798        // Real-time validation for open price inputs (Shop Loop)
799        $(document).on('input', '.product-info-wrap .open-price-input', function() {
800            var input = $(this);
801            var value = parseInt(input.val());
802            var messageSpan = input.closest('.product-item-loop-open-price').find('.validation-message');
803
804            var min_amount = input.attr('min');
805            var max_amount = input.attr('max');
806            
807            
808            // Clear previous validation state
809            input.removeClass('error valid');
810            messageSpan.hide().text('');
811            
812            if (input.val() === '') {
813                // Reset button to "Select options" when input is empty
814                resetButtonToSelectOptions(input);
815                return;
816            }
817
818            // set lanuage texts
819            let please_enter_numbers_only = spark_open_price_events_texts('please_enter_numbers_only', min_amount, max_amount);
820            let minimum_amount_err_txt    = spark_open_price_events_texts('minimum_amount_err_txt', min_amount, max_amount);
821            let maximum_amount_err_txt    = spark_open_price_events_texts('maximum_amount_err_txt', min_amount, max_amount);
822            let add_to_cart_button_text   = spark_open_price_events_texts('add_to_cart_button_text', min_amount, max_amount);
823            
824            // Check if value is a number
825            if (isNaN(value) || !/^[0-9]+$/.test(input.val())) {
826                input.addClass('error');
827                messageSpan.text(please_enter_numbers_only).show();
828                
829                // Reset button text to "Select options" when input is invalid
830                resetButtonToSelectOptions(input);
831                return;
832            }
833            
834            // Check min/max range
835            if (value < min_amount) {
836                input.addClass('error');
837                messageSpan.text(minimum_amount_err_txt).show();
838                
839                // Reset button text to "Select options" when input is invali
839d
840                resetButtonToSelectOptions(input);
841            } else if (value > max_amount) {
842                input.addClass('error');
843                messageSpan.text(maximum_amount_err_txt).show();
844                
845                // Reset button text to "Select options" when input is invalid
846                resetButtonToSelectOptions(input);
847            } else {
848                input.addClass('valid');
849                messageSpan.hide();
850                
851                // Deactivate NASA attribute UX items when valid number is entered
852                var productInfoWrap = input.closest('.product-info-wrap');
853                if (productInfoWrap.length > 0) {
854                    // Find the NASA variable wrapper within the product info
855                    var nasaVariableWrap = productInfoWrap.find('.nasa-product-content-variable-warp');
856                    if (nasaVariableWrap.length > 0) {
857                        // Find all matching a tags within the lend amount wrap child
858                        var targetLinks = nasaVariableWrap.find('.nasa-product-content-lend-amount-wrap-child a.nasa-attr-ux-item.nasa-attr-ux-nasa_label');
859                        
860                        targetLinks.each(function() {
861                            var linkElement = $(this);
862                            
863                            // Remove nasa-active class if it exists
864                            if (linkElement.hasClass('nasa-active')) {
865                                linkElement.removeClass('nasa-active');
866                            }
867                            
868                            // Set data-act attribute to 0
869                            linkElement.attr('data-act', '0');
870                        });
871                        
872                        // Remove data-variation attribute from add-to-cart button when variations are deselected
873                        var addWrap = productInfoWrap.find('.add-to-cart-grid');
874                        if (addWrap.length > 0) {
875                            addWrap.removeAttr('data-variation');
876                            addWrap.removeAttr('data-variation_id');
877                            addWrap.addClass('product_type_variable');
878                            addWrap.removeClass('product_type_variation');
879                        }
880                    }
881                    
882                    // Update button text to "Add to cart" and activate button
883                    // Following Elessi theme's logic from nasa.functions.js
884                    var addWrap = productInfoWrap.find('.add-to-cart-grid');
885                    
886                    if (addWrap.hasClass('nasa-variable-add-to-cart-in-grid') && !$('body').hasClass('nasa-ywraq-hide-add-to-cart')) {
887                        // Get the "Add to cart" text from theme localization or fallback
888                        var addText = $('input[name="add_to_cart_text"]').val() || add_to_cart_button_text;
889                        
890                        // Update button text and attributes
891                        addWrap.find('.add_to_cart_text').html(addText);
892                        addWrap.attr('title', addText);
893                        
894                        // Update tooltip if present
895                        if (addWrap.hasClass('nasa-tip')) {
896                            addWrap.attr('data-tip', addText);
897                            
898                            if (addWrap.find('.nasa-tip-content').length) {
899                                addWrap.find('.nasa-tip-content').html(addText);
900                            }
901                        }
902                        
903                        // Activate the button by adding nasa-active class
904                        if (!addWrap.hasClass('nasa-active')) {
905                            addWrap.addClass('nasa-active');
906                        }
907                    }
908                }
909            }
910        });
911jQuery(document).ready(function($) {
912    // האזנה ברמת ה-document (Event Delegation) שתופסת את הלחיצה תמיד
913    $(document).on('click', '.e-n-tab-title, .e-n-tab-title *, [role="tab"]', function() {
914        
915        // בדיקה קסקדית בכמה זמנים (לכידת סיום האנימציה של אלמנטור)
916        [100, 300, 600].forEach(function(delay) {
917            setTimeout(function() {
918                // 1. טריגר resize כללי לדפדפן
919                window.dispatchEvent(new Event('resize'));
920                
921                // 2. הכרחת Slick Slider בתוך הטאב הפעיל לחשב מידות מחדש
922                $('.slick-slider:visible').each(function() {
923                    if ($(this).hasClass('slick-initialized')) {
924                        $(this).slick('setPosition');
925                    }
926                });
927            }, delay);
928        });
929    });
930});
931        // Real-time validation for open price inputs (Single Product Page)
932        $(document).on('input', '.variations_form .open-price-input', function() {
933            var input = $(this);
934            var value = parseInt(input.val());
935            var messageSpan = input.closest('.product-single-open-price, .product-item-loop-open-price').find('.validation-message');
936            var variationsForm = input.closest('.variations_form');
937            var is_v3_custom_input = input.closest('.spark-v3-open-price-wrap').length > 0;
938            
939            var min_amount = input.attr('min');
940            var max_amount = input.attr('max');
941            
942            // Clear previous validation state
943            input.removeClass('error valid');
944            messageSpan.hide().text('');
945            
946            if (input.val() === '') {
947                // Clear any validation when input is empty
948                return;
949            }
950
951            // set lanuage texts
952            let please_enter_numbers_only = spark_open_price_events_texts('please_enter_numbers_only', min_amount, max_amount);
953            let minimum_amount_err_txt    = spark_open_price_events_texts('minimum_amount_err_txt', min_amount, max_amount);
954            let maximum_amount_err_txt    = spark_open_price_events_texts('maximum_amount_err_txt', min_amount, max_amount);
955            let add_to_cart_button_text   = spark_open_price_events_texts('add_to_cart_button_text', min_amount, max_amount);
956                    
957            // Check if value is a number
958            if (isNaN(value) || !/^[0-9]+$/.test(input.val())) {
959                input.addClass('error');
960                messageSpan.text(please_enter_numbers_only).show();
961                return;
962            }
963                    
964            // Check min/max range
965            if (value < min_amount) {
966                input.addClass('error');
967                messageSpan.text(minimum_amount_err_txt).show();
968            } else if (value > max_amount) {
969                input.addClass('error');
970                messageSpan.text(maximum_amount_err_txt).show();
971            } else {
972                input.addClass('valid');
973                messageSpan.hide();
974
975				if (is_v3_custom_input && variationsForm.length > 0) {
976					var custom_option_value = spark_get_v3_custom_amount_option_value();
977					var v3_attribute_select = variationsForm.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount").first();
978					if (v3_attribute_select.length && v3_attribute_select.val() !== custom_option_value) {
979						v3_attribute_select.val(custom_option_value);
980					}
981
982					var v3_add_to_cart_button = variationsForm.find('.single_add_to_cart_button, .nasa-buy-now');
983					if (v3_add_to_cart_button.length > 0) {
984						v3_add_to_cart_button.prop('disabled', false);
985						v3_add_to_cart_button.removeClass('disabled wc-variation-selection-needed');
986					}
987
988					return;
989				}
990                        
991                // Deactivate NASA attribute UX items when valid number is entered
992                if (variationsForm.length > 0) {
993                    // Find all selected variation items and deselect them (single product page uses 'selected' class)
994                    var selectedItems = variationsForm.find('.nasa-attr-ux.selected');
995                    selectedItems.each(function() {
996                        $(this).removeClass('selected').attr('data-act', '0');
997                    });
998                            
999                    // Also check for nasa-active class (fallback)
1000                    var activeItems = variationsForm.find('.nasa-attr-ux.nasa-active');
1001                    activeItems.each(function() {
1002                        $(this).removeClass('nasa-active').attr('data-act', '0');
1003                    });
1004                            
1005                    // Clear the variation_id hidden input
1006                    var variationIdInput = variationsForm.find('input[name="variation_id"]');
1007                    if (variationIdInput.length > 0) {
1008                        variationIdInput.val('0');
1009                    }
1010                            
1011                    // Clear the attribute select value
1012                    var attributeSelect = variationsForm.find('select[name="attribute_pa_lend-amount"]');
1013                    if (attributeSelect.length > 0) {
1014                        attributeSelect.val('');
1015                    }
1016                            
1017                    // Reset the add-to-cart button to disabled state
1018                    var addToCartButton = variationsForm.find('.single_add_to_cart_button');
1019                    if (addToCartButton.length > 0) {
1020                        addToCartButton.addClass('disabled wc-variation-selection-needed');
1021                        addToCartButton.removeClass('alt');
1022                    }
1023                            
1024                    // Trigger change event to notify WooCommerce that variation was cleared
1025                    if (attributeSelect.length > 0) {
1026                        attributeSelect.trigger('change');
1027                    }
1028                }
1029            }
1030        });
1031
1032        /**
1033         * Handle focus out event to reset button when user leaves input
1034         * @since 1.2.0
1035         */
1036        $(document).on('focusout', '.open-price-input', function() {
1037            var input = $(this);
1038            var value = parseInt(input.val());
1039
1040			if (input.closest('.spark-v3-open-price-wrap').length > 0) {
1041				return;
1042			}
1043
1044            var min_amount = input.attr('min');
1045            var max_amount = input.attr('max');
1046            
1047            // If input is empty or invalid, reset button to "Select options"
1048            if (input.val() === '' || isNaN(value) || value < min_amount || value > max_amount) {
1049                resetButtonToSelectOptions(input);
1050            }
1051        });
1052        
1053        // Prevent non-numeric input
1054        $(document).on('keypress', '.open-price-input', function(e) {
1055            // Allow backspace, delete, tab, escape, enter
1056            if ($.inArray(e.keyCode, [46, 8, 9, 27, 13]) !== -1 ||
1057                // Allow Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X
1058                (e.keyCode === 65 && e.ctrlKey === true) ||
1059                (e.keyCode === 67 && e.ctrlKey === true) ||
1060                (e.keyCode === 86 && e.ctrlKey === true) ||
1061                (e.keyCode === 88 && e.ctrlKey === true)) {
1062                return;
1063            }
1064            // Ensure that it is a number and stop the keypress
1065            if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
1066                e.preventDefault();
1067            }
1068        });
1069
1070        /**
1071         * Clear custom input when variation label is selected (Shop Loop)
1072         * @since 1.2.0
1073         */
1074        $(document).on('click', '.product-info-wrap .nasa-attr-ux-item', function() {
1075            var clickedVariation = $(this);
1076                    
1077            // Use setTimeout to ensure the nasa-active class has been added by the theme's JS
1078            setTimeout(function() {
1079                // Check if this variation item now has the nasa-active class
1080                if (clickedVariation.hasClass('nasa-active')) {
1081                    // Find the product container
1082                    var productInfoWrap = clickedVariation.closest('.product-info-wrap');
1083                            
1084                    // Find the custom open price input within this product
1085                    var openPriceInput = productInfoWrap.find('.open-price-input');
1086                            
1087                    if (openPriceInput.length > 0 && openPriceInput.val() !== '') {
1088                        // Clear the input value
1089                        openPriceInput.val('');
1090                                
1091                        // Remove any validation classes
1092                        openPriceInput.removeClass('error valid');
1093                                
1094                        // Hide validation message
1095                        var messageSpan = productInfoWrap.find('.validation-message');
1096                        messageSpan.hide().text('');
1097                                
1098                        // Optional: Add a subtle visual feedback that input was cleared
1099                        openPriceInput.addClass('cleared');
1100                        setTimeout(function() {
1101                            openPriceInput.removeClass('cleared');
1102                        }, 300);
1103                    }
1104                }
1105            }, 50); // Small delay to ensure theme's JS has processed the click
1106        });
1107
1108        /**
1109         * Clear custom input when variation label is selected (Single Product Page)
1110         * @since 1.3.0
1111         */
1112        $(document).on('click', '.variations_form .nasa-attr-ux', function() {
1113            var clickedVariation = $(this);
1114            
1115            // Use setTimeout to ensure the nasa-active class has been added by the theme's JS
1116            setTimeout(function() {
1117                // Check if this variation item now has the nasa-active class
1118                if (clickedVariation.hasClass('nasa-active')) {
1119                    // Find the variations form container
1120                    var variationsForm = clickedVariation.closest('.variations_form');
1121                    
1122                    // Find the custom open price input within this form
1123                    var openPriceInput = variationsForm.find('.open-price-input');
1124                    
1125                    if (openPriceInput.length > 0 && openPriceInput.val() !== '') {
1126                        // Clear the input value
1127                        openPriceInput.val('');
1128                        
1129                        // Remove any validation classes
1130                        openPriceInput.removeClass('error valid');
1131                        
1132                        // Hide validation message
1133                        var messageSpan = variationsForm.find('.validation-message');
1134                        messageSpan.hide().text('');
1135                        
1136                        // Optional: Add a subtle visual feedback that input was cleared
1137                        openPriceInput.addClass('cleared');
1138                        setTimeout(function() {
1139                            openPriceInput.removeClass('cleared');
1140                        }, 300);
1141                    }
1142                }
1143            }, 50); // Small delay to ensure theme's JS has processed the click
1144        });
1145
1146                /**
1147         * Intercept add-to-cart button mousedown to handle custom input validation
1148         * and set data-variation attributes before theme handlers run
1149         * @since 1.2.0
1150         */
1151        $(document).on('mousedown', '.add-to-cart-grid', function(e) {
1152            var button = $(this);
1153            var productInfoWrap = button.closest('.product-info-wrap');
1154            var openPriceInput = productInfoWrap.find('.open-price-input');
1155            var activeVariations = productInfoWrap.find('.nasa-attr-ux-item.nasa-active');
1156            var attributeSelect = productInfoWrap.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount");
1157            var hasValidDropdown = false;
1158            var hasValidInput = false;
1159            var inputValue = null;
1160
1161            var min_amount = openPriceInput.attr('min');
1162            var max_amount = openPriceInput.attr('max');
1163            
1164            // Check if we have a valid custom input
1165            if (openPriceInput.length > 0 && openPriceInput.val() !== '') {
1166                inputValue = parseInt(openPriceInput.val());
1167                hasValidInput = !isNaN(inputValue) && inputValue >= min_amount && inputValue <= max_amount;
1168            }
1169            
1170            if (attributeSelect.length > 0) {
1171                var dd_val = attributeSelect.val();
1172                hasValidDropdown = (typeof dd_val !== 'undefined' && dd_val !== '');
1173            }
1174            
1175            // If no variation selected and no valid input, show tooltip and prevent action
1176            if (activeVariations.length === 0 && !hasValidInput && !hasValidDropdown) {
1177                e.preventDefault();
1178                e.stopPropagation();
1179                e.stopImmediatePropagation();
1180                
1181                // Store original href and temporarily disable it
1182                var originalHref = button.attr('href');
1183                if (originalHref) {
1184                    button.attr('data-original-href', originalHref);
1185                    button.removeAttr('href');
1186                }
1187                
1188                // Show tooltip with validation message
1189                let select_options_missimg_notification = spark_open_price_events_texts('select_options_missimg_notification', min_amount, max_amount);
1190
1191                var tooltip = $('<div class="open-price-tooltip">' + select_options_missimg_notification + '</div>');
1192                var buttonOffset = button.offset();
1193                var buttonHeight = button.outerHeight();
1194                
1195                tooltip.css({
1196                    'position': 'absolute',
1197                    'top': (buttonOffset.top - buttonHeight + 5) + 'px',
1198                    'left': buttonOffset.left + 'px',
1199                    'z-index': 9999
1200                }).appendTo('body').fadeIn(200);
1201                
1202                // Add shake animation to button
1203                button.addClass('shake-animation');
1204                
1205                // Remove tooltip, animation, and restore href after 3 seconds
1206                setTimeout(function() {
1207                    tooltip.fadeOut(200, function() {
1208                        tooltip.remove();
1209                    });
1210                    button.removeClass('shake-animation');
1211                    
1212                    // Restore original href
1213                    var storedHref = button.attr('data-original-href');
1214                    if (storedHref) {
1215                        button.attr('href', storedHref);
1216                        button.removeAttr('data-original-href');
1217                    }
1218                }, 3000);
1219                
1220                return false;
1221            }
1222            
1223            // If we have valid input but no preset variation, set up variation data
1224            if (hasValidInput && activeVariations.length === 0) {
1225                // Remove any existing data-variation to avoid conflicts
1226                button.removeAttr('data-variation');
1227                button.removeAttr('data-variation_id');
1228                
1229                // Set new variation data for custom input
1230                var variationData = {
1231                    'attribute_pa_lend-amount': 'lend-' + inputValue
1232                };
1233                var variationJson = JSON.stringify(variationData);
1234                button.attr('data-variation', variationJson);
1235                button.attr('data-variation_id', 'custom-' + inputValue);
1236                
1237                // Also try setting the href to include variation data (fallback approach)
1238                var currentHref = button.attr('href');
1239                if (currentHref && !currentHref.includes('add-to-cart=')) {
1240                    var separator = currentHref.includes('?') ? '&' : '?';
1241                    var newHref = currentHref + separator + 'add-to-cart=' + button.attr('data-product_id') + '&variation_id=custom-' + inputValue + '&attribute_pa_lend-amount=lend-' + inputValue;
1242                    button.attr('href', newHref);
1243                }
1244            }
1245            
1246            // Let the original theme handler continue
1247            return true;
1248        });
1249
1250        /**
1251         * Additional click handler to prevent link navigation when validation fails (Shop Loop)
1252         * @since 1.2.0
1253         * This prevents the href redirect when validation shows tooltip
1254         */
1255        $(document).on('click', '.add-to-cart-grid', function(e) {
1256            var button = $(this);
1257            var productInfoWrap = button.closest('.product-info-wrap');
1258            var openPriceInput = productInfoWrap.find('.open-price-input');
1259
1260            var min_amount = openPriceInput.attr('min');
1261            var max_amount = openPriceInput.attr('max');
1262            
1263            // Check current state (same logic as mousedown)
1264            var activeVariations = productInfoWrap.find('.nasa-attr-ux-item.nasa-active');
1265            var attributeSelect = productInfoWrap.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount");
1266            var hasValidDropdown = false;
1267            var hasValidInput = false;
1268            
1269            if (openPriceInput.length > 0 && openPriceInput.val() !== '') {
1270                var inputValue = parseInt(openPriceInput.val());
1271                hasValidInput = !isNaN(inputValue) && inputValue >= min_amount && inputValue <= max_amount;
1272            }
1273            
1274            if (attributeSelect.length > 0) {
1275                var dd_val = attributeSelect.val();
1276                hasValidDropdown = (typeof dd_val !== 'undefined' && dd_val !== '');
1277            }
1278            
1279            // If validation failed (no selection), prevent the link navigation aggressively
1280            if (activeVariations.length === 0 && !hasValidInput && !hasValidDropdown) {
1281                e.preventDefault();
1282                e.stopPropagation();
1283                e.stopImmediatePropagation();
1284                
1285                // Also check if href was temporarily removed and don't restore it yet
1286                if (button.attr('data-original-href') && !button.attr('href')) {
1287                    // Keep href disabled until timeout completes
1288                    return false;
1289                }
1290                
1291                return false;
1292            }
1293        });
1294
1295        /**
1296         * Single Product Page: Handle add-to-cart button validation and custom input
1297         * @since 1.2.0
1298         */
1299        $(document).on('click', '.single_add_to_cart_button, .nasa-buy-now', function(e) {
1300            var button = $(this);
1301            var variationsForm = button.closest('.variations_form');
1302            var openPriceInput = variationsForm.find('.open-price-input');
1303            var activeVariations = variationsForm.find('.nasa-attr-ux.nasa-active');
1304            var attributeSelect = variationsForm.find("select[name='attribute_pa_lend-amount'], #pa_lend-amount");
1305            var hasValidDropdown = false;
1306            var hasValidInput = false;
1307            var inputValue = null;
1308
1309            var min_amount = openPriceInput.attr('min');
1310            var max_amount = openPriceInput.attr('max');
1311            
1312            // Check if we have a valid custom input
1313            if (openPriceInput.length > 0 && openPriceInput.val() !== '') {
1314                inputValue = parseInt(openPriceInput.val());
1315                hasValidInput = !isNaN(inputValue) && inputValue >= min_amount && inputValue <= max_amount;
1316            }
1317            
1318            // If no variation selected and no valid input, show tooltip and prevent action
1319            if (activeVariations.length === 0 && !hasValidInput) {
1320                e.preventDefault();
1321                e.stopPropagation();
1322                e.stopImmediatePropagation();
1323                
1324                // Show tooltip with validation message
1325                let select_options_missimg_notification = spark_open_price_events_texts('select_options_missimg_notification', min_amount, max_amount);
1326                var tooltip = $('<div class="open-price-tooltip">' + select_options_missimg_notification + '</div>');
1327                var buttonOffset = button.offset();
1328                var buttonHeight = button.outerHeight();
1329                
1330                tooltip.css({
1331                    'position': 'absolute',
1332                    'top': (buttonOffset.top - buttonHeight + 5) + 'px',
1333                    'left': buttonOffset.left + 'px',
1334                    'z-index': 9999
1335                }).appendTo('body').fadeIn(200);
1336                
1337                // Add shake animation to button
1338                button.addClass('shake-animation');
1339                
1340                // Remove tooltip and animation after 3 seconds
1341                setTimeout(function() {
1342                    tooltip.fadeOut(200, function() {
1343                        tooltip.remove();
1344                    });
1345                    button.removeClass('shake-animation');
1346                }, 3000);
1347                
1348                return false;
1349            }
1350            
1351            // If we have valid input but no preset variation, set up variation data
1352            if (hasValidInput && activeVariations.length === 0) {
1353                // Set the variation_id hidden input for custom amount
1354                var variationIdInput = variationsForm.find('input[name="variation_id"]');
1355                if (variationIdInput.length > 0) {
1356                    variationIdInput.val('custom-' + inputValue);
1357                }
1358                
1359                // Set the attribute value in the hidden select
1360                var attributeSelect = variationsForm.find('select[name="attribute_pa_lend-amount"]');
1361                if (attributeSelect.length > 0) {
1362                    attributeSelect.val('lend-' + inputValue);
1363                }
1364                
1365                // Trigger change event to notify WooCommerce
1366                attributeSelect.trigger('change');
1367            }
1368        });
1369
1370        /**
1371         * Helper function  to get texts for validation and errors
1372         * @since 1.2.0
1373         */
1374        function spark_open_price_events_texts($text_key, $min_amount, $max_amount){
1375            let return_text = '';
1376            switch ($text_key) {
1377                case 'please_enter_numbers_only' :
1378                    return_text = 'Please enter numbers only';
1379                    
1380                    if(digi_e_vars.lang == 'he') {
1381                        return_text = 'אנא הכנס מספרים בלבד';
1382                    }  
1383                    return return_text;
1384
1385                    break;
1386
1387                case 'minimum_amount_err_txt' :
1388                    return_text = 'Minimum amount is ' + $min_amount;
1389                    
1390                    if(digi_e_vars.lang == 'he') {
1391                        return_text = 'הסכום המינימלי הוא ' + $min_amount;
1392                    }  
1393                    return return_text;
1394
1395                    break;
1396
1397                case 'maximum_amount_err_txt' :
1398                    return_text = 'Maximum amount is ' + $max_amount;
1399                    
1400                    if(digi_e_vars.lang == 'he') {
1401                        return_text = 'הסכום המינימלי הוא ' + $max_amount;
1402                    }  
1403                    return return_text;
1404
1405                    break;
1406
1407                case 'add_to_cart_button_text' :
1408                    return_text = 'Lend Now';
1409                    
1410                    if(digi_e_vars.lang == 'he') {
1411                        return_text = 'הלוואה לעסק';
1412                    }  
1413                    return return_text;
1414
1415                    break;
1416
1417                case 'select_options_missimg_notification' :
1418                    return_text = 'Please Select an Option';
1419                    
1420                    if(digi_e_vars.lang == 'he') {
1421                        return_text = 'אנא בחר אפשרות';
1422                    }  
1423                    return return_text;
1424
1425                    break;
1426            }
1427
1428            return return_text;
1429        }
1430
1431
1432
1433        /**
1434         * Helper function to reset button text to "Select options"
1435         * @since 1.2.0
1436         * @param {jQuery} input - The input element that triggered the reset
1437         */
1438        function resetButtonToSelectOptions(input) {
1439            var productInfoWrap = input.closest('.product-info-wrap');
1440            var addWrap = productInfoWrap.find('.add-to-cart-grid');
1441            var variationsWrap = productInfoWrap.find('.nasa-product-content-variations');
1442
1443            let select_options_missimg_notification = spark_open_price_events_texts('select_options_missimg_notification', min_amount, max_amount);
1444            
1445            if (addWrap.hasClass('nasa-variable-add-to-cart-in-grid') && !$('body').hasClass('nasa-ywraq-hide-add-to-cart')) {
1446                // Get the "Select options" text from data attribute or fallback
1447                var selectText = variationsWrap.attr('data-select_text') || select_options_missimg_notification;
1448                
1449                // Reset button text and attributes
1450                addWrap.find('.add_to_cart_text').html(selectText);
1451                addWrap.attr('title', selectText);
1452                
1453                // Update tooltip if present
1454                if (addWrap.hasClass('nasa-tip')) {
1455                    addWrap.attr('data-tip', selectText);
1456                    
1457                    if (addWrap.find('.nasa-tip-content').length) {
1458                        addWrap.find('.nasa-tip-content').html(selectText);
1459                    }
1460                }
1461                
1462                // Deactivate the button by removing nasa-active class
1463                addWrap.removeClass('nasa-active');
1464            }
1465        }
1466
1467        /** ------------------------------------------------------------------------------------- */
1468        
1469      /** Programs filter icon toggle */  
1470        $(document).on('click', '#programs-filter-icon-toggle', function (e) {
1471            e.preventDefault();
1472    
1473            const $target = $("#programs-filter-search");
1474    
1475            // If it's currently visible, slide it up; otherwise, slide it down
1476            if ($target.is(':visible')) {
1477                $target.slideUp(200, function () {
1478                    $target.addClass('spark-hide'); // re-add the hidden class after animation
1479                });
1480            } else {
1481                $target.removeClass('spark-hide').hide().slideDown(200);
1482            }
1483        });
1484        
1485        /** Programs go to section after select*/
1486        $(document).on('change', '#programs-age-filter .spark-taxonomy-filter-select', function (e) {
1487            // Scroll smoothly to the target element
1488            $('html, body').animate({
1489                scrollTop: $('#programs-filter-icon-toggle').offset().top
1490            }, 600); // 600ms for smoothness
1491        });
1492
1493        /****
1494         * HP Tabs Products Slider   ----------------------------------------------------------
1495         * @since  2.1
1496        */
1497        
1498          // Helper: normalize NASA slider to single row on mobile
1499          function normalizeSliderToSingleRow($slider) {
1500            if (!$slider.length || $slider.data('normalized-mobile')) return;
1501        
1502            const isMobile = window.matchMedia('(max-width: 767px)').matches;
1503            if (!isMobile) return;
1504        
1505            if ($slider.hasClass('nasa-slide-double-row')) {
1506              //console.log('Normalizing NASA double-row → single row for:', $slider.attr('class'));
1507        
1508              // Unslick if initialized
1509              if ($slider.hasClass('slick-initialized')) {
1510                $slider.slick('unslick');
1511              }
1512        
1513              // Flatten DOM: one product per column
1514              const $newSlides = [];
1515              $slider.find('.nasa-wrap-column').each(function () {
1516                $(this).find('.product').each(function () {
1517                  $newSlides.push($('<div class="nasa-wrap-column"></div>').append($(this)));
1518                });
1519              });
1520        
1521              $slider.empty().append($newSlides);
1522              $slider.removeClass('nasa-slide-double-row');
1523        
1524              // Re-init Slick as a single-row slider
1525              const columns = parseInt($slider.data('columns-small'), 10) || 1;
1526              const tabletColumns = parseInt($slider.data('columns-tablet'), 10) || 2;
1527              const desktopColumns = parseInt($slider.data('columns'), 10) || 4;
1528        
1529              $slider.slick({
1530                rows: 1,
1531                slidesToShow: columns,
1532                slidesToScroll: 1,
1533                mobileFirst: true,
1534                rtl: $('html').attr('dir') === 'rtl',
1535                responsive: [
1536                  { breakpoint: 768, settings: { slidesToShow: tabletColumns, rows: 1 } },
1537                  { breakpoint: 1024, settings: { slidesToShow: desktopColumns, rows: 1 } },
1538                ],
1539              });
1540        
1541              $slider.data('normalized-mobile', true);
1542              //console.log('NASA slider rebuilt for mobile.');
1543            }
1544          }
1545        
1546        // Intercept "All Businesses" tab before Elementor handles it
1547        document.addEventListener(
1548          'click',
1549          function (e) {
1550            const el = e.target.closest('#hp-products-tabs .e-n-tab-title#all-tab');
1551            
1552            let redirect_to = '/lend/';
1553            
1554            if(digi_e_vars.lang == 'he') {
1555                redirect_to = '/he/lend/';
1556            }
1557            
1558            
1559            if (el) {
1560              e.preventDefault();            // stop default action
1561              e.stopImmediatePropagation();  // block Elementor’s listener
1562              e.stopPropagation();           // block bubbling
1563              window.location.href = redirect_to; // redirect immediately
1564            }
1565          },
1566          true // <--- capture phase: runs before Elementor's own click handler
1567        );
1568
1569
1570        // Listen for Elementor tab clicks
1571        $(document).on('click', '#hp-products-tabs .e-n-tab-title', function (e) {
1572            const $this = $(this);
1573            const targetId = $this.attr('aria-controls');
1574            const $targetPanel = $('#' + targetId);
1575        
1576            const waitForVisible = setInterval(function () {
1577              if ($targetPanel.is(':visible') && $targetPanel.height() > 0) {
1578                clearInterval(waitForVisible);
1579        
1580                const $tabsWrapper = $targetPanel.closest('.e-n-tabs-content');
1581                $tabsWrapper.css({ height: 'auto', overflow: 'visible' });
1582                $targetPanel.css({
1583                  height: 'auto',
1584                  opacity: 1,
1585                  visibility: 'visible',
1586                  transform: 'none',
1587                  display: 'block',
1588                });
1589        
1590                setTimeout(function () {
1591                  const $sliders = $targetPanel.find('.nasa-slick-slider');
1592        
1593                  $sliders.each(function () {
1594                    const $slider = $(this);
1595                    if ($slider.hasClass('slick-initialized')) {
1596                      $slider.slick('setPosition');
1597                    } else {
1598                      $slider.slick();
1599                    }
1600        
1601                    // Normalize NASA slider if on mobile
1602                    normalizeSliderToSingleRow($slider);
1603                  });
1604        
1605                  // Force browser reflow & repaint to fix “blank until scroll” issue
1606                  $targetPanel[0].style.willChange = 'transform';
1607                  void $targetPanel[0].offsetHeight;
1608                  $targetPanel[0].style.willChange = 'auto';
1609                  window.scrollBy(0, 1);
1610                  window.scrollBy(0, -1);
1611                }, 100);
1612              }
1613            }, 100);
1614          }); // #hp-products-tabs .e-n-tab-title onclick
1615
1616          $(document).on('click', '.spark-biz-gallery-slider .spark-gallery-nav', function(e) {
1617            e.preventDefault();
1618            
1619            var $btn = $(this);
1620            var $slider = $btn.closest('.spark-biz-gallery-slider');
1621            
1622            if (!$slider.length) {
1623              return;
1624            }
1625            
1626            var dir = parseInt($btn.attr('data-dir'), 10);
1627            if (isNaN(dir) || (dir !== 1 && dir !== -1)) {
1628              dir = 1;
1629            }
1630            
1631            var $slides = $slider.find('.spark-gallery-slide');
1632            var total = $slides.length;
1633            
1634            if (total < 2) {
1635              return;
1636            }
1637            
1638            var current = parseInt($slider.attr('data-current'), 10);
1639            if (isNaN(current)) {
1640              current = 0;
1641            }
1642            
1643            var next = current + dir;
1644            if (next < 0) {
1645              next = total - 1;
1646            }
1647            if (next >= total) {
1648              next = 0;
1649            }
1650            
1651            $slides.removeClass('is-active');
1652            $slider.find('.spark-gallery-slide[data-index="' + next + '"]').addClass('is-active');
1653            $slider.attr('data-current', String(next));
1654          });
1655
1656
1657
1658        /** End HP Tabs Products Slider ---------------------------------------*/
1659		
1660    }); // domContentLoaded
1661
1662})(window);
1663
1664;(function($){
1665  'use strict';
1666
1667  /**
1668   * Elementor Pro Taxonomy Filter - Dropdown + Ignore Other Filters
1669   *
1670   * Reads custom controls from `includes/elementor_filter_widget_custom.php` and applies frontend behavior:
1671   * - If wrapper has `spark-tax-filter-as-dropdown`, build a <select> from rendered buttons and hide the bar.
1672   * - If wrapper has `spark-tax-filter-ignore-yes`, clear other taxonomy filters before applying this one.
1673   *
1674   * Security/Performance/Data Privacy:
1675   * - No external requests; scoped DOM operations; URL cleaned with history.replaceState.
1676   * - Human readable code and comments.
1677   *
1678   * @since 2
1679   */
1680  function spark_register_taxonomy_filter_behavior() {
1681    if (typeof elementorFrontend === 'undefined' || !elementorFrontend.hooks) {
1682      return;
1683    }
1684    elementorFrontend.hooks.addAction('frontend/element_ready/taxonomy-filter.default', function(scope){
1685      var $scope = jQuery(scope);
1686
1687      // avoid double init on rerenders
1688      if ($scope.data('spark_dropdown_initialized')) {
1689        return;
1690      }
1691
1692      // detect settings via wrapper classes added by prefix_class
1693      var is_dropdown   = $scope.hasClass('spark-tax-filter-as-dropdown');
1694      var ignore_others = $scope.hasClass('spark-tax-filter-ignore-yes');
1695
1696      // Helper: enhance original buttons with taxonomy images (button mode only)
1697      function enhance_taxonomy_images($sc, $cont, $btns){
1698        var tax_img_enabled = $sc.attr('data-spark-tax-image') === 'yes';
1699        if (!tax_img_enabled) { return; }
1700        // If server-side already injected images/classes, skip AJAX enhancement
1701        if ($btns.filter('.spark-taxonomy-button').length || $btns.find('.spark-tax-image-wrap').length) {
1702          return;
1703        }
1704        try {
1705          var st = $sc.data('settings') || {};
1706          var taxonomy = st.taxonomy || null;
1707          var meta_key = $sc.attr('data-spark-tax-image-key') || '';
1708          var img_extra_class = $sc.attr('data-spark-tax-image-class') || '';
1709          if (!taxonomy || !meta_key) { return; }
1710
1711          var slugs = [];
1712          $btns.each(function(){
1713            var v = jQuery(this).data('filter');
1714            if (v && v !== '__all') { slugs.push(String(v)); }
1715          });
1716          if (!slugs.length) { return; }
1717
1718          jQuery.ajax({
1719            url: (typeof digi_e_vars !== 'undefined' ? digi_e_vars.ajaxurl : '/wp-admin/admin-ajax.php'),
1720            method: 'POST',
1721            dataType: 'json',
1722            data: {
1723              action: 'spark_get_tax_images',
1724              taxonomy: taxonomy,
1725              meta_key: meta_key,
1726              slugs: slugs
1727            }
1728          }).done(function(resp){
1729            var images = resp && resp.success && resp.data && resp.data.images ? resp.data.images : {};
1730            $btns.each(function(){
1731              var $btn = jQuery(this);
1732              var slug = String($btn.data('filter') || '');
1733              if (slug === '__all') { return; }
1734              var img_url = images[slug] || '';
1735              var label_text = ($btn.text() || '').trim();
1736              var safe_label = label_text.replace(/</g,'&lt;').replace(/>/g,'&gt;');
1737              if (img_url) {
1738                var img_cls = img_extra_class ? ' ' + img_extra_class : '';
1739                var html = '' +
1740                  '<span class="spark-tax-image-wrap">' +
1741                    '<img src="' + img_url + '" alt="' + safe_label + '" class="spark-tax-image' + img_cls + '" />' +
1742                  '</span>' +
1743                  '<span class="spark-tax-title-wrap">' + safe_label + '</span>';
1744                $btn.empty().append(html).addClass('spark-taxonomy-button');
1745              } else {
1746                var html2 = '<span class="spark-tax-title-wrap">' + safe_label + '</span>';
1747                $btn.empty().append(html2).addClass('spark-taxonomy-button');
1748              }
1749            });
1750          });
1751        } catch(e) {}
1752      }
1753
1754      // Observe class changes to handle live toggling in Elementor editor (both ON and OFF)
1755      if (!$scope.data('spark_class_observer_attached')) {
1756        try {
1757          var class_observer = new MutationObserver(function(mutations){
1758            mutations.forEach(function(m){
1759              if (m.attributeName !== 'class') return;
1760              var has_dropdown_now = $scope.hasClass('spark-tax-filter-as-dropdown');
1761              var built_now = !!$scope.data('spark_dropdown_initialized');
1762              var $container_now = $scope.find('.e-filter');
1763
1764              if (has_dropdown_now && !built_now) {
1765                // Build dropdown
1766                var $buttons_now = $container_now.find('.e-filter-item');
1767                if (!$buttons_now.length) return;
1768                var $select_now = jQuery('<select class="spark-taxonomy-filter-select" aria-label="Taxonomy filter"></select>');
1769                var all_label_now = $scope.attr('data-spark-dropdown-all-label') || 'All';
1770                var active_slugs_now = [];
1771                $buttons_now.filter('[aria-pressed="true"]').each(function(){
1772                  var slug = jQuery(this).data('filter');
1773                  if (typeof slug !== 'undefined') active_slugs_now.push(String(slug));
1774                });
1775                if (!active_slugs_now.length) active_slugs_now = ['__all'];
1776
1777                var $opt_all_now = jQuery('<option></option>').attr('value', '__all').text(all_label_now);
1778                if (active_slugs_now.indexOf('__all') !== -1) { $opt_all_now.prop('selected', true); }
1779                $select_now.append($opt_all_now);
1780
1781                $buttons_now.each(function(){
1782                  var $b = jQuery(this);
1783                  var val = String($b.data('filter'));
1784                  if (val === '__all') return;
1785                  var lbl = ($b.text() || '').trim();
1786                  var $op = jQuery('<option></option>').attr('value', val).text(lbl);
1787                  if (active_slugs_now.indexOf(val) !== -1) { $op.prop('selected', true); }
1788                  $select_now.append($op);
1789                });
1790
1791                $container_now.before($select_now);
1792                $container_now.attr('hidden', 'hidden');
1793
1794                $select_now.on('change', function(){
1795                  var sel = jQuery(this).val();
1796                  if ($scope.hasClass('spark-tax-filter-ignore-yes')) { clear_other_tax_filters($scope); }
1797                  var $t = $container_now.find('.e-filter-item[data-filter="' + sel + '"]');
1798                  if ($t.length) {
1799                    $t.trigger('click');
1800                  } else if (sel === '__all') {
1801                    try {
1802                      var st = $scope.data('settings') || {};
1803                      var se = st.selected_element || null;
1804                      var fid = $scope.data('id');
1805                      if (!fid) {
1806                        var mm = ($scope.attr('class') || '').match(/elementor-element-([a-f0-9]+)/i);
1807                        if (mm && mm[1]) { fid = mm[1]; }
1808                      }
1809                      if (se && fid && elementorProFrontend && elementorProFrontend.modules && elementorProFrontend.modules.taxonomyFilter) {
1810                        elementorProFrontend.modules.taxonomyFilter.removeFilterFromLoopWidget(se, fid, '');
1811                      }
1812                    } catch(e) {}
1813                  }
1814                });
1815
1816                $scope.data('spark_dropdown_initialized', true);
1817              }
1818
1819              if (!has_dropdown_now && built_now) {
1820                // Tear down dropdown
1821                $scope.find('select.spark-taxonomy-filter-select').remove();
1822                $container_now.removeAttr('hidden');
1823                $scope.removeData('spark_dropdown_initialized');
1824
1825                // Re-apply taxonomy images on returning to button mode
1826                var $buttons_now = $container_now.find('.e-filter-item');
1827                if ($buttons_now.length) {
1828                  enhance_taxonomy_images($scope, $container_now, $buttons_now);
1829                }
1830              }
1831            });
1832          });
1833          class_observer.observe($scope[0], { attributes: true, attributeFilter: ['class'] });
1834          $scope.data('spark_class_observer_attached', true);
1835        } catch(e) {}
1836      }
1837
1838      // If ignore-other-filters is enabled but widget is not dropdown, bind a lightweight handler
1839      // so interacting will clear other filters first. Use mousedown to run before Elementor's click.
1840      if (ignore_others && !is_dropdown) {
1841        $scope.find('.e-filter').off('mousedown.sparkIgnore').on('mousedown.sparkIgnore', '.e-filter-item', function(){
1842          clear_other_tax_filters($scope);
1843        });
1844      }
1845
1846      if (!is_dropdown) {
1847        // Editor fallback: if user toggles to dropdown in the editor, Elementor sometimes updates classes
1848        // without a full re-render. Poll briefly to detect the class and build the dropdown once.
1849        var tries = 0;
1850        var poll_id = setInterval(function(){
1851          tries++;
1852          if ($scope.hasClass('spark-tax-filter-as-dropdown') && !$scope.data('spark_dropdown_initialized')) {
1853            var $container_fb = $scope.find('.e-filter');
1854            if (!$container_fb.length) { return; }
1855            var $buttons_fb = $container_fb.find('.e-filter-item');
1856            if (!$buttons_fb.length) { return; }
1857
1858            var $select_fb = jQuery('<select class="spark-taxonomy-filter-select" aria-label="Taxonomy filter"></select>');
1859            var dropdown_all_label_fb = $scope.attr('data-spark-dropdown-all-label') || 'All';
1860
1861            var active_slugs_fb = [];
1862            $buttons_fb.filter('[aria-pressed="true"]').each(function(){
1863              var slug = jQuery(this).data('filter');
1864              if (typeof slug !== 'undefined') { active_slugs_fb.push(String(slug)); }
1865            });
1866            if (!active_slugs_fb.length) { active_slugs_fb = ['__all']; }
1867
1868            var $opt_all_fb = jQuery('<option></option>').attr('value', '__all').text(dropdown_all_label_fb);
1869            if (active_slugs_fb.indexOf('__all') !== -1) { $opt_all_fb.prop('selected', true); }
1870            $select_fb.append($opt_all_fb);
1871
1872            $buttons_fb.each(function(){
1873              var $btn  = jQuery(this);
1874              var value = String($btn.data('filter'));
1875              if (value === '__all') { return; }
1876              var label = ($btn.text() || '').trim();
1877              var $opt  = jQuery('<option></option>').attr('value', value).text(label);
1878              if (active_slugs_fb.indexOf(value) !== -1) { $opt.prop('selected', true); }
1879              $select_fb.append($opt);
1880            });
1881
1882            $container_fb.before($select_fb);
1883            $container_fb.attr('hidden', 'hidden');
1884
1885            // bind change like main path
1886            $select_fb.on('change', function(){
1887              var selected_value_fb = jQuery(this).val();
1888              if (ignore_others) { clear_other_tax_filters($scope); }
1889              var $target_fb = $container_fb.find('.e-filter-item[data-filter="' + selected_value_fb + '"]');
1890              if ($target_fb.length) {
1891                $target_fb.trigger('click');
1892              } else if (selected_value_fb === '__all') {
1893                try {
1894                  var settings_fb = $scope.data('settings') || {};
1895                  var selected_element_id_fb = settings_fb.selected_element || null;
1896                  var filter_id_fb = $scope.data('id');
1897                  if (!filter_id_fb) {
1898                    var m_fb = ($scope.attr('class') || '').match(/elementor-element-([a-f0-9]+)/i);
1899                    if (m_fb && m_fb[1]) { filter_id_fb = m_fb[1]; }
1900                  }
1901                  if (selected_element_id_fb && filter_id_fb && elementorProFrontend && elementorProFrontend.modules && elementorProFrontend.modules.taxonomyFilter) {
1902                    elementorProFrontend.modules.taxonomyFilter.removeFilterFromLoopWidget(selected_element_id_fb, filter_id_fb, '');
1903                  }
1904                } catch(e) {}
1905              }
1906            });
1907
1908            $scope.data('spark_dropdown_initialized', true);
1909            clearInterval(poll_id);
1910          }
1911          if (tries > 80) {
1912            clearInterval(poll_id);
1913          }
1914        }, 150);
1915        // Before exiting (button mode), enhance buttons with taxonomy images once
1916        var $cont_btn = $scope.find('.e-filter');
1917        var $btns_btn = $cont_btn.find('.e-filter-item');
1918        if ($cont_btn.length && $btns_btn.length) {
1919          enhance_taxonomy_images($scope, $cont_btn, $btns_btn);
1920        }
1921        return; // nothing else to do when not dropdown
1922      }
1923
1924      var $container = $scope.find('.e-filter');
1925      if (!$container.length) {
1926        return;
1927      }
1928
1929      var $buttons = $container.find('.e-filter-item');
1930      if (!$buttons.length) {
1931        return;
1932      }
1933
1934      // Note: taxonomy image enhancement runs only in button mode; skipped in dropdown mode
1935
1936      // build dropdown
1937      var $select = jQuery('<select class="spark-taxonomy-filter-select" aria-label="Taxonomy filter"></select>');
1938
1939      // read custom first option label from wrapper data attribute
1940      var dropdown_all_label = $scope.attr('data-spark-dropdown-all-label') || 'All';
1941
1942      // determine currently active slugs
1943      var active_slugs = [];
1944      $buttons.filter('[aria-pressed="true"]').each(function(){
1945        var slug = jQuery(this).data('filter');
1946        if (typeof slug !== 'undefined') {
1947          active_slugs.push(String(slug));
1948        }
1949      });
1950      if (!active_slugs.length) {
1951        active_slugs = ['__all'];
1952      }
1953
1954      // 1) add first option for clearing filter ("All")
1955      var $opt_all = jQuery('<option></option>').attr('value', '__all').text(dropdown_all_label);
1956      if (active_slugs.indexOf('__all') !== -1) {
1957        $opt_all.prop('selected', true);
1958      }
1959      $select.append($opt_all);
1960
1961      // 2) add other options, skipping the original __all button to avoid duplication
1962      $buttons.each(function(){
1963        var $btn  = jQuery(this);
1964        var value = String($btn.data('filter'));
1965        if (value === '__all') {
1966          return; // skip duplicate of first option
1967        }
1968        var label = ($btn.text() || '').trim();
1969        var $opt  = jQuery('<option></option>').attr('value', value).text(label);
1970        if (active_slugs.indexOf(value) !== -1) {
1971          $opt.prop('selected', true);
1972        }
1973        $select.append($opt);
1974      });
1975
1976      // insert and hide original bar (kept for accessibility and event wiring)
1977      $container.before($select);
1978      $container.attr('hidden', 'hidden');
1979
1980      /**
1981       * clear_other_tax_filters
1982       *
1983       * Reset other taxonomy-filter widgets to default (All) and remove their query params.
1984       * @param {jQuery} current_scope
1985       * @since 2
1986       */
1987      function clear_other_tax_filters(current_scope){
1988        // clean URL e-filter-* params
1989        try {
1990          var url_obj = new URL(window.location.href);
1991          var keys_to_delete = [];
1992
1993          url_obj.searchParams.forEach(function(_v, key){
1994            if (key.indexOf('e-filter-') === 0) {
1995              keys_to_delete.push(key);
1996            }
1997          });
1998
1999          if (keys_to_delete.length) {
2000            keys_to_delete.forEach(function(k){ url_obj.searchParams.delete(k); });
2001            var new_qs = url_obj.searchParams.toString();
2002            window.history.replaceState({}, '', url_obj.pathname + (new_qs ? '?' + new_qs : '') + url_obj.hash);
2003          }
2004        } catch(err) {
2005          // ignore silently
2006        }
2007
2008        // click "All" on other widgets to reset their state, or deactivate active terms if no All option exists
2009        jQuery('.elementor-widget-taxonomy-filter').each(function(){
2010          var $widget = jQuery(this);
2011          if ($widget.is(current_scope)) {
2012            return;
2013          }
2014          var $all_btn = $widget.find('.e-filter .e-filter-item[data-filter="__all"]');
2015          if ($all_btn.length) {
2016            if ($all_btn.attr('aria-pressed') !== 'true') {
2017              $all_btn.trigger('click');
2018            }
2019          } else {
2020            // No All button configured: deactivate any active terms to clear filter store
2021            var $active_terms = $widget.find('.e-filter .e-filter-item[aria-pressed="true"]');
2022            $active_terms.each(function(){
2023              var $btn = jQuery(this);
2024              var val = String($btn.data('filter'));
2025              if (val !== '__all') {
2026                $btn.trigger('click');
2027              }
2028            });
2029          }
2030
2031          // Final assurance: directly clear filter via Elementor API if available
2032          try {
2033            var w_settings = $widget.data('settings') || {};
2034            var w_selected_element = w_settings.selected_element || null;
2035            var w_filter_id = $widget.data('id');
2036            if (!w_filter_id) {
2037              var m2 = ($widget.attr('class') || '').match(/elementor-element-([a-f0-9]+)/i);
2038              if (m2 && m2[1]) { w_filter_id = m2[1]; }
2039            }
2040            if (w_selected_element && w_filter_id && elementorProFrontend && elementorProFrontend.modules && elementorProFrontend.modules.taxonomyFilter) {
2041              elementorProFrontend.modules.taxonomyFilter.removeFilterFromLoopWidget(w_selected_element, w_filter_id, '');
2042            }
2043          } catch(e) {}
2044        });
2045      }
2046
2047      // apply selection from dropdown
2048      $select.on('change', function(){
2049        var selected_value = jQuery(this).val();
2050
2051        if (ignore_others) {
2052          clear_other_tax_filters($scope);
2053        }
2054
2055        // delegate to built-in button logic for consistency
2056        var $target = $container.find('.e-filter-item[data-filter="' + selected_value + '"]');
2057        if ($target.length) {
2058          $target.trigger('click');
2059        } else if (selected_value === '__all') {
2060          // Fallback: widget may not render an "All" button; clear filter via public API
2061          try {
2062            var settings = $scope.data('settings') || {};
2063            var selected_element_id = settings.selected_element || null;
2064            var filter_id = $scope.data('id');
2065            if (!filter_id) {
2066              var m = ($scope.attr('class') || '').match(/elementor-element-([a-f0-9]+)/i);
2067              if (m && m[1]) { filter_id = m[1]; }
2068            }
2069            if (selected_element_id && filter_id && elementorProFrontend && elementorProFrontend.modules && elementorProFrontend.modules.taxonomyFilter) {
2070              elementorProFrontend.modules.taxonomyFilter.removeFilterFromLoopWidget(selected_element_id, filter_id, '');
2071            }
2072          } catch(e) {
2073            // ignore runtime errors
2074          }
2075        }
2076      });
2077
2078      $scope.data('spark_dropdown_initialized', true);
2079    });
2080  }
2081
2082  // Register immediately if Elementor is already initialized (covers editor preview load order)
2083  if (typeof elementorFrontend !== 'undefined' && elementorFrontend.hooks) {
2084    spark_register_taxonomy_filter_behavior();
2085  }
2086
2087  // Also register on the standard init event (covers normal frontend load order)
2088  $(window).on('elementor/frontend/init', function(){
2089    spark_register_taxonomy_filter_behavior();
2090  });
2091
2092})(jQuery);

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.