PageSourceSearch

https://www.religionstatue.com/wp-content/plugins/unlimited-elemen…/filters/ue_filters.js?ver=2.0.10

js religionstatue.com collected 2026-10-03 01:42:45 UTC 96,852 bytes, 4,824 lines download raw bytes

1//UE Filters Version 1.27
2
3function UEDynamicFilters(){
4
5	var g_objFilters, g_filtersData, g_urlBase;
6	var g_urlAjax, g_lastGridAjaxCall, g_cache = {}, g_objBody;
7	var g_remote = null, g_lastSyncGrids, g_initFiltersCounter = 0;
8	
9	var t = this;
10	
11	var g_showDebug = false;
12	var g_debugInitMode = false;
13	
14	var g_debugBeforeRefreshMode = false;	//debug filters state before refresh
15	
16	var g_isGutenberg = false;
17	
18	var g_types = {
19		PAGINATION:"pagination",
20		LOADMORE:"loadmore",
21		TERMS_LIST:"terms_list",
22		SEARCH: "search",
23		SELECT: "select",
24		SUMMARY: "summary",
25		GENERAL: "general",
26		GENERAL_MOBILE_DRAWER: "mobilefilters"
27	};
28
29	var g_vars = {
30		CLASS_DIV_DEBUG:"uc-div-ajax-debug",
31		CLASS_GRID:"uc-filterable-grid",
32		CLASS_GRID_NOREFRESH:"uc-grid-norefresh",	//grid that will not refresh
33		DEBUG_AJAX_OPTIONS: false,
34		CLASS_CLICKED:"uc-clicked",
35		CLASS_HIDDEN: "uc-filter-hidden",	//don't refresh with this class
36		CLASS_INITING: "uc-filter-initing",
37		CLASS_INITING_HIDDEN: "uc-initing-filter-hidden",
38		CLASS_SKIP_REFRESH: "uc-filters-norefresh",		//on some grid parent
39		CLASS_REFRESH_SOON: "uc-ajax-refresh-soon",
40		EVENT_SET_HTML_ITEMS: "uc_ajax_sethtml",
41		CLASS_FILTER_INITED:"ucfilters--filter-inited",
42		ATTRIBUTE_URLADD:"ajaxurladd",
43		GRID_DATA_SKIP_HTML: "skip_set_html",
44		
45		//grid events
46
47		EVENT_BEFORE_REFRESH: "uc_before_ajax_refresh",	   //on grid
48		EVENT_AJAX_REFRESHED: "uc_ajax_refreshed",	   //on grid
49		EVENT_AJAX_REFRESHED_BODY: "uc_ajax_refreshed_body",	   //on body
50		EVENT_UPDATE_ACTIVE_FILTER_ITEMS: "update_active_filter_items",	   //on grid
51		EVENT_UNSELECT_FILTER: "uc_unselect_filter",   //on grid
52		EVENT_SILENT_FILTER_CHANGE: "uc_silent_filter_change",   //on grid
53
54		EVENT_DOM_UPDATED: "uc_dom_updated",   //on body
55
56		//events on filters
57
58		EVENT_INIT_FILTER:"init_filter",
59		EVENT_INIT_FILTER_TYPE:"init_filter_type",
60		EVENT_GET_FILTER_DATA:"get_filter_data",
61		EVENT_FILTER_RELOADED: "uc_ajax_reloaded",
62
63		//grid actions
64
65		ACTION_CLEAR_FILTERS: "clear_filters",	   //on grid
66		ACTION_REFRESH_GRID: "uc_refresh",	//listen on grid
67		ACTION_GET_FILTERS_URL: "uc_get_filters_url",	//listen on grid
68		ACTION_FILTER_CHANGE: "uc_filter_change",		//listen on grid
69		ACTION_FILTER_UNSELECT_BY_KEY: "unselect_by_key",	//listen on grid
70		
71		REFRESH_MODE_PAGINATION: "pagination",
72		REFRESH_MODE_LOADMORE: "loadmore",
73		trashold_handle:null,
74		class_widget_wrapper:"elementor-widget",
75		current_postid:null,
76		ucpage_url:null
77	};
78
79	var g_options = {
80		is_cache_enabled:true,
81		urlkey_taxsap:"~"
82	};
83	
84	/**
85	 * console log some string
86	 */
87	function trace(str){
88		console.log(str);
89	}
90
91	function ________GENERAL_______________(){}
92
93
94
95	/**
96	 * add url param
97	 */
98	function addUrlParam(url, param, value){
99
100		if(url){
101			if(url.indexOf("?") == -1)
102				url += "?";
103			else
104				url += "&";
105		}
106
107		if(typeof value == "undefined")
108			url += param;
109		else
110			url += param + "=" + value;
111
112		return(url);
113	}
114
115
116	/**
117	 * get object property
118	 */
119	function getVal(obj, name, defaultValue){
120
121		if(!defaultValue)
122			var defaultValue = "";
123
124		var val = "";
125
126		if(!obj || typeof obj != "object")
127			val = defaultValue;
128		else if(obj.hasOwnProperty(name) == false){
129			val = defaultValue;
130		}else{
131			val = obj[name];
132		}
133
134		return(val);
135	}
136
137	/**
138	 * turn string value ("true", "false") to string
139	 */
140	function strToBool(str){
141
142		switch(typeof str){
143			case "boolean":
144				return(str);
145			break;
146			case "undefined":
147				return(false);
148			break;
149			case "number":
150				if(str == 0)
151					return(false);
152				else
153					return(true);
154			break;
155			case "string":
156				str = str.toLowerCase();
157
158				if(str == "true" || str == "1")
159					return(true);
160				else
161					return(false);
162
163			break;
164		}
165
166		return(false);
167	};
168
169	/**
170	 * get offsets distance
171	 */
172	function getOffsetsDistance(offset1, offset2){
173
174	  var dx = offset2.left-offset1.left;
175	  var dy = offset2.top-offset1.top;
176
177	  return Math.sqrt(dx*dx+dy*dy);
178	}
179
180	/**
181	 * round number to one decimal
182	 */
183	function roundToOneDecimal(num) {
184	    if (num % 1 !== 0) {
185	        return num.toFixed(1); // Round to 1 decimal place
186	    } else {
187	        return num.toFixed(0); // Keep the whole number
188	    }
189	}
190
191
192	/**
193	 * get closest object by offset
194	 */
195	function getClosestByOffset(objParents, objElement, isVertical){
196
197		if(objParents.length == 0){
198			throw new Error("get closest by offset error - grids not found");
199		}
200
201		if(g_showDebug == true){
202
203			trace("get closest grids for");
204			trace(objElement)
205			trace("parents");
206			trace(objParents);
207		}
208
209		var objClosest = null;
210		var minDiff = 1000000;
211
212		var elementOffset = objElement.offset();
213
214		jQuery.each(objParents, function(index, parent){
215
216			var objParent = jQuery(parent);
217
218			var objGrid = jQuery(parent);	//return this one
219
220			var distance = 0;
221
222			var isVisible = objParent.is(":visible");
223			
224			var constantHeight = null;
225
226			if(isVisible == false){
227				objParent = objParent.parent();
228			}
229
230			var parentOffset = objParent.offset();
231
232			if(isVertical == true){
233
234				var offsetY = elementOffset.top;
235				var parentY = parentOffset.top;
236
237				//get bottom of the parent
238
239				if(parentY < offsetY)
240					parentY += objParent.height();
241
242				var distance = Math.abs(offsetY - parentY);
243
244			}else{
245
246				var parentOffset = objParent.offset();
247
248				var distance = getOffsetsDistance(parentOffset, elementOffset);
249			}
250
251			if(g_showDebug == true){
252
253				trace(objParent);
254				trace("distance: " + distance);
255
256				trace("is vertical: " + isVertical);
257			}
258
259			if(distance < minDiff){
260				minDiff = distance;
261				objClosest = objGrid;
262			}
263
264		});
265
266		if(g_showDebug == true){
267
268			trace("filter: ");
269			trace(objElement);
270
271			trace("Closest grid found:");
272			trace(objClosest);
273		}
274
275
276		return(objClosest);
277	}
278
279	/**
280	 * get all grids
281	 */
282	function getAllGrids(type){
283
284		if(type == "loaded_only")
285			var objGrids = jQuery("."+ g_vars.CLASS_GRID).not(".ucfilters--grid-inited");
286		else
287			var objGrids = jQuery("."+ g_vars.CLASS_GRID);
288
289		return(objGrids);
290	}
291
292
293  /**
294   * get grid from parents containers
295   */
296  function getGridFromParentContainers(objSource){
297
298    var objParents = objSource.parents();
299    var objGrid = null;
300
301    if(g_showDebug == true){
302
303		trace("get from parent containers");
304		trace(objParents);
305	}
306
307    objParents.each(function(){
308
309      var objParent = jQuery(this);
310
311      objGrid = objParent.find("."+ g_vars.CLASS_GRID);
312
313      //if grid found return it and exit loop
314      if(objGrid.length >= 1)
315        return(false);
316
317    });
318
319
320    return(objGrid);
321  }
322
323
324	/**
325	 * get closest grid to some object
326	 */
327	function getClosestGrid(objSource){
328
329		//in case there are nothing:
330		var objGrids = getAllGrids();
331
332		if(objGrids.length == 0)
333			return(null);
334
335		if(g_showDebug == true){
336
337			trace("get closest grids");
338			trace(objSource);
339			trace(objGrids);
340		}
341
342		//get grid from parents
343
344		if(objGrids.length == 1)
345			return(objGrids);
346
347		//narrow by group
348		var group = objSource.data("connectgroup");
349
350		if(group){
351			var objGridsGroup = objGrids.filter("[data-filtergroup="+group+"]");
352			
353			if(objGridsGroup.length > 0){
354
355				if(objGridsGroup.length == 1)
356					return(objGridsGroup);
357
358				objGrids = objGridsGroup;
359			}
360
361		}else{
362
363			//get from same container - if group not set
364
365		    var objGrid = getGridFromParentContainers(objSource);
366
367		    if(objGrid && objGrid.length == 1)
368		        return(objGrid);
369		}
370
371
372		//get closest by offset
373
374	    if(objGrid && objGrid.length > 1)
375	    	objGrids = objGrid;
376
377		var objSingleGrid = getClosestByOffset(objGrids, objSource, true);
378
379		if(objSingleGrid && objSingleGrid.length == 1)
380			return(objSingleGrid);
381
382		//return first grid in the list
383
384		var objFirstGrid = jQuery(objGrids[0]);
385
386		return(objFirstGrid);
387	}
388
389	
390	
391	/**
392	 * add filter object to grid
393	 */
394	function bindFilterToGrid(objGrid, objFilter){
395		
396		if(g_showDebug){
397			trace("bind filter to grid");
398			
399			trace(objFilter);
400		}
401		
402		var arrFilters = objGrid.data("filters");
403		var objTypes = objGrid.data("filter_types");
404
405		if(!arrFilters)
406			arrFilters = [];
407
408		if(!objTypes)
409			objTypes = {};
410
411		var type = getFilterType(objFilter);
412
413		//validate double types
414
415		if(objTypes.hasOwnProperty(type)){
416
417			switch(type){
418				case g_types.LOADMORE:
419
420					trace("Double filter not allowed");
421					trace("existing Filters:");
422					trace(arrFilters);
423
424					trace("Second Filter");
425					trace(objFilter);
426
427					trace("Grid:");
428					trace(objGrid);
429
430					showElementError(objFilter, "Double load more button for one grid not allowed")
431					return(false);
432				break;
433			}
434
435		}
436
437		objTypes[type] = true;
438
439		var filterID = objFilter.attr("id");
440
441		//handle sticky
442		
443		var objElementorStickySpacer = objFilter.closest(".elementor-sticky__spacer");
444		if(objElementorStickySpacer.length)
445			return(true);
446		
447		
448		//----- validate existing -----
449		
450		var objExistingFilter = arrFilters.filter(function(objFilterInArray){
451			return objFilterInArray.attr("id") == filterID;
452		});
453		
454		if(objExistingFilter && objExistingFilter.length)
455				throw new Error("Can't bind filter to grid, it's already exists: " + filterID);			
456		
457		arrFilters.push(objFilter);
458
459		//add init after filters
460		var isInitAfter = objFilter.data("initafter");
461				
462		if(!isInitAfter)
463			isInitAfter = isSpecialFilterInitAfter(objFilter, objGrid);
464		
465		if(g_showDebug){
466			trace("init after: "+isInitAfter);
467		}
468				
469		if(isInitAfter === true){
470			addFilterToInitAfter(objFilter, objGrid);
471		}
472		
473		objGrid.data("filters", arrFilters);
474		
475		objGrid.data("filter_types", objTypes);
476
477	}
478
479	/**
480	 *
481	 * get element widget id from parent wrapper
482	 */
483	function getElementWidgetID(objElement){
484		
485		if (!objElement || objElement.length === 0)
486			throw new Error("Element not found");
487				
488		var objWidget = objElement.closest("."+g_vars.class_widget_wrapper);
489
490		if (objWidget.length === 0)
491			throw new Error("Element parent not found with class: "+g_vars.class_widget_wrapper);
492		
493		var widgetID = objWidget.data("id");
494
495		if (!widgetID)
496			throw new Error("widget id not found");
497
498		return widgetID;
499	}
500	
501
502	/**
503	 * get the grid widget object from elementor element id
504	 */
505	function getGridFromElementorElementID(elementID, group, showDebug){
506		
507		var selector = "."+g_vars.class_widget_wrapper+"[data-id='"+elementID+"']";
508		
509		var objElement = g_objBody.find(selector);
510		
511		if(showDebug == true){
512			trace("selector: "+selector);
513			trace("element: ");
514			trace(objElement);
515		}
516		
517		if(objElement.length == 0)
518			return(null);
519		
520		var selectorGrid = "."+g_vars.CLASS_GRID;
521		
522		var objGrid = objElement.find(selectorGrid);
523
524		if(showDebug == true){
525			trace("selector grid: "+selectorGrid);
526			trace("grid: ");
527			trace(objGrid);
528		}
529		
530		if(objGrid.length == 1)
531			return(objGrid);
532		
533		if(objGrid.length == 0)
534			return(null);
535
536		//more then one, filter by group
537		if(group){
538			objGrid = objGrid.filter("[data-filtergroup="+group+"]");
539		}
540
541		if(showDebug == true){
542			trace("after group filter: "+group);
543			trace(objGrid);
544		}
545		
546		if(objGrid.length != 1)
547			return(null);
548		
549		
550		return(objGrid);
551	}
552	
553	
554
555	/**
556	 * get another group widgets
557	 */
558	function getGroupWidgets(arrSyncedGrids, objElement){
559
560		var group = objElement.data("filtergroup");
561
562		if(!group)
563			return(arrSyncedGrids);
564
565		var objGrids = jQuery("."+ g_vars.CLASS_GRID);
566
567		if(objGrids.length < 2)
568			return(arrSyncedGrids);
569
570		var elementID = objElement.attr("id");
571
572		var objDataGrids = objGrids.filter("[data-filtergroup='"+group+"']:not(#" + elementID + ")");
573
574		if(objDataGrids.length == 0)
575			return(arrSyncedGrids);
576
577		jQuery.each(objDataGrids, function(index, grid){
578
579			var objGrid = jQuery(grid);
580
581			arrSyncedGrids.push(objGrid);
582		});
583
584
585
586		return(arrSyncedGrids);
587	}
588
589	/**
590	 * get synced widget IDs
591	 */
592	function getSyncedWidgetData(objElement){
593
594		var arrSyncedGrids = [];
595
596		if(g_remote)
597			arrSyncedGrids = g_remote.getSyncedElements(objElement);
598
599		if(!arrSyncedGrids)
600			arrSyncedGrids = [];
601
602		arrSyncedGrids = getGroupWidgets(arrSyncedGrids, objElement);
603
604		if(!arrSyncedGrids || arrSyncedGrids.length == 0)
605			return(false);
606
607		var arrWidgetIDs = [];
608
609		var objGrids = null;
610
611		for(var index in arrSyncedGrids){
612
613			var objGrid = arrSyncedGrids[index];
614
615			if(objGrid.hasClass(g_vars.CLASS_GRID) == false){
616
617				var message = "Please enable ajax on all synced widgets";
618				var message2 = "Please enable ajax on this synced widget, it's missing class: "+g_vars.CLASS_GRID;
619
620				showElementError(objGrid, message2);
621
622				showAjaxError(message);
623				throw new Error(message);
624				return(false);
625			}
626
627			var objWidgetID = getElementWidgetID(objGrid);
628
629			//add to jquery collection
630
631			if(!objGrids)
632				objGrids = objGrid;
633			else
634				objGrids = objGrids.add(objGrid);
635
636			arrWidgetIDs.push(objWidgetID);
637		}
638
639		var strWidgetIDs = arrWidgetIDs.toString();
640
641		var objOutput = {};
642		objOutput["ids"] = strWidgetIDs;
643		objOutput["grids"] = objGrids;
644
645		return(objOutput);
646	}
647
648
649	/**
650	 * get element layout data
651	 */
652	function getElementLayoutData(objElement, addSyncedGrids){
653		
654		//get widget id
655		var widgetID = getElementWidgetID(objElement);
656		var objWidget = objElement.parents("."+g_vars.class_widget_wrapper);
657
658		//get synced grids
659		var objSyncedData = null;
660
661		//add sync if allowed and available
662
663		if(addSyncedGrids){
664
665			var objSyncedData = getSyncedWidgetData(objElement);
666
667			if(g_showDebug && objSyncedData){
668
669				trace("sync data");
670				trace(objSyncedData);
671			}
672		}else{
673
674			if(g_showDebug)
675				trace("skip sync grid");
676
677		}
678		
679		//get layout id
680		
681		if(g_isGutenberg == false){
682		
683			var objLayout = objWidget.parents(".elementor");
684	
685			if(objLayout.length == 0)
686				throw new Error("layout not found");
687			
688			var layoutID = objLayout.data("elementor-id");
689	
690			if(!layoutID)
691				layoutID = objLayout.data("id");
692			
693		}else{	//gutenberg
694			
695			var layoutID = g_vars.current_postid;			
696		}
697		
698		
699		var output = {};
700
701		output["widgetid"] = widgetID;
702		output["layoutid"] = layoutID;
703
704		if(objSyncedData){
705			output["synced_widgetids"] = objSyncedData["ids"];
706			output["synced_grids"] = objSyncedData["grids"];
707		}
708
709		return(output);
710	}
711
712	/**
713	 * show element error above it
714	 */
715	function showElementError(objElement, error){
716
717		var objParent = objElement.parent();
718		
719		if(g_showDebug == true){
720			trace("Show Error Message for: ");
721			trace(objElement);
722			trace(error);
723		}
724		
725		var objError = objParent.find(".uc-filers-error-message");
726		if(objError.length == 0){
727			objParent.append("<div class='uc-filers-error-message' style='color:red;position:absolute;top:-24px;left:0px;background-color:rgba(230, 230, 230, 0.8);padding:3px;font-size:12px;border:5px solid white;'></div>");
728			var objError = objParent.find(".uc-filers-error-message");
729			objParent.css("border","1px solid red !important");
730		}
731		
732		objError.append(error);
733
734		objError.css("top",-objError.height()-5);
735		
736	}
737
738	/**
739	 * get grid empty message
740	 */
741	function getGridEmptyMessage(objGrid){
742
743		var gridID = objGrid.attr("id");
744
745		if(!gridID)
746			return(null);
747
748		var objEmptyMessage = jQuery("#"+gridID+"_empty_message");
749
750		if(objEmptyMessage.length == 0)
751			return(null);
752
753		return(objEmptyMessage);
754	}
755
756	/**
757	 * get active filter items, if no items - return 0
758	 */
759	function getGridActiveFilterItems(objGrid){
760		
761		var arrActiveItems = objGrid.data("active_filters_items");
762
763		if(!arrActiveItems)
764			return(null);
765
766		if(arrActiveItems.length == 0)
767			return(null);
768
769		return(arrActiveItems);
770	}
771
772
773	/**
774	 * get filters that are selected
775	 */
776	function getSelectedFilters(objFilters, roleArg){
777
778		if(!objFilters)
779			var objFilters = objGrid.data("filters");
780
781		if(!objFilters)
782			return(false);
783
784		var arrSelectedFilters = [];
785
786		jQuery.each(objFilters, function(index, filter){
787
788			var objFilter = jQuery(filter);
789			var isSelected = objFilter.hasClass("uc-has-selected");
790
791			if(!roleArg && isSelected == true){
792				arrSelectedFilters.push(objFilter);
793				return(true);
794			}
795
796			var role = objFilter.data("role");
797
798			if(role == roleArg){
799				var isSelected = objFilter.hasClass("uc-has-selected");
800				if(isSelected)
801					arrSelectedFilters.push(objFilter);
802			}
803
804		});
805
806		return(arrSelectedFilters);
807	}
808
809
810	function ________FILTERS_______________(){}
811
812
813	/**
814	 * get the parent
815	 */
816	function getFiltersParent(objFilters){
817
818		//init the events
819		var objParent = objFilters.parents(".elementor");
820
821		if(objFilters.length > 1 && objParent.length > 1)
822			objParent = objFilters.parents("body");
823
824		if(objParent.length > 1){
825			objParent = jQuery(objParent[0]);
826		}
827
828		if(objParent.length == 0)
829			objParent = objFilters.parents("body");
830
831		return(objParent);
832	}
833	
834	/**
835	 * get filter wrapper
836	 */
837	function getFilterWrapper(objFilter){
838		
839		var objParent = objFilter.parent();		
840		
841		if(objParent.hasClass("uc-checkbox-filter-accordion-container"))
842			objParent = objParent.parent();
843		
844		return(objParent);
845	}
846
847	
848	/**
849	 * get filter type
850	 */
851	function getFilterType(objFilter, getGeneralType){
852		
853		if(objFilter.hasClass("uc-filter-pagination"))
854			return(g_types.PAGINATION);
855
856		if(objFilter.hasClass("uc-filter-load-more"))
857			return(g_types.LOADMORE);
858
859		var filterType = objFilter.data("filtertype")
860
861		if(filterType == g_types.GENERAL && getGeneralType === true){
862			
863			var generalType = objFilter.data("generaltype");
864			return(generalType);
865		}
866		
867		if(filterType)
868			return(filterType);
869		
870		//if not found - throw error
871		
872		trace("Filter type not found: ");
873		trace(objFilter);
874		
875		throw new Error("wrong filter type");
876		
877	}
878
879
880	/**
881	 * clear all filters
882	 */
883	function clearAllFilters(objGrid){
884		
885		clearChildFilters(objGrid, null, true, null, true);
886	}
887
888	/**
889	 * get grid filters or null
890	 */
891	function getGridFilters(objGrid){
892
893		var objFilters = objGrid.data("filters");
894
895		if(!objFilters)
896			return(null);
897
898		if(objFilters.length == 0)
899			return(null);
900
901		return(objFilters);
902	}
903
904
905	/**
906	 * clear non main grid filters
907	 * hide children and just clear the main filters
908	 */
909	function clearChildFilters(objGrid, objCurrentFilter, isHideChildren, termID, isClearAll){
910		
911		var objFilters = getGridFilters(objGrid);
912		
913		if(!objFilters)
914			return(false);
915
916		var currentFilterID = null;
917
918		if(objCurrentFilter)
919			var currentFilterID = objCurrentFilter.attr("id");
920						
921		jQuery.each(objFilters, function(index, filter){
922						
923			var objFilter = jQuery(filter);
924			var filterID = objFilter.attr("id");
925
926			if(filterID == currentFilterID)
927				return(true);
928
929			var role = objFilter.data("role");
930			
931			//clear all others if that option selected
932			
933			if(role != "child" && role != "main" && role != "term_child"){
934				
935				if(isClearAll == true){
936					clearFilter(objFilter);
937				}
938				
939				return(true);
940			}
941
942			var isHide = false;
943			var isShow = false;
944
945			switch(role){
946				case "term_child":
947					if(isHideChildren == true)
948						isHide = true;
949
950					var linkedTermID = objFilter.data("childterm");
951
952					if(linkedTermID == termID){		//show the filter
953
954						objFilter.removeClass(g_vars.CLASS_HIDDEN);
955						objFilter.removeClass(g_vars.CLASS_INITING);
956						objFilter.removeClass(g_vars.CLASS_INITING_HIDDEN);
957					}else{
958						isHide = true;
959					}
960
961				break;
962				case "child":
963
964					if(isHideChildren == true)
965						isHide = true;
966					else{
967						//hide the filters and refresh
968
969						objFilter.removeClass(g_vars.CLASS_HIDDEN);
970
971						objFilter.addClass(g_vars.CLASS_INITING);
972						objFilter.addClass(g_vars.CLASS_INITING_HIDDEN);
973
974					}
975
976				break;
977				default:
978					
979					if(isClearAll == true){
980						clearFilter(objFilter);
981					}
982					
983					return(true);
984				break;
985			}
986
987			//hide the child filters and not refresh
988
989			if(isHide == true)
990				objFilter.addClass(g_vars.CLASS_HIDDEN);
991			
992			clearFilter(objFilter);
993
994		});
995
996	}
997
998	/**
999	 * clear some filter
1000	 */
1001	function clearFilter(objFilter){
1002		
1003		var type = getFilterType(objFilter);
1004
1005		switch(type){
1006			case g_types.TERMS_LIST:
1007				var objSelectedItems = objFilter.find(".ue_taxonomy_item.uc-selected");
1008				objSelectedItems.removeClass("uc-selected");
1009
1010				var objAll = objFilter.find(".ue_taxonomy_item.uc-item-all");
1011				objAll.addClass("uc-selected");
1012
1013			break;
1014			case g_types.SELECT:
1015				
1016				var objSelect = objFilter.find("select");
1017				objSelect.val("");
1018				
1019				//must leave one selected
1020				var objSelected = objFilter.find("option:selected");
1021				
1022				if(objSelected.length == 0)
1023					objFilter.find("option:first-child").prop("selected","selected");
1024				
1025			break;
1026			default:
1027			case g_types.SEARCH:
1028			case g_types.GENERAL:
1029				objFilter.trigger("clear_filter");
1030			break;
1031		}
1032
1033	}
1034
1035	/**
1036	 * unselect filter item
1037	 */
1038	function unselectFilterItem(objGrid, key){
1039
1040		var objFilters = getGridFilters(objGrid);
1041
1042		if(!objFilters)
1043			return(false);
1044		
1045		jQuery.each(objFilters, function(index, filter){
1046
1047			var objFilter = jQuery(filter);
1048			
1049			objFilter.trigger(g_vars.ACTION_FILTER_UNSELECT_BY_KEY, [key]);
1050			
1051		});
1052
1053	}
1054
1055	/**
1056	 * return true if the filter skip's it's action - like under mobile drawer
1057	 */
1058	function isFilterSkipAction(objFilter){
1059
1060		var objParentSkipRefresh = objFilter.parents("." + g_vars.CLASS_SKIP_REFRESH);
1061		
1062		if(objParentSkipRefresh.length)
1063			return(true);
1064
1065		return(false);
1066	}
1067	
1068	/**
1069	 * return if the grid has some child filters
1070	 */
1071	function hasChildFilters(objGrid){
1072		
1073		var objFilters = getGridFilters(objGrid);
1074		
1075		if(!objFilters)
1076			return(false);
1077		
1078		for(var index in objFilters){
1079			
1080			var objFilter = objFilters[index];
1081			var role = objFilter.data("role");
1082			if(role == "child")
1083				return(true);
1084		}
1085		
1086		return(false);
1087	}
1088	
1089	/**
1090	 * check and trigger skip action to the grid if needed 
1091	 * run before the refresh on some filter click
1092	 * for the mobile drawer (off canvas)
1093	 */
1094	function checkTriggerSkipAction(objFilter, objGrid){
1095		
1096		var isSkipAction = isFilterSkipAction(objFilter);
1097		if(isSkipAction == false)
1098			return(false);
1099		
1100		if(g_showDebug == true)
1101			trace("skip refresh - silent change triggered");
1102		
1103		var filterRole = objFilter.data("role");
1104		
1105		objGrid.trigger(g_vars.EVENT_SILENT_FILTER_CHANGE);
1106		
1107		initGrid_setActiveFiltersData(objGrid);
1108		
1109		//refresh children only main / children available
1110		if(filterRole == "main" && hasChildFilters(objGrid)){
1111			
1112			if(g_showDebug == true)
1113				trace("refresh children only");
1114			
1115			objGrid.data(g_vars.GRID_DATA_SKIP_HTML, true);
1116			refreshAjaxGrid(objGrid);
1117		}
1118		
1119		
1120		return(true);
1121	}
1122	
1123	function ________PAGINATION_FILTER______(){}
1124
1125
1126	/**
1127	 * get pagination selected url or null if is current
1128	 */
1129	function getPaginationSelectedData(objPagination){
1130				
1131		var objCurrentLink = objPagination.find("a.current,span.current");
1132			
1133		if(objCurrentLink.length == 0)
1134			return(null);
1135
1136		var url = objCurrentLink.attr("href");
1137				
1138		var numPage = objCurrentLink.text();
1139		
1140		if(jQuery.isNumeric(numPage) == false)
1141			numPage = null;
1142
1143		numPage = Number(numPage);
1144
1145		if(numPage === 1)
1146			numPage = null;
1147
1148		var output = {};
1149		output["url"] = url;
1150		output["page"] = numPage;
1151
1152		return(output);
1153	}
1154
1155
1156	/**
1157	 * on ajax pagination click
1158	 */
1159	function onAjaxPaginationLinkClick(event){
1160		
1161		var objLink = jQuery(this);
1162		
1163		//if no grid attached - act like a regular link
1164		
1165		var objPagination = objLink.parents(".uc-filter-pagination");
1166		
1167		var objGrid = objPagination.data("grid");
1168		
1169		if(!objGrid || objGrid.length == 0 || objPagination.hasClass("uc-no-ajax")){
1170						
1171			return(true);
1172		}
1173		
1174		//run the ajax, prevent default
1175		event.preventDefault();
1176		
1177		var objLinkCurrent = objPagination.find(".current");
1178
1179		
1180		//on next button click
1181
1182		if(objLink.hasClass("next")){
1183
1184			var nextLink = objLinkCurrent.next();
1185
1186			var objNextLink = jQuery(nextLink);
1187
1188			objNextLink.trigger("click");
1189
1190			return(false);
1191		}
1192
1193
1194		//on prev button click
1195
1196		if(objLink.hasClass("prev")){
1197
1198			var prevLink = objLinkCurrent.prev();
1199
1200			var objPrevLink = jQuery(prevLink);
1201
1202			objPrevLink.trigger("click");
1203
1204			return(false);
1205		}
1206
1207		objLinkCurrent.removeClass("current");
1208
1209		objLink.addClass("current");
1210
1211		var objGrid = objPagination.data("grid");
1212		
1213		objPagination.addClass(g_vars.CLASS_CLICKED);
1214
1215		if(g_showDebug == true){
1216
1217			trace("click on pagination!!!, no grid refresh");
1218			trace(objLink);
1219
1220		}else{
1221
1222			refreshAjaxGrid(objGrid, g_vars.REFRESH_MODE_PAGINATION);
1223
1224		}
1225
1226		return(false);
1227	}
1228
1229
1230	function ________LOAD_MORE_______________(){}
1231
1232
1233	/**
1234	 * get current load more page
1235	 */
1236	function getLoadMoreUrlData(objFilter){
1237
1238		var objData = objFilter.find(".uc-filter-load-more__data");
1239
1240		var nextOffset = objData.data("nextoffset");
1241		if(!nextOffset)
1242			nextOffset = null;
1243
1244		var numItems = objFilter.data("numitems");
1245
1246		if(!numItems)
1247			numItems = null;
1248
1249		//affect only single grids
1250
1251		var isSingleGridOnly = objFilter.data("affect_single_grid");
1252
1253
1254		var data = {};
1255		data.offset = nextOffset;
1256		data.numItems = numItems;
1257		data.singlegrid = isSingleGridOnly;
1258
1259		return(data);
1260	}
1261
1262
1263	/**
1264	 * do the load more operation
1265	 */
1266	function onLoadMoreClick(){
1267
1268		var objLink = jQuery(this);
1269
1270		var objLoadMore = objLink.parents(".uc-filter-load-more");
1271
1272		var objData = objLoadMore.find(".uc-filter-load-more__data");
1273
1274		var isMore = objData.data("more");
1275
1276		if(isMore == false)
1277			return(false);
1278
1279		var objGrid = objLoadMore.data("grid");
1280
1281		if(!objGrid || objGrid.length == 0)
1282			throw new Error("Grid not found!");
1283
1284		//run the ajax, prevent default
1285
1286		objLoadMore.addClass(g_vars.CLASS_CLICKED);
1287
1288		refreshAjaxGrid(objGrid, g_vars.REFRESH_MODE_LOADMORE);
1289
1290	}
1291
1292	function ________SELECT_______________(){}
1293
1294	/**
1295	 * init select filter, select the selected item (avoid cache)
1296	 */
1297	function initSelectFilter(objFilter){
1298		
1299		var objSelected = objFilter.find(".uc-selected");
1300
1301		if(objSelected.length == 0)
1302			return(false);
1303
1304		var value = objSelected.attr("value");
1305
1306		var objSelect = objFilter.find("select");
1307
1308		objSelect.val(value);
1309
1310	}
1311
1312
1313	function ________TERMS_LIST_______________(){}
1314
1315	/**
1316	 * unselect by key terms list and select
1317	 */
1318	function termsFilterUnselectByKey(event,key){
1319				
1320		var objFilter = jQuery(this);
1321		
1322		var selectedTerm = getTermsListSelectedTerm(objFilter);
1323		
1324		if(!selectedTerm)
1325			return(false);
1326		
1327		var selectedKey = getVal(selectedTerm,"key");
1328		
1329		if(selectedKey != key)
1330			return(false);
1331		
1332		//if key match - clear filter and set no refresh.
1333
1334		clearFilter(objFilter);	
1335		
1336		setNoRefreshFilter(objFilter);
1337	}
1338
1339
1340	/**
1341	 * on terms list click
1342	 */
1343	function onTermsLinkClick(event){
1344		
1345		var className = "uc-selected";
1346
1347		event.preventDefault();
1348
1349		var objLink = jQuery(this);
1350 
1351		if(objLink.hasClass("uc-grid-filter")){
1352
1353			var objTermsFilter = objLink;
1354
1355		}else{
1356
1357			var objTermsFilter = objLink.parents(".uc-grid-filter");
1358		}
1359
1360		var filterType = getFilterType(objTermsFilter);
1361
1362		if(filterType == g_types.SELECT){
1363
1364			var objLink = objTermsFilter.find("option:selected");
1365		}
1366
1367		if(filterType == g_types.TERMS_LIST){
1368
1369			var objActiveLinks = objLink.siblings("."+className).not(objLink);
1370
1371			objActiveLinks.removeClass(className);
1372			objLink.addClass(className);
1373
1374		}
1375
1376		var objGrid = objTermsFilter.data("grid");
1377
1378		if(!objGrid || objGrid.length == 0)
1379			throw new Error("Grid not found");
1380
1381		//if main filter - clear other filters
1382
1383		var filterRole = objTermsFilter.data("role");
1384
1385		var termID = objLink.data("id");
1386
1387		//set refresh - if all and there are hidden items - refresh
1388		var isRefresh = false;
1389
1390		if(!termID){
1391			var objHiddenItems = objTermsFilter.find(".uc-item-hidden");
1392			if(objHiddenItems.length)
1393				isRefresh = true;
1394		}
1395
1396		var isHideChildren = false;
1397		if(!termID)
1398			isHideChildren = true;
1399		
1400		//set not refresh next iteration, because of the clicked
1401		if(isRefresh == false)
1402			setNoRefreshFilter(objTermsFilter);
1403
1404		if(filterRole == "main")
1405			clearChildFilters(objGrid, objTermsFilter, isHideChildren, termID);
1406
1407		//skip action
1408		
1409		var isSkipAction = checkTriggerSkipAction(objTermsFilter, objGrid);
1410		
1411		if(isSkipAction == true)
1412			return(false);
1413		
1414		
1415		if(g_showDebug == true){
1416			trace("refresh grid - on term click");
1417		}
1418		
1419		//refresh grid
1420		refreshAjaxGrid(objGrid);
1421
1422	}
1423
1424
1425	/**
1426	 * get terms list term id
1427	 */
1428	function getTermsListSelectedTerm(objFilter){
1429
1430		if(!objFilter)
1431			return(null);
1432
1433		var filterType = getFilterType(objFilter);
1434
1435		var objSelected = objFilter.find(".uc-selected");
1436
1437		if(filterType == g_types.SELECT){
1438
1439			var objSelected = objFilter.find("option:selected");
1440
1441		}else{
1442
1443			var objSelected = objFilter.find(".uc-selected");
1444		}
1445
1446		if(objSelected.length == 0){
1447
1448			if(g_showDebug == true){
1449				trace("no selected found, skipping...");
1450			}
1451
1452			return(null);
1453		}
1454
1455		//check for hidden
1456
1457		if(filterType == g_types.TERMS_LIST && objSelected.hasClass("uc-item-hidden") == true){
1458
1459			if(g_showDebug == true){
1460
1461				trace("the selected object");
1462				trace(objSelected);
1463				trace("the term is hidden, skipping...");
1464
1465			}
1466
1467			return(null);
1468		}
1469
1470		if(objSelected.length > 1)
1471			objSelected = jQuery(objSelected[0]);
1472
1473		var objTerm = getFilterElementData(objSelected);
1474
1475		return(objTerm);
1476	}
1477
1478	/**
1479	 * select items in terms list by terms
1480	 */
1481	function termListSelectItems(objFilter, arrTerms){
1482
1483		//deselect
1484		var objSelected = objFilter.find(".uc-selected");
1485
1486		objSelected.removeClass("uc-selected");
1487
1488		//select by term
1489
1490		jQuery.each(arrTerms, function(index, term){
1491
1492			var termID = getVal(term,"id");
1493			var objItem = objFilter.find("a.ue_taxonomy_item[data-id='"+termID+"']");
1494
1495			if(objItem.length == 0)
1496				return(true);
1497
1498			objItem.addClass("uc-selected");
1499		});
1500
1501
1502	}
1503
1504	function ________GENERAL_FILTER_______________(){}
1505
1506	/**
1507	 * init general filter
1508	 */
1509	function initGeneralFilter(objFilter){
1510		
1511		objFilter.on(g_vars.ACTION_FILTER_CHANGE, onGeneralFilterChange);
1512
1513	}
1514
1515
1516
1517	/**
1518	 * on general filter change
1519	 */
1520	function onGeneralFilterChange(event, params){
1521			
1522		event.stopPropagation();
1523
1524		var isRefresh = getVal(params, "refresh");
1525
1526		var objFilter = jQuery(this);
1527		
1528		var filterType = objFilter.data("filtertype");
1529
1530		if(filterType != "general"){
1531			
1532			trace(objFilter);
1533
1534			throw new Error("Not a general filter on action: " + g_vars.ACTION_FILTER_CHANGE);
1535			return(false);
1536		}
1537				
1538		if(isRefresh !== true)
1539			setNoRefreshFilter(objFilter);
1540
1541		var objGrid = objFilter.data("grid");
1542
1543		if(!objGrid || objGrid.length == 0){
1544
1545			trace(objGrid);
1546
1547			throw new Error("Wrong filter change");
1548			return(false);
1549		}
1550		
1551		var filterRole = objFilter.data("role");
1552		
1553		if(filterRole == "main"){
1554			
1555			var isHideChildren = false;
1556			
1557			//if no items selected - hide all children			
1558			var objData = getGeneralFilterData(objFilter);
1559			if(!objData)
1560				isHideChildren = true;
1561			
1562			clearChildFilters(objGrid, objFilter, isHideChildren);
1563		}
1564		
1565		//check for skip action
1566
1567		var isSkipAction = checkTriggerSkipAction(objFilter, objGrid);
1568		
1569		if(isSkipAction == true)
1570			return(false);
1571
1572
1573		if(g_showDebug == true){
1574
1575			trace("refresh grid - on general filter change");
1576			trace(objFilter);
1577
1578		}
1579		
1580		refreshAjaxGrid(objGrid);
1581
1582		return(false);
1583	}
1584
1585
1586	/**
1587	 * select filter items by terms, without refresh, just set selected
1588	 */
1589	function selectFilterItemsByTerms(objFilters, arrTerms){
1590
1591		if(!objFilters || objFilters.length == 0)
1592			return(false);
1593
1594		if(!arrTerms || arrTerms.length == 0)
1595			return(false);
1596		
1597		jQuery.each(objFilters,function(index, filter){
1598
1599			var objFilter = jQuery(filter);
1600
1601			selectFilterItems(objFilter, arrTerms);
1602
1603		});
1604
1605	}
1606
1607	/**
1608	 * select filter items
1609	 */
1610	function selectFilterItems(objFilter, arrTerms){
1611
1612		var type = getFilterType(objFilter);
1613
1614		switch(type){
1615			//case g_types.SELECT:
1616			case g_types.TERMS_LIST:
1617
1618				termListSelectItems(objFilter, arrTerms);
1619
1620			break;
1621			case g_types.GENERAL:
1622
1623				objFilter.trigger("uc_select_items", arrTerms);
1624
1625			break;
1626		}
1627
1628	}
1629
1630	/**
1631	 * get filter data
1632	 */
1633	function getGeneralFilterData(objFilter){
1634		
1635		var filterDataObj = {};
1636		objFilter.trigger(g_vars.EVENT_GET_FILTER_DATA, filterDataObj);
1637		
1638		var filterData = getVal(filterDataObj, "output");
1639		
1640		return(filterData);
1641	}
1642
1643
1644	function ________INIT_FILTERS_______________(){}
1645
1646	/**
1647	 * init terms related filer (terms list and select)
1648	 */
1649	function initTermsRelatedFilter(objFilter){
1650		
1651		objFilter.on(g_vars.ACTION_FILTER_UNSELECT_BY_KEY, termsFilterUnselectByKey);
1652
1653	}
1654
1655
1656	/**
1657	 * get filter taxonomy id's
1658	 */
1659	function getFilterTaxIDs(objFilter, objIDs){
1660
1661		var type = getFilterType(objFilter);
1662
1663		//skip the if
1664		if(type == g_types.SELECT)
1665			var objItems = objFilter.find(".uc-select-filter__option");
1666		else
1667			var objItems = objFilter.find(".ue_taxonomy_item");
1668
1669		if(objItems.length == 0)
1670			return(objIDs);
1671
1672		jQuery.each(objItems, function(index, item){
1673
1674			var objItem = jQuery(item);
1675			var taxID = objItem.data("id");
1676
1677			if(!taxID)
1678				return(true);
1679
1680			objIDs[taxID] = true;
1681		});
1682
1683
1684		return(objIDs);
1685	}
1686
1687	/**
1688	 * get tax id's list string from assoc object
1689	 */
1690	function getTermDsList(objIDs){
1691
1692		var strIDs = "";
1693		for(var id in objIDs){
1694
1695			if(jQuery.isNumeric(id) == false)
1696				continue;
1697
1698			if(strIDs)
1699				strIDs += ",";
1700
1701			strIDs += id;
1702		}
1703
1704		return(strIDs);
1705	}
1706
1707
1708	function ________DATA_______________(){}
1709
1710
1711	/**
1712	 * handle term, add to taxonomy array
1713	 */
1714	function buildTermsQuery_handleTerm(objTerm, arrTax1){
1715
1716		var taxonomy = objTerm["taxonomy"];
1717		var slug = objTerm["slug"];
1718
1719		var objTax = getVal(arrTax1, taxonomy);
1720		if(!objTax)
1721			objTax = {};
1722
1723		objTax[slug] = true;
1724		arrTax1[taxonomy] = objTax;
1725
1726		return(arrTax1);
1727	}
1728
1729	/**
1730	 * get slugs string
1731	 */
1732	function buildTermsQuery_getStrSlugs(objSlugs, isGroup){
1733		
1734		var isDebug = false;
1735		
1736		if(isDebug == true){
1737			trace("get str slugs");
1738			trace(objSlugs);
1739			trace("is group:" + isGroup);
1740		}
1741		
1742		var strSlugs = "";
1743
1744		var moreThenOne = false;
1745		var isEndSlugFound = false;
1746		var isOrSlugFound = false;
1747		
1748		for (var slug in objSlugs){
1749				
1750			if(slug === "__ucand__"){
1751				isEndSlugFound = true;
1752				continue
1753			}
1754			
1755			if(slug === "__ucor__"){
1756				isOrSlugFound = true;
1757				continue
1758			}
1759
1760			if(strSlugs){
1761				moreThenOne = true;
1762				strSlugs += ".";
1763			}
1764
1765			strSlugs += slug;
1766		}
1767
1768		//add "and"
1769		if(isDebug == true){
1770			trace("more then one: "+moreThenOne);
1771			trace("is end found: "+isEndSlugFound);
1772		}
1773		
1774		var addAnd = (moreThenOne == true && isGroup !== true || isEndSlugFound);
1775		
1776		if(isOrSlugFound === true)
1777			addAnd = false;
1778		
1779		if(addAnd)
1780			strSlugs += ".*";
1781
1782		if(isDebug)
1783			trace("str slugs: "+strSlugs);
1784		
1785		return(strSlugs);
1786	}
1787
1788
1789	/**
1790	 * build terms query
1791	 * ucterms=product_cat~shoes.dress;cat~123.43;
1792	 */
1793	function buildTermsQuery(arrTerms){
1794		
1795		var isDebug = false;
1796
1797		var query = "";
1798
1799		//break by taxonomy
1800
1801		var arrTax = {};
1802		var arrGroupTax = [];
1803
1804		if(isDebug == true){
1805			trace("arr terms");
1806			trace(arrTerms);
1807		}
1808		
1809		jQuery.each(arrTerms, function(index, objTerm){
1810
1811			//group term
1812			if(jQuery.isArray(objTerm) && objTerm.length != 0){
1813				
1814				if(objTerm.length == 1){
1815					arrTax = buildTermsQuery_handleTerm(objTerm[0], arrTax);
1816					return;
1817				}
1818
1819				var arrGroupTaxonomy = {};
1820				
1821				jQuery.each(objTerm, function(index, groupTerm){
1822					
1823					arrGroupTaxonomy = buildTermsQuery_handleTerm(groupTerm, arrGroupTaxonomy);
1824				});
1825
1826				arrGroupTax.push(arrGroupTaxonomy);
1827
1828			}else{	//single term
1829
1830				arrTax = buildTermsQuery_handleTerm(objTerm, arrTax);
1831			}
1832
1833		});
1834		
1835		if(isDebug == true){
1836			trace("first arr tax");
1837			trace(arrTax);
1838		}
1839
1840		//combine the query
1841
1842		if(jQuery.isEmptyObject(arrTax) && jQuery.isEmptyObject(arrGroupTax))
1843			return(null);
1844
1845		if(isDebug == true){
1846			trace("group tax");
1847			trace(arrGroupTax);
1848		}
1849		
1850		//build group slugs, in case that there is a group
1851		
1852		jQuery.each(arrGroupTax, function(index, objGroupTaxonomies){
1853			
1854			jQuery.each(objGroupTaxonomies, function(taxonomy, objSlugs){
1855				
1856			var strSlugs = buildTermsQuery_getStrSlugs(objSlugs, true);
1857			
1858			var strAdd = strSlugs;
1859			if(strSlugs.indexOf(".") !== -1){
1860				strAdd = "|"+strSlugs+"|";	//OR inside the group
1861			}
1862				
1863				var objTax = getVal(arrTax, taxonomy);
1864				if(!objTax)
1865					objTax = {};
1866		
1867				objTax[strAdd] = true;
1868		
1869				arrTax[taxonomy] = objTax;
1870			});
1871		});
1872
1873		
1874		if(isDebug == true){
1875			trace("The result taxonomy after grouping");
1876			trace(arrTax);
1877		}
1878
1879		//add group to tax
1880
1881		jQuery.each(arrTax, function(taxonomy, objSlugs){
1882			
1883			var strSlugs = buildTermsQuery_getStrSlugs(objSlugs);
1884				
1885			var strTax = taxonomy + g_options.urlkey_taxsap + strSlugs;
1886			
1887			if(query)
1888				query += ";";
1889
1890			query += strTax;
1891
1892		});
1893
1894		if(isDebug == true){
1895			trace("query");
1896			trace(query);
1897		}
1898
1899		return(query);
1900	}
1901
1902	/**
1903	 * get selected filter element data
1904	 */
1905	function getFilterElementData(objElement){
1906				
1907		var id = objElement.data("id");
1908		var title = objElement.data("title");
1909		var key = objElement.data("key");
1910		var type = objElement.data("type");
1911		
1912		if(!id && !key)
1913			return(null);
1914		
1915		
1916		switch(type){
1917		case "taxonomy":
1918		default:
1919			var slug = objElement.data("slug");
1920			var taxonomy = objElement.data("taxonomy");
1921			
1922			var objTerm = {
1923				"type": type,
1924				"id": id,
1925				"slug": slug,
1926				"taxonomy": taxonomy,
1927				"title": title,
1928				"key": key
1929			};
1930			return(objTerm);
1931			
1932		break;
1933		case "author":
1934			
1935			var username = objElement.data("username");
1936			
1937			var objAuthor = {
1938					"type": type,
1939					"id": id,
1940					"username": username,
1941					"title": title,
1942					"key": key
1943				};
1944				return(objAuthor);
1945			
1946		break;
1947		}
1948		
1949	}
1950
1951
1952	function ________AJAX_CACHE_________(){}
1953
1954	/**
1955	 * get ajax url
1956	 */
1957	function getAjaxCacheKeyFromUrl(ajaxUrl){
1958
1959		var key = ajaxUrl;
1960
1961		key = key.replace(g_urlAjax, "");
1962		key = key.replace(g_urlBase, "");
1963
1964		//replace special signs
1965		key = replaceAll(key, "/","");
1966		key = replaceAll(key, "?","_");
1967		key = replaceAll(key, "&","_");
1968		key = replaceAll(key, "=","_");
1969
1970		return(key);
1971	}
1972
1973	/**
1974	 * get ajax cache key
1975	 */
1976	function getAjaxCacheKey(ajaxUrl, action, objData){
1977
1978	    if(g_options.is_cache_enabled == false)
1979	    	return(false);
1980
1981	    //cache only by url meanwhile
1982
1983	    if(jQuery.isEmptyObject(objData) == false)
1984	    	return(false);
1985
1986	    if(action)
1987	    	return(false);
1988
1989	    var cacheKey = getAjaxCacheKeyFromUrl(ajaxUrl);
1990
1991	    if(!cacheKey)
1992	    	return(false);
1993
1994	    return(cacheKey);
1995	}
1996
1997
1998	/**
1999	 * cache ajax response
2000	 */
2001	function cacheAjaxResponse(ajaxUrl, action, objData, response){
2002
2003	    var cacheKey = getAjaxCacheKey(ajaxUrl, action, objData);
2004
2005	    if(!cacheKey)
2006	    	return(false);
2007
2008	    //some precoutions for overload
2009	    if(g_cache.length > 100)
2010	    	return(false);
2011
2012	    g_cache[cacheKey] = response;
2013
2014	}
2015
2016
2017	function ________AJAX_RESPONSE_______________(){}
2018
2019	/**
2020	 * replace the grid debug
2021	 */
2022	function operateAjax_setHtmlDebug(response, objGrid){
2023
2024		//replace the debug
2025		var htmlDebug = getVal(response, "html_debug");
2026
2027		if(!htmlDebug)
2028			return(false);
2029		
2030		var gridParent = objGrid.parents("." + g_vars.class_widget_wrapper);
2031		
2032		var objDebug = gridParent.find(".uc-debug-query-wrapper");
2033
2034		if(objDebug.length == 0)
2035			return(false);
2036
2037		objDebug.replaceWith(htmlDebug);
2038	}
2039
2040
2041	/**
2042	 * set html grid from ajax response
2043	 */
2044	function operateAjax_setHtmlGrid(response, objGrid, isLoadMore){
2045		
2046		if(g_showDebug == true){
2047			trace("set html grid, response: ");
2048			trace(response);
2049
2050			trace("obj grid:");
2051			trace(objGrid);
2052		}
2053
2054		if(objGrid.length == 0)
2055			return(false);
2056		
2057		//skip set html if exists
2058		if(objGrid.data(g_vars.GRID_DATA_SKIP_HTML) === true){
2059			
2060			if(g_showDebug == true)
2061				trace("skip set html");
2062			
2063			objGrid.data(g_vars.GRID_DATA_SKIP_HTML,false);
2064			return(false);
2065		}
2066		
2067		var objItemsWrapper = getGridItemsWrapper(objGrid);
2068		var objItemsWrapper2 = getGridItemsWrapper(objGrid, true);
2069
2070		if(g_showDebug == true){
2071			trace("items wrapper 1: ");
2072			trace(objItemsWrapper);
2073
2074			trace("items wrapper 2:");
2075			trace(objItemsWrapper2);
2076		}
2077
2078
2079		if(!objItemsWrapper || objItemsWrapper.length == 0)
2080			throw new Error("Missing items wrapper: .uc-items-wrapper");
2081
2082		operateAjax_setHtmlDebug(response, objGrid);
2083
2084		//set grid items
2085
2086		//if init filters mode, and no items response - don't set
2087		if(response.hasOwnProperty("html_items") == false)
2088			return(false);
2089		
2090		var htmlItems = getVal(response, "html_items");
2091				
2092		var htmlItems2 = null;
2093
2094		if(objItemsWrapper2)
2095			htmlItems2 = getVal(response, "html_items2");
2096
2097		//replace widget id
2098		var gridID = objGrid.attr("id");
2099
2100		htmlItems = replaceAll(htmlItems, "%uc_widget_id%", gridID);
2101		
2102		if(htmlItems2)
2103			htmlItems2 = replaceAll(htmlItems2, "%uc_widget_id%", gridID);
2104
2105		var isCustomRefresh = objGrid.data("custom-sethtml");
2106
2107		//show / hide empty message if available and empty response
2108		var objEmptyMessage = getGridEmptyMessage(objGrid);
2109
2110		if(objEmptyMessage){
2111			if(htmlItems == "")
2112				objEmptyMessage.show();
2113			else
2114				objEmptyMessage.hide();
2115		}
2116
2117		//set the query data
2118		var queryDataOriginal = getVal(response, "query_data");
2119		var queryIDs = getVal(response,"query_ids");
2120
2121		var queryData = jQuery.extend({}, queryDataOriginal);
2122
2123		//add to old data
2124
2125		if(isLoadMore == true){
2126
2127			var currentQueryData = objGrid.attr("querydata");
2128
2129			var objCurrentData = jQuery.parseJSON(currentQueryData);
2130			var currentNumPosts = getVal(objCurrentData, "count_posts");
2131
2132			queryData.count_posts += currentNumPosts;
2133
2134			var currentQueryIDs = objGrid.data("postids");
2135
2136			if(queryIDs && currentQueryIDs)
2137				queryIDs = currentQueryIDs + "," + queryIDs;
2138		}
2139
2140		//query data replace
2141
2142		if(queryData){
2143
2144			objGrid.removeAttr("querydata");
2145
2146			var jsonData = JSON.stringify(queryData);
2147			objGrid.attr("querydata", jsonData);
2148
2149			objGrid.data("querydata", queryData);
2150		}
2151
2152		//post id's replace
2153
2154		objGrid.removeAttr("data-postids");
2155		objGrid.attr("data-postids", queryIDs);
2156		objGrid.data("postids", queryIDs);
2157
2158
2159		//if custom refresh - just save the new html in data
2160		if(isCustomRefresh == true){
2161
2162			objGrid.trigger(g_vars.EVENT_SET_HTML_ITEMS,[htmlItems, isLoadMore, htmlItems2]);
2163			return(false);
2164		}
2165
2166
2167		if(!htmlItems2)
2168			htmlItems2 = "";
2169
2170		if(isLoadMore === true){
2171
2172			if(g_showDebug == true){
2173				trace("append load more");
2174			}
2175
2176			objItemsWrapper.append(htmlItems);
2177
2178			if(objItemsWrapper)
2179				objItemsWrapper.append(htmlItems2);
2180
2181		}else{
2182						
2183			objItemsWrapper.html(htmlItems);
2184
2185			if(objItemsWrapper2 && objItemsWrapper2.length)
2186				objItemsWrapper2.html(htmlItems2);
2187
2188		}
2189		
2190		
2191		return(true);
2192	}
2193
2194
2195	/**
2196	 * refresh synced grids
2197	 */
2198	function operateAjax_setHtmlSyngGrids(response, objGrid, isLoadMore){
2199		
2200		var objSyncWidgetsResponse = getVal(response, "html_sync_widgets");
2201
2202		if(g_showDebug == true){
2203			trace("set html sync grids");
2204			trace(objSyncWidgetsResponse);
2205		}
2206
2207		var queryData = getVal(response,"query_data");
2208
2209		if(!objSyncWidgetsResponse){
2210			
2211			if(g_showDebug == true){
2212				trace("no sync widgets response");
2213			}
2214			
2215			return(false);
2216		}
2217		
2218		var group = objGrid.data("filtergroup");
2219		
2220		jQuery.each(objSyncWidgetsResponse, function(elementID, childResponse){
2221			
2222			var objGridWidget = getGridFromElementorElementID(elementID, group);
2223			
2224			if(!objGridWidget){
2225				
2226				if(g_showDebug == true){
2227					trace("no grid widget found: "+elementID);
2228					
2229					getGridFromElementorElementID(elementID,group,true);	//for debug
2230				}
2231				
2232				return(true);
2233			}
2234
2235			if(g_showDebug == true){
2236				trace("set sync grid!");
2237				trace(objGridWidget);
2238				trace(childResponse);
2239			}
2240			
2241			
2242			objGridWidget.removeClass(g_vars.CLASS_REFRESH_SOON);
2243			
2244			childResponse.query_data = queryData;
2245			
2246			operateAjax_setHtmlGrid(childResponse, objGridWidget, isLoadMore);
2247			
2248			objGridWidget.trigger(g_vars.EVENT_AJAX_REFRESHED);
2249			g_objBody.trigger(g_vars.EVENT_AJAX_REFRESHED_BODY, [objGridWidget]);
2250
2251		});
2252
2253	}
2254
2255
2256	/**
2257	 * replace filters html
2258	 */
2259	function operateAjax_setHtmlWidgets(response, objFilters){
2260
2261		if(!objFilters)
2262			return(false);
2263
2264		if(objFilters.length == 0)
2265			return(false);
2266
2267		var objHtmlWidgets = getVal(response, "html_widgets");
2268
2269		if(!objHtmlWidgets)
2270			return(false);
2271
2272		if(objHtmlWidgets.length == 0)
2273			return(false);
2274
2275		var objHtmlDebug = getVal(response, "html_widgets_debug");
2276
2277		jQuery.each(objFilters, function(index, objFilter){
2278
2279			var widgetID = getElementWidgetID(objFilter);
2280
2281			if(!widgetID)
2282				return(true);
2283
2284			var html = getVal(objHtmlWidgets, widgetID);
2285
2286			if(!html)
2287				return(true);
2288
2289			var objHtml = jQuery(html);
2290
2291			var htmlInner = objHtml.html();
2292
2293			//set the class
2294
2295			var filterClassName = objHtml.attr("class");
2296
2297			filterClassName += " "+g_vars.CLASS_FILTER_INITED;
2298
2299			objFilter.attr("class", filterClassName);
2300
2301			objFilter.removeClass(g_vars.CLASS_INITING);
2302			objFilter.removeClass(g_vars.CLASS_REFRESH_SOON);
2303
2304			objFilter.html(htmlInner);
2305
2306
2307
2308			//---- put the debug if exists
2309
2310			var htmlDebug = null;
2311
2312			if(objHtmlDebug)
2313				var htmlDebug = getVal(objHtmlDebug, widgetID);
2314
2315			if(htmlDebug){
2316				var objParent = objFilter.parents("." + g_vars.class_widget_wrapper);
2317				var objDebug = objParent.find(".uc-div-ajax-debug");
2318
2319				if(objDebug.length)
2320					objDebug.replaceWith(htmlDebug);
2321			}
2322			
2323			objFilter.trigger(g_vars.EVENT_FILTER_RELOADED);
2324
2325		});
2326
2327	}
2328
2329	/**
2330	 * scroll to grid top
2331	 */
2332	function scrollToGridTop(objGrid){
2333
2334		var gapTop = 150;
2335
2336		var gridOffset = objGrid.offset().top;
2337
2338		var gridTop = gridOffset - gapTop;
2339
2340		if(gridTop < 0)
2341			gridTop = 0;
2342
2343		//check if the grid top is visible
2344
2345		var currentPos = jQuery(window).scrollTop();
2346
2347		if(currentPos <= gridOffset)
2348			return(false);
2349
2350		window.scrollTo({ top: gridTop, behavior: 'smooth' });
2351
2352	}
2353
2354
2355	/**
2356	 * operate the response
2357	 */
2358	function operateAjaxRefreshResponse(response, objGrid, objFilters, isLoadMore, isNoScroll){
2359		
2360		var isGridRefreshed = operateAjax_setHtmlGrid(response, objGrid, isLoadMore);
2361		
2362		operateAjax_setHtmlWidgets(response, objFilters);
2363		
2364		operateAjax_setHtmlSyngGrids(response, objGrid, isLoadMore);
2365		
2366		objGrid.trigger(g_vars.EVENT_AJAX_REFRESHED,[{isLoadMore:isLoadMore}]);
2367		g_objBody.trigger(g_vars.EVENT_AJAX_REFRESHED_BODY, [objGrid]);
2368		
2369		//trigger body as well
2370
2371		//scroll to grid top
2372		if(isLoadMore == false && isGridRefreshed == true && isNoScroll !== true){
2373						
2374			setTimeout(function(){
2375				
2376				scrollToGridTop(objGrid);
2377					
2378			},200);
2379
2380		}
2381
2382	}
2383
2384
2385	/**
2386	 * replace all occurances
2387	 */
2388	function replaceAll(text, from, to){
2389
2390		return text.split(from).join(to);
2391	};
2392
2393
2394
2395
2396	/**
2397	 * get response from ajax cache
2398	 */
2399	function getResponseFromAjaxCache(ajaxUrl, action, objData){
2400
2401	    var cacheKey = getAjaxCacheKey(ajaxUrl, action, objData);
2402
2403	    if(!cacheKey)
2404	    	return(false);
2405
2406	    var response = getVal(g_cache, cacheKey);
2407
2408	    return(response);
2409	}
2410
2411
2412	function ________AJAX_______________(){}
2413
2414	/**
2415	 * set this filter not to refresh next time
2416	 */
2417	function setNoRefreshFilter(objFilter){
2418
2419		objFilter.data("uc_norefresh",true);
2420
2421	}
2422
2423	/**
2424	 * show ajax error, should be something visible
2425	 */
2426	function showAjaxError(message){
2427
2428		alert(message);
2429
2430	}
2431
2432	/**
2433	 * get the debug object
2434	 */
2435	function getDebugObject(){
2436
2437		var objGrid = g_lastGridAjaxCall;
2438
2439		if(!objGrid)
2440			return(null);
2441
2442		var objDebug = objGrid.find("."+g_vars.CLASS_DIV_DEBUG);
2443
2444		if(objDebug.length)
2445			return(objDebug);
2446
2447		//insert if not exists
2448
2449		objGrid.after("<div class='"+g_vars.CLASS_DIV_DEBUG+"' style='padding:10px;display:none;background-color:#D8FCC6'></div>");
2450
2451		var objDebug = jQuery("body").find("."+g_vars.CLASS_DIV_DEBUG);
2452
2453		return(objDebug);
2454	}
2455
2456
2457	/**
2458	 * show ajax debug
2459	 */
2460	function showAjaxDebug(str){
2461
2462		trace("Ajax Error! - Check the debug");
2463
2464		str = jQuery.trim(str);
2465
2466		if(!str || str.length == 0)
2467			return(false);
2468
2469		var objStr = jQuery(str);
2470
2471		if(objStr.find("header").length || objStr.find("body").length){
2472			str = "Wrong ajax response!";
2473		}
2474
2475		var objDebug = getDebugObject();
2476
2477		if(!objDebug || objDebug.length == 0){
2478
2479			alert(str);
2480
2481			throw new Error("debug not found");
2482		}
2483
2484		objDebug.show();
2485		objDebug.html(str);
2486
2487	}
2488
2489
2490	/**
2491	 * small ajax request
2492	 */
2493	function ajaxRequest(ajaxUrl, action, objData, onSuccess){
2494				
2495		if(g_debugInitMode === true){
2496
2497			trace("debug init mode - skip request");
2498			return(false);
2499		}
2500
2501		if(g_showDebug == true){
2502			trace("ajax request");
2503			trace(ajaxUrl);
2504		}
2505
2506		if(!objData)
2507			var objData = {};
2508
2509		if(typeof objData != "object")
2510			throw new Error("wrong ajax param");
2511
2512		//check response from cache
2513		var responseFromCache = getResponseFromAjaxCache(ajaxUrl, action, objData);
2514
2515		if(responseFromCache){
2516
2517			//simulate ajax request
2518			setTimeout(function(){
2519				onSuccess(responseFromCache);
2520			}, 300);
2521
2522			return(false);
2523		}
2524
2525		var ajaxData = {};
2526		ajaxData["action"] = "unlimitedelements_ajax_action";
2527		ajaxData["client_action"] = action;
2528
2529		var ajaxtype = "get";
2530
2531		if(jQuery.isEmptyObject(objData) == false){
2532			ajaxData["data"] = objData;
2533			ajaxtype = "post";
2534		}
2535
2536
2537		var ajaxOptions = {
2538				type:ajaxtype,
2539				url:ajaxUrl,
2540				success:function(response){
2541
2542					if(!response){
2543						showAjaxError("Empty ajax response!");
2544						return(false);
2545					}
2546
2547					if(typeof response != "object"){
2548
2549						try{
2550
2551							response = jQuery.parseJSON(response);
2552
2553						}catch(e){
2554
2555							showAjaxDebug(response);
2556
2557							showAjaxError("Ajax Error!!! not ajax response");
2558							return(false);
2559						}
2560					}
2561
2562					if(response == -1){
2563						showAjaxError("ajax error!!!");
2564						return(false);
2565					}
2566
2567					if(response == 0){
2568						showAjaxError("ajax error, action: <b>"+action+"</b> not found");
2569						return(false);
2570					}
2571
2572					if(response.success == undefined){
2573						showAjaxError("The 'success' param is a must!");
2574						return(false);
2575					}
2576
2577
2578					if(response.success == false){
2579						showAjaxError(response.message);
2580						return(false);
2581					}
2582
2583					cacheAjaxResponse(ajaxUrl, action, objData, response);
2584
2585					if(typeof onSuccess == "function"){
2586
2587						onSuccess(response);
2588					}
2589
2590				},
2591				error:function(jqXHR, textStatus, errorThrown){
2592
2593					switch(textStatus){
2594						case "parsererror":
2595						case "error":
2596
2597							//showAjaxError("parse error");
2598
2599							showAjaxDebug(jqXHR.responseText);
2600
2601						break;
2602					}
2603				}
2604		}
2605
2606		if(ajaxtype == "post"){
2607			ajaxOptions.dataType = 'json';
2608			ajaxOptions.data = ajaxData
2609		}
2610
2611		var handle = jQuery.ajax(ajaxOptions);
2612
2613		return(handle);
2614	}
2615
2616
2617
2618	/**
2619	 * get grid items wrapper
2620	 */
2621	function getGridItemsWrapper(objGrid, isSecond){
2622
2623		var classItems = "uc-items-wrapper";
2624
2625		if(isSecond == true)
2626			classItems = "uc-items-wrapper2";
2627
2628		if(objGrid.hasClass(classItems))
2629			return(objGrid);
2630
2631		var objItemsWrapper = objGrid.find("."+classItems);
2632
2633		if(objItemsWrapper.length == 0 && isSecond == false)
2634			throw new Error("Missing items wrapper - with class: uc-items-wrapper");
2635
2636		if(objItemsWrapper.length == 0)
2637			return(null);
2638
2639		return(objItemsWrapper);
2640	}
2641
2642
2643	/**
2644	 * set ajax loader
2645	 */
2646	function showAjaxLoader(objElement){
2647
2648		objElement.addClass("uc-ajax-loading");
2649	}
2650
2651	/**
2652	 * hide ajax loader
2653	 */
2654	function hideAjaxLoader(objElement){
2655
2656		objElement.removeClass("uc-ajax-loading");
2657	}
2658
2659
2660	/**
2661	 * show multiple ajax loader
2662	 */
2663	function showMultipleAjaxLoaders(objElements, isShow){
2664
2665		if(!objElements)
2666			return(false);
2667
2668		if(objElements.length == 0)
2669			return(false);
2670
2671		jQuery.each(objElements,function(index, objElement){
2672
2673			objElement = jQuery(objElement);
2674
2675			if(isShow == true){
2676
2677				showAjaxLoader(objElement);
2678			}
2679			else
2680				hideAjaxLoader(objElement);
2681		});
2682
2683	}
2684
2685
2686	/**
2687	 * refresh ajax grid
2688	 */
2689	function refreshAjaxGrid(objGrid, refreshType){
2690				
2691		var isLoadMore = (refreshType == g_vars.REFRESH_MODE_LOADMORE);	 //for the output
2692		var isFiltersInit = (refreshType == "filters" || refreshType == "filters_children");
2693		
2694		//for the options - not refresh other filters
2695		var isLoadMoreMode = (refreshType == g_vars.REFRESH_MODE_LOADMORE || refreshType == g_vars.REFRESH_MODE_PAGINATION);
2696		
2697		//get all grid filters
2698		var objFilters = objGrid.data("filters");
2699
2700		if(!objFilters)
2701			return(false);
2702
2703		if(objFilters.length == 0)
2704			return(false);
2705
2706		if(objGrid.hasClass(g_vars.CLASS_GRID_NOREFRESH))
2707			return(false);
2708
2709		var params = {};
2710		if(refreshType == "filters_children")
2711			params["filters_init_type"] = "children";
2712		
2713		params["refresh_type"] = refreshType;
2714		
2715		var objAjaxOptions = getGridAjaxOptions(objFilters, objGrid, isFiltersInit, isLoadMoreMode, params);
2716		
2717		if(!objAjaxOptions){
2718
2719			trace("ajax options are null");
2720			return(false);
2721		}
2722
2723		var ajaxUrl = objAjaxOptions["ajax_url"];
2724		var urlReplace = objAjaxOptions["url_replace"];
2725		var arrTerms = objAjaxOptions["terms"];
2726
2727		if(g_vars.DEBUG_AJAX_OPTIONS == true){
2728
2729			trace("DEBUG AJAX OPTIONS");
2730			trace(objAjaxOptions);
2731			return(false);
2732		}
2733
2734		//set the url params
2735		var behave = objGrid.data("filterbehave");
2736
2737		var isSetUrl = (behave == "mixed" || behave == "mixed_back");
2738
2739		if(isFiltersInit == false && isSetUrl === true){
2740			
2741			try{
2742				
2743				if(behave == "mixed_back"){
2744	
2745					//save state for back button
2746	
2747					var gridID = objGrid.attr("id");
2748	
2749					//save initial state
2750					var isStateEmpty = jQuery.isEmptyObject(history.state);
2751					
2752					var objState = {"ucaction":"change", "ajaxurl":ajaxUrl, "gridid":gridID, selected_terms:arrTerms};
2753	
2754					if(isStateEmpty){
2755	
2756						var ajaxUrlInitial = objGrid.data("initajaxurl");
2757	
2758						objState["ajaxurl"] = ajaxUrlInitial;
2759	
2760						history.replaceState(objState, null, urlReplace);
2761					}
2762	
2763					history.pushState(objState, null, urlReplace);		//with back
2764	
2765				}
2766				else
2767					history.replaceState({}, null, urlReplace);		//without back
2768			
2769			}catch(error){
2770				trace("history push state error");
2771				trace(error);
2772			}
2773		}
2774		
2775		
2776		initGrid_setActiveFiltersData(objGrid, objAjaxOptions);
2777		
2778		doGridAjaxRequest(ajaxUrl, objGrid, objFilters, isLoadMore, isFiltersInit);
2779
2780	}
2781
2782
2783	/**
2784	 * do the actual grid ajax request
2785	 */
2786	function doGridAjaxRequest(ajaxUrl, objGrid, objFilters, isLoadMore, isFiltersInit){
2787		
2788		var objEmptyMessage = getGridEmptyMessage(objGrid);
2789
2790		//set the loaders
2791
2792		if(isLoadMore !== true && isFiltersInit !== true){
2793
2794			showAjaxLoader(objGrid);
2795
2796			if(objEmptyMessage)
2797				showAjaxLoader(objEmptyMessage);
2798		}
2799
2800		var objFiltersToReload = objFilters.filter(function(objFilter){
2801
2802			return objFilter.hasClass(g_vars.CLASS_REFRESH_SOON);
2803		});
2804
2805		showMultipleAjaxLoaders(objFiltersToReload, true);
2806
2807		if(g_lastSyncGrids && isLoadMore !== true){
2808
2809			showMultipleAjaxLoaders(g_lastSyncGrids, true);
2810		}
2811
2812		//ajax reload
2813		g_lastGridAjaxCall = objGrid;
2814		
2815		objGrid.trigger(g_vars.EVENT_BEFORE_REFRESH);
2816		
2817		var lastAjaxHandle = objGrid.data("last_ajax_refresh_handle");
2818
2819		if(lastAjaxHandle){
2820			lastAjaxHandle.abort();
2821		}
2822		
2823		//--- debug before refresh
2824		
2825		if(g_debugBeforeRefreshMode == true){
2826			
2827			alert("Debug before refresh - please turn if off");
2828			return(false);
2829		}
2830		
2831		var ajaxHandle = ajaxRequest(ajaxUrl,null,null, function(response){
2832
2833			if(isLoadMore !== true){
2834				hideAjaxLoader(objGrid);
2835
2836				if(objEmptyMessage)
2837					hideAjaxLoader(objEmptyMessage);
2838			}
2839
2840			showMultipleAjaxLoaders(objFilters, false);
2841
2842			if(g_lastSyncGrids)
2843				showMultipleAjaxLoaders(g_lastSyncGrids, false);
2844			
2845			operateAjaxRefreshResponse(response, objGrid, objFilters, isLoadMore);
2846
2847			onAfterGridRefresh(objGrid);
2848
2849		});
2850
2851		objGrid.data("last_ajax_refresh_handle", ajaxHandle);
2852
2853	}
2854
2855	/**
2856	 * do some actions after grid refresh, if needed
2857	 */
2858	function onAfterGridRefresh(objGrid){
2859
2860		//refresh child grids
2861
2862		var isInitRefesh = objGrid.data("init_refresh_child_filters");
2863
2864		if(isInitRefesh === true){
2865
2866			objGrid.removeData("init_refresh_child_filters");
2867
2868			//refresh child filters if there are selected main after init
2869
2870			var objFilters = objGrid.data("filters");
2871
2872			var arrSelectedMain = getSelectedFilters(objFilters, "main");
2873
2874			if(arrSelectedMain.length)
2875				refreshAjaxGrid(objGrid, "filters_children");
2876		}
2877
2878	}
2879
2880
2881	function ________STATE_RELATED_______________(){}
2882
2883
2884	/**
2885	 * do history
2886	 */
2887	function changeToHistoryState(state){
2888
2889		if(g_showDebug == true){
2890			trace("change to history");
2891			trace(state);
2892		}
2893
2894		var ajaxUrl = getVal(state, "ajaxurl");
2895
2896		var gridID = getVal(state, "gridid");
2897
2898		var arrTerms = getVal(state, "selected_terms");
2899
2900		if(!gridID)
2901			return(false);
2902
2903		if(!ajaxUrl)
2904			return(false);
2905
2906		var objGrid = jQuery("#"+gridID);
2907
2908		var objFilters = objGrid.data("filters");
2909
2910		if(!objFilters)
2911			return(false);
2912
2913		//select by terms
2914
2915		selectFilterItemsByTerms(objFilters, arrTerms);
2916
2917		var responseFromCache = getResponseFromAjaxCache(ajaxUrl);
2918
2919		if(!responseFromCache){
2920
2921			//do ajax request
2922
2923			doGridAjaxRequest(ajaxUrl, objGrid, objFilters);
2924
2925			return(false);
2926		}
2927
2928		//get data from cache
2929
2930		//trace("restore");
2931		//trace(responseFromCache);
2932
2933		operateAjaxRefreshResponse(responseFromCache, objGrid, objFilters, false, true);
2934
2935	}
2936
2937	/**
2938	 * on pop state, if it's a grid state, set the grid
2939	 */
2940	function onPopState(){
2941
2942		if(!history.state)
2943			return(true);
2944
2945		var action = getVal(history.state, "ucaction");
2946
2947		if(!action)
2948			return(true);
2949
2950		switch(action){
2951			case "change":
2952
2953				changeToHistoryState(history.state);
2954
2955			break;
2956			default:
2957				throw new Error("Wrong history action: " + action);
2958			break;
2959		}
2960
2961	}
2962
2963
2964	function ________RUN_______________(){}
2965
2966
2967	/**
2968	 * get url filters string
2969	 */
2970	function getGridUrlFiltersString(objGrid){
2971
2972		var objAjaxOptions = getGridAjaxOptions_simple(objGrid);
2973
2974		if(!objAjaxOptions)
2975			return("");
2976
2977		var strFilters = getVal(objAjaxOptions, "filters_string");
2978		
2979		return(strFilters);
2980	}
2981
2982
2983	/**
2984	 * get simply the grid ajax options
2985	 */
2986	function getGridAjaxOptions_simple(objGrid){
2987
2988		var objFilters = objGrid.data("filters");
2989		
2990		if(!objFilters)
2991			return(null);
2992		
2993		var objAjaxOptions = getGridAjaxOptions(objFilters, objGrid, false,false,{getonly:true});
2994
2995		if(!objAjaxOptions)
2996			return(null);
2997
2998		return(objAjaxOptions);
2999	}
3000	
3001	/**
3002	 * check that element is hidden only by display:none. ":hidden" checks width and height as well
3003	 */
3004	function isElementHiddenByDisplayNone(objElement) {
3005	    	    
3006		var element = objElement[0];
3007		
3008		var hidden = window.getComputedStyle(element).display == "none";
3009		
3010	    return hidden;
3011	};	
3012
3013	/**
3014	* get operator term
3015	*/
3016	function getObjOperatorTerm(operator, dataTerms){
3017		var slug = (operator == "and")?"__ucand__":"__ucor__";
3018		var firstTerm = dataTerms[0];        
3019		var objOperatorTerm = {
3020			taxonomy: firstTerm.taxonomy,
3021			slug: slug,
3022			id:null
3023		};
3024		
3025		return(objOperatorTerm);
3026	}
3027
3028	/**
3029	 * get grid ajax options
3030	 */
3031	function getGridAjaxOptions(objFilters, objGrid, isFiltersInitMode, isLoadMoreMode, params){
3032		
3033		if(!isLoadMoreMode)
3034			var isLoadMoreMode = false;
3035		
3036		if(g_showDebug){
3037			trace("getGridAjaxOptions");
3038
3039			trace("Filters:");
3040			trace(objFilters);
3041			
3042			trace("grid:");
3043			trace(objGrid);
3044			trace("is init: " + isFiltersInitMode);
3045
3046			trace("params: ");
3047			trace(params);
3048
3049		}
3050
3051		//filter only visible elements (by it's parents)
3052		
3053		var objVisibleFilters = objFilters.filter(function(objFilter){
3054			
3055			var objParent = getFilterWrapper(objFilter);
3056			
3057			var isHidden = isElementHiddenByDisplayNone(objParent);
3058			
3059			return(!isHidden);
3060		});
3061		
3062		
3063		if(objVisibleFilters.length < objFilters.length){
3064			
3065			if(objVisibleFilters.length == 0){
3066				
3067				if(g_showDebug)
3068					trace("no visible filters");
3069				
3070				var objFilters = [];
3071			}
3072			else{		//test for mobile drawer
3073				
3074				var objFirstFilter = jQuery(objVisibleFilters[0]);
3075				var visibleFilterType = getFilterType(objFirstFilter, true);
3076				
3077				//exception for mobile drawer
3078				if(visibleFilterType !=  g_types.GENERAL_MOBILE_DRAWER){
3079					
3080					var objFilters = objVisibleFilters;
3081					
3082					if(g_showDebug){
3083						trace("Visible Filters: ");
3084						trace(objFilters);
3085					}
3086				}
3087				
3088			}//end else
3089			
3090			
3091		} //end visible filters test
3092		
3093		
3094		if(!objFilters || objFilters.length == 0)
3095			return(null);
3096
3097		var urlReplace = g_urlBase;
3098
3099		var urlAjax = g_urlBase;
3100
3101		var strRefreshIDs = "";
3102
3103		var isReplaceMode = false;
3104		var page = null;
3105		var offset = null;
3106		var numItems = null;
3107		var arrTerms = [];
3108		var objTaxIDs = {};
3109		var objAuthorIDs = {};
3110		var strSelectedTerms = "";
3111		var strSelectedAuthors = "";
3112		var search = "";
3113		var price_from, price_to;
3114		var arrAuthors = [];
3115		var orderby = null;
3116		var orderby_metaname = null;
3117		var orderby_metatype = null;
3118		var orderdir = null;
3119		var title_start = null;
3120		var addSyncedGrids = true;
3121		var arrAllFiltersData;		//all data gethered for the active filters
3122		var arrFiltersForInit = [];
3123		var urlAddFromFilters = "";
3124		var isPaginationClicked = false;
3125		var isGetUrlOnly = getVal(params,"getonly");
3126
3127		var initModeType = getVal(params,"filters_init_type");
3128
3129		var initModeChildrens = false;
3130		if(isFiltersInitMode == true && initModeType == "children")
3131			initModeChildrens = true;
3132
3133		var wasInitMode = objGrid.data("was_init_mode");
3134
3135		var arrFilterIDs = {};
3136		
3137		var advancedSearchFilterID;
3138		
3139		var refreshType = getVal(params,"refresh_type");
3140		
3141		if(refreshType == g_vars.REFRESH_MODE_PAGINATION)
3142			isPaginationClicked = true;
3143
3144		var child_auto, childAutoTaxonomy, childAutoSlug, childAutoString = "";
3145				
3146		//get ajax options
3147		jQuery.each(objFilters, function(index, objFilter){
3148			
3149			//protection against duplicate id's
3150			var id = objFilter.attr("id");
3151
3152			if(arrFilterIDs.hasOwnProperty(id) == true){
3153
3154				trace("problematic filter: ");
3155				trace(objFilter);
3156
3157				trace("original filter found: ");
3158				trace(arrFilterIDs[id]);
3159
3160				trace("filters list: ");
3161				trace(objFilters);
3162
3163				throw new Error("Duplicate Filter ID found: " + id);
3164			}
3165						
3166			arrFilterIDs[id] = objFilter;
3167
3168			var isNoRefresh = objFilter.data("uc_norefresh");
3169			var filterRole = objFilter.data("role");
3170						
3171			var type = getFilterType(objFilter);
3172			
3173			if(g_showDebug == true){
3174
3175				trace("filter: "+type+", role: "+filterRole);
3176				trace(objFilter);
3177			}
3178
3179			var urlAdd = objFilter.attr(g_vars.ATTRIBUTE_URLADD);
3180
3181			if(urlAdd)
3182				urlAddFromFilters = addUrlParam(urlAddFromFilters, urlAdd);
3183			
3184			switch(type){
3185				case g_types.PAGINATION:
3186						
3187						//run pagination only if it's clicked, unless reset pagination
3188						var isClicked = objFilter.hasClass(g_vars.CLASS_CLICKED);
3189						if(isClicked == true || isFiltersInitMode == true){
3190
3191							 var paginationData = getPaginationSelectedData(objFilter);
3192							 
3193							 var paginationPage = getVal(paginationData, "page");
3194							 
3195							 if(paginationPage)
3196								 page = paginationPage;		//never set the url
3197							 
3198							 //set page from url
3199							 if(isFiltersInitMode == true && !page && g_vars.ucpage_url)
3200								 page = g_vars.ucpage_url;
3201							
3202							 if(g_showDebug){
3203								 trace("pagination data");
3204								 trace(paginationData);
3205							 }
3206
3207							objFilter.removeClass(g_vars.CLASS_CLICKED);
3208						}
3209						
3210
3211				break;
3212				case g_types.LOADMORE:
3213
3214					//check if loadmore is before grid in init mode
3215					var isLoadMoreBeforeGrid = false;
3216					if(isFiltersInitMode == true){
3217						var offsetLoadMore = objFilter.offset();
3218						var offsetGrid = objGrid.offset();
3219						
3220						if(offsetLoadMore.top < offsetGrid.top){
3221							isLoadMoreBeforeGrid = true;
3222							
3223							if(g_showDebug == true)
3224								trace("Loadmore before grid - process in init mode");
3225						}
3226					}
3227					
3228					if(isFiltersInitMode == true && isLoadMoreBeforeGrid == false)
3229						return(true);
3230
3231					//run load more only if it's clicked, unless reset load more
3232					var isClicked = objFilter.hasClass(g_vars.CLASS_CLICKED);
3233					if(isClicked == true){
3234
3235						var loadMoreData = getLoadMoreUrlData(objFilter);
3236						offset = loadMoreData.offset;
3237						numItems = loadMoreData.numItems;
3238
3239						var isSingleGrid = loadMoreData.singlegrid;
3240
3241						if(isSingleGrid == true)
3242							addSyncedGrids = false;
3243
3244						if(!offset)
3245							urlAjax = null;
3246
3247						objFilter.removeClass(g_vars.CLASS_CLICKED);
3248					}
3249
3250				break;
3251				case g_types.TERMS_LIST:
3252				case g_types.SELECT:
3253
3254					//if not init mode - take first item
3255					var objTerm = getTermsListSelectedTerm(objFilter);
3256					var filterSource = objFilter.data("filtersource");
3257										
3258					if(objTerm){
3259						
3260						if(isFiltersInitMode == false){
3261							
3262							if(filterSource == "authors")
3263								arrAuthors.push(objTerm);
3264							else
3265								arrTerms.push(objTerm);
3266						}
3267						else{
3268							
3269							//INIT MODE
3270							
3271							//add terms if the filter is not initing itself
3272							var isInit = objFilter.data("initafter");
3273							
3274							//add terms, if only children mode and the filter not child
3275							if(initModeChildrens == true && filterRole != "child")
3276								arrTerms.push(objTerm);
3277							else
3278								if(isInit != true){
3279									
3280									if(filterSource == "authors")
3281										arrAuthors.push(objTerm);
3282									else
3283										arrTerms.push(objTerm);
3284									
3285								}
3286							
3287							//set selected terms string
3288							
3289							var termID = objTerm.id;
3290							
3291							if(filterSource == "authors"){
3292								
3293								if(strSelectedAuthors)
3294									strSelectedAuthors +=",";
3295								
3296								strSelectedAuthors += termID;
3297							}
3298							else{
3299								if(strSelectedTerms)
3300									strSelectedTerms +=",";
3301								
3302								strSelectedTerms += termID;
3303							}
3304							
3305						}
3306					}
3307
3308					//replace mode
3309
3310					var modeReplace = objFilter.data("replace-mode");
3311					if(modeReplace === true)
3312						isReplaceMode = true;
3313
3314					if(isLoadMoreMode == true)
3315						isNoRefresh = true;
3316
3317					//debug
3318					if(g_showDebug == true){
3319
3320						trace("Selected Term: ");
3321						trace(objTerm);
3322					}
3323
3324				break;
3325				case g_types.SUMMARY:
3326
3327					isNoRefresh = true;
3328
3329					//take nothing
3330				break;
3331				case g_types.SEARCH:
3332
3333					isNoRefresh = true;
3334
3335					var objInput = objFilter.find("input");
3336
3337					search = objInput.val();
3338					search = search.trim();
3339					
3340					//add id
3341					var isAdvancedSearch = objFilter.data("advancedsearch");
3342					
3343					if(isAdvancedSearch == true)
3344						advancedSearchFilterID = getElementWidgetID(objFilter);
3345										
3346				break;
3347				case g_types.GENERAL:
3348					
3349					var generalType = objFilter.data("generaltype");
3350				
3351					if(generalType == g_types.GENERAL_MOBILE_DRAWER)
3352						return(true);
3353					
3354					var generalIsNoRefresh = objFilter.data("norefresh");
3355					
3356					if(generalIsNoRefresh === true)
3357						isNoRefresh = true;
3358					
3359					var filterData = getGeneralFilterData(objFilter);
3360					
3361					//add terms
3362					
3363					var dataTerms = getVal(filterData,"terms");
3364					
3365					if(dataTerms && dataTerms.length){	
3366
3367						var isOperatoeAdded = false;
3368
3369						if(filterRole == "main"){
3370							var operator = getVal(filterData,"operator");
3371										
3372							if(operator === "and" || operator === "or"){									
3373								var objOperatorTerm = getObjOperatorTerm(operator, dataTerms);
3374
3375								dataTerms.push(objOperatorTerm);	
3376						    isOperatoeAdded = true;
3377							}
3378						}
3379
3380						if(dataTerms.length == 1){		//single term			
3381						  arrTerms.push(dataTerms[0]);
3382						}
3383						
3384						if(dataTerms.length > 1){	//multiple terms
3385							//push the end or or operator
3386							var operator = getVal(filterData,"operator");
3387									
3388							if(isOperatoeAdded == false){
3389
3390								if(operator === "and" || operator === "or"){								
3391									var objOperatorTerm = getObjOperatorTerm(operator, dataTerms);
3392		
3393									dataTerms.push(objOperatorTerm);
3394								}
3395							}
3396							
3397							arrTerms.push(dataTerms);	//multiple (grouping)
3398						}
3399						
3400						//set selected terms string if init mode
3401						
3402						if(isFiltersInitMode == true && dataTerms && dataTerms.length){
3403							
3404							var arrTermsForSelect = [];
3405							
3406							if(jQuery.isArray(arrTerms))
3407								arrTermsForSelect = arrTerms.flat();
3408							
3409							jQuery.each(arrTermsForSelect, function(index, term){
3410								
3411								var termID = getVal(term,"id");
3412								
3413								if(!termID)
3414									return(true);
3415								
3416								if(strSelectedTerms)
3417									strSelectedTerms +=",";
3418								
3419								strSelectedTerms += termID;
3420							});
3421							
3422						}
3423					}
3424					
3425					//add authors
3426					var dataAuthors = getVal(filterData,"authors");
3427					
3428					if(dataAuthors && dataAuthors.length){
3429						
3430						//gather authors list
3431						jQuery.each(dataAuthors, function(index, author){
3432							arrAuthors.push(author);
3433						});
3434						
3435						//set selected authors string if init mode
3436						
3437						if(isFiltersInitMode == true){
3438							
3439							jQuery.each(dataAuthors, function(index, author){
3440								
3441								var authorID = getVal(author,"id");
3442								
3443								if(!authorID)
3444									return(true);
3445								
3446								if(strSelectedAuthors)
3447									strSelectedAuthors +=",";
3448								
3449								strSelectedAuthors += authorID;
3450							});
3451							
3452						}
3453					}
3454					
3455					
3456					if(g_showDebug == true){
3457						trace("Filter Data:");
3458						trace(filterData);
3459					}
3460					
3461					if(generalType == "price" && isFiltersInitMode == false){
3462						
3463						var priceFromArg = getVal(filterData,"price_from");
3464						var priceToArg = getVal(filterData,"price_to");
3465
3466						if(priceFromArg)
3467							price_from = roundToOneDecimal(priceFromArg);
3468
3469						if(priceToArg)
3470							price_to = roundToOneDecimal(priceToArg);
3471					}
3472					
3473					
3474					//add title start
3475					
3476					var titleStartArg = getVal(filterData, "title_start");
3477					if(titleStartArg)
3478						title_start = titleStartArg;
3479					
3480					//handle sort
3481					var argOrderby = getVal(filterData,"orderby");
3482					if(argOrderby && argOrderby != "default"){
3483						orderby = argOrderby;
3484
3485						orderby_metaname = getVal(filterData,"metaname");
3486						orderby_metatype = getVal(filterData,"metatype");
3487					}
3488
3489					var argOrderDir = getVal(filterData,"orderdir");
3490					if(argOrderDir && argOrderDir != "default")
3491						orderdir = argOrderDir;
3492
3493					if(isLoadMoreMode == true)
3494						isNoRefresh = true;
3495					
3496				break;
3497				default:
3498					throw new Error("Unknown filter type: "+type);
3499				break;
3500			}
3501
3502			
3503			//handle filters init mode
3504			
3505			if(isFiltersInitMode == true){
3506								
3507				var isInit = objFilter.data("initafter");
3508
3509					
3510				if(isInit != true){
3511					isNoRefresh = true;
3512				}
3513
3514				//refresh parents only
3515				if(initModeChildrens == false && filterRole == "child")
3516					isNoRefresh = true;
3517
3518				//refresh children only
3519				if(initModeChildrens == true && filterRole != "child")
3520					isNoRefresh = true;
3521				
3522				if(isNoRefresh == false){
3523					arrFiltersForInit.push(objFilter);					
3524				}
3525								
3526			}
3527			
3528			
3529			//if hidden - no refresh
3530			
3531			var isFilterHidden = objFilter.hasClass(g_vars.CLASS_HIDDEN);
3532			if(isFilterHidden == true)
3533				isNoRefresh = true;
3534			
3535			objFilter.data("uc_norefresh",false);
3536			
3537			var isMainFilter = (filterRole == "main");
3538			var isTermChild = (filterRole == "term_child");
3539			
3540			//add to refresh filter if it's qualify
3541
3542			var isRefresh = true;
3543			
3544			if(isFiltersInitMode == false && (isMainFilter === true || isTermChild == true))
3545				isRefresh = false;
3546
3547			if(isNoRefresh === true)
3548				isRefresh = false;
3549						
3550			if(g_showDebug == true){
3551				trace("Filter Refresh: "+isRefresh);
3552				if(isRefresh == true){
3553					trace("isFiltersInitMode: "+isFiltersInitMode);
3554					trace("isMainFilter: "+isMainFilter);
3555					trace("isTermChild: "+isTermChild);
3556					trace("isNoRefresh: "+isNoRefresh);
3557				}
3558			}
3559			
3560			if(isRefresh == true){
3561
3562				var filterWidgetID = getElementWidgetID(objFilter);
3563
3564				//add test tax id's for init mode
3565				var filterSource = objFilter.data("filtersource");
3566				if(filterSource == "authors" && isFiltersInitMode == true){
3567					//add test author id's for init mode
3568					objAuthorIDs = getFilterTaxIDs(objFilter, objAuthorIDs);
3569				}else{
3570					objTaxIDs = getFilterTaxIDs(objFilter, objTaxIDs);
3571				}
3572
3573				if(strRefreshIDs)
3574					strRefreshIDs += ",";
3575
3576				strRefreshIDs += filterWidgetID;
3577
3578				if(!isGetUrlOnly)
3579					objFilter.addClass(g_vars.CLASS_REFRESH_SOON);
3580			}
3581			
3582			if(filterRole == "main"){
3583				var objTerm = getTermsListSelectedTerm(objFilter);
3584
3585				if(objTerm && objTerm != null){
3586
3587					childAutoTaxonomy = objTerm.taxonomy;
3588					childAutoSlug = objTerm.slug;
3589				}
3590			}
3591			
3592			if(filterRole == "child_auto" && arrTerms.length){
3593				child_auto = true;
3594
3595				if(childAutoTaxonomy && childAutoSlug){
3596					childAutoString = "&ucmainterm=" + childAutoTaxonomy + ":" + childAutoSlug;
3597				}
3598			
3599			}
3600
3601
3602		});		//end filters iteration
3603
3604		
3605		//add init filters additions
3606
3607		var urlAddition_filtersTest = "";
3608		var strTaxIDs = getTermDsList(objTaxIDs);
3609		var strAuthorIDs = getTermDsList(objAuthorIDs);
3610				
3611		if(isFiltersInitMode == true){
3612
3613			if(!strTaxIDs && !strAuthorIDs && arrFiltersForInit.length == 0)
3614				urlAjax = null;
3615			else{
3616
3617				if(urlAddition_filtersTest)
3618					urlAddition_filtersTest += "&";
3619				
3620				urlAddition_filtersTest += "modeinit=true";
3621			}
3622		}
3623
3624		//test terms - only if there are terms in query, or mode init
3625				
3626		if(strTaxIDs && (search || arrTerms.length || isFiltersInitMode == true || wasInitMode === true) ){
3627			 
3628			if(urlAddition_filtersTest)
3629				urlAddition_filtersTest += "&";
3630			
3631			urlAddition_filtersTest += "testtermids="+strTaxIDs;
3632		}
3633		
3634		//test authors - only if there are authors in query, or mode init (author mode)
3635		if(strAuthorIDs && (search || arrAuthors.length || isFiltersInitMode == true || wasInitMode === true) ){
3636			
3637			if(urlAddition_filtersTest)
3638				urlAddition_filtersTest += "&";
3639			
3640			urlAddition_filtersTest += "testauthorids="+strAuthorIDs;
3641		}
3642
3643		g_lastSyncGrids = null;
3644
3645		if(urlAjax == null)
3646			return(null);
3647
3648		var dataLayout = getElementLayoutData(objGrid, addSyncedGrids);
3649
3650		var widgetID = dataLayout["widgetid"];
3651		var layoutID = dataLayout["layoutid"];
3652
3653		//disable synced
3654
3655		if(addSyncedGrids == false){
3656
3657			var syncedWidgetIDs = false;
3658			g_lastSyncGrids = null;
3659
3660		}else{
3661
3662			var syncedWidgetIDs = getVal(dataLayout,"synced_widgetids");
3663			g_lastSyncGrids = getVal(dataLayout,"synced_grids");
3664		}
3665		
3666		var urlFilterString = "";
3667		
3668		var urlAddition = "ucfrontajaxaction=getfiltersdata&layoutid="+layoutID+"&elid="+widgetID;
3669		
3670		urlAjax = addUrlParam(urlAjax, urlAddition);
3671		
3672		if(g_isGutenberg == true)
3673			urlAjax = addUrlParam(urlAjax, "platform=gutenberg");
3674
3675		if(syncedWidgetIDs)
3676			urlAjax += "&syncelids="+syncedWidgetIDs;
3677
3678		if(urlAddition_filtersTest)
3679			urlAjax = addUrlParam(urlAjax, urlAddition_filtersTest);
3680
3681		if(price_from){
3682			urlAjax += "&ucpricefrom="+price_from;
3683
3684			if(g_showDebug == true){
3685				trace("add price from");
3686				trace(urlAjax);
3687			}
3688		}
3689
3690		if(price_to){
3691			urlAjax += "&ucpriceto="+price_to;
3692
3693			if(g_showDebug == true){
3694				trace("add price to");
3695				trace(urlAjax);
3696			}
3697		}
3698		
3699		if(title_start){
3700			
3701			if(g_showDebug == true)
3702				trace("add title start: "+title_start);
3703			
3704			urlAjax += "&titlestart="+title_start;
3705			urlReplace = addUrlParam(urlReplace, "titlestart="+title_start);
3706		}
3707			
3708		
3709		if(page){
3710			urlAjax += "&ucpage="+page;
3711			
3712			urlReplace = addUrlParam(urlReplace, "ucpage="+page);
3713		}
3714
3715		if(numItems)
3716			urlAjax += "&uccount="+numItems;
3717				
3718		if(arrTerms.length){
3719			
3720			var strTerms = buildTermsQuery(arrTerms);
3721		
3722			if(strTerms){
3723				urlAjax += "&ucterms="+strTerms;
3724				//set the url params as well
3725				urlReplace = addUrlParam(urlReplace, "ucterms="+strTerms);
3726				urlFilterString = addUrlParam(urlFilterString, "ucterms="+strTerms);
3727			}
3728			
3729		}
3730		
3731		//add authors
3732		if(arrAuthors.length){
3733			
3734			var strAuthors = "";
3735			jQuery.each(arrAuthors, function(index, author){
3736				var authorID = getVal(author, "id");
3737				if(authorID){
3738					if(strAuthors)
3739						strAuthors += ",";
3740					strAuthors += authorID;
3741				}
3742			});
3743			
3744			if(strAuthors){
3745				urlAjax += "&ucauthors="+strAuthors;
3746				urlReplace = addUrlParam(urlReplace, "ucauthors="+strAuthors);
3747				urlFilterString = addUrlParam(urlFilterString, "ucauthors="+strAuthors);
3748			}
3749		}
3750		
3751		 if(child_auto && arrTerms.length && childAutoString != ""){
3752			 urlAjax += childAutoString;
3753		 }
3754
3755		if(orderby){
3756			
3757			urlAjax += "&ucorderby="+orderby;
3758			urlReplace = addUrlParam(urlReplace, "ucorderby="+orderby);
3759
3760			if(orderby_metaname){
3761				urlAjax += "&ucorderby_meta="+orderby_metaname;
3762				urlReplace = addUrlParam(urlReplace, "ucorderby_meta="+orderby_metaname);
3763			}
3764
3765			if(orderby_metatype){
3766				urlAjax += "&ucorderby_metatype="+orderby_metatype;
3767				urlReplace = addUrlParam(urlReplace, "ucorderby_metatype="+orderby_metatype);
3768			}
3769
3770		}
3771
3772		if(orderdir){
3773			urlAjax += "&ucorderdir="+orderdir;
3774
3775			urlReplace = addUrlParam(urlReplace, "ucorderdir="+orderdir);
3776		}
3777		
3778		if(isFiltersInitMode && strSelectedTerms && strSelectedTerms !== "undefined")
3779			urlAjax += "&ucinitselectedterms="+strSelectedTerms;
3780		
3781		if(isFiltersInitMode && strSelectedAuthors && strSelectedAuthors !== "undefined")
3782			urlAjax += "&ucinitselectedauthors="+strSelectedAuthors;
3783		
3784		//add refresh ids
3785		if(strRefreshIDs)
3786			urlAjax += "&addelids="+strRefreshIDs;
3787		
3788		if(isReplaceMode == true)
3789			urlAjax += "&ucreplace=1";
3790
3791		//search
3792		if(search){
3793			search = encodeURIComponent(search);
3794			
3795			//search = escape(search);
3796
3797			urlAjax = addUrlParam(urlAjax, "ucs=" + search);
3798
3799			urlFilterString = addUrlParam(urlFilterString, "ucs=" + search);
3800			
3801			urlReplace = addUrlParam(urlReplace, "ucs=" + search);
3802			
3803			//add special search id
3804			if(advancedSearchFilterID)
3805				urlAjax = addUrlParam(urlAjax, "ucsid=" + advancedSearchFilterID);
3806			
3807		}
3808		
3809		//avoid duplicates - exclude, disable the offset
3810		
3811		if(objGrid.hasClass("uc-avoid-duplicates")){
3812			
3813			var objCurrentGrid = objGrid;
3814			if(isLoadMoreMode == true)
3815				objCurrentGrid = null;		//load with exclude but without offset
3816			
3817			var strExcludePostIDs = getExcludePostIDs(objCurrentGrid);		//exclude current grid
3818			
3819			if(strExcludePostIDs){
3820				urlAjax += "&ucexclude="+strExcludePostIDs;
3821				
3822				if(isLoadMoreMode == true)
3823					offset = null;
3824	
3825				urlFilterString = addUrlParam(urlFilterString, "ucexclude=" + strExcludePostIDs);
3826			}
3827		
3828		}
3829		
3830		
3831		if(offset){
3832			urlAjax += "&ucoffset="+offset;
3833
3834			urlFilterString = addUrlParam(urlFilterString, "offset=" + offset);
3835			
3836		}
3837
3838		//add custom additional attributes
3839
3840		if(urlAddFromFilters){
3841			urlAjax += addUrlParam(urlAjax, urlAddFromFilters);
3842			urlFilterString = addUrlParam(urlFilterString, urlAddFromFilters);
3843		}
3844
3845		//remove the "?" from first
3846		if(urlFilterString)
3847			urlFilterString = urlFilterString.substring(1);
3848
3849
3850		//remember init mode
3851		if(isFiltersInitMode == true)
3852			objGrid.data("was_init_mode",true);
3853
3854
3855		if(g_showDebug == true){
3856
3857			trace("url ajax: " + urlAjax);
3858		}
3859
3860		var output = {};
3861		output["ajax_url"] = urlAjax;
3862		output["url_replace"] = urlReplace;
3863		output["terms"] = arrTerms;
3864		output["search"] = search;
3865		output["title_start"] = title_start;
3866		output["filters_string"] = urlFilterString;
3867		
3868		if(g_showDebug == true){
3869
3870			trace("output: ");
3871			trace(output);
3872
3873			trace("End getGridAjaxOptions function");
3874		}
3875
3876
3877
3878		return(output);
3879	}
3880
3881
3882	/**
3883	 * get all exclude post ids from all avoid duplicates grids
3884	 * if it's a single avoid duplicates grid - don't get excludes
3885	 */
3886	function getExcludePostIDs(objCurrentGrid){
3887		
3888		//check if it's only one grid involved
3889		if(!objCurrentGrid)
3890			var objGrids = jQuery(".uc-avoid-duplicates");
3891		else
3892			var objGrids = jQuery(".uc-avoid-duplicates").not(objCurrentGrid);
3893		
3894		if(objGrids.length == 0)
3895			return("");
3896		
3897		//check if rand of only grid, get id's, else not
3898		
3899		if(objGrids.length == 1 && !objCurrentGrid){
3900			var queryData = objGrids.attr("querydata");
3901			
3902			var objQueryData = JSON.parse(queryData);
3903			var orderby = getVal(objQueryData,"orderby");
3904			
3905			if(orderby != "rand")
3906				return("");
3907		}
3908		
3909		
3910		//get all the id's of all including the existing.
3911		
3912		var strIDs = "";
3913
3914		jQuery.each(objGrids, function(index, grid){
3915			var objGrid = jQuery(grid);
3916
3917			var postIDs = objGrid.data("postids");
3918
3919			if(!postIDs)
3920				return(true);
3921
3922			if(strIDs)
3923				strIDs += ",";
3924
3925			strIDs += postIDs;
3926		});
3927
3928
3929		return(strIDs);
3930	}
3931
3932	function ________INIT_AFTER_______________(){}
3933
3934	/**
3935	 * add filter to grid init after array
3936	 */
3937	function addFilterToInitAfter(objFilter, objGrid){
3938		
3939		var role = objFilter.data("role");
3940		
3941		var key = "filters_init_after";
3942
3943		if(role == "child")
3944			key = "filters_init_after_children";
3945
3946		objFilter.data("initafter",true);
3947
3948		var arrFiltersInitAfter = objGrid.data(key);
3949
3950		if(!arrFiltersInitAfter)
3951			arrFiltersInitAfter = [];
3952
3953		arrFiltersInitAfter.push(objFilter);
3954
3955		if(g_showDebug == true)
3956			trace("Add init after: "+key+" | "+objFilter.attr("id") );
3957		
3958		objGrid.data(key, arrFiltersInitAfter);
3959
3960	}
3961
3962	/**
3963	 * check filters init after
3964	 */
3965	function isSpecialFilterInitAfter(objFilter, objGrid){
3966		
3967		var type = getFilterType(objFilter);
3968				
3969		if(type != g_types.PAGINATION && type != g_types.LOADMORE)
3970			return(false);
3971
3972		var offsetPagination = objFilter.offset();
3973		var offsetGrid = objGrid.offset();
3974
3975		if(offsetPagination.top < offsetGrid.top){
3976
3977			if(g_showDebug == true)
3978				trace("Set "+type+" to ajax init");
3979
3980			return(true);
3981		}
3982
3983		return(false);
3984	}
3985
3986	/**
3987	 * check if there is a need to refresh child filters
3988	 * grid related, other filters are set in the settings
3989	 */
3990	function initGrid_setInitFiltersAfterLoad(objGrid){
3991		
3992		//get all grid filters
3993		var objFilters = objGrid.data("filters");
3994		
3995		if(!objFilters)
3996			return(false);
3997
3998		if(objFilters.length == 0)
3999			return(false);
4000				
4001		//check if there are filters with selected
4002		
4003		var arrSelectedFilters = getSelectedFilters(objFilters);
4004		
4005		if(arrSelectedFilters.length == 0)
4006			return(false);
4007
4008		//add to refresh all not selected filters
4009		
4010		jQuery.each(objFilters, function(index, filter){
4011						
4012			var objFilter = jQuery(filter);
4013			var type = getFilterType(objFilter);
4014			
4015			//skip not related to filter types
4016			switch(type){
4017				case g_types.PAGINATION:
4018				case g_types.LOADMORE:
4019					return(true);
4020				break;
4021			}
4022			
4023			var isSelected = objFilter.hasClass("uc-has-selected");
4024			
4025			if(isSelected == true)
4026				return(true);
4027			
4028			//skip by role. main don't add to init after
4029			var filterRole = objFilter.data("role");
4030			if(filterRole == "main")
4031				return(true);
4032			
4033			//add to grid and option to refresh
4034			
4035			var objGrid = objFilter.data("grid");
4036			
4037			addFilterToInitAfter(objFilter, objGrid);
4038			
4039		});
4040
4041	}
4042	
4043	
4044	function ________INIT_______________(){}
4045
4046
4047	/**
4048	 * init the globals
4049	 */
4050	function initGlobals(){
4051
4052		if(typeof g_strFiltersData === "undefined")
4053			return(false);
4054
4055		g_filtersData = JSON.parse(g_strFiltersData);
4056
4057		if(jQuery.isEmptyObject(g_filtersData)){
4058
4059			trace("filters error - filters data not found");
4060			return(false);
4061		}
4062		
4063		g_urlBase = getVal(g_filtersData, "urlbase");
4064		g_urlAjax = getVal(g_filtersData, "urlajax");
4065		
4066		var platform = getVal(g_filtersData, "platform");
4067		
4068		//switch to gutenberg
4069		
4070		if(platform == "gutenberg"){
4071			g_isGutenberg = true;
4072			g_vars.class_widget_wrapper = "ue-widget-root";
4073			g_vars.current_postid = getVal(g_filtersData, "postid");
4074		}
4075		
4076		//ucpage url
4077		var ucpage = getVal(g_filtersData,"ucpage");
4078		if(jQuery.isNumeric(ucpage))
4079			g_vars.ucpage_url = ucpage;
4080		
4081		//url keys
4082
4083		var objUrlKeys = getVal(g_filtersData, "urlkeys");
4084		
4085		var taxSap = getVal(objUrlKeys, "tax_sap");
4086		if(taxSap)
4087			g_options.urlkey_taxsap = taxSap;
4088		
4089		var isShowDebug = getVal(g_filtersData, "debug");
4090
4091		if(isShowDebug == true)
4092			g_showDebug = true;
4093
4094		if(g_showDebug == true)
4095			trace("Show Filters Debug");
4096
4097		if(!g_urlBase){
4098			trace("ue filters error - base url not inited");
4099			return(false);
4100		}
4101
4102		if(!g_urlAjax){
4103			trace("ue filters error - ajax url not inited");
4104			return(false);
4105		}
4106		
4107		//trace(g_options);
4108		
4109		return(true);
4110	}
4111
4112
4113	/**
4114	 * init filter and bing to grid
4115	 */
4116	function initFilter(objFilter, type){
4117
4118		var objGrid = getClosestGrid(objFilter);
4119
4120		var error = "Filter Parent not found! Please put the posts element on the page, and turn on 'Enable Post Filtering' option on it";
4121
4122		if(!objGrid){
4123			
4124			
4125			//pagination can work without parent as regular link
4126			
4127			var type = getFilterType(objFilter);
4128			if(type == g_types.PAGINATION)
4129				return(false);
4130			
4131			showElementError(objFilter, error);
4132			return(null);
4133		}
4134
4135		var isAjax = objGrid.data("ajax");
4136
4137		if(isAjax == false){
4138			showElementError(objFilter, error);
4139			return(false);
4140		}
4141
4142		//bind grid to filter
4143		objFilter.data("grid", objGrid);
4144		
4145		//bind filter to grid
4146		bindFilterToGrid(objGrid, objFilter);
4147		
4148		
4149		//set data var
4150		if(g_showDebug == true)
4151			objFilter.attr("data-showdebug", true);
4152		
4153		switch(type){
4154			case g_types.TERMS_LIST:
4155				initTermsRelatedFilter(objFilter);
4156			break;
4157			case g_types.SELECT:
4158				initSelectFilter(objFilter);
4159				initTermsRelatedFilter(objFilter);				
4160			break;
4161			case g_types.GENERAL:		//general filter events
4162				initGeneralFilter(objFilter);
4163			break;
4164		}
4165
4166
4167		objFilter.trigger(g_vars.EVENT_INIT_FILTER);
4168
4169	}
4170
4171
4172	/**
4173	 * init filter events by types
4174	 */
4175	function initFilterEventsByTypes(arrTypes, arrGeneralTypes, objFilters, objParent){
4176
4177		if(!arrTypes || arrTypes.length == 0)
4178			return(false);
4179
4180		if(g_showDebug == true){
4181			trace("Init filter events for parent");
4182			trace(arrTypes);
4183			trace(objParent);
4184		}
4185
4186		for(var type in arrTypes){
4187
4188			switch(type){
4189				case g_types.PAGINATION:
4190										
4191					objParent.on("click",".uc-filter-pagination a", onAjaxPaginationLinkClick);
4192					
4193				break;
4194				case g_types.LOADMORE:
4195
4196					//load more
4197					objParent.on("click",".uc-filter-load-more__link", onLoadMoreClick);
4198				break;
4199				case g_types.TERMS_LIST:
4200
4201					objParent.on("click",".ue_taxonomy.uc-grid-filter a.ue_taxonomy_item", onTermsLinkClick);
4202
4203				break;
4204				case g_types.SEARCH:
4205
4206					//do nothing for init
4207
4208				break;
4209				case g_types.SELECT:
4210
4211					objParent.on("change", ".uc-select-filter__select", onTermsLinkClick);
4212
4213				break;
4214				case g_types.SUMMARY:
4215					//do nothing for now
4216				break;
4217				case g_types.GENERAL:
4218					//the init is from the general types
4219				break;
4220				default:
4221					trace("init by type - unrecognized type: "+type);
4222				break;
4223			}
4224		}
4225
4226		if(!arrGeneralTypes || arrGeneralTypes.length == 0)
4227			return(false);
4228
4229
4230		//init the general types
4231
4232		for(var generalType in arrGeneralTypes){
4233
4234			var objFirstFilter = arrGeneralTypes[generalType];
4235
4236			objFirstFilter.trigger(g_vars.EVENT_INIT_FILTER_TYPE,[objParent]);
4237
4238		}
4239
4240	}
4241
4242
4243
4244
4245	/**
4246	 * init pagination filter
4247	 */
4248	function initFilters(objFilters){
4249		
4250		if(g_showDebug == true){
4251
4252			trace("init filters");
4253
4254			if(objFilters.length == 0)
4255				trace("no filters found");
4256			else
4257				trace(objFilters);
4258		}
4259
4260		var numFilters = objFilters.length;
4261
4262		if(numFilters == 0)
4263			return(false);
4264
4265		var arrTypes = {};
4266		var arrGeneralTypes = {};
4267
4268		var objParent = getFiltersParent(objFilters);
4269
4270		jQuery.each(objFilters, function(index, filter){
4271
4272			var objFilter = jQuery(filter);
4273			var type = getFilterType(objFilter);
4274
4275			//set single filter
4276			if(numFilters === 1){
4277				objFilter.attr("data-singlefilter",true);
4278			}
4279
4280			initFilter(objFilter, type);
4281
4282			//collect the general type
4283
4284			arrTypes[type] = true;
4285
4286			if(type == g_types.GENERAL){
4287				var generalType = objFilter.data("generaltype");
4288				
4289				if(!generalType){
4290					trace(objFilter);
4291					throw new Error("The filter is missing generaltype data");
4292				}
4293
4294				if(arrGeneralTypes.hasOwnProperty(generalType) == false)
4295					arrGeneralTypes[generalType] = objFilter;
4296
4297			}
4298
4299			objFilter.addClass(g_vars.CLASS_FILTER_INITED);
4300
4301		});
4302
4303		initFilterEventsByTypes(arrTypes, arrGeneralTypes, objFilters, objParent);
4304
4305	}
4306
4307
4308	/**
4309	 * set init state ajax url for each grid (for go back)
4310	 */
4311	function initGrid_setAjaxUrl(objGrid){
4312
4313		var behave = objGrid.data("filterbehave");
4314
4315		if(behave != "mixed_back")
4316			return(false);
4317
4318		//get all grid filters
4319		var objFilters = objGrid.data("filters");
4320
4321		if(!objFilters)
4322			return(false);
4323
4324		if(objFilters.length == 0)
4325			return(false);
4326
4327		var objAjaxOptions = getGridAjaxOptions(objFilters, objGrid,false,false,{getonly:true});
4328
4329		var ajaxUrlInit = getVal(objAjaxOptions, "ajax_url");
4330
4331		objGrid.data("initajaxurl", ajaxUrlInit);
4332
4333	}
4334
4335
4336	/**
4337	 * set active filters data - for third party connections, active filters and clear button
4338	 */
4339	function initGrid_setActiveFiltersData(objGrid, objAjaxOptions){
4340		
4341		if(!objAjaxOptions)
4342			var objAjaxOptions = getGridAjaxOptions_simple(objGrid);
4343		
4344		var arrTerms = getVal(objAjaxOptions, "terms");
4345	
4346		if(jQuery.isArray(arrTerms))
4347			arrTerms = arrTerms.flat();
4348
4349		// Create a new array for filtered items
4350		var filteredTerms = [];
4351		
4352		jQuery.each(arrTerms, function(index, term) {
4353			
4354			// Skip if the term is an object with slug "__or__", "__and__", or "__ucor__"
4355				if (term.slug === "__ucand__" || term.slug === "__ucor__") {
4356					return(true);
4357				}
4358				
4359				// Add the term to the filtered array
4360				filteredTerms.push(term);
4361		});
4362
4363		// Assign the filtered array back to arrTerms
4364		arrTerms = filteredTerms;
4365		
4366		var search = getVal(objAjaxOptions, "search");
4367
4368		if(search)
4369			search = search.trim();
4370
4371		if(search){
4372			var objSearch = {
4373				type:"search",
4374				"key": "search|"+search,
4375				"title": search
4376			};
4377
4378			if(!arrTerms)
4379				var arrTerms = [];
4380
4381			arrTerms.push(objSearch);
4382		}
4383		
4384		//title start
4385		var titleStart = getVal(objAjaxOptions, "title_start");
4386		
4387		if(titleStart){
4388			
4389			var objTitleStart = {
4390					type:"titlestart",
4391					"key": "titlestart|"+titleStart,
4392					"title": titleStart
4393				};
4394
4395			if(!arrTerms)
4396				var arrTerms = [];
4397
4398			arrTerms.push(objTitleStart);
4399		}
4400			
4401		
4402		objGrid.data("active_filters_items", arrTerms);
4403		objGrid.trigger(g_vars.EVENT_UPDATE_ACTIVE_FILTER_ITEMS, [arrTerms]);
4404		
4405	}
4406
4407
4408	/**
4409	 * init the grids, ininital filters refresh,
4410	 * set active filters, and update initial url's
4411	 */
4412	function initGrids(){
4413
4414		var objGrids = getAllGrids("loaded_only");
4415
4416		if(objGrids.length == 0)
4417			return(false);
4418
4419		if(g_showDebug == true){
4420			trace("init grids");
4421			trace(objGrids);
4422		}
4423
4424		jQuery.each(objGrids, function(index, grid){
4425
4426			var objGrid = jQuery(grid);
4427
4428			//--- set go back url if needed
4429
4430			initGrid_setAjaxUrl(objGrid);
4431
4432			initGrid_setInitFiltersAfterLoad(objGrid);
4433
4434			//--- set active filters (for clear and active filters links)
4435
4436			initGrid_setActiveFiltersData(objGrid);
4437			
4438						
4439			//--- refresh init filters
4440			
4441			var objInitFilters = objGrid.data("filters_init_after");
4442						
4443			var isMainFiltersRefreshed = false;
4444			if(objInitFilters && objInitFilters.length > 0){
4445
4446				isMainFiltersRefreshed = true;
4447
4448				if(g_showDebug == true){
4449					trace("ajax init Filters");
4450					trace(objInitFilters);
4451				}
4452
4453				refreshAjaxGrid(objGrid, "filters");
4454			}
4455
4456			//--- refresh init filters - children
4457
4458			var objInitFiltersChildren = objGrid.data("filters_init_after_children");
4459
4460			if(objInitFiltersChildren && objInitFiltersChildren.length > 0){
4461
4462				if(isMainFiltersRefreshed == false){
4463
4464					if(g_showDebug == true){
4465						trace("ajax init child Filters");
4466						trace(objInitFiltersChildren);
4467					}
4468					
4469					refreshAjaxGrid(objGrid, "filters_children");
4470					
4471				}
4472				else
4473					objGrid.data("init_refresh_child_filters", true);
4474			}
4475
4476			objGrid.addClass("ucfilters--grid-inited");
4477
4478		});
4479
4480
4481		return(objGrids);
4482	}
4483
4484	/**
4485	 * init grids events
4486	 */
4487	function initGridsEvents(objGrids){
4488
4489		//init grids events
4490
4491		if(!objGrids || objGrids.length == 0)
4492			return(false);
4493
4494
4495		//grid several action
4496
4497		objGrids.on(g_vars.ACTION_REFRESH_GRID,function(){
4498
4499			var objGrid = jQuery(this);
4500
4501			if(g_showDebug == true){
4502				trace("Refresh grid - by event:" + g_vars.ACTION_REFRESH_GRID);
4503				console.trace();
4504			}
4505			
4506			refreshAjaxGrid(objGrid);
4507		});
4508
4509
4510		objGrids.on(g_vars.ACTION_GET_FILTERS_URL,function(){
4511
4512			var objGrid = jQuery(this);
4513
4514			var urlFilters = getGridUrlFiltersString(objGrid);
4515
4516			return(urlFilters);
4517		});
4518
4519		//clear filters from event
4520
4521		objGrids.on(g_vars.ACTION_CLEAR_FILTERS, function(){
4522			
4523			var objGrid = jQuery(this);
4524
4525			var arrActiveFilterItems = getGridActiveFilterItems(objGrid);
4526
4527			//if already cleared - no need
4528			if(!arrActiveFilterItems)
4529				return(null);
4530			
4531			clearAllFilters(objGrid, null, true);
4532			
4533			objGrid.trigger(g_vars.ACTION_REFRESH_GRID);
4534
4535		});
4536
4537		//unselect filter from event
4538
4539		objGrids.on(g_vars.EVENT_UNSELECT_FILTER, function(event, key){
4540						
4541			var objGrid = jQuery(this);
4542			
4543			unselectFilterItem(objGrid, key);
4544			
4545			objGrid.trigger(g_vars.ACTION_REFRESH_GRID);
4546		});
4547
4548	}
4549
4550	/**
4551	 * init events
4552	 */
4553	function initGeneralEvents(){
4554
4555		addEventListener('popstate', onPopState);
4556
4557		g_objBody.on(g_vars.EVENT_DOM_UPDATED, runInitFilters);
4558
4559	}
4560
4561
4562	/**
4563	 * validate the grids
4564	 */
4565	function validateGrid(objGrid){
4566
4567		//check for |raw absence
4568
4569		var isAjax = objGrid.data("ajax");
4570
4571		if(isAjax === "'true'")
4572			showElementError(objGrid, "This grid configured wrong way, missing |raw in html attributes");
4573
4574	}
4575
4576
4577	/**
4578	 * add some validation to the grids
4579	 */
4580	function validateGrids(){
4581
4582		var objGrids = getAllGrids("loaded_only");
4583
4584		jQuery.each(objGrids, function(index, grid){
4585
4586			var objGrid = jQuery(grid);
4587
4588			validateGrid(objGrids);
4589		});
4590	}
4591
4592
4593	/**
4594	 * run init filters
4595	 */
4596	function runInitFilters(){
4597
4598		validateGrids();
4599
4600		//get the filters
4601		var objFilters = jQuery(".uc-grid-filter, .uc-filter-pagination").not("." + g_vars.CLASS_FILTER_INITED);
4602		
4603		//wait for load...
4604
4605		var objFiltersLoading = objFilters.filter(".uc-waitforload");
4606
4607		if(objFiltersLoading.length && g_initFiltersCounter < 2){
4608
4609			if(g_showDebug == true){
4610				trace(objFiltersLoading);
4611				trace("Wait for Load!");
4612			}
4613
4614			setTimeout(runInitFilters, 500);
4615
4616			g_initFiltersCounter++;
4617
4618			objFilters = null;
4619			objFiltersLoading = null;
4620
4621			return(false);
4622		}
4623
4624		//init for the next time
4625		g_initFiltersCounter = 0;
4626
4627		initFilters(objFilters);
4628
4629		//init all grids with several stuff like init filters, active modes and url's
4630		var objGrids = initGrids();
4631
4632		initGridsEvents(objGrids);
4633
4634	}
4635
4636
4637	/**
4638	 * init
4639	 */
4640	function init(){
4641
4642		g_objBody = jQuery("body");
4643
4644		var success = initGlobals();
4645					//run again on fail 3 times
4646		if(success == false){
4647
4648			if(typeof window.ueFiltersTimeoutCounter != "undefined")
4649					window.ueFiltersTimeoutCounter++;
4650			else
4651				window.ueFiltersTimeoutCounter = 0;
4652
4653			if(window.ueFiltersTimeoutCounter == 3){
4654				trace("Failed to init filters");
4655				return(false);
4656			}
4657
4658			setTimeout(init, 200);
4659
4660			return(false);
4661		}
4662
4663		//init remote object if exists
4664		if(typeof UERemoteConnection == "function")
4665			g_remote = window.ueRemoteConnection;
4666
4667		runInitFilters();
4668
4669		initGeneralEvents();
4670		
4671		
4672		//run init again on elementor popup
4673		
4674		jQuery( document ).on( 'elementor/popup/show', function(event, id, objPopup){
4675			
4676			g_objBody.trigger(g_vars.EVENT_DOM_UPDATED);
4677			
4678		});
4679		
4680		
4681	}
4682
4683
4684	/**
4685	 * is element in viewport
4686	 */
4687	this.isElementInViewport = function(objElement) {
4688
4689		  var elementTop = objElement.offset().top;
4690		  var elementBottom = elementTop + objElement.outerHeight();
4691
4692		  var viewportTop = jQuery(window).scrollTop();
4693		  var viewportBottom = viewportTop + jQuery(window).height();
4694
4695		  return (elementBottom > viewportTop && elementTop < viewportBottom);
4696	}
4697
4698	/**
4699	 * run function with trashold, default is 500
4700	 */
4701	this.runWithTrashold = function(func, trashold){
4702
4703		if(!trashold)
4704			 var trashold = 500;
4705
4706		if(g_vars.trashold_handle)
4707			clearTimeout(g_vars.trashold_handle);
4708
4709		g_vars.trashold_handle = setTimeout(func, trashold);
4710
4711	};
4712
4713	/**
4714	 * get filter element data
4715	 */
4716	this.getFilterElementData = function(objElement){
4717		
4718		var objData = getFilterElementData(objElement);
4719
4720		return(objData);
4721	}
4722
4723	/**
4724	 * get filter parent query data
4725	 */
4726	this.getFilterGridQueryData = function(objFilter){
4727
4728     	 var objGrid = objFilter.data("grid");
4729      	 if(!objGrid)
4730           	return(null);
4731
4732         var queryData = objGrid.attr("querydata");
4733      	  if(!queryData)
4734            return(null);
4735
4736      	 var objData = jQuery.parseJSON(queryData);
4737
4738      	 if(g_showDebug == true){
4739      		 console.log("getQueryData (filter, grid, querydata): ",objFilter, objGrid, queryData);
4740      	 }
4741
4742		return(objData);
4743	}
4744
4745	/**
4746	 * get key
4747	 */
4748	this.getFilterItemKey = function(objItem){
4749
4750		if(!objItem || objItem.length == 0)
4751			return(null);
4752
4753		var key = objItem.data("key");
4754
4755		if(key)
4756			return(key);
4757
4758		//fallback
4759
4760		key = "term|" + objItem.data("taxonomy") + "|" + objItem.data("slug");
4761
4762		return(key);
4763	}
4764
4765
4766	/**
4767	 * get value
4768	 */
4769	this.getVal = function(obj, name, defaultValue){
4770
4771		return getVal(obj, name, defaultValue);
4772	}
4773	
4774	/**
4775	 * get filters by type
4776	 * return jquery object
4777	 */
4778	this.getGridFiltersByType = function(objGrid, filterType){
4779		
4780		if(!filterType)
4781			throw new Error("getGridFiltersByType error - enter type as second param");
4782		
4783		var arrFilters = getGridFilters(objGrid);
4784		
4785		if(arrFilters.length == 0)
4786			return(jQuery());
4787		
4788		var objChosenFilters = jQuery();
4789		
4790		jQuery.each(arrFilters, function(index, objFilter){
4791			
4792			var type = getFilterType(objFilter, true);
4793						
4794			if(type == filterType){
4795				objChosenFilters = objChosenFilters.add(objFilter);
4796			}
4797			
4798		});
4799		
4800		return(objChosenFilters);
4801	}
4802
4803
4804	/**
4805	 * init the class
4806	 */
4807	function construct(){
4808
4809		if(!jQuery){
4810			trace("Filters not loaded, jQuery not loaded");
4811			return(false);
4812		}
4813		
4814		jQuery("document").ready(function(){
4815			setTimeout(init, 200);
4816		});
4817		
4818	}
4819
4820	construct();
4821
4822}
4823
4824g_ucDynamicFilters = new UEDynamicFilters();

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.