PageSourceSearch

https://www.obdlink.com/wp-content/plugins/side-cart-woocommerce/assets/js/xoo-wsc-main.js?ver=2.8.0

js obdlink.com collected 2026-09-24 18:12:59 UTC 18,188 bytes, 768 lines download raw bytes

1jQuery(document).ready(function($){
2
3	var isCartPage 		= xoo_wsc_params.isCart == '1',
4		isCheckoutPage 	= xoo_wsc_params.isCheckout == '1';
5
6	var get_wcurl = function( endpoint ) {
7		return xoo_wsc_params.wc_ajax_url.toString().replace(
8			'%%endpoint%%',
9			endpoint
10		);
11	};
12
13
14	var markupTimeout = null;
15
16	var Notice = {
17
18		timeout: null,
19
20		markupTimeout: null,
21
22		$cartNoticeCont: function(){
23			return $('.xoo-wsc-markup').find('.xoo-wsc-notice-container');
24		},
25
26		$markupNoticeCont: function(){
27			return $('.xoo-wsc-markup-notices')
28		},
29
30		add: function( notice, type = 'success', clearPrevious = true ){
31
32			if( clearPrevious ){
33				Notice.$cartNoticeCont().html('');
34			}
35
36			var noticeHTML = type === 'success' ? xoo_wsc_params.html.successNotice.toString().replace( '%s%', notice ) : xoo_wsc_params.html.errorNotice.toString().replace( '%s%', notice );
37
38			Notice.$cartNoticeCont().html( noticeHTML );
39
40		},
41
42
43		setHTML: function(noticeHTML){
44			Notice.$cartNoticeCont().add( Notice.$markupNoticeCont() ).html(noticeHTML);
45		},
46
47		showNotification: function(){
48
49			if( !cart.isOpen() ){
50				Notice.showMarkupNotice();
51				return;
52			}
53
54			Notice.$cartNoticeCont().slideDown();
55			
56			clearTimeout(Notice.timeout);
57
58			Notice.timeout = setTimeout(function(){
59				Notice.$cartNoticeCont().slideUp('slow');
60			}, xoo_wsc_params.notificationTime );
61
62		},
63
64
65		hideNotification: function(){
66			Notice.$cartNoticeCont().hide();
67		},
68
69		hideMarkupNotice: function(){
70			Notice.$markupNoticeCont().removeClass('xoo-wsc-active');
71		},
72
73
74		showMarkupNotice: function(){
75
76			var $markupNotice = Notice.$markupNoticeCont();
77
78			var $noticeCont = $markupNotice.find('.xoo-wsc-notice-container .xoo-wsc-notices');
79
80			if( !$noticeCont.length || $noticeCont.children().length === 0 ) return;
81
82			setTimeout(function(){$markupNotice.addClass('xoo-wsc-active')},10);
83			
84			clearTimeout(Notice.markupTimeout);
85
86			Notice.markupTimeout = setTimeout(function(){
87				$markupNotice.removeClass('xoo-wsc-active');
88			},xoo_wsc_params.notificationTime )
89		}
90	}
91
92	class Container{
93
94		constructor( $modal, container ){
95			this.$modal 	= $modal;
96			this.container 	= container || 'cart';
97		}
98
99		isOpen(){
100			return this.$modal.hasClass('xoo-wsc-'+this.container+'-active');
101		}
102
103		eventHandlers(){
104			$(document.body).on( 'wc_fragments_loaded updated_checkout', this.onCartUpdate.bind(this) );
105		}
106
107		onCartUpdate(){
108			this.unblock();
109			Notice.showNotification();
110		}
111
112		setAjaxData( data, noticeSection ){
113
114			var ajaxData = {
115				container: this.container,
116				noticeSection: noticeSection || this.noticeSection || this.container,
117				isCheckout: isCheckoutPage,
118				isCart: isCartPage
119			}
120
121
122			if( typeof data === 'object' ){
123
124				$.extend( ajaxData, data );
125
126			}
127			else{
128
129				var serializedData = data;
130
131				$.each( ajaxData, function( key, value ){
132					serializedData += ( '&'+key+'='+value );
133				} )
134		
135				ajaxData = serializedData;
136
137			}
138
139			return ajaxData;
140		}
141
142
143		toggle( type ){
144
145			var $activeEls 	= this.$modal.add( 'body' ).add('html'),
146				activeClass = 'xoo-wsc-'+ this.container +'-active';
147
148			if( type === 'show' ){
149				$activeEls.addClass(activeClass);
150			}
151			else if( type === 'hide' ){
152				$activeEls.removeClass(activeClass);
153			}
154			else{
155				$activeEls.toggleClass(activeClass);
156			}
157
158			$(document.body).trigger( 'xoo_wsc_' + this.container + '_toggled', [ type ] );
159
160			Notice.hideNotification();
161
162		}
163
164
165		block(){
166			this.$modal.addClass('xoo-wsc-loading');
167		}
168
169		unblock(){
170			this.$modal.removeClass('xoo-wsc-loading');
171		}
172
173
174		refreshMyFragments(){
175
176			if( xoo_wsc_params.refreshCart === "yes" && typeof wc_cart_fragments_params !== 'undefined' ){
177				$( document.body ).trigger( 'wc_fragment_refresh' );
178				return;
179			}
180
181			this.block();
182
183			$.ajax({
184				url: get_wcurl( 'xoo_wsc_refresh_fragments' ),
185				type: 'POST',
186				context: this,
187				data: {},
188				success: function( response ){
189					this.updateFragments(response);
190				},
191				complete: function(){
192					this.unblock();
193				}
194			})
195
196		}
197
198
199		updateCartCheckoutPage(){
200
201			//Refresh checkout page
202			if( isCheckoutPage ){
203				if( $( 'form.checkout' ).length === 0 ){
204					location.reload();
205					return;
206				}
207				$(document.body).trigger("update_checkout");
208			}
209
210			//Refresh Cart page
211			if( isCartPage ){
212				$(document.body).trigger("wc_update_cart");
213			}
214
215		}
216
217		updateFragments( response ){
218
219			if( response.fragments ){
220
221				$( document.body ).trigger( 'xoo_wsc_before_loading_fragments', [ response ] );
222
223				this.block();
224
225				//Set fragments
226		   		$.each( response.fragments, function( key, value ) {
227					$( key ).replaceWith( value );
228				});
229
230		   		if( typeof wc_cart_fragments_params !== 'undefined' && ( 'sessionStorage' in window && window.sessionStorage !== null ) ){
231
232		   			sessionStorage.setItem( wc_cart_fragments_params.fragment_name, JSON.stringify( response.fragments ) );
233					localStorage.setItem( wc_cart_fragments_params.cart_hash_key, response.cart_hash );
234					sessionStorage.setItem( wc_cart_fragments_params.cart_hash_key, response.cart_hash );
235
236					if ( response.cart_hash ) {
237						sessionStorage.setItem( 'wc_cart_created', ( new Date() ).getTime() );
238					}
239
240				}
241
242				$( document.body ).trigger( 'wc_fragments_loaded' );
243
244				this.unblock();
245
246			}
247
248			if( xoo_wsc_params.refreshCart === "yes" && typeof wc_cart_fragments_params !== 'undefined' ){
249				this.block();
250				$( document.body ).trigger( 'wc_fragment_refresh' );
251				return;
252			}
253
254		}
255
256	}
257
258
259	class Cart extends Container{
260
261		static isWCAjaxAddToCart = false;
262
263		constructor( $modal ){
264
265			super( $modal, 'cart' );
266
267			this.cartLoaded 			= false;
268			this.blockAddedToCartCalled = false;
269			this.baseQty 				= 1;
270			this.qtyUpdateDelay 		= null;
271
272			this.refreshFragmentsOnPageLoad();
273			this.eventHandlers();
274
275		}
276
277
278		refreshFragmentsOnPageLoad(){
279			if( xoo_wsc_params.fetchCart === 'page_load' ){
280				setTimeout(function(){
281					this.refreshMyFragments();
282				}.bind(this), xoo_wsc_params.fetchDelay )
283			}
284		}
285
286		eventHandlers(){
287
288			super.eventHandlers();
289
290			this.$modal.on( 'click', '.xoo-wsc-chng', this.toggleQty.bind(this) );
291			this.$modal.on( 'change', '.xoo-wsc-qty', this.changeInputQty.bind(this) );
292			this.$modal.on( 'click', '.xoo-wsc-smr-del', this.deleteIconClick.bind(this) );
293			this.$modal.on( 'click', '.xoo-wsch-close, .xoo-wsc-opac, .xoo-wsc-cart-close', this.closeCartOnClick.bind(this) );
294			this.$modal.on( 'click', '.xoo-wsc-basket', this.toggleCart.bind(this) );
295
296			$(document.body).on( 'xoo_wsc_cart_updated', this.updateCartCheckoutPage.bind(this) );
297			$(document.body).on( 'click', 'a.added_to_cart, .xoo-wsc-cart-trigger', this.openCart.bind(this) );
298			$(document.body).on( 'added_to_cart', this.addedToCart.bind(this) );
299
300			$(document.body).on( 'wc-blocks_added_to_cart', this.blockAddedToCart.bind(this) );
301
302			$(document.body).on( 'adding_to_cart', this.checkIfWCAjaxAddToCart.bind(this) );
303
304			if( xoo_wsc_params.autoOpenCart === 'yes' && xoo_wsc_params.addedToCart === 'yes'){
305				this.openCart();
306			}
307
308			if( xoo_wsc_params.ajaxAddToCart === 'yes' ){
309				$(document.body).on( 'submit', 'form.cart', this.addToCartFormSubmit.bind(this) );
310			}
311
312			if( typeof wc_cart_fragments_params === 'undefined' ){
313				$( window ).on( 'pageshow' , this.onPageShow.bind(this) );
314			}
315
316			if( xoo_wsc_params.triggerClass ){
317				$(document.body).on( 'click', '.'+xoo_wsc_params.triggerClass, this.openCart.bind(this) );
318			}
319
320
321			if( isCheckoutPage || isCartPage ){
322				$(document.body).on( 'updated_shipping_method', this.refreshMyFragments.bind(this) );
323			}
324
325			this.initMasonryLayout();
326
327		}
328
329		toggleQty(e){
330
331			var $toggler 	= $(e.currentTarget),
332				$input 		= $toggler.siblings('.xoo-wsc-qty');
333
334			if( !$input.length ) return;
335
336			var baseQty = this.baseQty = parseFloat( $input.val() ),
337				step 	= parseFloat( $input.attr('step') ),
338				action 	= $toggler.hasClass( 'xoo-wsc-plus' ) ? 'add' : 'less',
339				newQty 	= action === 'add' ? baseQty + step : baseQty - step;
340
341			
342			$input.val(newQty).trigger('change');
343
344		}
345
346		changeInputQty(e){
347
348			Notice.hideNotification();
349
350			var $_this	= this,
351 				$input 	= $(e.currentTarget),
352				newQty 	= parseFloat( $input.val() ),
353				step 	= parseFloat( $input.attr('step') ),
354				min 	= parseFloat( $input.attr('min') ),
355				max 	= parseFloat( $input.attr('max') ),
356				invalid = false,
357				message = false;
358
359			//Validation
360			
361			if( isNaN( newQty )  || newQty < 0 || newQty < min  ){
362				invalid = true;
363			}
364			else if( newQty > max ){
365				invalid = true;
366				message = xoo_wsc_params.strings.maxQtyError.replace( '%s%', max );
367			}
368			else if( !Number.isInteger(newQty/step ) ){
369				invalid = true;
370				message = xoo_wsc_params.strings.stepQtyError.replace( '%s%', step );
371			}
372			
373			//Set back to default quantity
374			if( invalid ){
375				$input.val( this.baseQty );
376				if( message ){
377					Notice.add( message, 'error' );
378					Notice.showNotification();
379				}
380				return;
381			}
382
383			//Update
384			$input.val( newQty );
385
386			clearTimeout( this.qtyUpdateDelay );
387
388			this.qtyUpdateDelay = setTimeout(function(){
389				$_this.updateItemQty( $input.parents('.xoo-wsc-product').data('key'), newQty )
390			}, xoo_wsc_params.qtyUpdateDelay );
391			
392			
393		}
394
395		updateItemQty( cart_key, qty ){
396
397			if( !cart_key || qty === undefined ) return;
398
399			this.block();
400			
401			this.saveScrollPosition();
402
403			var formData = {
404				cart_key: cart_key,
405				qty: qty
406			}
407
408			$.ajax({
409				url: get_wcurl( 'xoo_wsc_update_item_quantity' ),
410				type: 'POST',
411				context: this,
412				data: this.setAjaxData(formData),
413				success: function(response){
414					this.updateFragments( response );
415					$(document.body).trigger( 'xoo_wsc_quantity_updated', [response] );
416					$(document.body).trigger( 'xoo_wsc_cart_updated', [response] );
417					this.setScrollPosition();
418					this.unblock();
419				}
420
421			})
422		}
423
424		checkIfWCAjaxAddToCart(e, $button, data){
425
426			Cart.isWCAjaxAddToCart = true;
427
428			if( ( !(data instanceof FormData) || !data.has('action') || !data.get('action') === 'xoo_wsc_add_to_cart' ) && $button.hasClass('ajax_add_to_cart') ){
429				this.isWCAjaxAddToCart = true;
430			}
431		}
432
433		toggleCart(e){
434			if( this.isOpen() ){
435				this.closeCartOnClick(e);
436			}
437			else{
438				this.openCart(e);
439			}
440			
441		}
442
443		openCart(e){
444			if( e ){
445				e.preventDefault();
446				e.stopImmediatePropagation();
447			}
448
449			if( !this.cartLoaded && xoo_wsc_params.fetchCart === 'cart_open' ){
450				this.refreshMyFragments();
451				this.cartLoaded = true;
452			}
453
454			this.toggle('show');
455			Notice.hideMarkupNotice();
456		}
457
458		addToCartFormSubmit(e){
459
460			var $form = $(e.currentTarget);
461
462			if( $form.closest('.product').hasClass('product-type-external') || $form.siblings('.xoo-wsc-disable-atc').length ) return;
463
464			var $button  		= e.originalEvent && e.originalEvent.submitter ? $(e.originalEvent.submitter) : $form.find( 'button[type="submit"]'),
465				formData 		= new FormData($form.get(0)),
466				productData  	= $form.serializeArray(),
467				hasProductId 	= false;
468
469			//Check for woocommerce custom quantity code 
470			//https://docs.woocommerce.com/document/override-loop-template-and-show-quantities-next-to-add-to-cart-buttons/
471			$.each( productData, function( key, form_item ){
472				if( form_item.name === 'productID' || form_item.name === 'add-to-cart' ){
473					if( form_item.value ){
474						hasProductId = true;
475						return false;
476					}
477				}
478			})
479
480			//If no product id found , look for the form action URL
481			if( !hasProductId && $form.attr('action') ){
482				var is_url = $form.attr('action').match(/add-to-cart=([0-9]+)/),
483					productID = is_url ? is_url[1] : false; 
484			}
485
486			// Add submitted button value
487	        if( $button.attr('name') && $button.attr('value') ){
488	            formData.append( $button.attr('name'), $button.attr('value') );
489	        }
490
491	        if( productID ){
492	        	formData.append( 'add-to-cart', productID );
493	        }
494
495	        formData.append( 'action', 'xoo_wsc_add_to_cart' );
496
497	        var doAjaxAddToCart = true;
498
499	        
500        	$.each( xoo_wsc_params.skipAjaxForData, function( key, value ){
501        		if( formData.has(key) && ( !value || formData.get(key) == value ) ){
502        			doAjaxAddToCart = false;
503        			return false;
504        		}
505        	} )
506	        
507
508	        if( doAjaxAddToCart ){
509	        	e.preventDefault();
510	        	this.addToCartAjax( $button, formData );//Ajax add to cart
511	        }
512			
513		}
514
515
516		addToCartAjax( $button, formData ){
517
518			this.block();
519
520			$button.addClass('loading');
521
522			// Trigger event.
523			$( document.body ).trigger( 'adding_to_cart', [ $button, formData ] );
524
525			$.ajax({
526				url: get_wcurl( 'xoo_wsc_add_to_cart' ),
527				type: 'POST',
528				context: this,
529				cache: false,
530			    contentType: false,
531			    processData: false,
532				data: formData,
533			    success: function(response){
534
535					if(response.fragments){
536						// Trigger event so themes can refresh other areas.
537						$( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $button ] );
538					}else if(response.error){
539						Notice.setHTML(response.notice);
540						Notice.showNotification();
541					}
542					else{
543						window.location.reload();
544					}
545
546			    },
547			    complete: function(){
548			    	this.unblock();
549			    	$button
550			    		.removeClass('loading')
551			    		.addClass('added');
552			    }
553			})
554		}
555
556		addedToCart( e, response, hash, $button ){
557
558			var _this = this;
559
560			this.updateFragments( { fragments: response } );
561
562			if( xoo_wsc_params.autoOpenCart === "yes" ){
563				_this.openCart();
564			}
565
566			this.onCartUpdate();
567			
568		}
569
570		blockAddedToCart(){
571
572			if( !Cart.isWCAjaxAddToCart && !this.blockAddedToCartCalled ){
573
574				this.refreshMyFragments();
575				
576				var _this = this;
577
578				if( xoo_wsc_params.autoOpenCart === "yes" ){
579					setTimeout(function(){
580						_this.openCart();	
581					},20 )
582				}
583
584				this.blockAddedToCartCalled = true;
585
586				setTimeout( function(){
587					_this.blockAddedToCartCalled = false;
588				}, 200 );
589
590				Cart.isWCAjaxAddToCart = false;
591
592			}
593
594
595						
596		}
597
598		
599		closeCartOnClick(e){
600			e.preventDefault();
601			this.toggle( 'hide' );
602		}
603
604
605		onPageShow(e){
606			if ( e.originalEvent.persisted ) {
607				this.refreshMyFragments();
608				$( document.body ).trigger( 'wc_fragment_refresh' );
609			}
610		}
611
612		deleteIconClick(e){
613			this.updateItemQty( $( e.currentTarget ).parents('.xoo-wsc-product').data('key'), 0 );
614		}
615
616		updateItemQty( cart_key, qty ){
617
618			if( !cart_key || qty === undefined ) return;
619
620			this.block();
621
622			var formData = {
623				cart_key: cart_key,
624				qty: qty
625			}
626
627			$.ajax({
628				url: get_wcurl( 'xoo_wsc_update_item_quantity' ),
629				type: 'POST',
630				context: this,
631				data: this.setAjaxData(formData),
632				success: function(response){
633					this.updateFragments( response );
634					$(document.body).trigger( 'xoo_wsc_quantity_updated', [response] );
635					$(document.body).trigger( 'xoo_wsc_cart_updated', [response] );
636					this.unblock();
637				}
638
639			})
640		}
641
642		onCartUpdate(){
643			super.onCartUpdate();
644			this.cartLoaded = true;
645			this.toggleBasket();
646			this.initMasonryLayout();
647		}
648
649
650		initMasonryLayout(){
651			if( xoo_wsc_params.productLayout !== 'cards' ) return;
652			$('.xoo-wsc-products.xoo-wsc-pattern-card').masonry({
653				// options
654				itemSelector: '.xoo-wsc-product-cont',
655				columnWidth: '.xoo-wsc-product-cont', /* Each column takes 50% */
656				percentPosition: true
657			});
658		}
659
660		
661		toggleBasket(){
662
663			var $basket 	= $('.xoo-wsc-basket'),
664				show 		= xoo_wsc_params.showBasket,
665				hasProducts = this.$modal.find('.xoo-wsc-product').length;
666
667			if( show === "always_show" ){
668				$basket.show();	
669			}
670			else if( show === "hide_empty" ){
671				if( hasProducts){
672					$basket.show();
673				}
674				else{
675					$basket.hide();
676				}
677			}
678			else{
679				$basket.hide();
680			}
681
682			var $shortcode = $('.xoo-wsc-sc-cont');
683
684			if( $shortcode.length && xoo_wsc_params.menuCartHideOnEmpty.length ){
685
686				var shortcodeEls = xoo_wsc_params.shortcodeEls;
687
688				$.each( xoo_wsc_params.menuCartHideOnEmpty, function( index, val ){
689
690					if( shortcodeEls[val] ){
691						if( hasProducts ){
692							$(shortcodeEls[val]).show();
693						}
694						else{
695							$(shortcodeEls[val]).hide();
696						}
697					}
698
699				})
700
701			}
702		}
703
704	
705
706	}
707
708
709
710
711	var cart 	= new Cart( $('.xoo-wsc-modal') );
712
713
714	var AnimateCard = {
715
716		type: xoo_wsc_params.cardAnimate.type,
717		duration: xoo_wsc_params.cardAnimate.duration,
718
719		init: function(){
720
721			var onEvent = xoo_wsc_params.cardAnimate.event === 'back_hover' ? 'mouseenter' : 'click';
722		
723			$('body').on( onEvent, '.xoo-wsc-has-back', this.animate );
724			$('body').on( 'mouseleave', '.xoo-wsc-has-back', this.reverseAnimate );
725
726		},
727		animate: function(e){
728
729			if( e.target.classList.contains('xoo-wsc-smr-del') ) return;
730
731			var $img = $(this).find('.xoo-wsc-img-col');
732
733			if( !$img.hasClass('xoo-wsc-caniming') ){
734				e.preventDefault();
735			}
736			else{
737				return;
738			}
739
740			$img.attr('data-exclasses', $img.attr('class') );
741
742			$img.removeClass()
743			$img.addClass($img.attr('data-exclasses'));
744
745			$img.addClass( 'xoo-wsc-caniming' + ' ' + AnimateCard.type );
746
747		},
748		reverseAnimate: function(){
749
750			var $img = $(this).find('.xoo-wsc-img-col');
751
752			if( !$img.hasClass( 'xoo-wsc-caniming' ) ) return;
753
754			$img.addClass(AnimateCard.type+'Return');
755
756			AnimateCard.clear = setTimeout(function(){
757				$img.removeClass().addClass( $img.attr('data-exclasses') );
758			}, AnimateCard.duration * 1000);
759
760		}
761	}
762
763	if( xoo_wsc_params.cardAnimate.enable === "yes" ){
764		AnimateCard.init();
765	}
766
767
768})

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.