PageSourceSearch

https://www.traces-ecrites.com/core/views/traces-ecrites/js/script.js

js traces-ecrites.com collected 2026-10-02 17:09:28 UTC 49,557 bytes, 1,814 lines download raw bytes

1(function ( $ ) {
2	'use strict';
3
4	var sober = sober || {};
5
6	sober.init = function () {
7		this.$window = $( window );
8		this.$body = $( document.body );
9		this.$sideMenu = $( '.side-menu' );
10
11		this.data = soberData || {};
12
13		this.closeTopbar();
14		this.menuHover();
15		this.toggleSideMenu();
16		this.toggleModal();
17		this.removeCartItem();
18		this.toggleTabs();
19		this.focusInputs();
20		this.filterProducts();
21		this.sortProducts();
22		this.productQuantity();
23		this.productImagesLightbox();
24		this.stickyProductSummary();
25		this.stickUpSells();
26		this.upsellsCarousel();
27		this.checkBox();
28		this.formatGallery();
29		this.backToTop();
30		this.toggleProductFilter();
31		this.productQuickView();
32		this.instanceSearch();
33		this.fakeScrollbar();
34		this.stickyHeader();
35		this.navAjax();
36		this.portfolioFilter();
37		this.productVariationSwatches();
38		this.productGallerySlider();
39		this.productImageZoom();
40		this.productImageSlider();
41		this.singeProductAjaxAddToCart();
42		this.openCartModalAfterAdd();
43		this.pageHeaderParallax();
44		this.responsive();
45		this.preload();
46		this.popup();
47		this.addedToCartNotice();
48		this.checkoutTerms();
49
50		$( document.body ).trigger( 'sober_init', [sober] );
51	};
52
53	/**
54	 * Check if a node is blocked for processing.
55	 *
56	 * @param {object} $node
57	 * @return {bool} True if the DOM Element is UI Blocked, false if not.
58	 */
59	sober.isBlocked = function ( $node ) {
60		return $node.is( '.processing' ) || $node.parents( '.processing' ).length;
61	};
62
63	/**
64	 * Block a node visually for processing.
65	 *
66	 * @param {object} $node
67	 */
68	sober.block = function ( $node ) {
69		if ( !sober.isBlocked( $node ) ) {
70			$node.addClass( 'processing' ).block( {
71				message   : null,
72				overlayCSS: {
73					background: '#fff',
74					opacity   : 0.6
75				}
76			} );
77		}
78	};
79
80	/**
81	 * Unblock a node after processing is complete.
82	 *
83	 * @param {object} $node
84	 */
85	sober.unblock = function ( $node ) {
86		$node.removeClass( 'processing' ).unblock();
87	};
88
89	/**
90	 * Check if an element is in view-port or not
91	 *
92	 * @param el
93	 * @returns {boolean}
94	 */
95	sober.isVisible = function ( el ) {
96		if ( el instanceof jQuery ) {
97			el = el[0];
98		}
99
100		var rect = el.getBoundingClientRect();
101
102		return rect.bottom > 0 &&
103			rect.right > 0 &&
104			rect.left < ( window.innerWidth || document.documentElement.clientWidth ) &&
105			rect.top < ( window.innerHeight || document.documentElement.clientHeight );
106	};
107
108	/**
109	 * Post format gallery with carousel slider
110	 */
111	sober.formatGallery = function () {
112		$( '.entry-gallery' ).addClass( 'owl-carousel' ).owlCarousel( {
113			singleItem: true,
114			items     : 1,
115			navSpeed  : 800,
116			nav       : true,
117			dots      : false,
118			autoplay  : true,
119			dotsSpeed : 1000,
120			rtl       : sober.data.isRTL === "1",
121			navText   : ['<svg viewBox="0 0 20 20"><use xlink:href="#left-arrow"></use></svg>', '<svg viewBox="0 0 20 20"><use xlink:href="#right-arrow"></use></svg>']
122		} );
123	};
124
125	/**
126	 * Style checkboxes
127	 */
128	sober.checkBox = function () {
129		// Checkbox: Ship to a different address
130		$( '#ship-to-different-address' ).find( '.input-checkbox' ).on( 'change', function () {
131			if ( $( this ).is( ':checked' ) ) {
132				$( this ).parent().find( '.checkbox' ).addClass( 'checked' );
133			} else {
134				$( this ).parent().find( '.checkbox' ).removeClass( 'checked' );
135			}
136		} ).trigger( 'change' );
137	};
138
139	/**
140	 * Load ajax on shop page and blog
141	 */
142	sober.navAjax = function () {
143		// Blog & Portfolio
144		sober.$body.on( 'click', '.ajax-navigation a', function ( e ) {
145			e.preventDefault();
146
147			var $button = $( this ),
148				$nav = $button.parent(),
149				$main = $( '#main' ),
150				url = $button.attr( 'href' );
151
152			if ( $nav.hasClass( 'loading' ) ) {
153				return;
154			}
155
156			$nav.addClass( 'loading' );
157
158			$.get(
159				url,
160				function ( response ) {
161					var $response = $( response ),
162						nextTitle = $response.filter( 'title' ).text();
163
164					if ( $nav.hasClass( 'posts-navigation' ) ) {
165						var $content = $( $response.find( '#main' ).html() );
166						$content.hide();
167
168						$main.append( $content );
169						$content.fadeIn( 1000 );
170						$nav.remove();
171					} else if ( $nav.hasClass( 'portfolio-navigation' ) ) {
172						var $items = $response.find( '.portfolio-items .portfolio' ),
173							$link = $response.find( '.ajax-navigation a' );
174
175						if ( $items.length ) {
176							$items.imagesLoaded( function () {
177								$main.find( '.portfolio-items' ).isotope( 'insert', $items );
178							} );
179							$nav.removeClass( 'loading' );
180
181							if ( $link.length ) {
182								$nav.html( $link );
183							} else {
184								$nav.fadeOut();
185							}
186						}
187					}
188
189					window.history.pushState( null, nextTitle, url );
190				}
191			);
192		} );
193
194		// Shop
195		if ( 'ajax' === sober.data.shop_nav_type || 'infinity' === sober.data.shop_nav_type ) {
196			sober.$body.on( 'click', '.woocommerce-pagination .next', function ( e ) {
197				e.preventDefault();
198
199				var $button = $( this ),
200					$nav = $button.closest( '.woocommerce-pagination' ),
201					$products = $nav.prev( 'ul.products' ),
202					url = $button.attr( 'href' );
203
204				if ( $button.hasClass( 'loading' ) ) {
205					return;
206				}
207
208				$button.addClass( 'loading' );
209
210				load_products( url, $products, function ( response ) {
211					var $pagination = $( response ).find( '.woocommerce-pagination' );
212
213					if ( $pagination.length ) {
214						$nav.html( $pagination.html() );
215					} else {
216						$nav.html( '' );
217					}
218				} );
219			} );
220		}
221
222		// Infinity Shop
223		if ( 'infinity' === sober.data.shop_nav_type ) {
224			var $nav = $( '.woocommerce-pagination' ),
225				$button = $nav.find( '.next' ),
226				$products = $( 'ul.products' );
227
228			if ( $button.length ) {
229				// Use this variable to control scroll event handle for better performance
230				var waiting = false,
231					endScrollHandle;
232
233				sober.$window.on( 'scroll', function () {
234					if ( waiting ) {
235						return;
236					}
237
238					waiting = true;
239
240					// clear previous scheduled endScrollHandle
241					clearTimeout( endScrollHandle );
242
243					infiniteScoll();
244
245					setTimeout( function () {
246						waiting = false;
247					}, 100 );
248
249					// schedule an extra execution of infiniteScoll() after 200ms
250					// in case the scrolling stops in next 100ms
251					endScrollHandle = setTimeout( function () {
252						infiniteScoll();
253					}, 200 );
254				} );
255			}
256
257			var infiniteScoll = function () {
258				// When almost reach to nav and new next button is exists
259				if ( sober.isVisible( $nav ) && $button.length ) {
260					if ( $button.hasClass( 'loading' ) ) {
261						return;
262					}
263
264					$button.addClass( 'loading' );
265
266					load_products( $button.attr( 'href' ), $products, function ( response ) {
267						var $pagination = $( response ).find( '.woocommerce-pagination' );
268
269						if ( $pagination.length ) {
270							$nav.html( $pagination.html() );
271
272							// Re-select because DOM has been changed
273							$button = $nav.find( '.next' );
274						} else {
275							$nav.html( '' );
276							$button.length = 0;
277						}
278					} );
279				}
280			}
281		}
282
283		/**
284		 * Private function for ajax loading product
285		 *
286		 * @param url
287		 * @param $holder
288		 * @param callback
289		 */
290		function load_products( url, $holder, callback ) {
291			$.get(
292				url,
293				function ( response ) {
294					var $primary = $( response ).find( '#primary' ),
295						$_products = $primary.find( 'ul.products' ).children();
296
297					$_products.imagesLoaded( function () {
298						$holder.isotope( 'insert', $_products );
299
300						if ( 'function' === typeof callback ) {
301							callback( response );
302						}
303					} );
304
305					window.history.pushState( null, '', url );
306				}
307			);
308		}
309	};
310
311	/**
312	 * Close topbar
313	 */
314	sober.closeTopbar = function () {
315		$( '#topbar' ).on( 'click', '.close', function ( e ) {
316			e.preventDefault();
317
318			$( this ).closest( '#topbar' ).slideUp();
319		} );
320	};
321
322	/**
323	 * Main navigation sub-menu hover
324	 */
325	sober.menuHover = function () {
326		var animations = {
327			none : ['show', 'hide'],
328			fade : ['fadeIn', 'fadeOut'],
329			slide: ['slideDown', 'slideUp']
330		};
331
332		var animation = sober.data.menu_animation ? animations[sober.data.menu_animation] : 'fade';
333
334		$( '.site-navigation li, .topbar-menu li' ).on( 'mouseenter', function () {
335			$( this ).addClass( 'active' ).children( '.sub-menu' ).stop( true, true )[animation[0]]();
336		} ).on( 'mouseleave', function () {
337			$( this ).removeClass( 'active' ).children( '.sub-menu' ).stop( true, true )[animation[1]]();
338		} );
339	};
340
341	/**
342	 *  Toggle modal
343	 */
344	sober.toggleModal = function () {
345		sober.$body.on( 'click', '[data-toggle="modal"]', function ( e ) {
346			e.preventDefault();
347
348			var $el = $( this ),
349				$target = $( '#' + $el.data( 'target' ) ),
350				tab = $el.data( 'tab' );
351
352			if ( !$target.length ) {
353				return;
354			}
355
356			sober.openModal( $target, tab );
357		} );
358
359		sober.$body.on( 'click', '.close-modal, .sober-modal-backdrop', function ( e ) {
360			e.preventDefault();
361
362			sober.closeModal();
363		} );
364
365		// Close when press escape button
366		$( document ).on( 'keyup', function ( e ) {
367			if ( e.keyCode === 27 ) {
368				sober.closeModal();
369			}
370		} );
371	};
372
373	/**
374	 * Open modal
375	 *
376	 * @param $modal
377	 * @param tab
378	 */
379	sober.openModal = function ( $modal, tab ) {
380		$modal = $modal instanceof jQuery ? $modal : $( $modal );
381
382		if ( ! $modal.length ) {
383			return;
384		}
385
386		sober.$body.addClass( 'modal-open' );
387		$modal.fadeIn();
388		$modal.addClass( 'open' );
389
390		if ( tab ) {
391			var $tab = $modal.find( '.tab-nav' ).filter( '[data-tab="' + tab + '"]' );
392
393			$tab.trigger( 'click' );
394		}
395	};
396
397	/**
398	 * Close modal
399	 */
400	sober.closeModal = function () {
401		sober.$body.removeClass( 'modal-open' );
402
403		var $opened = $( '.sober-modal.open' );
404
405		$opened.fadeOut( function () {
406			$( this ).removeClass( 'open' );
407		} );
408
409		sober.$body.trigger( 'sober_modal_closed', [$opened] );
410	};
411
412	/*
413	 * Remove Cart Item
414	 */
415	sober.removeCartItem = function () {
416		var $cartModal = $( '#cart-modal' );
417
418		$cartModal.on( 'click', '.remove', function ( e ) {
419			e.preventDefault();
420			$cartModal.addClass( 'loading' );
421			sober.block( $cartModal );
422			var currentURL = $( this ).attr( 'href' );
423
424			$.ajax( {
425				type    : 'GET',
426				url     : currentURL,
427				dataType: 'html',
428				success : function () {
429					$( document.body ).trigger( 'wc_fragment_refresh' );
430
431					$( document.body ).on( 'wc_fragments_refreshed', function () {
432						$cartModal.removeClass( 'loading' );
433						sober.unblock( $cartModal );
434					} );
435				}
436			} );
437		} );
438	};
439
440	/**
441	 * Toggle side menu and its' child items
442	 */
443	sober.toggleSideMenu = function () {
444		// Toggle side menu
445		sober.$body.on( 'click', '.toggle-nav', function () {
446			var target = '#' + $( this ).data( 'target' );
447
448			$( target ).toggleClass( 'open' );
449			sober.$body.toggleClass( 'side-menu-opened' );
450		} );
451
452		// Close when click to backdrop
453		sober.$body.on( 'click touchstart', '.side-menu-backdrop', function () {
454			$( '.side-menu' ).removeClass( 'open' );
455			sober.$body.removeClass( 'side-menu-opened' );
456		} );
457
458		// Add class 'open' to current menu item
459		sober.$sideMenu.find( '.menu > .menu-item-has-children, .menu > ul > .menu-item-has-children' ).filter( function () {
460			return $( this ).hasClass( 'current-menu-item' ) || $( this ).hasClass( 'current-menu-ancestor' );
461		} ).addClass( 'open' );
462
463		// Toggle sub-menu
464		sober.$sideMenu.on( 'click', '.menu > .menu-item-has-children > a, .menu > ul > .menu-item-has-children > a', function ( e ) {
465			e.stopPropagation();
466			e.preventDefault();
467
468			$( this ).parent().toggleClass( 'open' ).children( 'ul' ).slideToggle();
469			$( this ).parent().siblings( '.open' ).removeClass( 'open' ).children( 'ul' ).slide
469Up();
470		} );
471	};
472
473	/**
474	 * Focusing inputs and adds 'active' class
475	 */
476	sober.focusInputs = function () {
477
478		$( '.woocommerce-account, .woocommerce-checkout' ).on( 'focus', '.input-text', function () {
479			$( this ).closest( '.form-row' ).addClass( 'active' );
480		} ).on( 'focusout', '.input-text', function () {
481			if ( $( this ).val() === '' ) {
482				$( this ).closest( '.form-row' ).removeClass( 'active' );
483			}
484		} ).find( '.input-text' ).each( function () {
485			if ( $( this ).val() !== '' ) {
486				$( this ).closest( '.form-row' ).addClass( 'active' );
487			}
488		} );
489
490
491		$( '#commentform' ).on( 'focus', ':input', function () {
492			$( this ).closest( 'p' ).addClass( 'active' );
493		} ).on( 'focusout', ':input', function () {
494			if ( $( this ).val() === '' ) {
495				$( this ).closest( 'p' ).removeClass( 'active' );
496			}
497		} ).find( ':input' ).each( function () {
498			if ( $( this ).val() !== '' ) {
499				$( this ).closest( 'p' ).addClass( 'active' );
500			}
501		} );
502
503	};
504
505	/**
506	 * Toggle tabs
507	 */
508	sober.toggleTabs = function () {
509		sober.$body.on( 'click', '.tabs-nav .tab-nav', function () {
510			var $tab = $( this ),
511				tab = $tab.data( 'tab' );
512
513			if ( $tab.hasClass( 'active' ) ) {
514				return;
515			}
516
517			$tab.addClass( 'active' ).siblings( '.active' ).removeClass( 'active' );
518			$tab.closest( '.tabs-nav' ).next( '.tab-panels' )
519				.children( '[data-tab="' + tab + '"]' ).addClass( 'active' )
520				.siblings( '.active' ).removeClass( 'active' );
521		} )
522	};
523
524	/**
525	 * Make products filterable with Isotope
526	 */
527	sober.filterProducts = function () {
528		$( 'body.archive ul.products' ).imagesLoaded( function () {
529			$( this.elements ).isotope( {
530				itemSelector      : '.product',
531				transitionDuration: 700,
532				layoutMode        : 'fitRows',
533				isOriginLeft      : !(sober.data.isRTL === '1')
534			} );
535		} );
536
537		$( '.products-filter' ).on( 'click', 'li', function ( e ) {
538			e.preventDefault();
539
540			var $this = $( this ),
541				selector = $this.attr( 'data-filter' );
542
543			if ( $this.hasClass( 'active' ) ) {
544				return;
545			}
546			var q = $.query;
547			// https://github.com/alrusdi/jquery-plugin-query-object
548			switch(selector) {
549			    case 'remarquables':
550			    	q = $.query.set("paged", '1').REMOVE("product_cat").set("product_cat", 'remarquables').set("filtre", '1').REMOVE("woof_new").REMOVE("stock").set("stock", 'instock');
551			        break;
552			    case 'soldes':
553			    	q = $.query.set("paged", '1').REMOVE("product_cat").set("product_cat", 'promotion-10,promotion-30,promotion-50').set("filtre", '1').REMOVE("woof_new").REMOVE("stock").set("stock", 'instock');
554			        break;
555			    case 'new':
556			    	q = $.query.set("paged", '1').set("woof_new", '1').set("filtre", '1').REMOVE("product_cat").REMOVE("stock").set("stock", 'instock');
557			        break;
558			    case 'vendus':
559			    	q = $.query.set("paged", '1').REMOVE("stock").set("stock", 'outofstock').set("filtre", '1').REMOVE("product_cat").REMOVE("woof_new");
560			        break;
561			    default:
562			    	q = $.query.empty().set("filtre", '1').set("stock", 'instock');
563					break;			    
564			} 
565
566			$this.addClass( 'active' ).siblings( '.active' ).removeClass( 'active' );
567		    window.location.search = q;
568			// if (selector != "")
569			// 	location.href = "/catalogue/?"+selector;
570			// else
571			// 	location.href = "/catalogue/";
572			// $this.closest( '.shop-toolbar' ).next( 'ul.products' ).isotope( {
573			// 	filter: selector
574			// } );
575		} );
576	};
577
578	/**
579	 * Use select2 to styling the dropdown of the ordring
580	 */
581	sober.sortProducts = function() {
582		if ( ! $.fn.select2 ) {
583			return;
584		}
585
586		$( '.woocommerce-ordering select' ).select2( {
587			minimumResultsForSearch: -1,
588			width: 'auto',
589			dropdownAutoWidth: true
590		} );
591	};
592
593	/**
594	 * Change product quantity
595	 */
596	sober.productQuantity = function () {
597		sober.$body.on( 'click', '.quantity .increase, .quantity .decrease', function ( e ) {
598			e.preventDefault();
599
600			var $this = $( this ),
601				$qty = $this.siblings( '.qty' ),
602				current = parseInt( $qty.val(), 10 ),
603				min = parseInt( $qty.attr( 'min' ), 10 ),
604				max = parseInt( $qty.attr( 'max' ), 10 );
605
606			min = min ? min : 1;
607			max = max ? max : current + 1;
608
609			if ( $this.hasClass( 'decrease' ) && current > min ) {
610				$qty.val( current - 1 );
611				$qty.trigger( 'change' );
612			}
613			if ( $this.hasClass( 'increase' ) && current < max ) {
614				$qty.val( current + 1 );
615				$qty.trigger( 'change' );
616			}
617		} );
618	};
619
620	/**
621	 * Make up sells products be sticky
622	 */
623	sober.stickUpSells = function () {
624		if ( !sober.$body.hasClass( 'product-style-3' ) ) {
625			return;
626		}
627
628		var $topbar = $( '#topbar' ),
629			$header = $( '#masthead' ),
630			$upsells = $( '.upsells' );
631
632		if ( !$upsells.length ) {
633			return;
634		}
635
636		var $primary = $( '#primary' );
637
638		var offset = $topbar.length ? $topbar.outerHeight() : 0;
639		offset += $header.length ? $header.outerHeight() : 0;
640
641		$( window ).on( 'scroll', function () {
642			if ( $( document ).scrollTop() >= offset ) {
643				$upsells.addClass( 'sticky' );
644
645				if ( !$upsells.data( 'wrap' ) ) {
646					$upsells.wrap( '<div id="upsells-wrap" class="upsells-wrap"/>' );
647					$upsells.data( 'wrap', true );
648				}
649			} else {
650				$upsells.removeClass( 'sticky' );
651
652				if ( $upsells.data( 'wrap' ) ) {
653					$upsells.unwrap();
654					$upsells.data( 'wrap', false );
655				}
656			}
657
658			if ( $( window ).scrollTop() >= $primary.offset().top + $primary.outerHeight() - window.innerHeight ) {
659				var $wrap = $( '#upsells-wrap' );
660
661				$wrap.addClass( 'sticky-bottom' ).css( 'top', function () {
662					return $( window ).scrollTop() - $primary.offset().top;
663				} );
664
665				if ( $wrap.outerHeight() <= $upsells.outerHeight() ) {
666					$wrap.addClass( 'reach-bottom' );
667				} else {
668					$wrap.removeClass( 'reach-bottom' );
669				}
670			} else {
671				$( '#upsells-wrap' ).removeClass( 'sticky-bottom' ).css( 'top', 0 );
672			}
673		} ).trigger( 'scroll' );
674	};
675
676	/**
677	 * Prepare and init carousel for up sell products
678	 */
679	sober.upsellsCarousel = function () {
680		if ( !sober.$body.hasClass( 'product-style-3' ) ) {
681			return;
682		}
683
684		var $upsells = $( '.upsells' );
685
686		if ( !$upsells.length ) {
687			return;
688		}
689
690		if ( $upsells.find( 'li.product' ).length > 4 ) {
691			$upsells.find( 'ul.products' ).addClass( 'owl-carousel' ).owlCarousel( {
692				rtl          : sober.data.isRTL === "1",
693				owl2row      : true,
694				owl2rowTarget: 'product',
695				dots         : true,
696				nav          : true,
697				navText      : ['<svg viewBox="0 0 20 20"><use xlink:href="#left-arrow"></use></svg>', '<svg viewBox="0 0 20 20"><use xlink:href="#right-arrow"></use></svg>'],
698				items        : 2,
699				responsive   : {
700					0   : {
701						items: 1
702					},
703					992 : {
704						items: 1
705					},
706					1200: {
707						items: 2
708					}
709				}
710			} );
711		}
712	};
713
714	/**
715	 * Show photoSwipe lightbox for product images
716	 */
717	sober.productImagesLightbox = function () {
718		if ( 'no' === sober.data.lightbox || '0' === sober.data.lightbox ) {
719			return;
720		}
721
722		var $gallery = $( 'div.product div.images' ),
723			$slides = $( '.woocommerce-product-gallery__slider .woocommerce-product-gallery__image', $gallery );
724
725		if ( !$gallery.length ) {
726			return;
727		}
728
729		$gallery.on( 'click', '.woocommerce-product-gallery__slider .woocommerce-product-gallery__image a', function ( e ) {
730			e.preventDefault();
731
732			var items = getGalleryItems(),
733				$target = $( e.target ),
734				$clicked = $target.closest( '.owl-item' ),
735				options = {
736					index              : $clicked.length ? $clicked.index() : $target.closest( '.woocommerce-product-gallery__image' ).index(),
737					history            : false,
738					bgOpacity          : 0.85,
739					showHideOpacity    : true,
740					mainClass          : 'pswp--minimal-dark',
741					captionEl          : true,
742					fullscreenEl       : false,
743					shareEl            : false,
744					tapToClose         : true,
745					tapToToggleControls: false
746				};
747
748			var lightBox = new PhotoSwipe( $( '.pswp' ).get(0), window.PhotoSwipeUI_Default, items, options );
749			lightBox.init();
750		} );
751
752		/**
753		 * Private function to get gallery items
754		 * @returns {Array}
755		 */
756		function getGalleryItems() {
757			var items = [];
758
759			if ( $slides.length > 0 ) {
760				$slides.each( function( i, el ) {
761					var img = $( el ).find( 'img' ),
762						large_image_src = img.attr( 'data-large_image' ),
763						large_image_w   = img.attr( 'data-large_image_width' ),
764						large_image_h   = img.attr( 'data-large_image_height' ),
765						item            = {
766							src  : large_image_src,
767							w    : large_image_w,
768							h    : large_image_h,
769							title: img.attr( 'data-caption' ) ? img.attr( 'data-caption' ) : ''
770						};
771					items.push( item );
772				} );
773			}
774
775			return items;
776		}
777	};
778
779	/**
780	 * Make product summary be sticky when use product layout 1
781	 */
782	sober.stickyProductSummary = function () {
783		if ( $.fn.stick_in_parent && sober.$window.width() > 767 ) {
784			$( 'div.product .sticky-summary' ).stick_in_parent( {
785				parent: '.product-summary'
786			} );
787		}
788	};
789
790	/**
791	 * Back to top icon
792	 */
793	sober.backToTop = function () {
794		sober.$body.on( 'click', '#gotop', function ( e ) {
795			e.preventDefault();
796
797			$( 'html, body' ).animate( {scrollTop: 0}, 'slow' );
798		} );
799	};
800
801	/**
802	 * Toggle product filter widgets
803	 */
804	sober.toggleProductFilter = function () {
805		sober.$body.on( 'click', '.toggle-filter', function ( e ) {
806			e.preventDefault();
807
808			$( this ).next( '.filter-widgets' ).fadeIn( function () {
809				$( this ).addClass( 'active' );
810			} );
811		} ).on( 'click', '.filter-widgets button.close', function () {
812			$( this ).closest( '.filter-widgets' ).fadeOut( function () {
813				$( this ).removeClass( 'active' );
814			} );
815		} );
816
817	};
818
819	/**
820	 * Toggle product quick view
821	 */
822	sober.productQuickView = function () {
823		if ( !sober.$body.hasClass( 'product-quickview-enable' ) ) {
824			return;
825		}
826
827		var target = 'ul.products .woocommerce-LoopProduct-link';
828
829		switch ( sober.data.quickview ) {
830			case 'buy_button':
831				target = 'ul.products .add_to_cart_button, ul.products .button.product_type_external';
832				break;
833
834			case 'view_button':
835				target = 'ul.products .quick_view_button';
836				break;
837
838			case 'title':
839				target = 'ul.products h3 a';
840				break;
841		}
842
843		sober.$body.on( 'click', target, function ( e ) {
844			if ( sober.$window.width() <= 768 ) {
845				return;
846			}
847
848			e.preventDefault();
849
850			var $a = $( this ),
851				url = $a.data( 'url' ) ? $a.data( 'url' ) : $a.attr( 'href' ),
852				$modal = $( '#quick-view-modal' ),
853				$product = $modal.find( '.product' ),
854				$button = $modal.find( '.modal-header .close-modal' ).first().clone();
855
856			$product.hide().html( '' ).addClass( 'invisible' );
857			$modal.addClass( 'loading' );
858			sober.openModal( $modal );
859
860			$.get( url, function ( response ) {
861				var $html = $( response ),
862					$summary = $html.find( '#content' ).find( '.product-summary' ),
863					$gallery = $summary.find( '.images' ),
864					$variations = $summary.find( '.variations_form' ),
865					$carousel = $( '.woocommerce-product-gallery__slider', $gallery );
866
867				// Remove unused elements
868				$summary.find( '.product-toolbar' ).remove();
869				$summary.find( 'h1.product_title' ).wrapInner( '<a href="' + url + '"></a>' );
870				$gallery.find( '.thumbnails' ).remove();
871				$product.show().html( $summary ).prepend( $button );
872
873				// Force height for images
874				$carousel.find( 'img' ).css( 'height', $product.outerHeight() );
875
876				if ( $carousel.children().length > 1 ) {
877					$carousel.addClass( 'owl-carousel' ).owlCarousel( {
878						rtl       : sober.data.isRTL === "1",
879						items     : 1,
880						smartSpeed: 500,
881						dots      : false,
882						nav       : true,
883						navText   : ['<svg width="20" height="20"><use xlink:href="#left-arrow"></use></svg>', '<svg width="20" height="20"><use xlink:href="#right-arrow"></use></svg>'],
884					} );
885				}
886
887				$gallery.css( 'opacity', 1 );
888
889				$carousel.on( 'click', '.woocommerce-product-gallery__image a', function( event ) {
890					event.preventDefault();
891				} );
892
893				$variations.wc_variation_form().find( '.variations select:eq(0)' ).change();
894
895				if ( $.fn.tawcvs_variation_swatches_form ) {
896					$variations.tawcvs_variation_swatches_form();
897					sober.modifyVariationSwatches( $variations );
898				}
899
900				$variations.on( 'reset_image found_variation', function() {
901					$carousel.trigger( 'to.owl.carousel', [0] );
902				} );
903
904				$modal.removeClass( 'loading' );
905				$product.removeClass( 'invisible' );
906
907				if ( typeof SimpleScrollbar !== 'undefined' ) {
908					SimpleScrollbar.initEl( $summary.find( '.summary' ).get( 0 ) );
909				}
910
911				sober.$body.trigger( 'sober_quickview_opened', [$html, $modal, sober] );
912			}, 'html' );
913
914			if ( 'buy_button' === sober.data.quickview ) {
915				return false; // Prevent ajax add to cart
916			}
917		} );
918	};
919
920	/**
921	 * Product instance search
922	 */
923	sober.instanceSearch = function () {
924		var xhr = null,
925			searchCache = {},
926			$modal = $( '#search-modal' ),
927			$form = $modal.find( 'form' ),
928			$search = $form.find( 'input.search-field' ),
929			$results = $modal.find( '.search-results' );
930
931		$modal.on( 'keyup', '.search-field', function ( e ) {
932			var valid = false;
933
934			if ( typeof e.which === 'undefined' ) {
935				valid = true;
936			} else if ( typeof e.which === 'number' && e.which > 0 ) {
937				valid = !e.ctrlKey && !e.metaKey && !e.altKey;
938			}
939
940			if ( !valid ) {
941				return;
942			}
943
944			if ( xhr ) {
945				xhr.abort();
946			}
947
948			search();
949		} ).on( 'change', '.product-cats input', function () {
950			if ( xhr ) {
951				xhr.abort();
952			}
953
954			search();
955		} ).on( 'click', '.search-reset', function () {
956			if ( xhr ) {
957				xhr.abort();
958			}
959
960			$results.find( '.woocommerce, .buttons' ).slideUp( function () {
961				$modal.removeClass( 'searching searched found-products found-no-product invalid-length' );
962			} );
963		} ).on( 'focusout', '.search-field', function () {
964			if ( $search.val().length < 2 ) {
965				$results.find( '.woocommerce, .buttons' ).slideUp( function () {
966					$modal.removeClass( 'searching searched found-products found-no-product invalid-length' );
967				} );
968			}
969		} );
970
971		/**
972		 * Private function for search
973		 */
974		function search() {
975			var keyword = $search.val();
976
977			if ( keyword.length < 2 ) {
978				$modal.removeClass( 'searching found-products found-no-product' ).addClass( 'invalid-length' );
979				return;
980			}
981
982			var url = $form.attr( 'action' ) + '?' + $form.serialize();
983
984			$modal.removeClass( 'found-products found-no-product' ).addClass( 'searching' );
985
986			if ( keyword in searchCache ) {
987				var result = searchCache[keyword];
988
989				$modal.removeClass( 'searching' );
990
991				if ( result.found ) {
992					$modal.addClass( 'found-products' );
993
994					$results.find( '.woocommerce' ).html( result.products );
995					$results.find( '.buttons a' ).attr( 'href', url );
996
997					$results.find( '.woocommerce, .buttons' ).slideDown( function () {
998						$modal.removeClass( 'invalid-length' );
999					} );
1000				} else {
1001					$modal.addClass( 'found-no-product' );
1002
1003					$results.find( '.woocommerce' ).html( $( '<div class="not-found text-center" />' ).text( result.text ) );
1004					$results.find( '.buttons a' ).attr( 'href', '#' );
1005
1006					$results.find( '.buttons' ).slideUp();
1007					$results.find( '.woocommerce' ).slideDown( function () {
1008						$modal.removeClass( 'invalid-length' );
1009					} );
1010				}
1011
1012				$modal.addClass( 'searched' );
1013			} else {
1014				xhr = $.get( url, function ( response ) {
1015					var $html = $( response ),
1016						$products = $html.find( '#content #primary ul.products' ),
1017						$info = $html.find( '#content #primary .woocommerce-info' );
1018
1019					$modal.removeClass( 'searching' );
1020
1021					if ( $products.length ) {
1022						$products.children( '.last' ).nextAll().remove();
1023
1024						$modal.addClass( 'found-products' );
1025
1026						$results.find( '.woocommerce' ).html( $products );
1027						$results.find( '.buttons a' ).attr( 'href', url );
1028
1029						$results.find( '.woocommerce, .buttons' ).slideDown( function () {
1030							$modal.removeClass( 'invalid-length' );
1031						} );
1032
1033						// Cache
1034						searchCache[keyword] = {
1035							found   : true,
1036							products: $products
1037						};
1038					} else if ( $info.length ) {
1039						$modal.addClass( 'found-no-product' );
1040
1041						$results.find( '.woocommerce' ).html( $( '<div class="not-found text-center" />' ).text( $info.text() ) );
1042						$results.find( '.buttons a' ).attr( 'href', '#' );
1043
1044						$results.find( '.buttons' ).slideUp();
1045						$results.find( '.woocommerce' ).slideDown( function () {
1046							$modal.removeClass( 'invalid-length' );
1047						} );
1048
1049						// Cache
1050						searchCache[keyword] = {
1051							found: false,
1052							text : $info.text()
1053						};
1054					}
1055
1056					$modal.addClass( 'searched' );
1057				}, 'html' );
1058			}
1059		}
1060	};
1061
1062	/**
1063	 * Init simple scrollbar
1064	 */
1065	sober.fakeScrollbar = function () {
1066		var el = document.querySelector( '.primary-menu.side-menu' );
1067
1068		if ( el && typeof SimpleScrollbar !== 'undefined' ) {
1069			SimpleScrollbar.initEl( el );
1070		}
1071	};
1072
1073	/**
1074	 * Sticky header
1075	 */
1076	sober.stickyHeader = function () {
1077		if ( !sober.data.sticky_header || 'none' === sober.data.sticky_header ) {
1078			return;
1079		}
1080
1081		var header = document.getElementById( 'masthead' );
1082		var topbar = document.getElementById( 'topbar' );
1083		var offset = 0;
1084
1085		// Prepare for white header
1086		if (
1087			sober.$body.hasClass( 'header-white' )
1088			|| ( sober.$body.hasClass( 'no-page-header' ) && !sober.$body.hasClass( 'page-title-hidden' ) && !sober.$body.hasClass( 'page-template-homepage' ) )
1089		) {
1090			if ( topbar ) {
1091				topbar.style.marginBottom = header.clientHeight + 'px';
1092			} else {
1093				document.getElementById( 'page' ).style.paddingTop = header.clientHeight + 'px';
1094			}
1095		}
1096
1097		if ( 'smart' === sober.data.sticky_header && typeof Headroom !== 'undefined' ) {
1098			offset = topbar ? topbar.clientHeight : 1;
1099
1100			var stickyHeader = new Headroom( header, {
1101				offset  : offset,
1102				onTop   : function () {
1103					setTimeout( function () {
1104						header.classList.remove( 'headroom--animation' );
1105					}, 500 );
1106				},
1107				onNotTop: function () {
1108					setTimeout( function () {
1109						header.classList.add( 'headroom--animation' );
1110					}, 10 );
1111				}
1112			} );
1113
1114			stickyHeader.init();
1115		} else if ( 'normal' === sober.data.sticky_header ) {
1116			offset = topbar ? topbar.clientHeight : 1;
1117			sticky();
1118
1119			sober.$window.on( 'scroll', function () {
1120				sticky();
1121			} );
1122		}
1123
1124		/**
1125		 * Private function for sticky header
1126		 */
1127		function sticky() {
1128			if ( sober.$window.scrollTop() >= offset ) {
1129				header.classList.add( 'sticky' );
1130			} else {
1131				header.classList.remove( 'sticky' );
1132			}
1133		}
1134	};
1135
1136	/**
1137	 * Initialize isotope for portfolio items
1138	 */
1139	sober.portfolioFilter = function () {
1140		var $items = $( '.portfolio-items' );
1141
1142		if ( !$items.length ) {
1143			return;
1144		}
1145
1146		var options = {
1147			itemSelector      : '.portfolio',
1148			transitionDuration: 700,
1149			isOriginLeft      : !(sober.data.isRTL === '1')
1150		};
1151
1152		if ( sober.$body.hasClass( 'portfolio-fullwidth' ) ) {
1153			options.masonry = {
1154				columnWidth: '.col-md-3'
1155			};
1156		}
1157
1158		$items.imagesLoaded( function () {
1159			$( this.elements ).isotope( options );
1160		} );
1161
1162		var $filter = $( '.portfolio-filter' );
1163
1164		$filter.on( 'click', 'li', function ( e ) {
1165			e.preventDefault();
1166
1167			var $this = $( this ),
1168				selector = $this.attr( 'data-filter' );
1169
1170			if ( $this.hasClass( 'active' ) ) {
1171				return;
1172			}
1173
1174			$this.addClass( 'active' ).siblings( '.active' ).removeClass( 'active' );
1175			$this.closest( '.portfolio-filter' ).next( '.portfolio-items' ).isotope( {
1176				filter: selector
1177			} );
1178		} );
1179	};
1180
1181	/**
1182	 * Add extra script for product variation swatches
1183	 * This function will run after plugin swatches did
1184	 */
1185	sober.productVariationSwatches = function () {
1186		sober.$body.on( 'tawcvs_initialized', function () {
1187			var $form = $( '.variations_form' );
1188
1189			sober.modifyVariationSwatches( $form );
1190		} );
1191	};
1192
1193	/**
1194	 * Modify variation swatches
1195	 * This function is used in sober.productVariationSwatches and sober.productQuickView
1196	 *
1197	 * @param $form
1198	 */
1199	sober.modifyVariationSwatches = function ( $form ) {
1200		var $variables = $form.find( '.variations .variable' );
1201
1202		// Remove class "swatches-support" if there is no swatches in this product
1203		var hasSwatches = false;
1204		$variables.each( function() {
1205			if ( $( this ).hasClass( 'swatches' ) ) {
1206				hasSwatches = true;
1207			}
1208		} );
1209
1210		if ( ! hasSwatches ) {
1211			$form.removeClass( 'swatches-support' );
1212		}
1213
1214		// Add class for the last even variation
1215		if ( $variables.length % 2 ) {
1216			$variables.last().addClass( 'wide-variable' );
1217		}
1218
1219		// Change alert style
1220		$form.off( 'tawcvs_no_matching_variations' );
1221		$form.on( 'tawcvs_no_matching_variations', function () {
1222			event.preventDefault();
1223
1224			$form.find( '.woocommerce-variation.single_variation' ).show();
1225			if ( typeof wc_add_to_cart_variation_params !== 'undefined' ) {
1226				$form.find( '.single_variation' ).stop( true, true ).slideDown( 500 ).html( '<p class="invalid-variation-combination">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
1227			}
1228		} );
1229	};
1230
1231	/**
1232	 * Init product gallery as a slider
1233	 */
1234	sober.productGallerySlider = function() {
1235		if ( ! sober.$body.hasClass( 'single-product' ) ) {
1236			return;
1237		}
1238
1239		var $gallery = $( 'div.product div.images' ),
1240			$carousel = $( '.woocommerce-product-gallery__slider', $gallery ),
1241			$thumbnails = $( '.thumbnails', $gallery );
1242
1243		if ( !sober.$body.hasClass( 'product-style-1' ) && !sober.$body.hasClass( 'product-style-4' ) && $carousel.children().length > 1 && !$carousel.hasClass( 'owl-loaded' ) ) {
1244			$carousel.addClass( 'owl-carousel' ).owlCarousel( {
1245				rtl       : sober.data.isRTL === "1",
1246				dots      : false,
1247				items     : 1,
1248				loop      : false,
1249				responsive: {
1250					0: {
1251						items: 1
1252					}
1253				}
1254			} );
1255		}
1256
1257		if ( sober.$body.hasClass( 'product-style-1' ) && $carousel.children().length > 1 ) {
1258			if ( sober.$window.width() < 992 && ! $carousel.hasClass( 'owl-carousel' ) ) {
1259				$carousel.addClass( 'owl-carousel' ).owlCarousel( {
1260					rtl       : sober.data.isRTL === "1",
1261					items     : 1,
1262					loop      : false,
1263					margin    : 10,
1264					responsive: {
1265						0: {
1266							items: 1
1267						}
1268					}
1269				} );
1270			} else if ( sober.$window.width() >= 992 && $carousel.hasClass( 'owl-carousel' ) ) {
1271				$carousel.trigger( 'destroy.owl.carousel' ).removeClass( 'owl-carousel' );
1272			}
1273		}
1274
1275		if ( sober.$body.hasClass( 'product-style-4' ) && $carousel.children().length > 1 ) {
1276			var start = $carousel.children().length > 2 ? 1 : 0;
1277
1278			$carousel.addClass( 'owl-carousel' ).owlCarousel( {
1279				rtl   : sober.data.isRTL === "1",
1280				items : 2,
1281				startPosition: start,
1282				loop  : false,
1283				margin: 30,
1284				center: true,
1285				dots: false,
1286				nav: true,
1287				navText: ['<svg viewBox="0 0 20 20"><use xlink:href="#left-arrow"></use></svg>', '<svg viewBox="0 0 20 20"><use xlink:href="#right-arrow"></use></svg>']
1288			} );
1289		}
1290
1291		// Show it
1292		$gallery.css( 'opacity', 1 );
1293
1294		// Use thumbnails as pagination
1295		$gallery.on( 'click', '.thumbnails .woocommerce-product-gallery__image a', function( event ) {
1296			event.preventDefault();
1297
1298			var $image = $( this ).closest( '.woocommerce-product-gallery__image' );
1299
1300			$carousel.trigger( 'to.owl.carousel', [$image.index()] );
1301		} );
1302
1303		// Change the active state of thumbnails
1304		$carousel.on( 'translated.owl.carousel', function( event ) {
1305			$thumbnails.children().removeClass( 'active' ).eq( event.item.index ).addClass( 'active' );
1306		} );
1307
1308		// Variation form changed
1309		$( '.variations_form' ).on( 'reset_image found_variation', function() {
1310			$carousel.trigger( 'to.owl.carousel', [0] );
1311		} ).on( 'reset_image', function() {
1312			$thumbnails.children( ':eq(0)' ).find( 'img' ).wc_reset_variation_attr( 'src' );
1313		} ).on( 'found_variation', function( event, variation ) {
1314			$thumbnails.children( ':eq(0)' ).find( 'img' ).wc_set_variation_attr( 'src', variation.image.thumb_src );
1315		} );
1316	};
1317
1318	/**
1319	 * Zoom product image when hover
1320	 */
1321	sober.productImageZoom = function() {
1322		var $thumbnails = $( '.product-thumbnail-zoom' );
1323
1324		$thumbnails.each( function () {
1325			var $el = $( this );
1326
1327			$el.zoom( {
1328				url: $el.attr( 'data-zoom_image' )
1329			} );
1330		} );
1331	};
1332
1333	/**
1334	 * Display product thumbnail images as slider
1335	 */
1336	sober.productImageSlider = function() {
1337		$( '.product-images__slider' ).owlCarousel( {
1338			items: 1,
1339			lazyLoad: true,
1340			dots: false,
1341			nav: true,
1342			navText: ['<svg viewBox="0 0 14 20"><use xlink:href="#left"></use></svg>', '<svg viewBox="0 0 14 20"><use xlink:href="#right"></use></svg>']
1343		} );
1344	};
1345
1346	/**
1347	 * Ajaxify add to cart button on single product page
1348	 */
1349	sober.singeProductAjaxAddToCart = function () {
1350		if ( 'yes' !== sober.data.single_ajax_add_to_cart ) {
1351			return;
1352		}
1353
1354		sober.$body.on( 'submit', 'form.cart', function () {
1355			var $form = $( this ),
1356				$button = $form.find( '.single_add_to_cart_button' ),
1357				url = $form.attr( 'action' ) ? $form.attr( 'action' ) : window.location.href;
1358
1359			if ( $button.hasClass( 'loading' ) ) {
1360				return false;
1361			}
1362
1363			$button.removeClass( 'added' ).addClass( 'loading' );
1364
1365			$.ajax( {
1366				url    : url,
1367				data   : $form.serialize(),
1368				method : 'POST',
1369				success: function ( response ) {
1370					$button.removeClass( 'loading' ).addClass( 'added' );
1371
1372					// Show alert bar
1373					if ( sober.data.open_cart_modal_after_add !== '1' ) {
1374						var $message = $( response ).find( '.woocommerce-error, .woocommerce-info, .woocommerce-message' ),
1375							$alert = $( '.sober-alert-bar' );
1376
1377						if ( !$alert.length ) {
1378							$alert = $( '<div class="sober-alert-bar"></div>' );
1379							sober.$body.append( $alert );
1380						}
1381
1382						$alert.html( $message );
1383						setTimeout( function () {
1384							$alert.addClass( 'active' );
1385						}, 500 );
1386
1387						// Auto hide the alert bar after 5 seconds. Apply for success actions only
1388						if ( $message.hasClass( 'woocommerce-message' ) ) {
1389							setTimeout( function () {
1390								$alert.removeClass( 'active' );
1391							}, 5000 );
1392						}
1393					} else {
1394						sober.$body.trigger( 'added_to_cart' );
1395					}
1396
1397					// Trigger fragment refresh
1398					sober.$body.trigger( 'wc_fragment_refresh' );
1399
1400					if ( typeof wc_add_to_cart_params !== 'undefined' ) {
1401						if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' && wc_add_to_cart_params.cart_url ) {
1402							window.location.href = wc_add_to_cart_params.cart_url;
1403						}
1404					}
1405				}
1406			} );
1407
1408			return false;
1409		} );
1410
1411		// Close alert bar
1412		sober.$body.on( 'click', '.sober-alert-bar .close', function ( e ) {
1413			e.preventDefault();
1414
1415			$( this ).closest( '.sober-alert-bar' ).removeClass( 'active' );
1416		} );
1417	};
1418
1419	/**
1420	 * Open the cart modal after successful addition
1421	 */
1422	sober.openCartModalAfterAdd = function () {
1423		if ( sober.data.open_cart_modal_after_add !== '1' ) {
1424			return;
1425		}
1426
1427		sober.$body.on( 'added_to_cart', function () {
1428			sober.closeModal();
1429			sober.openModal( '#cart-modal', 'cart' );
1430		} );
1431	};
1432
1433	/**
1434	 * Init parallax for page header elements
1435	 */
1436	sober.pageHeaderParallax = function () {
1437		if ( typeof Rellax === 'undefined' ) {
1438			return;
1439		}
1440
1441		var $title = $( '.page-header .page-title' ),
1442			$breadcrumb = $( '.page-header .breadcrumb' );
1443
1444		if ( 'up' === sober.data.page_header_parallax ) {
1445			if ( $title.length ) {
1446				new Rellax( '.page-header .page-title', {speed: 1} );
1447			}
1448			if ( $breadcrumb.length ) {
1449				new Rellax( '.page-header .breadcrumb', {speed: 2} );
1450			}
1451		} else if ( 'down' === sober.data.page_header_parallax ) {
1452			if ( $title.length ) {
1453				new Rellax( '.page-header .page-title', {speed: -2} );
1454			}
1455			if ( $breadcrumb.length ) {
1456				new Rellax( '.page-header .breadcrumb', {speed: -1} );
1457			}
1458		}
1459	};
1460
1461	/**
1462	 * Add page preloader
1463	 */
1464	sober.preload = function () {
1465		var $preloader = $( '#preloader' );
1466
1467		if ( ! $preloader.length ) {
1468			return;
1469		}
1470
1471		sober.$window.on( 'beforeunload', function() {
1472			$preloader.fadeIn( 'slow' );
1473		});
1474
1475		$preloader.fadeOut( 800 );
1476	};
1477
1478	/**
1479	 * Call functions for responsiveness
1480	 */
1481	sober.responsive = function () {
1482		// Initialize fitvids
1483		sober.responsiveVideos();
1484
1485		// Init/destroy product image carousel for product style 1
1486		sober.$window.on( 'resize', sober.productGallerySlider );
1487	};
1488
1489	/**
1490	 * Responsive videos
1491	 */
1492	sober.responsiveVideos = function () {
1493		$( document.body ).fitVids();
1494	};
1495
1496	/**
1497	 * Open popup
1498	 */
1499	sober.popup = function() {
1500		var days = parseInt( sober.data.popup_frequency ),
1501			delay = parseInt( sober.data.popup_visible_delay );
1502
1503		if ( days > 0 && document.cookie.match( /^(.*;)?\s*sober_popup\s*=\s*[^;]+(.*)?$/ ) ) {
1504			return;
1505		}
1506
1507		delay = Math.max( delay, 0 );
1508		delay = 'delay' === sober.data.popup_visible ? delay : 0;
1509
1510		sober.$window.on( 'load', function() {
1511			setTimeout( function() {
1512				sober.openModal( '#popup' );
1513			}, delay * 1000 );
1514		} );
1515
1516		sober.$body.on( 'sober_modal_closed', function (event, modal) {
1517			if ( ! modal.hasClass( 'sober-popup' ) ) {
1518				return;
1519			}
1520
1521			var date = new Date(),
1522				value = date.getTime();
1523
1524			date.setTime( date.getTime() + (days * 24 * 60 * 60 * 1000) );
1525
1526			document.cookie = 'sober_popup=' + value + ';expires=' + date.toGMTString() + ';path=/';
1527		} );
1528	};
1529
1530	/**
1531	 * Show a notification after added a product to cart successfully
1532	 */
1533	sober.addedToCartNotice = function() {
1534		if ( ! sober.data.added_to_cart_notice || ! $.fn.notify ) {
1535			return;
1536		}
1537
1538		$.notify.addStyle( 'sober', {
1539			html: '<div><svg viewBox="0 0 20 20" class="message-icon"><use xlink:href="#success" href="#success"></use></svg><span data-notify-text/></div>'
1540		});
1541
1542		$( document ).on( 'added_to_cart', function() {
1543			$.notify( sober.data.l10n.added_to_cart_notice, {
1544				autoHideDelay: 2000,
vendor: 8,586 bytes, lines 1545-1814
1545				className: 'success',
1546				style: 'sober',
1547				showAnimation: 'fadeIn',
1548				hideAnimation: 'fadeOut'
1549			} );
1550		} );
1551	};
1552
1553	/**
1554	 * Turn off the event handler for terms and conditions link
1555	 */
1556	sober.checkoutTerms = function() {
1557		sober.$body.off( 'click', 'a.woocommerce-terms-and-conditions-link' );
1558	};
1559
1560	/**
1561	 * Document ready
1562	 */
1563	$( function () {
1564		sober.init();
1565	} );
1566})( jQuery );
1567
1568
1569/**
1570 * jQuery.query - Query String Modification and Creation for jQuery
1571 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
1572 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
1573 * Date: 2009/8/13
1574 *
1575 * @author Blair Mitchelmore
1576 * @version 2.2.3
1577 *
1578 **/
1579new function(settings) { 
1580  // Various Settings
1581  var $separator = settings.separator || '&';
1582  var $spaces = settings.spaces === false ? false : true;
1583  var $suffix = settings.suffix === false ? '' : '[]';
1584  var $prefix = settings.prefix === false ? false : true;
1585  var $hash = $prefix ? settings.hash === true ? "#" : "?" : "";
1586  var $numbers = settings.numbers === false ? false : true;
1587
1588  jQuery.query = new function() {
1589    var is = function(o, t) {
1590      return o != undefined && o !== null && (!!t ? o.constructor == t : true);
1591    };
1592    var parse = function(path) {
1593      var m, rx = /\[([^[]*)\]/g, match = /^([^[]+)(\[.*\])?$/.exec(path), base = match[1], tokens = [];
1594      while (m = rx.exec(match[2])) tokens.push(m[1]);
1595      return [base, tokens];
1596    };
1597    var set = function(target, tokens, value) {
1598      var o, token = tokens.shift();
1599      if (typeof target != 'object') target = null;
1600      if (token === "") {
1601        if (!target) target = [];
1602        if (is(target, Array)) {
1603          target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
1604        } else if (is(target, Object)) {
1605          var i = 0;
1606          while (target[i++] != null);
1607          target[--i] = tokens.length == 0 ? value : set(target[i], tokens.slice(0), value);
1608        } else {
1609          target = [];
1610          target.push(tokens.length == 0 ? value : set(null, tokens.slice(0), value));
1611        }
1612      } else if (token && token.match(/^\s*[0-9]+\s*$/)) {
1613        var index = parseInt(token, 10);
1614        if (!target) target = [];
1615        target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
1616      } else if (token) {
1617        var index = token.replace(/^\s*|\s*$/g, "");
1618        if (!target) target = {};
1619        if (is(target, Array)) {
1620          var temp = {};
1621          for (var i = 0; i < target.length; ++i) {
1622            temp[i] = target[i];
1623          }
1624          target = temp;
1625        }
1626        target[index] = tokens.length == 0 ? value : set(target[index], tokens.slice(0), value);
1627      } else {
1628        return value;
1629      }
1630      return target;
1631    };
1632    
1633    var queryObject = function(a) {
1634      var self = this;
1635      self.keys = {};
1636      
1637      if (a.queryObject) {
1638        jQuery.each(a.get(), function(key, val) {
1639          self.SET(key, val);
1640        });
1641      } else {
1642        self.parseNew.apply(self, arguments);
1643      }
1644      return self;
1645    };
1646    
1647    queryObject.prototype = {
1648      queryObject: true,
1649      parseNew: function(){
1650        var self = this;
1651        self.keys = {};
1652        jQuery.each(arguments, function() {
1653          var q = "" + this;
1654          q = q.replace(/^[?#]/,''); // remove any leading ? || #
1655          q = q.replace(/[;&]$/,''); // remove any trailing & || ;
1656          if ($spaces) q = q.replace(/[+]/g,' '); // replace +'s with spaces
1657          
1658          jQuery.each(q.split(/[&;]/), function(){
1659            var key = decodeURIComponent(this.split('=')[0] || "");
1660            var val = decodeURIComponent(this.split('=')[1] || "");
1661            
1662            if (!key) return;
1663            
1664            if ($numbers) {
1665              if (/^[+-]?[0-9]+\.[0-9]*$/.test(val)) // simple float regex
1666                val = parseFloat(val);
1667              else if (/^[+-]?[1-9][0-9]*$/.test(val)) // simple int regex
1668                val = parseInt(val, 10);
1669            }
1670            
1671            val = (!val && val !== 0) ? true : val;
1672            
1673            self.SET(key, val);
1674          });
1675        });
1676        return self;
1677      },
1678      has: function(key, type) {
1679        var value = this.get(key);
1680        return is(value, type);
1681      },
1682      GET: function(key) {
1683        if (!is(key)) return this.keys;
1684        var parsed = parse(key), base = parsed[0], tokens = parsed[1];
1685        var target = this.keys[base];
1686        while (target != null && tokens.length != 0) {
1687          target = target[tokens.shift()];
1688        }
1689        return typeof target == 'number' ? target : target || "";
1690      },
1691      get: function(key) {
1692        var target = this.GET(key);
1693        if (is(target, Object))
1694          return jQuery.extend(true, {}, target);
1695        else if (is(target, Array))
1696          return target.slice(0);
1697        return target;
1698      },
1699      SET: function(key, val) {
1700        var value = !is(val) ? null : val;
1701        var parsed = parse(key), base = parsed[0], tokens = parsed[1];
1702        var target = this.keys[base];
1703        this.keys[base] = set(target, tokens.slice(0), value);
1704        return this;
1705      },
1706      set: function(key, val) {
1707        return this.copy().SET(key, val);
1708      },
1709      REMOVE: function(key, val) {
1710        if (val) {
1711          var target = this.GET(key);
1712          if (is(target, Array)) {
1713            for (tval in target) {
1714                target[tval] = target[tval].toString();
1715            }
1716            var index = $.inArray(val, target);
1717            if (index >= 0) {
1718              key = target.splice(index, 1);
1719              key = key[index];
1720            } else {
1721              return;
1722            }
1723          } else if (val != target) {
1724              return;
1725          }
1726        }
1727        return this.SET(key, null).COMPACT();
1728      },
1729      remove: function(key, val) {
1730        return this.copy().REMOVE(key, val);
1731      },
1732      EMPTY: function() {
1733        var self = this;
1734        jQuery.each(self.keys, function(key, value) {
1735          delete self.keys[key];
1736        });
1737        return self;
1738      },
1739      load: function(url) {
1740        var hash = url.replace(/^.*?[#](.+?)(?:\?.+)?$/, "$1");
1741        var search = url.replace(/^.*?[?](.+?)(?:#.+)?$/, "$1");
1742        return new queryObject(url.length == search.length ? '' : search, url.length == hash.length ? '' : hash);
1743      },
1744      empty: function() {
1745        return this.copy().EMPTY();
1746      },
1747      copy: function() {
1748        return new queryObject(this);
1749      },
1750      COMPACT: function() {
1751        function build(orig) {
1752          var obj = typeof orig == "object" ? is(orig, Array) ? [] : {} : orig;
1753          if (typeof orig == 'object') {
1754            function add(o, key, value) {
1755              if (is(o, Array))
1756                o.push(value);
1757              else
1758                o[key] = value;
1759            }
1760            jQuery.each(orig, function(key, value) {
1761              if (!is(value)) return true;
1762              add(obj, key, build(value));
1763            });
1764          }
1765          return obj;
1766        }
1767        this.keys = build(this.keys);
1768        return this;
1769      },
1770      compact: function() {
1771        return this.copy().COMPACT();
1772      },
1773      toString: function() {
1774        var i = 0, queryString = [], chunks = [], self = this;
1775        var encode = function(str) {
1776          str = str + "";
1777          str = encodeURIComponent(str);
1778          if ($spaces) str = str.replace(/%20/g, "+");
1779          return str;
1780        };
1781        var addFields = function(arr, key, value) {
1782          if (!is(value) || value === false) return;
1783          var o = [encode(key)];
1784          if (value !== true) {
1785            o.push("=");
1786            o.push(encode(value));
1787          }
1788          arr.push(o.join(""));
1789        };
1790        var build = function(obj, base) {
1791          var newKey = function(key) {
1792            return !base || base == "" ? [key].join("") : [base, "[", key, "]"].join("");
1793          };
1794          jQuery.each(obj, function(key, value) {
1795            if (typeof value == 'object') 
1796              build(value, newKey(key));
1797            else
1798              addFields(chunks, newKey(key), value);
1799          });
1800        };
1801        
1802        build(this.keys);
1803        
1804        if (chunks.length > 0) queryString.push($hash);
1805        queryString.push(chunks.join($separator));
1806        
1807        return queryString.join("");
1808      }
1809    };
1810    
1811    return new queryObject(location.search, location.hash);
1812  };
1813}(jQuery.query || {}); // Pass in jQuery.query as settings object
1814

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.