PageSourceSearch

https://www.anci.piemonte.it/wp-content/plugins/eventON/assets/js/eventon_functions.js?ver=5.0.13

js anci.piemonte.it collected 2026-09-24 11:24:00 UTC 84,288 bytes, 2,484 lines download raw bytes

1/**
2 * Javascript: EventON functions for all calendars
3 * @version: 5.0.13
4 * @license EventON JavaScript Assets 
5 * Copyright (C) 2014-2026 Ashan Jay, AshanJay Designs LLC.
6 * 
7 * PROPRIETARY LICENSE - All Rights Reserved
8 * 
9 * Permission granted solely for personal use with valid EventON license.
10 * YOU MAY NOT: redistribute, resell, sublicense, or publish these Assets.
11 * 
12 * Trademark: "EventON" is a trademark of AshanJay Designs LLC.
13 * Contact: [email protected]
14 * 
15 * PROVIDED "AS IS" WITHOUT WARRANTY. VIOLATION MAY RESULT IN LEGAL ACTION.
16 */
17
18jQuery(document).ready(function($) {
19
20	const BB = $('body');
21
22	// Basics
23		// Calendar function s
24			$.fn.evo_cal_functions = function(O){
25				const el = this;
26				switch(O.action){
27					// load shortcodes inside calendar data
28					case 'load_shortcodes':
29						return el.find('.evo_cal_data').data('sc');		
30					break;
31					case 'update_json':
32						//console.log(O.json);
33						el.find('.evo_cal_events').data('events', O.json);		
34					break;
35					case 'update_shortcodes':
36						//console.log(O.SC);
37						el.find('.evo_cal_data').data( 'sc', O.SC );
38					break;
39				}
40			};
41
42		// access page GLOBALS
43			$.fn.evo_get_global = function(opt){
44				var defaults = { S1:'', S2:''};
45				var OPT = $.extend({}, defaults, opt);
46
47				var BUS = $('#evo_global_data').data('d');
48
49				if(!(OPT.S1 in BUS)) return false;
50				if(!(OPT.S2 in BUS[OPT.S1])) return false;
51				return BUS[OPT.S1][OPT.S2];
52			}
53			$.fn.evo_get_txt = function(opt){
54				var defaults = { V:''}
55				var OPT = $.extend({}, defaults, opt);
56
57				var BUS = $('#evo_global_data').data('d');
58				//console.log(BUS);
59				if(!('txt' in BUS)) return false;
60				if(!(OPT.V in BUS.txt)) return false;
61				return BUS.txt[OPT.V];
62			}
63
64			// get translated text strings from ajax loaded data @4.6.4
65			$.fn.evo_lang = function(text){
66				var t = text.toLowerCase()
67				    .replace(/ /g, "_")
68				    .replace(/[^\w-]+/g, "");
69
70
71				var BUS = $('#evo_global_data').data('d');
72
73				if(!('txt' in BUS)) return text;
74				if(!(t in BUS.txt)) return text;
75				return BUS.txt[ t ];
76
77			}
78			$.fn.evo_get_cal_def = function(opt){
79				var defaults = { V:''}
80				var OPT = $.extend({}, defaults, opt);
81
82				var BUS = $('#evo_global_data').data('d');
83				if(!('cal_def' in BUS)) return false;
84				if(!(OPT.V in BUS.cal_def)) return false;
85				return BUS.cal_def[OPT.V];
86			}
87
88			// return dms translates values from global data
89			// added 4.0
90			$.fn.evo_get_dms_vals = function(opt){
91				// type = d, d1,d3, m, m3
92				// V = 0-x
93				var defaults = { type:'d', V:''}
94				var OPT = $.extend({}, defaults, opt);
95
96				var BUS = $('#evo_global_data').data('d');			
97				if(!('dms' in BUS)) return false;
98				if(!(OPT.type in BUS.dms)) return false;
99
100				return BUS.dms[ OPT.type ][ OPT.V ];
101				
102			}
103
104	// GENERAL AJAX ACCESS @4.7.2 updated @4.9.2
105		$.fn.evo_admin_get_ajax = function(opt){
106
107			var el = $(this);
108
109  			var OO = this.evo_process_ajax_params( opt );
110
111
112  			var _lbdata = OO.lbdata;
113			var _adata = OO.adata;	
114			var _populate_id = OO._populate_id;	
115
116			// Allow custom success callback to be passed in opt -- 4.9.2    		
117    		var customBefore = typeof opt.onBefore === 'function' ? opt.onBefore : null;   // New onBefore callback
118		    var customSuccess = typeof opt.onSuccess === 'function' ? opt.onSuccess : (typeof opt.success === 'function' ? opt.success : null); 
119		    	// Rename to onSuccess, keep backward compatibility with 'success'
120		    var customSuccess_Extra = typeof opt.successExtra === 'function' ? opt.successExtra : null; // this will run with default ajax
121		    var customComplete = typeof opt.onComplete === 'function' ? opt.onComplete : null; // New onComplete callback
122
123			var ajax_url = el.evo_get_ajax_url({a: _adata.a, e: _adata.end, type: _adata.ajax_type});
124
125			// for lightbox
126				var LB = false;
127	  			if( _lbdata.class != '') LB = $('body').find('.evo_lightbox.'+ _lbdata.class );
128
129
130	  		// Run AJAX
131	  		let ajaxResponse = '';
132  			$.ajax({
133				beforeSend: function(){
134					if (customBefore) {   customBefore.call(el, OO, LB); } // Call with onBefore:function(OO, LB){}
135					el.evo_perform_ajax_run_loader( OO, LB, 'start'  );
136				},
137				type: 'POST', url: ajax_url, data: _adata.data,	dataType:'json',
138				success:function(data){	
139					ajaxResponse = data;
140					//console.log(data);
141					// If a custom success callback is provided, use it
142		            if (customSuccess) {
143		                customSuccess.call(el, OO, data, LB); // Call with onSuccess:function( OO, data, LB){} 
144		                // call data with data.data
145		                // Trigger a custom event for onSuccess - 4.9.11
146		                $('body').trigger('evo_ajax_success_' + OO.uid,[ OO, data , el]);	
147		            } else {
148		                // Otherwise, use the default success behavior
149		                el.evo_perform_ajax_success(OO, data, LB);
150		                if( customSuccess_Extra ) customSuccess_Extra.call( el, OO, data, LB );
151		            }
152
153				},complete:function(){
154					if (customComplete) {     customComplete.call(el, OO, ajaxResponse, LB);  } // Call with onSuccess:function( OO, data, LB){} 
155					el.evo_perform_ajax_run_loader( OO, LB, 'end'  );
156					
157				}
158			});				
159		}
160
161		// submit forms via ligtbox
162		// @since 4.2.2		@updated 4.8
163		$.fn.evo_ajax_form_submit = function( opt , boxtype , formObj){
164			const el = this;	
165
166
167  			var OO = this.evo_process_ajax_params( opt );
168
169  			//console.log(OO);
170
171  			var _lbdata = OO.lbdata;
172  			var _spdata = OO.spdata;
173			var _adata = OO.adata;	
174			var _populate_id = OO._populate_id;	
175  			  			
176  			// get parent element
177  			var parent = '';
178  			if( boxtype == 'sp') parent = el.closest('.evosp_in');
179  			if( boxtype == 'lb'){
180  				parent = el.closest('.evo_lightbox');
181  				if( _lbdata.class != '') parent = $('body').find('.evo_lightbox.'+ _lbdata.class );
182  			} 
183
184  			var form = parent.find('form');
185  			if( formObj !== undefined ) form = formObj;
186
187  			if( form.length == 0){ console.log('No Fom object found'); return;}
188
189  			// form required fields validation - @4.9
190			if( el.hasClass('validate')){
191
192				var hasError = false;
193				$('body').trigger('evo_elm_form_presubmit_validation', [form, function(isValid) {
194				    hasError =  isValid ? false: true;
195				}]);
196			    if( hasError){
197			    	el.evo_snackbar({message: 'Required fields missing' });
198			    	//LB.evo_lightbox_show_msg({message:'Required fields missing'});
199			    	return;
200			    }	
201			}
202
203
204  			// reset LB message
205  			if( boxtype == 'lb') parent.evo_lightbox_hide_msg();
206
207  			var ajax_url = el.evo_get_ajax_url({a: _adata.a, e: _adata.end, type: _adata.ajax_type});
208
209
210  			// Add passed on data from ajax object @4.8.2
211			var extra_ajax_data = ('data' in _adata ) ? _adata.data : null;
212
213			let ajaxResponse = '';
214	  			
215  			// Submit form
216				form.ajaxSubmit({
217					beforeSubmit: function(opt, xhr){
218						el.evo_perform_ajax_run_loader( OO, parent, 'start', boxtype  );
219					},
220					dataType: 	'json',	
221					url: ajax_url,	type: 	'POST',
222					data: extra_ajax_data,
223					success:function(data){
224						//console.log(data);
225						ajaxResponse = data;
226						el.evo_perform_ajax_success( OO, data, parent , boxtype);
227					},
228					complete:function(){	
229						el.evo_perform_ajax_run_loader( OO, parent, 'end' , boxtype , ajaxResponse);
230					}
231				});
232		}
233		$.fn.evo_ajax_lightbox_form_submit = function(opt , formObj ){			
234  			this.evo_ajax_form_submit( opt, 'lb', formObj );
235		}
236
237	// perform ajax functions / type = start/end
238		$.fn.evo_perform_ajax_run_loader = function( OO , LB, type , boxtype, ajaxResponse){
239			var el = this;
240			var _lbdata = OO.lbdata;
241			var _adata = OO.adata;	
242			var _spdata = OO.spdata;	
243
244			var customer_loader_elm = false;
245			var loader_btn_el = false;
246			var loader_in_icon = false;
247
248  			if( _adata.loader_el !='')	customer_loader_elm = _adata.loader_el;
249  			if( 'loader_class' in _adata && _adata.loader_class != '') 
250  				customer_loader_elm = $('.' + _adata.loader_class);
251  			if( _adata.loader_btn_el != '' && _adata.loader_btn_el !== undefined ) loader_btn_el = el;
252  			if( _adata.loader_in_icon != '' && _adata.loader_in_icon !== undefined ) loader_in_icon = el;
253  			
254  			var LB_loader = false;
255  			if( LB && 'loader' in _lbdata && _lbdata.loader ) LB_loader = true;
256
257  			if( type == 'start'){
258
259  				var trigger_id = ( 'uid' in OO && OO.uid != '' ) ? OO.uid : OO.ajax_action; // @4.8
260  				$('body').trigger('evo_ajax_beforesend_' + trigger_id ,[ OO, el ]);
261
262				if( LB_loader ){
263					LB.find('.ajde_popup_text').addClass( 'evoloading'); // legacy
264					LB.evo_lightbox_start_inloading();
265				}
266				if( customer_loader_elm ) $( customer_loader_elm ).addClass('evoloading ');
267				if( loader_btn_el ) el.addClass('evobtn_loader'); // loader on button
268				if( loader_in_icon ) el.addClass('evoloader_icon'); // Loader in Icon (replace i.fa child with loader elm) @5.0.3
269  			
270			// COMPLETE
271  			}else{
272
273  				var trigger_id = ( 'uid' in OO && OO.uid != '' ) ? OO.uid : OO.ajax_action; // @4.8
274  				if( trigger_id === undefined ) trigger_id = OO.adata.a;
275  				//console.log(OO);
276
277  				$('body').trigger('evo_ajax_complete_' + trigger_id ,[ OO , el ]);
278			
279				if( LB_loader ){
280					LB.find('.ajde_popup_text').removeClass( 'evoloading');
281					LB.evo_lightbox_stop_inloading();	
282				}
283				if( customer_loader_elm ) $( customer_loader_elm ).removeClass('evoloading');
284				if( loader_btn_el ) el.removeClass('evobtn_loader'); // loader on button
285				if( 'loader_btn_el_done' in _adata && _adata.loader_btn_el_done ){
286					if( ajaxResponse.success ) el.removeClass('evobtn_loader success' );
287				} 
288				if( loader_in_icon ) el.removeClass('evoloader_icon'); // Loader in Icon (replace i.fa child with loader elm) @5.0.3				
289  			}
290
291			return {
292				'l1': customer_loader_elm,
293				'l2':LB_loader
294			};
295		}
296
297		$.fn.evo_perform_ajax_success = function ( OO, data, LB , boxtype){
298			var el = this;
299			var _lbdata = OO.lbdata;
300			var _adata = OO.adata;	
301			var _spdata = OO.spdata;	
302
303			var _populate_id = OO._populate_id;	
304			if( '_populate_id' in _adata ) 	_populate_id = _adata._populate_id;
305
306			if( !data || data === undefined ) return;
307
308
309			// if json is passing data object @4.9
310			var _success = ('success' in data) ? data.success : (data.status === 'good');
311
312			var extractedContent = 'content' in data ? data.content: '';
313			if( 'data' in data && 'content' in data.data) extractedContent = data.data.content;
314			var extractedData = ('data' in data) ? data.data : data;
315			extractedData['content'] = extractedContent;
316
317			// Ensure extractedData is an object for property checks; if it’s a string, wrap it
318		    if (typeof extractedData !== 'object' || extractedData === null) {
319		        extractedData = { msg: extractedData }; // Convert string to object
320		    }
321
322		    // Assign success and status to the extracted data
323		    extractedData.success = _success;
324		    extractedData.status = ('status' in extractedData) ? extractedData.status : (_success ? 'good' : 'bad');
325
326		    // Replace original data with processed data
327		    data = extractedData;
328
329		    //console.log(data);
330			//console.log( OO);
331
332			// if inside lightbox
333			if( LB.length > 0 && boxtype != 'sp'){
334				//console.log('show lb msg');
335				// show message
336					if (data && typeof data === 'object' && !Array.isArray(data) && 'msg' in data && data.msg !== '') {
337						LB.evo_lightbox_show_msg({
338							'type': ( _success ? 'good':'bad'), 
339							'message': ( data.msg ? data.msg : (data.data.msg ? data.data.msg : '') ), 
340							hide_lightbox: (  _success ? _lbdata.hide : false ),	
341							hide_message: _lbdata.hide_msg
342						});
343					}	
344
345				// populate lightbox
346				if( data && _lbdata.new_content && 'content' in data && data.content != '' ){
347
348					// populate a specific dom element with content
349					if( _populate_id ){
350						$('body').find('#'+_populate_id ).replaceWith( data.content );					
351					}else{
352						LB.evo_lightbox_populate_content({content: data.content});
353					}
354				}	
355								
356			}else{
357				// populate content
358				if( data && _populate_id && extractedContent != ''){
359					$('body').find('#'+_populate_id ).html( extractedContent );
360				}						
361			}
362
363			// Show snackbar message
364				if( 'show_snackbar' in  _adata && ('msg' in data)  && data.msg != '' ) {
365					el.evo_snackbar({message: data.msg});
366				}
367
368			// populate content with matching DOM class names, will set new html @4.7.2
369				if( data && 'populate_dom_classes' in data){
370					$.each( data.populate_dom_classes, function( domclass, content){
371						$('body').find('.'+ domclass).html( content );
372					} );
373				}
374
375			// Replace Content with new content DOM class match @since 5.0.9
376				if( data && 'replace_dom_classes' in data){
377					$.each( data.replace_dom_classes, function( domclass, content){
378						$('body').find('.'+ domclass).replaceWith( content );
379					} );
380				}
381
382			// if ajax data pass dom content to be replaced with run through each and replace - @4.2.3
383				if(data &&  'refresh_dom_content' in data ){
384					$.each(data.refresh_dom_content, function(domid, content){
385						$('body').find('#'+ domid).replaceWith( content);
386					});
387				}
388
389			// Trigger success actions @5.0.3
390			// call like 'trig_success'=> [ ['evosp_trig_close', ['delay'=> 2000] ] ]
391				if( _success &&  'trig_success' in _adata ){
392					$.each( _adata.trig_success, function(i, item) {
393						 var event_name = item[0];
394				        var extra_data = item[1] || {};   // parameters object (or {} if none)
395				        $('body').trigger( event_name, [ extra_data ] );
396				    });
397				}
398
399			// SIDE PANEL ACTIONS
400				// for SP content @since 4.5.2
401					if(data &&  'sp_content' in data){
402						if( 'load_new_content_id' in OO){
403							BB.find('#'+ OO.load_new_content_id).html( data.sp_content );
404						}else{
405							$("body").find('.evops_content').html( data.sp_content);
406						}
407						
408					}
409				// SP footer content @since 4.5.2
410					if( data && 'sp_content_foot' in data){
411						$("body").find('.evosp_foot_in').html( data.sp_content_foot);
412					}
413
414				// SP Show message @ since 5.0.13
415					if( data && 'sp_show_msg' in data){
416						BB.evo_showmsg_sidepanel( data.sp_show_msg , _spdata);
417					}
418			// process trumbowyg editors
419				$('body').trigger('evo_elm_load_interactivity');
420
421
422			// assign dynamic vals to DOM element
423				setTimeout(function(){
424					if( 'evoelms' in data ){
425						$.each( data.evoelms , function( uniqueid, elm_data ){
426
427							$('body').find('.has_dynamic_vals').each(function(){
428
429								if( $(this).attr('id') != uniqueid ) return;
430								var dynamic_elm = $(this);
431
432								$.each( elm_data , function( elm_key, elmv){
433									dynamic_elm.data( elm_key, elmv );
434								});
435							});
436						});
437					}
438				},200);
439
440
441			// call like $('body').on('evo_ajax_success_X', function(event, OO, data, el){
442			$('body').trigger('evo_ajax_success_' + OO.uid,[ OO, data , el]);	
443		}
444
445	// Process ajax and lightbox values @4.7.2 @updated 5.0.13
446		$.fn.evo_process_ajax_params = function ( opt ){
447			// defaults
448			var defz = { 
449				'uid':'',
450
451				// @since 4.7.2
452				'adata':{}, // @4.7.2 include all ajax data in here, type (ajax,rest,endpoint),action/a, other data
453				'lbdata':{},// @4.7.2 lightbox data all in one place, class, title, size, padding
454				'spdata':{},// @5.0.3 side panel data all in one place, class, title, size, padding, ajax_data
455				'_populate_id':'', // loading new content into matching elements outside of lightbox
456				
457				// legacy values
458				'content':'',// passed on dynamic content
459				'content_id' :'',// id to get dynamic content from page		
460								
461				't':'', //title
462				'lbc':'',// * lightbox class - REQUIRED
463				'lbac':'',// ligthbox additional class 4.6
464				'lbsz':'',// lightbox size = mid small, s400, s500, s700, s800
465				'lightbox_loader': true,
466				'preload_temp_key': 'init', // 4.6
467				'load_new_content': true, // @since 4.3.5
468				'lb_padding': '', // @4.3.5
469				'load_new_content_id':'',
470
471				'ajax':'no',// use ajax to load content yes no
472				'ajax_url':'',// load content from ajax file
473				'end':'admin',// admin or client end
474				'ajax_action':'', // @4.4 pass on ajax endpoint action key
475				'a':'',
476				'ajax_type':'ajax', // @4.4 ajax type, ajax, rest or endpoint
477				'd':'', // data object for ajax
478				'other_data':'',
479				'ajaxdata':'',				
480			};
481
482
483			// extend passed with defaults
484			var OO = $.extend({}, defz, opt);
485
486			// Build processed object
487				var processed = {};
488				processed['uid'] = OO.uid;
489
490
491			// Ajax	
492				var _adata = ( OO.adata == '') ? {}: OO.adata;
493
494				// type passed value fix
495				var passed_type_val = false;
496				if( 'type' in _adata && _adata.type != '' &&
497					!['ajax', 'rest', 'endpoint'].includes(_adata.type)
498				){
499					passed_type_val = _adata.type;
500					_adata.type = '';
501				}
502
503				// set default needed values
504				var def_avals = { 
505					'a':'',
506					'type':'ajax',
507					'end':'admin',
508					'data': '',
509					'loader_el':'',
510					'loader_btn_el':'',//4.8
511					'loader_btn_el_done':'', // 5.0.9
512					'loader_class':'',
513					'url':'',
514					'trig_success':[], // @5.0.3 trigger actions to run on success
515				}
516				
517				// set default values
518				$.each( def_avals, function(key, value) {					
519					if( key == 'data' && !( 'a' in _adata ) && ('data' in _adata ) && 'a' in _adata.data ) return;
520					if( !(key in _adata ) && value != '' ) _adata[ key ] = value;
521				});	
522
523				//console.log( _adata );
524
525				// map old to new
526				var def_adata_mapping = { 
527					'a' : 'a',
528					'ajax_action' : 'a',
529					'ajax_type':'type',
530					'end': 'end',
531					'ajax_url': 'url',
532					'ajaxdata':'data',
533					'ajax_data':'data',
534					'd':'data',
535				}
536				$.each( def_adata_mapping, function(oldV, newV) {					
537					if( newV in _adata && _adata[ newV ] != '' ) return;
538
539					if(  oldV in OO && OO[oldV] !== '' ) {
540						_adata[newV] = OO[oldV];
541					}  
542				});	
543
544				if( _adata.data === undefined ) _adata.data = {};
545
546				//console.log( _adata );			
547
548				// Move additional values in _adata to _adata.data
549					$.each(_adata, function(key, value) {
550						if ( !(key in def_avals)) {
551							//_adata.data[key] = value; // Move any extra values to _adata.data
552							//delete _adata[key]; // Remove them from the main _adata object
553						}
554					});
555
556				if( 'data' in _adata ){
557					//_adata['data']['nn'] = ( _adata.end == 'client' ) ? evo_general_params.n : evo_admin_ajax_handle.postnonce; 
558										
559					_adata['data']['nn'] = (typeof evo_admin_ajax_handle !== 'undefined' && evo_admin_ajax_handle !== null) 
560					    ? evo_admin_ajax_handle.postnonce 
561					    : evo_general_params.n;
562
563
564					_adata['data']['uid'] = processed['uid'];
565					if( passed_type_val ) _adata['data']['type'] = passed_type_val;
566					if( 'action' in _adata.data ) _adata['a'] =  _adata.data.action;
567					if( 'a' in _adata.data ) _adata['a'] =  _adata.data.a;
568					if( 'ajaxdata' in OO ) processed['ajaxdata'] = _adata.data;
569				}		
570
571				processed['adata'] = _adata;
572				
573
574			// lightbox
575				var _lbdata = ( OO.lbdata == '') ? {}: OO.lbdata;
576
577				// if legacy values exists > convert them to new
578				var def_lbdata_mapping = {
579					'lbc':'class',
580				    'lbsz':'size',
581				    'lbac' :'additional_class',
582				    't':'title',
583				    'lb_padding': 'padding',
584				    'load_new_content':'new_content',
585				    'lightbox_loader': 'loader',
586				    'content_id':'content_id',
587				    'content':'content',
588				    'hide_lightbox':'hide',
589				    'hide_message':'hide_msg',
590				    'lightbox_key': 'class',
591				}
592				$.each( def_lbdata_mapping, function(oldV, newV) {
593					// if _lbdata has new value > skip
594					if (newV in _lbdata && _lbdata[newV] !== '' && _lbdata[newV] !== null && _lbdata[newV] !== undefined) {
595				        return; 
596				    }
597					if(  oldV in OO && OO[oldV] !== '' ) {
598						_lbdata[newV] = OO[oldV];
599					} 
600				});	
601
602				// set default needed values
603				var def_lbvals = {
604					'padding':'evopad30',
605					'loader': false,
606					'preload_temp_key':'init',
607					'new_content': true,
608					'additional_class':'',
609					'title':'',
610					'hide':false,
611					'hide_msg':2000,
612					'content':'', // content for lightbox
613					'content_id':'', // content id in DOM to grab content for lightbox
614				}
615				// set default values
616				$.each( def_lbvals, function(key, value) {
617					if(  key in _lbdata )  return;
618					if( value == '') return;
619					_lbdata[ key ] = value;
620				});
621
622
623				//console.log( _lbdata.new_content ) ;
624
625				// load lightbox content legacy
626				if( OO.ajaxdata.load_lbcontent ) _lbdata['new_content'] = true;
627				if( OO.ajaxdata.load_new_content ) _lbdata['new_content'] = true;
628
629				// populate new content @4.7.3
630					processed['_populate_id'] =  false;
631					if( OO._populate_id != '')  processed['_populate_id'] = OO._populate_id;
632					if( OO.load_new_content_id != '')  processed['_populate_id'] = OO.load_new_content_id;
633					if( 'new_content_id' in _lbdata && _lbdata.new_content_id != '')  processed['_populate_id'] = _lbdata.new_content_id;
634					if( 'content_id' in _lbdata && _lbdata.content_id != '') processed['_populate_id'] = _lbdata.content_id;
635
636				processed['lbdata'] = _lbdata;
637
638			// make sure uid is moved to main level
639				if( processed.uid == '' && 'uid' in processed['lbdata'] ) processed['uid'] = processed['lbdata']['uid'];
640
641			// add legacy variables for backward compatibility
642				$.each(opt, function(oldkey, oldval){
643					if( oldkey in processed ) return;
644					processed[ oldkey ] = oldval;
645				});
646
647			// Side Panel
648				var _spdata = ( OO.spdata == '' ) ? {} : OO.spdata;
649				// set default needed values
650				var def_spvals = {
651					'class':'',
652					'loader': false,
653					'new_content': true,
654					'additional_class':'',
655					'title':'',
656					'hide':false,
657					'hide_msg':2000,
658					'content':'', // content for sp
659					'content_id':'', // content id in DOM to grab content for sp
660					'size':'',
661				}
662				// set default values
663				$.each( def_spvals, function(key, value) {
664					if(  key in _lbdata )  return;
665					if( value == '') return;
666					_lbdata[ key ] = value;
667				});
668
669			//console.log( processed );
670
671			return processed;
672		}
673
674	// LIGHTBOX triggers
675		// @version 4.2
676		$('body').on('click','.evolb_trigger', function(event){
677			if( event !== undefined ){
678				event.preventDefault();
679				event.stopPropagation();
680			}
681				
682			$(this).evo_lightbox_open(
683				$(this).data('lbvals') ?? $(this).data('d')
684			);
685		});
686		$('body').on('click','.evolb_close_btn', function (){
687			const LB = $(this).closest('.evo_lightbox');
688			LB.evo_lightbox_close();
689		});
690
691		// save form content - @since 4.2.2
692		$('body').on('click','.evolb_trigger_save, .evo_submit_form', function(event){
693			if( event !== undefined ){	event.preventDefault();	event.stopPropagation();	}
694
695			$(this).evo_ajax_form_submit( $(this).data('d') , ( $(this).closest('.evo_lightbox').length ? 'lb':'') );
696		});
697
698		$('body').on('click','.evo_trigger_ajax_run', function(event){
699			if( event !== undefined ){
700				event.preventDefault();
701				event.stopPropagation();
702			}
703
704			//console.log($(this).data('d') );
705			$(this).evo_admin_get_ajax( $(this).data('d') );
706		});
707		// @since 4.3.3
708		$('body').on('evo_lightbox_trigger', function(event, data){
709			event.preventDefault();
710			//console.log( data );
711			$('body').evo_lightbox_open(data);
712		});
713
714	// Lightbox opening	
715	// @updated 4.9.11	
716		$.fn.evo_alert = function(opt){ // @since 4.9.2
717			var defz = { 
718		        'title': 'Confirmation Action',
719		        'message': '',
720		        'yes_text': 'Proceed',
721		        'no_text': 'No',
722		        'on_yes': function() {}, // Callback for Yes
723		        'on_no': function() {}   // Callback for No
724		    };	
725
726		    // Extend passed options with defaults
727		    var options = $.extend({}, defz, opt);
728
729		    // Create alert HTML content
730		    var alertHtml = '<div class="evo_alert_box">' +
731		        '<p class="evotal evopad10i">' + options.message + '</p>' +
732		        '<div class="evo_alert_buttons evotar">' +		            
733		            '<button class="evo_alert_no evoboxsn evobrn evooln evocurp evohoop7 evopad10-20 evobr20 evobgclt">
733' + options.no_text + '</button>' +
734		            '<button class="evo_alert_yes evoboxsn evobrn evooln evocurp evoHbgc1 evopad10-20 evobr20 evomarr10 evobgclp evoclw">' + options.yes_text + '</button>' +
735		        '</div></div>';
736
737		    // Define lightbox options with the alert content
738		    var lightboxOptions = {
739		        lbdata: {
740		            class: 'evo_alert_lightbox',
741		            title: options.title || 'Alert',
742		            content: alertHtml, // Set the alert HTML as the lightbox content
743		            padding: 'pad20', // Optional: Add padding class if needed
744		            size:'small',
745		        },
746		    };
747
748		    // Open the lightbox with the alert content
749		    $(this).evo_lightbox_open(lightboxOptions);
750
751		    // After the lightbox is opened, attach event handlers
752		    setTimeout(function() {
753		        var LIGHTBOX = $('.evo_lightbox.evo_alert_lightbox');
754		        
755		        LIGHTBOX.find('.evo_alert_yes').on('click', function() {
756		        	var shouldClose = options.on_yes(LIGHTBOX);// Execute Yes callback
757		        	console.log(shouldClose);
758		        	if (shouldClose !== false) {
759		        		LIGHTBOX.evo_lightbox_close(); // Close the lightbox
760		        	}
761		            removeKeyListeners(); // Remove key listeners
762		        });
763
764		        LIGHTBOX.find('.evo_alert_no').on('click', function() {
765		            options.on_no(LIGHTBOX); // Execute No callback
766		            LIGHTBOX.evo_lightbox_close(); // Close the lightbox
767		            removeKeyListeners(); // Remove key listeners
768		        });
769
770		        // Keypress handler function
771		        function handleKeyPress(event) {
772		            if (event.key === 'Escape') { // Esc key
773		                options.on_no(LIGHTBOX); // Execute No callback
774		                LIGHTBOX.remove(); // Close the lightbox
775		                removeKeyListeners(); // Remove key listeners
776		            } else if (event.key === 'Enter') { // Enter key
777		                options.on_yes(LIGHTBOX); // Execute Yes callback
778		                LIGHTBOX.remove(); // Close the lightbox
779		                removeKeyListeners(); // Remove key listeners
780		            }
781		        }
782
783		        // Add keypress listener
784		        $(document).on('keydown', handleKeyPress);
785
786		        // Function to remove key listeners
787		        function removeKeyListeners() {
788		            $(document).off('keydown', handleKeyPress);
789		        }
790
791		        // Ensure key listeners are removed when lightbox is closed manually (e.g., via close button)
792		        LIGHTBOX.find('.evolb_close_btn').on('click', function() {
793		            removeKeyListeners();
794		        });
795		    }, 350); // Delay to ensure lightbox is fully rendered
796		}
797		$.fn.evo_lightbox_open = function (opt ){
798
799			var OO = this.evo_process_ajax_params( opt );
800			
801			var _lbdata = OO.lbdata;
802			var _adata = OO.adata;
803			var _populate_id = OO._populate_id;
804
805			//console.log(opt);
806			//console.log(OO);
807			
808
809			// check if required values missing for lightbox
810			if( !('class' in _lbdata) || _lbdata.class == '' ) return;
811
812
813			const fl_footer = _adata.end == 'client' ? '<div class="evolb_footer"></div>' :'';
814
815			// create lightbox HTML
816				var __lb_size = _lbdata.size === undefined ? '' : _lbdata.size;
817
818				// zindex
819				let openBoxes = 0;
820				openBoxes = $('.evo_lightbox.show, .evosp_one.show').length;
821				zIndex = 950000+ openBoxes;
822
823				var html = '<div class="evo_lightbox '+_lbdata.class+' '+_adata.end+' '+ ( _lbdata.additional_class !== undefined ? _lbdata.additional_class :'') +'" data-lbc="'+_lbdata.class+'" style="z-index:'+ zIndex + '"><div class="evolb_content_in"><div class="evolb_content_inin"><div class="evolb_box '+_lbdata.class+' '+ __lb_size +'"><div class="evolb_header"><a class="evolb_backbtn" style="display:none"><i class="fa fa-angle-left"></i></a>';
824				if( _lbdata.title !== undefined ) html += '<p class="evolb_title">' + _lbdata.title + '</p>';
825				html += '<span class="evolb_close_btn evolbclose "><i class="fa fa-xmark"><i></span></div><div class="evolb_content '+ _lbdata.padding +'"></div><p class="message"></p>'+fl_footer+'</div></div></div></div>';
826
827			$('#evo_lightboxes').append( html );	
828			const lbCount = $('#evo_lightboxes').find('.evo_lightbox').length;
829
830			var LIGHTBOX = $('.evo_lightbox.'+ _lbdata.class );		
831			if( $('.evo_sp').hasClass('show')) LIGHTBOX.addClass('aboveSP');
832
833			
834			// Open lightbox on page
835				setTimeout( function(){ 
836					$('#evo_lightboxes').show();
837					LIGHTBOX.addClass('show');	
838					$('body').addClass('evo_overflow');
839					$('html').addClass('evo_overflow');
840				},300);
841
842				// show loading animation
843				LIGHTBOX.evo_lightbox_show_open_animation(OO);
844
845
846			// Load content locally from DOM
847			    if (_lbdata.content_id != '') {
848			        var content = $('#' + _lbdata.content_id).html();
849			        LIGHTBOX.find('.evolb_content').html(content);
850			    }
851			    if (_lbdata.content != '') {
852			        LIGHTBOX.find('.evolb_content').html(_lbdata.content);
853			    }
854
855			// run ajax to load content for the lightbox inside
856				if( 'a' in _adata  && _adata.a != ''){ // @4.7.2
857					LB.evo_admin_get_ajax( OO );
858				}
859				
860			// load content from a AJAX file			
861				if( 'url' in _adata && _adata.url != '' ){
862					$.ajax({
863						beforeSend: function(){},
864						url:	OO.ajax_url,
865						success:function(data){
866							LIGHTBOX.find('.evolb_content').html( data);							
867						},complete:function(){}
868					});
869				}
870			
871			$('body').trigger('evo_lightbox_processed', [ OO, LIGHTBOX]);
872		}
873
874		// support close lightbox with click outside @since 5.0.10
875		let isMouseDownInside = false;
876		$(document).on('mousedown', '.evo_lightbox', function(e) {
877		    // Check if mousedown happened inside the actual lightbox content
878		    isMouseDownInside = $(e.target).closest('.evolb_box, .evo_lightbox_body').length > 0;
879		});
880		$(document).on('click', '.evo_lightbox', function(e) {
881
882			let close = false;
883		    if (!isMouseDownInside && 
884		        !$(e.target).closest('.evolb_box').length && 
885		        !$(e.target).closest('.evo_lightbox_body').length) {		        
886		        close = true;
887		    }
888
889		    let remove_from_dom = true;
890		    if( $(this).closest('.ajde_admin_lightboxes').length > 0 ) remove_from_dom = false;
891		    if( close )   $(this).closest('.evo_lightbox').evo_lightbox_close({ delay: 300 , remove_from_dom });
892
893		    //console.log(isMouseDownInside);
894		    isMouseDownInside = false;
895		});
896		
897		$.fn.evo_lightbox_close = function(opt) {
898		    if (!this.hasClass('show')) return;
899
900		    const defaults = { delay: 500, remove_from_dom: true };
901		    const OO = $.extend({}, defaults, opt);
902		    const hideDelay = parseInt(OO.delay);
903		    const completeClose = this.parent().find('.evo_lightbox.show').length === 1;
904
905		    // Remove 'show' class with delay if needed
906		    hideDelay > 500 ? setTimeout(() => this.removeClass('show'), hideDelay - 500) : this.removeClass('show');
907
908		    // Final cleanup after delay
909		    setTimeout(() => {
910			    completeClose && $('body, html').removeClass('evo_overflow');
911			    OO.remove_from_dom && this.remove();
912			}, hideDelay);
913		};
914
915
916		// Other LB functions
917			$.fn.evo_lightbox_populate_content = function(opt){
918				LB = this;
919				var defaults = { 
920					'content':'',
921				}; var OO = $.extend({}, defaults, opt);
922
923				LB.find('.evolb_content').html( OO.content );
924			}
925			
926			$.fn.evo_lightbox_show_msg = function(opt){
927				LB = this;
928				var defaults = { 
929					'type':'good',
930					'message':'',
931					'hide_message': false,// hide message after some time pass time or false
932					'hide_lightbox': false, // hide lightbox after some time of false
933				}; var OO = $.extend({}, defaults, opt);
934				LB.find('.message').removeClass('bad good').addClass( OO.type ).html( OO.message ).fadeIn();
935				//console.log('showing LB msg');
936
937				if( OO.hide_message ) setTimeout(function(){  LB.evo_lightbox_hide_msg() }, OO.hide_message );
938
939				if( OO.hide_lightbox ) LB.evo_lightbox_close({ delay: OO.hide_lightbox });
940			}
941			$.fn.evo_lightbox_hide_msg = function(opt){
942				LB = this;
943				LB.find('p.message').hide();
944			}
945
946
947			// add preload animations to lightbox u4.6
948			$.fn.evo_lightbox_show_open_animation = function(opt){
949				LB = this;
950				var defaults = { 
951					'animation_type':'initial', // animation type initial or saving
952					'preload_temp_key': 'init', // 4.6 passed on preload template key
953					'end':'admin',
954				};
955				var OO = $.extend({}, defaults, opt);
956
957				if( OO.animation_type == 'initial'){
958
959					passed_data = (  typeof evo_admin_ajax_handle !== 'undefined') ? evo_admin_ajax_handle: evo_general_params;
960
961					//console.log( passed_data);
962
963					html = passed_data.html.preload_general;
964					if( OO.preload_temp_key != 'init') html = passed_data.html[ OO.preload_temp_key ];
965					LB.find('.evolb_content').html( html );
966				}
967
968				if( OO.animation_type == 'saving')
969					LB.find('.evolb_content').addClass('evoloading');
970			}
971
972		// eventcard Lightbox function v4.6
973			$.fn.evo_cal_lightbox_trigger = function( SC_data , obj, CAL , LB = null){
974				
975				const event = obj.closest('.eventon_list_event');
976			    const classes = ['cancel_event', SC_data.additional_class, SC_data.calendar_type]
977			        .filter(cls => cls && (cls !== 'cancel_event' || obj.hasClass('cancel_event')))
978			        .join(' ');
979
980			    //console.log( SC_data);
981
982				const other_data = {
983			        extra_classes: `evo_lightbox_body eventon_list_event evo_pop_body evcal_eventcard event_${SC_data.event_id}_${SC_data.repeat_interval} ${classes}`,
984			        CAL,
985			        obj,
986			        et_data: obj.find('.evoet_data').data(),
987			        SC: SC_data
988			    };
989				
990				const randomId = `evo_eventcard_${Math.floor(Math.random() * 90) + 10}`;
991				const lbac = { 'sc1': 'within', 'sc2': 'within ecSCR' }[evo_general_params.cal.lbs] || '';
992
993				const openLightbox = (content,  ajaxData = null) => {
994			        const config = {
995			            //uid: ajaxData?.uid || 'evo_open_eventcard_lightbox',
996			            uid: 'evo_open_eventcard_lightbox',
997			            lbc: randomId,
998			            lbc: LB ? LB.data('lbc') || randomId : randomId,
999			            lbac,
1000			            end: 'client',
1001			            content,
1002			            other_data
1003			        };
1004			        if (ajaxData) {
1005			            Object.assign(config, {
1006			                ajax: 'yes',
1007			                ajax_type: 'endpoint',
1008			                ajax_action: 'eventon_load_single_eventcard_content',
1009			                d: ajaxData
1010			            });
1011			        }
1012
1013			        // if LB is passed populate that LB @4.9
1014			        if( LB  ){
1015			        	if( ajaxData){			        		
1016
1017			        		var OO = this.evo_process_ajax_params( config );
1018			        		LB.evo_admin_get_ajax( OO );
1019			        		$('body').trigger('evo_lightbox_processed', [ config, LB]);
1020			        		return;
1021			        	}
1022			        	LB.evo_lightbox_populate_content({content: content}); 
1023			        	$('body').trigger('evo_lightbox_processed', [ config, LB]);
1024			        	return;
1025			        }
1026
1027			        //console.log( config);
1028			        $('body').evo_lightbox_open(config);
1029			    };
1030
1031				if (SC_data.ux_val === '3a') {
1032			        const placeholder = `
1033			            <div class="evo_cardlb" style="padding:10px 10px 0 10px">
1034			                <div style="margin-bottom:20px; width:100%; height:200px" class="evo_preloading"></div>
1035			                ${Array(3).fill('<div style="display:flex;justify-content:space-between;margin-bottom:10px"><div style="width:40px;height:40px;margin-right:20px" class="evo_preloading"></div><div style="flex:1 0 auto"><div class="evo_preloading" style="width:70%;height:20px;margin-bottom:10px"></div><div class="evo_preloading" style="width:100%;height:80px;margin-bottom:10px"></div></div></div>').join('')}
1036			            </div>
1037			        `;
1038
1039			        
1040			        const ajaxData = {
1041			            event_id: SC_data.event_id,
1042			            ri: SC_data.repeat_interval,
1043			            SC: { ...SC_data, tile_style: '0', tile_bg: '0', tiles: 'no', eventtop_style: SC_data.tile_style == '2' ? '0' : SC_data.eventtop_style },
1044			            load_lbcontent: true,
1045			            action: 'eventon_load_single_eventcard_content',
1046			            uid: 'load_single_eventcard_content_3a',
1047			            calid: ( CAL ? CAL.attr('id') : '' ), 
1048			        };
1049
1050			        openLightbox(placeholder, ajaxData);
1051			    } else {
1052			        const content = event.find('.event_description').html();
1053			        const clrW = event.hasClass('clrW') ? 'clrW' : 'clrD';
1054			        openLightbox(`<div class="evopop_top ${clrW}">${obj.html()}</div><div class="evopop_body">${content}</div>`);
1055			    }
1056			}
1057
1058			// listerners for lightbox on eventcard
1059			$.fn.evo_cal_lb_listeners = function(){
1060				// Listerners
1061				// process various lightbox types
1062				$('body')
1063				.on('evo_lightbox_processed', function(event, OO, LIGHTBOX){
1064					if( OO.uid != 'evo_open_eventcard_lightbox') return false;
1065
1066					var CAL = OO.other_data.CAL;
1067
1068					LIGHTBOX.addClass('eventcard eventon_events_list');
1069					LIGHTBOX_content = LIGHTBOX.find('.evolb_content');
1070					LIGHTBOX_content.attr('class', 'evolb_content '+ OO.other_data.extra_classes );
1071					
1072					var SC = OO.other_data.SC;
1073					var obj = OO.other_data.obj;
1074
1075					//console.log(SC);
1076
1077					// update border color and eventtop color
1078						const evoet_data = OO.other_data.et_data;
1079						
1080						bgcolor = bggrad ='';
1081						if( evoet_data ){
1082							bgcolor = evoet_data.bgc;
1083							bggrad = evoet_data.bggrad;
1084						}
1085						
1086
1087						// if tiles and eventtop style set to clean
1088						var show_lightbox_color = ( SC.eventtop_style == '0' || SC.eventtop_style == '4') ? false: true;
1089						
1090						if( (CAL && CAL.hasClass('color') && show_lightbox_color) ||
1091							(!CAL && show_lightbox_color)
1092
1093						){
1094							LIGHTBOX_content.addClass('color');
1095							LIGHTBOX_content.find('.evopop_top').css({
1096								'background-color':bgcolor,
1097								'background-image': bggrad,
1098							});
1099						}else{
1100							LIGHTBOX_content.addClass('clean');
1101							LIGHTBOX_content.find('.evopop_top').css({'border-left':'3px solid '+bgcolor});
1102						}
1103
1104					// trigger 
1105					if( obj.data('runjs')){
1106						$('body').trigger('evo_load_single_event_content',[ SC.event_id, OO.other_data.obj]);
1107					}
1108									
1109					
1110					// RTL
1111					if( SC.evortl =='yes')	LIGHTBOX.addClass('evortl');
1112
1113					$('body').trigger('evolightbox_end', [ LIGHTBOX , CAL, OO]);	// @s4.6
1114
1115				})
1116
1117				// after eventcard content is loaded to lightbox via 3a - @since 4.2.3
1118					.on('evo_ajax_success_evo_open_eventcard_lightbox', function (event, OO, data){
1119						
1120						if( OO.ajaxdata.uid != "load_single_eventcard_content_3a") return false;
1121						
1122						LIGHTBOX = $('.evo_lightbox.'+ OO.lightbox_key);
1123
1124						CAL = $('body').find('#'+ OO.ajaxdata.calid);
1125						
1126						$('body').trigger('evolightbox_end', [ LIGHTBOX , CAL, OO]);	// @s4.6	
1127					})
1128				;			
1129			}
1130
1131	// Side Panel for admin
1132	// @since 4.5.2 @updated 5.0
1133		BB
1134		.on('click', '.evosp_trigger', function(e){ 
1135			e.preventDefault(); e.stopPropagation();
1136			const $el = $(this);
1137			$el.addClass('evo_sp_trig_on');
1138			$el.evo_open_sidepanel($el.data('d'), $el.data('spv'));
1139		 })
1140		.on('click', '.evosp_close', function(e){ e.preventDefault(); e.stopPropagation(); $(this).evo_close_sidepanel() })
1141		.on('click', '.evosp_trigger_save', function(e){ e.preventDefault(); e.stopPropagation(); $(this).evo_ajax_form_submit( $(this).data('d'), 'sp');  })
1142		.on('evosp_trig_close', function(e, opt){ 
1143			$(this).evo_close_sidepanel( opt ); 
1144		});
1145		
1146
1147		/**
1148		 * Side panel for eventON 
1149		 * @version 4.9
1150		 */ 		
1151		$.fn.evo_open_sidepanel = function(opt, spv){
1152			var defs = {
1153				'uid':'',
1154				'end':'admin', // admin or client
1155				'hide_sp':false,
1156				'hide_message':false,
1157				'title':'',
1158				'sp_title':'',
1159				'sp_class':'',
1160				'sp_id':'',// identifier for side panel @5.0.3
1161				'content_id':'',  // only to load dynamic content
1162				'content':'',// @5.0.3 populate passed on content with delay
1163				'content_footer':'',// @5.0.9 footer content
1164				'content_load_delay':0,// 1000
1165				'ajax':'no',
1166				'ajax_data':'',		
1167				'adata':{},
1168				'other_data':{},	
1169				'spdata':{}, // in progress pass all sidepanel data in one			
1170				'size': 'sm', // sm | med | lar
1171				'movepage': false,// in complete -- idea to move the entire page
1172				'fresh_content': false, // if fresh content stream is loading
1173				end:'admin'
1174			}
1175			var OO = $.extend({}, defs, opt);
1176			//console.log(OO);
1177
1178			const SP = $('body').find('.evo_sp');
1179			let sp_has_content = SP.length > 0 && SP.html()?.trim() !== '';
1180			
1181			let SP_uid = OO.sp_id || 'evosp_' + Math.random().toString(36).substr(2, 9);
1182			if( $('#'+ SP_uid).length > 0 ) SP_uid = SP_uid + '_' + ($('#'+ SP_uid).length); 
1183
1184			// get zindex value
1185			let openBoxes = 0;
1186			openBoxes = $('.evo_lightbox.show, .evosp_one.show').length;
1187			zIndex = 950000+ openBoxes;
1188
1189
1190
1191			// structure
1192				const load_html = "<div class='evo_loading_bar_holder h100'><div class='evo_loading_bar wid_50 hi_50'></div><div class='evo_loading_bar hi_100'></div><div class='evo_loading_bar'></div><div class='evo_loading_bar'></div><div class='evo_loading_bar hi_50'></div></div>";
1193
1194				const footer_html = `<div class='evosp_foot evo_bordert evodfx evofxdrr evofxaic evofxww evogap10'><div class='evosp_foot_in evofx_1 evogap10'>
1195				<div class='evo_loading_bar_holder h100 evopad0i'><div class='evo_loading_bar wid_50 hi_50'></div></div>
1196				</div><p class='evosp_message message evomar0i'></p></div>`;
1197
1198				SP_back_btn = ( sp_has_content && !OO.fresh_content) ? `<button class='evonobtn evosp_back_trig'><i class='fa fa-chevron-left'></i></button>`: '';
1199
1200				let sp_header = OO.sp_title !== '' ? `<div class='evosp_head evoff_1'>${OO.sp_title}</div>` : '';
1201
1202				SP_HTML = `<div id='${SP_uid}' class='evosp_one ${OO.sp_class} ${OO.size}' style='z-index:${zIndex}'><div class='evosp_in'>${SP_back_btn}<span class='evosp_close'><i class='fa fa-multiply'></i></span>${sp_header}<div id='evops_content_${SP_uid}' class='evosp_body evops_content'>${load_html}</div>${footer_html}</div></div>`;
1203
1204				
1205				SP.append( SP_HTML );
1206
1207				SP_one = SP.find('#'+ SP_uid);
1208				setTimeout(() => { 
1209				  SP_one.addClass('show'); 
1210				}, 300);
1211				//SP.removeClass('med lar sm').addClass( OO.size );
1212
1213				// if move page as well
1214				//if( OO.movepage ) $('body').find('.editor-editor-interface').addClass('evotrans pagemoved').css('right', '400px');
1215
1216				const SP_body = SP.find('.evosp_body');
1217				const SP_head = SP.find('.evosp_head');
1218				const SP_foot = SP.find('.evosp_foot');		
1219
1220			// load using content
1221				if( OO.content_id != ''){
1222					if( OO.content_load_delay > 0){
1223						setTimeout(function(){
1224							SP.evo_populate_sidepanel( BB.find('#'+ OO.content_id ).html() );
1225						}, OO.content_load_delay );
1226					}else{
1227						SP.evo_populate_sidepanel( BB.find('#'+ OO.content_id ).html() );
1228					}				
1229				}
1230
1231			// run ajax to load content for the lightbox inside
1232				if( ( OO.ajax == 'yes' && OO.ajax_data != '') || ( OO.adata != '' && 'a' in OO.adata) ){
1233					var passing_data = {
1234						adata: OO.adata,
1235						ajaxdata: OO.ajax_data, 
1236						uid: OO.uid ,
1237						end: OO.end,
1238						load_new_content: true,
1239						load_new_content_id: 'evops_content_'+ SP_uid,
1240						lightbox_loader:false,
1241						end: OO.end,
1242						spdata:{
1243							spid: SP_uid,
1244						}
1245					};
1246
1247					SP.evo_admin_get_ajax( passing_data );
1248				}else{
1249					setTimeout(()=> BB.trigger('evo_sp_stop_loading'),OO.content_load_delay);
1250				}
1251
1252			// populate with passed on content with delay @5.0.3
1253				if( OO.content != ''){
1254					setTimeout(()=> SP.evo_populate_sidepanel( OO.content ),OO.content_load_delay);
1255					if( OO.content_footer ) setTimeout(()=> SP.evo_populate_sidepanel_footer( OO.content_footer ), (OO.content_load_delay + 500) );
1256				}
1257			// populate new content with spv values
1258				if( spv != ''){
1259					BB.on('evo_ajax_success_'+ OO.uid , function(){
1260						$('#evops_content').find('input, select').each(function(){
1261							var fel = $(this);
1262							$.each(spv,function(index, val){
1263								if( fel.attr('name') == index){
1264
1265									if( val == 'no' || val == 'yes') fel.evo_elm_change_yn_btn( val );
1266									fel.val( val );
1267								}
1268							});					
1269						});
1270					});
1271				}
1272	  		
1273	  		BB.trigger('evo_sp_opened_'+OO.uid, OO);
1274	  		BB.trigger('evo_sp_opened', OO);
1275	  		
1276	  	}
1277	  	// back from side panel
1278	  	BB.on('click','.evosp_back_trig',function(){
1279	  		const $el = $(this);
1280	  		const thisSPone = $el.closest('.evosp_one');
1281	  		let prevSPone = thisSPone.prev();
1282	  		thisSPone.remove();
1283	  		//prevSPone.removeClass('sp_hide');
1284	  	});
1285	  	BB.on('evo_sp_stop_loading',function(){
1286	  		$('body').find('.evo_sp').find('.evo_loading_bar_holder').remove();
1287	  	});
1288	  	$.fn.evo_savevals_sidepanel = function(spv){
1289	  		const el = BB.find('.evo_sp_trig_on');
1290
1291	  		el.data('spv', spv);
1292	  		el.removeClass('evo_sp_trig_on');
1293	  	}
1294
1295	  	$.fn.evo_populate_sidepanel = function(content){
1296	  		const SP = $('body').find('.evo_sp');
1297	  		SP.find('.evosp_body').html( content );
1298	  	}
1299
1300	  	// populate sidepanel footer @5.0.3
1301	  	$.fn.evo_populate_sidepanel_footer = function(content ){
1302	  		const SP = $('body').find('.evo_sp');
1303	  		SP.find('.evosp_foot_in').html( content );
1304	  	}
1305	  	// CLOSE sidepanel
1306	  	$.fn.evo_close_sidepanel = function(opt){
1307	  		$el = $(this);
1308	  		SP = BB.find('.evo_sp');
1309
1310	  		var defaults = { 
1311	  			'sp_id':'',
1312	  			'delay':200
1313	  		};
1314	  		var OO = $.extend({}, defaults, opt);
1315
1316	  		let SPone = OO.sp_id ? SP.find('#' + OO.sp_id) : SP.find('.evosp_one').last();
1317			if( !(SPone.hasClass('show')) ) return;
1318			
1319						
1320	  		setTimeout(function(){	
1321	  			BB.trigger('evo_sp_closed',[ SP, SPone ]);
1322	  			SPone.removeClass('show');
1323	  			//$('body').find('.editor-editor-interface.pagemoved').removeClass('pagemoved').css('right', 'auto');
1324	  			BB.find('.evo_sp_trig_on').removeClass('evo_sp_trig_on');
1325	  		}, OO.delay );
1326	  		setTimeout(function(){
1327	  			SPone.remove();	
1328	  			if( SP.find('.evosp_one').length < 0 ) SP.html('');	
1329	  		}, ( OO.delay + 100 ) );
1330	  	}
1331
1332	  	$.fn.evo_showmsg_sidepanel = function(opt, spdata){
1333	  		var defaults = { 
1334	  			'sp_id':'',
1335				'type':'good',
1336				'message':'',
1337				'hide_message': false,// hide message after some time pass time or false
1338				'hide_sp': false, // hide lightbox after some time of false
1339			}; var OO = $.extend({}, defaults, opt);
1340
1341			//console.log('showing sp msg');
1342			const SP = BB.find('#evo_sp');
1343
1344			// SP ID
1345			if( 'sp_id' in spdata ) OO.sp_id = spdata.sp_id;
1346			let SPone = OO.sp_id ? SP.find('#' + OO.sp_id) : SP.find('.evosp_one').last();
1347
1348			SPone.find('.evosp_message').removeClass('bad good').addClass( OO.type ).html( OO.message ).fadeIn();
1349			if( OO.hide_message ) setTimeout(function(){  SPone.evo_hidemsg_sidepanel() }, OO.hide_message );
1350			if( OO.hide_sp ) SPone.evo_close_sidepanel({ delay: OO.hide_sp });
1351	  	}
1352	  	$.fn.evo_hidemsg_sidepanel = function(opt){
1353			SP = this;
1354			SP.find('p.evosp_message').hide();
1355		}
1356
1357
1358
1359	// Get Ajax url @since 4.4 @u 4.5.5
1360		$.fn.evo_get_ajax_url = function(opt){
1361			var defaults = { 
1362				a:'', // action key
1363				e:'client', // end
1364				type: 'ajax'};
1365			var OO = $.extend({}, defaults, opt);
1366
1367			
1368
1369			// end point url
1370			if( OO.type == 'endpoint'){
1371				var evo_ajax_url = ( OO.e == 'client' || typeof evo_general_params !== 'undefined' )? 
1372					evo_general_params.evo_ajax_url : evo_admin_ajax_handle.evo_ajax_url;
1373				return  evo_ajax_url.toString().replace( '%%endpoint%%', OO.a );
1374			// rest api url
1375			}else if( OO.type == 'rest' ){
1376				var evo_ajax_url = ( OO.e == 'client' || typeof evo_general_params !== 'undefined')? 
1377					evo_general_params.rest_url : evo_admin_ajax_handle.rest_url;
1378					//console.log(evo_ajax_url);
1379					//console.log(OO);
1380				return  evo_ajax_url.toString().replace( '%%endpoint%%', OO.a );
1381			}else{
1382				action_add = OO.a != '' ? '?action='+ OO.a: '';
1383				return ( OO.e == 'client' || typeof evo_general_params !== 'undefined') ? 
1384					evo_general_params.ajaxurl + action_add : evo_admin_ajax_handle.ajaxurl + action_add;
1385			}	
1386		}
1387
1388	// loading animations @4.7.2
1389		$.fn.evo_start_loading = function( opt ){
1390			var defaults = { type:'1'};
1391			var OPT = $.extend({}, defaults, opt);
1392			var el = this;
1393
1394			if( OPT.type == '1') el.addClass('evoloading loading');
1395			if( OPT.type == '2') el.addClass('evoloading_2');
1396		}
1397		$.fn.evo_stop_loading = function( opt ){
1398			var el = this;
1399			var defaults = { type:'1'};
1400			var OPT = $.extend({}, defaults, opt);
1401
1402			if( OPT.type == '1') el.removeClass('evoloading loading');
1403			if( OPT.type == '2') el.removeClass('evoloading_2');
1404		}
1405		$.fn.evo_lightbox_start_inloading = function(opt){
1406			LB = this;
1407			LB.find('.evolb_content').addClass('loading evoloading');
1408		}
1409		$.fn.evo_lightbox_stop_inloading = function(opt){
1410			LB = this;
1411			LB.find('.evolb_content').removeClass('loading evoloading');
1412		}
1413	
1414	// Count down	// @+ 4.5
1415		$.fn.evo_countdown_get = function(opt){
1416			var defaults = { gap:'', endutc: ''};
1417			var OPT = $.extend({}, defaults, opt);
1418			var gap = OPT.gap;
1419
1420			// if gap not provided use endutc
1421			if( gap == '' ){				
1422				var Mnow = moment().utc();
1423				var M = moment();
1424				M.set('millisecond', OPT.endutc );
1425
1426				gap = OPT.endutc - Mnow.unix();
1427			}
1428			
1429			// if negative gap
1430			if( gap < 0){
1431				return {
1432					'd': 0,
1433					'h':0,
1434					'm':0,
1435					's':0
1436				}; 
1437			}
1438		
1439			distance = ( gap * 1000);
1440
1441			var days = Math.floor(distance / (1000 * 60 * 60 * 24));
1442			var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
1443			var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
1444			var seconds = Math.floor((distance % (1000 * 60)) / 1000);
1445
1446			minutes = minutes<10? '0'+minutes : minutes;
1447			seconds = seconds<10? '0'+seconds : seconds;
1448
1449			return {
1450				'd': days,
1451				'h':hours,
1452				'm':minutes,
1453				's':seconds
1454			}; 
1455		};
1456		// @u 4.5.2
1457		$.fn.evo_countdown = function(opt){
1458			var defaults = { S1:''};
1459			var OPT = $.extend({}, defaults, opt);
1460			var el = $(this);
1461
1462			const day_text = ( el.data('d') !== undefined && el.data('d') != '' )? el.data('d'):'Day';
1463			const days_text = ( el.data('ds') !== undefined && el.data('ds') != '' )? el.data('ds'):'Days';
1464
1465			// intial run
1466			//var gap = parseInt(el.data('gap'));
1467			var duration = el.data('dur');
1468			var endutc = parseInt(el.data('endutc'));
1469			var text = el.data('t');
1470			
1471			if(text === undefined) text = '';
1472
1473			if( el.hasClass('evo_cd_on')) return;
1474
1475			// get gap using end time utc
1476				var Mnow = moment().utc();
1477				var M = moment();
1478				M.set('millisecond', OPT.endutc );
1479
1480				//console.log(Mnow.unix());
1481				//console.log(endutc);
1482
1483				gap = endutc - Mnow.unix();
1484
1485
1486			// on initial run - event hasnt happened yet
1487			if( gap > 0 ){
1488
1489				// initial
1490				dd = el.evo_countdown_get({ 'gap': gap });
1491				
1492				el.html( ( dd.d>0 ? dd.d + ' ' + ( dd.d >1 ? days_text: day_text ) + " "  :'') + dd.h + ":" + dd.m +':'+ dd.s +'  '+text );
1493				
1494				el.data('gap', ( gap - 1)  );	// save new gap value
1495				el.addClass('evo_cd_on');
1496
1497				//return;
1498				
1499				// set intervals
1500				var CD = setInterval(function(){
1501					
1502					gap = el.data('gap'); // get gap for this cycle
1503					duration = el.data('dur');	
1504
1505					const bar_elm = el.closest('.evo_event_progress').find('.evo_ep_bar');	
1506
1507					// when timer is ticking
1508					if( gap > 0 ){
1509
1510						// increase bar width if exists
1511						if( duration !== undefined && bar_elm.length){
1512							perc = ( (duration - gap)/ duration ) * 100;
1513							bar_elm.find('b').css('width',perc+'%');							
1514						}
1515						
1516						dd = el.evo_countdown_get({ 'gap': gap });	
1517
1518						el.html( ( dd.d>0 ? dd.d + ' '  + ( dd.d >1 ? days_text: day_text ) + " ":'') + dd.h + ":" + dd.m +':'+ dd.s +' '+text );
1519						el.data('gap', ( gap - 1)  );
1520
1521					// when timer expired
1522					}else{
1523
1524						const expire_timer_action = el.data('exp_act');
1525
1526						// perform ajax task after expiration
1527						if(expire_timer_action !== undefined){
1528							$('body').trigger('runajax_refresh_now_cal',[ 
1529								el , 
1530								el.data('n'),
1531							]);
1532						}
1533
1534						const _complete_text = el.evo_get_txt({V:'event_completed'});
1535
1536						// live now text
1537						if(bar_elm.length){
1538							bar_elm.addClass('evo_completed');
1539							//el.siblings('.evo_ep_pre').html( _complete_text );
1540						}
1541
1542
1543						// event tag & live elements
1544						if( el.closest('.evcal_desc').length){
1545							el.closest('.evcal_desc').find('.eventover').html( _complete_text);
1546							el.closest('.evcal_desc').find('.evo_live_now').remove();
1547						}
1548
1549						// event card
1550						if( el.closest('.eventon_list_event').length){
1551							el.closest('.eventon_list_event').find('span.evo_live_now').hide();
1552						}
1553
1554						el.html('');
1555						clearInterval(CD);
1556					}
1557
1558				},1000);
1559			// event has already passed
1560			}else{
1561				// if gap is less
1562				el.closest('.evo_event_progress').find('.evo_ep_bar').hide();
1563				clearInterval(CD);
1564			}
1565		};	
1566
1567	// Handlebar process template data into html
1568		$.fn.evo_HB_process_template = function(opt){
1569			var defaults = { TD:'', part:''}
1570			var OPT = $.extend({}, defaults, opt);
1571
1572			BUS = $('#evo_global_data').data('d');
1573						
1574			template = Handlebars.compile( BUS.temp[ OPT.part ] );
1575			return template( OPT.TD );
1576		}
1577
1578	// Date range and events @4.6.7
1579		// Date range and events - from webpage
1580		$.fn.evo_cal_events_in_range = function(opt){
1581			var defaults = { S:'', E:'', 
1582				hide: true, 
1583				closeEC:true,
1584				showEV: false, // show events
1585				showEVL: false, // show events list
1586				showAllEvs: false // show all events regardless of the range
1587			};
1588			var OPT = $.extend({}, defaults, opt);
1589			var CAL = $(this);
1590
1591			var eJSON = CAL.find('.evo_cal_events').data('events');
1592			var SC = CAL.evo_shortcode_data();
1593
1594			R = {};
1595			html = '';
1596			json = {};
1597
1598			show = 0;
1599
1600			// using events JSON data
1601			if( eJSON && eJSON.length > 0){
1602				$.each(eJSON, function(ind, ED){
1603					eO = CAL.find('#event_'+ ED._ID);
1604					if(eO === undefined || eO.length==0) return;
1605
1606					if(OPT.hide)	eO.hide(); // pre hide
1607					this_show = false;
1608
1609					// month long or year long events
1610					if( ED.month_long || ED.year_long ){
1611						this_show = true;
1612
1613					}else{
1614						if(CAL.evo_is_in_range({
1615							'S': OPT.S,	'E': OPT.E,	'start': ED.unix_start ,	'end':ED.unix_end 
1616						})){						
1617							this_show = true;
1618						} 
1619					}
1620
1621					if( OPT.showAllEvs) this_show = true;
1622					
1623					if( this_show){	
1624						// show event
1625						if( OPT.showEV) eO.show();
1626
1627						// close open event cards
1628						if(OPT.closeEC && SC.evc_open == 'no') eO.find('.event_description').hide().removeClass('open');
1629
1630						html += eO[0].outerHTML;
1631						json[ ED._ID] = ED;
1632						show++;	
1633					} 
1634				});
1635			}else{	
1636				// get all the events in the events list
1637				var cal_events = CAL.find('.eventon_list_event');
1638
1639				cal_events.each(function(index, elm){
1640					var ED = $(elm).evo_cal_get_basic_eventdata();
1641					if( !ED) return;
1642
1643					if(OPT.hide)	$(elm).hide(); // pre hide
1644					this_show = false;
1645
1646					// month long or year long events
1647					if( $(elm).hasClass('month_long') || $(elm).hasClass('year_long') ){
1648						this_show = true;
1649
1650					}else{
1651						if(CAL.evo_is_in_range({
1652							'S': OPT.S,	'E': OPT.E,	'start': ED.unix_start ,	'end':ED.unix_end 
1653						})){						
1654							this_show = true;
1655						} 
1656					}
1657
1658					if( OPT.showAllEvs) this_show = true;
1659					
1660					if( this_show){	
1661						// show event
1662						if( OPT.showEV) $(elm).show();
1663
1664						// close open event cards
1665						if(OPT.closeEC && SC.evc_open == 'no') 
1666							$(elm).find('.event_description').hide().removeClass('open');
1667
1668						html += $(elm)[0].outerHTML;
1669						json[ ED.uID ] = ED;
1670						show++;	
1671					} 
1672				});
1673			}
1674
1675
1676			// No events
1677			if( OPT.showEV){
1678
1679				no_event_content = CAL.evo_get_global({S1: 'html', S2:'no_events'});
1680
1681				tx_noevents = CAL.evo_get_txt({V:'no_events'});
1682				EL = CAL.find('.eventon_events_list');
1683				EL.find('.eventon_list_event.no_events').remove();
1684				if( show == 0 )
1685					EL.append('<div class="eventon_list_event no_events">'+ no_event_content +'</div>');
1686			}
1687
1688			// if show events list
1689			if( OPT.showEVL){
1690				CAL.find('.eventon_events_list').show().removeClass('evo_hide');
1691			}
1692
1693			R['count'] = show;
1694			R['html'] = html;
1695			R['json'] = json;
1696
1697			return R;
1698		}
1699
1700		// check if an event is in the given date range
1701			$.fn.evo_is_in_range = function(opt){
1702				var defaults = { S:'', E:'', start:'',end:''}
1703				var OPT = $.extend({}, defaults, opt);
1704
1705				S = parseInt(OPT.S);
1706				E = parseInt(OPT.E);
1707				start = parseInt(OPT.start);
1708				end = parseInt(OPT.end);
1709
1710				return (
1711					( start <= S && end >= E ) ||
1712					( start <= S && end >= S && end <= E) ||
1713					( start <= E && end >= E ) ||
1714					( start >= S && end <= E )
1715				) ? true: false;
1716			}
1717			$.fn.evo_cal_hide_events = function(){
1718				CAL = $(this);
1719				CAL.find('.eventon_list_event').hide();
1720			}
1721
1722	// get event data basics from html event on page 
1723	// ~@version 4.0.3 @updated 4.9.8
1724		$.fn.evo_cal_get_basic_eventdata = function(){
1725			var ELM = $(this);
1726
1727			var _time = ELM.data('time');
1728			if( _time === undefined ) return false;
1729
1730			const time = _time.split('-');
1731			const ri = ELM.data('ri').replace('r','');
1732			const eID = ELM.data('event_id');
1733
1734			var _event_title = ELM.find('.evcal_event_title').text();
1735			_event_title = _event_title.replace(/'/g, '&apos;');
1736
1737			// extract text time
1738			let timeRange = '';
1739			const timeElement = ELM.find('.evo_tz_time');
1740			if( timeElement.length > 0){
1741				const timeClone = timeElement.clone();
1742		        // Remove the span.evo_tz and its contents
1743		        timeClone.find('.evo_tz').remove();
1744		        // Get the text, trim it, and remove any remaining icon-related characters
1745		        let timeText = timeClone.text().trim();
1746		        // Remove any lingering non-time characters (e.g., leftover from <i> tags)
1747		        timeText = timeText.replace(/[^\d:\s-]/g, '');
1748		        // Trim again to remove any extra spaces
1749		        timeRange = timeText.trim() || 'N/A';
1750			}
1751			
1752			var RR = {
1753				'uID': eID + '_' + ri,
1754				'ID': eID ,
1755				'event_id': eID ,
1756				'ri': ri,
1757				'event_start_unix': parseInt(time[0]),
1758				'event_end_unix': parseInt(time[1]),
1759				'time_text': timeRange, // @since 4.9.8
1760				'ux_val': ELM.find('.evcal_list_a').data('ux_val'),
1761				'event_title': _event_title,
1762				'hex_color': ELM.data('colr'),
1763				'hide_et': ELM.hasClass('no_et') ? 'y':'n', // hide endtime
1764				'evcal_event_color': ELM.data('colr'),
1765				'unix_start': parseInt(time[0]),// @4.5.7
1766				'unix_end': parseInt(time[1]),// @4.5.7
1767			};
1768
1769			// event type
1770			RR['ett1'] = {};
1771			ELM.find('.evoet_eventtypes.ett1 .evoetet_val').each(function(){
1772				RR['ett1'][ $(this).data('id')] = $(this).data('v');
1773			});
1774
1775			// since 4.3.5
1776			const eventtop_data = ELM.find('.evoet_data').data('d');
1777
1778			// location
1779			if(eventtop_data && 'loc.n' in eventtop_data && eventtop_data['loc.n'] != ''){
1780				RR['location'] = eventtop_data['loc.n'];
1781			}
1782
1783			// organizer
1784			if(eventtop_data && 'orgs' in eventtop_data && eventtop_data.orgs !== undefined ){
1785				var org_names = '';
1786				$.each(eventtop_data.orgs, function(index, value){
1787					org_names += value +' ';
1788				});
1789				RR['organizer'] = org_names;
1790			}
1791
1792			// event image
1793			if( ELM.find('.evo_event_schema').length > 0){
1794				imgObj = ELM.find('.evo_event_schema').find('meta[itemprop=image]').attr('content');
1795				RR['image_url'] = imgObj;
1796			}
1797
1798			// event tags @s 4.5.2
1799			if( eventtop_data && 'tags' in eventtop_data && eventtop_data.tags !== undefined ){
1800				//console.log(eventtop_data.tags);
1801				RR['event_tags'] = eventtop_data.tags;
1802			}
1803
1804
1805			return RR;
1806
1807		}
1808
1809
1810	// Calendar Helper functions @+2.8 @updated 4.9	
1811		$.fn.evo_cal_oneevent_onload = function(type){// @since 4.9
1812			if( type != 'complete') return;
1813
1814			const bodyClasses = $('body').attr('class') || '';
1815			const match = bodyClasses.match(/one_event_\d+_\d+/);
1816			if (match) {
1817        		const className = match[0];
1818        		const [, x, y] = className.match(/one_event_(\d+)_(\d+)/);
1819
1820				const event_obj = $('body').find('#event_'+ x +'_'+ y);
1821				const $cal = event_obj.closest('.ajde_evcal_calendar');
1822				const SC = $cal.evo_shortcode_data();
1823
1824
1825				if( event_obj.length > 1 ) return;
1826
1827				const new_SC_data = {
1828		            ...SC,
1829		            repeat_interval: y,
1830		            event_id: x,
1831		            ux_val: '3a',
1832		            evortl: event_obj.find('.eventon_events_list').hasClass('evortl') ? 'yes' : 'no',			            
1833		            ajax_eventtop_show_content: true,
1834		            additional_class: CAL.attr('class').match(/etttc_\w+/)?.[0] || '',
1835		        };
1836
1837		        console.log( new_SC_data);
1838		        $cal.evo_cal_lightbox_trigger(new_SC_data, event_obj, $cal);
1839				
1840			}
1841		}
1842		$.fn.evo_cal_event_get_uxval = function(SC, obj){
1843			const CAL = this;
1844			var ux_val = obj.data('ux_val');
1845
1846			if(SC && 'ux_val' in SC && SC.ux_val!='' && SC.ux_val!== undefined && SC.ux_val!='0'){
1847				ux_val = SC.ux_val;
1848			}
1849
1850			// special mobile only user interaction 
1851			if( SC && SC.ux_val_mob !== undefined && SC.ux_val_mob != '' && 
1852				SC.ux_val_mob != '-' && SC.ux_val_mob != ux_val){
1853				if( CAL.evo_is_mobile() ) ux_val = SC.ux_val_mob;
1854			}
1855			return ux_val;
1856		}
1857
1858		// to run before cal ajax is performed @4.6
1859		$.fn.evo_pre_cal = function(options){
1860			var el = this;
1861			var cal = {};
1862			var OO = $.extend({}, options);
1863
1864			var run = function(){
1865				cal_width_assoc();
1866				cal_load_nav_html();
1867			}
1868			var cal_width_assoc = function(){
1869				cal_w = el.width();
1870				if( cal_w <300) el.addClass('szS');
1871				if( cal_w >300 && cal_w <600) el.addClass('szM');
1872				if( cal_w >600 && cal_w <900) el.addClass('szL');
1873				if( cal_w >900) el.addClass('szX');
1874			}
1875
1876			// load nav html into cal
1877			var cal_load_nav_html = function(){
1878				nav_data = el.evo_cal_get_footer_data('nav_data');				
1879				if( nav_data && 'month_title' in nav_data){
1880					__html = nav_data.month_title;
1881					if( 'arrows' in nav_data ) __html += nav_data.arrows;
1882					el.find('.evo_header_mo').html( __html );
1883					el.find('.evo_footer_nav').html( __html );
1884				}
1885			}
1886			run();
1887		}
1888
1889		// localize time @4.6.7 @u 4.9
1890		$.fn.evo_cal_localize_time = function(){			
1891			this.find('.evo_loct_inprocess').each(function(e){	$(this).evo_localize_time();	});
1892		}
1893		$.fn.evo_localize_time = function( ){
1894			
1895			const eventcard = this.closest('.eventon_list_event');
1896		    const hideEnd = eventcard.hasClass('no_et');
1897		    const textLocal = evo_general_params.text.local_time;
1898
1899		    eventcard.find('.evo_mytime').each(function() {
1900		    	const $el = $(this);
1901		        const isEventCard = $el.hasClass('evocard');
1902		        const { times, __f: fullFormat, __tf: timeOnlyFormat, tzo: utcOffset = 0 } = $el.data();
1903		        const [start, end] = times.split('-').map(Number);
1904
1905		        const startMoment = moment.unix(start).utc().local();
1906		        const endMoment = moment.unix(end).utc().local();
1907		        const sameMonth = startMoment.format('YYYY/M') === endMoment.format('YYYY/M');
1908		        const sameDay = sameMonth && startMoment.format('DD') === endMoment.format('DD');
1909
1910		        const startText = startMoment.format(fullFormat);
1911		        const endText = endMoment.format(sameDay ? timeOnlyFormat : fullFormat);
1912		        const html = `${startText}${hideEnd ? '' : ' - ' + endText}` + 
1913		                     (isEventCard ? `<span class='evomarl5'>(${textLocal})</span>` : '');
1914
1915		        $el.replaceWith(`<span class='evo_newmytime'>${html}</span>`);
1916		    });
1917		}	
1918		$.fn.evo_day_in_month = function(opt){
1919			var defaults = { M:'', Y:''}
1920			var OPT = $.extend({}, defaults, opt);
1921
1922			return new Date(OPT.Y, OPT.M, 0).getDate();
1923		}
1924		$.fn.evo_get_day_name_index = function(opt){
1925			var defaults = { M:'', Y:'', D:''}
1926			var OPT = $.extend({}, defaults, opt);
1927
1928			//return moment(OPT.Y+'-'+OPT.M+'-'+OPT.D).utc().day();
1929
1930			return new Date(  Date.UTC(OPT.Y, OPT.M-1, OPT.D) ).getUTCDay();
1931		}
1932
1933		// scrollbar
1934		// Function to initialize custom scrollbar
1935		$.fn.evo_init_scrollbars = function(options){
1936
1937			const defaults = { scrollSpeed: 50 };
1938		    const settings = $.extend({}, defaults, options);
1939
1940
1941		    return this.each(function() {
1942		        const $scope = $(this);
1943		        $scope.find('.evo-scrollbar').each(function() {
1944		            const $container = $(this);
1945		            if ($container.hasClass('evo-scroll-container')) return;
1946
1947		            $container.addClass('evo-scroll-container');
1948		            const $parent = $container.parent();
1949		            if (!$parent.css('height') || $parent.css('height') === 'auto') {
1950		                $parent.css('height', '300px');
1951		            }
1952
1953		            const $content = $container.children().wrapAll('<div class="evo-scroll-content"></div>').parent();
1954		            $container.append('<div class="evo-scroll-tab-container"><div class="evo-scroll-tab"></div></div>');
1955
1956		            const $tabContainer = $container.find('.evo-scroll-tab-container');
1957		            const $tab = $tabContainer.find('.evo-scroll-tab');
1958		            const $scrollContent = $container.find('.evo-scroll-content');
1959
1960		            // Dynamic tab height and visibility
1961		            const updateTabHeight = () => {
1962		                const height = $container.height();
1963		                const contentHeight = $scrollContent[0].scrollHeight;
1964		                const maxScroll = contentHeight - height;
1965		                const tabHeight = Math.max(height * (height / contentHeight), 20);
1966		                $tab.css('height', `${tabHeight}px`);
1967		                $tab.toggleClass('scroll-needed', maxScroll > 0); // Show tab only if scrollable
1968		                console.log(height+' '+contentHeight+' '+maxScroll+' '+tabHeight);
1969            		};
1970		            $container.on('mouseenter', updateTabHeight);
1971
1972		            // Click to scroll
1973		            $tab.on('click', (e) => {
1974		                const height = $container.height();
1975		                const maxScroll = $scrollContent[0].scrollHeight - height;
1976		                const current = $container.scrollTop();
1977		                $container.scrollTop(current < maxScroll ? current + settings.scrollSpeed : current - settings.scrollSpeed);
1978		            });
1979
1980		            // Drag events
1981		            let isDragging = false;
1982		            let startY, startScrollTop;
1983
1984		            // Drag events
1985		            $tab.on('mousedown', (e) => {
1986		                isDragging = true;
1987		                $tab.addClass('dragging');
1988		                startY = e.pageY;
1989		                startScrollTop = $container.scrollTop();
1990		                e.preventDefault();
1991		            });
1992
1993		            $(document).on('mouseup', () => {
1994		                isDragging = false;
1995		                $tab.removeClass('dragging');
1996		            });
1997
1998		            $(document).on('mousemove', (e) => {
1999		                if (!isDragging) return;
2000
2001		                const height = $container.height();
2002		                const maxScroll = $scrollContent[0].scrollHeight - height;
2003		                const tabHeight = $tab.height();
2004		                const tabMaxTravel = height - tabHeight;
2005		                const deltaY = e.pageY - startY;
2006		                const scrollPercent = deltaY / tabMaxTravel;
2007		                $container.scrollTop(Math.max(0, Math.min(startScrollTop + (scrollPercent * maxScroll), maxScroll)));
2008		            });
2009
2010		            // Scroll event with requestAnimationFrame
2011		            $container.on('scroll', () => {
2012		                const height = $container.height();
2013		                const contentHeight = $scrollContent[0].scrollHeight;
2014		                const maxScroll = contentHeight - height;
2015		                const tabHeight = $tab.height();
2016		                const tabMaxTravel = height - tabHeight;
2017		                const scrollPosition = $container.scrollTop();
2018		                const scrollPercent = maxScroll > 0 ? scrollPosition / maxScroll : 0;
2019
2020		                requestAnimationFrame(() => {
2021		                    $tabContainer.css('top', `${scrollPosition}px`);
2022		                    $tab.css('top', `${scrollPercent * tabMaxTravel}px`);
2023		                });
2024		            });
2025		        });
2026		    });
2027		}
2028
2029
2030		/*
2031	    // Run on page load for all elements with .evo-scrollbar
2032	    initCustomScrollbar($('body').find('.evo-scrollbar'));
2033
2034	    // Expose function globally for on-demand use
2035	    window.initCustomScrollbar = function(selector) {
2036	        const $elements = selector ? $(selector) : $('body').find('.evo-scrollbar');
2037	        initCustomScrollbar($elements);
2038	    };
2039	    */
2040
2041
2042
2043	// LIGHTBOX
2044	// page Lightbox functions @+2.8
2045	// append to the lightbox main class name .evo_lightbox		
2046		// Legacy
2047			$.fn.evo_prepare_lb = function(){
2048				$(this).find('.evo_lightbox_body').html('');
2049			}
2050			$.fn.evo_show_lb = function(opt){
2051				var defaults = { RTL:'', calid:''}
2052				var OPT = $.extend({}, defaults, opt);
2053
2054				$(this).addClass('show '+ OPT.RTL).attr('data-cal_id', OPT.calid);
2055				$('body').trigger('evolightbox_show');
2056			}
2057			$.fn.evo_append_lb = function(opt){
2058				var defaults = { C:'', CAL:''}
2059				var OPT = $.extend({}, defaults, opt);
2060				$(this).find('.evo_lightbox_body').html( OPT.C);
2061
2062				if(  OPT.CAL!= '' && OPT.CAL !== undefined && OPT.CAL.hasClass('color')){
2063					const LIST = $(this).find('.eventon_events_list');
2064					if( LIST.length>0){
2065						LIST.find('.eventon_list_event').addClass('color');
2066					}				
2067				}
2068			}
2069
2070	// event image gallery @4.6
2071		$.fn.eventon_process_main_ft_img = function(OO){
2072			const IMG = this;
2073			var img_sty = 'def';
2074			if( IMG.hasClass('fit') ) img_sty = 'fit';
2075			if( IMG.hasClass('full') ) img_sty = 'full';
2076			
2077			// Initialize box dimensions
2078		    let box_width =  IMG.width();
2079		    let box_height =  IMG.height();
2080			
2081			// Ensure valid box dimensions
2082		    box_width = box_width > 0 ? box_width : 100; // Fallback to prevent errors
2083		    box_height = box_height > 0 ? box_height : 100;
2084			
2085
2086			 // Get image dimensions from data attributes
2087		    const img_width = parseInt(IMG.data('w')) || 100; // Fallback to prevent division by zero
2088		    const img_height = parseInt(IMG.data('h')) || 100;
2089		    const img_ratio = img_height / img_width; // Image aspect ratio
2090					
2091			let new_width, new_height;
2092			
2093			// Handle 'fit' style 
2094			if( IMG.hasClass('fit')){
2095				// Scale to fit within box while maintaining aspect ratio
2096		        new_width = box_height / img_ratio;
2097				new_height = box_height;
2098				if( new_width > box_width ){// width is wider than box
2099
2100					if( img_ratio <1 ){
2101						new_width = box_width; new_height = img_ratio * new_width;
2102					}else{
2103						new_height = box_height; new_width = new_height / img_ratio;
2104					}
2105				} 	
2106					
2107				IMG.find('span').css({'width':new_width, 'height': new_height} );
2108			}
2109
2110			// full style
2111			if( IMG.hasClass('full')){
2112				new_height = img_ratio * box_width;
2113				new_width = box_width;
2114				IMG.find('span').css({'width':new_width, 'height': new_height} );
2115				IMG.css({'height': new_height} );
2116			}
2117
2118			//console.log(box_width +' '+img_width+' '+new_width);
2119		}
2120
2121
2122	/**
2123	 * Form functions
2124	 * @version 4.8.2
2125	 * @updated 4.9.6
2126	 */
2127		$.fn.evo_RealTime_form_validation = function() {
2128	        return this.each(function() {
2129	            var form = $(this);
2130	            var req_fields = form.find('.input.req');
2131	            var email_fields = form.find('.input.email');
2132	            var humanvalid_fields = form.find('.input.evoelm_hval_val');
2133
2134            		        
2135	            req_fields.on('input blur', function() { $(this).evo_form_validate_field( 'text'); });
2136            	email_fields.on('input blur', function() { $(this).evo_form_validate_field( 'email'); });
2137            	humanvalid_fields.on('input blur', function() { $(this).evo_form_validate_field( 'humanvalid'); });
2138            	
2139	        });
2140	    }
2141
2142	    $.fn.evo_form_validation_check = function(){
2143
2144	    	var form = this;
2145	    	var req_fields = form.find('.input.req'); // Define here for use in validateForm
2146		    var email_fields = form.find('.input.email');
2147		    var humanvalid_fields = form.find('.input.evoelm_hval_val');
2148
2149	    	
2150            function validateForm() {
2151	            var hasErrors = false;
2152	            req_fields.each(function() {
2153	                if ( $(this).evo_form_validate_field( 'text')) hasErrors = true;
2154	            });
2155	            email_fields.each(function() {
2156	                if ($(this).evo_form_validate_field( 'email')) hasErrors = true;
2157	            });
2158	            humanvalid_fields.each(function() {
2159	                if ($(this).evo_form_validate_field( 'humanvalid')) hasErrors = true;
2160	            });
2161
2162	            return !hasErrors;
2163	        }
2164
2165	        return validateForm();
2166	    }
2167	    $.fn.evo_form_validate_field = function(type){
2168	    	var field = this;
2169	    	var errorElement = field.siblings('em');
2170            var hasError = false;
2171            var fieldValue = field.val().trim();
2172
2173            if (type === 'email') {		   
2174            	if (field.hasClass('req')) {
2175                    // Required email: Check if filled AND valid
2176                    hasError = fieldValue === '' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(fieldValue);
2177                } else {
2178                    // Optional email: Only check if it’s not empty
2179                    hasError = fieldValue !== '' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(fieldValue);
2180                }
2181                 	
2182            } else if (type === 'humanvalid') {
2183                var correctAnswer =  field.data('val'); // Expected answer from data attribute
2184                hasError = ( '89r329' +field.val().trim()+ '8932ufe' ) !== correctAnswer;
2185            } else {
2186                hasError = field.val().trim() === '';
2187            }                
2188
2189            if (hasError) {
2190                if (errorElement.length === 0) {
2191                    errorElement = $('<em class="evoelm_field_errmsg evopadt5"></em>');
2192                    field.after(errorElement);
2193                }
2194                errorElement.html(getErrorMessage(type === 'email' ? 'err2' : type === 'humanvalid' ? 'err3' : 'err1'))
2195                    .removeClass('evodn')
2196                    .addClass('evodib');
2197                field.addClass('err');
2198            } else {
2199                errorElement.remove();
2200                field.removeClass('err');
2201            }	   
2202
2203            function getErrorMessage(type) {
2204	            const messages = {
2205	                err1: evo_general_params.text.err1, // Required field error
2206	                err2: evo_general_params.text.err2, // Email format error
2207	                err3: evo_general_params.text.err3  // Human validation error (e.g., "Incorrect answer")
2208	            };
2209	            return messages[type] || "";
2210	        }             
2211
2212            return hasError;
2213	    }	
2214
2215	    $('body').on('evo_elm_form_presubmit_validation', function(event, form, callback){
2216    		event.preventDefault();
2217    		var $form = $(form);
2218
2219    		var isValid = $form.evo_form_validation_check();
2220
2221            if (typeof callback === "function") {
2222                callback(isValid); // Return true/false to the callback
2223            }
2224    	});
2225
2226	// Calendar Data & Shortcodes
2227		// get shortcodes from evo bottom
2228		$.fn.evo_shortcode_data = function(){		
2229			var ev_cal = $(this);
2230			return ev_cal.find('.evo_cal_data').data('sc');			
2231		}
2232
2233		// get filter data @4.6
2234			$.fn.evo_get_filter_data = function(){			
2235				return $(this).find('.evo_cal_data').data('filter_data');			
2236			}
2237			$.fn.evo_cal_get_filter_sub_data = function( tax , key){
2238				newdata = $(this).evo_get_filter_data();
2239
2240				if( !( tax in newdata ) ) return;
2241				if( !( key in newdata[tax] ) ) return;
2242				return newdata[ tax ][ key ];
2243			}
2244			$.fn.evo_cal_update_filter_data = function(tax, new_val, key){
2245
2246				newdata = $(this).evo_get_filter_data();
2247				if( key === undefined) key = 'nterms';
2248				newdata[ tax ][ key ] = new_val;
2249				$(this).find('.evo_cal_data').data('filter_data', newdata );
2250			}
2251			$.fn.evo_cal_get_footer_data = function( key ){
2252				data = $(this).find('.evo_cal_data').data();
2253
2254				//console.log(data);
2255
2256				if( data === undefined ) return false; // 4.6.2
2257				if( key in data ) return data[ key ];
2258				return false;		
2259			}
2260
2261		// hide cal data from view
2262		$.fn.evo_cal_hide_data = function(){			
2263			$(this).find('.evo_cal_data').attr({
2264				'data-sc':'',
2265				'data-filter_data':'',
2266				'data-nav_data':'',
2267			});			
2268		}
2269
2270		// update shortcode values from filter changes @u4.6
2271		$.fn.evo_update_sc_from_filters = function(){
2272			var el = $(this); 	
2273			SC = el.evo_shortcode_data();
2274
2275
2276			$.each( el.evo_get_filter_data() , function(index, value){
2277				var default_val 	= value.terms;
2278				var filter_val 		= value.nterms;
2279				const NOT_values 	= value.__notvals;
2280
2281				filter_val = filter_val == ''? 'NOT-all': filter_val;	
2282				
2283				var not_string = '';
2284
2285				// if NOT filter in place > include that in tax value for query
2286				if( NOT_values!== undefined && NOT_values.length >0 && filter_val != default_val ){	
2287					
2288					$.each(NOT_values, function(index, value){
2289						not_string += 'NOT-'+ value +',';
2290					});
2291				}		
2292
2293				SC[ index ] = not_string + filter_val;
2294			});
2295			
2296
2297			el.find('.evo_cal_data').data( 'sc', SC );
2298		}
2299		
2300		
2301
2302		// get shortcode single value
2303		$.fn.evo_get_sc_val = function(opt){
2304			var defaults = {	F:''}
2305			var OPT = $.extend({}, defaults, opt);
2306			var ev_cal = $(this); 
2307
2308			if(OPT.F=='') return false;
2309			SC = ev_cal.find('.evo_cal_data').data('sc');
2310
2311			if(!(SC[ OPT.F])) return false;
2312			return SC[ OPT.F];
2313		}
2314		// UPDATE Single value
2315		$.fn.evo_update_cal_sc = function(opt){
2316			var defaults = {
2317				F:'', V:''
2318			}
2319			var OPT = $.extend({}, defaults, opt);
2320			var ev_cal = $(this); 
2321			SC = ev_cal.find('.evo_cal_data').data('sc');
2322
2323			SC[ OPT.F ] = OPT.V;
2324
2325			ev_cal.find('.evo_cal_data').data( 'sc', SC );
2326		}
2327		// UPDATE all shortcode values
2328		$.fn.evo_update_all_cal_sc = function(opt){
2329			var defaults = {SC:''}
2330			var OPT = $.extend({}, defaults, opt);
2331			var CAL = $(this);
2332			CAL.find('.evo_cal_data').data( 'sc', OPT.SC );
2333		}
2334
2335		
2336
2337	// OTHERS
2338		// hex colors // @+2.8 @updated 4.7.2
2339			$.fn.evo_is_hex_dark = function(opt){
2340				var defaults = { hex:'808080'}
2341				var OPT = $.extend({}, defaults, opt);
2342
2343				hex = OPT.hex;
2344
2345				var c = hex.replace('#','');
2346				var is_hex = typeof c === 'string' && c.length === 6 && !isNaN(Number('0x' + c));
2347
2348				if(is_hex){	
2349					var values = c.split('');
2350					r = parseInt(values[0].toString() + values[1].toString(), 16);
2351				    g = parseInt(values[2].toString() + values[3].toString(), 16);
2352				    b = parseInt(values[4].toString() + values[5].toString(), 16);
2353				}else{
2354					var vals = c.substring(c.indexOf('(') +1, c.length -1).split(', ');
2355					var r = vals[0]  // extract red
2356					var g = vals[1];  // extract green
2357					var b = vals[2];
2358				}
2359
2360				var luma = ((r * 299) + (g * 587) + (b * 114)) / 1000; // per ITU-R BT.709
2361
2362				return luma> 128? true:false;
2363			}
2364
2365		// get rgb from hex code @4.5
2366			$.fn.evo_rgb_process = function(opt){
2367				var defaults = { data:'808080',type:'rgb', method:'rgb_to_val'}
2368				var opt = $.extend({}, defaults, opt);
2369
2370				const color = opt.data;
2371
2372				// RGB => hex
2373				if( opt.method == 'rgb_to_hex'){
2374					if(color == '1'){
2375						return;
2376					}else{
2377						if(color !=='' && color){
2378							rgb = color.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
2379							
2380							return "#" +
2381							("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
2382							("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
2383							("0" + parseInt(rgb[3],10).toString(16)).slice(-2);
2384						}
2385					}
2386				}
2387
2388				// RGB => rgb val
2389				if( opt.method == 'rgb_to_val'){
2390					if( opt.type == 'hex'){
2391						var rgba = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);	
2392						var rgb = new Array();
2393						rgb['r']= parseInt(rgba[1], 16);			
2394						rgb['g']= parseInt(rgba[2], 16);			
2395						rgb['b']= parseInt(rgba[3], 16);
2396						
2397					}else{
2398						rgb = color;
2399					}
2400					
2401					return parseInt((rgb['r'] + rgb['g'] + rgb['b'])/3);
2402				}				
2403			}
2404
2405		// Other data
2406			$.fn.evo_get_OD = function(){			
2407				var ev_cal = $(this);
2408				return ev_cal.find('.evo_cal_data').data('od');			
2409			}
2410
2411	
2412
2413		// get evo data for a given calendar
2414		$.fn.evo_getevodata = function(){
2415
2416			var ev_cal = $(this);
2417			var evoData = {};
2418			
2419			ev_cal.find('.evo-data').each(function(){
2420				$.each(this.attributes, function(i, attrib){
2421					var name = attrib.name;
2422					if(attrib.name!='class' && attrib.name!='style' ){
2423						name__ = attrib.name.split('-');
2424						evoData[name__[1]] = attrib.value;	
2425					}
2426				});
2427			});	
2428
2429			return evoData;
2430		}
2431
2432		// check if mobile device v4.6
2433		$.fn.evo_is_mobile = function(){
2434			return ( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) )? true: false;		
2435		}
2436
2437	// eventon loading functions
2438	// v 2.4.5 -- deprecating
2439		$.fn.evo_loader_animation = function(opt){
2440			var defaults = {
2441				direction:'start'
2442			}
2443			var OPT = $.extend({}, defaults, opt);
2444
2445			if(OPT.direction == 'start'){
2446				$(this).find('#eventon_loadbar').slideDown();
2447			}else{
2448				$(this).find('#eventon_loadbar').slideUp();
2449			}
2450		}
2451
2452	// DEPRECATED functions
2453		$.fn.evo_item_shortcodes = function(){			
2454			var OBJ = $(this);
2455			var shortcode_array ={};			
2456			OBJ.each(function(){	
2457				$.each(this.attributes, function(i, attrib){
2458					var name = attrib.name;
2459					if(attrib.name!='class' && attrib.name!='style' && attrib.value !=''){
2460						name__ = attrib.name.split('-');
2461						shortcode_array[name__[1]] = attrib.value;	
2462					}
2463				});
2464			});
2465			return shortcode_array;
2466		}
2467		$.fn.evo_shortcodes = function(){			
2468			var ev_cal = $(this);
2469			var shortcode_array ={};
2470					
2471			ev_cal.find('.cal_arguments').each(function(){
2472				$.each(this.attributes, function(i, attrib){
2473					var name = attrib.name;
2474					if(attrib.name!='class' && attrib.name!='style' && attrib.value !=''){
2475						name__ = attrib.name.split('-');
2476						shortcode_array[name__[1]] = attrib.value;	
2477					}
2478				});
2479			});	
2480			return shortcode_array;
2481		}
2482		
2483
2484});

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.