PageSourceSearch

https://porpatas.es/wp-content/plugins/customer-reviews-woocommerce/js/frontend.js?ver=5.124.0

js porpatas.es collected 2026-10-09 21:59:53 UTC 97,653 bytes, 2,041 lines download raw bytes

1(function() {
2	jQuery(document).ready(function($) {
3		const crAddCaptionText = function( item, captionElement ) {
4			const caption = captionElement.children[ 0 ];
5			if ( ! caption ) {
6				return false;
7			}
8			caption.textContent = item.title || '';
9			return !! item.title;
10		};
11		// initial resize of [cusrev_reviews_grid] and Trust Badges
12		crResizeAllGridItems();
13		crResizeTrustBadges();
14		//enable attachment of images to comments
15		jQuery("form#commentform").attr( "enctype", "multipart/form-data" ).attr( "encoding", "multipart/form-data" );
16		//prevent review submission if captcha is not solved
17		jQuery("#commentform").on( "submit", function(event) {
18			if( ! crCaptchaEnabled() ) {
19				return;
20			}
21			const commentForm = jQuery( this );
22			if( crCaptcha.isInvisible() ) {
23				if( commentForm.data( "crCaptchaToken" ) ) {
24					commentForm.data( "crCaptchaToken", false );
25					return;
26				}
27				event.preventDefault();
28				crCaptcha.execute( commentForm, function( token ) {
29					if( ! token ) {
30						alert( crCaptcha.errorText() );
31						return;
32					}
33					commentForm.data( "crCaptchaToken", true );
34					const submitButton = commentForm.find( "[type='submit']" ).first();
35					if( submitButton.length ) {
36						submitButton[0].click();
37					} else {
38						HTMLFormElement.prototype.submit.call( commentForm[0] );
39					}
40				} );
41			} else if( "" === crCaptcha.getResponse( commentForm ) ) {
42				event.preventDefault();
43				alert( crCaptcha.errorText() );
44			}
45		} );
46		//show lightbox when click on images attached to reviews
47		jQuery("ol.commentlist").on("click", ".cr-comment-a", function(t) {
48			if(cr_ajax_object.disable_lightbox === '0') {
49				//only if lightbox is not disabled in settings of the plugin
50				t.preventDefault();
51				const oo = jQuery(".pswp");
52				if ( 0 < oo.length ) {
53					const o = oo[0];
54					var pics = jQuery(this).parent().parent().find(".cr-comment-a img");
55					var this_pic = jQuery(this).find("img");
56					var inx = 0;
57					if (pics.length > 0 && this_pic.length > 0) {
58						var a = [];
59						for (i = 0; i < pics.length; i++) {
60							a.push({
61								src: pics[i].src,
62								w: pics[i].naturalWidth,
63								h: pics[i].naturalHeight,
64								title: pics[i].alt
65							});
66							if (this_pic[0].src == pics[i].src) {
67								inx = i;
68							}
69						}
70						var r = {
71							index: inx,
72							addCaptionHTMLFn: crAddCaptionText,
73						};
74						new PhotoSwipe(o, PhotoSwipeUI_Default, a, r).init();
75					}
76				}
77			}
78		});
79		// play a video when a user clicks on it in the reviews grid
80		jQuery(".cr-reviews-grid").on("click", ".image-row-vid, .cr-comment-videoicon", function(t) {
81			if( ! jQuery(this).closest(".image-row").hasClass( "cr-vid-playing" ) ) {
82				jQuery(this).closest(".image-row").addClass( "cr-vid-playing" );
83				jQuery(this).closest(".image-row").find(".image-row-vid").prop( "controls", true );
84				jQuery(this).closest(".image-row").find(".image-row-vid").get(0).play();
85			} else {
86				jQuery(this).closest(".image-row").find(".image-row-vid").get(0).pause();
87				jQuery(this).closest(".image-row").find(".image-row-vid").prop( "controls", false );
88				jQuery(this).closest(".image-row").removeClass( "cr-vid-playing" );
89			}
90			return false;
91		} );
92		// play a video when a user clicks on it in the media pop-up window
93		jQuery(".cr-ajax-reviews-cus-images-modal").on("click", ".cr-ajax-reviews-video, .cr-ajax-reviews-video .cr-comment-videoicon", function(t) {
94			if( ! jQuery(this).closest(".cr-ajax-reviews-video").hasClass( "cr-vid-playing" ) ) {
95				jQuery(this).closest(".cr-ajax-reviews-video").addClass( "cr-vid-playing" );
96				jQuery(this).closest(".cr-ajax-reviews-video").find("video").prop( "controls", true );
97				jQuery(this).closest(".cr-ajax-reviews-video").find("video").get(0).play();
98			} else {
99				jQuery(this).closest(".cr-ajax-reviews-video").find("video").get(0).pause();
100				jQuery(this).closest(".cr-ajax-reviews-video").find("video").prop( "controls", false );
101				jQuery(this).closest(".cr-ajax-reviews-video").removeClass( "cr-vid-playing" );
102			}
103			return false;
104		} );
105		// open a gallery with media files in the reviews grid
106		jQuery(".cr-reviews-grid").on("click", ".media-row-count", function(t) {
107			if ( cr_ajax_object.disable_lightbox === '0' ) {
108				// only if lightbox is not disabled in settings of the plugin
109				t.preventDefault();
110				const oo = jQuery(".pswp");
111				let media = jQuery(this).parent().find(".image-row-vid,.image-row-img"),
112					this_media = jQuery(this),
113					inx = 0;
114				if (media.length > 0 && this_media.length > 0) {
115					const o = oo[0];
116					var a = [];
117					for (i = 0; i < media.length; i++) {
118						if ( "vid" === media[i].dataset.crmedia ) {
119							a.push({
120								html: '<div class="cr-video-wrapper"><video class="cr-media-video" src="' + media[i].src + '" controls></video></div>',
121								title: media[i].dataset.crtitle
122							});
123						} else {
124							a.push({
125								src: media[i].src,
126								w: media[i].naturalWidth,
127								h: media[i].naturalHeight,
128								title: media[i].alt
129							});
130						}
131						if (this_media[0].src == media[i].src) {
132							inx = i;
133						}
134					}
135					var r = {
136						index: inx,
137						addCaptionHTMLFn: crAddCaptionText,
138					};
139					new PhotoSwipe(o, PhotoSwipeUI_Default, a, r).init();
140				}
141			}
142		} );
143		// play or pause a video in the gallery
144		jQuery(document).on("click", ".cr-video-wrapper .cr-media-video", function(t) {
145			const vid = jQuery(this).get(0);
146			if ( vid ) {
147				const isVideoPlaying = !!( vid.currentTime > 0 && !vid.paused && !vid.ended && vid.readyState > 2 );
148				if ( isVideoPlaying ) {
149					vid.pause();
150				} else {
151					vid.play();
152				}
153			}
154			return false;
155		} );
156		// show a lightbox when a user clicks on images in the reviews grid
157		jQuery(".cr-reviews-grid").on("click", ".image-row-img, .image-row-count", function(t) {
158			if(cr_ajax_object.disable_lightbox === '0') {
159				// only if lightbox is not disabled in settings of the plugin
160				t.preventDefault();
161				const oo = jQuery(".pswp");
162				if ( 0 < oo.length ) {
163					const o = oo[0];
164					var pics = jQuery(this).parent().find("img.image-row-img");
165					var this_pic = jQuery(this);
166					var inx = 0;
167					if (pics.length > 0 && this_pic.length > 0) {
168						var a = [];
169						for (i = 0; i < pics.length; i++) {
170							a.push({
171								src: pics[i].src,
172								w: pics[i].naturalWidth,
173								h: pics[i].naturalHeight,
174								title: pics[i].alt
175							});
176							if (this_pic[0].src == pics[i].src) {
177								inx = i;
178							}
179						}
180						var r = {
181							index: inx,
182							addCaptionHTMLFn: crAddCaptionText,
183						};
184						new PhotoSwipe(o, PhotoSwipeUI_Default, a, r).init();
185					}
186				}
187			}
188		});
189		//register a listener for votes on for reviews
190		initVoteClick("ol.commentlist", ".cr-voting-a", "cr_vote_review");
191		//register a listener for the voting buttons on modal
192		initVoteClick(".cr-ajax-reviews-cus-images-modal", ".cr-voting-a", "cr_vote_review");
193		//register a listener for the voting buttons on Q & A
194		initVoteClick(".cr-qna-block .cr-qna-list-block", ".cr-voting-a", "cr_vote_question");
195
196		//show a lightbox when click on videos attached to reviews
197		jQuery("ol.commentlist").on("click", ".cr-video-a, .cr-comment-videoicon", function(t) {
198			if( ! jQuery(this).closest(".cr-comment-videos").hasClass( "cr-comment-videos-modal" ) ) {
199				let tt = jQuery(this).closest("[class*='cr-comment-video-']");
200				jQuery(this).closest(".cr-comment-videos").addClass( "cr-comment-videos-modal" );
201				tt.addClass( "cr-comment-video-modal" );
202				tt.find( "video" ).prop( "controls", true );
203				tt.find( ".cr-comment-videoicon" ).hide();
204				tt.find( "video" ).get(0).play();
205				return false;
206			}
207			return false;
208		} );
209		//close a video lightbox
210		jQuery("ol.commentlist").on( "click", ".cr-comment-videos", function(t) {
211			if( jQuery(this).hasClass( "cr-comment-videos-modal" ) ) {
212				jQuery(this).removeClass( "cr-comment-videos-modal" );
213				jQuery(this).find("[class*='cr-comment-video-']").each(function(index, element){
214					if( jQuery(element).hasClass( "cr-comment-video-modal" ) ) {
215						jQuery(element).removeClass( "cr-comment-video-modal" );
216						jQuery(element).find( "video").get(0).pause();
217						jQuery(element).find( "video" ).prop( "controls", false );
218						jQuery(element).find( ".cr-comment-videoicon" ).show();
219						jQuery(element).removeAttr("style");
220					}
221				});
222				return false;
223			}
224		} );
225		//show more ajax reviews
226		jQuery(".cr-show-more-reviews-prd").on( "click", function(t) {
227			t.preventDefault();
228			crShowMoreReviewsPrd( jQuery(this) );
229		} );
230
231		// ajax sorting of reviews
232		jQuery(".cr-ajax-reviews-sort").on( "change", function(t) {
233			t.preventDefault();
234
235			if ( jQuery(this).parents(".cr-all-reviews-shortcode").length ) {
236				// sorting in the all reviews block
237				cr_filter_all_reviews( jQuery(this) );
238			} else {
239				// sorting on a product page
240				var cr_product_id = jQuery(this).parents(".cr-reviews-ajax-comments").find(".commentlist.cr-ajax-reviews-list").attr("data-product");
241				var cr_sort = jQuery(this).children("option:selected").val();
242				var cr_rating = jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-summaryBox-ajax .ivole-histogramRow.ivole-histogramRow-s .cr-histogram-a").attr("data-rating");
243				if(!cr_rating){
244					cr_rating = 0;
245				}
246				var cr_tags = [];
247				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-review-tags-filter .cr-tags-filter.cr-tag-selected").each(
248					function() {
249						cr_tags.push( jQuery(this).attr("data-crtagid") );
250					}
251				);
252				var cr_media = jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-review-tags-filter .cr-media-pill.cr-tag-selected").length ? 1 : 0;
253				var cr_data = {
254					"action": "cr_sort_reviews",
255					"productID": cr_product_id,
256					"sort": cr_sort,
257					"rating": cr_rating,
258					"tags": cr_tags,
259					"media": cr_media
260				};
261				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-search-no-reviews").hide();
262				jQuery(this).parents(".cr-reviews-ajax-comments").find('.cr-ajax-search input').val("").trigger("change");
263				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-reviews-prd").hide();
264				jQuery(this).parents(".cr-reviews-ajax-comments").find(".commentlist.cr-ajax-reviews-list").hide();
265				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-review-spinner").show();
266				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-summaryBox-ajax").addClass("cr-summaryBar-updating");
267				jQuery(this).addClass("cr-sort-updating");
268				jQuery.post( {
269					url: cr_ajax_object.ajax_url,
270					data: cr_data,
271					context: this,
272					success: function(response) {
273						jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-review-spinner").hide();
274						jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-summaryBox-ajax").removeClass("cr-summaryBar-updating");
275						jQuery(this).removeClass("cr-sort-updating");
276						if(response.page > 0){
277							jQuery(this).parents(".cr-reviews-ajax-comments").find(".commentlist.cr-ajax-reviews-list").empty();
278							jQuery(this).parents(".cr-reviews-ajax-comments").find(".commentlist.cr-ajax-reviews-list").append(response.html);
279							jQuery(this).parents(".cr-reviews-ajax-comments").find(".commentlist.cr-ajax-reviews-list").show();
280							jQuery(this).parents(".cr-reviews-ajax-comments").attr("data-page",response.page);
281							if( response.show_more_label ) {
282								jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-reviews-prd").text( response.show_more_label );
283							}
284							if ( response.count_row ) {
285								jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-count-row .cr-count-row-count").html( response.count_row );
286							}
287							if(!response.last_page){
288								jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-reviews-prd").show();
289							}
290						}
291					},
292					dataType: "json"
293				} );
294			}
295		} );
296		// non-ajax filtering of reviews
297		jQuery(".cr-noAjax").on( "click", ".cr-histogram-a", function (t) {
298			t.preventDefault();
299			const parser = new URL(window.location);
300			parser.searchParams.set(cr_ajax_object.rating_filter, jQuery(this).data("rating"));
301			parser.hash = cr_ajax_object.reviews_tab;
302			window.location = parser.href;
303		} );
304		// ajax filtering of reviews
305		jQuery(".cr-reviews-ajax-comments").on("click", ".cr-histogram-a, .cr-seeAllReviews", function(t){
306			t.preventDefault();
307			let tmpParent = jQuery(this).parents(".cr-reviews-ajax-comments");
308			let cr_product_id = tmpParent.find(".commentlist.cr-ajax-reviews-list").attr("data-product");
309			let cr_nonce = tmpParent.find(".cr-summaryBox-ajax").attr("data-nonce");
310			let cr_rating = jQuery(this).attr("data-rating");
311			let cr_sort = tmpParent.find(".cr-ajax-reviews-sort").children("option:selected").val();
312			let cr_tags = [];
313			tmpParent.find(".cr-review-tags-filter .cr-tags-filter.cr-tag-selected").each(
314				function() {
315					cr_tags.push( jQuery(this).attr("data-crtagid") );
316				}
317			);
318			let cr_media = tmpParent.find(".cr-review-tags-filter .cr-media-pill.cr-tag-selected").length ? 1 : 0;
319			let cr_data = {
320				"action": "cr_filter_reviews",
321				"productID": cr_product_id,
322				"rating": cr_rating,
323				"sort": cr_sort,
324				"tags": cr_tags,
325				"media": cr_media,
326				"security": cr_nonce
327			};
328			tmpParent.find(".cr-summaryBox-ajax .ivole-histogramRow.ivole-histogramRow-s").removeClass("ivole-histogramRow-s");
329			if( cr_rating > 0 ) {
330				jQuery(this).closest(".ivole-histogramRow").addClass("ivole-histogramRow-s");
331			}
332			tmpParent.find(".cr-search-no-reviews").hide();
333			tmpParent.find('.cr-ajax-search input').val("").trigger("change");
334			tmpParent.find(".cr-show-more-reviews-prd").hide();
335			tmpParent.find(".commentlist.cr-ajax-reviews-list").hide();
336			tmpParent.find(".cr-show-more-review-spinner").show();
337			tmpParent.find(".cr-summaryBox-ajax").addClass("cr-summaryBar-updating");
338			tmpParent.find(".cr-ajax-reviews-sort").addClass("cr-sort-updating");
339			jQuery.post( {
340				url: cr_ajax_object.ajax_url,
341				data: cr_data,
342				context: tmpParent,
343				success: function(response) {
344					this.find(".cr-show-more-review-spinner").hide();
345					this.find(".cr-summaryBox-ajax").removeClass("cr-summaryBar-updating");
346					this.find(".cr-ajax-reviews-sort").removeClass("cr-sort-updating");
347					if(response.page > 0) {
348						this.find(".commentlist.cr-ajax-reviews-list").empty();
349						this.find(".commentlist.cr-ajax-reviews-list").append(response.html);
350						this.find(".commentlist.cr-ajax-reviews-list").show();
351						this.attr("data-page",response.page);
352						if( response.show_more_label ) {
353							this.find( ".cr-show-more-reviews-prd" ).text( response.show_more_label );
354						}
355						if ( response.count_row ) {
356							this.find(".cr-count-row .cr-count-row-count").html( response.count_row );
357						}
358						if(!response.last_page){
359							this.find(".cr-show-more-reviews-prd").show();
360						}
361					}
362				},
363				dataType: "json"
364			} );
365		} );
366		// ajax search typing
367		jQuery('.cr-ajax-search input').on("keyup", function(e){
368			if(e.keyCode == 13){
369				jQuery(this).parents(".cr-ajax-search").find("button").trigger("click");
370			}
371			// show clear icon
372			if(jQuery(this).val() !== "") {
373				jQuery(this).parents(".cr-ajax-search").find(".cr-clear-input").css("display", "inline-block");
374			} else {
375				jQuery(this).parents(".cr-ajax-search").find(".cr-clear-input").css("display", "none");
376			}
377		}).on("change", function(){
378			if(jQuery(this).val() === "") jQuery(this).parents(".cr-ajax-search").find(".cr-clear-input").hide();
379		});
380		//
381		jQuery('.cr-reviews-ajax-reviews .cr-ajax-search input').on( 'keyup', crDebounce(
382			( ref ) => {
383				jQuery(ref.target).parents(".cr-reviews-ajax-comments").attr("data-page", 0);
384				jQuery(ref.target).parents(".cr-reviews-ajax-reviews").find(".cr-ajax-reviews-list").empty();
385				crShowMoreReviewsPrd( jQuery(ref.target) );
386			},
387			1000
388		) );
389		// clear search field
390		jQuery(".cr-ajax-search .cr-clear-input").on("click", function () {
391			jQuery(this).prev("input").val("");
392			jQuery(this).parents(".cr-ajax-search").find(".cr-clear-input").hide();
393			jQuery(this).parents(".cr-ajax-search").find("button").trigger("click");
394			//
395			if( jQuery(this).parents(".cr-reviews-ajax-reviews").length ) {
396				// clear search in the case of product pages
397				jQuery(this).parents(".cr-reviews-ajax-comments").attr("data-page", 0);
398				jQuery(this).parents(".cr-reviews-ajax-reviews").find(".cr-ajax-reviews-list").empty();
399				crShowMoreReviewsPrd( jQuery(this) );
400			}
401		});
402		// ajax search of reviews
403		jQuery(".cr-ajax-search button").on("click", function (e) {
404			e.preventDefault();
405
406			//search in the all reviews block
407			if( jQuery(this).parents(".cr-all-reviews-shortcode").length ){
408				// search in ajax version of the All Reviews block / shortcode
409				cr_filter_all_reviews( jQuery(this) );
410			} else {
411				jQuery(this).parents(".cr-reviews-ajax-comments").attr("data-page", 0);
412				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-ajax-reviews-list").empty();
413				crShowMoreReviewsPrd( jQuery(this) );
414			}
415		});
416		jQuery(".cr-ajax-reviews-add-review, .cr-nosummary-add").on( "click", function(t) {
417			t.preventDefault();
418			var parent = jQuery(this).closest(".cr-reviews-ajax-reviews");
419			parent.find(".cr-reviews-ajax-comments").hide();
420			var reviewForm = parent.find(".cr-ajax-reviews-review-form");
421			reviewForm.show();
422			reviewForm.find( ".cr-review-form-wrap" ).first().trigger( "focus" );
423
424			// If captcha script is loaded, reset and render the widget after the form becomes visible.
425			if ( window.crCaptcha && typeof window.crCaptcha.render === 'function' ) {
426				// small delay to allow layout/visibility changes to take effect
427				window.setTimeout( function() {
428					try {
429						if ( typeof window.crCaptcha.reset === 'function' ) {
430							window.crCaptcha.reset( reviewForm );
431						}
432						window.crCaptcha.render( reviewForm );
433					} catch ( e ) {
434						// ignore errors
435					}
436				}, 50 );
437			}
438		} );
439		// click to filter reviews by tags
440		jQuery(".cr-review-tags-filter span.cr-tags-filter").on( "click", function (e) {
441			e.preventDefault();
442			if(jQuery(this).hasClass("cr-tag-selected")) {
443				jQuery(this).removeClass("cr-tag-selected");
444			} else {
445				jQuery(this).addClass("cr-tag-selected");
446			}
447			if ( jQuery(this).parents(".cr-all-reviews-shortcode").length ) {
448				// tags filtering in the all reviews shortcode
449				cr_filter_all_reviews( jQuery(this) );
450			} else {
451				// tags filtering on a product page
452				jQuery(this).parents(".cr-reviews-ajax-comments").attr("data-page", 0);
453				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-ajax-reviews-list").empty();
454				crShowMoreReviewsPrd( jQuery(this) );
455			}
456		} );
457		// click to filter reviews to only show ones with attached photos or videos
458		jQuery(".cr-review-tags-filter span.cr-media-pill").on( "click", function (e) {
459			e.preventDefault();
460			jQuery(this).toggleClass("cr-tag-selected");
461			if ( jQuery(this).parents(".cr-all-reviews-shortcode").length ) {
462				// media filtering in the all reviews shortcode
463				cr_filter_all_reviews( jQuery(this) );
464			} else {
465				// media filtering on a product page
466				jQuery(this).parents(".cr-reviews-ajax-comments").attr("data-page", 0);
467				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-ajax-reviews-list").empty();
468				crShowMoreReviewsPrd( jQuery(this) );
469			}
470		} );
471		//open popup window with pictures
472		jQuery(".cr-comment-image-top .cr-comment-image-top-item").on( "click", function(t) {
473			t.preventDefault();
474			jQuery("body").addClass("cr-noscroll");
475			let slide_no = jQuery(this).data("slide");
476			let imgParent = jQuery(this).closest(".cr-ajax-reviews-cus-images-div").parent();
477			imgParent.find(".cr-ajax-reviews-cus-images-modal-cont").addClass("cr-mask-active");
478			imgParent.find(".cr-ajax-reviews-cus-images-modal .cr-ajax-reviews-cus-images-slider-main").slickk('setPosition');
479			imgParent.find(".cr-ajax-reviews-cus-images-modal .cr-ajax-reviews-cus-images-slider-nav").slickk('setPosition');
480			if ( typeof slide_no !== 'undefined' ) {
481				imgParent.find(".cr-ajax-reviews-cus-images-modal .cr-ajax-reviews-cus-images-slider-main").slickk('slickGoTo', slide_no, true);
482				imgParent.find(".cr-ajax-reviews-cus-images-modal .cr-ajax-reviews-cus-images-slider-nav").slickk('slickGoTo', slide_no, true);
483			}
484		} );
485		jQuery(".cr-comment-image-top .cr-comment-videoicon").on( "click", function(t) {
486			jQuery(this).closest( ".cr-comment-image-top" ).find( ".cr-comment-image-top-item" ).trigger( "click" );
487		} );
488		//close popup window with pictures
489		jQuery(".cr-ajax-reviews-cus-images-modal-cont, .cr-ajax-reviews-cus-images-modal .cr-ajax-reviews-cus-images-close").on( "click", function(t) {
490			t.preventDefault();
491			let closeParent = jQuery(this).closest(".cr-ajax-reviews-cus-images-modal-cont.cr-mask-active");
492			closeParent.find(".cr-ajax-reviews-cus-images-modal .cr-ajax-reviews-cus-images-slider-main").slickk('slickGoTo',0,true);
493			closeParent.find(".cr-ajax-reviews-cus-images-modal .cr-ajax-reviews-cus-images-slider-nav").slickk('slickGoTo',0,true);
494			closeParent.removeClass("cr-mask-active");
495			jQuery("body").removeClass("cr-noscroll");
496		} );
497		jQuery(".cr-ajax-reviews-cus-images-modal-cont .cr-ajax-reviews-cus-images-modal").on( "click", function(t) {
498			t.stopPropagation();
499		} );
500		//Product variations
501		jQuery(".single_variation_wrap").on( "show_variation", function ( event, variation ) {
502			if(jQuery(".cr_gtin").length){
503				jQuery(".cr_gtin_val").text(variation._cr_gtin);
504			}
505			if(jQuery(".cr_mpn").length){
506				jQuery(".cr_mpn_val").text(variation._cr_mpn);
507			}
508			if(jQuery(".cr_brand").length){
509				jQuery(".cr_brand_val").text(variation._cr_brand);
510			}
511		});
512		//Reset Product variations
513		jQuery(document).on('reset_data', function () {
514			var cr_gtin = jQuery(".cr_gtin"),
515			cr_mpn = jQuery(".cr_mpn"),
516			cr_brand = jQuery(".cr_brand");
517
518			if(cr_gtin.length){
519				jQuery(".cr_gtin_val").text(cr_gtin.data("o_content"));
520			}
521			if(cr_mpn.length){
522				jQuery(".cr_mpn_val").text(cr_mpn.data("o_content"));
523			}
524			if(cr_brand.length){
525				jQuery(".cr_brand_val").text(cr_brand.data("o_content"));
526			}
527		});
528		// show more ajax reviews in the all reviews block
529		jQuery('.cr-all-reviews-shortcode .cr-show-more-button').on("click", function (e) {
530			e.preventDefault();
531			cr_filter_all_reviews( jQuery(this), true );
532		});
533		jQuery('.cr-all-reviews-shortcode').on("click", ".cr-page-numbers-a", function (e) {
534			e.preventDefault();
535			cr_filter_all_reviews( jQuery(this), true );
536		});
537		// filter ajax reviews in the all reviews block
538		jQuery(".cr-all-reviews-shortcode").on("click", ".cr-histogram-a, .cr-seeAllReviews", function(t){
539			t.preventDefault();
540			let cr_rating = jQuery(this).data("rating");
541			jQuery("div.ivole-summaryBox .ivole-histogramRow.ivole-histogramRow-s").removeClass("ivole-histogramRow-s");
542			if ( cr_rating > 0 ) {
543				jQuery(this).closest(".ivole-histogramRow").addClass("ivole-histogramRow-s");
544			}
545			jQuery(this).parents(".cr-all-reviews-shortcode").find(".cr-review-tags-filter .cr-tag-selected").removeClass("cr-tag-selected");
546			cr_filter_all_reviews( jQuery(this) );
547		});
548
549		// show more ajax reviews in the grid
550		jQuery( ".cr-reviews-grid .cr-show-more-button" ).on( "click", function (e) {
551			e.preventDefault();
552
553			let $this = jQuery(this),
554			$spinner =  $this.next(".cr-show-more-spinner"),
555			cr_rating = $this.parents(".cr-reviews-grid").find(".ivole-summaryBox.cr-grid-reviews-ajax .ivole-histogramRow.ivole-histogramRow-s .cr-histogram-a").attr("data-rating"),
556			attributes = $this.parents(".cr-reviews-grid").data("attributes");
557
558			attributes.comment__not_in = $this.parents(".cr-reviews-grid").find(".cr-review-card.cr-card-product").map( function() {
559				return jQuery(this).data("reviewid");
560			} ).get();
561			attributes.comment__not_in = attributes.comment__not_in.concat(
562				$this.parents(".cr-reviews-grid").find(".cr-review-card.cr-card-shop").map(function(){
563					return jQuery(this).data("reviewid");
564				}).get() );
565
566			var grid_data = {
567				'action': "ivole_show_more_grid_reviews",
568				'rating': cr_rating,
569				'attributes': attributes
570			};
571
572			$this.hide();
573			$spinner.show();
574
575			jQuery.post(cr_ajax_object.ajax_url, grid_data, function(response) {
576				$spinner.hide();
577				$reviews = jQuery(response.html).find(".cr-review-card");
578				let showMoreBtn = jQuery(response.html).find(".cr-show-more-button");
579				if ( $reviews.length ) {
580					$this.parents(".cr-reviews-grid").find(".cr-reviews-grid-inner").colcade("append", $reviews);
581					if ( showMoreBtn.length ) {
582						$this.text( showMoreBtn.text() );
583						$this.show();
584					} else {
585						$this.hide();
586					}
587				} else {
588					$this.hide();
589				}
590			}).fail(function(response) {
591				$spinner.hide();
592				$this.show();
593				$this.parent().append('<div style="color:#cd2653;text-align:center;display:block;">'+response.responseText+'</div>');
594			});
595		});
596
597		jQuery(".cr-reviews-grid .cr-summaryBox-wrap").on("click", ".cr-histogram-a, .cr-seeAllReviews", function(e){
598			e.preventDefault();
599
600			let $this = jQuery(this),
601			$grid =  $this.parents(".cr-reviews-grid"),
602			$spinner =  $grid.find(".cr-show-more-spinner"),
603			cr_rating = $this.attr("data-rating"),
604			attributes = $grid.data("attributes");
605
606			attributes.show_more = attributes.count + attributes.count_shop_reviews;
607			attributes.comment__not_in = [];
608
609			if(!cr_rating) cr_rating = 0;
610
611			var grid_data = {
612				'action': "ivole_show_more_grid_reviews",
613				'rating': cr_rating,
614				'attributes': attributes
615			};
616
617			$grid.find("div.ivole-summaryBox .ivole-histogramRow.ivole-histogramRow-s").removeClass("ivole-histogramRow-s");
618			if( cr_rating > 0 ) {
619				$this.closest(".ivole-histogramRow").addClass("ivole-histogramRow-s");
620			}
621			$grid.find(".cr-reviews-grid-inner").hide();
622			$grid.find(".cr-show-more-button").hide();
623			$spinner.show();
624			$grid.find("div.ivole-summaryBox").addClass("cr-summaryBar-updating");
625
626			jQuery.post(cr_ajax_object.ajax_url, grid_data, function(response) {
627				$spinner.hide();
628				$grid.find(".cr-show-more-button").show();
629				$grid.find(".cr-summaryBox-wrap .cr-count-filtered-reviews").empty();
630				$reviews = jQuery(response.html).find(".cr-review-card");
631				if($reviews.length){
632					$grid.find(".cr-reviews-grid-inner").colcade("empty");
633					$grid.find(".cr-reviews-grid-inner").show();
634					$grid.find(".cr-reviews-grid-inner").colcade("append", $reviews);
635					$grid.find("div.ivole-summaryBox").removeClass("cr-summaryBar-updating");
636					$grid.find(".cr-summaryBox-wrap .cr-count-filtered-reviews").append(jQuery(response.html).find(".cr-count-filtered-reviews").html());
637				}
638			}).fail(function(response) {
639				$spinner.hide();
640				$this.parent().append('<div style="color: #cd2653;text-align: center;display: block;">'+response.responseText+'</div>');
641			});
642
643		});
644		jQuery('#cr_floatingtrustbadge').on( "click", function() {
645			if( !jQuery(this).hasClass( 'cr-floatingbadge-big' ) ) {
646				jQuery(this).find('div.cr-badge.badge_size_compact').hide();
647				jQuery(this).find('div.cr-badge.badge--wide-mobile').css( 'display', 'block' );
648				jQuery(this).find('div.cr-floatingbadge-close').css( 'display', 'block' );
649				jQuery(this).addClass( 'cr-floatingbadge-big' );
650				//update colors
651				var crcolors = jQuery(this).data('crcolors');
652				if (typeof crcolors !== 'undefined') {
653					jQuery(this).css( 'border-color', crcolors['big']['border'] );
654					jQuery(this).find('div.cr-floatingbadge-background-top').css( 'background-color', crcolors['big']['top'] );
655					jQuery(this).find('div.cr-floatingbadge-background-middle').
655css( 'background-color', crcolors['big']['middle'] );
656					jQuery(this).find('div.cr-floatingbadge-background-bottom').css( 'background-color', crcolors['big']['bottom'] );
657					jQuery(this).find('div.cr-floatingbadge-background-bottom').css( 'border-color', crcolors['big']['border'] );
658				}
659			}
660		} );
661		jQuery('#cr_floatingtrustbadge .cr-floatingbadge-close').on( "click", function(event) {
662			if( jQuery('#cr_floatingtrustbadge').hasClass( 'cr-floatingbadge-big' ) ) {
663				jQuery(this).closest('#cr_floatingtrustbadge').find('div.cr-badge.badge--wide-mobile').hide();
664				jQuery(this).closest('#cr_floatingtrustbadge').find('div.cr-badge.badge_size_compact').css( 'display', 'block' );
665				jQuery(this).closest('#cr_floatingtrustbadge').removeClass( 'cr-floatingbadge-big' );
666				//update colors
667				var crcolors = jQuery(this).closest('#cr_floatingtrustbadge').data('crcolors');
668				if (typeof crcolors !== 'undefined') {
669					jQuery(this).closest('#cr_floatingtrustbadge').css( 'border-color', crcolors['small']['border'] );
670					jQuery(this).closest('#cr_floatingtrustbadge').find('div.cr-floatingbadge-background-top').css( 'background-color', crcolors['small']['top'] );
671					jQuery(this).closest('#cr_floatingtrustbadge').find('div.cr-floatingbadge-background-middle').css( 'background-color', crcolors['small']['middle'] );
672					jQuery(this).closest('#cr_floatingtrustbadge').find('div.cr-floatingbadge-background-bottom').css( 'background-color', crcolors['small']['bottom'] );
673					jQuery(this).closest('#cr_floatingtrustbadge').find('div.cr-floatingbadge-background-bottom').css( 'border-color', crcolors['small']['border'] );
674				}
675			} else {
676				jQuery('#cr_floatingtrustbadge').hide();
677				document.cookie = 'cr_hide_trustbadge=true; path=/; max-age='+60*60*24+';';
678			}
679			event.stopPropagation();
680		} );
681		jQuery( '.cr-reviews-slider' ).on( 'click', '.cr-slider-read-more a', function (e) {
682			e.preventDefault();
683			let parent = jQuery(this).parents(".review-text");
684			parent.find(".cr-slider-read-more").hide();
685			parent.find(".cr-slider-details").css("display", "inline");
686			jQuery(this).parents(".cr-reviews-slider").slickk('setPosition');
687		} );
688		jQuery( '.cr-reviews-slider' ).on( 'click', '.cr-slider-read-less a', function (e) {
689			e.preventDefault();
690			let parent = jQuery(this).parents(".review-text");
691			parent.find(".cr-slider-details").hide();
692			parent.find(".cr-slider-read-more").css("display", "inline");
693			jQuery(this).parents(".cr-reviews-slider").slickk('setPosition');
694		} );
695		jQuery( '.cr-reviews-grid' ).on( 'click', '.cr-grid-read-more a', function (e) {
696			e.preventDefault();
697			let parent = jQuery(this).parents(".review-content");
698			if ( 0 === parent.length ) {
699				parent = jQuery(this).parents(".cr-grid-reply-content");
700			}
701			parent.find(".cr-grid-read-more").hide();
702			parent.find(".cr-grid-details").css("display", "inline");
703		} );
704		jQuery( '.cr-reviews-grid' ).on( 'click', '.cr-grid-read-less a', function (e) {
705			e.preventDefault();
706			let parent = jQuery(this).parents(".review-content");
707			if ( 0 === parent.length ) {
708				parent = jQuery(this).parents(".cr-grid-reply-content");
709			}
710			parent.find(".cr-grid-details").hide();
711			parent.find(".cr-grid-read-more").css("display", "inline");
712		} );
713		jQuery('.cr-qna-block .cr-qna-search-block .cr-qna-ask-button').on( 'click', function (e) {
714			e.preventDefault();
715			jQuery( this ).closest( '.cr-qna-block' ).addClass( 'cr-qna-new-q-form-open' );
716		} );
717		jQuery(".cr-qna-block .cr-qna-list-block").on( "click", ".cr-qna-ans-button", function (e) {
718			e.preventDefault();
719
720			let nameField = jQuery( this ).closest( '.cr-qna-block' ).find( ".cr-qna-new-q-form .cr-review-form-name" );
721			let nameValue = nameField.find( ".cr-review-form-txt" ).data("defval");
722			jQuery( this ).closest( '.cr-qna-list-q-b' ).find( ".cr-qna-list-inl-answ .cr-review-form-name .cr-review-form-txt" ).val( nameValue );
723
724			let emailField = jQuery( this ).closest( '.cr-qna-block' ).find( ".cr-qna-new-q-form .cr-review-form-email" );
725			let emailValue = emailField.find( ".cr-review-form-txt" ).data("defval");
726			jQuery( this ).closest( '.cr-qna-list-q-b' ).find( ".cr-qna-list-inl-answ .cr-review-form-email .cr-review-form-txt" ).val( emailValue );
727
728			jQuery( this ).closest( '.cr-qna-list-q-b' ).addClass( 'cr-qna-ans-form-open' );
729		} );
730		//show more questions and answers
731		jQuery(".cr-qna-block").on( "click", ".cr-show-more-que", function(t) {
732			t.preventDefault();
733			let qna_block = jQuery(this).parents(".cr-qna-block").eq(0);
734			let cr_product_id = jQuery(this).attr("data-product");
735			let cr_page = jQuery(this).attr("data-page");
736			let cr_attributes = qna_block.data("attributes");
737			let cr_search = qna_block.find(".cr-ajax-qna-search input").val();
738			let cr_permalink = jQuery(this).attr("data-permalink");
739			let cr_data = {
740				"action": "cr_show_more_qna",
741				"productID": cr_product_id,
742				"page": cr_page,
743				"permalink": cr_permalink,
744				"search": cr_search,
745				"cr_attributes": cr_attributes
746			};
747			qna_block.find(".cr-search-no-qna").hide();
748			jQuery(this).hide();
749			qna_block.find("#cr-show-more-q-spinner").show();
750			jQuery.post(cr_ajax_object.ajax_url, cr_data, function(response) {
751				jQuery(".cr-qna-block #cr-show-more-q-spinner").hide();
752				if(response.page >= 0){
753					jQuery(".cr-qna-block .cr-qna-list-block .cr-qna-list-block-inner").append(response.html);
754					jQuery(".cr-qna-block #cr-show-more-q-id").attr("data-page",response.page);
755					if(!response.last_page){
756						jQuery(".cr-qna-block #cr-show-more-q-id").show();
757					}
758				}
759				if(response.html === "" && response.page === 0){
760					jQuery(".cr-qna-block .cr-search-no-qna").show();
761				}
762			}, "json");
763		} );
764		//search questions and answers
765		jQuery(".cr-qna-block .cr-ajax-qna-search input").on("keyup", cr_keyup_delay(function(e) {
766			// do nothing if it's an arrow key
767			var code = (e.keyCode || e.which);
768			if(code == 37 || code == 38 || code == 39 || code == 40) {
769				return;
770			}
771			jQuery(".cr-qna-block #cr-show-more-q-id").attr("data-page", -1);
772			jQuery(".cr-qna-block .cr-qna-list-block .cr-qna-list-block-inner").empty();
773			jQuery(".cr-qna-block #cr-show-more-q-id").trigger("click");
774		}, 500));
775		jQuery(".cr-qna-block .cr-ajax-qna-search input").on("keyup", function(e){
776			//show clear icon
777			if(jQuery(this).val() !== "") {
778				jQuery(".cr-qna-block .cr-ajax-qna-search .cr-clear-input").css("display", "inline-block");
779			} else {
780				if(jQuery(this).val() === "") jQuery(".cr-qna-block .cr-ajax-qna-search .cr-clear-input").hide();
781			}
782		}).on("change", function(){
783			if(jQuery(this).val() === "") jQuery(".cr-qna-block .cr-ajax-qna-search .cr-clear-input").hide();
784		});
785		jQuery(".cr-qna-block .cr-ajax-qna-search .cr-clear-input").on("click", function () {
786			jQuery(this).prev("input").val("");
787			jQuery(".cr-qna-block .cr-ajax-qna-search .cr-clear-input").hide();
788			jQuery(".cr-qna-block #cr-show-more-q-id").attr("data-page", -1);
789			jQuery(".cr-qna-block .cr-qna-list-block .cr-qna-list-block-inner").empty();
790			jQuery(".cr-qna-block #cr-show-more-q-id").trigger("click");
791		});
792		//show QnA tab
793		jQuery("body").on("click", "a.cr-qna-link", function () {
794			const cr_qna_tab = jQuery( '.cr_qna_tab a' );
795			if( cr_qna_tab.length ) {
796				cr_qna_tab.trigger( "click" );
797			} else {
798				jQuery( '.cr-qna-block' ).parents( ':hidden' ).show();
799			}
800			return true;
801		});
802		// show Reviews tab
803		jQuery("body").on("click", ".cr-review-link", function () {
804			const wc_reviews_tab = jQuery( '.reviews_tab a' );
805			if( wc_reviews_tab.length ) {
806				wc_reviews_tab.trigger( "click" );
807				return true;
808			}
809		});
810
811		// upload images with a review
812		jQuery("#cr_review_image").on("change", function () {
813			jQuery(".cr-upload-images-status").removeClass("cr-upload-images-status-error");
814			jQuery(".cr-upload-images-status").text(cr_ajax_object.cr_upload_initial);
815			let allowedTypes = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif', 'video/mp4', 'video/mpeg', 'video/ogg', 'video/webm', 'video/quicktime', 'video/x-msvideo'];
816			let uploadFiles = jQuery("#cr_review_image");
817			let countFiles = uploadFiles[0].files.length;
818			let countUploaded = jQuery(".cr-upload-images-preview .cr-upload-images-containers").length;
819			let lastIndex = 1;
820			if(jQuery(this).attr("data-lastindex")) {
821				lastIndex = parseInt(jQuery(this).attr("data-lastindex"));
822			}
823			if( countFiles + countUploaded > cr_ajax_object.cr_images_upload_limit ) {
824				jQuery(".cr-upload-images-status").addClass("cr-upload-images-status-error");
825				jQuery(".cr-upload-images-status").text(cr_ajax_object.cr_upload_error_too_many);
826				jQuery(".cr-upload-images-preview .cr-upload-images-containers").not(".cr-upload-ok").remove();
827				uploadFiles.val("");
828				return;
829			}
830			for(let i = 0; i < countFiles; i++) {
831				if(!allowedTypes.includes(uploadFiles[0].files[i].type) ) {
832					jQuery(".cr-upload-images-status").addClass("cr-upload-images-status-error");
833					jQuery(".cr-upload-images-status").text(cr_ajax_object.cr_upload_error_file_type);
834					jQuery(".cr-upload-images-preview .cr-upload-images-containers").not(".cr-upload-ok").remove();
835					uploadFiles.val("");
836					return;
837				} else if(uploadFiles[0].files[i].size && uploadFiles[0].files[i].size > cr_ajax_object.cr_images_upload_max_size) {
838					jQuery(".cr-upload-images-status").addClass("cr-upload-images-status-error");
839					jQuery(".cr-upload-images-status").text(cr_ajax_object.cr_upload_error_file_size);
840					jQuery(".cr-upload-images-preview .cr-upload-images-containers").not(".cr-upload-ok").remove();
841					uploadFiles.val("");
842					return;
843				} else {
844					let container = jQuery("<div/>", {class:"cr-upload-images-containers cr-upload-images-container-" + (lastIndex + i)});
845					let progressBar = jQuery("<div/>", {class:"cr-upload-images-pbar"});
846					progressBar.append(
847						jQuery("<div/>", {class:"cr-upload-images-pbarin"})
848					);
849					if( -1 === uploadFiles[0].files[i].type.indexOf( 'image' ) ) {
850						container.append(
851							jQuery( "<svg class='cr-upload-video-thumbnail' viewBox='0 0 576 512'>
851<path d='M336.2 64H47.8C21.4 64 0 85.4 0 111.8v288.4C0 426.6 21.4 448 47.8 448h288.4c26.4 0 47.8-21.4 47.8-47.8V111.8c0-26.4-21.4-47.8-47.8-47.8zm189.4 37.7L416 177.3v157.4l109.6 75.5c21.2 14.6 50.4-.3 50.4-25.8V127.5c0-25.4-29.1-40.4-50.4-25.8z'></path></svg>" )
852						);
853					} else{
854						container.append(
855							jQuery("<img>", {class:"cr-upload-images-thumbnail",src:URL.createObjectURL(uploadFiles[0].files[i])})
856						);
857					}
858					container.append(
859						progressBar
860					);
861					let removeButton = jQuery("<button/>", {class:"cr-upload-images-delete"});
862					removeButton.append(
863						'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path class="cr-no-icon" d="M12.12 10l3.53 3.53-2.12 2.12L10 12.12l-3.54 3.54-2.12-2.12L7.88 10 4.34 6.46l2.12-2.12L10 7.88l3.54-3.53 2.12 2.12z"/></g></svg>'
864					);
865					container.append(
866						removeButton
867					);
868					container.append(
869						jQuery("<input>", {name:"cr-upload-images-ids[]",type:"hidden",value:""})
870					);
871					container.append(
872						jQuery("<span/>", {class:"cr-upload-images-delete-spinner"})
873					);
874					jQuery(".cr-upload-images-preview").append(container);
875				}
876			}
877
878			let filesToUpload = [];
879			for(let i = 0; i < countFiles; i++) {
880				filesToUpload.push(uploadFiles[0].files[i]);
881			}
882			const uploadField = jQuery(this);
883			const crUploadFiles = function( cr_captcha ) {
884				for(let i = 0; i < countFiles; i++) {
885					let formData = new FormData();
886					formData.append("action", "cr_upload_local_images_frontend");
887					formData.append("cr_nonce", uploadField.attr("data-nonce"));
888					formData.append("cr_postid", uploadField.attr("data-postid"));
889					formData.append("cr_file", filesToUpload[i]);
890					formData.append("cr_captcha", cr_captcha);
891					jQuery.ajax({
892						url: cr_ajax_object.ajax_url,
893						data: formData,
894						processData: false,
895						contentType: false,
896						dataType: "json",
897						type: "POST",
898						beforeSend: function() {
899						},
900						xhr: function() {
901							var myXhr = jQuery.ajaxSettings.xhr();
902							if ( myXhr.upload ) {
903								myXhr.upload.addEventListener( 'progress', function(e) {
904									if ( e.lengthComputable ) {
905										let perc = ( e.loaded / e.total ) * 100;
906										perc = perc.toFixed(0);
907										jQuery(".cr-upload-images-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i) + " .cr-upload-images-pbar .cr-upload-images-pbarin").width(perc + "%");
908									}
909								}, false );
910							}
911							return myXhr;
912						},
913						success: function(response) {
914							if(200 === response["code"]) {
915								let idkey = JSON.stringify({ id: response["attachment"]["id"], key: response["attachment"]["key"] });
916								jQuery(".cr-upload-images-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i) + " input").val(idkey);
917								jQuery(".cr-upload-images-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i)).addClass("cr-upload-ok");
918								jQuery(".cr-upload-images-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i) + " button").attr("data-delnonce",response["attachment"]["nonce"]);
919							} else if(500 <= response["code"]) {
920								jQuery(".cr-upload-images-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i)).remove();
921								jQuery(".cr-upload-images-status").addClass("cr-upload-images-status-error");
922								jQuery(".cr-upload-images-status").text(response["message"]);
923							}
924						}
925					});
926				}
927			};
928			if( crCaptchaEnabled() ) {
929				crCaptcha.consume( uploadField.closest( "form" ), crUploadFiles );
930			} else {
931				crUploadFiles( "" );
932			}
933			jQuery(this).attr("data-lastindex", lastIndex + countFiles);
934			uploadFiles.val("");
935		});
936
937		// delete uploaded image
938		jQuery(".cr-upload-images-preview").on("click", ".cr-upload-images-delete", function (e) {
939			e.preventDefault();
940			jQuery(".cr-upload-images-status").removeClass("cr-upload-images-status-error");
941			jQuery(".cr-upload-images-status").text(cr_ajax_object.cr_upload_initial);
942			let classList = jQuery(this).parent().eq(0).attr("class").split(/\s+/);
943			let classes = "";
944			jQuery.each(classList, function(index, item) {
945				classes += "." + item;
946			});
947			let ajaxData = {
948				"action": "cr_delete_local_images_frontend",
949				"cr_nonce": jQuery(this).attr("data-delnonce"),
950				"image": jQuery(this).parent().children("input").eq(0).val(),
951				"class": classes
952			}
953			jQuery(this).parent().addClass("cr-upload-delete-pending");
954			jQuery.post(cr_ajax_object.ajax_url, ajaxData, function(response) {
955				if(200 === response["code"] && response["class"]) {
956					jQuery(".cr-upload-images-preview " + response["class"]).remove();
957				}
958				jQuery(".cr-upload-images-preview " + response["class"]).removeClass("cr-upload-delete-pending");
959			}, "json");
960		});
961
962		// update star rating on an add-a-review form hover
963		jQuery( ".cr-review-form-rating .cr-review-form-rating-inner" ).on(
964			"mouseenter",
965			function() {
966				let rating = parseInt( jQuery( this ).data( "rating" ) );
967				let ratingActv = parseInt( jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-actv" ).data( "rating" ) );
968				if( isNaN( ratingActv ) ) {
969					ratingActv = 0;
970				}
971				for( r = 1; r < 6; r++ ) {
972					if( r > rating && r > ratingActv ) {
973						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-act" ).hide();
974						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-deact" ).show();
975					} else {
976						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-deact" ).hide();
977						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-act" ).show();
978					}
979				}
980				jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-nbr" ).text( rating + "/5" );
981			}
982		).on(
983			"mouseleave",
984			function() {
985				let ratingActv = parseInt( jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-actv" ).data( "rating" ) );
986				if( isNaN( ratingActv ) ) {
987					ratingActv = 0;
988				}
989				for( r = 1; r < 6; r++ ) {
990					if( r > ratingActv ) {
991						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-act" ).hide();
992						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-deact" ).show();
993					} else {
994						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-deact" ).hide();
995						jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-act" ).show();
996					}
997				}
998				jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-nbr" ).text( ratingActv + "/5" );
999			}
1000		);
1001
1002		// update star rating on an add-a-review form click
1003		jQuery( ".cr-review-form-rating .cr-review-form-rating-inner" ).on( "click", function( e ) {
1004			e.preventDefault();
1005			let rating = parseInt( jQuery( this ).data( "rating" ) );
1006			jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner" ).removeClass( "cr-review-form-rating-actv" );
1007			jQuery( this ).addClass( "cr-review-form-rating-actv" );
1008			for( r = 1; r < 6; r++ ) {
1009				if( r > rating ) {
1010					jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-act" ).hide();
1011					jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-deact" ).show();
1012				} else {
1013					jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-deact" ).hide();
1014					jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-inner[data-rating=" + r + "] .cr-rating-act" ).show();
1015				}
1016			}
1017			jQuery( this ).closest( ".cr-review-form-rating-cont" ).find( ".cr-review-form-rating-nbr" ).text( rating + "/5" );
1018			jQuery( this ).closest( ".cr-review-form-rating" ).find( ".cr-review-form-rating-inp" ).val( rating );
1019			jQuery( this ).closest( ".cr-review-form-rating" ).removeClass( "cr-review-form-error" );
1020		} );
1021
1022		// close the review form
1023		jQuery( ".cr-all-reviews-shortcode .cr-nav-left svg, .cr-all-reviews-shortcode .cr-nav-right svg, .cr-all-reviews-shortcode .cr-review-form-cancel" ).on( "click", function( e ) {
1024			jQuery( this ).closest( ".cr-all-reviews-shortcode" ).removeClass( "cr-all-reviews-new-review" );
1025			jQuery( this ).closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-res" );
1026			cr_reset_review_form( jQuery( this ) );
1027		} );
1028		jQuery( ".cr-all-reviews-shortcode .cr-review-form-wrap" ).on( "click", ".cr-review-form-success", function( e ) {
1029			jQuery( this ).closest( ".cr-all-reviews-shortcode" ).removeClass( "cr-all-reviews-new-review" );
1030			jQuery( this ).closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-res" );
1031			cr_reset_review_form( jQuery( this ) );
1032			// reload the page
1033			window.location.reload();
1034		} );
1035		jQuery( ".cr-review-form-wrap" ).on( "click", ".cr-review-form-error", function( e ) {
1036			jQuery( this ).closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-res" );
1037		} );
1038		jQuery( ".cr-ajax-reviews-review-form .cr-nav-left svg, .cr-ajax-reviews-review-form .cr-nav-right svg, .cr-ajax-reviews-review-form .cr-review-form-cancel" ).on( "click", function( e ) {
1039			jQuery(this).closest(".cr-reviews-ajax-reviews").find(".cr-reviews-ajax-comments").show();
1040			jQuery(this).closest(".cr-reviews-ajax-reviews").find(".cr-ajax-reviews-review-form").hide();
1041			jQuery( this ).closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-res" );
1042			cr_reset_review_form( jQuery( this ) );
1043		} );
1044		jQuery( ".cr-ajax-reviews-review-form .cr-review-form-wrap" ).on( "click", ".cr-review-form-success", function( e ) {
1045			jQuery(this).closest(".cr-reviews-ajax-reviews").find(".cr-reviews-ajax-comments").show();
1046			jQuery(this).closest(".cr-reviews-ajax-reviews").find(".cr-ajax-reviews-review-form").hide();
1047			jQuery( this ).closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-res" );
1048			cr_reset_review_form( jQuery( this ) );
1049			// reload the page
1050			if ( window.location.hash !== '#reviews' ) {
1051				window.location.href = window.location.pathname + '#reviews';
1052			}
1053			window.location.reload();
1054		} );
1055		jQuery( ".cr-reviews-grid .cr-nav-left svg, .cr-reviews-grid .cr-nav-right svg, .cr-reviews-grid .cr-review-form-cancel" ).on( "click", function( e ) {
1056			jQuery( this ).closest( ".cr-reviews-grid" ).removeClass( "cr-reviews-grid-new-review" );
1057			jQuery( this ).closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-res" );
1058			cr_reset_review_form( jQuery( this ) );
1059		} );
1060		jQuery( ".cr-reviews-grid .cr-review-form-wrap" ).on( "click", ".cr-review-form-success", function( e ) {
1061			jQuery( this ).closest( ".cr-reviews-grid" ).removeClass( "cr-reviews-grid-new-review" );
1062			jQuery( this ).closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-res" );
1063			cr_reset_review_form( jQuery( this ) );
1064			// reload the page
1065			window.location.reload();
1066		} );
1067		// close the qna form
1068		jQuery( ".cr-qna-block" ).on( "click", ".cr-qna-new-q-form .cr-nav-left svg, .cr-qna-new-q-form .cr-nav-right svg, .cr-qna-new-q-form .cr-review-form-cancel", function( e ) {
1069			jQuery( this ).closest( ".cr-qna-block" ).removeClass( "cr-qna-new-q-form-open" );
1070			jQuery( this ).closest( ".cr-qna-new-q-form" ).removeClass( "cr-review-form-res" );
1071			cr_reset_qna_form( jQuery( this ) );
1072		} );
1073		jQuery( ".cr-qna-block" ).on( "click", ".cr-qna-new-q-form .cr-review-form-success", function( e ) {
1074			jQuery( this ).closest( ".cr-qna-block" ).removeClass( "cr-qna-new-q-form-open" );
1075			jQuery( this ).closest( ".cr-qna-new-q-form" ).removeClass( "cr-review-form-res" );
1076			cr_reset_qna_form( jQuery( this ) );
1077		} );
1078		jQuery( ".cr-qna-block" ).on( "click", ".cr-qna-new-q-form .cr-review-form-error", function( e ) {
1079			jQuery( this ).closest( ".cr-qna-new-q-form" ).removeClass( "cr-review-form-res" );
1080		} );
1081		jQuery( ".cr-qna-block" ).on( "click", ".cr-qna-list-inl-answ .cr-nav-left svg, .cr-qna-list-inl-answ .cr-nav-right svg, .cr-qna-list-inl-answ .cr-review-form-cancel", function( e ) {
1082			jQuery( this ).closest( ".cr-qna-list-q-b" ).removeClass( "cr-qna-ans-form-open" );
1083			jQuery( this ).closest( ".cr-qna-list-inl-answ" ).removeClass( "cr-review-form-res" );
1084			cr_reset_ans_form( jQuery( this ) );
1085		} );
1086		jQuery( ".cr-qna-block" ).on( "click", ".cr-qna-list-inl-answ .cr-review-form-success", function( e ) {
1087			jQuery( this ).closest( ".cr-qna-list-q-b" ).removeClass( "cr-qna-ans-form-open" );
1088			jQuery( this ).closest( ".cr-qna-list-inl-answ" ).removeClass( "cr-review-form-res" );
1089			cr_reset_ans_form( jQuery( this ) );
1090		} );
1091		jQuery( ".cr-qna-block" ).on( "click", ".cr-qna-list-inl-answ .cr-review-form-error", function( e ) {
1092			jQuery( this ).closest( ".cr-qna-list-inl-answ" ).removeClass( "cr-review-form-res" );
1093		} );
1094
1095		// submit the review form
1096		jQuery( ".cr-review-form-wrap .cr-review-form-submit" ).on( "click", function( e ) {
1097			// check if media upload is in progress
1098			if ( 0 < jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-form-item-media-preview .cr-upload-images-containers:not(.cr-upload-ok)" ).length ) {
1099				return false;
1100			}
1101			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating" ).removeClass( "cr-review-form-error" );
1102			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-comment" ).removeClass( "cr-review-form-error" );
1103			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-name" ).removeClass( "cr-review-form-error" );
1104			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-email" ).removeClass( "cr-review-form-error" );
1105			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-onsite-question" ).removeClass( "cr-review-form-error" );
1106			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-form-item-media" ).removeClass( "cr-review-form-error" );
1107			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-captcha" ).removeClass( "cr-review-form-error" );
1108			jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-terms" ).removeClass( "cr-review-form-error" );
1109			if( cr_validate_review_form( jQuery( this ) ) ) {
1110				// add custom onsite questions and ratings to the ajax call
1111				let onsiteQuestions = {};
1112				jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating input[type='hidden']" ).each(
1113					function() {
1114						onsiteQuestions[jQuery( this ).attr( 'name' )] = jQuery( this ).val();
1115					}
1116				)
1117				jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-onsite-question input" ).each(
1118					function() {
1119						onsiteQuestions[jQuery( this ).attr( 'name' )] = jQuery( this ).val();
1120					}
1121				)
1122				// submit the form if the validation is successful
1123				let cr_data = {
1124					"action": "cr_submit_review",
1125					"rating": jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating-overall .cr-review-form-rating-inp" ).val(),
1126					"review": jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-comment-txt" ).val().trim(),
1127					"name": jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-name .cr-review-form-txt" ).val().trim(),
1128					"id": jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-item-id" ).val(),
1129					"email": jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-email .cr-review-form-txt" ).val().trim(),
1130					"onsiteQuestions": onsiteQuestions,
1131					"cr-upload-images-ids": jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-form-item-media .cr-upload-images-containers input" ).map( function() {
1132						return jQuery( this ).val();
1133					} ).get()
1134				};
1135				jQuery( this ).closest( ".cr-review-form-wrap" ).addClass( "cr-review-form-submitting" );
1136				jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-continue" ).removeClass( "cr-review-form-success" );
1137				jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-continue" ).removeClass( "cr-review-form-error" );
1138				//
1139				const postReview = ( token, data, ref ) => {
1140					data.cr_captcha_response = token;
1141					jQuery.post(
1142						{
1143							url: cr_ajax_object.ajax_url,
1144							data: data,
1145							context: jQuery( ref ),
1146							success: function( response ) {
1147								if ( ! Object.hasOwn( response, 'button' ) ) {
1148									response.button = 'OK';
1149								}
1150								if ( ! Object.hasOwn( response, 'description' ) ) {
1151									response.description = 'An unexpected error that could be caused by a third-party plugin';
1152								}
1153								this.closest( ".cr-review-form-wrap" ).removeClass( "cr-review-form-submitting" );
1154								this.closest( ".cr-review-form-wrap" ).addClass( "cr-review-form-res" );
1155								this.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-result span" ).html( response.description );
1156								this.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-continue" ).html( response.button );
1157								if( 0 === response.code ) {
1158									this.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-continue" ).addClass( "cr-review-form-success" );
1159								} else {
1160									this.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-continue" ).addClass( "cr-review-form-error" );
1161								}
1162							},
1163							dataType: "json"
1164						}
1165					);
1166				};
1167				//
1168				const reviewForm = jQuery( this ).closest( ".cr-review-form-wrap" );
1169				const submitRef = this;
1170				if ( crCaptchaEnabled() ) {
1171					crCaptcha.execute( reviewForm, function( token ) {
1172						postReview( token, cr_data, submitRef );
1173					} );
1174				} else {
1175					postReview( '', cr_data, submitRef );
1176				}
1177			};
1178		} );
1179
1180		// submit a new question
1181		jQuery( ".cr-qna-block .cr-qna-new-q-form" ).on( "click", ".cr-review-form-submit", function( e ) {
1182			jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-comment" ).removeClass( "cr-review-form-error" );
1183			jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-name" ).removeClass( "cr-review-form-error" );
1184			jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-email" ).removeClass( "cr-review-form-error" );
1185			jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-terms" ).removeClass( "cr-review-form-error" );
1186			if( cr_validate_qna( jQuery( this ) ) ) {
1187				// submit the form if the validation is successful
1188				let cr_data = {
1189					"action": "cr_new_qna",
1190					"crNonce": jQuery( this ).closest( ".cr-qna-block" ).data( "nonce" ),
1191					"currentPostID": jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-item-id" ).val(),
1192					"text": jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-comment-txt" ).val().trim(),
1193					"name": jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-name .cr-review-form-txt" ).val().trim(),
1194					"email": jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-email .cr-review-form-txt" ).val().trim()
1195				};
1196				jQuery( this ).closest( ".cr-qna-new-q-form" ).addClass( "cr-review-form-submitting" );
1197				jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-continue" ).removeClass( "cr-review-form-success" );
1198				jQuery( this ).closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-continue" ).removeClass( "cr-review-form-error" );
1199				//
1200				const postQuestion = ( token, data, ref ) => {
1201					data.cptcha = token;
1202					jQuery.post(
1203						{
1204							url: cr_ajax_object.ajax_url,
1205							data: data,
1206							context: jQuery( ref ),
1207							success: function( response ) {
1208								this.closest( ".cr-qna-new-q-form" ).removeClass( "cr-review-form-submitting" );
1209								this.closest( ".cr-qna-new-q-form" ).addClass( "cr-review-form-res" );
1210								this.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-result span" ).html( response.description );
1211								this.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-continue" ).html( response.button );
1212								if( 0 === response.code ) {
1213									this.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-continue" ).addClass( "cr-review-form-success" );
1214								} else {
1215									this.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-continue" ).addClass( "cr-review-form-error" );
1216								}
1217							},
1218							dataType: "json"
1219						}
1220					);
1221				};
1222				//
1223				let cr_cptcha = jQuery(this).attr("data-crcptcha");
1224				var rf = this;
1225				if ( cr_cptcha && cr_cptcha.length > 0 ) {
1226					grecaptcha.ready(function() {
1227						grecaptcha.execute( cr_cptcha, {action: 'submit'} ).then( function(token) {
1228							postQuestion( token, cr_data, rf )
1229						} );
1230					} );
1231				} else {
1232					postQuestion( '', cr_data, rf );
1233				}
1234			};
1235		} );
1236
1237		// submit a new answer
1238		jQuery( ".cr-qna-block" ).on( "click", ".cr-qna-list-inl-answ .cr-review-form-submit", function( e ) {
1239			jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-comment" ).removeClass( "cr-review-form-error" );
1240			jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-name" ).removeClass( "cr-review-form-error" );
1241			jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-email" ).removeClass( "cr-review-form-error" );
1242			jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-terms" ).removeClass( "cr-review-form-error" );
1243			if( cr_validate_ans( jQuery( this ) ) ) {
1244				// submit the form if the validation is successful
1245				let cr_data = {
1246					"action": "cr_new_qna",
1247					"crNonce": jQuery( this ).closest( ".cr-qna-block" ).data( "nonce" ),
1248					"currentPostID": jQuery( this ).closest( ".cr-qna-block" ).find( ".cr-review-form-item-id" ).val(),
1249					"questionID": jQuery( this ).closest( ".cr-qna-list-q-b" ).data( "question" ),
1250					"productID": jQuery( this ).closest( ".cr-qna-list-q-b" ).data( "post" ),
1251					"text": jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-comment-txt" ).val().trim(),
1252					"name": jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-name .cr-review-form-txt" ).val().trim(),
1253					"email": jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-email .cr-review-form-txt" ).val().trim()
1254				};
1255				jQuery( this ).closest( ".cr-qna-list-inl-answ" ).addClass( "cr-review-form-submitting" );
1256				jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-continue" ).removeClass( "cr-review-form-success" );
1257				jQuery( this ).closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-continue" ).removeClass( "cr-review-form-error" );
1258				//
1259				const postQuestion = ( token, data, ref ) => {
1260					data.cptcha = token;
1261					jQuery.post(
1262						{
1263							url: cr_ajax_object.ajax_url,
1264							data: data,
1265							context: jQuery( ref ),
1266							success: function( response ) {
1267								this.closest( ".cr-qna-list-inl-answ" ).removeClass( "cr-review-form-submitting" );
1268								this.closest( ".cr-qna-list-inl-answ" ).addClass( "cr-review-form-res" );
1269								this.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-result span" ).html( response.description );
1270								this.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-continue" ).html( response.button );
1271								if( 0 === response.code ) {
1272									this.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-continue" ).addClass( "cr-review-form-success" );
1273								} else {
1274									this.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-continue" ).addClass( "cr-review-form-error" );
1275								}
1276							},
1277							dataType: "json"
1278						}
1279					);
1280				};
1281				//
1282				let cr_cptcha = jQuery(this).attr("data-crcptcha");
1283				var rf = this;
1284				if ( cr_cptcha && cr_cptcha.length > 0 && grecaptcha ) {
1285					grecaptcha.ready(function() {
1286						grecaptcha.execute( cr_cptcha, {action: 'submit'} ).then( function(token) {
1287							postQuestion( token, cr_data, rf )
1288						} );
1289					} );
1290				} else {
1291					postQuestion( '', cr_data, rf );
1292				}
1293			};
1294		} );
1295
1296		// validate custom questions and ratings on submission of a review form on a product page
1297		jQuery( ".cr-single-product-review" ).on( "click", ".cr-single-product-rev-submit", function(t) {
1298			let validationResult = true;
1299			let reviewForm = jQuery( this ).closest( ".cr-single-product-review" );
1300
1301			// validate ratings
1302			reviewForm.find( ".cr-review-form-rating-cont.cr-review-form-rating-req" ).each( function( index ) {
1303				if( 1 > jQuery( this ).find( ".cr-review-form-rating-actv" ).length ) {
1304					jQuery( this ).closest( ".cr-review-form-rating" ).addClass( "cr-review-form-error" );
1305					validationResult = false;
1306				}
1307			} );
1308
1309			// validate custom questions
1310			reviewForm.find( ".cr-onsite-question.cr-review-form-que-req" ).each( function( index ) {
1311				if( 1 > jQuery( this ).find( "input[type=text]" ).val().trim().length ) {
1312					jQuery( this ).closest( ".cr-onsite-question" ).addClass( "cr-review-form-error" );
1313					validationResult = false;
1314				} else {
1315					jQuery( this ).closest( ".cr-onsite-question" ).removeClass( "cr-review-form-error" );
1316				}
1317			} );
1318
1319			// validate the comment field
1320			reviewForm.find( ".cr-review-form-textbox" ).each( function( index ) {
1321				if( 1 > jQuery( this ).val().trim().length ) {
1322					jQuery( this ).addClass( "cr-review-form-error" );
1323					validationResult = false;
1324				} else {
1325					jQuery( this ).removeClass( "cr-review-form-error" );
1326				}
1327			} );
1328
1329			// validate the terms checkbox
1330			if ( 0 < reviewForm.find( '.cr-review-form-terms' ).length ) {
1331				if ( ! reviewForm.find( '.cr-review-form-terms .cr-review-form-checkbox' ).is(':checked') ) {
1332					alert( 'Please tick the checkbox to proceed' );
1333					validationResult = false;
1334				}
1335			}
1336
1337			if( ! validationResult ) {
1338				t.preventDefault();
1339			}
1340		} );
1341
1342		// open the review form
1343		jQuery( ".cr-all-reviews-add-review" ).on( "click", function(t) {
1344			t.preventDefault();
1345			if ( 0 < jQuery( this ).closest( ".cr-all-reviews-shortcode" ).length ) {
1346				jQuery( this ).closest( ".cr-all-reviews-shortcode" ).addClass( "cr-all-reviews-new-review" );
1347			}
1348			if ( 0 < jQuery( this ).closest( ".cr-reviews-grid" ).length ) {
1349				jQuery( this ).closest( ".cr-reviews-grid" ).addClass( "cr-reviews-grid-new-review" );
1350			}
1351		} );
1352
1353		// upload media trigger
1354		jQuery( ".cr-review-form-wrap .cr-form-item-media-none" ).on( "click", function( t ) {
1355			jQuery( this ).parent().find( "input.cr-form-item-media-file" ).trigger( "click" );
1356		} );
1357		jQuery( ".cr-review-form-wrap .cr-form-item-media-none" ).on( "keydown", function( e ) {
1358			if ( "Enter" === e.key || " " === e.key ) {
1359				e.preventDefault();
1360				jQuery( this ).trigger( "click" );
1361			}
1362		} );
1363
1364		// upload media trigger
1365		jQuery( ".cr-review-form-wrap .cr-form-item-media-preview" ).on( "click", ".cr-form-item-media-add", function( t ) {
1366			jQuery( this ).parents( ".cr-form-item-media" ).find( "input.cr-form-item-media-file" ).trigger( "click" );
1367		} );
1368
1369		// upload media
1370		jQuery( ".cr-review-form-wrap .cr-form-item-media .cr-form-item-media-file" ).on( "change", function () {
1371			let allowedTypes = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif', 'video/mp4', 'video/mpeg', 'video/ogg', 'video/webm', 'video/quicktime', 'video/x-msvideo'],
1372			uploadFiles = jQuery( this ),
1373			countFiles = uploadFiles[0].files.length,
1374			lastIndex = 1,
1375			mediaPreview = jQuery( this ).parent().find( ".cr-form-item-media-preview" ),
1376			countUploaded = mediaPreview.children( ".cr-upload-images-containers" ).length;
1377			jQuery(this).closest(".cr-form-item-media").removeClass("cr-review-form-error");
1378			if( jQuery(this).attr("data-lastindex") ) {
1379				lastIndex = parseInt( jQuery( this ).attr( "data-lastindex" ) );
1380			}
1381			if( countFiles + countUploaded > cr_ajax_object.cr_images_upload_limit ) {
1382				jQuery(this).closest(".cr-form-item-media").addClass("cr-review-form-error");
1383				jQuery(this).closest(".cr-form-item-media").find(".cr-review-form-field-error").text(cr_ajax_object.cr_upload_error_too_many);
1384				uploadFiles.val("");
1385				return;
1386			}
1387			for(let i = 0; i < countFiles; i++) {
1388				if(!allowedTypes.includes(uploadFiles[0].files[i].type) ) {
1389					jQuery(this).closest(".cr-form-item-media").addClass("cr-review-form-error");
1390					jQuery(this).closest(".cr-form-item-media").find(".cr-review-form-field-error").text(cr_ajax_object.cr_upload_error_file_type);
1391					uploadFiles.val("");
1392					return;
1393				} else if( uploadFiles[0].files[i].size && uploadFiles[0].files[i].size > cr_ajax_object.cr_images_upload_max_size * 100 ) {
1394					jQuery(this).closest(".cr-form-item-media").addClass("cr-review-form-error");
1395					jQuery(this).closest(".cr-form-item-media").find(".cr-review-form-field-error").text(cr_ajax_object.cr_upload_error_file_size);
1396					uploadFiles.val("");
1397					return;
1398				} else {
1399					let container = jQuery( "<div/>", {class:"cr-upload-images-containers cr-upload-images-container-" + (lastIndex + i)} );
1400					let progressBar = jQuery( "<div/>", {class:"cr-upload-images-pbar"} );
1401					progressBar.append(
1402						jQuery( "<div/>", {class:"cr-upload-images-pbarin"} )
1403					);
1404					if( -1 === uploadFiles[0].files[i].type.indexOf( 'image' ) ) {
1405						container.append(
1406							jQuery( "<svg class='cr-upload-video-thumbnail' viewBox='0 0 576 512'>
1406<path d='M336.2 64H47.8C21.4 64 0 85.4 0 111.8v288.4C0 426.6 21.4 448 47.8 448h288.4c26.4 0 47.8-21.4 47.8-47.8V111.8c0-26.4-21.4-47.8-47.8-47.8zm189.4 37.7L416 177.3v157.4l109.6 75.5c21.2 14.6 50.4-.3 50.4-25.8V127.5c0-25.4-29.1-40.4-50.4-25.8z'></path></svg>" )
1407						);
1408					} else {
1409						container.append(
1410							jQuery( "<img>", {class:"cr-upload-images-thumbnail", src:URL.createObjectURL(uploadFiles[0].files[i])} )
1411						);
1412					}
1413					container.append(
1414						progressBar
1415					);
1416					let removeButton = jQuery( "<button/>", {class:"cr-upload-images-delete"} );
1417					removeButton.append(
1418						'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><rect x="0" fill="none" width="20" height="20"/><g><path class="cr-no-icon" d="M12.12 10l3.53 3.53-2.12 2.12L10 12.12l-3.54 3.54-2.12-2.12L7.88 10 4.34 6.46l2.12-2.12L10 7.88l3.54-3.53 2.12 2.12z"/></g></svg>'
1419					);
1420					container.append(
1421						removeButton
1422					);
1423					container.append(
1424						jQuery( "<input>", {name:"cr-upload-images-ids[]",type:"hidden",value:""} )
1425					);
1426					container.append(
1427						jQuery( "<span/>", {class:"cr-upload-images-delete-spinner"} )
1428					);
1429					mediaPreview.find( ".cr-form-item-media-add" ).remove();
1430					mediaPreview.append( container );
1431					if( countFiles + countUploaded < cr_ajax_object.cr_images_upload_limit ) {
1432						mediaPreview.append(
1433							jQuery( "<div class='cr-form-item-media-add'>+</div>" )
1434						);
1435					}
1436				}
1437			}
1438			if( 0 < mediaPreview.children( ".cr-upload-images-containers" ).length && ! mediaPreview.hasClass( "cr-form-visible" ) ) {
1439				mediaPreview.parents( ".cr-form-item-subcontainer" ).addClass( "cr-form-visible" );
1440			}
1441			for(let i = 0; i < countFiles; i++) {
1442				let formData = new FormData();
1443				formData.append( "action", "cr_upload_media" );
1444				formData.append( "cr_file", uploadFiles[0].files[i] );
1445				formData.append( "cr_item", jQuery( this ).closest( ".cr-review-form-wrap" ).find( ".cr-review-form-item-id" ).val() );
1446				formData.append( "cr_nonce", jQuery( this ).closest( ".cr-review-form-wrap" ).data( "nonce" ) );
1447				var currentFileInput = jQuery( this );
1448				jQuery.ajax({
1449					url: cr_ajax_object.ajax_url,
1450					data: formData,
1451					processData: false,
1452					contentType: false,
1453					dataType: "json",
1454					type: "POST",
1455					context: this,
1456					beforeSend: function() {
1457					},
1458					xhr: function() {
1459						var myXhr = jQuery.ajaxSettings.xhr();
1460						if ( myXhr.upload ) {
1461							myXhr.upload.addEventListener( 'progress', function(e) {
1462								if ( e.lengthComputable ) {
1463									let perc = ( e.loaded / e.total ) * 100;
1464									perc = perc.toFixed(0);
1465									currentFileInput.parent().find( ".cr-form-item-media-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i) + " .cr-upload-images-pbar .cr-upload-images-pbarin" ).width(perc + "%");
1466								}
1467							}, false );
1468						}
1469						return myXhr;
1470					},
1471					success: function(response) {
1472						if(200 === response["code"]) {
1473							let idkey = JSON.stringify( { "id": response["attachment"]["id"], "key": response["attachment"]["key"] } );
1474							currentFileInput.parent().find( ".cr-form-item-media-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i) + " input").val(idkey);
1475							currentFileInput.parent().find( ".cr-form-item-media-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i)).addClass("cr-upload-ok");
1476						} else if(500 <= response["code"]) {
1477							currentFileInput.parent().find( ".cr-form-item-media-preview .cr-upload-images-containers.cr-upload-images-container-" + (lastIndex + i)).remove();
1478							let mediaPreview = jQuery(this).closest(".cr-form-item-media").find(".cr-form-item-media-preview");
1479							let countUploaded = mediaPreview.find( ".cr-upload-images-containers" ).length;
1480							if( 0 < countUploaded ) {
1481								if( 0 === mediaPreview.children( ".cr-form-item-media-add" ).length ) {
1482									mediaPreview.append(
1483										jQuery( "<div class='cr-form-item-media-add'>+</div>" )
1484									);
1485								}
1486							} else {
1487								mediaPreview.removeClass( "cr-form-visible" );
1488								mediaPreview.parents( ".cr-form-item-subcontainer" ).removeClass( "cr-form-visible" );
1489							}
1490							jQuery(this).closest(".cr-form-item-media").addClass("cr-review-form-error");
1491							jQuery(this).closest(".cr-form-item-media").find(".cr-review-form-field-error").text(response["message"]);
1492						}
1493					}
1494				});
1495			}
1496			jQuery(this).attr("data-lastindex", lastIndex + countFiles);
1497			uploadFiles.val("");
1498		} );
1499
1500		// delete uploaded image
1501		jQuery(".cr-review-form-wrap .cr-form-item-media-preview").on("click", ".cr-upload-images-delete", function (e) {
1502			e.preventDefault();
1503			let imgContainer = jQuery(this).parent(),
1504			mediaPreview = imgContainer.parent();
1505			let ajaxData = {
1506				"action": "cr_delete_media",
1507				"image": jQuery( this ).parent().children( "input" ).eq( 0 ).val()
1508			}
1509			imgContainer.addClass( "cr-upload-delete-pending" );
1510			jQuery.post( cr_ajax_object.ajax_url, ajaxData, function(response) {
1511				imgContainer.removeClass( "cr-upload-delete-pending" );
1512				if( 200 === response["code"] ) {
1513					imgContainer.remove();
1514					let countUploaded = mediaPreview.children( ".cr-upload-images-containers" ).length;
1515					if( 0 < countUploaded ) {
1516						if( 0 === mediaPreview.children( ".cr-form-item-media-add" ).length ) {
1517							mediaPreview.append(
1518								jQuery( "<div class='cr-form-item-media-add'>+</div>" )
1519							);
1520						}
1521					} else {
1522						mediaPreview.removeClass( "cr-form-visible" );
1523						mediaPreview.parents( ".cr-form-item-subcontainer" ).removeClass( "cr-form-visible" );
1524					}
1525				}
1526			}, "json" );
1527		} );
1528
1529		cr_maybe_download_media_frontend();
1530
1531		if( "object" === typeof elementorFrontend && "hooks" in elementorFrontend ) {
1532			elementorFrontend.hooks.addAction( "frontend/element_ready/widget", function( $scope ) {
1533				if( -1 !== $scope.data( "widget_type" ).indexOf( "shortcode" ) ) {
1534					if( 0 < $scope.find( ".cr-reviews-grid-inner" ).length ) {
1535						crResizeAllGridItems();
1536					}
1537				}
1538			} );
1539		}
1540
1541	} );
1542
1543	const crValidateEmail = (email) => {
1544		return email.match(
1545			/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
1546		);
1547	};
1548
1549	function initVoteClick(sel1, sel2, action) {
1550		jQuery(sel1).on("click", sel2, function(e) {
1551			e.preventDefault();
1552
1553			let reviewIDhtml = jQuery(this).data("vote");
1554			let parent = jQuery(this).parents(".cr-voting-cont-uni");
1555
1556			if(reviewIDhtml != null) {
1557				let reviewID = reviewIDhtml;
1558				let data = {
1559					"action": action,
1560					"reviewID": reviewID,
1561					"upvote": jQuery(this).data("upvote")
1562				};
1563
1564				parent.find(".cr-voting-a").removeClass("cr-voting-active");
1565				parent.find(".cr-voting-a").addClass("cr-voting-update");
1566				jQuery.post(cr_ajax_object.ajax_url, data, function(response) {
1567					parent.find(".cr-voting-a").removeClass("cr-voting-update");
1568					if( response.code === 0 ) {
1569						if( response.votes ) {
1570							parent.find(".cr-voting-upvote-count").text("(" +  response.votes.upvotes + ")");
1571							parent.find(".cr-voting-downvote-count").text("(" +  response.votes.downvotes + ")");
1572						}
1573						if( 0 !== response.votes.current ) {
1574							if( 0 < response.votes.current ) {
1575								parent.find(".cr-voting-upvote").addClass("cr-voting-active");
1576							} else {
1577								parent.find(".cr-voting-downvote").addClass("cr-voting-active");
1578							}
1579						}
1580					}
1581				}, "json");
1582			}
1583		});
1584	}
1585
1586	function cr_keyup_delay(fn, ms) {
1587		let timer = 0;
1588		return function(...args) {
1589			clearTimeout(timer);
1590			timer = setTimeout(fn.bind(this, ...args), ms || 0);
1591		};
1592	}
1593
1594	function cr_filter_all_reviews( refElement, show_more = false ) {
1595		let attributes = refElement.parents(".cr-all-reviews-shortcode").data("attributes"),
1596		cr_rating = refElement.parents(".cr-all-reviews-shortcode").find(".ivole-summaryBox .ivole-histogramRow.ivole-histogramRow-s .cr-histogram-a").attr("data-rating"),
1597		cr_search = refElement.parents(".cr-all-reviews-shortcode").find(".cr-ajax-search input").val(),
1598		cr_sort = refElement.parents(".cr-all-reviews-shortcode").find(".cr-ajax-reviews-sort").children("option:selected").val();
1599		let cr_tags = [];
1600		refElement.parents(".cr-all-reviews-shortcode").find(".cr-review-tags-filter .cr-tags-filter.cr-tag-selected").each(
1601			function() {
1602				cr_tags.push( jQuery(this).attr("data-crtagid") );
1603			}
1604		);
1605		let cr_media = refElement.parents(".cr-all-reviews-shortcode").find(".cr-review-tags-filter .cr-media-pill.cr-tag-selected").length ? 1 : 0;
1606		let cr_data = {
1607			"action": "cr_show_more_all_reviews",
1608			"attributes": attributes,
1609			"rating": cr_rating,
1610			"page": 0,
1611			"search": cr_search,
1612			"sort": cr_sort,
1613			"tags": cr_tags,
1614			"media": cr_media
1615		};
1616		//
1617		if( show_more ) {
1618			cr_data.page = refElement.data( "page" );
1619			// click on 'show more' button
1620			jQuery(".cr-search-no-reviews").hide();
1621			jQuery('.cr-show-more-button').hide();
1622
1623			// dim the list of comments when dealing with the pagination
1624			if ( refElement.hasClass( "cr-page-numbers-a" ) ) {
1625				refElement.closest( ".cr-all-reviews-shortcode" ).find( ".commentlist" ).addClass( "cr-pagination-load" );
1626				refElement.closest( ".cr-all-reviews-shortcode" ).find( ".cr-all-reviews-pagination" ).addClass( "cr-pagination-load" );
1627			} else {
1628				refElement.closest( ".cr-all-reviews-shortcode" ).find( ".cr-show-more-review-spinner" ).show();
1629			}
1630
1631			jQuery.post(
1632				{
1633					url: cr_ajax_object.ajax_url,
1634					data: cr_data,
1635					context: refElement,
1636					success: function(response) {
1637						let shcode = jQuery(this).closest( ".cr-all-reviews-shortcode" );
1638						shcode.find( ".cr-show-more-review-spinner" ).hide();
1639						if( response.html !== "" ) {
1640							if ( jQuery(this).hasClass( "cr-page-numbers-a" ) ) {
1641								shcode.find(".commentlist").find("*").not(".cr-pagination-review-spinner-li").not(".cr-pagination-review-spinner").remove();
1642								shcode.find(".commentlist").prepend(response.html);
1643							} else {
1644								shcode.find(".commentlist").append(response.html);
1645							}
1646							if( ! response.last_page ) {
1647								shcode.find(".cr-show-more-button").text( response.show_more_label );
1648								shcode.find(".cr-show-more-button").show();
1649							}
1650							shcode.find(".cr-show-more-button").data( "page", response.page );
1651							shcode.find(".cr-count-row .cr-count-row-count").html( response.count_row );
1652							if ( response.pagination !== "" ) {
1653								shcode.find(".cr-all-reviews-pagination").html(response.pagination);
1654							}
1655						} else {
1656							shcode.find(".cr-show-more-button").hide();
1657						}
1658						if( response.html == "" && response.page === 1 ){
1659							shcode.find( ".cr-search-no-reviews" ).show();
1660						}
1661						shcode.find( ".commentlist" ).removeClass( "cr-pagination-load" );
1662						shcode.find( ".cr-all-reviews-pagination" ).removeClass( "cr-pagination-load" );
1663					},
1664					dataType: "json"
1665				}
1666			);
1667		} else {
1668			// click on 'search' button
1669			refElement.closest(".cr-all-reviews-shortcode").find(".cr-search-no-reviews").hide();
1670			refElement.closest(".cr-all-reviews-shortcode").find(".cr-show-more-button").hide();
1671			refElement.closest(".cr-all-reviews-shortcode").find(".commentlist").hide();
1672			refElement.closest(".cr-all-reviews-shortcode").find(".cr-show-more-review-spinner").show();
1673			refElement.closest(".cr-all-reviews-shortcode").find(".ivole-summaryBox").addClass("cr-summaryBar-updating");
1674			refElement.closest(".cr-all-reviews-shortcode").find(".cr-seeAllReviews").addClass("cr-seeAll-updating");
1675			refElement.closest(".cr-all-reviews-shortcode").find(".cr-ajax-reviews-sort").addClass("cr-sort-updating");
1676			refElement.closest(".cr-all-reviews-shortcode").find(".cr-review-tags-filter").addClass("cr-tags-updating");
1677			refElement.closest(".cr-all-reviews-shortcode").find(".cr-all-reviews-pagination").hide();
1678			jQuery.post(
1679				{
1680					url: cr_ajax_object.ajax_url,
1681					data: cr_data,
1682					context: refElement,
1683					success: function(response) {
1684						let shcode = jQuery(this).closest( ".cr-all-reviews-shortcode" );
1685						shcode.find( ".cr-show-more-review-spinner" ).hide();
1686						shcode.find(".ivole-summaryBox").removeClass("cr-summaryBar-updating");
1687						shcode.find(".cr-seeAllReviews").removeClass("cr-seeAll-updating");
1688						shcode.find(".cr-ajax-reviews-sort").removeClass("cr-sort-updating");
1689						shcode.find(".cr-review-tags-filter").removeClass("cr-tags-updating");
1690						if(response.html !== ""){
1691							shcode.find(".commentlist").empty();
1692							shcode.find(".commentlist").append(response.html);
1693							shcode.find(".commentlist").show();
1694							shcode.find(".cr-show-more-button").data("page",response.page);
1695							if( !response.last_page ){
1696								shcode.find(".cr-show-more-button").text( response.show_more_label );
1697								shcode.find(".cr-show-more-button").show();
1698							}
1699						} else {
1700							shcode.find(".cr-search-no-reviews").show();
1701						}
1702						shcode.find(".cr-count-row .cr-count-row-count").html( response.count_row );
1703						shcode.find(".cr-all-reviews-pagination").html(response.pagination);
1704						shcode.find(".cr-all-reviews-pagination").show();
1705					},
1706					dataType: "json"
1707				}
1708			);
1709		}
1710	}
1711
1712	function cr_maybe_download_media_frontend() {
1713		jQuery(".cr-comment-image-ext,.cr-comment-video-ext").each(function() {
1714			let ajaxData = {
1715				"action": "cr_auto_download_media_frontend",
1716				"reviewID": jQuery(this).data("reviewid")
1717			}
1718			jQuery.post(cr_ajax_object.ajax_url, ajaxData, function(response) {
1719				// do nothing
1720			}, "json");
1721			return false;
1722		});
1723	}
1724
1725	function crCaptchaEnabled() {
1726		return "undefined" !== typeof crCaptcha && crCaptcha.isEnabled();
1727	}
1728
1729	function cr_validate_review_form( submitBtn ) {
1730		let validationResult = true;
1731
1732		submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating-cont.cr-review-form-rating-req" ).each( function( index ) {
1733			if( 1 > jQuery( this ).find( ".cr-review-form-rating-actv" ).length ) {
1734				jQuery( this ).closest( ".cr-review-form-rating" ).addClass( "cr-review-form-error" );
1735				validationResult = false;
1736			}
1737		} );
1738		if( 1 > submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-comment-txt" ).val().trim().length ) {
1739			submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-comment" ).addClass( "cr-review-form-error" );
1740			validationResult = false;
1741		}
1742		if( 1 > submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-name .cr-review-form-txt" ).val().trim().length ) {
1743			submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-name" ).addClass( "cr-review-form-error" );
1744			validationResult = false;
1745		}
1746		if( ! crValidateEmail( submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-email .cr-review-form-txt" ).val().trim() ) ) {
1747			submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-email" ).addClass( "cr-review-form-error" );
1748			validationResult = false;
1749		}
1750		// validate custom questions
1751		submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-onsite-question.cr-review-form-que-req" ).each( function( index ) {
1752			if ( 0 < jQuery( this ).find( "input[type=text]" ).length ) {
1753				if( 1 > jQuery( this ).find( "input[type=text]" ).val().trim().length ) {
1754					jQuery( this ).closest( ".cr-onsite-question" ).addClass( "cr-review-form-error" );
1755					validationResult = false;
1756				} else {
1757					jQuery( this ).closest( ".cr-onsite-question" ).removeClass( "cr-review-form-error" );
1758				}
1759			}
1760			if ( 0 < jQuery( this ).find( "input[type=number]" ).length ) {
1761				if( 1 > jQuery( this ).find( "input[type=number]" ).val().trim().length ) {
1762					jQuery( this ).closest( ".cr-onsite-question" ).addClass( "cr-review-form-error" );
1763					validationResult = false;
1764				} else {
1765					jQuery( this ).closest( ".cr-onsite-question" ).removeClass( "cr-review-form-error" );
1766				}
1767			}
1768		} );
1769		// validate terms and conditions if available
1770		if ( 0 < submitBtn.closest( ".cr-review-form-wrap" ).find( '.cr-review-form-terms' ).length ) {
1771			if ( ! submitBtn.closest( ".cr-review-form-wrap" ).find( '.cr-review-form-terms .cr-review-form-checkbox' ).is(':checked') ) {
1772				submitBtn.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-terms" ).addClass( "cr-review-form-error" );
1773				validationResult = false;
1774			}
1775		}
1776		if ( crCaptchaEnabled() && ! crCaptcha.isInvisible() ) {
1777			const captchaForm = submitBtn.closest( ".cr-review-form-wrap" );
1778			if ( 0 < captchaForm.find( '.cr-review-form-captcha .cr-captcha-widget' ).length ) {
1779				if ( "" === crCaptcha.getResponse( captchaForm ) ) {
1780					captchaForm.find( ".cr-review-form-captcha" ).addClass( "cr-review-form-error" );
1781					validationResult = false;
1782				}
1783			}
1784		}
1785
1786		return validationResult;
1787	}
1788
1789	function cr_validate_qna( submitBtn ) {
1790		let validationResult = true;
1791		if( 1 > submitBtn.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-comment-txt" ).val().trim().length ) {
1792			submitBtn.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-comment" ).addClass( "cr-review-form-error" );
1793			validationResult = false;
1794		}
1795		if( 1 > submitBtn.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-name .cr-review-form-txt" ).val().trim().length ) {
1796			submitBtn.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-name" ).addClass( "cr-review-form-error" );
1797			validationResult = false;
1798		}
1799		if( ! crValidateEmail( submitBtn.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-email .cr-review-form-txt" ).val().trim() ) ) {
1800			submitBtn.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-email" ).addClass( "cr-review-form-error" );
1801			validationResult = false;
1802		}
1803		if ( 0 < submitBtn.closest( ".cr-qna-new-q-form" ).find( '.cr-review-form-terms' ).length ) {
1804			if ( ! submitBtn.closest( ".cr-qna-new-q-form" ).find( '.cr-review-form-terms .cr-review-form-checkbox' ).is(':checked') ) {
1805				submitBtn.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-terms" ).addClass( "cr-review-form-error" );
1806				validationResult = false;
1807			}
1808		}
1809		return validationResult;
1810	}
1811
1812	function cr_validate_ans( submitBtn ) {
1813		let validationResult = true;
1814		if( 1 > submitBtn.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-comment-txt" ).val().trim().length ) {
1815			submitBtn.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-comment" ).addClass( "cr-review-form-error" );
1816			validationResult = false;
1817		}
1818		if( 1 > submitBtn.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-name .cr-review-form-txt" ).val().trim().length ) {
1819			submitBtn.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-name" ).addClass( "cr-review-form-error" );
1820			validationResult = false;
1821		}
1822		if( ! crValidateEmail( submitBtn.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-email .cr-review-form-txt" ).val().trim() ) ) {
1823			submitBtn.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-email" ).addClass( "cr-review-form-error" );
1824			validationResult = false;
1825		}
1826		if ( 0 < submitBtn.closest( ".cr-qna-list-inl-answ" ).find( '.cr-review-form-terms' ).length ) {
1827			if ( ! submitBtn.closest( ".cr-qna-list-inl-answ" ).find( '.cr-review-form-terms .cr-review-form-checkbox' ).is(':checked') ) {
1828				submitBtn.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-terms" ).addClass( "cr-review-form-error" );
1829				validationResult = false;
1830			}
1831		}
1832		return validationResult;
1833	}
1834
1835	function cr_reset_review_form( refElement ) {
1836		// reset the rating bar
1837		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating-cont .cr-review-form-rating-inner" ).removeClass( "cr-review-form-rating-actv" );
1838		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating-cont .cr-review-form-rating-inner .cr-rating-act" ).hide();
1839		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating-cont .cr-review-form-rating-inner .cr-rating-deact" ).show();
1840		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating-cont .cr-review-form-rating-nbr" ).text( "0/5" );
1841		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-rating" ).removeClass( "cr-review-form-error" );
1842
1843		// reset the comment field
1844		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-comment-txt" ).val('');
1845		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-comment" ).removeClass( "cr-review-form-error" );
1846
1847		// reset the name field
1848		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-name .cr-review-form-txt" ).val('');
1849		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-name" ).removeClass( "cr-review-form-error" );
1850
1851		// reset the email field
1852		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-email .cr-review-form-txt" ).val('');
1853		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-email" ).removeClass( "cr-review-form-error" );
1854
1855		// reset the custom questions
1856		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-onsite-questions .cr-onsite-question" ).removeClass( "cr-review-form-error" );
1857		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-onsite-questions .cr-onsite-question input[type = 'text']" ).val('');
1858		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-onsite-questions .cr-onsite-question input[type = 'number']" ).val('');
1859
1860		// reset the key custom questions
1861		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-onsite-key-question" ).removeClass( "cr-review-form-error" );
1862		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-onsite-key-question input[type = 'text']" ).val('');
1863		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-onsite-key-question input[type = 'number']" ).val('');
1864
1865		// reset the media files
1866		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-form-item-media .cr-upload-images-containers" ).remove();
1867		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-form-item-media .cr-form-item-media-preview" ).removeClass( "cr-form-visible" );
1868		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-form-item-media .cr-form-item-media-preview" ).parents( ".cr-form-item-subcontainer" ).removeClass( "cr-form-visible" );
1869
1870		// reset the terms and conditions checkbox
1871		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-terms .cr-review-form-checkbox" ).prop( 'checked', false );
1872		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-terms" ).removeClass( "cr-review-form-error" );
1873
1874		// reset captcha
1875		refElement.closest( ".cr-review-form-wrap" ).find( ".cr-review-form-captcha" ).removeClass( "cr-review-form-error" );
1876		if ( crCaptchaEnabled() ) {
1877			crCaptcha.reset( refElement.closest( ".cr-review-form-wrap" ) );
1878		}
1879	}
1880
1881	function cr_reset_qna_form( refElement ) {
1882		// reset the comment field
1883		refElement.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-comment-txt" ).val('');
1884		refElement.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-comment" ).removeClass( "cr-review-form-error" );
1885
1886		// reset the name field
1887		const nameField = refElement.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-name" );
1888		nameField.find( ".cr-review-form-txt" ).val(nameField.find( ".cr-review-form-txt" ).data('defval'));
1889		nameField.removeClass( "cr-review-form-error" );
1890
1891		// reset the email field
1892		const emailField = refElement.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-email" );
1893		emailField.find( ".cr-review-form-txt" ).val(emailField.find( ".cr-review-form-txt" ).data('defval'));
1894		emailField.removeClass( "cr-review-form-error" );
1895
1896		// reset the terms and conditions checkbox
1897		refElement.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-terms .cr-review-form-checkbox" ).prop( 'checked', false );
1898		refElement.closest( ".cr-qna-new-q-form" ).find( ".cr-review-form-terms" ).removeClass( "cr-review-form-error" );
1899	}
1900
1901	function cr_reset_ans_form( refElement ) {
1902		// reset the comment field
1903		refElement.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-comment-txt" ).val("");
1904		refElement.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-comment" ).removeClass( "cr-review-form-error" );
1905
1906		// reset the name field
1907		const nameField = refElement.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-name" );
1908		nameField.find( ".cr-review-form-txt" ).val("");
1909		nameField.removeClass( "cr-review-form-error" );
1910
1911		// reset the email field
1912		const emailField = refElement.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-email" );
1913		emailField.find( ".cr-review-form-txt" ).val("");
1914		emailField.removeClass( "cr-review-form-error" );
1915
1916		// reset the terms and conditions checkbox
1917		refElement.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-terms .cr-review-form-checkbox" ).prop( 'checked', false );
1918		refElement.closest( ".cr-qna-list-inl-answ" ).find( ".cr-review-form-terms" ).removeClass( "cr-review-form-error" );
1919	}
1920
1921	function crDebounce(callback, wait) {
1922		let timeout;
1923		return (...args) => {
1924			clearTimeout(timeout);
1925			if ( 0 < args.length && 13 === args[0].keyCode ) {
1926				wait = 0;
1927			} else {
1928				wait = 1000;
1929			}
1930			timeout = setTimeout(function () { callback.apply(this, args); }, wait);
1931		};
1932	}
1933
1934	function crShowMoreReviewsPrd( refElement ) {
1935		let cr_product_id = refElement.parents(".cr-reviews-ajax-comments").find(".commentlist.cr-ajax-reviews-list").attr("data-product");
1936		let cr_nonce = refElement.parents(".cr-reviews-ajax-comments").attr("data-nonce");
1937		let cr_page = refElement.parents(".cr-reviews-ajax-comments").attr("data-page");
1938		let cr_sort = refElement.parents(".cr-reviews-ajax-comments").find(".cr-ajax-reviews-sort").children("option:selected").val();
1939		let cr_rating = refElement.parents(".cr-reviews-ajax-comments").find(".cr-summaryBox-ajax .ivole-histogramRow.ivole-histogramRow-s a.cr-histogram-a").attr("data-rating");
1940		let cr_search = refElement.parents(".cr-reviews-ajax-comments").find(".cr-ajax-search input").val();
1941		let cr_tags = [];
1942		refElement.parents(".cr-reviews-ajax-comments").find(".cr-review-tags-filter .cr-tags-filter.cr-tag-selected").each(
1943			function() {
1944				cr_tags.push( jQuery(this).attr("data-crtagid") );
1945			}
1946		);
1947		let cr_media = refElement.parents(".cr-reviews-ajax-comments").find(".cr-review-tags-filter .cr-media-pill.cr-tag-selected").length ? 1 : 0;
1948		if ( ! cr_rating ){
1949			cr_rating = 0;
1950		}
1951		let cr_data = {
1952			"action": "cr_show_more_reviews",
1953			"productID": cr_product_id,
1954			"page": cr_page,
1955			"sort": cr_sort,
1956			"rating": cr_rating,
1957			"search": cr_search,
1958			"tags": cr_tags,
1959			"media": cr_media,
1960			"security": cr_nonce
1961		};
1962		refElement.parents(".cr-reviews-ajax-comments").find(".cr-summaryBox-ajax").addClass("cr-summaryBar-updating");
1963		refElement.parents(".cr-reviews-ajax-comments").find(".cr-ajax-reviews-sort").addClass("cr-sort-updating");
1964		refElement.parents(".cr-reviews-ajax-comments").find(".cr-review-tags-filter").addClass("cr-review-tags-filter-disabled");
1965		refElement.parents(".cr-reviews-ajax-comments").find(".cr-search-no-reviews").hide();
1966		refElement.parents(".cr-reviews-ajax-comments").find(".cr-show-more-reviews-prd").hide();
1967		refElement.parents(".cr-reviews-ajax-comments").find(".cr-show-more-review-spinner").show();
1968		jQuery.post( {
1969			url: cr_ajax_object.ajax_url,
1970			data: cr_data,
1971			context: refElement,
1972			success: function(response) {
1973				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-review-spinner").hide();
1974				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-summaryBox-ajax").removeClass("cr-summaryBar-updating");
1975				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-ajax-reviews-sort").removeClass("cr-sort-updating");
1976				jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-review-tags-filter").removeClass("cr-review-tags-filter-disabled");
1977				if( response.page > 0 ) {
1978					jQuery(this).parents(".cr-reviews-ajax-comments").find(".commentlist.cr-ajax-reviews-list").append( response.html );
1979					jQuery(this).parents(".cr-reviews-ajax-comments").attr("data-page",response.page);
1980					if ( response.show_more_label ) {
1981						jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-reviews-prd").text( response.show_more_label );
1982					}
1983					if ( response.count_row ) {
1984						jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-count-row .cr-count-row-count").html( response.count_row );
1985					}
1986					if ( ! response.last_page ) {
1987						jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-show-more-reviews-prd").show();
1988					}
1989					cr_maybe_download_media_frontend();
1990				}
1991				if ( response.html == null && response.page === 1 ) {
1992					jQuery(this).parents(".cr-reviews-ajax-comments").find(".cr-search-no-reviews").show();
1993				}
1994			},
1995			dataType: "json"
1996		} );
1997	}
1998
1999})();
2000
2001function crResizeAllGridItemsUtil(grids) {
2002	jQuery(grids).each( function() {
2003		if(800 > jQuery(this).width()) {
2004			jQuery(this).find(".cr-reviews-grid-col3").addClass("cr-reviews-grid-col-none");
2005		}
2006		if(550 > jQuery(this).width()) {
2007			jQuery(this).find(".cr-reviews-grid-col2").addClass("cr-reviews-grid-col-none");
2008		}
2009		jQuery(this).colcade( {
2010			columns: ".cr-reviews-grid-col",
2011			items: ".cr-review-card"
2012		} );
2013	} );
2014}
2015
2016function crResizeAllGridItems() {
2017	if (
2018		typeof Colcade !== "undefined" &&
2019		typeof Colcade.makeJQueryPlugin !== "undefined" &&
2020		typeof Colcade.makeJQueryPlugin === "function"
2021	) {
2022		if (
2023			! typeof jQuery.fn.colcade === "function" ||
2024			typeof jQuery.fn.colcade === "undefined"
2025		) {
2026			Colcade.makeJQueryPlugin();
2027		}
2028	}
2029	crResizeAllGridItemsUtil( jQuery(".cr-reviews-grid-inner") );
2030}
2031
2032function crResizeTrustBadges() {
2033	jQuery(".cr-trustbadgef").each(function() {
2034		let badge = jQuery(this).find(".cr-badge").eq(0);
2035		let scale = jQuery(this).width() / badge.outerWidth();
2036		if( 1 > scale ) {
2037			badge.css("transform", "scale(" + scale + ")");
2038		}
2039		badge.css("visibility", "visible");
2040	});
2041}

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.