PageSourceSearch

https://pocketwizard.com/wp-content/plugins/customer-reviews-woocommerce/js/frontend.js?ver=5.121.0

js pocketwizard.com collected 2026-09-24 09:15:47 UTC 97,253 bytes, 2,030 lines download raw bytes

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

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.